@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
@@ -38,6 +38,7 @@ Extract from init JSON: `phase_dir`, `phase_number`, `phase_name`, `has_plans`,
38
38
 
39
39
  Then load phase details and list plans/summaries:
40
40
  ```bash
41
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
41
42
  pp_run query roadmap.get-phase "${phase_number}"
42
43
  grep -E "^| ${phase_number}" .planning/REQUIREMENTS.md 2>/dev/null || true
43
44
  ls "$phase_dir"/*-SUMMARY.md "$phase_dir"/*-PLAN.md 2>/dev/null || true
@@ -57,6 +58,7 @@ Extract **phase goal** from ROADMAP.md (the outcome to verify, not tasks), **req
57
58
  Use `pp-tools.cjs query` verify handlers (or legacy pp-tools) to extract must_haves from each PLAN:
58
59
 
59
60
  ```bash
61
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
60
62
  for plan in "$PHASE_DIR"/*-PLAN.md; do
61
63
  MUST_HAVES=$(pp_run query frontmatter.get "$plan" --field must_haves)
62
64
  echo "=== $plan ===" && echo "$MUST_HAVES"
@@ -124,6 +126,7 @@ For each truth: identify supporting artifacts → check artifact status → chec
124
126
  Use `pp-tools.cjs query verify.artifacts` (or legacy pp-tools) for artifact verification against must_haves in each PLAN:
125
127
 
126
128
  ```bash
129
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
127
130
  for plan in "$PHASE_DIR"/*-PLAN.md; do
128
131
  ARTIFACT_RESULT=$(pp_run query verify.artifacts "$plan")
129
132
  echo "=== $plan ===" && echo "$ARTIFACT_RESULT"
@@ -167,6 +170,7 @@ wiring or leftover code from plan revisions.
167
170
  Use `pp-tools.cjs query verify.key-links` (or legacy pp-tools) for key link verification against must_haves in each PLAN:
168
171
 
169
172
  ```bash
173
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
170
174
  for plan in "$PHASE_DIR"/*-PLAN.md; do
171
175
  LINKS_RESULT=$(pp_run query verify.key-links "$plan")
172
176
  echo "=== $plan ===" && echo "$LINKS_RESULT"
@@ -223,6 +227,7 @@ phase.
223
227
  no `<decisions>` block.
224
228
 
225
229
  ```bash
230
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
226
231
  GATE_CFG=$(pp_run query config-get workflow.context_coverage_gate 2>/dev/null || echo "true")
227
232
  if [ "$GATE_CFG" != "false" ]; then
228
233
  # Discover the phase CONTEXT.md via glob expansion rather than `ls | head`
@@ -38,6 +38,7 @@ If $ARGUMENTS contains a phase number, load context:
38
38
 
39
39
  ```bash
40
40
  _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
41
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
41
42
  GSD_WS=""
42
43
  echo "$ARGUMENTS" | grep -qE -- '--ws[[:space:]]+[^[:space:]]+' && GSD_WS=$(echo "$ARGUMENTS" | grep -oE -- '--ws[[:space:]]+[^[:space:]]+')
43
44
  PHASE_ARG=$(echo "$ARGUMENTS" | sed -E 's/--ws[[:space:]]+[^[:space:]]+//g' | xargs)
@@ -51,6 +52,7 @@ AGENT_SKILLS_CHECKER=$(pp_run query agent-skills pp-plan-checker)
51
52
  Parse JSON for: `planner_model`, `checker_model`, `commit_docs`, `phase_found`, `phase_dir`, `phase_number`, `phase_name`, `has_verification`, `uat_path`.
52
53
 
53
54
  ```bash
55
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
54
56
  # MVP mode detection via the centralized phase.mvp-mode resolver.
55
57
  # verify-work has no --mvp CLI flag (mode is inherited from the planned phase),
56
58
  # so we omit --cli-flag — the verb falls through roadmap → config → false.
@@ -111,6 +113,7 @@ Continue to `create_uat_file`.
111
113
  Before UAT, check UI capability activation and whether Playwright/Puppeteer MCP tools are available.
112
114
 
113
115
  ```bash
116
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
114
117
  PLAN_HOOKS_JSON=$(pp_run loop render-hooks plan:pre --raw)
115
118
  UI_SPEC_FILE=$(ls "${PHASE_DIR}"/*-UI-SPEC.md 2>/dev/null | head -1)
116
119
  ```
@@ -148,6 +151,7 @@ UI checkpoints: {N} auto-verified, {M} queued for manual review
148
151
  Use `phase_dir` from init (or run init if not already done).
149
152
 
150
153
  ```bash
154
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
151
155
  ls "$phase_dir"/*-SUMMARY.md 2>/dev/null || true
152
156
  ```
153
157
 
@@ -167,6 +171,7 @@ When `MVP_MODE=false` (mode is null, absent, or the phase has no `**Mode:**` lin
167
171
  **User-story format guard.** When `MVP_MODE=true`, also verify the phase's goal is in User Story format via the centralized validator:
168
172
 
169
173
  ```bash
174
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
170
175
  PHASE_GOAL=$(pp_run query roadmap.get-phase "${phase_number}" ${GSD_WS} --pick goal)
171
176
  USER_STORY_VALID=$(pp_run query user-story.validate --story "$PHASE_GOAL" --pick valid)
172
177
  if [ "$USER_STORY_VALID" != "true" ]; then
@@ -434,7 +439,7 @@ Clear Current Test section:
434
439
 
435
440
  Commit the UAT file:
436
441
  ```bash
437
- pp_run query commit "test({phase_num}): complete UAT - {passed} passed, {issues} issues" --files ".planning/phases/XX-name/{phase_num}-UAT.md"
442
+ pp_run query commit "docs(planning): complete UAT - {passed} passed, {issues} issues" --phase "{phase_num}" --files ".planning/phases/XX-name/{phase_num}-UAT.md"
438
443
  ```
439
444
 
440
445
  Present summary:
@@ -458,6 +463,7 @@ Present summary:
458
463
  **If issues == 0:**
459
464
 
460
465
  ```bash
466
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
461
467
  VERIFY_POST_HOOKS_JSON=$(pp_run loop render-hooks verify:post --raw)
462
468
  printf '%s' "$VERIFY_POST_HOOKS_JSON" | node -e "let h=[];try{h=JSON.parse(require('fs').readFileSync(0,'utf-8')).activeHooks||[]}catch{}console.log('VERIFY_POST_HOOKS_JSON='+JSON.stringify({activeHooks:h}))"
463
469
  SECURITY_FILE=$(ls "${PHASE_DIR}"/*-SECURITY.md 2>/dev/null | head -1)
@@ -478,6 +484,7 @@ Skill(skill="pp-${ref.skill}", args="{phase}")
478
484
  After the skill returns, refresh `SECURITY_FILE`:
479
485
 
480
486
  ```bash
487
+ [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
481
488
  SECURITY_FILE=$(ls "${PHASE_DIR}"/*-SECURITY.md 2>/dev/null | head -1)
482
489
  ```
483
490
 
@@ -84,7 +84,7 @@ PATTERNS=(
84
84
  ALLOWLIST=(
85
85
  'scripts/prompt-injection-scan.sh::the PATTERNS array above is the literal source of every phrase this scanner looks for, so the file matches itself by construction; measured 4 pattern hits at HEAD on 2026-09-19'
86
86
  'scripts/base64-scan.sh::decodes base64 blobs and re-scans the recovered plaintext against the same injection vocabulary, so it names those phrases inline; measured 2 pattern hits at HEAD on 2026-09-19'
87
- 'scripts/secret-scan.sh::third of the three diff-mode scan scripts CI runs together in the security_scan job of .github/workflows/ci.yml; measured 0 pattern hits at HEAD on 2026-09-19, retained because its own exemption list at line 223 already names security-prompt-injection.security.test.cjs and grows with that vocabulary'
87
+ 'scripts/secret-scan.sh::third of the three diff-mode scan scripts CI runs together in the pr_gates job of .github/workflows/ci.yml; measured 0 pattern hits at HEAD on 2026-09-19, retained because its own exemption list at line 223 already names security-prompt-injection.security.test.cjs and grows with that vocabulary'
88
88
  'tests/security-scan.security.test.cjs::the behavioural suite for this very scanner, so every positive case embeds a real injection phrase as fixture input; measured 28 pattern hits at HEAD on 2026-09-19'
89
89
  'tests/security.test.cjs::the adversarial suite for the library sanitisers, whose fixtures are real override and role-manipulation strings asserted to be neutralised; measured 54 pattern hits at HEAD on 2026-09-19'
90
90
  'tests/prompt-injection-scan.security.test.cjs::drives scanForInjection in the compiled security library with crafted payloads, and carries a second allowlist of its own for that separate scanner; measured 11 pattern hits at HEAD on 2026-09-19'
@@ -12,6 +12,13 @@
12
12
  * (document order) that contains a pp_run call. All other bash blocks
13
13
  * keep their pp_run calls with NO preamble. (Define once per file,
14
14
  * use across blocks — original footprint.)
15
+ * 4. Start every bash/sh/shell/zsh block that zsh would run differently
16
+ * from bash with ZSH_GUARD (right after the preamble where the block
17
+ * carries one), and drop the guard from a block that no longer needs it.
18
+ * Each block may run in its own shell, and an agent's shell is often zsh:
19
+ * the guard makes zsh read the block as sh (unmatched globs stay literal,
20
+ * `====` is a word, unquoted words split, arrays index from 0) and is a
21
+ * no-op under bash. See needsZshGuard for what counts.
15
22
  *
16
23
  * Run: node scripts/sync-runtime-launcher.cjs
17
24
  */
