feat(ingest): a container's pinned team decides, as the config always claimed #49

Merged
ryangr0 merged 1 commit from pinned-team-decides into development 2026-09-02 08:42:39 +00:00
Owner

feat(ingest): a container's pinned team decides, as the config always claimed

The Project type has carried this comment since routing moved into the file:

Team routes this project's work to one team. Empty means the
assignee decides, via the team's `assignees` list below.

Only the second sentence was ever implemented. team: was consumed solely as
a routing-table qualifier — "/=repo" disambiguates WHICH REPO a
team's work lands in — while the team itself always came from the assignee
mapping, falling through to PLOEG_DEFAULT_TEAM for anyone unmapped. A config
that pinned a project to team: app routed nothing to app unless the
assignee independently mapped there, which makes the pin a comment about an
intention rather than a control.

The gap has a concrete cost on a real board. On ClickUp, assignees are
licensed workspace members — there are no bot users to invent, and the
validator's one-assignee-one-team rule means a PERSON can only ever trigger a
single tier. The natural gesture — three Lists, one per tier, drop a task in
the right one — was unexpressible.

Now the pin decides. After mirror() has fetched the item (a thin clickup
webhook carries no List, so the scope is only known post-fetch, which is why
this cannot live in a provider), ingest overrides the assignee's team with the
container's pinned team, then resolves the target — so the team-qualified
routing rules see the team the work will actually run as. Unpinned containers
are byte-for-byte unchanged: the assignee still decides.

Config grows ScopeTeams(): every project with both a pinned id and a team.
Name-resolved projects are deliberately absent until a resolver hands their
ids back — the shape that needs pinning is the shape that pins ids.

Gates: gofmt clean, go vet clean, go build ok, go test ./... ok, goldens
untouched (no chart change).

Driving consumer: code14's staging cluster, routing three ClickUp Lists to the docs/app/infra tiers. Without this, tier selection on a board with licensed seats has no workable gesture.

feat(ingest): a container's pinned team decides, as the config always claimed The Project type has carried this comment since routing moved into the file: Team routes this project's work to one team. Empty means the assignee decides, via the team's `assignees` list below. Only the second sentence was ever implemented. `team:` was consumed solely as a routing-table qualifier — "<scope>/<team>=repo" disambiguates WHICH REPO a team's work lands in — while the team itself always came from the assignee mapping, falling through to PLOEG_DEFAULT_TEAM for anyone unmapped. A config that pinned a project to `team: app` routed nothing to app unless the assignee independently mapped there, which makes the pin a comment about an intention rather than a control. The gap has a concrete cost on a real board. On ClickUp, assignees are licensed workspace members — there are no bot users to invent, and the validator's one-assignee-one-team rule means a PERSON can only ever trigger a single tier. The natural gesture — three Lists, one per tier, drop a task in the right one — was unexpressible. Now the pin decides. After mirror() has fetched the item (a thin clickup webhook carries no List, so the scope is only known post-fetch, which is why this cannot live in a provider), ingest overrides the assignee's team with the container's pinned team, then resolves the target — so the team-qualified routing rules see the team the work will actually run as. Unpinned containers are byte-for-byte unchanged: the assignee still decides. Config grows ScopeTeams(): every project with both a pinned id and a team. Name-resolved projects are deliberately absent until a resolver hands their ids back — the shape that needs pinning is the shape that pins ids. Gates: gofmt clean, go vet clean, go build ok, go test ./... ok, goldens untouched (no chart change). Driving consumer: code14's staging cluster, routing three ClickUp Lists to the docs/app/infra tiers. Without this, tier selection on a board with licensed seats has no workable gesture.
feat(ingest): a container's pinned team decides, as the config always claimed
All checks were successful
On Pull Request / checks (pull_request) Successful in 44s
9680081c3d
The Project type has carried this comment since routing moved into the file:

    Team routes this project's work to one team. Empty means the
    assignee decides, via the team's `assignees` list below.

Only the second sentence was ever implemented. `team:` was consumed solely as
a routing-table qualifier — "<scope>/<team>=repo" disambiguates WHICH REPO a
team's work lands in — while the team itself always came from the assignee
mapping, falling through to PLOEG_DEFAULT_TEAM for anyone unmapped. A config
that pinned a project to `team: app` routed nothing to app unless the
assignee independently mapped there, which makes the pin a comment about an
intention rather than a control.

The gap has a concrete cost on a real board. On ClickUp, assignees are
licensed workspace members — there are no bot users to invent, and the
validator's one-assignee-one-team rule means a PERSON can only ever trigger a
single tier. The natural gesture — three Lists, one per tier, drop a task in
the right one — was unexpressible.

Now the pin decides. After mirror() has fetched the item (a thin clickup
webhook carries no List, so the scope is only known post-fetch, which is why
this cannot live in a provider), ingest overrides the assignee's team with the
container's pinned team, then resolves the target — so the team-qualified
routing rules see the team the work will actually run as. Unpinned containers
are byte-for-byte unchanged: the assignee still decides.

Config grows ScopeTeams(): every project with both a pinned id and a team.
Name-resolved projects are deliberately absent until a resolver hands their
ids back — the shape that needs pinning is the shape that pins ids.

Gates: gofmt clean, go vet clean, go build ok, go test ./... ok, goldens
untouched (no chart change).
ryangr0 merged commit 3dd3fd5730 into development 2026-09-02 08:42:39 +00:00
Commenting is not possible because the repository is archived.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
webgrip/ploeg!49
No description provided.