@pareto4/pp-core 1.22.0 → 1.23.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/bin/install.js +205 -28
  3. package/commands/pp-help.md +2 -1
  4. package/gemini-extension.json +1 -1
  5. package/hooks/dist/pp-check-update-worker.js +1 -1
  6. package/hooks/dist/pp-context-monitor.js +3 -3
  7. package/hooks/dist/pp-statusline.js +88 -14
  8. package/hooks/dist/pp-update-banner.js +44 -4
  9. package/hooks/dist/pp-workflow-guard.js +3 -3
  10. package/hooks/pp-check-update-worker.js +1 -1
  11. package/hooks/pp-context-monitor.js +3 -3
  12. package/hooks/pp-statusline.js +88 -14
  13. package/hooks/pp-update-banner.js +44 -4
  14. package/hooks/pp-workflow-guard.js +3 -3
  15. package/package.json +1 -1
  16. package/pp-core/bin/lib/audience-command.cjs +271 -0
  17. package/pp-core/bin/lib/audience.cjs +293 -0
  18. package/pp-core/bin/lib/commands.cjs +26 -17
  19. package/pp-core/bin/lib/discovery-charter.cjs +13 -1
  20. package/pp-core/bin/lib/discovery-input-check.cjs +11 -11
  21. package/pp-core/bin/lib/discovery-session-check.cjs +7 -7
  22. package/pp-core/bin/lib/discovery-status.cjs +419 -0
  23. package/pp-core/bin/lib/explain-command.cjs +48 -0
  24. package/pp-core/bin/lib/gate-card.cjs +97 -0
  25. package/pp-core/bin/lib/hook-messages.cjs +132 -0
  26. package/pp-core/bin/lib/init-contract.cjs +116 -76
  27. package/pp-core/bin/lib/init-interactive.cjs +110 -49
  28. package/pp-core/bin/lib/init.cjs +44 -3
  29. package/pp-core/bin/lib/io.cjs +33 -0
  30. package/pp-core/bin/lib/message-labels.cjs +75 -0
  31. package/pp-core/bin/lib/messages/core.cjs +20 -0
  32. package/pp-core/bin/lib/messages/discovery.cjs +267 -0
  33. package/pp-core/bin/lib/messages/gate.cjs +257 -0
  34. package/pp-core/bin/lib/messages/hook.cjs +114 -0
  35. package/pp-core/bin/lib/messages/init.cjs +513 -0
  36. package/pp-core/bin/lib/messages/progress.cjs +110 -0
  37. package/pp-core/bin/lib/messages.cjs +208 -0
  38. package/pp-core/bin/lib/vault-command-router.cjs +16 -3
  39. package/pp-core/bin/lib/violation-render.cjs +78 -0
  40. package/pp-core/bin/pp-tools.cjs +68 -23
  41. package/pp-core/bin/shared/config-schema.manifest.json +1 -0
  42. package/pp-core/references/audience-moments.md +119 -0
  43. package/pp-core/references/audience.md +114 -0
  44. package/pp-core/references/discovery-charter.md +2 -2
  45. package/pp-core/templates/project-charter.md +3 -4
  46. package/pp-core/workflows/add-phase.md +2 -0
  47. package/pp-core/workflows/add-tests.md +2 -0
  48. package/pp-core/workflows/add-todo.md +2 -0
  49. package/pp-core/workflows/ai-integration-phase.md +2 -0
  50. package/pp-core/workflows/audit-milestone.md +2 -0
  51. package/pp-core/workflows/autonomous.md +2 -0
  52. package/pp-core/workflows/check-todos.md +2 -0
  53. package/pp-core/workflows/code-review-fix.md +2 -0
  54. package/pp-core/workflows/code-review.md +2 -0
  55. package/pp-core/workflows/complete-milestone.md +10 -1
  56. package/pp-core/workflows/discovery-sprint/charter.md +3 -2
  57. package/pp-core/workflows/discovery-sprint/prefill.md +3 -0
  58. package/pp-core/workflows/discovery-sprint/prototype.md +14 -0
  59. package/pp-core/workflows/discovery-sprint/sessions/01-kick-off.md +4 -1
  60. package/pp-core/workflows/discovery-sprint/sessions/13-wrap-up.md +1 -1
  61. package/pp-core/workflows/discovery-sprint/vault-context.md +15 -0
  62. package/pp-core/workflows/discovery-sprint.md +14 -0
  63. package/pp-core/workflows/discovery-to-build.md +8 -2
  64. package/pp-core/workflows/discuss-phase-assumptions.md +2 -0
  65. package/pp-core/workflows/discuss-phase.md +1 -1
  66. package/pp-core/workflows/edit-phase.md +2 -0
  67. package/pp-core/workflows/eval-review.md +2 -0
  68. package/pp-core/workflows/execute-phase/steps/check-query-gate.md +25 -1
  69. package/pp-core/workflows/execute-phase/steps/vault-fetch.md +1 -0
  70. package/pp-core/workflows/execute-phase/steps/vault-load-gate.md +2 -0
  71. package/pp-core/workflows/execute-phase.md +1 -1
  72. package/pp-core/workflows/execute-plan.md +2 -0
  73. package/pp-core/workflows/extract-learnings.md +2 -0
  74. package/pp-core/workflows/help/modes/business.md +56 -0
  75. package/pp-core/workflows/help.md +12 -2
  76. package/pp-core/workflows/import.md +10 -1
  77. package/pp-core/workflows/ingest-docs.md +2 -0
  78. package/pp-core/workflows/init.md +17 -1
  79. package/pp-core/workflows/insert-phase.md +2 -0
  80. package/pp-core/workflows/list-workspaces.md +2 -0
  81. package/pp-core/workflows/manager.md +2 -0
  82. package/pp-core/workflows/map-codebase.md +2 -0
  83. package/pp-core/workflows/milestone-summary.md +2 -0
  84. package/pp-core/workflows/new-milestone.md +10 -1
  85. package/pp-core/workflows/new-project.md +12 -2
  86. package/pp-core/workflows/new-workspace.md +2 -0
  87. package/pp-core/workflows/next.md +8 -0
  88. package/pp-core/workflows/plan-milestone-gaps.md +10 -1
  89. package/pp-core/workflows/plan-phase.md +2 -1
  90. package/pp-core/workflows/plan-review-convergence.md +1 -1
  91. package/pp-core/workflows/progress.md +10 -0
  92. package/pp-core/workflows/quick.md +11 -1
  93. package/pp-core/workflows/remove-phase.md +2 -0
  94. package/pp-core/workflows/remove-workspace.md +2 -0
  95. package/pp-core/workflows/resume-project.md +25 -0
  96. package/pp-core/workflows/review.md +2 -0
  97. package/pp-core/workflows/scan.md +2 -0
  98. package/pp-core/workflows/secure-phase.md +2 -0
  99. package/pp-core/workflows/settings.md +41 -0
  100. package/pp-core/workflows/ship.md +2 -0
  101. package/pp-core/workflows/spec-phase.md +1 -1
  102. package/pp-core/workflows/ui-phase.md +2 -0
  103. package/pp-core/workflows/ui-review.md +2 -0
  104. package/pp-core/workflows/ultraplan-phase.md +2 -0
  105. package/pp-core/workflows/validate-phase.md +2 -0
  106. package/pp-core/workflows/vault-review.md +2 -0
  107. package/pp-core/workflows/verify-phase.md +2 -0
  108. package/pp-core/workflows/verify-work.md +2 -0
  109. package/scripts/affected-tests-lib.cjs +26 -12
  110. package/scripts/ci-release-only.cjs +158 -0
  111. package/scripts/live-runs/driver.cjs +326 -0
  112. package/scripts/live-runs/run.cjs +906 -0
  113. package/scripts/live-runs/scenarios.cjs +326 -0
  114. package/scripts/live-runs/scratch-project.cjs +132 -0
  115. package/scripts/live-runs/scrub.cjs +291 -0
  116. package/scripts/live-runs/turn-guard.cjs +107 -0
  117. package/scripts/live-runs/walk-setup.cjs +198 -0
  118. package/scripts/run-tests.cjs +151 -135
  119. package/scripts/test-env.cjs +64 -0
