@pareto4/pp-core 1.12.1 → 1.17.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (196) hide show
  1. package/.claude-plugin/plugin.json +3 -3
  2. package/README.md +26 -9
  3. package/agents/pp-code-reviewer.md +3 -2
  4. package/agents/pp-debug-session-manager.md +9 -6
  5. package/agents/pp-executor.md +7 -21
  6. package/agents/pp-plan-checker.md +4 -4
  7. package/agents/pp-planner.md +23 -9
  8. package/agents/pp-vault-reviewer.md +274 -0
  9. package/agents/pp-verifier.md +7 -3
  10. package/bin/install.js +10 -3
  11. package/commands/pp-execute-phase.md +1 -3
  12. package/commands/pp-ns-review.md +2 -1
  13. package/commands/pp-plan-phase.md +1 -2
  14. package/commands/pp-vault-review.md +35 -0
  15. package/commands/pp-verify-work.md +1 -2
  16. package/gemini-extension.json +1 -1
  17. package/hooks/dist/pp-check-update.js +0 -0
  18. package/hooks/dist/pp-cursor-session-start.js +1 -1
  19. package/hooks/dist/pp-statusline.js +1 -1
  20. package/hooks/dist/pp-update-banner.js +0 -0
  21. package/hooks/pp-check-update.js +0 -0
  22. package/hooks/pp-cursor-session-start.js +1 -1
  23. package/hooks/pp-statusline.js +1 -1
  24. package/hooks/pp-update-banner.js +0 -0
  25. package/package.json +14 -19
  26. package/pareto-skills/_shared/create-project-board.sh +0 -0
  27. package/pareto-skills/pp-project-setup/SKILL.md +1 -1
  28. package/pp-core/bin/check-latest-version.cjs +0 -0
  29. package/pp-core/bin/detect-build-commands.sh +2 -2
  30. package/pp-core/bin/lib/capability-activation.cjs +83 -9
  31. package/pp-core/bin/lib/capability-registry.cjs +526 -22
  32. package/pp-core/bin/lib/capability-state.cjs +160 -4
  33. package/pp-core/bin/lib/capability-writer.cjs +19 -5
  34. package/pp-core/bin/lib/check-command-router.cjs +3867 -274
  35. package/pp-core/bin/lib/clusters.cjs +4 -0
  36. package/pp-core/bin/lib/command-aliases.cjs +0 -28
  37. package/pp-core/bin/lib/commands.cjs +9 -4
  38. package/pp-core/bin/lib/compose-bindings.cjs +253 -76
  39. package/pp-core/bin/lib/config-loader.cjs +7 -103
  40. package/pp-core/bin/lib/config-schema.cjs +1 -1
  41. package/pp-core/bin/lib/config.cjs +154 -62
  42. package/pp-core/bin/lib/decisions.cjs +104 -27
  43. package/pp-core/bin/lib/discovery-vault-check.cjs +246 -0
  44. package/pp-core/bin/lib/frontmatter.cjs +1 -1
  45. package/pp-core/bin/lib/git-base-branch.cjs +138 -10
  46. package/pp-core/bin/lib/git-provider.cjs +4 -4
  47. package/pp-core/bin/lib/init-command-router.cjs +5 -8
  48. package/pp-core/bin/lib/init-contract.cjs +653 -629
  49. package/pp-core/bin/lib/init-interactive.cjs +77 -21
  50. package/pp-core/bin/lib/init.cjs +24 -51
  51. package/pp-core/bin/lib/install-profiles.cjs +1 -1
  52. package/pp-core/bin/lib/io.cjs +8 -0
  53. package/pp-core/bin/lib/loop-resolver.cjs +169 -47
  54. package/pp-core/bin/lib/org-profile.cjs +544 -53
  55. package/pp-core/bin/lib/package-identity.cjs +3 -3
  56. package/pp-core/bin/lib/phase-command-router.cjs +1 -23
  57. package/pp-core/bin/lib/phase-scope.cjs +1 -1
  58. package/pp-core/bin/lib/phase.cjs +11 -203
  59. package/pp-core/bin/lib/platform-bindings.cjs +40 -19
  60. package/pp-core/bin/lib/practices-review-check.cjs +15 -9
  61. package/pp-core/bin/lib/profile-output.cjs +1 -1
  62. package/pp-core/bin/lib/shell-command-projection.cjs +104 -1
  63. package/pp-core/bin/lib/state.cjs +11 -85
  64. package/pp-core/bin/lib/template.cjs +1 -1
  65. package/pp-core/bin/lib/vault-audit.cjs +2594 -0
  66. package/pp-core/bin/lib/vault-command-router.cjs +2756 -60
  67. package/pp-core/bin/lib/vault-coordinates.cjs +13 -4
  68. package/pp-core/bin/lib/vault-index.cjs +699 -0
  69. package/pp-core/bin/lib/vault-mode.cjs +235 -0
  70. package/pp-core/bin/lib/vault-practices.cjs +1194 -89
  71. package/pp-core/bin/lib/vault-review.cjs +2102 -0
  72. package/pp-core/bin/lib/vault-seal.cjs +1936 -0
  73. package/pp-core/bin/lib/vault-standards.cjs +1505 -0
  74. package/pp-core/bin/lib/vault-trace.cjs +3184 -0
  75. package/pp-core/bin/lib/vault-update.cjs +242 -0
  76. package/pp-core/bin/lib/vault-write-back.cjs +78 -31
  77. package/pp-core/bin/lib/vault.cjs +2713 -634
  78. package/pp-core/bin/lib/verify.cjs +0 -11
  79. package/pp-core/bin/portable-timeout.sh +1 -1
  80. package/pp-core/bin/pp-tools.cjs +184 -37
  81. package/pp-core/bin/shared/config-defaults.manifest.json +0 -7
  82. package/pp-core/bin/shared/config-schema.manifest.json +0 -3
  83. package/pp-core/bin/shared/model-catalog.json +1 -0
  84. package/pp-core/bin/verify-reapply-patches.cjs +0 -0
  85. package/pp-core/org-profile.json +26 -0
  86. package/pp-core/references/autonomous-best-effort.md +8 -7
  87. package/pp-core/references/loop-hook-dispatch.md +0 -14
  88. package/pp-core/references/planner-gap-closure.md +0 -1
  89. package/pp-core/references/planner-tdd.md +0 -1
  90. package/pp-core/references/planner-vault-practices.md +31 -3
  91. package/pp-core/references/planner-vault-standards.md +320 -0
  92. package/pp-core/references/planning-config.md +0 -8
  93. package/pp-core/references/practice-arithmetic-contract.md +121 -0
  94. package/pp-core/references/tdd.md +0 -1
  95. package/pp-core/references/verifier-practice-verdicts.md +263 -0
  96. package/pp-core/templates/README.md +1 -0
  97. package/pp-core/templates/VAULT-REVIEW.md +202 -0
  98. package/pp-core/templates/phase-prompt.md +2 -6
  99. package/pp-core/templates/practices/README.md +137 -11
  100. package/pp-core/templates/project-charter.md +226 -0
  101. package/pp-core/workflows/_runtime-launcher.snippet.sh +0 -0
  102. package/pp-core/workflows/add-tests.md +55 -0
  103. package/pp-core/workflows/audit-fix.md +63 -0
  104. package/pp-core/workflows/audit-milestone.md +1 -1
  105. package/pp-core/workflows/autonomous.md +85 -11
  106. package/pp-core/workflows/check-todos.md +13 -2
  107. package/pp-core/workflows/code-review-fix.md +59 -1
  108. package/pp-core/workflows/code-review.md +10 -1
  109. package/pp-core/workflows/complete-milestone.md +1 -1
  110. package/pp-core/workflows/debug.md +56 -2
  111. package/pp-core/workflows/discovery-sprint/prefill.md +21 -0
  112. package/pp-core/workflows/discovery-sprint/prototype.md +46 -48
  113. package/pp-core/workflows/discovery-sprint/session-13-gates.md +2 -0
  114. package/pp-core/workflows/discovery-sprint/sessions/01-kick-off.md +1 -3
  115. package/pp-core/workflows/discovery-sprint/sessions/02-as-is.md +1 -3
  116. package/pp-core/workflows/discovery-sprint/sessions/03-to-be.md +1 -3
  117. package/pp-core/workflows/discovery-sprint/sessions/04-ux-design.md +20 -24
  118. package/pp-core/workflows/discovery-sprint/sessions/05-architecture.md +1 -3
  119. package/pp-core/workflows/discovery-sprint/sessions/06-security.md +1 -3
  120. package/pp-core/workflows/discovery-sprint/sessions/07-identity.md +1 -3
  121. package/pp-core/workflows/discovery-sprint/sessions/08-integration.md +1 -3
  122. package/pp-core/workflows/discovery-sprint/sessions/09-qa.md +1 -3
  123. package/pp-core/workflows/discovery-sprint/sessions/10-infrastructure.md +1 -6
  124. package/pp-core/workflows/discovery-sprint/sessions/11-roadmap.md +1 -3
  125. package/pp-core/workflows/discovery-sprint/sessions/12-delivery-model.md +1 -3
  126. package/pp-core/workflows/discovery-sprint/sessions/13-wrap-up.md +1 -3
  127. package/pp-core/workflows/discovery-sprint/templates/context-template.md +1 -1
  128. package/pp-core/workflows/discovery-sprint/vault-context.md +213 -0
  129. package/pp-core/workflows/discovery-sprint.md +7 -3
  130. package/pp-core/workflows/discovery-to-build/steps/architecture-deliverables.md +4 -4
  131. package/pp-core/workflows/discovery-to-build/templates/pp-handoff.md +43 -1
  132. package/pp-core/workflows/discovery-to-build.md +9 -1
  133. package/pp-core/workflows/discuss-phase.md +3 -10
  134. package/pp-core/workflows/execute-phase/steps/check-query-gate.md +329 -0
  135. package/pp-core/workflows/execute-phase/steps/client-context-gate.md +3 -2
  136. package/pp-core/workflows/execute-phase/steps/cross-ai-delegation.md +1 -1
  137. package/pp-core/workflows/execute-phase/steps/execute-pre-dispatch.md +98 -0
  138. package/pp-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +94 -0
  139. package/pp-core/workflows/execute-phase/steps/post-merge-gate.md +6 -8
  140. package/pp-core/workflows/execute-phase/steps/vault-fetch.md +115 -14
  141. package/pp-core/workflows/execute-phase/steps/vault-load-gate.md +322 -18
  142. package/pp-core/workflows/execute-phase/steps/verifier-practice-payload.md +165 -0
  143. package/pp-core/workflows/execute-phase/steps/verify-post-gate.md +163 -0
  144. package/pp-core/workflows/execute-phase.md +154 -110
  145. package/pp-core/workflows/execute-plan.md +58 -4
  146. package/pp-core/workflows/fast.md +53 -0
  147. package/pp-core/workflows/help/modes/full.md +1 -0
  148. package/pp-core/workflows/init/steps/client-context-capture.md +101 -0
  149. package/pp-core/workflows/init/steps/gitlab-provisioning.md +130 -0
  150. package/pp-core/workflows/init/steps/project-md-deferral-narration.md +66 -0
  151. package/pp-core/workflows/init/steps/reachability-outcome.md +70 -0
  152. package/pp-core/workflows/init.md +232 -272
  153. package/pp-core/workflows/new-project.md +31 -23
  154. package/pp-core/workflows/plan-phase.md +99 -43
  155. package/pp-core/workflows/quick.md +120 -2
  156. package/pp-core/workflows/secure-phase.md +1 -1
  157. package/pp-core/workflows/ship.md +57 -24
  158. package/pp-core/workflows/update.md +3 -3
  159. package/pp-core/workflows/validate-phase.md +60 -1
  160. package/pp-core/workflows/vault-review.md +325 -0
  161. package/pp-core/workflows/verify-work.md +13 -12
  162. package/scripts/changeset/cli.cjs +6 -5
  163. package/scripts/changeset/lint.cjs +0 -0
  164. package/scripts/changeset/new.cjs +33 -50
  165. package/scripts/dev-env.cjs +25 -85
  166. package/scripts/gen-capability-registry.cjs +199 -0
  167. package/scripts/gen-practice-arithmetic-contract.cjs +412 -0
  168. package/scripts/lib/allowlist-ratchet.cjs +1 -103
  169. package/scripts/lint-allow-test-rule-refs.allowlist.json +0 -2
  170. package/scripts/lint-docs-required.cjs +0 -0
  171. package/scripts/lint-pr-check-project-dir.cjs +1 -3
  172. package/scripts/lint-test-file-count.allowlist.json +13 -2
  173. package/scripts/practice-arithmetic-contract.allow.json +35 -0
  174. package/scripts/prompt-injection-scan.sh +22 -15
  175. package/scripts/record-vault-mode-golden.cjs +89 -0
  176. package/scripts/release-channel.cjs +0 -0
  177. package/scripts/sync-manifest-versions.cjs +5 -4
  178. package/scripts/sync-rulesets.sh +1 -1
  179. package/scripts/update-size-baseline.cjs +30 -274
  180. package/scripts/vault-calibrate.cjs +996 -0
  181. package/scripts/verify-opengsd-sweep.cjs +3 -5
  182. package/scripts/workflow-size.cjs +9 -61
  183. package/pp-core/bin/lib/dispatch-plan.cjs +0 -472
  184. package/pp-core/bin/lib/install-run.cjs +0 -536
  185. package/pp-core/bin/lib/phase-tier.cjs +0 -467
  186. package/pp-core/bin/lib/plan-graph.cjs +0 -368
  187. package/pp-core/references/planner-plan-graph.md +0 -66
  188. package/pp-core/workflows/execute-phase/steps/checkpoint-handling.md +0 -45
  189. package/pp-core/workflows/execute-phase/steps/install-run.md +0 -29
  190. package/pp-core/workflows/execute-phase/steps/phase-close-rebaseline.md +0 -23
  191. package/pp-core/workflows/execute-phase/steps/serial-group-dispatch.md +0 -72
  192. package/pp-core/workflows/plan-phase/steps/phase-tier.md +0 -34
  193. package/scripts/lib/size-budget.cjs +0 -311
  194. package/scripts/lint-neutrality-names.cjs +0 -694
  195. package/scripts/lint-org-coordinates.allowlist.json +0 -35
  196. package/scripts/lint-org-coordinates.cjs +0 -426
