@pareto4/pp-core 1.18.0 → 1.20.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 (194) 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 +13 -1
  9. package/agents/pp-plan-checker.md +3 -0
  10. package/agents/pp-planner.md +20 -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-vault-reviewer.md +2 -0
  15. package/agents/pp-verifier.md +22 -10
  16. package/commands/pp-add-tests.md +1 -1
  17. package/commands/pp-debug.md +1 -0
  18. package/commands/pp-discovery.md +3 -2
  19. package/commands/pp-init.md +4 -3
  20. package/commands/pp-quick.md +3 -0
  21. package/commands/pp-review-backlog.md +2 -1
  22. package/gemini-extension.json +1 -1
  23. package/package.json +6 -3
  24. package/pareto-skills/_shared/pp-claude-md-protocol.md +1 -1
  25. package/pareto-skills/pp-project-setup/SKILL.md +18 -343
  26. package/pp-core/bin/lib/capability-registry.cjs +3 -3
  27. package/pp-core/bin/lib/check-command-router.cjs +60 -20
  28. package/pp-core/bin/lib/commands.cjs +79 -4
  29. package/pp-core/bin/lib/compose-bindings.cjs +97 -14
  30. package/pp-core/bin/lib/discovery-access.cjs +276 -0
  31. package/pp-core/bin/lib/discovery-charter.cjs +664 -0
  32. package/pp-core/bin/lib/discovery-deviations.cjs +264 -0
  33. package/pp-core/bin/lib/discovery-entities.cjs +323 -0
  34. package/pp-core/bin/lib/discovery-for-phase.cjs +628 -0
  35. package/pp-core/bin/lib/discovery-integrations.cjs +286 -0
  36. package/pp-core/bin/lib/discovery-migration.cjs +246 -0
  37. package/pp-core/bin/lib/discovery-phases.cjs +233 -0
  38. package/pp-core/bin/lib/discovery-processes.cjs +355 -0
  39. package/pp-core/bin/lib/discovery-research-track.cjs +5 -4
  40. package/pp-core/bin/lib/discovery-rollup.cjs +12 -8
  41. package/pp-core/bin/lib/discovery-rules.cjs +216 -0
  42. package/pp-core/bin/lib/discovery-screens.cjs +21 -3
  43. package/pp-core/bin/lib/discovery-session-check.cjs +264 -0
  44. package/pp-core/bin/lib/discovery-stories.cjs +273 -0
  45. package/pp-core/bin/lib/discovery-sweep.cjs +13 -4
  46. package/pp-core/bin/lib/discovery-table.cjs +55 -0
  47. package/pp-core/bin/lib/discovery-vault-check.cjs +37 -3
  48. package/pp-core/bin/lib/init-contract.cjs +48 -7
  49. package/pp-core/bin/lib/io.cjs +22 -0
  50. package/pp-core/bin/lib/vault-coordinates.cjs +1 -1
  51. package/pp-core/bin/lib/vault-index.cjs +18 -5
  52. package/pp-core/bin/lib/vault-standards-review.cjs +50 -2
  53. package/pp-core/bin/lib/vault-update.cjs +4 -0
  54. package/pp-core/bin/lib/vault.cjs +2 -2
  55. package/pp-core/bin/pp-tools.cjs +153 -5
  56. package/pp-core/org-profile.json +1 -1
  57. package/pp-core/references/autonomous-best-effort.md +3 -2
  58. package/pp-core/references/autonomous-lifecycle.md +1 -0
  59. package/pp-core/references/autonomous-smart-discuss.md +5 -1
  60. package/pp-core/references/discovery-access.md +112 -0
  61. package/pp-core/references/discovery-build-consumption.md +256 -0
  62. package/pp-core/references/discovery-charter.md +127 -0
  63. package/pp-core/references/discovery-data-model.md +145 -0
  64. package/pp-core/references/discovery-id-conventions.md +77 -8
  65. package/pp-core/references/discovery-integrations.md +151 -0
  66. package/pp-core/references/discovery-processes.md +190 -0
  67. package/pp-core/references/discovery-rebaseline.md +2 -2
  68. package/pp-core/references/discovery-research-track.md +5 -6
  69. package/pp-core/references/discovery-session-output.md +70 -0
  70. package/pp-core/references/discovery-standards.md +107 -0
  71. package/pp-core/references/discovery-traceability.md +2 -2
  72. package/pp-core/references/execute-mvp-tdd.md +3 -3
  73. package/pp-core/references/git-integration.md +57 -33
  74. package/pp-core/references/git-planning-commit.md +31 -9
  75. package/pp-core/references/phase-argument-parsing.md +1 -0
  76. package/pp-core/references/planner-discovery-extract.md +35 -0
  77. package/pp-core/references/planner-gap-closure.md +1 -0
  78. package/pp-core/references/planner-revision.md +3 -1
  79. package/pp-core/references/planner-tdd.md +4 -4
  80. package/pp-core/references/planning-config.md +3 -3
  81. package/pp-core/references/shell-portability.md +28 -0
  82. package/pp-core/references/tdd.md +20 -16
  83. package/pp-core/references/verifier-discovery-conformance.md +36 -0
  84. package/pp-core/references/worktree-path-safety.md +1 -0
  85. package/pp-core/templates/milestone.md +5 -5
  86. package/pp-core/templates/project-charter.md +161 -100
  87. package/pp-core/templates/project.md +3 -3
  88. package/pp-core/templates/requirements.md +18 -0
  89. package/pp-core/templates/verification-report.md +16 -0
  90. package/pp-core/workflows/add-backlog.md +1 -1
  91. package/pp-core/workflows/add-tests.md +5 -2
  92. package/pp-core/workflows/add-todo.md +3 -1
  93. package/pp-core/workflows/ai-integration-phase.md +2 -1
  94. package/pp-core/workflows/audit-fix.md +4 -3
  95. package/pp-core/workflows/audit-milestone.md +1 -0
  96. package/pp-core/workflows/autonomous.md +6 -0
  97. package/pp-core/workflows/check-todos.md +2 -1
  98. package/pp-core/workflows/cleanup.md +3 -1
  99. package/pp-core/workflows/code-review-fix.md +12 -5
  100. package/pp-core/workflows/code-review.md +15 -1
  101. package/pp-core/workflows/complete-milestone.md +13 -3
  102. package/pp-core/workflows/debug.md +2 -0
  103. package/pp-core/workflows/diagnose-issues.md +1 -1
  104. package/pp-core/workflows/discovery-sprint/charter.md +114 -0
  105. package/pp-core/workflows/discovery-sprint/prefill.md +1 -1
  106. package/pp-core/workflows/discovery-sprint/prototype.md +4 -4
  107. package/pp-core/workflows/discovery-sprint/session-13-gates.md +11 -1
  108. package/pp-core/workflows/discovery-sprint/sessions/01-kick-off.md +54 -7
  109. package/pp-core/workflows/discovery-sprint/sessions/02-as-is.md +31 -7
  110. package/pp-core/workflows/discovery-sprint/sessions/03-to-be.md +64 -37
  111. package/pp-core/workflows/discovery-sprint/sessions/04-ux-design.md +12 -3
  112. package/pp-core/workflows/discovery-sprint/sessions/05-architecture.md +45 -22
  113. package/pp-core/workflows/discovery-sprint/sessions/06-security.md +30 -15
  114. package/pp-core/workflows/discovery-sprint/sessions/07-identity.md +43 -25
  115. package/pp-core/workflows/discovery-sprint/sessions/08-integration.md +63 -24
  116. package/pp-core/workflows/discovery-sprint/sessions/09-qa.md +28 -13
  117. package/pp-core/workflows/discovery-sprint/sessions/10-infrastructure.md +35 -16
  118. package/pp-core/workflows/discovery-sprint/sessions/11-roadmap.md +32 -8
  119. package/pp-core/workflows/discovery-sprint/sessions/12-delivery-model.md +21 -18
  120. package/pp-core/workflows/discovery-sprint/sessions/13-wrap-up.md +29 -12
  121. package/pp-core/workflows/discovery-sprint/vault-context.md +14 -3
  122. package/pp-core/workflows/discovery-sprint.md +23 -23
  123. package/pp-core/workflows/discovery-to-build/steps/architecture-deliverables.md +81 -29
  124. package/pp-core/workflows/discovery-to-build/steps/{screen-inventory-gate.md → handoff-gates.md} +111 -3
  125. package/pp-core/workflows/discovery-to-build/templates/discovery-references.md +12 -9
  126. package/pp-core/workflows/discovery-to-build/templates/pp-handoff.md +27 -26
  127. package/pp-core/workflows/discovery-to-build.md +70 -34
  128. package/pp-core/workflows/discuss-phase/discovery.md +83 -0
  129. package/pp-core/workflows/discuss-phase/templates/context.md +4 -0
  130. package/pp-core/workflows/discuss-phase-assumptions.md +5 -3
  131. package/pp-core/workflows/discuss-phase.md +18 -10
  132. package/pp-core/workflows/docs-update.md +1 -0
  133. package/pp-core/workflows/eval-review.md +2 -1
  134. package/pp-core/workflows/execute-phase/steps/check-query-gate.md +7 -6
  135. package/pp-core/workflows/execute-phase/steps/cross-ai-delegation.md +1 -0
  136. package/pp-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +1 -0
  137. package/pp-core/workflows/execute-phase/steps/vault-fetch.md +12 -0
  138. package/pp-core/workflows/execute-phase.md +19 -7
  139. package/pp-core/workflows/execute-plan.md +18 -7
  140. package/pp-core/workflows/explore.md +1 -1
  141. package/pp-core/workflows/forensics.md +4 -2
  142. package/pp-core/workflows/health.md +1 -0
  143. package/pp-core/workflows/import.md +2 -1
  144. package/pp-core/workflows/ingest-docs.md +1 -0
  145. package/pp-core/workflows/init/steps/client-context-capture.md +1 -0
  146. package/pp-core/workflows/init/steps/github-provisioning.md +145 -0
  147. package/pp-core/workflows/init/steps/gitlab-provisioning.md +18 -4
  148. package/pp-core/workflows/init/steps/reachability-outcome.md +3 -1
  149. package/pp-core/workflows/init.md +56 -66
  150. package/pp-core/workflows/map-codebase.md +5 -1
  151. package/pp-core/workflows/milestone-summary.md +2 -1
  152. package/pp-core/workflows/mvp-phase.md +1 -0
  153. package/pp-core/workflows/new-milestone.md +9 -5
  154. package/pp-core/workflows/new-project.md +12 -11
  155. package/pp-core/workflows/new-workspace.md +1 -0
  156. package/pp-core/workflows/next.md +2 -1
  157. package/pp-core/workflows/pause-work.md +6 -4
  158. package/pp-core/workflows/plan-milestone-gaps.md +3 -1
  159. package/pp-core/workflows/plan-phase/steps/chunked-planning.md +1 -1
  160. package/pp-core/workflows/plan-phase/steps/discovery-extract.md +41 -0
  161. package/pp-core/workflows/plan-phase.md +36 -16
  162. package/pp-core/workflows/plan-review-convergence.md +2 -0
  163. package/pp-core/workflows/plant-seed.md +4 -2
  164. package/pp-core/workflows/pr-branch.md +2 -0
  165. package/pp-core/workflows/progress.md +5 -0
  166. package/pp-core/workflows/quick.md +11 -4
  167. package/pp-core/workflows/reapply-patches.md +3 -0
  168. package/pp-core/workflows/remove-phase.md +1 -1
  169. package/pp-core/workflows/resume-project.md +3 -0
  170. package/pp-core/workflows/review.md +7 -1
  171. package/pp-core/workflows/secure-phase.md +2 -1
  172. package/pp-core/workflows/session-report.md +1 -0
  173. package/pp-core/workflows/ship.md +8 -1
  174. package/pp-core/workflows/sketch-wrap-up.md +1 -1
  175. package/pp-core/workflows/sketch.md +3 -2
  176. package/pp-core/workflows/spec-phase.md +2 -1
  177. package/pp-core/workflows/spike-wrap-up.md +1 -1
  178. package/pp-core/workflows/spike.md +4 -3
  179. package/pp-core/workflows/sync-skills.md +5 -2
  180. package/pp-core/workflows/thread.md +3 -2
  181. package/pp-core/workflows/transition.md +6 -0
  182. package/pp-core/workflows/ui-phase.md +3 -1
  183. package/pp-core/workflows/ui-review.md +2 -1
  184. package/pp-core/workflows/ultraplan-phase.md +1 -0
  185. package/pp-core/workflows/undo.md +14 -10
  186. package/pp-core/workflows/update.md +5 -0
  187. package/pp-core/workflows/validate-phase.md +6 -3
  188. package/pp-core/workflows/vault-review.md +7 -1
  189. package/pp-core/workflows/vault-write-back.md +5 -0
  190. package/pp-core/workflows/verify-phase.md +5 -0
  191. package/pp-core/workflows/verify-work.md +8 -1
  192. package/scripts/prompt-injection-scan.sh +1 -1
  193. package/scripts/sync-runtime-launcher.cjs +115 -5
  194. package/pp-core/workflows/discovery-sprint/templates/context-template.md +0 -266