@@ -28,6 +35,57 @@ const SNIPPET_FILE = path.join(WORKFLOWS_DIR, '_runtime-launcher.snippet.sh');
28
35
  */
29
36
  const LAUNCHER_HEAD = '_PP_SHIM_NAME="pp-tools.cjs"; ';
30
37
 
38
+ /**
39
+ * The first line of every shell block (issue #12 items 2-4). Exits 0 under
40
+ * bash, so a block's status never depends on it.
41
+ */
42
+ const ZSH_GUARD = '[ -z "${ZSH_VERSION:-}" ] || emulate -R sh';
43
+ const GUARDED_LANGS = Object.freeze(['bash', 'sh', 'shell', 'zsh']);
44
+
45
+ /**
46
+ * True when zsh would run `lines` differently from bash: an unquoted glob
47
+ * character, a word starting with `=` plus more (`====`, `==`), an unquoted
48
+ * `$var` (zsh does not split it), or array syntax (zsh indexes from 1). Errs
49
+ * towards true — a needless guard costs a line, a missing one breaks a run.
50
+ * The launcher preamble is zsh-safe and is never inspected.
51
+ */
52
+ function needsZshGuard(lines) {
53
+ for (const raw of lines) {
54
+ const line = raw.trim();
55
+ if (line === '' || line.startsWith('#') || isLauncherLine(line) || line === ZSH_GUARD) continue;
56
+ if (/\$\{#?\w+\[/.test(line) || /\b\w+\+?=\(/.test(line)) return true;
57
+ // Neither shell globs, splits or `=`-expands inside `[[ … ]]` (syntax, not
58
+ // a command), in a case pattern (`*)`), or on an assignment's right side.
59
+ const bare = line
60
+ .replace(/'[^']*'/g, "''")
61
+ .replace(/"(?:\\.|[^"\\])*"/g, '""')
62
+ .replace(/\[\[\s.*?\s\]\]/g, '[[ ]]')
63
+ .replace(/(^|[\s;(|])\*\)/g, '$1)')
64
+ .replace(/(^|[\s;&|])([A-Za-z_]\w*)=\$(?=[{\w])/g, '$1$2=');
65
+ if (/(^|[\s;|&(])=[^\s]/.test(bare)) return true;
66
+ if (/\$(\w|\{)/.test(bare)) return true;
67
+ if (/[*?]/.test(bare.replace(/\$[*?#@!$-]/g, ''))) return true;
68
+ if (/[^\s\[]\[[^\]\s]*\]/.test(bare)) return true;
69
+ }
70
+ return false;
71
+ }
72
+
73
+ /**
74
+ * Make `lines` carry ZSH_GUARD exactly when needsZshGuard says so: at the top
75
+ * (after leading blanks, and after the preamble when the block starts with
76
+ * it), indented like the fence. Idempotent.
77
+ */
78
+ function insertZshGuard(lines, preamble, indent) {
79
+ const rest = lines.filter((l) => l.trim() !== ZSH_GUARD);
80
+ if (!needsZshGuard(rest)) return rest.length === lines.length ? lines : rest;
81
+ let at = 0;
82
+ while (at < rest.length && rest[at].trim() === '') at++;
83
+ if (at === rest.length) return lines;
84
+ if (preamble.length > 0 && preamble.every((p, k) => rest[at + k] === p)) at += preamble.length;
85
+ const out = [...rest.slice(0, at), indent + ZSH_GUARD, ...rest.slice(at)];
86
+ return out.join('\n') === lines.join('\n') ? lines : out;
87
+ }
88
+
31
89
  /**
32
90
  * Launcher carriers that live OUTSIDE this script's two roots
33
91
  * (pp-core/workflows/ and agents/).
@@ -387,7 +445,7 @@ function transformFile(content, preamble) {
387
445
  if (i < allLines.length) i++;
388
446
 
389
447
  if (isShellBlock) {
390
- shellBlockRanges.push({ openLineIdx, contentStart, contentEnd, closingLineIdx });
448
+ shellBlockRanges.push({ openLineIdx, contentStart, contentEnd, closingLineIdx, lang, indent });
391
449
  }
392
450
  }
393
451
 
@@ -418,10 +476,9 @@ function transformFile(content, preamble) {
418
476
 
419
477
  // Insert preamble into the first pp_run block only
420
478
  const finalBlocks = strippedBlocks.map((stripped, bi) => {
421
- if (bi === firstPpRunBlockIdx) {
422
- return insertPreamble(stripped, preamble);
423
- }
424
- return stripped;
479
+ const withPreamble = bi === firstPpRunBlockIdx ? insertPreamble(stripped, preamble) : stripped;
480
+ const range = shellBlockRanges[bi];
481
+ return GUARDED_LANGS.includes(range.lang) ? insertZshGuard(withPreamble, preamble, range.indent) : withPreamble;
425
482
  });
426
483
 
427
484
  // --- Pass 3: splice back into output (reverse order to preserve indices) ---
@@ -443,6 +500,43 @@ function transformFile(content, preamble) {
443
500
  return outputLines.join('\n');
444
501
  }
445
502
 
503
+ /**
504
+ * Guard-only pass for the roots whose launcher lines are kept in place
505
+ * (commands/, pp-core/references/): every non-empty bash/sh/shell/zsh block
506
+ * gets ZSH_GUARD, after a launcher line that opens it. pp-core/templates/ is
507
+ * never passed here — its blocks are text written into the user's project.
508
+ * Returns new content, or null when nothing changes.
509
+ */
510
+ function guardOnlyTransform(content) {
511
+ const lines = content.split('\n');
512
+ const out = [];
513
+ let changed = false;
514
+ let i = 0;
515
+ while (i < lines.length) {
516
+ const open = lines[i].match(/^(\s*)```(\w+)?\s*$/);
517
+ out.push(lines[i]);
518
+ i++;
519
+ if (!open) continue;
520
+ const indent = open[1];
521
+ const lang = (open[2] || '').toLowerCase();
522
+ const closing = new RegExp('^' + escapeRegExp(indent) + '```\\s*$');
523
+ const body = [];
524
+ while (i < lines.length && !closing.test(lines[i])) body.push(lines[i++]);
525
+ let next = body;
526
+ if (GUARDED_LANGS.includes(lang)) {
527
+ const first = body.find((l) => l.trim() !== '');
528
+ next = insertZshGuard(body, first !== undefined && isLauncherLine(first) ? [first] : [], indent);
529
+ if (next !== body) changed = true;
530
+ }
531
+ out.push(...next);
532
+ if (i < lines.length) out.push(lines[i++]);
533
+ }
534
+ return changed ? out.join('\n') : null;
535
+ }
536
+
537
+ /** The roots that get only the guard pass. */
538
+ const GUARD_ONLY_DIRS = Object.freeze(['commands', path.join('pp-core', 'references')]);
539
+
446
540
  function escapeRegExp(str) {
447
541
  return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
448
542
  }
@@ -511,6 +605,18 @@ function main() {
511
605
  }
512
606
  }
513
607
 
608
+ for (const dir of GUARD_ONLY_DIRS) {
609
+ for (const f of collectFiles(path.join(repoRoot, dir))) {
610
+ const content = fs.readFileSync(f, 'utf8');
611
+ const result = guardOnlyTransform(content);
612
+ if (result !== null) {
613
+ fs.writeFileSync(f, result, 'utf8');
614
+ transformedCount++;
615
+ console.log(`transformed (guard): ${path.relative(repoRoot, f)}`);
616
+ }
617
+ }
618
+ }
619
+
514
620
  console.log(`\nDone. ${transformedCount} files transformed, ${unchangedCount} unchanged.`);
515
621
  }
516
622
 
@@ -523,6 +629,10 @@ module.exports = {
523
629
  replaceCanonicalLines,
524
630
  EXTRA_CARRIERS,
525
631
  LAUNCHER_HEAD,
632
+ ZSH_GUARD,
633
+ needsZshGuard,
634
+ guardOnlyTransform,
635
+ GUARD_ONLY_DIRS,
526
636
  };
527
637
 
528
638
  if (require.main === module) {
@@ -1,266 +0,0 @@
1
- # Bootstrap Template — .planning/discovery/_context.md
2
-
3
- > **Lazy-loaded.** Read this file from `workflows/discovery-sprint.md` — from
4
- > Flow 2 Step 1, or from the Bootstrap Templates section — when
5
- > `.planning/discovery/_context.md` is absent (first-ever session on this
6
- > project). Create that file verbatim from the fenced schema below. The path is
7
- > fixed under `.planning/discovery/` (T-04-03): never a root-level directory,
8
- > never an absolute path, never a path containing `..`.
9
-
10
- **`.planning/discovery/_context.md`:**
11
-
12
- ```markdown
13
- # Cross-Session Context — [PROJECT_NAME]
14
-
15
- This file accumulates key outputs from each completed session to provide context for subsequent sessions. It is automatically maintained as sessions are completed.
16
-
17
- ---
18
-
19
- ## Session 1: Kick-off Outputs
20
- _Populated after Session 1 completion_
21
-
22
- ### Project Context
23
- <!-- Notes about the rationale and context -->
24
-
25
- ### Business Vision
26
- <!-- Business vision summary, KPIs -->
27
-
28
- ### Stakeholders
29
- <!-- Key stakeholder list with roles -->
30
-
31
- ### Discovery Sprint Scope
32
- **In Scope:**
33
- -
34
-
35
- **Out of Scope:**
36
- -
37
-
38
- ---
39
-
40
- ## Session 2: As-Is Outputs
41
- _Populated after Session 2 completion_
42
-
43
- ### Core Processes
44
- <!-- Current business processes -->
45
-
46
- ### Pain Points
47
- <!-- Prioritized pain points -->
48
-
49
- ### User Personas
50
- <!-- Key personas and their journeys -->
51
-
52
- ### Current Systems
53
- <!-- Systems landscape -->
54
-
55
- ### Data Flows
56
- <!-- How information moves today -->
57
-
58
- ---
59
-
60
- ## Session 3: To-Be Outputs
61
- _Populated after Session 3 completion_
62
-
63
- ### Business Objectives
64
- <!-- Measurable outcomes and KPIs -->
65
-
66
- ### MVP Scope
67
- <!-- What's in/out for MVP -->
68
-
69
- ### EPICs Summary
70
- <!-- EPIC registry table -->
71
-
72
- ### User Stories Summary
73
- <!-- Story count and distribution -->
74
-
75
- ### Requirements Summary
76
- <!-- Copy the rollup:auto totals table verbatim from .planning/discovery/_requirements.md — never hand-count -->
77
-
78
- ---
79
-
80
- ## Session 4: UX Design Outputs
81
- _Populated after Session 4 completion_
82
-
83
- ### Design Principles
84
- <!-- Numbered design principles -->
85
-
86
- ### UX Standards
87
- <!-- Standards Applied: the frontend standard citations and every D-04 deviation -->
88
-
89
- ### Key Personas (Refined)
90
- <!-- Persona categories and interaction patterns -->
91
-
92
- ### Key Screen Decisions
93
- <!-- Screen layout decisions -->
94
-
95
- ### Prototype
96
- <!-- Session 4 Closing Step answer; per /pp-discovery prototype round: flows validated, open feedback count -->
97
-
98
- ---
99
-
100
- ## Session 5: Architecture Outputs
101
- _Populated after Session 5 completion_
102
-
103
- ### Target Architecture
104
- <!-- Platform, architecture style, ownership -->
105
-
106
- ### Technology Stack
107
- <!-- Full stack listing -->
108
-
109
- ### Key Components
110
- <!-- Module/component list -->
111
-
112
- ### Integration Points
113
- <!-- External system integrations -->
114
-
115
- ### ADRs
116
- <!-- Architecture Decision Records -->
117
-
118
- ### Domain Model / Entity Register
119
- <!-- Entity, key attributes, relationships, owner module -->
120
-
121
- ---
122
-
123
- ## Session 6: Security Outputs
124
- _Populated after Session 6 completion_
125
-
126
- ### Data Classification
127
- <!-- Data sensitivity levels -->
128
-
129
- ### Compliance Framework
130
- <!-- Standards and regulations -->
131
-
132
- ### Encryption
133
- <!-- In-transit, at-rest, key management -->
134
-
135
- ### Network & Access
136
- <!-- Network security approach -->
137
-
138
- ### Audit Logging
139
- <!-- Logging strategy and retention -->
140
-
141
- ### Availability
142
- <!-- SLA targets -->
143
-
144
- ---
145
-
146
- ## Session 7: Identity Management Outputs
147
- _Populated after Session 7 completion_
148
-
149
- ### RBAC Model
150
- <!-- Roles and permissions summary -->
151
-
152
- ### IdP Integration
153
- <!-- Identity provider details -->
154
-
155
- ### User Lifecycle
156
- <!-- Provisioning approach -->
157
-
158
- ---
159
-
160
- ## Session 8: Integration Outputs
161
- _Populated after Session 8 completion_
162
-
163
- ### External Systems
164
- <!-- Systems and their interfaces -->
165
-
166
- ### Interface Patterns
167
- <!-- Chosen patterns and protocols -->
168
-
169
- ### Data Exchange
170
- <!-- Key data flows and formats -->
171
-
172
- ---
173
-
174
- ## Session 9: QA Outputs
175
- _Populated after Session 9 completion_
176
-
177
- ### Test Strategy
178
- <!-- Testing approach -->
179
-
180
- ### Tooling
181
- <!-- Test management and automation tools -->
182
-
183
- ### Test Environments
184
- <!-- Environment list and purposes -->
185
-
186
- ### Quality Gates
187
- <!-- Gate definitions -->
188
-
189
- ### UAT
190
- <!-- UAT participants, period, criteria -->
191
-
192
- ---
193
-
194
- ## Session 10: Infrastructure Outputs
195
- _Populated after Session 10 completion_
196
-
197
- ### Infrastructure
198
- <!-- Cloud/hosting setup -->
199
-
200
- ### Deployment
201
- <!-- Deployment strategy -->
202
-
203
- ### Monitoring
204
- <!-- Monitoring and alerting approach -->
205
-
206
- ### Backup & DR
207
- <!-- Backup and disaster recovery -->
208
-
209
- ### Go-Live Readiness
210
- <!-- Readiness checklist status -->
211
-
212
- ---
213
-
214
- ## Session 11: Roadmap Outputs
215
- _Populated after Session 11 completion_
216
-
217
- ### Project Phases
218
- <!-- Phase breakdown -->
219
-
220
- ### Timeline
221
- <!-- Sprint cadence and key dates -->
222
-
223
- ### MVP Scope (Confirmed)
224
- <!-- Must-have vs nice-to-have -->
225
-
226
- ### Build Order
227
- <!-- Sprint-by-sprint plan -->
228
-
229
- ### Key Milestones
230
- <!-- Milestone dates -->
231
-
232
- ### Risks
233
- <!-- Top risks and mitigations -->
234
-
235
- ---
236
-
237
- ## Session 12: Delivery Model Outputs
238
- _Populated after Session 12 completion_
239
-
240
- ### Team Structure
241
- <!-- Key roles and people -->
242
-
243
- ### Governance
244
- <!-- Governance framework summary -->
245
-
246
- ### Ceremonies
247
- <!-- Sprint cadence and meetings -->
248
-
249
- ### Support Model
250
- <!-- Post-go-live support approach -->
251
-
252
- ---
253
-
254
- ## Session 13: Wrap-up Outputs
255
- _Populated after Session 13 completion_
256
-
257
- ### Decision Readiness
258
- <!-- Go / Conditional Go / No-Go assessment -->
259
-
260
- ### Open Items
261
- <!-- Items carried forward -->
262
-
263
- ### Next Steps
264
- <!-- Transition plan to execution -->
265
- ```
266
-