@@ -102,13 +102,16 @@ _PP_SHIM_NAME="pp-tools.cjs"; _pp_root() { ( for _v in $(env | sed -n 's/^\(GIT_
102
102
  [ -z "${ZSH_VERSION:-}" ] || emulate -R sh
103
103
  GATE_RESULT=$(pp_run check "${GATE_QUERY}" ${GATE_POSITIONAL_ARG:+"${GATE_POSITIONAL_ARG}"} ${GATE_POSITIONAL_ARG_2:+"${GATE_POSITIONAL_ARG_2}"} ${GATE_WS:+--ws} ${GATE_WS:+"${GATE_WS}"} ${GATE_STAGE:+--stage} ${GATE_STAGE:+"${GATE_STAGE}"} ${GATE_UNPAIRED:+--unpaired} ${GATE_UNPAIRED:+"${GATE_UNPAIRED}"} --raw)
104
104
  CHECK_EXIT=$?
105
+ GATE_CARDS=$(pp_run gate-card "${GATE_QUERY}" 2>/dev/null | node -e "const d=require('fs').readFileSync(0,'utf-8');const c=String.fromCharCode;try{const j=JSON.parse(d);if(j&&typeof j==='object'&&Array.isArray(j)===false)process.stdout.write(JSON.stringify(j).replace(new RegExp('['+c(127)+'-'+c(159)+c(8232,8233)+']','g'),(x)=>'\\\\u'+('000'+x.charCodeAt(0).toString(16)).slice(-4)));}catch{}" || true)
105
106
  if [ "$CHECK_EXIT" -ne 0 ] || [ -z "$GATE_RESULT" ] || ! printf '%s' "$GATE_RESULT" | node -e "const j=JSON.parse(require('fs').readFileSync(0,'utf-8'));if(j===null||typeof j!=='object')process.exit(1)" 2>/dev/null; then
106
107
  echo "GATE_CHECK=failed"
108
+ if [ -n "$GATE_CARDS" ]; then printf 'GATE_CARDS=%s\n' "$GATE_CARDS"; fi
107
109
  else
108
110
  GATE_BLOCK=$(printf '%s' "$GATE_RESULT" | node -e "const d=require('fs').readFileSync(0,'utf-8');try{process.stdout.write(String(JSON.parse(d).block===true));}catch{process.stdout.write('true');}")
109
111
  GATE_MESSAGE=$(printf '%s' "$GATE_RESULT" | node -e "const d=require('fs').readFileSync(0,'utf-8');const c=String.fromCharCode;const r=(a,b)=>c(a)+'-'+c(b);try{const m=JSON.parse(d).message;process.stdout.write(typeof m==='string'?m.replace(new RegExp('['+r(0,8)+c(11,12)+r(14,31)+r(127,132)+r(134,159)+']','g'),' ').replace(new RegExp(c(13,10)+'|['+c(13,10,133,8232,8233)+']','g'),c(10)+' '):'');}catch{process.stdout.write('');}")
110
112
  echo "GATE_CHECK=ok"
111
113
  echo "GATE_BLOCK=$GATE_BLOCK"
114
+ if [ -n "$GATE_CARDS" ]; then printf 'GATE_CARDS=%s\n' "$GATE_CARDS"; fi
112
115
  if [ -n "$GATE_MESSAGE" ]; then printf 'GATE_MESSAGE=%s\n' "$GATE_MESSAGE"; fi
113
116
  fi
114
117
  ```
@@ -128,6 +131,16 @@ routes on** (16 review W-1, D-97). It prints exactly one of two shapes:
128
131
  verdict is the one `GATE_BLOCK=` line at column 0, and a message cannot print a second one (16
129
132
  review iteration 3 WR-01).
130
133
 
134
+ **The audience card line (Phase 43, D-11).** For a business user or business engineer, either shape
135
+ carries one more line, `GATE_CARDS=` followed by one line of JSON from `pp_run gate-card`: the cards
136
+ for this query by state, each with a `code` and a `text`. It comes before any `GATE_MESSAGE=` line,
137
+ so the message is still last. The fence prints the line only when the verb's output parses as one
138
+ JSON object, and it re-serialises that object with DEL, the C1 controls (NEL among them) and the
139
+ Unicode line separators escaped, so the line is always exactly one line and can never begin a
140
+ verdict line of its own (43 review WR-02). For a developer the verb prints nothing and no such line appears; an
141
+ engine without the verb prints nothing either, and the lines below apply as written. The call stays
142
+ in this fence because it is the only one with the launcher.
143
+
131
144
  The verdict is computed here, in the shell that ran the check, for two measured reasons. **The
132
145
  engine:** this is the only fence in this file that carries the launcher preamble (the launcher
133
146
  generator keeps ONE preamble per file, in its first `pp_run` fence, and strips any other), so a
@@ -200,6 +213,9 @@ engine): with nothing printed there is no verdict to read. Route it by the hook'
200
213
  hook, and — this is an imperative, not a preference — **do NOT read a verdict.** The fence
201
214
  prints none on this path, and none may be inferred.
202
215
 
216
+ When step 1 printed a `GATE_CARDS=` line, print the `error` card's `text` and then `Ref: ` with its
217
+ `code` instead of the ⚠ line on either path. Nothing else changes: the halt block on `halt`, the next hook on `skip`, and no verdict read.
218
+
203
219
  Merging these two steps is the fail-open this gate exists to close: if a non-zero exit were read as
204
220
  a verdict, `onError: skip` would swallow a genuine block as a command warning.
205
221
 
@@ -233,6 +249,12 @@ behind the command-error test; it exists so that a future edit which removes tha
233
249
 
234
250
  - **`GATE_BLOCK` is `false` → continue.** No status line.
235
251
 
252
+ When step 1 printed a `GATE_CARDS=` line, print instead of the ⚠ or ℹ line the matching card's `text`
253
+ (`blocked` on the halt, `advisory` for the advisory line), then `Ref: ` with its `code`, then — when
254
+ step 1 printed a `GATE_MESSAGE=` — `Details:` followed by that message (D-10, D-12). The halt block
255
+ below runs unchanged. The output-independence rule applies to the card exactly as to the lines it
256
+ replaces.
257
+
236
258
  **Output-independence rule (a later plan's byte-identical regression pin depends on this).** On
237
259
  every NON-halting path, the enforcer's printed output must be **identical** whether `GATE_BLOCKING`
238
260
  is `true` or `false`. `blocking` decides one thing only: whether a `true` block halts. It must never
@@ -276,7 +298,9 @@ of step 1's output, its later lines indented by two spaces — it is already ope
276
298
  multi-line text. A gate that has
277
299
  something to tell the operator says it on every run, not only when its verdict is bad. This rule is
278
300
  preserved word-for-word in effect from the ship.md loop this file replaced; a later plan makes both
279
- the vault gate's actionable block text and its success-path observability ride on it.
301
+ the vault gate's actionable block text and its success-path observability ride on it. On a run
302
+ that printed a card under step 2, its `Details:` text is this passthrough, so
303
+ do not print the message a second time.
280
304
 
281
305
  ## Direct-query mode
282
306
 
@@ -105,6 +105,7 @@ if [ "$VAULT_REQUIRED" = "true" ] && [ "$VAULT_LOAD_OK" = "false" ]; then
105
105
  # summary all hard-stop (D-VH-4). Print the failure verbatim, then the named
106
106
  # halt token and a non-zero exit — the same two halves the extracted enforcer
107
107
  # uses, so an agent stops and an unattended runner sees the exit code.
108
+ { pp_run gate-card vault.fetch --state blocked --details 2>/dev/null || true; } >&2
108
109
  echo "✗ vault could not be loaded and vault.required is true (STRICT-03)" >&2
109
110
  if [ -n "$VAULT_FETCH_REASON" ]; then echo " fetch: $VAULT_FETCH_REASON" >&2; fi
110
111
  if [ -n "$VAULT_SUMMARY_ERROR" ]; then echo " summary: $VAULT_SUMMARY_ERROR" >&2; fi
@@ -107,6 +107,8 @@ Invocation mode never changes any of the above. `--auto` / `--chain` selects how
107
107
  surfaced, never whether the run proceeds. Mode-dependent gate behaviour was the precise shape of the
108
108
  hole this phase closes, so it is stated here rather than left to be re-derived.
109
109
 
110
+ When the payload carries `audience` (business or engineer), ask the fallback question below in the form `${PP_TOOLS%/bin/pp-tools.cjs}/references/audience-moments.md` gives for that audience (§ Vault fallback question); the explicit typed `confirmed` acknowledgment stays exactly as each column requires.
111
+
110
112
  ---
111
113
 
112
114
  ## §8 Message table — plan:pre column (`VAULT_GATE_POINT` == `plan`)
@@ -91,7 +91,7 @@ Parse JSON for: `executor_model`, `verifier_model`, `commit_docs`, `parallelizat
91
91
 
92
92
  **Model resolution:** If `executor_model` is `"inherit"`, omit the `model=` parameter from all `Agent()` calls — do NOT pass `model="inherit"` to Agent. Omitting the `model=` parameter causes Claude Code to inherit the current orchestrator model automatically. Only set `model=` when `executor_model` is an explicit model name (e.g., `"claude-sonnet-4-6"`, `"claude-opus-4-7"`).
93
93
 
94
- **If `response_language` is set:** Include `response_language: {value}` in all spawned subagent prompts so any user-facing output stays in the configured language.
94
+ **Audience:** if `audience` is set, Read and follow `{audience_ref}`. Reply in any `response_language` and pass it to subagents; code and paths stay as is.
95
95
 
96
96
  Read runtime/worktree config and fail closed before any executor dispatch:
97
97
 
@@ -48,6 +48,8 @@ INIT=$(pp_run query init.execute-phase "${PHASE}")
48
48
  if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
49
49
  ```
50
50
 
51
+ **Audience:** if `audience` is set, Read and follow `{audience_ref}`. Reply in any `response_language` and pass it to subagents; code and paths stay as is.
52
+
51
53
  Extract from init JSON: `executor_model`, `commit_docs`, `sub_repos`, `phase_dir`, `phase_number`, `plans`, `summaries`, `incomplete_plans`, `state_path`, `config_path`.
52
54
 
53
55
  If `.planning/` missing: error.
@@ -21,6 +21,8 @@ INIT=$(pp_run query init.phase-op "${PHASE_ARG}")
21
21
  if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
22
22
  ```
23
23
 
24
+ **Audience:** if `audience` is set, Read and follow `{audience_ref}`. Reply in any `response_language` and pass it to subagents; code and paths stay as is.
25
+
24
26
  Parse from init JSON: `phase_found`, `phase_dir`, `phase_number`, `phase_name`, `padded_phase`.
25
27
 
26
28
  If phase not found, exit with error: "Phase {PHASE_ARG} not found."
@@ -0,0 +1,56 @@
1
+ <purpose>
2
+ Help page for a business user, shown for `/pp:help` and `/pp:help --brief`. Output ONLY the `<reference>` content below, after the audience header line help.md prints. No other additions.
3
+ </purpose>
4
+
5
+ <reference>
6
+ # pp-core — your project, step by step
7
+
8
+ Start with the Discovery Sprint. When its Project Charter is signed, the build begins, and you test the result yourself.
9
+
10
+ ## 1. The Discovery Sprint
11
+
12
+ | Command | What it does |
13
+ |---|---|
14
+ | `/pp:discovery` | See where the sprint stands and which session comes next |
15
+ | `/pp:discovery <n>` | Hold session `<n>` (1 to 13), or carry on with it |
16
+ | `/pp:discovery prototype` | Build the clickable prototype from sessions 1 to 4 |
17
+ | `/pp:discovery charter` | Record the signatures on the Project Charter, or redraft it |
18
+ | `/pp:discovery-to-build` | Once the Project Charter is signed, start the build from what the sprint agreed |
19
+
20
+ ## 2. Where things stand
21
+
22
+ | Command | What it does |
23
+ |---|---|
24
+ | `/pp:progress` | Where the project stands and what comes next |
25
+ | `/pp:resume-work` | Pick up where you left off |
26
+
27
+ ## 3. Your acceptance test
28
+
29
+ | Command | What it does |
30
+ |---|---|
31
+ | `/pp:verify-work <N>` | Try out a finished stage yourself and say whether it does what was agreed |
32
+
33
+ ## Other commands
34
+
35
+ The build team uses these. You can use them too.
36
+
37
+ | Command | What it does |
38
+ |---|---|
39
+ | `/pp:init` | Set up a new project: repository, remote and the link to your organisation's standards |
40
+ | `/pp:new-project` | Start a project from scratch: questions, research, requirements and a plan of stages |
41
+ | `/pp:map-codebase` | Read an existing codebase so the work fits it |
42
+ | `/pp:discuss-phase <N>` | Talk through what stage `<N>` should do before it is planned |
43
+ | `/pp:plan-phase <N>` | Write the detailed plan for stage `<N>` |
44
+ | `/pp:execute-phase <N>` | Build stage `<N>` |
45
+ | `/pp:quick` | A small one-off task, tracked and saved |
46
+ | `/pp:fast "<task>"` | A tiny change, done straight away |
47
+ | `/pp:debug "<symptom>"` | Track down a problem step by step; it picks up again after a break |
48
+ | `/pp:capture` | Save an idea, a to-do or a note |
49
+ | `/pp:ship <N>` | Open a review request for a finished stage |
50
+ | `/pp:help --full` | Every command and every option |
51
+ | `/pp:help <topic>` | One section only |
52
+ | `/pp:help --brief <topic>` | A short summary of one topic |
53
+ | `npx @pareto4/pp-core@latest` | Update pp-core |
54
+
55
+ Topics: `workflow` · `planning` · `execute` · `quick` · `debug` · `capture` · `ship` · `config` · `milestones` · `spike` · `sketch` · `review` · `audit` · `progress`
56
+ </reference>
@@ -1,7 +1,17 @@
1
1
  <purpose>
2
- Display pp-core command help at the tier the user asked for. Output ONLY the reference content of the chosen mode. Do NOT add project-specific analysis, git status, next-step suggestions, or any commentary beyond the reference.
2
+ Display pp-core command help at the tier the user asked for. Output ONLY the reference content of the chosen mode, preceded by the one audience header line from `<audience>` when that section calls for it. Do NOT add project-specific analysis, git status, next-step suggestions, or any commentary beyond the reference.
3
3
  </purpose>
4
4
 
5
+ <audience>
6
+ ```bash
7
+ _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
8
+ pp_run query audience fields 2>/dev/null
9
+ ```
10
+ Run the block above once, before routing. It prints one JSON object for a business user or a business engineer and nothing for a developer. If it printed nothing, or failed in any way, say nothing about it and route exactly as below. If it printed JSON, output the line for its `"audience"` value first, then a blank line:
11
+ - `"business"`: You're using pp-core as a business user. To change this, run `/pp:settings`.
12
+ - `"engineer"`: You're using pp-core as a business engineer. To change this, run `/pp:settings`.
13
+ For `"business"` only, the empty / unset row and the `--brief` alone row read `workflows/help/modes/business.md` instead of the file the table names. Every other row, every row for `"engineer"`, and any other value read the file the table names, unchanged.
14
+ </audience>
5
15
  <progressive_disclosure>
6
16
  **Mode files are lazy-loaded.** Read only the one mode file that matches `$ARGUMENTS`, then output its `<reference>` body verbatim.
7
17
 
@@ -20,5 +30,5 @@ Argument parsing rules:
20
30
  - Multiple flags: `--brief` and `--full` are mutually exclusive — if both appear *without* a topic, prefer `--full`.
21
31
  - `--brief` combined with a topic invokes `topic.md` in compact scope; `--full` combined with a topic invokes `topic.md` in full scope (the default topic behavior). When passing arguments through to `topic.md`, retain the `--brief` flag so the mode can pick the right scope.
22
32
 
23
- After loading the chosen mode, emit its `<reference>` block content directly. No additions, no project context, no suggestions.
33
+ After loading the chosen mode, emit its `<reference>` block content directly, after the audience header line if `<audience>` printed one. No other additions, no project context, no suggestions.
24
34
  </progressive_disclosure>
@@ -8,6 +8,13 @@ Future: `--prd` mode (PRD extraction into PROJECT.md + REQUIREMENTS.md + ROADMAP
8
8
 
9
9
  ---
10
10
 
11
+ ```bash
12
+ _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
13
+ pp_run query audience fields
14
+ ```
15
+
16
+ **Audience, before any question:** run the block above. If it prints `pp-tools.cjs not found`, show that error and stop. If it exits non-zero for any other reason, tell the person the audience setting could not be read (show the error) and continue; if it prints JSON, apply the **Audience** line below to it now.
17
+
11
18
  <step name="banner">
12
19
 
13
20
  Display the stage banner:
@@ -177,12 +184,14 @@ Apply pp-core naming convention for the output filename:
177
184
  Determine the target directory by querying `init.phase-op` for the phase number extracted in `plan_read_input`. This ensures the `project_code` prefix from `.planning/config.json` is applied:
178
185
 
179
186
  ```bash
180
- _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
187
+ command -v pp_run >/dev/null 2>&1 || { echo "ERROR: pp_run is not on PATH; prepend the resolver line from the top block to this block and run it again" >&2; exit 1; }
181
188
  INIT=$(pp_run query init.phase-op "{NN}")
182
189
  if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
183
190
  expected_phase_dir=$(echo "$INIT" | node -e "process.stdout.write(JSON.parse(require('fs').readFileSync('/dev/stdin','utf8')).expected_phase_dir)")
184
191
  ```
185
192
 
193
+ **Audience:** if `audience` is set, Read and follow `{audience_ref}`. Reply in any `response_language` and pass it to subagents; code and paths stay as is.
194
+
186
195
  If the directory does not exist, create it:
187
196
  ```bash
188
197
  mkdir -p "${expected_phase_dir}"
@@ -58,6 +58,8 @@ INIT=$(pp_run init ingest-docs)
58
58
  if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
59
59
  ```
60
60
 
61
+ **Audience:** if `audience` is set, Read and follow `{audience_ref}`. Reply in any `response_language` and pass it to subagents; code and paths stay as is.
62
+
61
63
  Parse `project_exists`, `planning_exists`, `has_git`, `git_worktree_root`, `in_nested_subdir`, `project_path` from INIT.
62
64
 
63
65
  **Auto-detect MODE** if not set:
@@ -31,6 +31,13 @@ Read all files referenced by the invoking prompt's execution_context before star
31
31
 
32
32
  <process>
33
33
 
34
+ ```bash
35
+ _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
36
+ pp_run query audience fields
37
+ ```
38
+
39
+ **Audience, before any question:** run the block above. If it prints `pp-tools.cjs not found`, show that error and stop. If it exits non-zero for any other reason, tell the person the audience setting could not be read (show the error) and continue; if it prints JSON, apply the **Audience** line below to it now.
40
+
34
41
  ## Text mode (resolve before any prompt — WR-02)
35
42
 
36
43
  Resolve `TEXT_MODE` here, **before Step 0**, because the Step 0 drift prompt is the first
@@ -53,7 +60,7 @@ the app is on the **latest** platform before any building starts — bumping aft
53
60
  milestone is built is far more expensive.
54
61
 
55
62
  ```bash
56
- _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
63
+ command -v pp_run >/dev/null 2>&1 || { echo "ERROR: pp_run is not on PATH; prepend the resolver line from the top block to this block and run it again" >&2; exit 1; }
57
64
  # Gate on presence via reader — absent file → {present:false} exit 0 (inert, step skipped, no jq)
58
65
  if [ "$(pp_run query platform-bindings --pick present 2>/dev/null)" = "true" ]; then
59
66
  PINNED=$(pp_run query platform-bindings --pick platform.tag)
@@ -82,6 +89,12 @@ step is skipped entirely.
82
89
 
83
90
  ---
84
91
 
92
+ ## 0.5. Who you are (first run only — D-06)
93
+
94
+ Run `pp_run query audience status --raw`. If `needs_choice` is `true`, show its `prompt` exactly as printed and wait for the reply. Then run `pp_run query audience answer '<reply>'` (the reply in single quotes, with any single quote in it removed) and show its output. If that fails, show the prompt once more, then continue either way. Never write `~/.gsd/person.json` yourself. With nobody to answer (a headless run), skip this step and save nothing.
95
+
96
+ ---
97
+
85
98
  ## 1. Worktree-aware git init
86
99
 
87
100
  Parse the init signals by running the query below. `init.ingest-docs` takes no argument
@@ -90,10 +103,13 @@ and emits the git-state signals this step needs (`has_git`, `in_nested_subdir`,
90
103
  `init.execute-phase ""`: it refuses an empty phase, and the `{}` fallback would disable the guard.
91
104
 
92
105
  ```bash
106
+ command -v pp_run >/dev/null 2>&1 || { echo "ERROR: pp_run is not on PATH; prepend the resolver line from the top block to this block and run it again" >&2; exit 1; }
93
107
  INIT=$(pp_run query init.ingest-docs 2>/dev/null || echo '{}')
94
108
  if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
95
109
  ```
96
110
 
111
+ **Audience:** if `audience` is set, Read and follow `{audience_ref}`. Reply in any `response_language` and pass it to subagents; code and paths stay as is.
112
+
97
113
  Extract from the JSON: `has_git`, `in_nested_subdir`, `git_worktree_root`.
98
114
 
99
115
  Apply the `#3491` guard (never nest `.git` inside an existing worktree):
@@ -39,6 +39,8 @@ INIT=$(pp_run query init.phase-op "${after_phase}")
39
39
  if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
40
40
  ```
41
41
 
42
+ **Audience:** if `audience` is set, Read and follow `{audience_ref}`. Reply in any `response_language` and pass it to subagents; code and paths stay as is.
43
+
42
44
  Check `roadmap_exists` from init JSON. If false:
43
45
  ```
44
46
  ERROR: No roadmap found (.planning/ROADMAP.md)
@@ -16,6 +16,8 @@ INIT=$(pp_run query init.list-workspaces)
16
16
  if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
17
17
  ```
18
18
 
19
+ **Audience:** if `audience` is set, Read and follow `{audience_ref}`. Reply in any `response_language` and pass it to subagents; code and paths stay as is.
20
+
19
21
  Parse JSON for: `workspace_base`, `workspaces`, `workspace_count`.
20
22
 
21
23
  ## 2. Display
@@ -24,6 +24,8 @@ INIT=$(pp_run query init.manager)
24
24
  if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
25
25
  ```
26
26
 
27
+ **Audience:** if `audience` is set, Read and follow `{audience_ref}`. Reply in any `response_language` and pass it to subagents; code and paths stay as is.
28
+
27
29
  Parse JSON for: `milestone_version`, `milestone_name`, `phase_count`, `completed_count`, `in_progress_count`, `phases`, `recommended_actions`, `all_complete`, `waiting_signal`, `manager_flags`, and the optional trio `queued_milestone_version`, `queued_milestone_name`, `queued_phases` (added in SDK fix `2495-2496-2497` — may be absent on older SDK versions, treat missing as empty).
28
30
 
29
31
  `manager_flags` contains per-step passthrough flags from config:
@@ -75,6 +75,8 @@ if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
75
75
  AGENT_SKILLS_MAPPER=$(pp_run query agent-skills pp-codebase-mapper)
76
76
  ```
77
77
 
78
+ **Audience:** if `audience` is set, Read and follow `{audience_ref}`. Reply in any `response_language` and pass it to subagents; code and paths stay as is.
79
+
78
80
  Extract from init JSON: `mapper_model`, `commit_docs`, `codebase_dir`, `existing_maps`, `has_maps`, `codebase_dir_exists`, `subagent_timeout`, `date`.
79
81
  </step>
80
82
 
@@ -57,6 +57,8 @@ _PP_SHIM_NAME="pp-tools.cjs"; _pp_root() { ( for _v in $(env | sed -n 's/^\(GIT_
57
57
  pp_run query init.progress
58
58
  ```
59
59
 
60
+ **Audience:** if `audience` is set, Read and follow `{audience_ref}`. Reply in any `response_language` and pass it to subagents; code and paths stay as is.
61
+
60
62
  This returns phase metadata. For each phase in the milestone scope:
61
63
 
62
64
  - Read `{phase_dir}/{padded}-SUMMARY.md` if it exists — extract `one_liner`, `accomplishments`, `decisions`
@@ -23,6 +23,13 @@ Valid pp-core subagent types (use exact names — do not fall back to 'general-p
23
23
 
24
24
  <process>
25
25
 
26
+ ```bash
27
+ _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
28
+ pp_run query audience fields
29
+ ```
30
+
31
+ **Audience, before any question:** run the block above. If it prints `pp-tools.cjs not found`, show that error and stop. If it exits non-zero for any other reason, tell the person the audience setting could not be read (show the error) and continue; if it prints JSON, apply the **Audience** line below to it now.
32
+
26
33
  ## 1. Load Context
27
34
 
28
35
  Parse `$ARGUMENTS` before doing anything else:
@@ -186,7 +193,6 @@ blockers, todos) is preserved across the switch — symmetric with
186
193
  `milestone.complete`.
187
194
 
188
195
  ```bash
189
- _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
190
196
  pp_run query state.milestone-switch --milestone "v[X.Y]" --name "[Name]"
191
197
  ```
192
198
 
@@ -224,6 +230,7 @@ pp_run query commit "docs(planning): start milestone v[X.Y] [Name]" --files .pla
224
230
  ## 7. Load Context and Resolve Models
225
231
 
226
232
  ```bash
233
+ command -v pp_run >/dev/null 2>&1 || { echo "ERROR: pp_run is not on PATH; prepend the resolver line from the top block to this block and run it again" >&2; exit 1; }
227
234
  INIT=$(pp_run query init.new-milestone)
228
235
  if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
229
236
  AGENT_SKILLS_RESEARCHER=$(pp_run query agent-skills pp-project-researcher)
@@ -231,6 +238,8 @@ AGENT_SKILLS_SYNTHESIZER=$(pp_run query agent-skills pp-research-synthesizer)
231
238
  AGENT_SKILLS_ROADMAPPER=$(pp_run query agent-skills pp-roadmapper)
232
239
  ```
233
240
 
241
+ **Audience:** if `audience` is set, Read and follow `{audience_ref}`. Reply in any `response_language` and pass it to subagents; code and paths stay as is.
242
+
234
243
  Extract from init JSON: `researcher_model`, `synthesizer_model`, `roadmapper_model`, `commit_docs`, `research_enabled`, `current_milestone`, `project_exists`, `roadmap_exists`, `latest_completed_milestone`, `phase_dir_count`, `phase_archive_path`, `agents_installed`, `missing_agents`.
235
244
 
236
245
  **If `agents_installed` is false:** Display a warning before proceeding:
@@ -52,6 +52,13 @@ The document should describe what you want to build.
52
52
 
53
53
  <process>
54
54
 
55
+ ```bash
56
+ _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
57
+ pp_run query audience fields
58
+ ```
59
+
60
+ **Audience, before any question:** run the block above. If it prints `pp-tools.cjs not found`, show that error and stop. If it exits non-zero for any other reason, tell the person the audience setting could not be read (show the error) and continue; if it prints JSON, apply the **Audience** line below to it now.
61
+
55
62
  ## 0. Platform-version preflight (Pareto satellite repos)
56
63
 
57
64
  **Runs before Setup. Inert for non-Pareto projects** — gated entirely on
@@ -64,8 +71,8 @@ moment to confirm the app is on the **latest** platform before any building
64
71
  starts — bumping after a milestone is built is far more expensive.
65
72
 
66
73
  ```bash
67
- _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
68
- # Resolve pp_run before Step 1 — reader required for platform-bindings preflight (BIND-04)
74
+ # pp_run comes from PATH (the audience block above exports it through CLAUDE_ENV_FILE) — reader required for platform-bindings preflight (BIND-04)
75
+ command -v pp_run >/dev/null 2>&1 || { echo "ERROR: pp_run is not on PATH; prepend the resolver line from the top block to this block and run it again" >&2; exit 1; }
69
76
 
70
77
  # Gate on presence via reader — absent file → {present:false} exit 0 (inert, step skipped, no jq)
71
78
  if [ "$(pp_run query platform-bindings --pick present 2>/dev/null)" = "true" ]; then
@@ -99,6 +106,7 @@ a no-op and this step is skipped entirely.
99
106
  **MANDATORY FIRST STEP — Execute these checks before ANY user interaction:**
100
107
 
101
108
  ```bash
109
+ command -v pp_run >/dev/null 2>&1 || { echo "ERROR: pp_run is not on PATH; prepend the resolver line from the top block to this block and run it again" >&2; exit 1; }
102
110
  INIT=$(pp_run query init.new-project)
103
111
  if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
104
112
  AGENT_SKILLS_RESEARCHER=$(pp_run query agent-skills pp-project-researcher)
@@ -106,6 +114,8 @@ AGENT_SKILLS_SYNTHESIZER=$(pp_run query agent-skills pp-research-synthesizer)
106
114
  AGENT_SKILLS_ROADMAPPER=$(pp_run query agent-skills pp-roadmapper)
107
115
  ```
108
116
 
117
+ **Audience:** if `audience` is set, Read and follow `{audience_ref}`. Reply in any `response_language` and pass it to subagents; code and paths stay as is.
118
+
109
119
  Parse JSON for: `researcher_model`, `synthesizer_model`, `roadmapper_model`, `commit_docs`, `project_exists`, `has_codebase_map`, `planning_exists`, `has_existing_code`, `has_package_file`, `is_brownfield`, `needs_codebase_map`, `has_git`, `git_worktree_root`, `in_nested_subdir`, `project_path`, `agents_installed`, `missing_agents`, `agent_runtime`, `agents_dir`, `required_agents`, `required_agents_installed`, `missing_required_agents`, `agent_skill_payloads_available`, `agent_skill_payload_agents`.
110
120
 
111
121
  **If `agents_installed` is false:** Display a warning before proceeding:
@@ -18,6 +18,8 @@ INIT=$(pp_run query init.new-workspace)
18
18
  if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
19
19
  ```
20
20
 
21
+ **Audience:** if `audience` is set, Read and follow `{audience_ref}`. Reply in any `response_language` and pass it to subagents; code and paths stay as is.
22
+
21
23
  Parse JSON for: `default_workspace_base`, `child_repos`, `child_repo_count`, `worktree_available`, `is_git_repo`, `cwd_repo_name`, `project_root`.
22
24
 
23
25
  ## 2. Parse Arguments
@@ -18,6 +18,14 @@ _PP_SHIM_NAME="pp-tools.cjs"; _pp_root() { ( for _v in $(env | sed -n 's/^\(GIT_
18
18
  pp_run query state.json 2>/dev/null || echo "{}"
19
19
  ```
20
20
 
21
+ **Discovery Sprint only:** before reading anything else, run:
22
+
23
+ ```bash
24
+ pp_run query discovery.status --raw
25
+ ```
26
+
27
+ If it prints JSON with `"discovery_only": true`, run `pp_run query discovery.status`, show its output exactly as printed, and stop. Do not start a session: a Discovery Sprint session is a live workshop with the client, so the person starts it with the command the view names. Skip the safety gates and the routing below and re-invoke nothing; this holds for `--auto` and `--force` too. If it prints `"discovery_only": false`, or the command fails, continue below exactly as before.
28
+
21
29
  Also read:
22
30
  - `.planning/STATE.md` — current phase, progress, plan counts
23
31
  - `.planning/ROADMAP.md` — milestone structure and phase list