@@ -181,6 +181,7 @@ Write to a temp file: `/tmp/pp-review-prompt-{phase}.md`
181
181
  Also write individual section files so the budget tool can re-trim per reviewer:
182
182
 
183
183
  ```bash
184
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
184
185
  # Write individual section files for per-reviewer budget trimming
185
186
  # These are always written so reviewers with a budget can invoke prompt-budget
186
187
  cp "$INSTRUCTIONS_BLOCK_FILE" "/tmp/pp-review-${PHASE}-instructions.md"
@@ -257,6 +258,7 @@ fi
257
258
 
258
259
  **Codex:**
259
260
  ```bash
261
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
260
262
  # $CODEX_BYPASS_FLAG is capability-gated above (#1115). Capture stderr to a .err
261
263
  # file (not /dev/null) so a non-zero exit — e.g. a flag the installed codex-cli
262
264
  # does not support — is diagnosable instead of a silent empty review.
@@ -353,6 +355,7 @@ Invocation specifics (verified agy 1.0.0, macOS arm64 and Linux amd64):
353
355
  - No `-m` / `--model` flag — agy selects the model internally
354
356
 
355
357
  ```bash
358
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
356
359
  # Pre-flight: snapshot the transcript watermark before invoking agy.
357
360
  # Must run BEFORE agy -p — this is what prevents the fallback from reading a stale prior response.
358
361
  _AGY_WS=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
@@ -426,6 +429,7 @@ fi
426
429
  Read host and model from config. All three local backends share the same `/v1/chat/completions` endpoint — only host and model differ. Use `jq --rawfile` to safely encode the multi-line prompt as JSON without shell-escaping issues.
427
430
 
428
431
  ```bash
