Skip to content

Merge dev → main: backlog-manager scope safety (#1233)#1234

Merged
zbigniewsobiecki merged 1 commit intomainfrom
dev
Apr 29, 2026
Merged

Merge dev → main: backlog-manager scope safety (#1233)#1234
zbigniewsobiecki merged 1 commit intomainfrom
dev

Conversation

@zbigniewsobiecki
Copy link
Copy Markdown
Member

Summary

Closes the 2026-04-29 ucho incident: backlog-manager moved MNG-422 (in SPLITTING) to TODO when retriggered manually with no `triggerEvent`, because `pipelineSnapshot` never pre-loaded.

What's in this merge

🤖 Generated with Claude Code

…1233)

* fix(backlog-manager): fail-closed when pipelineSnapshot is missing

Prod incident 2026-04-29 (ucho): backlog-manager moved MNG-422 from
SPLITTING to TODO, kicking off implementation on a non-split card.

Root cause: a manual `cascade runs trigger --agent-type backlog-manager`
runs with `triggerEvent: undefined` → `resolveContextPipeline` returns
`[]` → `pipelineSnapshot` never executes → agent improvises by listing
all PM containers (BACKLOG + TODO + IN_PROGRESS + IN_REVIEW + ...) and
picks "good-looking" cards from any of them. The MoveWorkItem gadget
then moves them blindly because it does no source-state validation. The
prompt strongly implies "from BACKLOG only" but never says "REFUSE
otherwise" — the agent freelanced.

Three coordinated fixes (defense in depth):

A) Agent-level `requiredContext: ContextStepName[]` schema field. Steps
   listed here ALWAYS run, regardless of trigger source — manual,
   webhook, or internal. Backlog-manager declares
   `requiredContext: [pipelineSnapshot]` so the snapshot pre-load can no
   longer be skipped.

C) Fail-closed: when a required step returns 0 injections OR throws,
   the agent run aborts with a structured error + Sentry capture under
   tag `context_pipeline_required_step_failed`. Today the snapshot step
   warn-and-returns `[]` when no PM provider is in scope — so even when
   it's wired, missing scope was silent. With this fix it's loud.

D) Hard rule in `backlog-manager.eta`: explicit "NEVER move a card not
   in BACKLOG. NEVER call ListWorkItems against non-BACKLOG containers
   to discover candidates. If the snapshot is missing, ABORT — do not
   improvise."

Required steps run BEFORE the per-trigger contextPipeline and are
deduped (a step listed in both runs once).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(web): add requiredContext to EMPTY_DEFINITION fixture

Web tsc -b consumes the AgentDefinition output type which now requires
requiredContext (zod default([]) makes the field always defined on the
parsed shape). Add the explicit empty array to match.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@zbigniewsobiecki zbigniewsobiecki merged commit 24e1e4d into main Apr 29, 2026
14 checks passed
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 29, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant