* fix(#2772): only disable worktree isolation when planned paths touch submodules The previous guard in execute-phase.md and quick.md unconditionally set USE_WORKTREES=false whenever .gitmodules existed, penalising every plan in a submodule project even when no plan touched a submodule path. Replace with submodule-path parsing + per-plan path intersection: - Parse SUBMODULE_PATHS once from .gitmodules via `git config --file .gitmodules --get-regexp '^submodule\..*\.path$'`. - In execute-phase.md, intersect SUBMODULE_PATHS with each plan's files_modified frontmatter; disable worktree isolation only for plans with non-empty intersection. Fall back to safe-disable for that plan when files_modified is missing/unparseable, with a log line explaining why. - In quick.md (no pre-declared paths), keep submodule-path parsing and document a fail-loud commit-time guard so the executor aborts only when it actually stages a submodule path. Add tests/bug-2772-gitmodules-path-intersection.test.cjs covering both files: no unconditional disable, submodule paths are parsed, intersection logic exists in execute-phase, fallback path is documented. Full suite: 5680 / 5680 pass. Closes #2772 * test(#2772): replace source-grep with behavioral test of submodule path intersection * fix(#2772): wire USE_WORKTREES_FOR_PLAN into dispatch + fix glob matcher + add quick.md commit guard Address CodeRabbit review on PR #2779 — the original fix computed USE_WORKTREES_FOR_PLAN but never read it, so the per-plan submodule intersection was dead code. Dispatch sites still branched on the project-level USE_WORKTREES. Changes: 1. execute-phase.md (CRITICAL — dispatch wiring): Move per-plan computation into execute_waves as sub-step 2.5, run it for each plan before its dispatch, and gate all four dispatch sites on USE_WORKTREES_FOR_PLAN: worktree-mode header, sequential-mode header, "worktrees disabled" sequential rule, and post-wave cleanup. Document PLAN_FILES extraction via jq from the phase-plan-index JSON. Track WAVE_WORKTREE_PLANS so post-wave cleanup only runs when at least one plan in the wave actually used worktrees. 2. Per-plan gate matcher (MAJOR — glob safety): Strip leading "./" and trailing "/" from both submodule and planned paths. Match bidirectionally (pf inside sm AND sm inside pf). Handle globby planned paths like "vendor/**/*.c" by extracting the literal prefix before the first glob metachar and re-checking. Wrap the iteration in set -f / set +f so glob expansion does not corrupt patterns. Extracted the gate (~92 lines) into workflows/execute-phase/steps/per-plan-worktree-gate.md to keep execute-phase.md under the 1700-line XL budget. 3. quick.md (CRITICAL — fail-loud guard): Inject SUBMODULE_PATHS into the executor Task prompt and add a <submodule_commit_guard> bash block the executor must run before every git commit. The guard inspects staged paths via `git diff --cached --name-only`, normalizes paths, and aborts with a clear ABORT message + recovery instruction ("re-run with workflow.use_worktrees=false") when any staged path falls inside a submodule. 4. tests/bug-2772-gitmodules-path-intersection.test.cjs: 25 tests total. Updated GATE_SNIPPET to match the new bash matcher. Added normalization tests (./ prefix, trailing /, glob "vendor/**/*.c", parent directory, ./ in .gitmodules). Added workflow-markdown wiring assertions for all 4 dispatch sites + per-plan gate file extraction. Added quick.md guard tests: prompt injection assertion + behavioral fixture-repo tests that stage a submodule path and assert the guard exits non-zero with the ABORT message. Test count: 5701 pass / 0 fail (was 5698/1 before). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
20 KiB
20 KiB