432
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
429
433
  # Shared helper: apply prompt-budget trimming for local reviewers
430
434
  prepare_trimmed_prompt_for_reviewer() {
431
435
  REVIEWER_KEY="$1"
@@ -508,6 +512,7 @@ fi
508
512
 
509
513
  **LM Studio (local, OpenAI-compatible):**
510
514
  ```bash
515
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
511
516
  # Resolve prompt budget for LM Studio: per-reviewer override > global default > null
512
517
  LM_STUDIO_REVIEWER_BUDGET=$(pp_run query config-get review.max_prompt_tokens_per_reviewer.lm_studio 2>/dev/null | jq -r '.' 2>/dev/null || echo "null")
513
518
  if [ -z "$LM_STUDIO_REVIEWER_BUDGET" ] || [ "$LM_STUDIO_REVIEWER_BUDGET" = "null" ]; then
@@ -561,6 +566,7 @@ fi
561
566
 
562
567
  **llama.cpp (local, OpenAI-compatible):**
563
568
  ```bash
569
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
564
570
  # Resolve prompt budget for llama.cpp: per-reviewer override > global default > null
565
571
  LLAMA_CPP_REVIEWER_BUDGET=$(pp_run query config-get review.max_prompt_tokens_per_reviewer.llama_cpp 2>/dev/null | jq -r '.' 2>/dev/null || echo "null")
566
572
  if [ -z "$LLAMA_CPP_REVIEWER_BUDGET" ] || [ "$LLAMA_CPP_REVIEWER_BUDGET" = "null" ]; then
@@ -728,7 +734,7 @@ trimmed_reviewers: # only present if at least one reviewer was trimmed
728
734
 
729
735
  Commit:
730
736
  ```bash
731
- pp_run query commit "docs: cross-AI review for phase {N}" --files {phase_dir}/{padded_phase}-REVIEWS.md
737
+ pp_run query commit "docs(planning): cross-AI review for phase {N}" --phase "{padded_phase}" --files {phase_dir}/{padded_phase}-REVIEWS.md
732
738
  ```
733
739
  </step>
734
740
 
@@ -38,6 +38,7 @@ Display banner: `pp-core > SECURE PHASE {N}: {name}`
38
38
  ## 1. Detect Input State
39
39
 
40
40
  ```bash
41
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
41
42
  SECURITY_FILE=$(ls "${PHASE_DIR}"/*-SECURITY.md 2>/dev/null | head -1)
42
43
  PLAN_FILES=$(ls "${PHASE_DIR}"/*-PLAN.md 2>/dev/null)
43
44
  SUMMARY_FILES=$(ls "${PHASE_DIR}"/*-SUMMARY.md 2>/dev/null)
@@ -151,7 +152,7 @@ Do NOT emit next-phase routing. Stop here.
151
152
  ## 7. Commit
152
153
 
153
154
  ```bash
154
- pp_run query commit "docs(phase-${PHASE}): add/update security threat verification"
155
+ pp_run query commit "docs(planning): add/update security threat verification" --phase "${PADDED_PHASE}"
155
156
  ```
156
157
 
157
158
  ## 8. Results + Routing
@@ -34,6 +34,7 @@ Read `.planning/ROADMAP.md` to get milestone name and goals.
34
34
 
35
35
  Check for existing reports:
36
36
  ```bash
37
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
37
38
  ls -la .planning/reports/SESSION_REPORT*.md 2>/dev/null || echo "No previous reports"
38
39
  ```
39
40
  </step>
@@ -99,6 +99,7 @@ Verify the work is ready to ship:
99
99
  ```
100
100
 
101
101
  ```bash
102
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
102
103
  SHIP_PRE_HOOKS_JSON=$(pp_run loop render-hooks ship:pre --raw)
103
104
  printf '%s' "$SHIP_PRE_HOOKS_JSON" | node -e "let h=[];try{h=JSON.parse(require('fs').readFileSync(0,'utf-8')).activeHooks||[]}catch{}console.log('SHIP_PRE_HOOKS_JSON='+JSON.stringify({activeHooks:h}))"
104
105
  SECURITY_FILE=$(ls "${PHASE_DIR}"/*-SECURITY.md 2>/dev/null | head -1)
@@ -173,11 +174,13 @@ Verify the work is ready to ship:
173
174
  Push the current branch to remote:
174
175
 
175
176
  ```bash
177
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
176
178
  git push origin ${CURRENT_BRANCH} 2>&1
177
179
  ```
178
180
 
179
181
  If push fails (e.g., no upstream): set upstream:
180
182
  ```bash
183
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
181
184
  git push --set-upstream origin ${CURRENT_BRANCH} 2>&1
182
185
  ```
183
186
 
@@ -370,6 +373,7 @@ If `REVIEW_CMD` is non-empty and not `"null"`, run the external review:
370
373
 
371
374
  1. **Generate diff and stats:**
372
375
  ```bash
376
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
373
377
  DIFF=$(git diff ${BASE_BRANCH}...HEAD)
374
378
  DIFF_STATS=$(git diff --stat ${BASE_BRANCH}...HEAD)
375
379
  ```
@@ -382,6 +386,7 @@ If `REVIEW_CMD` is non-empty and not `"null"`, run the external review:
382
386
  3. **Build review prompt and pipe to command via stdin:**
383
387
  Construct a review prompt containing the diff, diff stats, and phase context, then pipe it to the configured command:
384
388
  ```bash
389
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
385
390
  REVIEW_PROMPT="You are reviewing a pull request.\n\nDiff stats:\n${DIFF_STATS}\n\nPhase context:\n${STATE_STATUS}\n\nFull diff:\n${DIFF}\n\nRespond with JSON: { \"verdict\": \"APPROVED\" or \"REVISE\", \"confidence\": 0-100, \"summary\": \"...\", \"issues\": [{\"severity\": \"...\", \"file\": \"...\", \"line_range\": \"...\", \"description\": \"...\", \"suggestion\": \"...\"}] }"
386
391
  PP_GATE_BIN=$(printf '%s\n' "${PP_TOOLS:+${PP_TOOLS%/*}:}$PATH" | tr : '\n' | while IFS= read -r d; do if [ -r "$d/portable-timeout.sh" ]; then printf %s "$d"; break; fi; done)
387
392
  if [ -r "$PP_GATE_BIN/portable-timeout.sh" ]; then
@@ -399,6 +404,7 @@ If `REVIEW_CMD` is non-empty and not `"null"`, run the external review:
399
404
  that disagreed. `is_timeout_exit` is not in scope in this block (the wrapper is sourced in
400
405
  the block above), so the codes are tested numerically:
401
406
  ```bash
407
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
402
408
  if [ "${REVIEW_EXIT}" -eq 124 ] || [ "${REVIEW_EXIT}" -eq 142 ]; then
403
409
  echo "⚠ External review timed out after 120s (exit ${REVIEW_EXIT}) — advisory, not a failure"
404
410
  elif [ "${REVIEW_EXIT}" -eq 127 ] || [ "${REVIEW_EXIT}" -eq 2 ]; then
@@ -455,6 +461,7 @@ AskUserQuestion:
455
461
 
456
462
  **If "Request review":**
457
463
  ```bash
464
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
458
465
  gh pr edit ${PR_NUMBER} --add-reviewer "${REVIEWER}"
459
466
  ```
460
467
 
@@ -472,7 +479,7 @@ pp_run query state.update "Status" "Phase ${PHASE_NUMBER} shipped — PR #${PR_N
472
479
 
473
480
  If `commit_docs` is true:
474
481
  ```bash
475
- pp_run query commit "docs(${padded_phase}): ship phase ${PHASE_NUMBER} — PR #${PR_NUMBER}" --files .planning/STATE.md
482
+ pp_run query commit "docs(planning): ship phase ${PHASE_NUMBER} — PR #${PR_NUMBER}" --phase "${padded_phase}" --files .planning/STATE.md
476
483
  ```
477
484
  </step>
478
485
 
@@ -233,7 +233,7 @@ If this routing line already exists (append mode), leave it as-is.
233
233
  Commit all artifacts (if `COMMIT_DOCS` is true):
234
234
 
235
235
  ```bash
236
- pp_run query commit "docs(sketch-wrap-up): package [N] sketch findings into project skill" --files .planning/sketches/WRAP-UP-SUMMARY.md
236
+ pp_run query commit "docs(planning): package [N] sketch findings into project skill" --files .planning/sketches/WRAP-UP-SUMMARY.md
237
237
  ```
238
238
  </step>
239
239
 
@@ -94,6 +94,7 @@ mkdir -p .planning/sketches/themes
94
94
 
95
95
  Check for existing sketches to determine numbering:
96
96
  ```bash
97
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
97
98
  ls -d .planning/sketches/[0-9][0-9][0-9]-* 2>/dev/null | sort | tail -1
98
99
  ```
99
100
 
@@ -298,7 +299,7 @@ Iterate until satisfied.
298
299
 
299
300
  **h.** Commit (if `COMMIT_DOCS` is true):
300
301
  ```bash
301
- pp_run query commit "docs(sketch-NNN): [winning direction] — [key visual insight]" --files .planning/sketches/NNN-descriptive-name/ .planning/sketches/MANIFEST.md
302
+ pp_run query commit "docs(planning): sketch NNN [winning direction] — [key visual insight]" --files .planning/sketches/NNN-descriptive-name/ .planning/sketches/MANIFEST.md
302
303
  ```
303
304
 
304
305
  **i.** Report:
@@ -357,6 +358,6 @@ After all sketches complete:
357
358
  - [ ] Winning variant selected and marked for each sketch
358
359
  - [ ] All variants preserved (winner marked, not others deleted)
359
360
  - [ ] MANIFEST.md is current
360
- - [ ] Commits use `docs(sketch-NNN): [winner]` format
361
+ - [ ] Commits use `docs(planning): sketch NNN [winner]` format
361
362
  - [ ] Summary presented with next-step routing
362
363
  </success_criteria>
@@ -74,6 +74,7 @@ Exit.
74
74
 
75
75
  **Check for existing SPEC.md:**
76
76
  ```bash
77
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
77
78
  ls ${phase_dir}/*-SPEC.md 2>/dev/null | grep -v AI-SPEC | head -1 || true
78
79
  ```
79
80
 
@@ -447,7 +448,7 @@ Write to: `{phase_dir}/{padded_phase}-SPEC.md`
447
448
 
448
449
  ```bash
449
450
  git add "${phase_dir}/${padded_phase}-SPEC.md"
450
- git commit -m "spec(phase-${phase_number}): add SPEC.md for ${phase_name} — ${requirement_count} requirements (#2213)"
451
+ git commit -m "docs(planning): add SPEC.md for ${phase_name} — ${requirement_count} requirements" -m "Phase: ${padded_phase}"
451
452
  ```
452
453
 
453
454
  If `commit_docs` is false: Skip commit. Note that SPEC.md was written but not committed.
@@ -247,7 +247,7 @@ Patterns and stack choices established across spike sessions. New spikes follow
247
247
  Commit all artifacts (if `COMMIT_DOCS` is true):
248
248
 
249
249
  ```bash
250
- pp_run query commit "docs(spike-wrap-up): package [N] spike findings into project skill" --files .planning/spikes/WRAP-UP-SUMMARY.md .planning/spikes/CONVENTIONS.md
250
+ pp_run query commit "docs(planning): package [N] spike findings into project skill" --files .planning/spikes/WRAP-UP-SUMMARY.md .planning/spikes/CONVENTIONS.md
251
251
  ```
252
252
  </step>
253
253
 
@@ -91,6 +91,7 @@ mkdir -p .planning/spikes
91
91
 
92
92
  Check for existing spikes to determine numbering:
93
93
  ```bash
94
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
94
95
  ls -d .planning/spikes/[0-9][0-9][0-9]-* 2>/dev/null | sort | tail -1
95
96
  ```
96
97
 
@@ -335,7 +336,7 @@ tags: [tag1, tag2]
335
336
 
336
337
  **i.** Commit (if `COMMIT_DOCS` is true):
337
338
  ```bash
338
- pp_run query commit "docs(spike-NNN): [VERDICT] — [key finding]" --files .planning/spikes/NNN-descriptive-name/ .planning/spikes/MANIFEST.md
339
+ pp_run query commit "docs(planning): spike NNN [VERDICT] — [key finding]" --files .planning/spikes/NNN-descriptive-name/ .planning/spikes/MANIFEST.md
339
340
  ```
340
341
 
341
342
  **j.** Report:
@@ -389,7 +390,7 @@ Only include patterns that repeated across 2+ spikes or were explicitly chosen b
389
390
 
390
391
  Commit (if `COMMIT_DOCS` is true):
391
392
  ```bash
392
- pp_run query commit "docs(spikes): update conventions" --files .planning/spikes/CONVENTIONS.md
393
+ pp_run query commit "docs(planning): update spike conventions" --files .planning/spikes/CONVENTIONS.md
393
394
  ```
394
395
  </step>
395
396
 
@@ -448,6 +449,6 @@ pp_run query commit "docs(spikes): update conventions" --files .planning/spikes/
448
449
  - [ ] CONVENTIONS.md created or updated with patterns that emerged
449
450
  - [ ] Each spike README has complete frontmatter, Investigation Trail, and Results
450
451
  - [ ] MANIFEST.md is current (with Type column and Requirements section)
451
- - [ ] Commits use `docs(spike-NNN): [VERDICT]` format
452
+ - [ ] Commits use `docs(planning): spike NNN [VERDICT]` format
452
453
  - [ ] Consolidated report presented with next-step routing
453
454
  </success_criteria>
@@ -24,20 +24,21 @@ If neither `--dry-run` nor `--apply` is specified, dry-run is the default.
24
24
  ## Step 1: Parse Arguments
25
25
 
26
26
  ```bash
27
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
27
28
  FROM_RUNTIME=""
28
29
  TO_RUNTIMES=()
29
30
  IS_APPLY=false
30
31
 
31
32
  # Parse --from
32
33
  if [[ "$@" == *"--from"* ]]; then
33
- FROM_RUNTIME=$(echo "$@" | grep -oP '(?<=--from )\S+')
34
+ FROM_RUNTIME=$(echo "$@" | grep -oE -- '--from [^ ]+' | head -1 | sed 's/^--from //')
34
35
  fi
35
36
 
36
37
  # Parse --to
37
38
  if [[ "$@" == *"--to all"* ]]; then
38
39
  TO_RUNTIMES=(claude codex grok copilot cursor windsurf opencode gemini kilo augment trae qwen codebuddy cline antigravity)
39
40
  elif [[ "$@" == *"--to"* ]]; then
40
- TO_RUNTIMES=( $(echo "$@" | grep -oP '(?<=--to )\S+') )
41
+ TO_RUNTIMES=( $(echo "$@" | grep -oE -- '--to [^ ]+' | sed 's/^--to //') )
41
42
  fi
42
43
 
43
44
  # Parse --apply
@@ -58,6 +59,7 @@ fi
58
59
  Use `install.js --skills-root` to resolve paths — this reuses the single authoritative path table rather than duplicating it:
59
60
 
60
61
  ```bash
62
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
61
63
  INSTALL_JS="$(dirname "$0")/../pp-core/bin/install.js"
62
64
  # If running from a global install, resolve relative to the pp-core package
63
65
  INSTALL_JS_GLOBAL="$HOME/.claude/pp-core/bin/install.js"
@@ -142,6 +144,7 @@ If `--dry-run` (or no flag): skip this step entirely and exit after printing the
142
144
  For each destination with changes:
143
145
 
144
146
  ```bash
147
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
145
148
  mkdir -p "$DEST_ROOT"
146
149
 
147
150
  for SKILL in $CREATE_LIST $UPDATE_LIST; do
@@ -22,6 +22,7 @@ Create, list, close, or resume persistent context threads for cross-session work
22
22
  **LIST / LIST-OPEN / LIST-RESOLVED mode:**
23
23
 
24
24
  ```bash
25
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
25
26
  ls .planning/threads/*.md 2>/dev/null
26
27
  ```
27
28
 
@@ -74,7 +75,7 @@ When SUBCMD=close and SLUG is set (already sanitized):
74
75
 
75
76
  3. Commit:
76
77
  ```bash
77
- pp_run query commit "docs: resolve thread — {SLUG}" --files ".planning/threads/{SLUG}.md"
78
+ pp_run query commit "docs(planning): resolve thread — {SLUG}" --files ".planning/threads/{SLUG}.md"
78
79
  ```
79
80
 
80
81
  4. Print:
@@ -186,7 +187,7 @@ updated: {today ISO date}
186
187
 
187
188
  5. Commit:
188
189
  ```bash
189
- pp_run query commit "docs: create thread — ${ARGUMENTS}" --files ".planning/threads/${SLUG}.md"
190
+ pp_run query commit "docs(planning): create thread — ${ARGUMENTS}" --files ".planning/threads/${SLUG}.md"
190
191
  ```
191
192
 
192
193
  6. Report:
@@ -59,6 +59,7 @@ Note accumulated context that may need updating after transition.
59
59
  Check current phase has all plan summaries:
60
60
 
61
61
  ```bash
62
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
62
63
  (ls .planning/phases/XX-current/*-PLAN.md 2>/dev/null || true) | sort
63
64
  (ls .planning/phases/XX-current/*-SUMMARY.md 2>/dev/null || true) | sort
64
65
  ```
@@ -81,6 +82,7 @@ cat .planning/config.json 2>/dev/null || true
81
82
  **Check for verification debt in this phase:**
82
83
 
83
84
  ```bash
85
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
84
86
  # Count outstanding items in current phase
85
87
  OUTSTANDING=""
86
88
  for f in .planning/phases/XX-current/*-UAT.md .planning/phases/XX-current/*-VERIFICATION.md; do
@@ -155,6 +157,7 @@ Wait for user decision.
155
157
  Check for lingering handoffs:
156
158
 
157
159
  ```bash
160
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
158
161
  ls .planning/phases/XX-current/.continue-here*.md 2>/dev/null || true
159
162
  ```
160
163
 
@@ -196,6 +199,7 @@ Evolve PROJECT.md to reflect learnings from completed phase.
196
199
  **Read phase summaries:**
197
200
 
198
201
  ```bash
202
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
199
203
  cat .planning/phases/XX-current/*-SUMMARY.md
200
204
  ```
201
205
 
@@ -385,6 +389,7 @@ After (if database indexing was addressed in Phase 2):
385
389
  Record the transition in STATE.md's Session Continuity through the state verb, never by hand: it writes the `Stopped at:` line, the `Last session` timestamp and the frontmatter `stopped_at` together. A hand edit leaves the stored `stopped_at` behind, and `state json`, `state-snapshot` and later writes keep the older value.
386
390
 
387
391
  ```bash
392
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
388
393
  pp_run query state.record-session --stopped-at "Phase [X] complete, ready to plan Phase [X+1]" --resume-file "None" ${GSD_WS}
389
394
  ```
390
395
 
@@ -452,6 +457,7 @@ Read ROADMAP.md to get the next phase's name and goal.
452
457
  **Check if next phase has CONTEXT.md:**
453
458
 
454
459
  ```bash
460
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
455
461
  ls .planning/phases/*[X+1]*/*-CONTEXT.md 2>/dev/null || true
456
462
  ```
457
463
 
@@ -32,6 +32,7 @@ Parse JSON for: `phase_dir`, `phase_number`, `phase_name`, `phase_slug`, `padded
32
32
 
33
33
  Detect sketch findings:
34
34
  ```bash
35
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
35
36
  SKETCH_FINDINGS_PATH=$(ls ./.claude/skills/sketch-findings-*/SKILL.md 2>/dev/null | head -1 || true)
36
37
  ```
37
38
 
@@ -113,6 +114,7 @@ Continue (non-blocking).
113
114
  ## 4. Check Existing UI-SPEC
114
115
 
115
116
  ```bash
117
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
116
118
  UI_SPEC_FILE=$(ls "${PHASE_DIR}"/*-UI-SPEC.md 2>/dev/null | head -1)
117
119
  ```
118
120
 
@@ -320,7 +322,7 @@ Dimensions: 6/6 passed
320
322
  ## 11. Commit (if configured)
321
323
 
322
324
  ```bash
323
- pp_run query commit "docs(${padded_phase}): UI design contract" --files "${PHASE_DIR}/${PADDED_PHASE}-UI-SPEC.md"
325
+ pp_run query commit "docs(planning): UI design contract" --phase "${padded_phase}" --files "${PHASE_DIR}/${PADDED_PHASE}-UI-SPEC.md"
324
326
  ```
325
327
 
326
328
  ## 12. Update State
@@ -38,6 +38,7 @@ Display banner:
38
38
  ## 1. Detect Input State
39
39
 
40
40
  ```bash
41
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
41
42
  SUMMARY_FILES=$(ls "${PHASE_DIR}"/*-SUMMARY.md 2>/dev/null)
42
43
  UI_SPEC_FILE=$(ls "${PHASE_DIR}"/*-UI-SPEC.md 2>/dev/null | head -1)
43
44
  UI_REVIEW_FILE=$(ls "${PHASE_DIR}"/*-UI-REVIEW.md 2>/dev/null | head -1)
@@ -177,7 +178,7 @@ tools is detected at runtime.
177
178
  ## 5. Commit (if configured)
178
179
 
179
180
  ```bash
180
- pp_run query commit "docs(${padded_phase}): UI audit review" --files "${PHASE_DIR}/${PADDED_PHASE}-UI-REVIEW.md"
181
+ pp_run query commit "docs(planning): UI audit review" --phase "${padded_phase}" --files "${PHASE_DIR}/${PADDED_PHASE}-UI-REVIEW.md"
181
182
  ```
182
183
 
183
184
  </process>
@@ -29,6 +29,7 @@ Use /pp:plan-phase for stable local planning.
29
29
  Check that the session is running inside Claude Code:
30
30
 
31
31
  ```bash
32
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
32
33
  if [ "$CLAUDECODE" = "1" ] || [ -n "$CLAUDE_CODE_ENTRYPOINT" ]; then
33
34
  CC_VERSION="$(claude --version 2>/dev/null | grep -Eo '[0-9]+\.[0-9]+\.[0-9]+' | head -n1)"
34
35
  if [ -n "$CC_VERSION" ] && [ "$(printf '%s\n' "2.1.91" "$CC_VERSION" | sort -V | head -n1)" = "2.1.91" ]; then
@@ -50,17 +50,18 @@ Based on MODE, gather candidate commits.
50
50
 
51
51
  Run:
52
52
  ```bash
53
- git log --oneline --no-merges -${COUNT}
53
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
54
+ git log --no-merges -${COUNT} --format='%h %s [Phase: %(trailers:key=Phase,valueonly,separator=%x2C)]'
54
55
  ```
55
56
 
56
- Filter for pp-core conventional commits matching `type(scope): message` pattern (e.g., `feat(04-01):`, `docs(03):`, `fix(02-03):`).
57
+ Filter for conventional commits matching `type(scope): message` or `type: message` (e.g., `feat(auth):`, `docs(planning):`, `fix:`). The scope names a part of the codebase; the phase or plan a commit belongs to is its `Phase:` trailer, shown in brackets (empty when the commit has none).
57
58
 
58
59
  Display a numbered list of matching commits:
59
60
  ```
60
61
  Recent pp-core commits:
61
- 1. abc1234 feat(04-01): implement auth endpoint
62
- 2. def5678 docs(03-02): complete plan summary
63
- 3. ghi9012 fix(02-03): correct validation logic
62
+ 1. abc1234 feat(auth): implement auth endpoint [Phase: 04-01]
63
+ 2. def5678 docs(planning): complete plan summary [Phase: 03-02]
64
+ 3. ghi9012 fix(validation): correct validation logic [Phase: 02-03]
64
65
  ```
65
66
 
66
67
 
@@ -82,9 +83,10 @@ If the file exists and `manifest.phases?.[TARGET_PHASE]?.commits` is a non-empty
82
83
 
83
84
  If the file does not exist, or `manifest.phases?.[TARGET_PHASE]` is missing:
84
85
  - Display: "Manifest has no entry for phase ${TARGET_PHASE} (or file missing), falling back to git log search"
85
- - Fallback: run git log and filter for the target phase scope:
86
+ - Fallback: run git log and filter for commits whose `Phase:` trailer is the target phase or one of its plans (a `type(<phase>):` subject from before the trailer convention also matches):
86
87
  ```bash
87
- git log --oneline --no-merges --all | grep -E "\(0*${TARGET_PHASE}(-[0-9]+)?\):" | head -50
88
+ git log --no-merges --all --format='%h %s [Phase: %(trailers:key=Phase,valueonly,separator=%x2C)]' \
89
+ | grep -E "\[Phase: 0*${TARGET_PHASE}(-[0-9]+)?\]|\(0*${TARGET_PHASE}(-[0-9]+)?\):" | head -50
88
90
  ```
89
91
  - Use matching commits as COMMITS
90
92
 
@@ -94,7 +96,8 @@ If the file does not exist, or `manifest.phases?.[TARGET_PHASE]` is missing:
94
96
 
95
97
  Run:
96
98
  ```bash
97
- git log --oneline --no-merges --all | grep -E "\(${TARGET_PLAN}\)" | head -50
99
+ git log --no-merges --all --format='%h %s [Phase: %(trailers:key=Phase,valueonly,separator=%x2C)]' \
100
+ | grep -E "\[Phase: ${TARGET_PLAN}\]|\(${TARGET_PLAN}\):" | head -50
98
101
  ```
99
102
 
100
103
  Use matching commits as COMMITS.
@@ -214,6 +217,7 @@ Sort COMMITS in reverse chronological order (newest first). If commits came from
214
217
 
215
218
  For each commit hash in COMMITS:
216
219
  ```bash
220
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
217
221
  git revert --no-commit ${HASH}
218
222
  ```
219
223
 
@@ -246,12 +250,12 @@ After all reverts are staged successfully, create a single commit:
246
250
 
247
251
  For MODE=phase:
248
252
  ```bash
249
- git commit -m "revert(${TARGET_PHASE}): undo phase ${TARGET_PHASE} — ${REVERT_REASON}"
253
+ git commit -m "revert: undo phase ${TARGET_PHASE} — ${REVERT_REASON}" -m "Phase: ${TARGET_PHASE}"
250
254
  ```
251
255
 
252
256
  For MODE=plan:
253
257
  ```bash
254
- git commit -m "revert(${TARGET_PLAN}): undo plan ${TARGET_PLAN} — ${REVERT_REASON}"
258
+ git commit -m "revert: undo plan ${TARGET_PLAN} — ${REVERT_REASON}" -m "Phase: ${TARGET_PLAN}"
255
259
  ```
256
260
 
257
261
  For MODE=last:
@@ -18,6 +18,7 @@ First, derive `PREFERRED_CONFIG_DIR` and `PREFERRED_RUNTIME` from the invoking p
18
18
  Then resolve the install context via the deterministic projection (#498). **Do NOT re-derive scope, runtime, or version by hand** — `update-context` owns that cascade in tested code (`pp-core/bin/lib/update-context.cjs`), the same way `check-latest-version` owns the package name (#2992):
19
19
 
20
20
  ```bash
21
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
21
22
  # Resolve pp-tools.cjs WITHOUT yet knowing GSD_DIR. The running workflow lives
22
23
  # at <PREFERRED_CONFIG_DIR>/pp-core/workflows/update.md, so its sibling
23
24
  # bin/pp-tools.cjs is the authoritative tool for THIS install. Fall back to a
@@ -79,6 +80,7 @@ If multiple runtime installs are detected and the invoking runtime cannot be det
79
80
  Determine the release channel from `$ARGUMENTS`. This selects which npm dist-tag the entire update flow targets — `latest` (stable) by default, or `next` (the RC channel established by ADR #660) when the user opts in with `--next`/`--rc`:
80
81
 
81
82
  ```bash
83
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
82
84
  case " $ARGUMENTS " in
83
85
  *" --next "*|*" --rc "*)
84
86
  TAG="next"
@@ -102,6 +104,7 @@ The `GSD_DIR` value emitted by `get_installed_version` (line 4) resolves to the
102
104
  `LATEST_RESULT` is a JSON document with the documented shape `{ ok: bool, version: string, reason: string, detail?: string }`. Parse via `jq` ONLY when the script actually ran. When `GSD_DIR` is empty (scope `UNKNOWN`), skip the check entirely and seed the parsed fields with their no-op values so downstream logic does not mistake an unset `LATEST_RESULT` for a failed network check (#2993 CR feedback):
103
105
 
104
106
  ```bash
107
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
105
108
  if [ -z "$GSD_DIR" ]; then
106
109
  # No install detected — fall through to install step; version-check is skipped.
107
110
  LATEST_RESULT=""
@@ -312,6 +315,7 @@ Back up each custom file to `$RUNTIME_DIR/pp-user-files-backup/` before the
312
315
  installer wipes the directories:
313
316
 
314
317
  ```bash
318
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
315
319
  BACKUP_DIR="$RUNTIME_DIR/pp-user-files-backup"
316
320
  mkdir -p "$BACKUP_DIR"
317
321
 
@@ -377,6 +381,7 @@ Capture output. If install fails, show error and exit.
377
381
  Clear the update cache so statusline indicator disappears:
378
382
 
379
383
  ```bash
384
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
380
385
  expand_home() {
381
386
  case "$1" in
382
387
  "~/"*) printf '%s/%s\n' "$HOME" "${1#~/}" ;;
@@ -57,6 +57,7 @@ gate on the `execute:pre` payload, filtered in the fence to the `vault`
57
57
  capability (D-30):
58
58
 
59
59
  ```bash
60
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
60
61
  VP_EXECUTE_PRE_HOOKS_JSON=$(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('');}")
61
62
  printf '%s' "$VP_EXECUTE_PRE_HOOKS_JSON" | node -e "let h=[];try{h=JSON.parse(require('fs').readFileSync(0,'utf-8')).activeHooks||[]}catch{}console.log('VP_EXECUTE_PRE_HOOKS_JSON='+JSON.stringify({activeHooks:h}))"
62
63
  ```
@@ -72,6 +73,7 @@ it owns the halt.
72
73
  ## 1. Detect Input State
73
74
 
74
75
  ```bash
76
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
75
77
  VALIDATION_FILE=$(ls "${PHASE_DIR}"/*-VALIDATION.md 2>/dev/null | head -1)
76
78
  SUMMARY_FILES=$(ls "${PHASE_DIR}"/*-SUMMARY.md 2>/dev/null)
77
79
  ```
@@ -188,9 +190,10 @@ Handle return:
188
190
 
189
191
  ```bash
190
192
  git add {test_files}
191
- git commit -m "test(phase-${PHASE}): add Nyquist validation tests"
193
+ # {area}: the part of the codebase the tests cover; drop "({area})" when no single area fits
194
+ git commit -m "test({area}): add Nyquist validation tests" -m "Phase: ${PADDED_PHASE}"
192
195
 
193
- pp_run query commit "docs(phase-${PHASE}): add/update validation strategy"
196
+ pp_run query commit "docs(planning): add/update validation strategy" --phase "${PADDED_PHASE}"
194
197
  ```
195
198
 
196
199
  Vault door record (D-12), only when Step 5 ran: after the door's last source commit, set `DOOR_DIR="${PHASE_DIR}"`,
@@ -205,7 +208,7 @@ The verb writes a `## Vault Door Record` (mode, vault ref and sha, governing pha
205
208
  recorded and the end commit; the agent never types a sha) into a fresh per-run artifact, because it refuses a second record
206
209
  in one file (D-57) and a rewritten report would drop the earlier run's coverage (D-79). It prints
207
210
  nothing and writes nothing unless `vault admission` answers `on`. When it wrote the file and
208
- `commit_docs` is true, commit the `artifact` path it printed: `pp_run query commit "docs(phase-${PHASE}): vault door record for validate-phase" --files "<that artifact>"`.
211
+ `commit_docs` is true, commit the `artifact` path it printed: `pp_run query commit "docs(planning): vault door record for validate-phase" --phase "${PADDED_PHASE}" --files "<that artifact>"`.
209
212
 
210
213
  (A per-run `-VALIDATION.md` name would be read as the phase's validation strategy by the `*-VALIDATION.md`
211
214
  globs, so validate-phase's record uses the `-ADD-TESTS.md` suffix: what it records is the tests it added.)
@@ -51,6 +51,7 @@ Then display the banner:
51
51
  ## 1. Detect Input State
52
52
 
53
53
  ```bash
54
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
54
55
  SUMMARY_FILES=$(ls "${PHASE_DIR}"/*-SUMMARY.md 2>/dev/null)
55
56
  VAULT_REVIEW_FILE=$(ls "${PHASE_DIR}"/*-VAULT-REVIEW.md 2>/dev/null | head -1)
56
57
  ```
@@ -84,6 +85,11 @@ reinterpret it.
84
85
  range (`filesTruncated` when the list was capped).
85
86
  - `gaps[]`: facts the CLI could not establish. Every gap goes into the artifact's `## Not Derived`
86
87
  section; a gap is never silently dropped and never turned into a verdict.
88
+ - `deviations[]`: the rows of `.planning/discovery/_deviations.md` when the project ran the
89
+ Discovery Sprint (`id`, `standard`, `status`, `decision`, `approver`); empty otherwise. An
90
+ `Approved` deviation that covers a clause turns that document's `FAIL` into `N-A` with the reason
91
+ `deviation on file: …` — the agent's rule, in `agents/pp-vault-reviewer.md`
92
+ (`references/discovery-build-consumption.md` § `_deviations.md` read contract).
87
93
 
88
94
  ## 3. Spawn pp-vault-reviewer
89
95
 
@@ -188,7 +194,7 @@ step reads a verdict into a halt, an exit code or a block, and nothing here writ
188
194
  ## 5. Commit (if configured)
189
195
 
190
196
  ```bash
191
- pp_run query commit "docs(${PADDED_PHASE}): vault standards review" --files "${PHASE_DIR}/${PADDED_PHASE}-VAULT-REVIEW.md"
197
+ pp_run query commit "docs(planning): vault standards review" --phase "${PADDED_PHASE}" --files "${PHASE_DIR}/${PADDED_PHASE}-VAULT-REVIEW.md"
192
198
  ```
193
199
 
194
200
  </process>
@@ -40,6 +40,7 @@ Do not compose, rewrite or reformat the document at this or any later step. What
40
40
  disk at that path are exactly the bytes that will be previewed and, if approved, pushed.
41
41
 
42
42
  ```bash
43
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
43
44
  DOC_FILE="<the resolved path>"
44
45
  PROMOTE_ARGS=() # add --path, --entry and --section with their values, as given
45
46
  ```
@@ -52,6 +53,7 @@ writes the change there, and reports the diff.
52
53
 
53
54
  ```bash
54
55
  _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
56
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
55
57
  PROMOTE_PREVIEW_OUT=$(mktemp)
56
58
  PROMOTE_PREVIEW_ERR=$(mktemp)
57
59
  pp_run vault standards promote "$DOC_FILE" "${PROMOTE_ARGS[@]}" --raw >"$PROMOTE_PREVIEW_OUT" 2>"$PROMOTE_PREVIEW_ERR"
@@ -71,6 +73,7 @@ its own file and read back with `$(cat …)`, whose result bash does not re-scan
71
73
  destination path containing `$(...)` or backticks is shown, never executed.
72
74
 
73
75
  ```bash
76
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
74
77
  PROMOTE_FIELDS=$(mktemp -d)
75
78
  node -e "
76
79
  const fs = require('fs');
@@ -137,6 +140,7 @@ Only inside this approved branch, run the verb again with the same arguments, `-
137
140
  expect token carried verbatim from the preview.
138
141
 
139
142
  ```bash
143
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
140
144
  PROMOTE_PUSH_OUT=$(mktemp)
141
145
  PROMOTE_PUSH_ERR=$(mktemp)
142
146
  pp_run vault standards promote "$DOC_FILE" "${PROMOTE_ARGS[@]}" --confirmed --expect "$PROMOTE_EXPECT" --raw >"$PROMOTE_PUSH_OUT" 2>"$PROMOTE_PUSH_ERR"
@@ -156,6 +160,7 @@ refresh did not succeed, say so plainly: the next vault fetch picks the change u
156
160
  succeeded.
157
161
 
158
162
  ```bash
163
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
159
164
  node -e "
160
165
  const fs = require('fs');
161
166
  const v = JSON.parse(fs.readFileSync(process.argv[1], 'utf8'));