The gap
graph.jsondeps gate dispatch on the dependency's approval, but a dependent task's worktree never contains the dependency's code while it runs:
- Phase 3 step 1 creates every worktree from the integration branch.
- Dependency branches are merged into the integration branch only in Phase 6, after Gate 2.
So deps: ["r1"] means "start after r1 is approved", not "start with r1's changes present". For a task that only consumes an interface, the skill's mitigation covers it — Phase 3 step 0 pastes the approved upstream's exact signatures into the brief as text. But that is not enough for a task whose whole job is to be consistent with merged code.
Concrete cases from one run
Two tasks in my graph were exactly this shape:
Doc realignment — a task owning plans/** whose job was to fix ~11 documentation-drift findings by matching the docs to whatever the code finally became. Text signatures do not help: it has to read the merged result.
A cross-module invariant assertion — jira_client.RETRY_AFTER_MAX < approve_web.STALE_SEC, where the two constants are produced by two different tasks. The consumer task measured the problem itself and asked:
실측: 내 워크트리(HEAD bcbe4c2)의 manday-sp/jira_client.py 에 RETRY_AFTER_MAX 가 없다 (grep 0건) … 지시대로 테스트를 지금 넣으면 r4 머지 전까지 AttributeError 로 1건 RED 가 되고 DoD 실패 0 과 충돌한다. 더 나쁜 건 상시 RED 1건이 있으면 내 뮤테이션 대조군 판독이 오염된다는 것 — 내 뮤테이션이 죽인 건지 이 알려진 RED 인지 구분이 흐려진다.
That last sentence is the real cost: a known-red test destroys the red/green signal the whole mutation-control protocol depends on, so "write it now and accept one failure" is not a viable workaround.
Why the obvious workarounds are bad
- "Write it anyway, accept 1 RED" — poisons mutation-control readings for that task's entire run (above).
hasattr/skip gate — a skip reads green at integration, which is the tests-that-cannot-fail class the bundled wiki explicitly warns about.- "The coordinator adds it later" — this is the orphaned-wiring failure the skill warns about elsewhere ("경계에 걸친 조각의 소유자를 이름으로 지정한다"): the piece has no owner and no time, so nobody picks it up. It passes every gate — each task's DoD is met, CI is green, git merges cleanly — and the assertion simply never exists.
What I did
Deferred worktree creation for both tasks, added a new node with deps on all five implementation tasks, and planned an early merge of approved dependencies into the integration branch before dispatching them. That works, but it is entirely outside what the skill describes, and I only got there because a worker pushed back instead of guessing.
Suggested fix (any of these would close it)
- Document the limitation in Phase 3 step 0, next to the preceding-interface injection text:
deps gives you signatures, not code, and a task needing merged code must be dispatched after an integration-time merge. - Create dependent worktrees lazily — at dispatch time rather than in Phase 3 step 1, branching from the integration branch's current tip, and merge approved dependency branches into the integration branch as they are approved (rather than only in Phase 6).
setup-worktrees.sh is already idempotent, so it can be re-invoked per dispatch. - Name the shape — an explicit "integration-time task" kind that the scheduler runs only after all its deps are merged, so the graph can express it instead of the operator improvising.
Option 2 also makes the common case better: a Wave-2 task would compile against real upstream code instead of a pasted signature, which is where drift between "the signature I was told" and "the signature that shipped" comes from.
The gap
graph.jsondepsgate dispatch on the dependency's approval, but a dependent task's worktree never contains the dependency's code while it runs:So
deps: ["r1"]means "start after r1 is approved", not "start with r1's changes present". For a task that only consumes an interface, the skill's mitigation covers it — Phase 3 step 0 pastes the approved upstream's exact signatures into the brief as text. But that is not enough for a task whose whole job is to be consistent with merged code.Concrete cases from one run
Two tasks in my graph were exactly this shape:
Doc realignment — a task owning
plans/**whose job was to fix ~11 documentation-drift findings by matching the docs to whatever the code finally became. Text signatures do not help: it has to read the merged result.A cross-module invariant assertion —
jira_client.RETRY_AFTER_MAX < approve_web.STALE_SEC, where the two constants are produced by two different tasks. The consumer task measured the problem itself and asked:That last sentence is the real cost: a known-red test destroys the red/green signal the whole mutation-control protocol depends on, so "write it now and accept one failure" is not a viable workaround.
Why the obvious workarounds are bad
hasattr/skip gate — a skip reads green at integration, which is thetests-that-cannot-failclass the bundled wiki explicitly warns about.What I did
Deferred worktree creation for both tasks, added a new node with
depson all five implementation tasks, and planned an early merge of approved dependencies into the integration branch before dispatching them. That works, but it is entirely outside what the skill describes, and I only got there because a worker pushed back instead of guessing.Suggested fix (any of these would close it)
depsgives you signatures, not code, and a task needing merged code must be dispatched after an integration-time merge.setup-worktrees.shis already idempotent, so it can be re-invoked per dispatch.Option 2 also makes the common case better: a Wave-2 task would compile against real upstream code instead of a pasted signature, which is where drift between "the signature I was told" and "the signature that shipped" comes from.