@@ -29,7 +29,7 @@ Orchestrator coordinates, not executes. Each subagent loads the full execute-pla
29
29
  Claude Code agent per #853, or a non-Claude runtime), use sequential inline execution as
30
30
  the fallback for executor parallelization only. If `Agent` IS available (top-level Claude
31
31
  Code), you MUST spawn pp-executor agents — inline execution is not authorized. Check for
32
- actual tool availability, not runtime name.
32
+ actual tool availability, not runtime name. Every inline path follows `EXECUTOR_HOOK_FRAGMENTS` as in `check_interactive_mode`.
33
33
 
34
34
  **Fallback rule:** If a spawned agent completes its work (commits visible, SUMMARY.md exists) but
35
35
  the orchestrator never receives the completion signal, treat it as successful based on spot-checks
@@ -69,8 +69,7 @@ Parse `$ARGUMENTS` before loading any context:
69
69
 
70
70
  - First positional token → `PHASE_ARG`
71
71
  - Optional `--wave N` → `WAVE_FILTER`
72
- - Optional `--gaps-only` → `GAPS_ONLY=true` (only `gap_closure: true` plans)
73
- - Optional `--tier light|standard|heavy` → `TIER_FLAG="--tier=<value>"` (one word, so zsh passes it as one argument; the phase's ceremony tier for this run; passed to init, dispatch plan and render-hooks)
72
+ - Optional `--gaps-only` keeps its current meaning
74
73
  - Optional `--cross-ai` → `CROSS_AI_FORCE=true` (force all plans through cross-AI execution)
75
74
  - Optional `--no-cross-ai` → `CROSS_AI_DISABLED=true` (disable cross-AI for this run, overrides config and frontmatter)
76
75
  - Optional `--unattended` → `UNATTENDED=true` — set by `/pp:autonomous`; prompt sites marked `U-En` apply the rules in `pp-core/references/autonomous-best-effort.md` (Read it at the first such site)
@@ -83,7 +82,7 @@ Load all context in one call:
83
82
 
84
83
  ```bash
85
84
  _PP_SHIM_NAME="pp-tools.cjs"; _pp_root() { ( for _v in $(env | sed -n 's/^\(GIT_[A-Za-z0-9_]*\)=.*/\1/p'); do unset "$_v"; done; _c=$(git rev-parse --git-common-dir 2>/dev/null); if [ "${_c##*/}" = .git ] && cd "$_c/.." 2>/dev/null; then pwd -P; else git rev-parse --show-toplevel 2>/dev/null || pwd; fi ); }; pp_run() { case "$PP_TOOLS" in *.cjs) node "$PP_TOOLS" "$@";; *) "$PP_TOOLS" "$@";; esac; }; _PP_RUNTIME_ROOT="${RUNTIME_DIR:-$(_pp_root)}"; PP_TOOLS="${_PP_RUNTIME_ROOT}/pp-core/bin/${_PP_SHIM_NAME}"; if [ -f "$PP_TOOLS" ]; then :; elif [ -f "${_PP_RUNTIME_ROOT}/.claude/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${_PP_RUNTIME_ROOT}/.claude/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${_PP_RUNTIME_ROOT}/.codex/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${_PP_RUNTIME_ROOT}/.codex/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "$HOME/.claude/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="$HOME/.claude/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${HERMES_HOME:-$HOME/.hermes}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${HERMES_HOME:-$HOME/.hermes}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${CURSOR_CONFIG_DIR:-$HOME/.cursor}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${CURSOR_CONFIG_DIR:-$HOME/.cursor}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${CODEX_HOME:-$HOME/.codex}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${CODEX_HOME:-$HOME/.codex}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${GEMINI_CONFIG_DIR:-$HOME/.gemini}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${GEMINI_CONFIG_DIR:-$HOME/.gemini}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${COPILOT_CONFIG_DIR:-$HOME/.copilot}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${COPILOT_CONFIG_DIR:-$HOME/.copilot}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${AUGMENT_CONFIG_DIR:-$HOME/.augment}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${AUGMENT_CONFIG_DIR:-$HOME/.augment}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${TRAE_CONFIG_DIR:-$HOME/.trae}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${TRAE_CONFIG_DIR:-$HOME/.trae}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${QWEN_CONFIG_DIR:-$HOME/.qwen}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${QWEN_CONFIG_DIR:-$HOME/.qwen}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${CLINE_CONFIG_DIR:-$HOME/.cline}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${CLINE_CONFIG_DIR:-$HOME/.cline}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${GROK_AGENTS_HOME:-$HOME/.agents}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${GROK_AGENTS_HOME:-$HOME/.agents}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/pp-core/bin/${_PP_SHIM_NAME}"; elif command -v pp-tools >/dev/null 2>&1; then PP_TOOLS="$(command -v pp-tools)"; else echo "ERROR: pp-tools.cjs not found at $PP_TOOLS and pp-tools is not on PATH. Run: npx -y @pareto4/pp-core@latest --claude --local" >&2; exit 1; fi; if [ -n "${CLAUDE_ENV_FILE:-}" ] && [ -n "${PP_TOOLS:-}" ]; then printf "export PATH='%s':\"\$PATH\"\n" "${PP_TOOLS%/*}" >> "$CLAUDE_ENV_FILE" 2>/dev/null || true; fi
86
- INIT=$(pp_run query init.execute-phase "${PHASE_ARG}" ${TIER_FLAG})
85
+ INIT=$(pp_run query init.execute-phase "${PHASE_ARG}")
87
86
  if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
88
87
  AGENT_SKILLS=$(pp_run query agent-skills pp-executor)
89
88
  ```
@@ -168,7 +167,7 @@ or absence of the `Agent()` subagent API. If running under Copilot, force sequen
168
167
  execution regardless of the `parallelization` setting — Copilot's subagent completion
169
168
  signals are unreliable (see `<runtime_compatibility>`). Set `COPILOT_SEQUENTIAL=true`
170
169
  internally and skip the `execute_waves` step in favor of `check_interactive_mode`'s
171
- inline path for each plan.
170
+ inline path for each plan. That inline path carries `EXECUTOR_HOOK_FRAGMENTS` as in `check_interactive_mode`.
172
171
 
173
172
  **REQUIRED — Sync chain flag with intent.** If user invoked manually (no `--auto`), clear the ephemeral chain flag from any previous interrupted `--auto` chain. This prevents stale `_auto_chain_active: true` from causing unwanted auto-advance. This does NOT touch `workflow.auto_advance` (the user's persistent settings preference). You MUST execute this bash block before any config reads:
174
173
  ```bash
@@ -183,10 +182,21 @@ Resolve `MVP_MODE` once via the centralized `phase.mvp-mode` query verb (precede
183
182
  MVP_FLAG_ARG=""
184
183
  if [[ "$ARGUMENTS" =~ (^|[[:space:]])--mvp([[:space:]]|$) ]]; then MVP_FLAG_ARG="--cli-flag"; fi
185
184
  MVP_MODE=$(pp_run query phase.mvp-mode "${PHASE_NUMBER}" $MVP_FLAG_ARG --pick active)
186
- EXECUTE_POST_HOOKS_JSON=$(pp_run loop render-hooks execute:post --raw --phase "${PHASE_NUMBER}" ${TIER_FLAG}) || exit 1
187
- TDD_MODE=$(pp_run loop render-hooks execute:post --active-cap tdd) || exit 1
185
+ EXECUTE_POST_HOOKS_JSON=$(pp_run loop render-hooks execute:post --raw)
186
+ TDD_MODE=$(pp_run loop render-hooks execute:post --active-cap tdd)
187
+ EXECUTE_PRE_HOOKS_JSON=$(pp_run loop render-hooks execute:pre --raw)
188
+ EXECUTOR_HOOK_FRAGMENTS=$(pp_run loop render-hooks execute:pre --into executor)
189
+ printf '%s' "$EXECUTE_PRE_HOOKS_JSON" | node -e "let h=[];try{h=JSON.parse(require('fs').readFileSync(0,'utf-8')).activeHooks||[]}catch{}console.log('EXECUTE_PRE_HOOKS_JSON='+JSON.stringify({activeHooks:h}))"
188
190
  ```
189
191
 
192
+ <step name="execute_pre_dispatch">
193
+ **`execute:pre` capability dispatch — fetch, then decide (GATE-03).**
194
+
195
+ Runs before `safe_resume_gate` — the first step that can spawn an executor — so the gate decides
196
+ before any code is written. Read and execute
197
+ `pp-core/workflows/execute-phase/steps/execute-pre-dispatch.md`.
198
+ </step>
199
+
190
200
  <step name="safe_resume_gate">
191
201
  Before trusting `STATE.md` or dispatching any executor, derive `CURRENT_PLAN_ID`
192
202
  from the active incomplete plan in `INIT`, then search recent history:
@@ -275,6 +285,9 @@ checkpoints between tasks. The user can review, modify, or redirect work at any
275
285
 
276
286
  c. **If "Execute":** Read and follow `~/.claude/pp-core/workflows/execute-plan.md` **inline**
277
287
  (do NOT spawn a subagent). Execute tasks one at a time.
288
+ The inline executor follows `EXECUTOR_HOOK_FRAGMENTS` (computed in the hooks fence above) as
289
+ its contract exactly as a spawned executor would: in standards mode it is the vault's
290
+ execute:pre executor fragment; in practices mode it is empty.
278
291
 
279
292
  d. **After each task:** Pause briefly. If the user intervenes (types anything), stop and address
280
293
  their feedback before continuing. Otherwise proceed to next task.
@@ -346,10 +359,6 @@ This updates Status, Last Activity, Current focus, Current Position, and plan co
346
359
  Read and execute `pp-core/workflows/execute-phase/steps/client-context-gate.md` — Pareto client-context gate (inert without `.platform-bindings.json`; confirms the Phase 9 CLAUDE.md block first).
347
360
  </step>
348
361
 
349
- <step name="execute_pre_vault">
350
- Before any executor: `EXECUTE_PRE_HOOKS_JSON=$(pp_run loop render-hooks execute:pre --raw) || exit 1`. For an active `capId == "vault"` step, Read and execute `pp-core/workflows/execute-phase/steps/vault-fetch.md`; then, for an active `vault.status` gate, set `VAULT_GATE_POINT=execute` and Read and execute `pp-core/workflows/execute-phase/steps/vault-load-gate.md`. None active → skip.
351
- </step>
352
-
353
362
  <step name="discover_and_group_plans">
354
363
  Load plan inventory with wave grouping in one call:
355
364
 
@@ -357,7 +366,7 @@ Load plan inventory with wave grouping in one call:
357
366
  PLAN_INDEX=$(pp_run query phase-plan-index "${PHASE_NUMBER}")
358
367
  ```
359
368
 
360
- Parse JSON for: `phase`, `plans[]` (each with `id`, `title`, `wave`, `serial_group`, `autonomous`, `objective`, `files_modified`, `task_count`, `has_summary`), `waves` (map of wave number → plan IDs), `serial_groups`, `incomplete`, `has_checkpoints`. A plan's `{plan_title}` is its `title` (legacy plans without one: its objective, 3-8 words).
369
+ Parse JSON for: `phase`, `plans[]` (each with `id`, `wave`, `autonomous`, `objective`, `files_modified`, `task_count`, `has_summary`), `waves` (map of wave number → plan IDs), `incomplete`, `has_checkpoints`.
361
370
 
362
371
  **Filtering:** Skip plans where `has_summary: true`. If `--gaps-only`: also skip non-gap_closure plans. If `WAVE_FILTER` is set: also skip plans whose `wave` does not equal `WAVE_FILTER`.
363
372
 
@@ -375,7 +384,7 @@ Report:
375
384
 
376
385
  | Wave | Plans | What it builds |
377
386
  |------|-------|----------------|
378
- | 1 | 01-01, 01-02 | 01-01 {plan_title}; 01-02 {plan_title} |
387
+ | 1 | 01-01, 01-02 | {from plan objectives, 3-8 words} |
379
388
  | 2 | 01-03 | ... |
380
389
  ```
381
390
  </step>
@@ -387,7 +396,7 @@ Read and execute `pp-core/workflows/execute-phase/steps/cross-ai-delegation.md`.
387
396
  </step>
388
397
 
389
398
  <step name="execute_waves">
390
- Execute each selected wave in sequence. Within a wave, follow its `run`: `parallel` — worktree spawns run alongside each other, main-checkout spawns one at a time; `sequential` — one spawn at a time.
399
+ Execute each selected wave in sequence. Within a wave: parallel if `PARALLELIZATION=true`, sequential if `false`.
391
400
 
392
401
  **Orchestrator cwd-drift guard (FIRST ACTION at execute_waves entry — #48):**
393
402
 
@@ -418,14 +427,6 @@ export ORCHESTRATOR_WT
418
427
  cd "$ORCHESTRATOR_WT" || { echo "FATAL: cannot cd to orchestrator worktree '$ORCHESTRATOR_WT' (#48)." >&2; exit 1; }
419
428
  ```
420
429
 
421
- **Dispatch plan (load once, after the cwd guard and cross-AI delegation):** what this run spawns, builds, tests and commits, computed by `phase.dispatch-plan`. Spawn exactly its spawns; never re-derive waves, serial groups, isolation or builds.
422
-
423
- ```bash
424
- DISPATCH_PLAN=$(pp_run query phase.dispatch-plan "${PHASE_NUMBER}" --use-worktrees "${USE_WORKTREES:-true}" ${WAVE_FILTER:+--wave "$WAVE_FILTER"} ${GAPS_ONLY:+--gaps-only} ${TIER_FLAG})
425
- ```
426
-
427
- `stages.execute.waves[]` in order, each with `spawns[]` (`kind` `serial-group`|`plan`, `plans[]` in run order with `id`, `title`, `build`, `touched_tests`; `isolation` `main-checkout`|`worktree`; `build`; `checkpoint`), `run`, `merge`, `build`, `suite_runs` (1), `tracking_commits` (1), `tracking.requirements`, `defects[]`. Report `totals` (spawns, suite runs, tracking commits). Non-empty `filters.lower_wave_incomplete` → STOP: finish the earlier waves first.
428
-
429
430
  **Stream-idle-timeout prevention — checkpoint heartbeats (#2410):**
430
431
 
431
432
  Multi-plan phases can accumulate enough subagent context that the Claude API
@@ -448,14 +449,39 @@ increases monotonically across waves. `{status}` is `complete` (success),
448
449
 
449
450
  **For each wave:**
450
451
 
451
- 1. **Intra-wave files_modified overlap check (BEFORE spawning — computed):** the wave's `defects[]` lists any two plans in it that share a source file, and any two plans in different spawns that share any file. Plans of one serial group share non-source files by design — not a defect; their one spawn runs them one after another.
452
+ 1. **Intra-wave files_modified overlap check (BEFORE spawning):**
453
+
454
+ Before spawning any agents for this wave, inspect the `files_modified` list of all plans
455
+ in the wave. Check every pair of plans in the wave — if any two plans share even one file
456
+ in their `files_modified` lists, those plans have an implicit dependency and MUST NOT run
457
+ in parallel.
458
+
459
+ **Detection algorithm (pseudocode):**
460
+ ```
461
+ seen_files = {}
462
+ overlapping_plans = []
463
+ for each plan in wave_plans:
464
+ for each file in plan.files_modified:
465
+ if file in seen_files:
466
+ overlapping_plans.add(plan, seen_files[file]) # both plans overlap on this file
467
+ else:
468
+ seen_files[file] = plan
469
+ ```
452
470
 
453
- **If `defects` is non-empty:** warn the user with each defect's `message`:
471
+ **If overlap is detected:**
472
+ - Warn the user:
454
473
  ```
455
474
  ⚠ Intra-wave files_modified overlap detected in Wave {N}:
456
- {defect.message}
475
+ Plan {A} and Plan {B} both modify {file}
476
+ Running these plans sequentially to avoid parallel worktree conflicts.
457
477
  ```
458
- The wave's `run` is then `sequential` — run its spawns one at a time — and the overlap is a planning defect the user may replan.
478
+ - Override `PARALLELIZATION` to `false` for this wave only — run all plans in the wave
479
+ sequentially regardless of the global parallelization setting.
480
+ - This is a safety net for plans that were incorrectly assigned to the same wave.
481
+ The planner should have caught this; flag it as a planning defect so the user can
482
+ replan the phase if desired.
483
+
484
+ **If no overlap:** proceed normally (parallel if `PARALLELIZATION=true`).
459
485
 
460
486
  2. **Describe what's being built (BEFORE spawning):**
461
487
 
@@ -481,19 +507,21 @@ increases monotonically across waves. `{status}` is `complete` (success),
481
507
  ---
482
508
  ## Wave {N}
483
509
 
484
- **{Plan ID}: {plan_title}**
510
+ **{Plan ID}: {Plan Name}**
485
511
  {2-3 sentences: what this builds, technical approach, why it matters}
486
512
 
487
- Spawning {count} agent(s) — one per spawn in this wave... (runs in a subagent — no output until it returns, ~1–5 min; expected, not a freeze)
513
+ Spawning {count} agent(s)... (runs in a subagent — no output until it returns, ~1–5 min; expected, not a freeze)
488
514
  ---
489
515
  ```
490
516
 
491
517
  - Bad: "Executing terrain generation plan"
492
518
  - Good: "Procedural terrain generator using Perlin noise — creates height maps, biome zones, and collision meshes. Required before vehicle physics can interact with ground."
493
519
 
494
- 2.5. **Per-plan worktree decision (from the dispatch plan):** a spawn's `isolation` is the decision. `phase.dispatch-plan` makes it from `USE_WORKTREES` and `.gitmodules`: a serial group, a plan touching a submodule path, or a submodule-project plan with no `files_modified` gets `main-checkout`. For a `main-checkout` spawn set `USE_WORKTREES_FOR_PLAN=false`; for a `worktree` spawn leave it unset and append its plan ids to `WAVE_WORKTREE_PLANS`.
520
+ 2.5. **Per-plan worktree decision (run for each plan in this wave BEFORE its dispatch):**
495
521
 
496
- The dispatch branches in step 3 below MUST gate on `USE_WORKTREES_FOR_PLAN` for the current spawn, not on the project-level `USE_WORKTREES`.
522
+ Read and execute `pp-core/workflows/execute-phase/steps/per-plan-worktree-gate.md` for each plan. It extracts `PLAN_FILES` from the plan's JSON, intersects against `SUBMODULE_PATHS` (with normalization, bidirectional matching, and glob-prefix handling), and sets `USE_WORKTREES_FOR_PLAN` to `false` when the plan touches a submodule path. Append `plan_id` to a `WAVE_WORKTREE_PLANS` accumulator when `USE_WORKTREES_FOR_PLAN != false`.
523
+
524
+ The dispatch branches in step 3 below MUST gate on `USE_WORKTREES_FOR_PLAN` for the current plan, not on the project-level `USE_WORKTREES`.
497
525
 
498
526
  3. **Spawn executor agents:**
499
527
 
@@ -502,8 +530,6 @@ increases monotonically across waves. `{status}` is `complete` (success),
502
530
 
503
531
  `[checkpoint] phase {PHASE_NUMBER} wave {N}/{M} plan {plan_id} starting ({P}/{Q} plans done)`
504
532
 
505
- **Serial-group spawn** (`kind: serial-group`): Read and execute `pp-core/workflows/execute-phase/steps/serial-group-dispatch.md` — ONE executor on the main checkout for the whole group. The rest of step 3 covers `kind: plan` spawns.
506
-
507
533
  Pass paths only — executors read files themselves with their fresh context window.
508
534
  For 200k models, this keeps orchestrator context lean (~10-15%).
509
535
  For 1M+ models (Opus 4.6, Sonnet 4.6), richer context can be passed directly.
@@ -540,7 +566,7 @@ increases monotonically across waves. `{status}` is `complete` (success),
540
566
  ```text
541
567
  Agent(
542
568
  subagent_type="pp-executor",
543
- description="Execute plan {plan_number} of phase {phase_number}: {plan_title}",
569
+ description="Execute plan {plan_number} of phase {phase_number}",
544
570
  # Only include model= when executor_model is an explicit model name.
545
571
  # When executor_model is "inherit", omit this parameter entirely so
546
572
  # Claude Code inherits the orchestrator model automatically.
@@ -548,13 +574,11 @@ increases monotonically across waves. `{status}` is `complete` (success),
548
574
  isolation="worktree",
549
575
  prompt="
550
576
  <objective>
551
- Execute plan {plan_number} ({plan_title}) of phase {phase_number}-{phase_name}.
577
+ Execute plan {plan_number} of phase {phase_number}-{phase_name}.
552
578
  Commit each task atomically. Create SUMMARY.md.
553
579
  Do NOT update STATE.md or ROADMAP.md — the orchestrator owns those writes after all worktree agents in the wave complete.
554
580
  </objective>
555
581
 
556
- <dispatch tracking="orchestrator" suite="orchestrator" build="{spawn.build}" />
557
-
558
582
  <worktree_branch_check>
559
583
  ORCHESTRATOR build-time embed (NOT a sub-agent runtime step): before this dispatch, read `pp-core/references/worktree-branch-check.md`, substitute `{EXPECTED_BASE}` with the base SHA captured above ({EXPECTED_BASE}), and replace this note with that fragment's `<worktree_branch_check>` block so the dispatched prompt carries the runnable guard verbatim — do not pass this instruction through in its place.
560
584
  Per-commit HEAD/cwd-drift/path-guard: `agents/pp-executor.md` steps 0/0a/0b + `references/worktree-path-safety.md` (in <execution_context>).
@@ -607,6 +631,7 @@ increases monotonically across waves. `{status}` is `complete` (success),
607
631
  </files_to_read>
608
632
 
609
633
  ${AGENT_SKILLS}
634
+ ${EXECUTOR_HOOK_FRAGMENTS}
610
635
 
611
636
  <mcp_tools>
612
637
  If CLAUDE.md or project instructions reference MCP tools (e.g. jCodeMunch, context7,
@@ -643,14 +668,15 @@ increases monotonically across waves. `{status}` is `complete` (success),
643
668
  </sequential_execution>
644
669
  ```
645
670
 
646
- Everything else is the worktree-mode prompt, `<dispatch>` tag included — the orchestrator owns tracking for every spawn:
671
+ The sequential mode Agent prompt uses the same structure as worktree mode but with these differences in success_criteria — since there is only one agent writing at a time, there are no shared-file conflicts:
647
672
 
648
673
  ```
649
674
  <success_criteria>
650
675
  - [ ] All tasks executed
651
676
  - [ ] Each task committed individually
652
677
  - [ ] SUMMARY.md created in plan directory
653
- - [ ] No tracking-file writes (the orchestrator advances them once per wave)
678
+ - [ ] STATE.md updated with position and decisions
679
+ - [ ] ROADMAP.md updated with plan progress (via `roadmap update-plan-progress`)
654
680
  </success_criteria>
655
681
  ```
656
682
 
@@ -693,7 +719,7 @@ increases monotonically across waves. `{status}` is `complete` (success),
693
719
  for activity. If no completion signal, no SUMMARY.md, and no expected-branch
694
720
  commits appear for `${EXECUTOR_STALL_THRESHOLD_MINUTES}` minutes, pause and
695
721
  ask for one recovery path: `continue waiting`, `kill and retry`, or
696
- `kill and switch to inline execution` (U-E7).
722
+ `kill and switch to inline execution` (U-E7). The inline switch follows `EXECUTOR_HOOK_FRAGMENTS` too.
697
723
 
698
724
  If the stalled executor ran in an isolated worktree, `kill and switch to inline execution` edits the primary checkout — see worktree recovery policy (`execute-phase/steps/worktree-recovery-policy.md`). Prefer `kill and retry` in a fresh worktree; inline execution requires explicit confirmation, never the default.
699
725
 
@@ -791,7 +817,7 @@ increases monotonically across waves. `{status}` is `complete` (success),
791
817
 
792
818
  **When to skip step 5.5:**
793
819
 
794
- **If no spawn in this wave used worktree isolation** (the wave's `merge.cleanup` is false — `WAVE_WORKTREE_PLANS` from step 2.5 is empty): all agents ran on the main working tree — skip this step entirely.
820
+ **If no plan in this wave used worktree isolation** (project-level `USE_WORKTREES=false` OR every plan in the wave had `USE_WORKTREES_FOR_PLAN=false` — i.e. `WAVE_WORKTREE_PLANS` from step 2.5 is empty): all agents ran on the main working tree — skip this step entirely.
795
821
 
796
822
  **If the orchestrator merged via custom messages (cross-wave-dependency deviation):** the templated cleanup loop above was not triggered for those merges. Run the cleanup-tail snippet above instead. After the snippet completes, proceed to step 5.6.
797
823
 
@@ -803,12 +829,10 @@ increases monotonically across waves. `{status}` is `complete` (success),
803
829
 
804
830
  5.6. **Post-merge build & test gate:**
805
831
 
806
- Once per wave, after the merge step (whatever ran: worktrees, a serial group, main-checkout
807
- plans), run a build and then the project's full test suite — exactly once per wave
808
- (`suite_runs: 1`), by the orchestrator, never per plan. Skip the build (Step A) when the
809
- wave's `build` is false (no plan in it touches source). This catches cross-plan integration
810
- issues that per-plan checks cannot detect (e.g., conflicting type definitions, removed
811
- exports, import changes, link errors).
832
+ After merging all worktrees in a wave (parallel mode), or after the last plan completes
833
+ (serial mode), run a build and then the project's test suite to catch cross-plan
834
+ integration issues that individual worktree self-checks cannot detect (e.g., conflicting
835
+ type definitions, removed exports, import changes, link errors).
812
836
 
813
837
  This addresses the Generator self-evaluation blind spot identified in Anthropic's
814
838
  harness engineering research: agents reliably report Self-Check: PASSED even when
@@ -816,28 +840,25 @@ increases monotonically across waves. `{status}` is `complete` (success),
816
840
 
817
841
  Read and execute `pp-core/workflows/execute-phase/steps/post-merge-gate.md`.
818
842
 
819
- 5.7. **Post-wave tracking (every wave, once, by the orchestrator; skip if tests failed):**
843
+ 5.7. **Post-wave shared artifact update (when at least one plan used worktrees, skip if tests failed):**
820
844
 
821
- No executor writes tracking files under execute-phase (each prompt carries `<dispatch tracking="orchestrator">`), worktree or main checkout alike. After the merge and the suite, the orchestrator alone:
822
- refreshes the plan rows and the Built state with `roadmap update-plan-progress`;
823
- advances STATE, records the wave's `tracking.requirements` (`requirements.mark-complete`) and the `key-decisions` of its SUMMARY.md files (`state.add-decision`);
824
- makes the wave's ONE tracking commit (`tracking_commits: 1`).
845
+ When **any** executor agent in this wave ran with `isolation="worktree"`, that agent skipped STATE.md and ROADMAP.md updates to avoid last-merge-wins overwrites. The orchestrator is the single writer for these files. After worktrees are merged back, update shared artifacts once for every completed plan in the wave (worktree-mode plans **and** sequential plans that ran on the main tree but deferred to the orchestrator for tracking writes).
825
846
 
826
847
  **Only update tracking when tests passed (TEST_EXIT=0).**
827
848
  If tests failed or timed out, skip the tracking update — plans should
828
849
  not be marked as complete when integration tests are failing or inconclusive.
829
850
 
830
851
  ```bash
831
- # Timeout (124) is inconclusive — do NOT mark plans complete
852
+ # Guard: only update tracking if post-merge tests passed
853
+ # Timeout (124) is treated as inconclusive — do NOT mark plans complete
832
854
  if [ "${TEST_EXIT}" -eq 0 ]; then
833
- # Plan rows and the Built state (D-08-12); phase completion is phase.complete's, in update_roadmap.
855
+ # Refresh plan rows and the Built state from disk (D-08-12). Phase completion is NOT
856
+ # written here — phase.complete does that in update_roadmap, after the execute:post gate.
834
857
  pp_run query roadmap.update-plan-progress "${PHASE_NUMBER}"
835
- pp_run query state.update-progress
836
- # WAVE_REQ_IDS: this wave's tracking.requirements from DISPATCH_PLAN, space-separated
837
- [ -n "${WAVE_REQ_IDS:-}" ] && pp_run query requirements.mark-complete ${WAVE_REQ_IDS}
838
- pp_run query state.record-session --stopped-at "Phase ${PHASE_NUMBER} wave ${N} complete" --resume-file "None"
839
- if ! git diff --quiet .planning/ROADMAP.md .planning/STATE.md .planning/REQUIREMENTS.md 2>/dev/null; then
840
- pp_run query commit "docs(phase-${PHASE_NUMBER}): update tracking after wave ${N}" --files .planning/ROADMAP.md .planning/STATE.md .planning/REQUIREMENTS.md
858
+
859
+ # Only commit tracking files if they actually changed
860
+ if ! git diff --quiet .planning/ROADMAP.md .planning/STATE.md 2>/dev/null; then
861
+ pp_run query commit "docs(phase-${PHASE_NUMBER}): update tracking after wave ${N}" --files .planning/ROADMAP.md .planning/STATE.md
841
862
  fi
842
863
  elif [ "${TEST_EXIT}" -eq 124 ]; then
843
864
  echo "⚠ Skipping tracking update — test suite timed out. Plans remain in-progress. Run tests manually to confirm."
@@ -846,48 +867,35 @@ increases monotonically across waves. `{status}` is `complete` (success),
846
867
  fi
847
868
  ```
848
869
 
870
+ **If no plan in this wave used worktrees** (project-level `USE_WORKTREES=false` OR `WAVE_WORKTREE_PLANS` is empty): sequential agents already updated STATE.md and ROADMAP.md themselves — skip this step.
871
+
849
872
  5.75. **Execute:wave:post capability dispatch:**
850
873
 
851
874
  After worktree merge, post-merge tests, and tracking updates, dispatch capability hooks registered at `execute:wave:post`. The primary hook is the `ui.safety-gate` gate from the UI capability — it verifies that any frontend files changed in this wave conform to the UI-SPEC contract.
852
875
 
853
876
  ```bash
854
- WAVE_POST_HOOKS_JSON=$(pp_run loop render-hooks execute:wave:post --raw) || exit 1
877
+ WAVE_POST_HOOKS_JSON=$(pp_run loop render-hooks execute:wave:post --raw)
878
+ printf '%s' "$WAVE_POST_HOOKS_JSON" | node -e "let h=[];try{h=JSON.parse(require('fs').readFileSync(0,'utf-8')).activeHooks||[]}catch{}console.log('WAVE_POST_HOOKS_JSON='+JSON.stringify({activeHooks:h}))"
855
879
  ```
856
880
 
857
- Read the `activeHooks` array from `WAVE_POST_HOOKS_JSON` in-context (do NOT pipe through a shell parser).
881
+ Read the `activeHooks` array from the printed `WAVE_POST_HOOKS_JSON=` line, in-context (do NOT pipe through a shell parser).
858
882
 
859
883
  **If `activeHooks` is empty or absent:** Skip silently to step 5.8.
860
884
 
861
- **For each active entry where `kind == "gate"`** (process in array order), run the gate check:
862
-
863
- ```bash
864
- GATE_RESULT=$(pp_run check ${hook.check.query} "${PHASE_NUMBER}" --raw)
865
- CHECK_EXIT=$?
866
- ```
867
-
868
- **Step 1 — did the CHECK COMMAND itself succeed?**
869
-
870
- If the check command failed (non-zero `CHECK_EXIT`, empty output, or unparseable JSON):
871
- - `onError == "halt"` → treat as a fatal error: stop wave completion, do NOT proceed to step 5.8, and surface: `⚠ Gate check command failed ({hook.capId}): command error. Resolve before continuing.`
872
- - `onError == "skip"` → log a warning and continue to the next hook. Do NOT read `GATE_RESULT.block`.
873
-
874
- **Step 2 — read `GATE_RESULT.block` (boolean).** This step is only reached when the command succeeded.
875
-
876
- - **Blocking gate (`hook.blocking == true`) AND `GATE_RESULT.block == true`:** HALT — stop wave completion, do NOT proceed to step 5.8, and present:
877
-
878
- ```
879
- ⚠ Wave {N} blocked by capability gate ({hook.capId}): {GATE_RESULT.message}
880
- Resolve before continuing to next wave.
881
- ```
882
-
883
- This halt is **not** bypassed by `onError` — `onError` only covers command errors (step 1 above), not the gate's block decision.
884
-
885
- - **Non-blocking gate (`hook.blocking == false`):** never halts. If `GATE_RESULT.block` is `true` (or non-empty `message`), print `⚠ {hook.capId} advisory (wave {N}): {GATE_RESULT.message}`, then:
886
- - If `GATE_RESULT.spawn_mapper == true` OR `GATE_RESULT.directive == "auto-remap"`: spawn `pp-codebase-mapper` per `execute-phase/steps/codebase-drift-gate.md`; pass `--paths {GATE_RESULT.affected_paths}`. Continue regardless (wave NOT failed by remap failure).
887
- - Otherwise: continue after advisory.
888
- - If block `false` and no `message`: continue silently.
889
-
890
- - **Blocking gate (`hook.blocking == true`) AND `GATE_RESULT.block == false`:** continue silently.
885
+ **Otherwise**, set `GATE_POINT=execute:wave:post`, `GATE_HOOKS_JSON=$WAVE_POST_HOOKS_JSON`,
886
+ `GATE_POSITIONAL_ARG="${PHASE_NUMBER}"` — preserving the positional phase-number argument this
887
+ call site has always passed — and `GATE_WS` to the active workstream name (empty in flat mode),
888
+ without which a phase-number positional cannot resolve on a partitioned project, then Read and follow
889
+ `pp-core/workflows/execute-phase/steps/check-query-gate.md`. That file is the single generic
890
+ `check.query` gate enforcer (GATE-02, D-VH-7): it owns the two-step contract (did the command
891
+ succeed? → then read the boolean `block`) and the halt. Do not restate its loop here.
892
+
893
+ **After the enforcer returns without halting**, perform this call site's own advisory follow-up
894
+ for each non-blocking entry it reported: if the verdict carried `spawn_mapper == true` OR
895
+ `directive == "auto-remap"`, spawn `pp-codebase-mapper` per
896
+ `execute-phase/steps/codebase-drift-gate.md`, passing `--paths {affected_paths}`. Continue
897
+ regardless — a remap failure never fails the wave. The enforcer owns the halt decision; this
898
+ directive handling is the host's, not the enforcer's.
891
899
 
892
900
  **When all active gates are processed without a blocking halt:** continue to step 5.8.
893
901
 
@@ -943,7 +951,7 @@ increases monotonically across waves. `{status}` is `complete` (success),
943
951
  ---
944
952
  ## Wave {N} Complete
945
953
 
946
- **{Plan ID}: {plan_title}**
954
+ **{Plan ID}: {Plan Name}**
947
955
  {What was built — from SUMMARY.md}
948
956
  {Notable deviations, if any}
949
957
 
@@ -989,7 +997,45 @@ increases monotonically across waves. `{status}` is `complete` (success),
989
997
  9. **Proceed to next wave.**
990
998
  </step>
991
999
  <step name="checkpoint_handling">
992
- Plans with `autonomous: false` require user interaction. When an executor returns a checkpoint, Read and execute `pp-core/workflows/execute-phase/steps/checkpoint-handling.md` (auto-mode rules, continuation-agent flow).
1000
+ Plans with `autonomous: false` require user interaction.
1001
+ **Auto-mode checkpoint handling:**
1002
+ Read auto-advance config (chain flag OR user preference — same boolean as `check.auto-mode`):
1003
+ ```bash
1004
+ AUTO_MODE=$(pp_run query check auto-mode --pick active 2>/dev/null || echo "false")
1005
+ ```
1006
+
1007
+ When executor returns a checkpoint AND (`UNATTENDED` or `AUTO_MODE`) is true (U-E1):
1008
+ - **human-action**, or package legitimacy — ANY of `**Gate:** blocking-human` in the return (the executor copies the task's `gate` attribute there), `gate="blocking-human"`, or `what-built` begins `Package`; the last two are the fallback for a return that predates the `Gate:` line → hard stop: present to user (below).
1009
+ - **human-verify** (other) → continuation with `{user_response}` = `"DEFERRED — not verified by a human (unattended run); record this checkpoint as not done in the SUMMARY and continue"`; log `⏭ Checkpoint deferred (recorded, not approved)`.
1010
+ - **decision** → continuation with the option marked recommended, else the first; log `⚡ Auto-selected: [option]`.
1011
+
1012
+ **Standard flow (neither flag, human-action, or blocking-human):**
1013
+
1014
+ 1. Spawn agent for checkpoint plan
1015
+ 2. Agent runs until checkpoint task or auth gate → returns structured state
1016
+ 3. Agent return includes: completed tasks table, current task + blocker, checkpoint type/details, what's awaited
1017
+ 4. **Present to user:**
1018
+ ```
1019
+ ## Checkpoint: [Type]
1020
+
1021
+ **Plan:** 03-03 Dashboard Layout
1022
+ **Progress:** 2/3 tasks complete
1023
+
1024
+ [Checkpoint Details from agent return]
1025
+ [Awaiting section from agent return]
1026
+ ```
1027
+ 5. User responds: "approved"/"done" | issue description | decision selection
1028
+ 6. **Spawn continuation agent (NOT resume)** using continuation-prompt.md template:
1029
+ - `{completed_tasks_table}`: From checkpoint return
1030
+ - `{resume_task_number}` + `{resume_task_name}`: Current task
1031
+ - `{user_response}`: What user provided
1032
+ - `{resume_instructions}`: Based on checkpoint type
1033
+ 7. Continuation agent verifies previous commits, continues from resume point
1034
+ 8. Repeat until plan completes or user stops
1035
+
1036
+ **Fresh agent, not resume:** resume breaks with parallel tool calls.
1037
+
1038
+ **Checkpoints in parallel waves:** Agent pauses and returns while other parallel agents may complete. Present checkpoint, spawn continuation, wait for all before next wave.
993
1039
  </step>
994
1040
 
995
1041
  <step name="aggregate_results">
@@ -1016,10 +1062,13 @@ After all waves:
1016
1062
 
1017
1063
  **Security gate check:**
1018
1064
  ```bash
1019
- VERIFY_POST_HOOKS_JSON=$(pp_run loop render-hooks verify:post --raw --phase "${PHASE_NUMBER}" ${TIER_FLAG}) || exit 1
1065
+ VERIFY_POST_HOOKS_JSON=$(pp_run loop render-hooks verify:post --raw)
1066
+ printf '%s' "$VERIFY_POST_HOOKS_JSON" | node -e "let h=[];try{h=JSON.parse(require('fs').readFileSync(0,'utf-8')).activeHooks||[]}catch{}console.log('VERIFY_POST_HOOKS_JSON='+JSON.stringify({activeHooks:h}))"
1020
1067
  SECURITY_FILE=$(ls "${PHASE_DIR}"/*-SECURITY.md 2>/dev/null | head -1)
1021
1068
  ```
1022
1069
 
1070
+ **Trace gate.** Read `pp-core/workflows/execute-phase/steps/verify-post-gate.md`.
1071
+
1023
1072
  Resolve active step hooks from `VERIFY_POST_HOOKS_JSON` where `kind == "step"` and `ref.skill == "secure-phase"`.
1024
1073
 
1025
1074
  If no active secure-phase step hook exists: skip.
@@ -1074,7 +1123,8 @@ Selected wave finished successfully. This phase still has incomplete plans, so p
1074
1123
 
1075
1124
  **Capability gate:**
1076
1125
  ```bash
1077
- EXECUTE_POST_HOOKS_JSON=${EXECUTE_POST_HOOKS_JSON:-$(pp_run loop render-hooks execute:post --raw --phase "${PHASE_NUMBER}" ${TIER_FLAG})} || exit 1
1126
+ EXECUTE_POST_HOOKS_JSON=${EXECUTE_POST_HOOKS_JSON:-$(pp_run loop render-hooks execute:post --raw)}
1127
+ printf '%s' "$EXECUTE_POST_HOOKS_JSON" | node -e "let h=[];try{h=JSON.parse(require('fs').readFileSync(0,'utf-8')).activeHooks||[]}catch{}console.log('EXECUTE_POST_HOOKS_JSON='+JSON.stringify({activeHooks:h}))"
1078
1128
  ```
1079
1129
 
1080
1130
  Resolve active step hooks from `EXECUTE_POST_HOOKS_JSON` where `kind == "step"` and `ref.skill == "code-review"`.
@@ -1101,17 +1151,11 @@ Code review found issues. Consider running:
1101
1151
 
1102
1152
  **Error handling:** If the Skill invocation fails or throws, catch the error, display "Code review encountered an error (non-blocking): {error}" and proceed to gate dispatch. Review failures must never block execution.
1103
1153
 
1104
- **Execute:post gate hook dispatch.** After code review, dispatch all active gate hooks from `EXECUTE_POST_HOOKS_JSON` where `kind == "gate"`:
1105
-
1106
- For each active gate hook:
1107
- ```bash
1108
- GATE_RESULT=$(pp_run check ${hook.check.query} "${PHASE_NUMBER}" --raw)
1109
- CHECK_EXIT=$?
1110
- ```
1154
+ **Execute:post gate hook dispatch.** After code review, dispatch all active gate hooks from `EXECUTE_POST_HOOKS_JSON` where `kind == "gate"`. If none are active, skip silently.
1111
1155
 
1112
- **Gate evaluation** uses the same two-step contract as `execute:wave:post` above: **Step 1** — if the check command failed (non-zero `CHECK_EXIT`, empty/unparseable output), `onError == "halt"` stops and surfaces the error, `onError == "skip"` warns and continues to the next hook (do not read `block`). **Step 2** (command succeeded) — a blocking gate (`hook.blocking == true`) halts on `GATE_RESULT.block == true` with its message/table (never bypassed by `onError`); an advisory gate (`hook.blocking == false`) shows its `table`/summary when `block == true` or `message` is non-empty, then continues; a blocking gate with `block == false` continues silently.
1156
+ Set `GATE_POINT=execute:post`, `GATE_HOOKS_JSON=$EXECUTE_POST_HOOKS_JSON`, `GATE_POSITIONAL_ARG="${PHASE_NUMBER}"` and `GATE_WS` to the active workstream name (empty in flat mode) — without it the phase-number positional cannot resolve on a partitioned project, and this is the point where the blocking `vault.trace` gate is declared — then Read and follow `pp-core/workflows/execute-phase/steps/check-query-gate.md` — the same single generic `check.query` gate enforcer used at `execute:pre` and `execute:wave:post` (GATE-02, D-VH-7). It owns the two-step contract (did the command succeed? → then read the boolean `block`) and the halt. Do not restate its loop here.
1113
1157
 
1114
- **TDD review escalation (overrides the advisory default for the `tdd.review-checkpoint` gate only).** The tdd `execute:post` gate is declared `blocking: false`, so by the generic contract above it displays its `message`/table and continues. There is ONE documented exception (see `~/.claude/pp-core/references/execute-mvp-tdd.md`): when `MVP_MODE=true` AND `TDD_MODE=true` AND `GATE_RESULT.block == true` (one or more TDD plans miss a RED or GREEN gate commit), the end-of-phase TDD review escalates from advisory to **blocking under MVP+TDD** — refuse to mark the phase complete and present:
1158
+ **TDD review escalation (overrides the advisory default for the `tdd.review-checkpoint` gate only).** The tdd `execute:post` gate is declared `blocking: false`, so the enforcer displays its `message`/table and continues. There is ONE documented exception (see `~/.claude/pp-core/references/execute-mvp-tdd.md`), applied by this host workflow *after* the enforcer returns: when `MVP_MODE=true` AND `TDD_MODE=true` AND the enforcer reported a `true` block verdict for `tdd.review-checkpoint` (one or more TDD plans miss a RED or GREEN gate commit), the end-of-phase TDD review escalates from advisory to **blocking under MVP+TDD** — refuse to mark the phase complete and present:
1115
1159
 
1116
1160
  ```
1117
1161
  Phase blocked: {N} TDD plan(s) violate the RED→GREEN gate sequence under MVP+TDD.
@@ -1120,7 +1164,7 @@ Resolve and re-run /pp:execute-phase, or override with /pp:execute-phase {phase}
1120
1164
 
1121
1165
  (`--force-mvp-gate` is the documented, not-yet-implemented escape hatch.) Outside MVP+TDD, TDD-review violations remain advisory (table shown, execution continues).
1122
1166
 
1123
- **Proceed rule:** If `MVP_MODE && TDD_MODE && GATE_RESULT.block == true` for `tdd.review-checkpoint`: STOP — do NOT proceed to `close_parent_artifacts`, `regression_gate`, `verify_phase_goal`, or `phase.complete`. Otherwise proceed normally.
1167
+ **Proceed rule:** If `MVP_MODE && TDD_MODE` and the enforcer's reported block verdict for `tdd.review-checkpoint` is `true`: STOP — do NOT proceed to `close_parent_artifacts`, `regression_gate`, `verify_phase_goal`, or `phase.complete`. Otherwise proceed normally.
1124
1168
  </step>
1125
1169
 
1126
1170
  <step name="close_parent_artifacts">
@@ -1243,12 +1287,12 @@ If `TEXT_MODE` is true, present as a plain-text numbered list and ask the user t
1243
1287
  <step name="verify_phase_goal">
1244
1288
  Verify phase achieved its GOAL, not just completed tasks.
1245
1289
 
1246
- **Tier gate:** spawn the verifier only when `DISPATCH_PLAN.stages.verify` lists `pp-verifier` (= `verifier_enabled`). Otherwise print `Verifier skipped (tier {phase_tier.tier})`, treat the phase as `passed` and go to `update_roadmap`. When it lists `verify-install` (heavy tier), first Read and execute `pp-core/workflows/execute-phase/steps/install-run.md`: the installed-product run the verifier judges on.
1247
-
1248
1290
  ```bash
1249
1291
  VERIFIER_SKILLS=$(pp_run query agent-skills pp-verifier)
1250
1292
  ```
1251
1293
 
1294
+ Read and execute `execute-phase/steps/verifier-practice-payload.md` (sets `PRACTICE_VERDICT_INPUT`).
1295
+
1252
1296
  ```
1253
1297
  Agent(
1254
1298
  description="Verify phase {phase_number} goal achievement",
@@ -1267,11 +1311,11 @@ MANDATORY: load every file listed here with the Read tool before you start the w
1267
1311
  - .planning/REQUIREMENTS.md (Requirement traceability)
1268
1312
  - {phase_dir}/*-CONTEXT.md (User decisions — verify they were honored)
1269
1313
  - {phase_dir}/*-RESEARCH.md (Known pitfalls — check for traps)
1270
- ${INSTALL_RUN_FILE ? `- ${INSTALL_RUN_FILE} (installed-product run — judge user-facing behaviour on it, not on the repo)
1271
- ` : ''}${CONTEXT_WINDOW >= 500000 ? `- Prior VERIFICATION.md files from earlier phases (regression check)
1314
+ ${CONTEXT_WINDOW >= 500000 ? `- Prior VERIFICATION.md files from earlier phases (regression check)
1272
1315
  ` : ''}
1273
1316
  </files_to_read>
1274
1317
 
1318
+ ${PRACTICE_VERDICT_INPUT}
1275
1319
  ${VERIFIER_SKILLS}",
1276
1320
  subagent_type="pp-verifier",
1277
1321
  model="{verifier_model}"
@@ -1389,7 +1433,7 @@ Gap closure cycle: `/pp:plan-phase {X} --gaps ${GSD_WS}` reads VERIFICATION.md
1389
1433
  <step name="update_roadmap">
1390
1434
  **Mark phase complete and update all tracking files:**
1391
1435
 
1392
- First, Read and execute `pp-core/workflows/execute-phase/steps/phase-close-rebaseline.md` (the phase's one size re-baseline; inert where no `size:baseline` script exists).
1436
+ Reached only after the `execute:post` gate dispatch above returned without halting and `verify_phase_goal` reported `passed` — completion follows that outcome, never a plan or SUMMARY count (D-08-13). `phase.complete` writes ROADMAP.md, REQUIREMENTS.md and STATE.md in one transaction with rollback: both move or neither does (D-08-14). Until here the phase reads `Built` (D-08-15).
1393
1437
 
1394
1438
  ```bash
1395
1439
  COMPLETION=$(pp_run query phase.complete "${PHASE_NUMBER}")