Plan: Compound Phase Merged-PR Guard & Docs-Only Validation#
Summary#
Add a pre-compound guard in PhaseRouterService that blocks compound execution until task.prNumber is confirmed merged via the GitHub API, and add post-compound diff validation in PhaseRouterService that rejects compound output touching src/ or test/ files (retry once, then BLOCKED:PERSISTENT).
Files#
| File | Action | Description |
|---|---|---|
src/github/github.service.ts | modify | Add isPrMerged(owner, repo, prNumber) method |
src/github/github.service.spec.ts | modify | Add tests for isPrMerged |
src/phase-router/phase-router.service.ts | modify | Add pre-compound merged-PR guard and post-compound diff validation |
src/phase-router/phase-router.service.spec.ts | modify | Add tests for compound guards (null prNumber, PR not merged, diff validation) |
src/internal-adapter/internal-adapter.service.ts | modify | Add compound-specific advancement logic in advanceAndEnqueue — only enqueue compound when PR is merged |
Steps#
- Add
isPrMergedtoGitHubService— callGET /repos/{owner}/{repo}/pulls/{prNumber}and returndata.merged === true. Handle 404 asfalse. - Add merged-PR guard in
PhaseRouterService.executePhase— before executing compound, checktask.prNumber. If null, signalBLOCKED:PERSISTENTwith "compound reached with no PR on record". If set, callisPrMerged; if not merged, signalBLOCKED:TRANSIENTwith "PR not yet merged". - Add post-compound diff validation in
PhaseRouterService.executePhase— after compound completes, rungit diff --name-only origin/master...HEADin the worktree. If any path starts withsrc/ortest/, set a retry flag. On first violation, re-invoke compound with an explicit docs-only constraint env var. On second violation, signalBLOCKED:PERSISTENT. - Update
advanceAndEnqueueinInternalAdapterService— when advancing fromdelivertocompound, check thattask.prNumberis set before enqueuing (fail-fast guard, complementing the runtime check in step 2). - Write unit tests — cover: (a)
isPrMergedhappy/404, (b) compound blocked on null prNumber, (c) compound blocked on open PR, (d) compound proceeds on merged PR, (e) diff validation retry and persistent block.
Verification#
npm run testpasses with new tests covering all compound guard pathsnpm run lintpasses with zero warnings- Manual trace: deliver_completed → compound enqueue only fires when prNumber is merged
Risks#
- Race condition: PR merge webhook and compound advancement could race. Mitigation: the runtime guard in
executePhaseis the authoritative check; theadvanceAndEnqueueguard is a fail-fast optimization. - Compound worktree: compound currently has no worktree (not in
WORKTREE_PHASES). The diff validation needs access to the git state — will use the artefacts repo orPROJECT_ROOTenv var instead.