Goal
Upstream-shaped feature (vanilla rule: issue here + upstream PR, we carry the delta): harden ao's trackerIntake loop with two missing controls:
- Label filtering —
TrackerIntakeConfig gains include/exclude label rules (e.g. labels: ["agent-ok"], excludeLabels: ["agent:noauto"]) applied in issueMatchesConfig alongside the existing assignee rule.
- Concurrency cap —
maxConcurrent per project: intake skips spawning when the project's live intake-spawned worker count is at the cap, and picks the issue up on a later tick once a slot frees (no permanent skip).
How we got here
We are adopting trackerIntake (merged upstream AgentWrapper#2325, in our tree) as the sole dispatcher for this repo, with an assignee rule as the go-signal. Two gaps surfaced in review of backend/internal/observe/trackerintake/observer.go:
issueMatchesConfig filters on assignees only — there is no label opt-out, so policies like our previous agent:noauto cannot be expressed.
- The poll loop spawns one worker per matching issue with no concurrency bound; a bulk filing-and-assignment burst would spawn unbounded workers. Our fleet policy caps concurrent workers per project (we use 4).
Both are generally useful upstream, not Polymath-specific. Interim mitigation on our side: assignment-as-opt-in keeps a deliberate finger on the throttle, but nothing enforces the cap.
Acceptance criteria
Context / pointers
Goal
Upstream-shaped feature (vanilla rule: issue here + upstream PR, we carry the delta): harden ao's
trackerIntakeloop with two missing controls:TrackerIntakeConfiggains include/exclude label rules (e.g.labels: ["agent-ok"],excludeLabels: ["agent:noauto"]) applied inissueMatchesConfigalongside the existing assignee rule.maxConcurrentper project: intake skips spawning when the project's live intake-spawned worker count is at the cap, and picks the issue up on a later tick once a slot frees (no permanent skip).How we got here
We are adopting
trackerIntake(merged upstream AgentWrapper#2325, in our tree) as the sole dispatcher for this repo, with an assignee rule as the go-signal. Two gaps surfaced in review ofbackend/internal/observe/trackerintake/observer.go:issueMatchesConfigfilters on assignees only — there is no label opt-out, so policies like our previousagent:noautocannot be expressed.Both are generally useful upstream, not Polymath-specific. Interim mitigation on our side: assignment-as-opt-in keeps a deliberate finger on the throttle, but nothing enforces the cap.
Acceptance criteria
TrackerIntakeConfig(domain + validation +issueMatchesConfig) with testsmaxConcurrenthonored by the intake loop — at-cap issues are deferred, not dropped; picked up when a slot frees; tests cover the boundarycd backend && go build ./... && go vet ./... && go test ./...backend/internal/daemon/**(wiring lives atbackend/internal/daemon/tracker_intake_wiring.go);observe/trackerintakeitself is not on the sensitive listContext / pointers
backend/internal/observe/trackerintake/observer.go(pollProject,issueMatchesConfig),backend/internal/domain/tracker.go(TrackerIntakeConfig,Validate— "rejects accidental broad intake" is the existing design intent these controls extend)