@pareto4/pp-core 1.18.0 → 1.19.0

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 (147) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/agents/pp-code-fixer.md +9 -5
  3. package/agents/pp-code-reviewer.md +1 -0
  4. package/agents/pp-codebase-mapper.md +3 -0
  5. package/agents/pp-debugger.md +3 -2
  6. package/agents/pp-executor.md +16 -7
  7. package/agents/pp-integration-checker.md +1 -0
  8. package/agents/pp-phase-researcher.md +3 -1
  9. package/agents/pp-plan-checker.md +3 -0
  10. package/agents/pp-planner.md +5 -1
  11. package/agents/pp-research-synthesizer.md +1 -1
  12. package/agents/pp-ui-auditor.md +1 -0
  13. package/agents/pp-ui-researcher.md +3 -1
  14. package/agents/pp-verifier.md +10 -2
  15. package/commands/pp-add-tests.md +1 -1
  16. package/commands/pp-debug.md +1 -0
  17. package/commands/pp-init.md +4 -3
  18. package/commands/pp-quick.md +3 -0
  19. package/commands/pp-review-backlog.md +2 -1
  20. package/gemini-extension.json +1 -1
  21. package/package.json +1 -1
  22. package/pp-core/bin/lib/capability-registry.cjs +2 -2
  23. package/pp-core/bin/lib/check-command-router.cjs +60 -20
  24. package/pp-core/bin/lib/commands.cjs +79 -4
  25. package/pp-core/bin/lib/compose-bindings.cjs +97 -14
  26. package/pp-core/bin/lib/discovery-rollup.cjs +9 -6
  27. package/pp-core/bin/lib/discovery-screens.cjs +20 -2
  28. package/pp-core/bin/lib/discovery-sweep.cjs +12 -3
  29. package/pp-core/bin/lib/discovery-vault-check.cjs +37 -3
  30. package/pp-core/bin/lib/init-contract.cjs +48 -7
  31. package/pp-core/bin/lib/vault-coordinates.cjs +1 -1
  32. package/pp-core/bin/lib/vault-index.cjs +18 -5
  33. package/pp-core/bin/lib/vault-update.cjs +4 -0
  34. package/pp-core/bin/lib/vault.cjs +2 -2
  35. package/pp-core/bin/pp-tools.cjs +10 -4
  36. package/pp-core/org-profile.json +1 -1
  37. package/pp-core/references/autonomous-best-effort.md +3 -2
  38. package/pp-core/references/autonomous-lifecycle.md +1 -0
  39. package/pp-core/references/autonomous-smart-discuss.md +5 -1
  40. package/pp-core/references/discovery-id-conventions.md +35 -2
  41. package/pp-core/references/execute-mvp-tdd.md +3 -3
  42. package/pp-core/references/git-integration.md +57 -33
  43. package/pp-core/references/git-planning-commit.md +31 -9
  44. package/pp-core/references/phase-argument-parsing.md +1 -0
  45. package/pp-core/references/planner-gap-closure.md +1 -0
  46. package/pp-core/references/planner-revision.md +3 -1
  47. package/pp-core/references/planner-tdd.md +4 -4
  48. package/pp-core/references/planning-config.md +3 -3
  49. package/pp-core/references/shell-portability.md +28 -0
  50. package/pp-core/references/tdd.md +20 -16
  51. package/pp-core/references/worktree-path-safety.md +1 -0
  52. package/pp-core/templates/milestone.md +5 -5
  53. package/pp-core/workflows/add-backlog.md +1 -1
  54. package/pp-core/workflows/add-tests.md +5 -2
  55. package/pp-core/workflows/add-todo.md +3 -1
  56. package/pp-core/workflows/ai-integration-phase.md +2 -1
  57. package/pp-core/workflows/audit-fix.md +4 -3
  58. package/pp-core/workflows/audit-milestone.md +1 -0
  59. package/pp-core/workflows/autonomous.md +6 -0
  60. package/pp-core/workflows/check-todos.md +2 -1
  61. package/pp-core/workflows/cleanup.md +3 -1
  62. package/pp-core/workflows/code-review-fix.md +12 -5
  63. package/pp-core/workflows/code-review.md +15 -1
  64. package/pp-core/workflows/complete-milestone.md +13 -3
  65. package/pp-core/workflows/debug.md +2 -0
  66. package/pp-core/workflows/diagnose-issues.md +1 -1
  67. package/pp-core/workflows/discovery-sprint/session-13-gates.md +1 -1
  68. package/pp-core/workflows/discovery-sprint/sessions/01-kick-off.md +51 -7
  69. package/pp-core/workflows/discovery-sprint/sessions/02-as-is.md +5 -3
  70. package/pp-core/workflows/discovery-sprint/sessions/03-to-be.md +10 -8
  71. package/pp-core/workflows/discovery-sprint/sessions/04-ux-design.md +11 -2
  72. package/pp-core/workflows/discovery-sprint/sessions/05-architecture.md +5 -5
  73. package/pp-core/workflows/discovery-sprint/sessions/06-security.md +3 -3
  74. package/pp-core/workflows/discovery-sprint/sessions/07-identity.md +2 -2
  75. package/pp-core/workflows/discovery-sprint/sessions/08-integration.md +14 -2
  76. package/pp-core/workflows/discovery-sprint/sessions/09-qa.md +2 -2
  77. package/pp-core/workflows/discovery-sprint/sessions/10-infrastructure.md +10 -10
  78. package/pp-core/workflows/discovery-sprint/sessions/11-roadmap.md +11 -8
  79. package/pp-core/workflows/discovery-sprint/sessions/12-delivery-model.md +21 -18
  80. package/pp-core/workflows/discovery-sprint/sessions/13-wrap-up.md +5 -3
  81. package/pp-core/workflows/discovery-sprint/templates/context-template.md +9 -3
  82. package/pp-core/workflows/discovery-sprint/vault-context.md +14 -3
  83. package/pp-core/workflows/discovery-sprint.md +11 -8
  84. package/pp-core/workflows/discovery-to-build/steps/architecture-deliverables.md +1 -0
  85. package/pp-core/workflows/discuss-phase-assumptions.md +5 -3
  86. package/pp-core/workflows/discuss-phase.md +8 -3
  87. package/pp-core/workflows/docs-update.md +1 -0
  88. package/pp-core/workflows/eval-review.md +2 -1
  89. package/pp-core/workflows/execute-phase/steps/check-query-gate.md +7 -6
  90. package/pp-core/workflows/execute-phase/steps/cross-ai-delegation.md +1 -0
  91. package/pp-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +1 -0
  92. package/pp-core/workflows/execute-phase/steps/vault-fetch.md +12 -0
  93. package/pp-core/workflows/execute-phase.md +19 -7
  94. package/pp-core/workflows/execute-plan.md +18 -7
  95. package/pp-core/workflows/explore.md +1 -1
  96. package/pp-core/workflows/forensics.md +4 -2
  97. package/pp-core/workflows/health.md +1 -0
  98. package/pp-core/workflows/import.md +2 -1
  99. package/pp-core/workflows/ingest-docs.md +1 -0
  100. package/pp-core/workflows/init/steps/client-context-capture.md +1 -0
  101. package/pp-core/workflows/init/steps/github-provisioning.md +145 -0
  102. package/pp-core/workflows/init/steps/gitlab-provisioning.md +18 -4
  103. package/pp-core/workflows/init/steps/reachability-outcome.md +3 -1
  104. package/pp-core/workflows/init.md +56 -66
  105. package/pp-core/workflows/map-codebase.md +5 -1
  106. package/pp-core/workflows/milestone-summary.md +2 -1
  107. package/pp-core/workflows/mvp-phase.md +1 -0
  108. package/pp-core/workflows/new-milestone.md +9 -5
  109. package/pp-core/workflows/new-project.md +9 -8
  110. package/pp-core/workflows/new-workspace.md +1 -0
  111. package/pp-core/workflows/next.md +2 -1
  112. package/pp-core/workflows/pause-work.md +6 -4
  113. package/pp-core/workflows/plan-milestone-gaps.md +3 -1
  114. package/pp-core/workflows/plan-phase/steps/chunked-planning.md +1 -1
  115. package/pp-core/workflows/plan-phase.md +21 -6
  116. package/pp-core/workflows/plan-review-convergence.md +2 -0
  117. package/pp-core/workflows/plant-seed.md +4 -2
  118. package/pp-core/workflows/pr-branch.md +2 -0
  119. package/pp-core/workflows/progress.md +5 -0
  120. package/pp-core/workflows/quick.md +11 -4
  121. package/pp-core/workflows/reapply-patches.md +3 -0
  122. package/pp-core/workflows/remove-phase.md +1 -1
  123. package/pp-core/workflows/resume-project.md +3 -0
  124. package/pp-core/workflows/review.md +7 -1
  125. package/pp-core/workflows/secure-phase.md +2 -1
  126. package/pp-core/workflows/session-report.md +1 -0
  127. package/pp-core/workflows/ship.md +8 -1
  128. package/pp-core/workflows/sketch-wrap-up.md +1 -1
  129. package/pp-core/workflows/sketch.md +3 -2
  130. package/pp-core/workflows/spec-phase.md +2 -1
  131. package/pp-core/workflows/spike-wrap-up.md +1 -1
  132. package/pp-core/workflows/spike.md +4 -3
  133. package/pp-core/workflows/sync-skills.md +5 -2
  134. package/pp-core/workflows/thread.md +3 -2
  135. package/pp-core/workflows/transition.md +6 -0
  136. package/pp-core/workflows/ui-phase.md +3 -1
  137. package/pp-core/workflows/ui-review.md +2 -1
  138. package/pp-core/workflows/ultraplan-phase.md +1 -0
  139. package/pp-core/workflows/undo.md +14 -10
  140. package/pp-core/workflows/update.md +5 -0
  141. package/pp-core/workflows/validate-phase.md +6 -3
  142. package/pp-core/workflows/vault-review.md +2 -1
  143. package/pp-core/workflows/vault-write-back.md +5 -0
  144. package/pp-core/workflows/verify-phase.md +5 -0
  145. package/pp-core/workflows/verify-work.md +8 -1
  146. package/scripts/prompt-injection-scan.sh +1 -1
  147. package/scripts/sync-runtime-launcher.cjs +115 -5
@@ -323,7 +323,7 @@ pp_run query config-new-project '{"mode":"yolo","granularity":"[selected]","para
323
323
 
324
324
  ```bash
325
325
  mkdir -p .planning
326
- pp_run query commit "chore: add project config" --files .planning/config.json
326
+ pp_run query commit "chore(planning): add project config" --files .planning/config.json
327
327
  ```
328
328
 
329
329
  **Persist auto-advance chain flag to config (survives context compaction):**
@@ -339,6 +339,7 @@ Proceed to Step 4 (skip Steps 3 and 5).
339
339
  Check for existing spike and sketch work that should inform project setup:
340
340
 
341
341
  ```bash
342
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
342
343
  # Check for spike findings skill (project-local)
343
344
  SPIKE_SKILL=$(ls ./.claude/skills/spike-findings-*/SKILL.md 2>/dev/null | head -1 || true)
344
345
 
@@ -539,7 +540,7 @@ Do not compress. Capture everything gathered.
539
540
 
540
541
  ```bash
541
542
  mkdir -p .planning
542
- pp_run query commit "docs: initialize project" --files .planning/PROJECT.md
543
+ pp_run query commit "docs(planning): initialize project" --files .planning/PROJECT.md
543
544
  ```
544
545
 
545
546
  ## 5. Workflow Preferences
@@ -836,7 +837,7 @@ pp_run query config-new-project '{"mode":"[yolo|interactive]","granularity":"[se
836
837
  **Commit config.json:**
837
838
 
838
839
  ```bash
839
- pp_run query commit "chore: add project config" --files .planning/config.json
840
+ pp_run query commit "chore(planning): add project config" --files .planning/config.json
840
841
  ```
841
842
 
842
843
  ## 5.1. Sub-Repo Detection
@@ -884,9 +885,9 @@ echo "$ARM"
884
885
  ARMED=$(printf '%s' "$ARM" | node -e 'let s="";process.stdin.on("data",d=>{s+=d}).on("end",()=>{try{process.stdout.write(String(JSON.parse(s).armed===true))}catch{process.stdout.write("false")}})')
885
886
  if [ "$ARM_EXIT" -eq 0 ] && [ "$ARMED" = "true" ]; then
886
887
  if [ -f .platform-bindings.json ]; then
887
- pp_run query commit "chore: arm client vault from org profile" --files .planning/config.json .platform-bindings.json
888
+ pp_run query commit "chore(planning): arm client vault from org profile" --files .planning/config.json .platform-bindings.json
888
889
  else
889
- pp_run query commit "chore: arm client vault from org profile" --files .planning/config.json
890
+ pp_run query commit "chore(planning): arm client vault from org profile" --files .planning/config.json
890
891
  fi
891
892
  fi
892
893
  ```
@@ -1138,7 +1139,7 @@ Commit after writing.
1138
1139
  **Synthesizer output self-heal (#222) — verify SUMMARY.md materialized:** The synthesizer's canonical output is `.planning/research/SUMMARY.md` on disk; its brief structured return (`## SYNTHESIS COMPLETE` plus a few `###` confirmation lines) is NOT the file content. A known LLM false-refusal (issue #222) sometimes makes the agent return the full SUMMARY.md document inline — fabricating a write restriction (e.g. "the runtime is blocking file writes") — instead of writing the file. Prompt hardening alone does not fully eliminate it, so the orchestrator MUST absorb the failure deterministically before spawning `pp-roadmapper`:
1139
1140
 
1140
1141
  1. Verify `.planning/research/SUMMARY.md` exists AND is substantive — non-empty, and free of any leftover `<!-- gsd:write-continue -->` continuation sentinel (which marks a truncated/incomplete write). You may validate with `pp-tools verify-summary .planning/research/SUMMARY.md` — it exits 0 regardless, so check its JSON `passed` field (`"passed": false` means missing or invalid), not the process exit code. If it passes, continue normally.
1141
- 2. If it is MISSING or invalid AND the synthesizer's return message contains the FULL SUMMARY.md document — recognizable by the template's top-level markers `# Project Research Summary`, `## Key Findings`, `## Implications for Roadmap`, and `## Sources`, not merely the brief `## SYNTHESIS COMPLETE` confirmation — the false-refusal fired: write that returned document to `.planning/research/SUMMARY.md` with the Write tool, then commit ALL research artifacts the synthesizer owns (it commits on behalf of the four researchers) with `pp-tools query commit "docs: complete project research" --files .planning/research/` unless they are already committed. Log `⚠ #222 self-heal: synthesizer returned SUMMARY.md inline without writing it; orchestrator persisted the file.`
1142
+ 2. If it is MISSING or invalid AND the synthesizer's return message contains the FULL SUMMARY.md document — recognizable by the template's top-level markers `# Project Research Summary`, `## Key Findings`, `## Implications for Roadmap`, and `## Sources`, not merely the brief `## SYNTHESIS COMPLETE` confirmation — the false-refusal fired: write that returned document to `.planning/research/SUMMARY.md` with the Write tool, then commit ALL research artifacts the synthesizer owns (it commits on behalf of the four researchers) with `pp_run query commit "docs(planning): complete project research" --files .planning/research/` unless they are already committed. Log `⚠ #222 self-heal: synthesizer returned SUMMARY.md inline without writing it; orchestrator persisted the file.`
1142
1143
  3. If it is MISSING or invalid AND the return is only a brief confirmation (no full SUMMARY document to recover), the synthesizer genuinely failed — surface the error and stop; do NOT spawn `pp-roadmapper` against a missing or incomplete SUMMARY.md.
1143
1144
 
1144
1145
  This guarantees `pp-roadmapper` (which lists SUMMARY.md as required reading) never runs against a missing or truncated SUMMARY.md.
@@ -1312,7 +1313,7 @@ If "adjust": Return to scoping.
1312
1313
  **Commit requirements:**
1313
1314
 
1314
1315
  ```bash
1315
- pp_run query commit "docs: define v1 requirements" --files .planning/REQUIREMENTS.md
1316
+ pp_run query commit "docs(planning): define v1 requirements" --files .planning/REQUIREMENTS.md
1316
1317
  ```
1317
1318
 
1318
1319
  ## 7.5. Project Structure Mode
@@ -1496,7 +1497,7 @@ This ensures new projects get the default pp-core workflow-enforcement guidance
1496
1497
  **Commit roadmap (after approval or auto mode):**
1497
1498
 
1498
1499
  ```bash
1499
- pp_run query commit "docs: create roadmap ([N] phases)" --files .planning/ROADMAP.md .planning/STATE.md .planning/REQUIREMENTS.md "$INSTRUCTION_FILE"
1500
+ pp_run query commit "docs(planning): create roadmap ([N] phases)" --files .planning/ROADMAP.md .planning/STATE.md .planning/REQUIREMENTS.md "$INSTRUCTION_FILE"
1500
1501
  ```
1501
1502
 
1502
1503
  ## 9. Done
@@ -110,6 +110,7 @@ Before creating anything, validate:
110
110
 
111
111
  1. **Target path** — must not exist or must be empty:
112
112
  ```bash
113
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
113
114
  if [ -d "$TARGET_PATH" ] && [ "$(ls -A "$TARGET_PATH" 2>/dev/null)" ]; then
114
115
  echo "Error: Target path already exists and is not empty: $TARGET_PATH"
115
116
  echo "Choose a different --name or --path."
@@ -187,7 +187,7 @@ Choice [S]:
187
187
  ```
188
188
  2. Commit the deferral record:
189
189
  ```bash
190
- pp_run query commit "docs: defer incomplete Phase {src} items to backlog"
190
+ pp_run query commit "docs(planning): defer incomplete Phase {src} items to backlog"
191
191
  ```
192
192
  3. Continue routing to `determine_next_action` immediately — no second prompt.
193
193
 
@@ -198,6 +198,7 @@ pp_run query commit "docs: defer incomplete Phase {src} items to backlog"
198
198
  Check for pending spike/sketch work and surface a notice (does not change routing):
199
199
 
200
200
  ```bash
201
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
201
202
  # Check for pending spikes (verdict: PENDING in any README)
202
203
  PENDING_SPIKES=$(grep -rl 'verdict: PENDING' .planning/spikes/*/README.md 2>/dev/null | wc -l | tr -d ' ')
203
204
 
@@ -14,14 +14,15 @@ Read all files referenced by the invoking prompt's execution_context before star
14
14
  Determine what kind of work is being paused and set the handoff destination accordingly:
15
15
 
16
16
  ```bash
17
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
17
18
  # Check for active phase
18
- phase=$(( ls -lt .planning/phases/*/PLAN.md 2>/dev/null || true ) | head -1 | grep -oP 'phases/\K[^/]+' || true)
19
+ phase=$(( ls -lt .planning/phases/*/PLAN.md 2>/dev/null || true ) | head -1 | sed -n 's|.*phases/\([^/]*\)/.*|\1|p')
19
20
 
20
21
  # Check for active spike
21
- spike=$(( ls -lt .planning/spikes/*/SPIKE.md .planning/spikes/*/DESIGN.md .planning/spikes/*/README.md 2>/dev/null || true ) | head -1 | grep -oP 'spikes/\K[^/]+' || true)
22
+ spike=$(( ls -lt .planning/spikes/*/SPIKE.md .planning/spikes/*/DESIGN.md .planning/spikes/*/README.md 2>/dev/null || true ) | head -1 | sed -n 's|.*spikes/\([^/]*\)/.*|\1|p')
22
23
 
23
24
  # Check for active sketch
24
- sketch=$(( ls -lt .planning/sketches/*/README.md .planning/sketches/*/index.html 2>/dev/null || true ) | head -1 | grep -oP 'sketches/\K[^/]+' || true)
25
+ sketch=$(( ls -lt .planning/sketches/*/README.md .planning/sketches/*/index.html 2>/dev/null || true ) | head -1 | sed -n 's|.*sketches/\([^/]*\)/.*|\1|p')
25
26
 
26
27
  # Check for active deliberation
27
28
  deliberation=$(ls .planning/deliberations/*.md 2>/dev/null | head -1 || true)
@@ -57,6 +58,7 @@ Ask user for clarifications if needed via conversational questions.
57
58
 
58
59
  **Also inspect SUMMARY.md files for false completions:**
59
60
  ```bash
61
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
60
62
  # Check for placeholder content in existing summaries
61
63
  grep -l "To be filled\|placeholder\|TBD" .planning/phases/*/*.md 2>/dev/null || true
62
64
  ```
@@ -214,7 +216,7 @@ timestamp=$(pp_run query current-timestamp full --raw)
214
216
 
215
217
  <step name="commit">
216
218
  ```bash
217
- pp_run query commit "wip: [context-name] paused at [X]/[Y]" --files [handoff-path] .planning/HANDOFF.json
219
+ pp_run query commit "docs(planning): pause [context-name] at [X]/[Y]" --files [handoff-path] .planning/HANDOFF.json
218
220
  ```
219
221
  </step>
220
222
 
@@ -11,6 +11,7 @@ Read all files referenced by the invoking prompt's execution_context before star
11
11
  ## 1. Load Audit Results
12
12
 
13
13
  ```bash
14
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
14
15
  # Find the most recent audit file
15
16
  (ls -t .planning/v*-MILESTONE-AUDIT.md 2>/dev/null || true) | head -1
16
17
  ```
@@ -65,6 +66,7 @@ Gap: Flow "View dashboard" broken at data fetch
65
66
  Find highest existing phase:
66
67
  ```bash
67
68
  _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
69
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
68
70
  # Get sorted phase list, extract last one
69
71
  HIGHEST=$(pp_run query phases.list --pick directories[-1])
70
72
  ```
@@ -154,7 +156,7 @@ Repeat for each gap-closure phase number. This produces `{CODE}-{NN}-{slug}/` wh
154
156
  ## 9. Commit Roadmap and Requirements Update
155
157
 
156
158
  ```bash
157
- pp_run query commit "docs(roadmap): add gap closure phases {N}-{M}" --files .planning/ROADMAP.md .planning/REQUIREMENTS.md
159
+ pp_run query commit "docs(planning): add gap closure phases {N}-{M}" --files .planning/ROADMAP.md .planning/REQUIREMENTS.md
158
160
  ```
159
161
 
160
162
  ## 10. Offer Next Steps
@@ -104,7 +104,7 @@ For each plan entry extracted from `PLAN-OUTLINE.md`:
104
104
  5. **Commit per-plan:**
105
105
  ```bash
106
106
  _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
107
- pp_run query commit "docs(${PADDED_PHASE}): plan ${plan_id} (chunked)" --files "${PHASE_DIR}/${plan_id}-PLAN.md"
107
+ pp_run query commit "docs(planning): plan ${plan_id} (chunked)" --phase "${PADDED_PHASE}" --files "${PHASE_DIR}/${plan_id}-PLAN.md"
108
108
  ```
109
109
 
110
110
  After all N plans are written and committed, treat this as `## PLANNING COMPLETE` and continue
@@ -71,6 +71,7 @@ Load all context in one call (paths only to minimize orchestrator context):
71
71
 
72
72
  ```bash
73
73
  _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
74
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
74
75
  GRAN_PARAM=""; if [[ "$ARGUMENTS" =~ (^|[[:space:]])--granularity[[:space:]]+([^[:space:]-][^[:space:]]*) ]]; then GRAN_PARAM="--granularity ${BASH_REMATCH[2]}"; fi
75
76
  INIT=$(pp_run query init.plan-phase "$PHASE" $GRAN_PARAM)
76
77
  if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
@@ -83,7 +84,7 @@ MVP_MODE_CFG=$(pp_run query config-get workflow.mvp_mode 2>/dev/null || echo "fa
83
84
 
84
85
  When the tdd capability's `workflow.tdd_mode` is active (resolved via the plan:pre render-hooks), the planner agent is instructed to apply `type: tdd` to eligible tasks using heuristics from `references/tdd.md`. The TDD guidance is injected via the tdd capability's contribution hook at §5.6; no inline config-get is needed.
85
86
 
86
- When `CONTEXT_WINDOW >= 500000`, the planner prompt includes the 3 most recent prior phase CONTEXT.md and SUMMARY.md files PLUS any phases explicitly listed in the current phase's `Depends on:` field in ROADMAP.md. Explicit dependencies always load regardless of recency (e.g., Phase 7 declaring `Depends on: Phase 2` always sees Phase 2's context). Bounded recency keeps the planner's context budget focused on recent work.
87
+ When `CONTEXT_WINDOW >= 500000`, the planner prompt includes the 3 most recent prior phase CONTEXT.md and SUMMARY.md files PLUS any phases explicitly listed in the current phase's `Depends on:` field in ROADMAP.md. Explicit dependencies always load regardless of recency (e.g., Phase 7 declaring `Depends on: Phase 2` always sees Phase 2's context).
87
88
 
88
89
  Parse JSON for: `researcher_model`, `planner_model`, `checker_model`, `research_enabled`, `plan_checker_enabled`, `nyquist_validation_enabled`, `commit_docs`, `text_mode`, `phase_found`, `phase_dir`, `phase_number`, `phase_name`, `phase_slug`, `padded_phase`, `has_research`, `has_context`, `has_reviews`, `has_plans`, `plan_count`, `phase_status` (#3569), `planning_exists`, `roadmap_exists`, `phase_req_ids`, `response_language`, `granularity`.
89
90
 
@@ -100,6 +101,7 @@ The init JSON includes `phase_status` — one of `Pending | Planned | In Progres
100
101
  Parse `phase_status` from the init JSON, then:
101
102
 
102
103
  ```bash
104
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
103
105
  FORCE_REPLAN=false
104
106
  if [[ "$ARGUMENTS" =~ (^|[[:space:]])--force([[:space:]]|$) ]]; then
105
107
  FORCE_REPLAN=true
@@ -148,6 +150,7 @@ In research-only mode, two modifiers control behavior when `RESEARCH.md` already
148
150
  - **`--view`** — view-only: print existing `RESEARCH.md` to stdout, do **not** spawn the researcher. Sets `VIEW_ONLY=true`. Cheapest mode for the correction-without-replanning loop. If `RESEARCH.md` does not exist, error with a hint to drop `--view`.
149
151
 
150
152
  ```bash
153
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
151
154
  RESEARCH_ONLY=false
152
155
  VIEW_ONLY=false
153
156
  if [[ "$ARGUMENTS" =~ --research-phase[[:space:]]+([0-9]+(\.[0-9]+)?) ]]; then
@@ -246,6 +249,7 @@ PHASE_INFO=$(pp_run query roadmap.get-phase "${PHASE}")
246
249
 
247
250
  Now that `PHASE` is finalized, resolve MVP mode:
248
251
  ```bash
252
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
249
253
  MVP_MODE=$(pp_run query phase.mvp-mode "${PHASE}" $MVP_FLAG_ARG --pick active)
250
254
  ```
251
255
 
@@ -346,7 +350,7 @@ Use full relative paths. Group by topic area.]
346
350
 
347
351
  5. Commit:
348
352
  ```bash
349
- pp_run query commit "docs(${padded_phase}): generate context from PRD" --files "${phase_dir}/${padded_phase}-CONTEXT.md"
353
+ pp_run query commit "docs(planning): generate context from PRD" --phase "${padded_phase}" --files "${phase_dir}/${padded_phase}-CONTEXT.md"
350
354
  ```
351
355
 
352
356
  6. Set `context_content` to the generated CONTEXT.md content and continue to step 5 (Handle Research).
@@ -364,7 +368,7 @@ pp_run query commit "docs(${padded_phase}): generate context from PRD" --files "
364
368
  3. Status gate: reject `superseded`/`rejected`/`deprecated`; warn on `proposed`; missing status defaults to `accepted`.
365
369
  4. Empty-decisions fallback: if all parsed ADRs have zero `decisions[]`, emit `ADR ingest produced no locked decisions; fall back to discuss-phase for this phase.` and exit with `/pp:discuss-phase {N}` guidance.
366
370
  5. Generate CONTEXT.md using `<domain>`, `<decisions>`, `<canonical_refs>`, `<specifics>`, `<deferred>`, `<scope_fence>`, map `consequences_positive[]` to Success Criteria and `consequences_negative[]` to Risk Summary, and include `**Source:** ADR Ingest Express Path ({INGEST_PATH})`.
367
- 6. Commit with `pp-tools.cjs query commit "docs(${padded_phase}): generate context from ADR ingest" --files "${phase_dir}/${padded_phase}-CONTEXT.md"` and set `context_content`; continue to step 5.
371
+ 6. Commit with `pp-tools.cjs query commit "docs(planning): generate context from ADR ingest" --phase "${padded_phase}" --files "${phase_dir}/${padded_phase}-CONTEXT.md"` and set `context_content`; continue to step 5.
368
372
 
369
373
  **Effect:** This bypasses step 4 (Load CONTEXT.md) since CONTEXT.md was synthesized from ADR input.
370
374
 
@@ -415,6 +419,7 @@ If "Run discuss-phase first":
415
419
  AI integration activation is owned by the `ai-integration` capability's `plan:pre` step hook. The plan-phase host only discovers existing artifacts here so the planner can consume them; it must not read the capability's config key directly.
416
420
 
417
421
  ```bash
422
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
418
423
  AI_SPEC_FILE=$(ls "${PHASE_DIR}"/*-AI-SPEC.md 2>/dev/null | head -1)
419
424
  AI_SPEC_PATH="${AI_SPEC_FILE}"
420
425
  FRAMEWORK_LINE=""
@@ -578,6 +583,7 @@ If `research_enabled` is false and `nyquist_validation_enabled` is true: warn "N
578
583
  In that case: **skip validation-strategy creation entirely**. Do **not** expect `RESEARCH.md` or `VALIDATION.md` for this run, and continue to Step 6.
579
584
 
580
585
  ```bash
586
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
581
587
  grep -l "## Validation Architecture" "${PHASE_DIR}"/*-RESEARCH.md 2>/dev/null || true
582
588
  ```
583
589
 
@@ -590,7 +596,7 @@ grep -l "## Validation Architecture" "${PHASE_DIR}"/*-RESEARCH.md 2>/dev/null ||
590
596
  test -f "${PHASE_DIR}/${PADDED_PHASE}-VALIDATION.md" && echo "VALIDATION_CREATED=true" || echo "VALIDATION_CREATED=false"
591
597
  ```
592
598
  5. If `VALIDATION_CREATED=false`: STOP — do not proceed to Step 6
593
- 6. If `commit_docs`: `commit "docs(phase-${PHASE}): add validation strategy"`
599
+ 6. If `commit_docs`: `commit "docs(planning): add validation strategy" --phase "${PADDED_PHASE}"`
594
600
 
595
601
  **If not found:** Warn and continue — plans may fail Dimension 8.
596
602
 
@@ -660,6 +666,7 @@ Read `frontend`, `hasUiSpec`, and `block` from `GATE`.
660
666
  **Branch 3 — UI-SPEC already exists (`hasUiSpec` is `true`):**
661
667
 
662
668
  ```bash
669
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
663
670
  UI_SPEC_FILE=$(ls "${PHASE_DIR}"/*-UI-SPEC.md 2>/dev/null | head -1)
664
671
  UI_SPEC_PATH="${UI_SPEC_FILE}"
665
672
  ```
@@ -685,6 +692,7 @@ Skill(skill="pp-${ref.skill}", args="${PHASE} --auto ${GSD_WS}")
685
692
  After all UI step hooks return, re-read:
686
693
 
687
694
  ```bash
695
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
688
696
  UI_SPEC_FILE=$(ls "${PHASE_DIR}"/*-UI-SPEC.md 2>/dev/null | head -1)
689
697
  UI_SPEC_PATH="${UI_SPEC_FILE}"
690
698
  ```
@@ -729,6 +737,7 @@ In `PLAN_PRE_HOOKS_JSON` (already loaded), find active plan:pre entries where `k
729
737
  ## 6. Check Existing Plans
730
738
 
731
739
  ```bash
740
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
732
741
  ls "${PHASE_DIR}"/*-PLAN.md 2>/dev/null || true
733
742
  ```
734
743
 
@@ -741,6 +750,7 @@ ls "${PHASE_DIR}"/*-PLAN.md 2>/dev/null || true
741
750
  Extract from INIT JSON:
742
751
 
743
752
  ```bash
753
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
744
754
  _gsd_field() { node -e "const o=JSON.parse(process.argv[1]); const v=o[process.argv[2]]; process.stdout.write(v==null?'':String(v))" "$1" "$2"; }
745
755
  STATE_PATH=$(_gsd_field "$INIT" state_path)
746
756
  ROADMAP_PATH=$(_gsd_field "$INIT" roadmap_path)
@@ -777,6 +787,7 @@ Also skip if all of the following are true:
777
787
  In that no-research path, Nyquist artifacts are **not required** for this run.
778
788
 
779
789
  ```bash
790
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
780
791
  VALIDATION_EXISTS=$(ls "${PHASE_DIR}"/*-VALIDATION.md 2>/dev/null | head -1)
781
792
  ```
782
793
 
@@ -1017,6 +1028,7 @@ Read and execute `pp-core/workflows/plan-phase/steps/chunked-planning.md` — th
1017
1028
  **Triggered when:** Agent() returns but the return contains no recognized marker (`## PLANNING COMPLETE`, `## PHASE SPLIT RECOMMENDED`, `## ⚠ Source Audit`, `## CHECKPOINT REACHED`, `## PLANNING INCONCLUSIVE`).
1018
1029
 
1019
1030
  ```bash
1031
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
1020
1032
  DISK_PLANS=$(ls "${PHASE_DIR}"/*-PLAN.md 2>/dev/null | wc -l | tr -d ' ')
1021
1033
  ```
1022
1034
 
@@ -1216,6 +1228,7 @@ If thinking_partner disabled: skip this block entirely.
1216
1228
  **Triggered when:** Checker Agent() returns but the return contains neither `## VERIFICATION PASSED` nor `## ISSUES FOUND`.
1217
1229
 
1218
1230
  ```bash
1231
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
1219
1232
  DISK_PLANS=$(ls "${PHASE_DIR}"/*-PLAN.md 2>/dev/null | wc -l | tr -d ' ')
1220
1233
  ```
1221
1234
 
@@ -1370,7 +1383,7 @@ After the script returns, check that the bounced file still has valid YAML front
1370
1383
 
1371
1384
  6. **Commit surviving bounced plans:** If at least one plan survived both the frontmatter validation and the checker re-run, commit the changes:
1372
1385
  ```bash
1373
- pp_run query commit "refactor(${padded_phase}): bounce plans through external refinement" --files "${PHASE_DIR}/*-PLAN.md"
1386
+ pp_run query commit "docs(planning): bounce plans through external refinement" --phase "${padded_phase}" --files "${PHASE_DIR}/*-PLAN.md"
1374
1387
  ```
1375
1388
 
1376
1389
  Display summary:
@@ -1388,6 +1401,7 @@ After plans pass the checker (or checker is skipped), verify that all phase requ
1388
1401
 
1389
1402
  **Step 1: Extract requirement IDs claimed by plans**
1390
1403
  ```bash
1404
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
1391
1405
  # Collect all requirement IDs from plan frontmatter
1392
1406
  PLAN_REQS=$(grep -h "^requirements_addressed\|^requirements:" ${PHASE_DIR}/*-PLAN.md 2>/dev/null | tr -d '[]' | tr ',' '\n' | sed 's/^[[:space:]]*//' | sort -u)
1393
1407
  ```
@@ -1526,7 +1540,8 @@ This operation is idempotent: if wave headers or cross-cutting constraints alrea
1526
1540
  If `commit_docs` is true (from the init JSON parsed in step 1), commit the generated plan artifacts (including any ROADMAP.md annotations from step 13c):
1527
1541
 
1528
1542
  ```bash
1529
- pp_run query commit "docs(${PADDED_PHASE}): create phase plan" --files "${PHASE_DIR}"/*-PLAN.md .planning/STATE.md .planning/ROADMAP.md
1543
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
1544
+ pp_run query commit "docs(planning): create phase plan" --phase "${PADDED_PHASE}" --files "${PHASE_DIR}"/*-PLAN.md .planning/STATE.md .planning/ROADMAP.md
1530
1545
  ```
1531
1546
 
1532
1547
  This commits all PLAN.md files for the phase plus the updated STATE.md and ROADMAP.md to version-control the planning artifacts. Skip this step if `commit_docs` is false.
@@ -109,6 +109,7 @@ Run plan-phase **inline** (do NOT wrap it in Agent()). The convergence orchestra
109
109
 
110
110
  After plan-phase completes, verify plans were created:
111
111
  ```bash
112
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
112
113
  PLAN_COUNT=$(ls ${phase_dir}/${padded_phase}-*-PLAN.md 2>/dev/null | wc -l)
113
114
  ```
114
115
 
@@ -207,6 +208,7 @@ Run this pass unless `plan_review.source_grounding` is `false`. It verifies ever
207
208
 
208
209
  After agent returns, verify REVIEWS.md exists:
209
210
  ```bash
211
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
210
212
  REVIEWS_FILE=$(ls ${phase_dir}/${padded_phase}-REVIEWS.md 2>/dev/null)
211
213
  ```
212
214
 
@@ -22,6 +22,7 @@ Parse `$ARGUMENTS` for the idea summary.
22
22
  First, check for an enrich flag:
23
23
 
24
24
  ```bash
25
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
25
26
  if echo "$ARGUMENTS" | grep -qE '\-\-enrich[[:space:]]+SEED-[0-9]+'; then
26
27
  ENRICH_TARGET=$(echo "$ARGUMENTS" | grep -oE 'SEED-[0-9]+')
27
28
  SEED_FILE=$(ls .planning/seeds/${ENRICH_TARGET}-*.md 2>/dev/null | head -1)
@@ -52,6 +53,7 @@ mkdir -p .planning/seeds
52
53
 
53
54
  <step name="generate-seed-id">
54
55
  ```bash
56
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
55
57
  # Find next seed number
56
58
  EXISTING=$( (ls .planning/seeds/SEED-*.md 2>/dev/null || true) | wc -l )
57
59
  NEXT=$((EXISTING + 1))
@@ -136,7 +138,7 @@ Store relevant file paths as `$BREADCRUMBS`.
136
138
  <step name="commit-seed">
137
139
  ```bash
138
140
  _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
139
- pp_run query commit "docs: plant seed — {$IDEA}" --files .planning/seeds/SEED-{PADDED}-{slug}.md
141
+ pp_run query commit "docs(planning): plant seed — {$IDEA}" --files .planning/seeds/SEED-{PADDED}-{slug}.md
140
142
  ```
141
143
  </step>
142
144
 
@@ -207,7 +209,7 @@ Update the seed file's frontmatter and sections with the gathered values:
207
209
 
208
210
  Commit the update:
209
211
  ```bash
210
- pp_run query commit "docs: enrich seed ${SEED_ID} — trigger + why + scope" --files "$SEED_FILE"
212
+ pp_run query commit "docs(planning): enrich seed ${SEED_ID} — trigger + why + scope" --files "$SEED_FILE"
211
213
  ```
212
214
 
213
215
  Confirm:
@@ -74,6 +74,7 @@ git log --oneline "$TARGET".."$CURRENT_BRANCH" --no-merges
74
74
  For each commit, check what it touches:
75
75
 
76
76
  ```bash
77
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
77
78
  # For each commit hash
78
79
  FILES=$(git diff-tree --no-commit-id --name-only -r $HASH)
79
80
  NON_PLANNING=$(echo "$FILES" | grep -v "^\.planning/" | wc -l)
@@ -107,6 +108,7 @@ git checkout -b "$PR_BRANCH" "$TARGET"
107
108
  Cherry-pick code commits and structural planning commits (in order):
108
109
 
109
110
  ```bash
111
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
110
112
  for HASH in $CODE_AND_STRUCTURAL_COMMITS; do
111
113
  git cherry-pick "$HASH" --no-commit
112
114
  # Remove only transient .planning/ subdirectories that came along in mixed commits.
@@ -227,6 +227,7 @@ Then exit the route step. Do NOT run Steps 1 through Routes A-F.
227
227
  List files in the current phase directory:
228
228
 
229
229
  ```bash
230
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
230
231
  (ls -1 .planning/phases/[current-phase-dir]/*-PLAN.md 2>/dev/null || true) | wc -l
231
232
  (ls -1 .planning/phases/[current-phase-dir]/*-SUMMARY.md 2>/dev/null || true) | wc -l
232
233
  (ls -1 .planning/phases/[current-phase-dir]/*-UAT.md 2>/dev/null || true) | wc -l
@@ -239,6 +240,7 @@ State: "This phase has {X} plans, {Y} summaries."
239
240
  Check for UAT.md files with status "diagnosed" (has gaps needing fixes).
240
241
 
241
242
  ```bash
243
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
242
244
  # Check for diagnosed UAT with gaps or partial (incomplete) testing
243
245
  grep -l "status: diagnosed\|status: partial" .planning/phases/[current-phase-dir]/*-UAT.md 2>/dev/null || true
244
246
  ```
@@ -660,6 +662,7 @@ Read STATE.md `status` / `stopped_at` fields (from the STATE snapshot already lo
660
662
 
661
663
  Check for existence of:
662
664
  ```bash
665
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
663
666
  ls .planning/HANDOFF.json .planning/phases/*/.continue-here.md .planning/phases/*/*HANDOFF*.md 2>/dev/null || true
664
667
  ```
665
668
  Also check `.planning/continue-here.md`.
@@ -685,6 +688,7 @@ Emit:
685
688
 
686
689
  Check if `.planning/MEMORY.md` or `.planning/memory/` exists:
687
690
  ```bash
691
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
688
692
  ls .planning/MEMORY.md .planning/memory/*.md 2>/dev/null || true
689
693
  ```
690
694
 
@@ -698,6 +702,7 @@ Emit:
698
702
 
699
703
  Check for pending todos:
700
704
  ```bash
705
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
701
706
  ls .planning/todos/pending/*.md 2>/dev/null || true
702
707
  ```
703
708
 
@@ -208,6 +208,7 @@ workflow byte-identically to how it ran before this gate existed (GATE-04).
208
208
  **Otherwise, fetch and load-gate at `plan:pre`:**
209
209
 
210
210
  ```bash
211
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
211
212
  QUICK_PLAN_PRE_HOOKS_JSON=$(pp_run loop render-hooks plan:pre --raw | node -e "const d=require('fs').readFileSync(0,'utf-8');try{const j=JSON.parse(d);j.activeHooks=(j.activeHooks||[]).filter((x)=>x&&x.capId==='vault');process.stdout.write(JSON.stringify(j));}catch{process.stdout.write('');}")
212
213
  printf '%s' "$QUICK_PLAN_PRE_HOOKS_JSON" | node -e "let h=[];try{h=JSON.parse(require('fs').readFileSync(0,'utf-8')).activeHooks||[]}catch{}console.log('QUICK_PLAN_PRE_HOOKS_JSON='+JSON.stringify({activeHooks:h}))"
213
214
  ```
@@ -513,6 +514,7 @@ Step 2.4 printed `VAULT_ADMIT=on`. The fence prints the fragments; put that prin
513
514
  the prompt says `${QUICK_PLANNER_HOOK_FRAGMENTS}` (nothing when it printed nothing).
514
515
 
515
516
  ```bash
517
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
516
518
  QUICK_PLANNER_HOOK_FRAGMENTS=$(pp_run loop render-hooks plan:pre --raw | node -e "const d=require('fs').readFileSync(0,'utf-8');try{const j=JSON.parse(d);j.activeHooks=(j.activeHooks||[]).filter((x)=>x&&x.capId==='vault');process.stdout.write(JSON.stringify(j));}catch{process.stdout.write('');}" | node -e "const d=require('fs').readFileSync(0,'utf-8');try{const h=(JSON.parse(d).activeHooks||[]).filter((x)=>x&&x.kind==='contribution'&&x.into==='planner'&&x.fragment&&typeof x.fragment.inline==='string');process.stdout.write(h.map((x)=>x.fragment.inline).join('\n\n'));}catch{process.stdout.write('');}")
517
519
  if [ -n "$QUICK_PLANNER_HOOK_FRAGMENTS" ]; then printf '%s\n' "$QUICK_PLANNER_HOOK_FRAGMENTS"; fi
518
520
  ```
@@ -696,6 +698,7 @@ Skip silently unless Step 2.4 printed `VAULT_ADMIT=on`. Runs after the planner (
696
698
  committed and no executor spawned (D-02, D-34).
697
699
 
698
700
  ```bash
701
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
699
702
  QUICK_PLAN_POST_HOOKS_JSON=$(pp_run loop render-hooks plan:post --raw | node -e "const d=require('fs').readFileSync(0,'utf-8');try{const j=JSON.parse(d);j.activeHooks=(j.activeHooks||[]).filter((x)=>x&&x.capId==='vault');process.stdout.write(JSON.stringify(j));}catch{process.stdout.write('');}")
700
703
  printf '%s' "$QUICK_PLAN_POST_HOOKS_JSON" | node -e "let h=[];try{h=JSON.parse(require('fs').readFileSync(0,'utf-8')).activeHooks||[]}catch{}console.log('QUICK_PLAN_POST_HOOKS_JSON='+JSON.stringify({activeHooks:h}))"
701
704
  ```
@@ -731,10 +734,10 @@ if [ "${USE_WORKTREES}" != "false" ]; then
731
734
  # workflow.worktree_skip_hooks=true, honor that opt-in only.
732
735
  SKIP_HOOKS=$(pp_run query config-get workflow.worktree_skip_hooks 2>/dev/null || echo "false")
733
736
  if [ "$SKIP_HOOKS" = "true" ]; then
734
- git commit --no-verify -m "docs(${quick_id}): pre-dispatch plan for ${DESCRIPTION}" -- "${QUICK_DIR}/${quick_id}-PLAN.md" \
737
+ git commit --no-verify -m "docs(planning): pre-dispatch plan for ${DESCRIPTION}" -m "Quick: ${quick_id}" -- "${QUICK_DIR}/${quick_id}-PLAN.md" \
735
738
  || { echo "ERROR: pre-dispatch PLAN.md commit failed (--no-verify path). Aborting before executor dispatch." >&2; exit 1; }
736
739
  else
737
- git commit -m "docs(${quick_id}): pre-dispatch plan for ${DESCRIPTION}" -- "${QUICK_DIR}/${quick_id}-PLAN.md" \
740
+ git commit -m "docs(planning): pre-dispatch plan for ${DESCRIPTION}" -m "Quick: ${quick_id}" -- "${QUICK_DIR}/${quick_id}-PLAN.md" \
738
741
  || { echo "ERROR: pre-dispatch PLAN.md commit failed — likely a pre-commit hook failure. Fix the hook output above (or set workflow.worktree_skip_hooks=true to bypass) and re-run." >&2; exit 1; }
739
742
  fi
740
743
  QUICK_PLAN_COMMIT=$(git rev-parse HEAD)
@@ -771,6 +774,7 @@ Step 2.4 printed `VAULT_ADMIT=on`. The fence prints the fragments; put that prin
771
774
  prompt says `${QUICK_EXECUTOR_HOOK_FRAGMENTS}` (nothing when it printed nothing).
772
775
 
773
776
  ```bash
777
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
774
778
  QUICK_EXECUTOR_HOOK_FRAGMENTS=$(pp_run loop render-hooks execute:pre --raw | node -e "const d=require('fs').readFileSync(0,'utf-8');try{const j=JSON.parse(d);j.activeHooks=(j.activeHooks||[]).filter((x)=>x&&x.capId==='vault');process.stdout.write(JSON.stringify(j));}catch{process.stdout.write('');}" | node -e "const d=require('fs').readFileSync(0,'utf-8');try{const h=(JSON.parse(d).activeHooks||[]).filter((x)=>x&&x.kind==='contribution'&&x.into==='executor'&&x.fragment&&typeof x.fragment.inline==='string');process.stdout.write(h.map((x)=>x.fragment.inline).join('\n\n'));}catch{process.stdout.write('');}")
775
779
  if [ -n "$QUICK_EXECUTOR_HOOK_FRAGMENTS" ]; then printf '%s\n' "$QUICK_EXECUTOR_HOOK_FRAGMENTS"; fi
776
780
  ```
@@ -851,7 +855,7 @@ SUMMARY.md and stop — the user must rerun with worktrees disabled.
851
855
 
852
856
  <constraints>
853
857
  - Execute all tasks in the plan
854
- - Commit each task atomically (code changes only)
858
+ - Commit each task atomically (code changes only); the scope names the part of the codebase (e.g. `fix(auth)`), and each message ends with the trailer `Quick: ${quick_id}` (after a blank line) in place of the `Phase:` trailer
855
859
  - Run the <submodule_commit_guard> bash block before every \`git commit\` if SUBMODULE_PATHS is non-empty
856
860
  - Create summary at: ${QUICK_DIR}/${quick_id}-SUMMARY.md with `status: complete` in SUMMARY frontmatter (required so the audit-open milestone-close scanner recognises the task as done, not [unknown])
857
861
  - Do NOT commit docs artifacts (SUMMARY.md, STATE.md, PLAN.md) — the orchestrator handles the docs commit in Step 8
@@ -872,6 +876,7 @@ If the executor ran with `isolation="worktree"`, append its returned `{agent_id,
872
876
  After executor returns:
873
877
  1. **Worktree cleanup:** If the executor ran with `isolation="worktree"`, merge the worktree branch back and clean up:
874
878
  ```bash
879
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
875
880
  QUICK_WORKTREE_MANIFEST=${QUICK_WORKTREE_MANIFEST:-$WAVE_WORKTREE_MANIFEST}
876
881
  [ -n "${QUICK_WORKTREE_MANIFEST:-}" ] && [ -f "$QUICK_WORKTREE_MANIFEST" ] || {
877
882
  echo "BLOCKED: missing QUICK_WORKTREE_MANIFEST; refusing broad worktree cleanup (#3384)." >&2
@@ -908,6 +913,7 @@ so a blocked task never gets a STATE.md row and never reaches the final commit (
908
913
  the executor already made stay in history, and the SEAL-01 check names them (D-02).
909
914
 
910
915
  ```bash
916
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
911
917
  QUICK_EXECUTE_POST_HOOKS_JSON=$(pp_run loop render-hooks execute:post --raw | node -e "const d=require('fs').readFileSync(0,'utf-8');try{const j=JSON.parse(d);j.activeHooks=(j.activeHooks||[]).filter((x)=>x&&x.capId==='vault');process.stdout.write(JSON.stringify(j));}catch{process.stdout.write('');}")
912
918
  printf '%s' "$QUICK_EXECUTE_POST_HOOKS_JSON" | node -e "let h=[];try{h=JSON.parse(require('fs').readFileSync(0,'utf-8')).activeHooks||[]}catch{}console.log('QUICK_EXECUTE_POST_HOOKS_JSON='+JSON.stringify({activeHooks:h}))"
913
919
  ```
@@ -1093,6 +1099,7 @@ Build file list:
1093
1099
  - If `${QUICK_DIR}/${quick_id}-deferred-items.md` exists: `${QUICK_DIR}/${quick_id}-deferred-items.md`
1094
1100
 
1095
1101
  ```bash
1102
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
1096
1103
  # Explicitly stage all artifacts before commit — PLAN.md may be untracked
1097
1104
  # if the executor ran without worktree isolation and committed docs early
1098
1105
  # Filter .planning/ files from staging if commit_docs is disabled (#1783)
@@ -1103,7 +1110,7 @@ if [ "$COMMIT_DOCS" = "false" ]; then
1103
1110
  else
1104
1111
  git add ${file_list} 2>/dev/null
1105
1112
  fi
1106
- pp_run query commit "docs(quick-${quick_id}): ${DESCRIPTION}" --files ${file_list}
1113
+ pp_run query commit "docs(planning): record quick task — ${DESCRIPTION}" --quick "${quick_id}" --files ${file_list}
1107
1114
  ```
1108
1115
 
1109
1116
  Get final commit hash:
@@ -13,6 +13,7 @@ After a pp-core update wipes and reinstalls files, this workflow merges user's p
13
13
  Check for local patches directory:
14
14
 
15
15
  ```bash
16
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
16
17
  expand_home() {
17
18
  case "$1" in
18
19
  "~/"*) printf '%s/%s\n' "$HOME" "${1#~/}" ;;
@@ -278,6 +279,7 @@ Run the deterministic verifier script. Do NOT rely solely on the free-text `veri
278
279
  Run the verifier as a child process (the pp-tools binary directory is not required — the script ships under 'pp-core/bin/' in the source repo and is installed to '/pp-core/bin/'; it is also exposed via the SDK at `sdk/dist/cli.js verify-reapply` when present):
279
280
 
280
281
  ```bash
282
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
281
283
  PRISTINE_DIR="${CONFIG_DIR}/pp-pristine"
282
284
 
283
285
  # Build args as a bash array so paths with spaces survive expansion intact
@@ -302,6 +304,7 @@ VERIFY_STATUS=$?
302
304
  **Step 5a: drift check** — even when `VERIFY_STATUS` is 0, the report may signal that one or more files were skipped due to pristine-snapshot drift (Bug #3657) or a missing baseline (Bug #934). Parse the JSON and check:
303
305
 
304
306
  ```bash
307
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
305
308
  DRIFTED_COUNT="$(echo "$VERIFY_OUTPUT" | node -e "const d=JSON.parse(require('fs').readFileSync('/dev/stdin','utf8'));process.stdout.write(String(d.drifted||0))")"
306
309
  DRIFTED_FILES="$(echo "$VERIFY_OUTPUT" | node -e "const d=JSON.parse(require('fs').readFileSync('/dev/stdin','utf8'));(d.drifted_files||[]).forEach(f=>process.stdout.write(f+'\n'))")"
307
310
  NO_BASELINE_COUNT="$(echo "$VERIFY_OUTPUT" | node -e "const d=JSON.parse(require('fs').readFileSync('/dev/stdin','utf8'));process.stdout.write(String(d.no_baseline||0))")"
@@ -104,7 +104,7 @@ Extract from result: `removed`, `directory_deleted`, `renamed_directories`, `ren
104
104
  Stage and commit the removal:
105
105
 
106
106
  ```bash
107
- pp_run query commit "chore: remove phase {target} ({original-phase-name})" --files .planning/
107
+ pp_run query commit "chore(planning): remove phase {target} ({original-phase-name})" --files .planning/
108
108
  ```
109
109
 
110
110
  The commit message preserves the historical record of what was removed.