fix(orchestrator): parent-must-be-on-main guard in state check + loop tick (AISDLC-358)#528
Conversation
AI-SDLC: Reviewer Agents Skipped (Local Attestation Valid)A valid DSSE attestation envelope was found at
CI re-running the same 3 agents would produce the same verdict at the cost Note: Attestation remains AUDIT-ONLY as a merge gate (per AISDLC-140 sub-4). Posted by AI-SDLC Review Agents — AISDLC-147 attestation cost-saver |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
7e9e30c to
c865234
Compare
c865234 to
84acc7d
Compare
84acc7d to
8676a92
Compare
8676a92 to
04a7a71
Compare
AI-SDLC: Reviewer Agents Skipped (Anthropic Budget Exhausted)3/3 review agents failed with HTTP 400 What this means:
Posted by AI-SDLC Review Agents — AISDLC-147 budget circuit breaker (AISDLC-157 broadened gate) |
04a7a71 to
1c429c1
Compare
1e1367f to
b22f5d6
Compare
b22f5d6 to
7e8d783
Compare
7e8d783 to
391c4b1
Compare
… tick (AISDLC-358) Augments check-orchestrator-state.sh with a pre-flight branch check (section 1a, AISDLC-358): if the parent working tree is NOT on main, auto-recover when the tree is clean (git checkout main + git reset --hard origin/main, log the recovered branch), or REFUSE with exit 1 and a clear error (branch name + dirty paths + recovery command) when the tree is dirty. Wires the same logic into pipeline-cli/src/orchestrator/loop.ts as runParentBranchGuard() + ParentNotOnMainError, called at the top of every runOrchestratorTick() before the sweep or frontier scan. The implementation resolves the parent root via git rev-parse --git-common-dir so it correctly handles invocations from inside linked worktrees (returns early when not in a git repo, making hermetic test setups safe without needing to inject a no-op parentBranchGuard adapter). Test coverage: extended check-orchestrator-state.test.mjs with 4 new hermetic cases covering all four AC-specified scenarios (main+clean, main+dirty, feature-branch+clean auto-recover, feature-branch+dirty refuse). CLAUDE.md: added "Pattern C hard guards (AISDLC-358)" subsection documenting the enforcement behavior and recovery steps. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…dapters (AISDLC-358)
Add error handling for git checkout/reset failures in runParentBranchGuard()
and check-orchestrator-state.sh: propagate failures as ParentNotOnMainError
instead of silently continuing. Also add parentBranchGuard: async () => {} to
hermeticFilterAdapters() in loop.test.ts and loop.umbrella.test.ts so tests
are hermetic regardless of the git working tree context during coverage runs.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…d (AISDLC-358) - Tests: add loop.branch-guard.test.ts covering 5 runParentBranchGuard branches + checkout/reset failure cases + ParentNotOnMainError truncation - Tests: inject parentBranchGuard no-op stub into all remaining loop test adapters (events, filters, rollback, resume, sweep, in-flight, blast-radius, dispatchability, chaos, playbook) to remove dependency on '/tmp not being a git repo' Note: Code Major 1 (shell silent failure), Code Minor 1 (reset silent failure), and Code Major 2 (TS false-success log) were addressed in the preceding commit 7d96da0 on this branch. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Rebase post-363 left dup parentBranchGuard keys in 3 test files (both 358's fix-up and 363's fix-up added them to the same adapter literals). Dedup keeps the 363 (newer) stub. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…LC-358) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Summary
Pattern-C contract enforcement: parent worktree MUST be on
main. Detects parent on stale feature branch and either auto-recovers (clean tree) or refuses (dirty tree). Prevents the silent-stale-main class of incident encountered today.Changes
scripts/check-orchestrator-state.sh: pre-flight branch check viagit symbolic-ref --short HEAD. Clean non-main →git checkout main && git reset --hard origin/main. Dirty non-main → refuse with explicit error naming branch + dirty paths + recovery command. Explicit error handling on checkout/reset failure (no silent2>/dev/nullswallowing).pipeline-cli/src/orchestrator/loop.ts:runParentBranchGuard()+ParentNotOnMainErrorcalled at top of everyrunOrchestratorTick(), before frontier scan. Exit-code check ongit checkout mainprevents false "auto-recovered" success log when checkout fails.loop.branch-guard.test.tscovering all 5runParentBranchGuardbranches +ParentNotOnMainErrorconstructor truncation.parentBranchGuard: async () => {}no-op stub injected into all loop test adapters (removes accidental/tmp not a git repodependency).Reviewer findings addressed
3 code/test reviewer subagents flagged 5 majors total; all addressed in commits 7d96da0 + 9f3fd04:
runParentBranchGuardhad zero TS unit tests → 22 new testsParentNotOnMainErroruntested → constructor tests including truncation pathparentBranchGuardadapter → stubbed across 12 loop test filesSecurity reviewer: APPROVED clean (no exploitable surface; branch-name injection prevented by git's check-ref-format + execFile array-arg).
Test plan
cli-orchestrator tickwhen parent is on stale feature branch (clean → auto-recover)🤖 Generated with Claude Code