@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.
- package/.claude-plugin/plugin.json +1 -1
- package/agents/pp-code-fixer.md +9 -5
- package/agents/pp-code-reviewer.md +1 -0
- package/agents/pp-codebase-mapper.md +3 -0
- package/agents/pp-debugger.md +3 -2
- package/agents/pp-executor.md +16 -7
- package/agents/pp-integration-checker.md +1 -0
- package/agents/pp-phase-researcher.md +13 -1
- package/agents/pp-plan-checker.md +3 -0
- package/agents/pp-planner.md +20 -1
- package/agents/pp-research-synthesizer.md +1 -1
- package/agents/pp-ui-auditor.md +1 -0
- package/agents/pp-ui-researcher.md +3 -1
- package/agents/pp-vault-reviewer.md +2 -0
- package/agents/pp-verifier.md +22 -10
- package/commands/pp-add-tests.md +1 -1
- package/commands/pp-debug.md +1 -0
- package/commands/pp-discovery.md +3 -2
- package/commands/pp-init.md +4 -3
- package/commands/pp-quick.md +3 -0
- package/commands/pp-review-backlog.md +2 -1
- package/gemini-extension.json +1 -1
- package/package.json +6 -3
- package/pareto-skills/_shared/pp-claude-md-protocol.md +1 -1
- package/pareto-skills/pp-project-setup/SKILL.md +18 -343
- package/pp-core/bin/lib/capability-registry.cjs +3 -3
- package/pp-core/bin/lib/check-command-router.cjs +60 -20
- package/pp-core/bin/lib/commands.cjs +79 -4
- package/pp-core/bin/lib/compose-bindings.cjs +97 -14
- package/pp-core/bin/lib/discovery-access.cjs +276 -0
- package/pp-core/bin/lib/discovery-charter.cjs +664 -0
- package/pp-core/bin/lib/discovery-deviations.cjs +264 -0
- package/pp-core/bin/lib/discovery-entities.cjs +323 -0
- package/pp-core/bin/lib/discovery-for-phase.cjs +628 -0
- package/pp-core/bin/lib/discovery-integrations.cjs +286 -0
- package/pp-core/bin/lib/discovery-migration.cjs +246 -0
- package/pp-core/bin/lib/discovery-phases.cjs +233 -0
- package/pp-core/bin/lib/discovery-processes.cjs +355 -0
- package/pp-core/bin/lib/discovery-research-track.cjs +5 -4
- package/pp-core/bin/lib/discovery-rollup.cjs +12 -8
- package/pp-core/bin/lib/discovery-rules.cjs +216 -0
- package/pp-core/bin/lib/discovery-screens.cjs +21 -3
- package/pp-core/bin/lib/discovery-session-check.cjs +264 -0
- package/pp-core/bin/lib/discovery-stories.cjs +273 -0
- package/pp-core/bin/lib/discovery-sweep.cjs +13 -4
- package/pp-core/bin/lib/discovery-table.cjs +55 -0
- package/pp-core/bin/lib/discovery-vault-check.cjs +37 -3
- package/pp-core/bin/lib/init-contract.cjs +48 -7
- package/pp-core/bin/lib/io.cjs +22 -0
- package/pp-core/bin/lib/vault-coordinates.cjs +1 -1
- package/pp-core/bin/lib/vault-index.cjs +18 -5
- package/pp-core/bin/lib/vault-standards-review.cjs +50 -2
- package/pp-core/bin/lib/vault-update.cjs +4 -0
- package/pp-core/bin/lib/vault.cjs +2 -2
- package/pp-core/bin/pp-tools.cjs +153 -5
- package/pp-core/org-profile.json +1 -1
- package/pp-core/references/autonomous-best-effort.md +3 -2
- package/pp-core/references/autonomous-lifecycle.md +1 -0
- package/pp-core/references/autonomous-smart-discuss.md +5 -1
- package/pp-core/references/discovery-access.md +112 -0
- package/pp-core/references/discovery-build-consumption.md +256 -0
- package/pp-core/references/discovery-charter.md +127 -0
- package/pp-core/references/discovery-data-model.md +145 -0
- package/pp-core/references/discovery-id-conventions.md +77 -8
- package/pp-core/references/discovery-integrations.md +151 -0
- package/pp-core/references/discovery-processes.md +190 -0
- package/pp-core/references/discovery-rebaseline.md +2 -2
- package/pp-core/references/discovery-research-track.md +5 -6
- package/pp-core/references/discovery-session-output.md +70 -0
- package/pp-core/references/discovery-standards.md +107 -0
- package/pp-core/references/discovery-traceability.md +2 -2
- package/pp-core/references/execute-mvp-tdd.md +3 -3
- package/pp-core/references/git-integration.md +57 -33
- package/pp-core/references/git-planning-commit.md +31 -9
- package/pp-core/references/phase-argument-parsing.md +1 -0
- package/pp-core/references/planner-discovery-extract.md +35 -0
- package/pp-core/references/planner-gap-closure.md +1 -0
- package/pp-core/references/planner-revision.md +3 -1
- package/pp-core/references/planner-tdd.md +4 -4
- package/pp-core/references/planning-config.md +3 -3
- package/pp-core/references/shell-portability.md +28 -0
- package/pp-core/references/tdd.md +20 -16
- package/pp-core/references/verifier-discovery-conformance.md +36 -0
- package/pp-core/references/worktree-path-safety.md +1 -0
- package/pp-core/templates/milestone.md +5 -5
- package/pp-core/templates/project-charter.md +161 -100
- package/pp-core/templates/project.md +3 -3
- package/pp-core/templates/requirements.md +18 -0
- package/pp-core/templates/verification-report.md +16 -0
- package/pp-core/workflows/add-backlog.md +1 -1
- package/pp-core/workflows/add-tests.md +5 -2
- package/pp-core/workflows/add-todo.md +3 -1
- package/pp-core/workflows/ai-integration-phase.md +2 -1
- package/pp-core/workflows/audit-fix.md +4 -3
- package/pp-core/workflows/audit-milestone.md +1 -0
- package/pp-core/workflows/autonomous.md +6 -0
- package/pp-core/workflows/check-todos.md +2 -1
- package/pp-core/workflows/cleanup.md +3 -1
- package/pp-core/workflows/code-review-fix.md +12 -5
- package/pp-core/workflows/code-review.md +15 -1
- package/pp-core/workflows/complete-milestone.md +13 -3
- package/pp-core/workflows/debug.md +2 -0
- package/pp-core/workflows/diagnose-issues.md +1 -1
- package/pp-core/workflows/discovery-sprint/charter.md +114 -0
- package/pp-core/workflows/discovery-sprint/prefill.md +1 -1
- package/pp-core/workflows/discovery-sprint/prototype.md +4 -4
- package/pp-core/workflows/discovery-sprint/session-13-gates.md +11 -1
- package/pp-core/workflows/discovery-sprint/sessions/01-kick-off.md +54 -7
- package/pp-core/workflows/discovery-sprint/sessions/02-as-is.md +31 -7
- package/pp-core/workflows/discovery-sprint/sessions/03-to-be.md +64 -37
- package/pp-core/workflows/discovery-sprint/sessions/04-ux-design.md +12 -3
- package/pp-core/workflows/discovery-sprint/sessions/05-architecture.md +45 -22
- package/pp-core/workflows/discovery-sprint/sessions/06-security.md +30 -15
- package/pp-core/workflows/discovery-sprint/sessions/07-identity.md +43 -25
- package/pp-core/workflows/discovery-sprint/sessions/08-integration.md +63 -24
- package/pp-core/workflows/discovery-sprint/sessions/09-qa.md +28 -13
- package/pp-core/workflows/discovery-sprint/sessions/10-infrastructure.md +35 -16
- package/pp-core/workflows/discovery-sprint/sessions/11-roadmap.md +32 -8
- package/pp-core/workflows/discovery-sprint/sessions/12-delivery-model.md +21 -18
- package/pp-core/workflows/discovery-sprint/sessions/13-wrap-up.md +29 -12
- package/pp-core/workflows/discovery-sprint/vault-context.md +14 -3
- package/pp-core/workflows/discovery-sprint.md +23 -23
- package/pp-core/workflows/discovery-to-build/steps/architecture-deliverables.md +81 -29
- package/pp-core/workflows/discovery-to-build/steps/{screen-inventory-gate.md → handoff-gates.md} +111 -3
- package/pp-core/workflows/discovery-to-build/templates/discovery-references.md +12 -9
- package/pp-core/workflows/discovery-to-build/templates/pp-handoff.md +27 -26
- package/pp-core/workflows/discovery-to-build.md +70 -34
- package/pp-core/workflows/discuss-phase/discovery.md +83 -0
- package/pp-core/workflows/discuss-phase/templates/context.md +4 -0
- package/pp-core/workflows/discuss-phase-assumptions.md +5 -3
- package/pp-core/workflows/discuss-phase.md +18 -10
- package/pp-core/workflows/docs-update.md +1 -0
- package/pp-core/workflows/eval-review.md +2 -1
- package/pp-core/workflows/execute-phase/steps/check-query-gate.md +7 -6
- package/pp-core/workflows/execute-phase/steps/cross-ai-delegation.md +1 -0
- package/pp-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +1 -0
- package/pp-core/workflows/execute-phase/steps/vault-fetch.md +12 -0
- package/pp-core/workflows/execute-phase.md +19 -7
- package/pp-core/workflows/execute-plan.md +18 -7
- package/pp-core/workflows/explore.md +1 -1
- package/pp-core/workflows/forensics.md +4 -2
- package/pp-core/workflows/health.md +1 -0
- package/pp-core/workflows/import.md +2 -1
- package/pp-core/workflows/ingest-docs.md +1 -0
- package/pp-core/workflows/init/steps/client-context-capture.md +1 -0
- package/pp-core/workflows/init/steps/github-provisioning.md +145 -0
- package/pp-core/workflows/init/steps/gitlab-provisioning.md +18 -4
- package/pp-core/workflows/init/steps/reachability-outcome.md +3 -1
- package/pp-core/workflows/init.md +56 -66
- package/pp-core/workflows/map-codebase.md +5 -1
- package/pp-core/workflows/milestone-summary.md +2 -1
- package/pp-core/workflows/mvp-phase.md +1 -0
- package/pp-core/workflows/new-milestone.md +9 -5
- package/pp-core/workflows/new-project.md +12 -11
- package/pp-core/workflows/new-workspace.md +1 -0
- package/pp-core/workflows/next.md +2 -1
- package/pp-core/workflows/pause-work.md +6 -4
- package/pp-core/workflows/plan-milestone-gaps.md +3 -1
- package/pp-core/workflows/plan-phase/steps/chunked-planning.md +1 -1
- package/pp-core/workflows/plan-phase/steps/discovery-extract.md +41 -0
- package/pp-core/workflows/plan-phase.md +36 -16
- package/pp-core/workflows/plan-review-convergence.md +2 -0
- package/pp-core/workflows/plant-seed.md +4 -2
- package/pp-core/workflows/pr-branch.md +2 -0
- package/pp-core/workflows/progress.md +5 -0
- package/pp-core/workflows/quick.md +11 -4
- package/pp-core/workflows/reapply-patches.md +3 -0
- package/pp-core/workflows/remove-phase.md +1 -1
- package/pp-core/workflows/resume-project.md +3 -0
- package/pp-core/workflows/review.md +7 -1
- package/pp-core/workflows/secure-phase.md +2 -1
- package/pp-core/workflows/session-report.md +1 -0
- package/pp-core/workflows/ship.md +8 -1
- package/pp-core/workflows/sketch-wrap-up.md +1 -1
- package/pp-core/workflows/sketch.md +3 -2
- package/pp-core/workflows/spec-phase.md +2 -1
- package/pp-core/workflows/spike-wrap-up.md +1 -1
- package/pp-core/workflows/spike.md +4 -3
- package/pp-core/workflows/sync-skills.md +5 -2
- package/pp-core/workflows/thread.md +3 -2
- package/pp-core/workflows/transition.md +6 -0
- package/pp-core/workflows/ui-phase.md +3 -1
- package/pp-core/workflows/ui-review.md +2 -1
- package/pp-core/workflows/ultraplan-phase.md +1 -0
- package/pp-core/workflows/undo.md +14 -10
- package/pp-core/workflows/update.md +5 -0
- package/pp-core/workflows/validate-phase.md +6 -3
- package/pp-core/workflows/vault-review.md +7 -1
- package/pp-core/workflows/vault-write-back.md +5 -0
- package/pp-core/workflows/verify-phase.md +5 -0
- package/pp-core/workflows/verify-work.md +8 -1
- package/scripts/prompt-injection-scan.sh +1 -1
- package/scripts/sync-runtime-launcher.cjs +115 -5
- package/pp-core/workflows/discovery-sprint/templates/context-template.md +0 -266
|
@@ -11,8 +11,8 @@ D-13 (gate on .platform-bindings.json via the Phase 7 reader — Step 2 now comp
|
|
|
11
11
|
writes this file too, not only reads it, Phase 34 INIT-01).
|
|
12
12
|
|
|
13
13
|
Provisioning is provider-aware (Phase 34 D-11/D-13): `resolveProvider` is the sole
|
|
14
|
-
authority for which provisioning path runs. The gated
|
|
15
|
-
|
|
14
|
+
authority for which provisioning path runs. The gated create recipe runs only when it
|
|
15
|
+
resolves to `gitlab` (`glab`, G-2…G-5) or `github` (`gh`, H-2…H-5); under any other provider (`azure` today) it is
|
|
16
16
|
**skipped, not failed**, and the run falls through to this same generic remote-wiring
|
|
17
17
|
path so the user still leaves with a wired remote (Phase 34 INIT-03).
|
|
18
18
|
|
|
@@ -31,13 +31,6 @@ Read all files referenced by the invoking prompt's execution_context before star
|
|
|
31
31
|
|
|
32
32
|
<process>
|
|
33
33
|
|
|
34
|
-
## Shim hoist
|
|
35
|
-
|
|
36
|
-
Resolve `pp_run` before any step — required for the platform-bindings preflight (D-13).
|
|
37
|
-
|
|
38
|
-
```bash
|
|
39
|
-
```
|
|
40
|
-
|
|
41
34
|
## Text mode (resolve before any prompt — WR-02)
|
|
42
35
|
|
|
43
36
|
Resolve `TEXT_MODE` here, **before Step 0**, because the Step 0 drift prompt is the first
|
|
@@ -91,13 +84,13 @@ step is skipped entirely.
|
|
|
91
84
|
|
|
92
85
|
## 1. Worktree-aware git init
|
|
93
86
|
|
|
94
|
-
Parse the init signals by running the query below. `init.
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
87
|
+
Parse the init signals by running the query below. `init.ingest-docs` takes no argument
|
|
88
|
+
and emits the git-state signals this step needs (`has_git`, `in_nested_subdir`,
|
|
89
|
+
`git_worktree_root`) from the same #3491 reader `init.new-project` uses. Never use
|
|
90
|
+
`init.execute-phase ""`: it refuses an empty phase, and the `{}` fallback would disable the guard.
|
|
98
91
|
|
|
99
92
|
```bash
|
|
100
|
-
INIT=$(pp_run query init.
|
|
93
|
+
INIT=$(pp_run query init.ingest-docs 2>/dev/null || echo '{}')
|
|
101
94
|
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
|
|
102
95
|
```
|
|
103
96
|
|
|
@@ -177,7 +170,12 @@ its booleans, never in `$?`, and its `error` prose is never echoed (D-07-07). Th
|
|
|
177
170
|
runs only *after* a clean probe, so a project that cannot reach its vault never ends up
|
|
178
171
|
with a half-populated cache (D-07-05).
|
|
179
172
|
|
|
173
|
+
The verdict is the client vault's. The platform repo is probed and shown, but a client
|
|
174
|
+
project may have no access to it, so an unreachable platform repo reads `(not required)`
|
|
175
|
+
and does not fail the proof.
|
|
176
|
+
|
|
180
177
|
```bash
|
|
178
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
181
179
|
# D-07-01 + OD-1 + INIT-01: three signals, all read through the resolvers every other path
|
|
182
180
|
# uses. Anything but the literal "true" is a fail-inert default.
|
|
183
181
|
PP_INIT_PROBE=""
|
|
@@ -219,26 +217,25 @@ if [ "$VAULT_ON" = "true" ] && [ "$PROFILE_RESOLVED" = "true" ]; then
|
|
|
219
217
|
PROBE=$(pp_run query vault probe --raw 2>/dev/null || echo '{"targets":[]}')
|
|
220
218
|
# R3-CR-02 + R3-WR-02: ONE evaluation of the target set, read by every arm
|
|
221
219
|
# below. FOUR hand-copied de-dup pipelines stood here and had already
|
|
222
|
-
# diverged
|
|
223
|
-
#
|
|
224
|
-
#
|
|
225
|
-
#
|
|
226
|
-
#
|
|
227
|
-
#
|
|
228
|
-
#
|
|
229
|
-
# tier's identity when two tiers name one coordinate
|
|
230
|
-
# the
|
|
231
|
-
#
|
|
232
|
-
#
|
|
233
|
-
#
|
|
234
|
-
#
|
|
235
|
-
#
|
|
236
|
-
#
|
|
237
|
-
#
|
|
238
|
-
#
|
|
239
|
-
#
|
|
240
|
-
|
|
241
|
-
PROBE_EVAL=$(printf '%s' "$PROBE" | node -e "const d=require('fs').readFileSync(0,'utf-8');try{const t=(JSON.parse(d).targets||[]).filter(x=>x&&x.configured===true);const key=x=>[x.repo,x.ref,x.host].join('|');const names=new Set(t.map(x=>x.name));const seen=new Set();const req=t.filter(x=>x.name!=='shared'&&!seen.has(key(x))&&seen.add(key(x)));const pick=new Map();for(const x of t){const k=key(x);const p=pick.get(k);if(!p||(p.name==='shared'&&x.name!=='shared'))pick.set(k,x);}const shown=t.filter(x=>pick.get(key(x))===x);const cfg={client:'client.vaultRepo',platform:'platform.repo'};const gone=Object.keys(cfg).filter(n=>!names.has(n));const ok=names.has('client')&&names.has('platform')&&req.length>0&&req.every(x=>x.reachable===true&&x.refFound===true);const sick=req.filter(x=>!(x.reachable===true&&x.refFound===true)).map(x=>String(x.name)+' '+String(x.repoSafe)+' @ '+String(x.ref)+' '+(x.reachable===true?'ref not found':'unreachable'));const all=gone.map(n=>n+' not configured').concat(sick);const lines=shown.map(x=>' '+String(x.name).padEnd(9)+String(x.repoSafe)+' @ '+((x.name==='platform'&&x.ref==='HEAD')?'(unpinned)':String(x.ref))+' '+(x.reachable===true?(x.refFound===true?'reachable, ref found':'ref not found'):'unreachable')+(x.name==='shared'?' (fallback tier, not required)':'')).concat(gone.map(n=>' '+n.padEnd(9)+'(not configured) missing — '+cfg[n]+' is absent from .platform-bindings.json'));process.stdout.write([ok?'pass':'fail',String(shown.length>0&&shown.every(x=>x.reachable!==true)),'failed='+(all.length?all.join('; '):'probe payload unreadable')].concat(lines).join('\n'));}catch{process.stdout.write('fail\nfalse\nfailed=probe payload unreadable');}")
|
|
220
|
+
# diverged, so every arm reads this one line. Only the CLIENT vault decides
|
|
221
|
+
# the verdict: it is what the fetch below lands. The platform repo is shown
|
|
222
|
+
# and recorded but not required (a client project may have no access to
|
|
223
|
+
# it), so an unreachable platform line carries "(not required)", like the
|
|
224
|
+
# fallback tier (OD-5 Option A: shared is probed and shown, out of the
|
|
225
|
+
# verdict and out of the note's sick list). A binding with no platform.repo
|
|
226
|
+
# at all still fails as "not configured". The DISPLAY de-dup keeps a
|
|
227
|
+
# non-shared tier's identity when two tiers name one coordinate, so a
|
|
228
|
+
# platform colliding with the fallback is still shown as platform. The
|
|
229
|
+
# all-down flag counts EVERY distinct remote, fallback included, ON
|
|
230
|
+
# PURPOSE: it drives the offline candidate below, and a remote that
|
|
231
|
+
# answered is evidence the network is up. CR-02: a target with no
|
|
232
|
+
# coordinate gets its own "missing" line — without it the D-07-02 case
|
|
233
|
+
# printed a card whose every line read healthy under a fail verdict;
|
|
234
|
+
# measured, not a diagnosis (D-07-07). EMITS: line 1 verdict, 2 all-down,
|
|
235
|
+
# 3 note, 4+ card; a card line can never carry a newline of its own
|
|
236
|
+
# (redactCloneTarget collapses the control class at the source, R2-WR-03),
|
|
237
|
+
# so the split below is safe.
|
|
238
|
+
PROBE_EVAL=$(printf '%s' "$PROBE" | node -e "const d=require('fs').readFileSync(0,'utf-8');try{const t=(JSON.parse(d).targets||[]).filter(x=>x&&x.configured===true);const key=x=>[x.repo,x.ref,x.host].join('|');const names=new Set(t.map(x=>x.name));const healthy=x=>x.reachable===true&&x.refFound===true;const req=t.filter(x=>x.name==='client');const pick=new Map();for(const x of t){const k=key(x);const p=pick.get(k);if(!p||(p.name==='shared'&&x.name!=='shared'))pick.set(k,x);}const shown=t.filter(x=>pick.get(key(x))===x);const cfg={client:'client.vaultRepo',platform:'platform.repo'};const gone=Object.keys(cfg).filter(n=>!names.has(n));const ok=names.has('client')&&names.has('platform')&&req.length>0&&req.every(healthy);const sick=req.filter(x=>!healthy(x)).map(x=>String(x.name)+' '+String(x.repoSafe)+' @ '+String(x.ref)+' '+(x.reachable===true?'ref not found':'unreachable'));const all=gone.map(n=>n+' not configured').concat(sick);const lines=shown.map(x=>' '+String(x.name).padEnd(9)+String(x.repoSafe)+' @ '+((x.name==='platform'&&x.ref==='HEAD')?'(unpinned)':String(x.ref))+' '+(x.reachable===true?(x.refFound===true?'reachable, ref found':'ref not found'):'unreachable')+(x.name==='shared'?' (fallback tier, not required)':(x.name==='platform'&&!healthy(x)?' (not required)':''))).concat(gone.map(n=>' '+n.padEnd(9)+'(not configured) missing — '+cfg[n]+' is absent from .platform-bindings.json'));process.stdout.write([ok?'pass':'fail',String(shown.length>0&&shown.every(x=>x.reachable!==true)),'failed='+(all.length?all.join('; '):'probe payload unreadable')].concat(lines).join('\n'));}catch{process.stdout.write('fail\nfalse\nfailed=probe payload unreadable');}")
|
|
242
239
|
PROBE_VERDICT=$(printf '%s' "$PROBE_EVAL" | sed -n '1p')
|
|
243
240
|
PROBE_ALL_DOWN=$(printf '%s' "$PROBE_EVAL" | sed -n '2p')
|
|
244
241
|
PROBE_NOTE=$(printf '%s' "$PROBE_EVAL" | sed -n '3p')
|
|
@@ -257,6 +254,9 @@ if [ "$VAULT_ON" = "true" ] && [ "$PROFILE_RESOLVED" = "true" ]; then
|
|
|
257
254
|
FETCH_COUNT=$(printf '%s' "$FETCH" | node -e "const d=require('fs').readFileSync(0,'utf-8');try{process.stdout.write(String((JSON.parse(d).files||[]).length));}catch{process.stdout.write('0');}")
|
|
258
255
|
FETCH_SUMMARY=$(printf '%s' "$FETCH" | node -e "const d=require('fs').readFileSync(0,'utf-8');try{process.stdout.write(String(JSON.parse(d).summaryWritten===true));}catch{process.stdout.write('false');}")
|
|
259
256
|
PLATFORM_REPO=$(printf '%s' "$PROBE" | node -e "const d=require('fs').readFileSync(0,'utf-8');try{const x=(JSON.parse(d).targets||[]).find(y=>y&&y.name==='platform');process.stdout.write(String((x&&x.repoSafe)||''));}catch{process.stdout.write('');}")
|
|
257
|
+
# The platform repo is not required (a client may have no access to it): its measured
|
|
258
|
+
# state goes on the card and into the record, it never decides the verdict.
|
|
259
|
+
PLATFORM_STATE=$(printf '%s' "$PROBE" | node -e "const d=require('fs').readFileSync(0,'utf-8');try{const x=(JSON.parse(d).targets||[]).find(y=>y&&y.name==='platform');process.stdout.write(x&&x.reachable===true?(x.refFound===true?'reachable':'ref not found (not required)'):'unreachable (not required)');}catch{process.stdout.write('unreachable (not required)');}")
|
|
260
260
|
# Never the probe's internal HEAD placeholder — an unpinned platform says so.
|
|
261
261
|
PLATFORM_TAG=$(pp_run query platform-bindings --pick platform.tag 2>/dev/null)
|
|
262
262
|
if [ "$FETCH_TIER" = "client" ] && [ "$FETCH_SUMMARY" = "true" ] && { [ "$FETCH_SOURCE" = "fetched" ] || [ "$FETCH_SOURCE" = "cache" ]; }; then
|
|
@@ -264,13 +264,13 @@ if [ "$VAULT_ON" = "true" ] && [ "$PROFILE_RESOLVED" = "true" ]; then
|
|
|
264
264
|
# card prints. A refused write used to be a warning under a PASSED card, and PASSED
|
|
265
265
|
# routes to "continue to Step 3" — so "unrecorded" was defined to continue. It is a
|
|
266
266
|
# failure of the step, kind FAIL_KIND=record. Markers unchanged: pass/unbound/fail.
|
|
267
|
-
if pp_run query init-contract --record-probe "passed=platform ${PLATFORM_REPO} @ ${PLATFORM_TAG:-(unpinned)}; vault ${FETCH_REPO} @ ${FETCH_REF} tier ${FETCH_TIER} ${FETCH_COUNT} files" >/dev/null 2>&1; then
|
|
267
|
+
if pp_run query init-contract --record-probe "passed=platform ${PLATFORM_REPO} @ ${PLATFORM_TAG:-(unpinned)} ${PLATFORM_STATE}; vault ${FETCH_REPO} @ ${FETCH_REF} tier ${FETCH_TIER} ${FETCH_COUNT} files" >/dev/null 2>&1; then
|
|
268
268
|
PP_INIT_PROBE=pass
|
|
269
269
|
echo "Reachability proof: PASSED"
|
|
270
270
|
# OD-3 + CR-01: the DISPLAY-SAFE coordinate (repoSafe), ref, tier and booleans
|
|
271
271
|
# only. Credentials are stripped at the source, so a PAT in the binding reaches
|
|
272
272
|
# neither this card nor the record. Never url, never error.
|
|
273
|
-
printf '%s\n' " platform ${PLATFORM_REPO} @ ${PLATFORM_TAG:-(unpinned)}
|
|
273
|
+
printf '%s\n' " platform ${PLATFORM_REPO} @ ${PLATFORM_TAG:-(unpinned)} ${PLATFORM_STATE}"
|
|
274
274
|
printf '%s\n' " vault ${FETCH_REPO} @ ${FETCH_REF} reachable, ref found — tier ${FETCH_TIER}, sha ${FETCH_SHA}, ${FETCH_COUNT} files, SUMMARY.md written (${FETCH_SOURCE})"
|
|
275
275
|
printf '%s\n' "$PROBE_LINES" | grep '^ shared ' || true
|
|
276
276
|
echo "PP_INIT_PROBE=pass"
|
|
@@ -353,7 +353,7 @@ outright. Take THIS generic sub-path when
|
|
|
353
353
|
bindings ARE present, take the gated GitLab/Azure sub-path below instead — that section is
|
|
354
354
|
still part of Step 3, not a separate optional step. **The provider answer never decides
|
|
355
355
|
whether Step 3 runs** — inside the gated sub-path it only decides whether the
|
|
356
|
-
|
|
356
|
+
`glab` or `gh` create recipe fires or falls through to this same generic code below.
|
|
357
357
|
|
|
358
358
|
On the generic path:
|
|
359
359
|
|
|
@@ -393,14 +393,14 @@ gets its own per-action confirmation immediately before it fires — nothing bat
|
|
|
393
393
|
step makes **ZERO `gh`/`glab`/provider-API calls**. The push target is the user-supplied
|
|
394
394
|
URL only.
|
|
395
395
|
|
|
396
|
-
### Gated GitLab/
|
|
396
|
+
### Gated GitLab/GitHub provisioning (Step 3's other sub-path — bindings present)
|
|
397
397
|
|
|
398
398
|
This is Step 3's other sub-path, not a separate step. It runs **instead of** the generic
|
|
399
399
|
remote-wiring path above when
|
|
400
400
|
`pp_run query platform-bindings --pick present 2>/dev/null` equals `"true"`. Within it,
|
|
401
|
-
G-1 always runs first to source coordinates and apply the two guards below;
|
|
402
|
-
|
|
403
|
-
|
|
401
|
+
G-1 always runs first to source coordinates and apply the two guards below; a create
|
|
402
|
+
recipe runs **only when the resolved provider is `gitlab` or `github`** — under any
|
|
403
|
+
other provider (`azure` today) it is skipped, not failed, and the
|
|
404
404
|
run falls through to Step 3's generic remote-wiring path above instead (D-11, D-13).
|
|
405
405
|
Implements D-05 (per-action confirmation), D-09 (existence probe → adopt-if-exists), D-10
|
|
406
406
|
(private by default), D-11 (auth verify-only; gated on provider), D-12 (adopt-if-exists
|
|
@@ -442,8 +442,9 @@ comes from, skip G-2 through G-5 entirely, and fall through to Step 3's generic
|
|
|
442
442
|
wiring:
|
|
443
443
|
|
|
444
444
|
```bash
|
|
445
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
445
446
|
if [ -z "$GROUP" ] || [ -z "$SLUG" ]; then
|
|
446
|
-
echo "Skipping
|
|
447
|
+
echo "Skipping repository provisioning: $( [ -z "$GROUP" ] && echo "GROUP (org profile seed provisioning group)" || echo "SLUG (project.slug)" ) is empty — falling through to Step 3's generic remote wiring."
|
|
447
448
|
fi
|
|
448
449
|
```
|
|
449
450
|
|
|
@@ -452,35 +453,24 @@ fi
|
|
|
452
453
|
|
|
453
454
|
```bash
|
|
454
455
|
PROVIDER=$(pp_run query compose-bindings --offline --pick provider 2>/dev/null)
|
|
455
|
-
if [ "$PROVIDER" != "gitlab" ]; then
|
|
456
|
-
echo "Skipping
|
|
456
|
+
if [ "$PROVIDER" != "gitlab" ] && [ "$PROVIDER" != "github" ]; then
|
|
457
|
+
echo "Skipping repository provisioning for provider \"$PROVIDER\" — falling through to Step 3's generic remote wiring instead."
|
|
457
458
|
fi
|
|
458
459
|
```
|
|
459
460
|
|
|
460
|
-
Continue
|
|
461
|
-
|
|
461
|
+
Continue only when the empty-group guard above did not skip **and** `PROVIDER`
|
|
462
|
+
is `gitlab` or `github`. Otherwise stop here and go to Step 3's generic remote wiring (`:283-312`)
|
|
462
463
|
instead — do not fail, do not error, do not prompt for a missing CLI. "Skipped, not
|
|
463
464
|
failed" is satisfied *and* the user still leaves with a wired remote, which a bare skip
|
|
464
465
|
would not give them; pp-core makes zero provider-API calls it has no client for.
|
|
465
466
|
|
|
466
|
-
When both conditions hold, **Read `pp-core/workflows/init/steps/gitlab-provisioning.md`
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
- Always use the group-qualified `$GROUP/$SLUG` path — never a bare slug (T-08-04, D-09).
|
|
474
|
-
A bare slug creates under the user's personal namespace, not the client group. G-1's
|
|
475
|
-
empty-group guard above is what actually enforces this before any create attempt.
|
|
476
|
-
- Always pass `--private` explicitly — never inherit `glab`'s default `--internal`
|
|
477
|
-
visibility (T-08-05, D-10). The `--internal` flag is what makes this dangerous; the
|
|
478
|
-
locked recipe must carry `--private` and must NOT emit `--internal`.
|
|
479
|
-
- Always confirm immediately before each outward action — nothing batched (T-08-06, D-05).
|
|
480
|
-
- Verify-only auth via `glab auth status` — never run `glab auth login`, never read
|
|
481
|
-
or write the user's token (T-08-08, D-11). Bindings hold only non-secret routing data.
|
|
482
|
-
- Always reconcile create with a `glab repo view` probe — a non-zero create exit does
|
|
483
|
-
NOT mean nothing happened (T-08-09, D-09).
|
|
467
|
+
When both conditions hold, **Read `pp-core/workflows/init/steps/gitlab-provisioning.md`
|
|
468
|
+
(provider `gitlab`) or `pp-core/workflows/init/steps/github-provisioning.md` (provider
|
|
469
|
+
`github`) and follow it.** Each owns, for its
|
|
470
|
+
CLI, auth verify-only, the existence probe → adopt-if-exists, per-action confirmation then
|
|
471
|
+
the locked `--private` create, post-create reconciliation, and its security invariants
|
|
472
|
+
(landmine guards: group-qualified path, explicit `--private`, verify-only auth). Under any
|
|
473
|
+
other provider read neither — fall through to Step 3's generic remote wiring above.
|
|
484
474
|
|
|
485
475
|
### Gated client-context capture (Pareto projects — bindings present)
|
|
486
476
|
|
|
@@ -555,9 +545,9 @@ legitimately not exist — the session declines or composes nothing on the inert
|
|
|
555
545
|
|
|
556
546
|
```bash
|
|
557
547
|
if [ -f .platform-bindings.json ]; then
|
|
558
|
-
pp_run query commit "docs: initialize project" --files .planning/config.json .platform-bindings.json
|
|
548
|
+
pp_run query commit "docs(planning): initialize project" --files .planning/config.json .platform-bindings.json
|
|
559
549
|
else
|
|
560
|
-
pp_run query commit "docs: initialize project" --files .planning/config.json
|
|
550
|
+
pp_run query commit "docs(planning): initialize project" --files .planning/config.json
|
|
561
551
|
fi
|
|
562
552
|
```
|
|
563
553
|
|
|
@@ -327,6 +327,7 @@ Continue to verify_output.
|
|
|
327
327
|
Verify all documents created successfully:
|
|
328
328
|
|
|
329
329
|
```bash
|
|
330
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
330
331
|
ls -la .planning/codebase/
|
|
331
332
|
wc -l .planning/codebase/*.md
|
|
332
333
|
```
|
|
@@ -346,6 +347,7 @@ Continue to scan_for_secrets.
|
|
|
346
347
|
Run secret pattern detection:
|
|
347
348
|
|
|
348
349
|
```bash
|
|
350
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
349
351
|
# Check for common API key patterns in generated docs
|
|
350
352
|
grep -E '(sk-[a-zA-Z0-9]{20,}|sk_live_[a-zA-Z0-9]+|sk_test_[a-zA-Z0-9]+|ghp_[a-zA-Z0-9]{36}|gho_[a-zA-Z0-9]{36}|glpat-[a-zA-Z0-9_-]+|AKIA[A-Z0-9]{16}|xox[baprs]-[a-zA-Z0-9-]+|-----BEGIN.*PRIVATE KEY|eyJ[a-zA-Z0-9_-]+\.eyJ[a-zA-Z0-9_-]+\.)' .planning/codebase/*.md 2>/dev/null && SECRETS_FOUND=true || SECRETS_FOUND=false
|
|
351
353
|
```
|
|
@@ -379,7 +381,8 @@ Continue to commit_codebase_map.
|
|
|
379
381
|
Commit the codebase map:
|
|
380
382
|
|
|
381
383
|
```bash
|
|
382
|
-
|
|
384
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
385
|
+
pp_run query commit "docs(planning): map existing codebase" --files .planning/codebase/*.md
|
|
383
386
|
```
|
|
384
387
|
|
|
385
388
|
Continue to offer_next.
|
|
@@ -390,6 +393,7 @@ Present completion summary and next steps.
|
|
|
390
393
|
|
|
391
394
|
**Get line counts:**
|
|
392
395
|
```bash
|
|
396
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
393
397
|
wc -l .planning/codebase/*.md
|
|
394
398
|
```
|
|
395
399
|
|
|
@@ -78,6 +78,7 @@ git tag -l "v${VERSION}" | head -1
|
|
|
78
78
|
```
|
|
79
79
|
If the tag exists:
|
|
80
80
|
```bash
|
|
81
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
81
82
|
git log v${VERSION} --oneline | wc -l
|
|
82
83
|
git diff --stat $(git log --format=%H --reverse v${VERSION} | head -1)..v${VERSION}
|
|
83
84
|
```
|
|
@@ -190,7 +191,7 @@ mkdir -p .planning/reports
|
|
|
190
191
|
|
|
191
192
|
Write the summary, then commit:
|
|
192
193
|
```bash
|
|
193
|
-
pp_run query commit "docs(v${VERSION}
|
|
194
|
+
pp_run query commit "docs(planning): generate v${VERSION} milestone summary for onboarding" --files \
|
|
194
195
|
".planning/reports/MILESTONE_SUMMARY-v${VERSION}.md"
|
|
195
196
|
```
|
|
196
197
|
|
|
@@ -99,6 +99,7 @@ If any of the three answers is empty or whitespace-only, error and re-prompt tha
|
|
|
99
99
|
**Validate via the centralized User Story validator.** The verb owns the canonical regex `/^As a .+, I want to .+, so that .+\.$/` and surfaces per-error guidance:
|
|
100
100
|
|
|
101
101
|
```bash
|
|
102
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
102
103
|
USER_STORY_RESULT=$(pp_run query user-story.validate --story "$USER_STORY")
|
|
103
104
|
if [ "$(echo "$USER_STORY_RESULT" | jq -r '.valid')" != "true" ]; then
|
|
104
105
|
echo "$USER_STORY_RESULT" | jq -r '.errors[]' >&2
|
|
@@ -55,6 +55,7 @@ If the flag is absent, keep the current behavior of continuing phase numbering f
|
|
|
55
55
|
Check `.planning/seeds/` for seed files that match the milestone goals gathered in step 2.
|
|
56
56
|
|
|
57
57
|
```bash
|
|
58
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
58
59
|
ls .planning/seeds/SEED-*.md 2>/dev/null
|
|
59
60
|
```
|
|
60
61
|
|
|
@@ -217,7 +218,7 @@ pp_run query phases.clear --confirm
|
|
|
217
218
|
```
|
|
218
219
|
|
|
219
220
|
```bash
|
|
220
|
-
pp_run query commit "docs: start milestone v[X.Y] [Name]" --files .planning/PROJECT.md .planning/STATE.md
|
|
221
|
+
pp_run query commit "docs(planning): start milestone v[X.Y] [Name]" --files .planning/PROJECT.md .planning/STATE.md
|
|
221
222
|
```
|
|
222
223
|
|
|
223
224
|
## 7. Load Context and Resolve Models
|
|
@@ -256,6 +257,7 @@ If `--reset-phase-numbers` is active:
|
|
|
256
257
|
If `phase_dir_count > 0`, let the engine archive what the closed milestones name — never move phase directories by hand:
|
|
257
258
|
|
|
258
259
|
```bash
|
|
260
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
259
261
|
ARCHIVED=$(pp_run query phases.archive-closed ${GSD_WS})
|
|
260
262
|
```
|
|
261
263
|
|
|
@@ -368,7 +370,7 @@ Commit after writing.
|
|
|
368
370
|
**Synthesizer output self-heal (#222) — verify SUMMARY.md materialized:** The synthesizer's canonical output is `.planning/research/SUMMARY.md` on disk; its brief structured return (`## SYNTHESIS COMPLETE` plus a few `###` confirmation lines) is NOT the file content. A known LLM false-refusal (issue #222) sometimes makes the agent return the full SUMMARY.md document inline — fabricating a write restriction (e.g. "the runtime is blocking file writes") — instead of writing the file. Prompt hardening alone does not fully eliminate it, so the orchestrator MUST absorb the failure deterministically before spawning `pp-roadmapper`:
|
|
369
371
|
|
|
370
372
|
1. Verify `.planning/research/SUMMARY.md` exists AND is substantive — non-empty, and free of any leftover `<!-- gsd:write-continue -->` continuation sentinel (which marks a truncated/incomplete write). You may validate with `pp-tools verify-summary .planning/research/SUMMARY.md` — it exits 0 regardless, so check its JSON `passed` field (`"passed": false` means missing or invalid), not the process exit code. If it passes, continue normally.
|
|
371
|
-
2. If it is MISSING or invalid AND the synthesizer's return message contains the FULL SUMMARY.md document — recognizable by the template's top-level markers `# Project Research Summary`, `## Key Findings`, `## Implications for Roadmap`, and `## Sources`, not merely the brief `## SYNTHESIS COMPLETE` confirmation — the false-refusal fired: write that returned document to `.planning/research/SUMMARY.md` with the Write tool, then commit ALL research artifacts the synthesizer owns (it commits on behalf of the four researchers) with `
|
|
373
|
+
2. If it is MISSING or invalid AND the synthesizer's return message contains the FULL SUMMARY.md document — recognizable by the template's top-level markers `# Project Research Summary`, `## Key Findings`, `## Implications for Roadmap`, and `## Sources`, not merely the brief `## SYNTHESIS COMPLETE` confirmation — the false-refusal fired: write that returned document to `.planning/research/SUMMARY.md` with the Write tool, then commit ALL research artifacts the synthesizer owns (it commits on behalf of the four researchers) with `pp_run query commit "docs(planning): complete project research" --files .planning/research/` unless they are already committed. Log `⚠ #222 self-heal: synthesizer returned SUMMARY.md inline without writing it; orchestrator persisted the file.`
|
|
372
374
|
3. If it is MISSING or invalid AND the return is only a brief confirmation (no full SUMMARY document to recover), the synthesizer genuinely failed — surface the error and stop; do NOT spawn `pp-roadmapper` against a missing or incomplete SUMMARY.md.
|
|
373
375
|
|
|
374
376
|
This guarantees `pp-roadmapper` (which lists SUMMARY.md as required reading) never runs against a missing or truncated SUMMARY.md.
|
|
@@ -456,7 +458,7 @@ If "adjust": Return to scoping.
|
|
|
456
458
|
|
|
457
459
|
**Commit requirements:**
|
|
458
460
|
```bash
|
|
459
|
-
pp_run query commit "docs: define milestone v[X.Y] requirements" --files .planning/REQUIREMENTS.md
|
|
461
|
+
pp_run query commit "docs(planning): define milestone v[X.Y] requirements" --files .planning/REQUIREMENTS.md
|
|
460
462
|
```
|
|
461
463
|
|
|
462
464
|
## 10. Create Roadmap
|
|
@@ -542,7 +544,7 @@ Success criteria:
|
|
|
542
544
|
|
|
543
545
|
**Commit roadmap** (after approval):
|
|
544
546
|
```bash
|
|
545
|
-
pp_run query commit "docs: create milestone v[X.Y] roadmap ([N] phases)" --files .planning/ROADMAP.md .planning/STATE.md .planning/REQUIREMENTS.md
|
|
547
|
+
pp_run query commit "docs(planning): create milestone v[X.Y] roadmap ([N] phases)" --files .planning/ROADMAP.md .planning/STATE.md .planning/REQUIREMENTS.md
|
|
546
548
|
```
|
|
547
549
|
|
|
548
550
|
## 10.5. Link Pending Todos to Roadmap Phases
|
|
@@ -551,6 +553,7 @@ After roadmap approval, scan pending todos against the newly approved phases. Fo
|
|
|
551
553
|
|
|
552
554
|
**Check for pending todos:**
|
|
553
555
|
```bash
|
|
556
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
554
557
|
PENDING_TODOS=$(ls .planning/todos/pending/*.md 2>/dev/null | head -50)
|
|
555
558
|
```
|
|
556
559
|
|
|
@@ -585,7 +588,8 @@ files: [existing]
|
|
|
585
588
|
|
|
586
589
|
**If any todos were linked:**
|
|
587
590
|
```bash
|
|
588
|
-
|
|
591
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
592
|
+
pp_run query commit "docs(planning): tag [count] pending todos with resolves_phase after milestone v[X.Y] roadmap" --files .planning/todos/pending/*.md
|
|
589
593
|
```
|
|
590
594
|
|
|
591
595
|
Print a summary:
|
|
@@ -323,7 +323,7 @@ pp_run query config-new-project '{"mode":"yolo","granularity":"[selected]","para
|
|
|
323
323
|
|
|
324
324
|
```bash
|
|
325
325
|
mkdir -p .planning
|
|
326
|
-
pp_run query commit "chore: add project config" --files .planning/config.json
|
|
326
|
+
pp_run query commit "chore(planning): add project config" --files .planning/config.json
|
|
327
327
|
```
|
|
328
328
|
|
|
329
329
|
**Persist auto-advance chain flag to config (survives context compaction):**
|
|
@@ -339,6 +339,7 @@ Proceed to Step 4 (skip Steps 3 and 5).
|
|
|
339
339
|
Check for existing spike and sketch work that should inform project setup:
|
|
340
340
|
|
|
341
341
|
```bash
|
|
342
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
342
343
|
# Check for spike findings skill (project-local)
|
|
343
344
|
SPIKE_SKILL=$(ls ./.claude/skills/spike-findings-*/SKILL.md 2>/dev/null | head -1 || true)
|
|
344
345
|
|
|
@@ -500,9 +501,9 @@ Initialize with any decisions made during questioning:
|
|
|
500
501
|
```markdown
|
|
501
502
|
## Key Decisions
|
|
502
503
|
|
|
503
|
-
| Decision | Rationale | Outcome |
|
|
504
|
-
|
|
505
|
-
| [Choice from questioning] | [Why] | — Pending |
|
|
504
|
+
| ID | Decision | Rationale | Outcome |
|
|
505
|
+
|----|----------|-----------|---------|
|
|
506
|
+
| — | [Choice from questioning] | [Why] | — Pending |
|
|
506
507
|
```
|
|
507
508
|
|
|
508
509
|
**Last updated footer:**
|
|
@@ -539,7 +540,7 @@ Do not compress. Capture everything gathered.
|
|
|
539
540
|
|
|
540
541
|
```bash
|
|
541
542
|
mkdir -p .planning
|
|
542
|
-
pp_run query commit "docs: initialize project" --files .planning/PROJECT.md
|
|
543
|
+
pp_run query commit "docs(planning): initialize project" --files .planning/PROJECT.md
|
|
543
544
|
```
|
|
544
545
|
|
|
545
546
|
## 5. Workflow Preferences
|
|
@@ -836,7 +837,7 @@ pp_run query config-new-project '{"mode":"[yolo|interactive]","granularity":"[se
|
|
|
836
837
|
**Commit config.json:**
|
|
837
838
|
|
|
838
839
|
```bash
|
|
839
|
-
pp_run query commit "chore: add project config" --files .planning/config.json
|
|
840
|
+
pp_run query commit "chore(planning): add project config" --files .planning/config.json
|
|
840
841
|
```
|
|
841
842
|
|
|
842
843
|
## 5.1. Sub-Repo Detection
|
|
@@ -884,9 +885,9 @@ echo "$ARM"
|
|
|
884
885
|
ARMED=$(printf '%s' "$ARM" | node -e 'let s="";process.stdin.on("data",d=>{s+=d}).on("end",()=>{try{process.stdout.write(String(JSON.parse(s).armed===true))}catch{process.stdout.write("false")}})')
|
|
885
886
|
if [ "$ARM_EXIT" -eq 0 ] && [ "$ARMED" = "true" ]; then
|
|
886
887
|
if [ -f .platform-bindings.json ]; then
|
|
887
|
-
pp_run query commit "chore: arm client vault from org profile" --files .planning/config.json .platform-bindings.json
|
|
888
|
+
pp_run query commit "chore(planning): arm client vault from org profile" --files .planning/config.json .platform-bindings.json
|
|
888
889
|
else
|
|
889
|
-
pp_run query commit "chore: arm client vault from org profile" --files .planning/config.json
|
|
890
|
+
pp_run query commit "chore(planning): arm client vault from org profile" --files .planning/config.json
|
|
890
891
|
fi
|
|
891
892
|
fi
|
|
892
893
|
```
|
|
@@ -1138,7 +1139,7 @@ Commit after writing.
|
|
|
1138
1139
|
**Synthesizer output self-heal (#222) — verify SUMMARY.md materialized:** The synthesizer's canonical output is `.planning/research/SUMMARY.md` on disk; its brief structured return (`## SYNTHESIS COMPLETE` plus a few `###` confirmation lines) is NOT the file content. A known LLM false-refusal (issue #222) sometimes makes the agent return the full SUMMARY.md document inline — fabricating a write restriction (e.g. "the runtime is blocking file writes") — instead of writing the file. Prompt hardening alone does not fully eliminate it, so the orchestrator MUST absorb the failure deterministically before spawning `pp-roadmapper`:
|
|
1139
1140
|
|
|
1140
1141
|
1. Verify `.planning/research/SUMMARY.md` exists AND is substantive — non-empty, and free of any leftover `<!-- gsd:write-continue -->` continuation sentinel (which marks a truncated/incomplete write). You may validate with `pp-tools verify-summary .planning/research/SUMMARY.md` — it exits 0 regardless, so check its JSON `passed` field (`"passed": false` means missing or invalid), not the process exit code. If it passes, continue normally.
|
|
1141
|
-
2. If it is MISSING or invalid AND the synthesizer's return message contains the FULL SUMMARY.md document — recognizable by the template's top-level markers `# Project Research Summary`, `## Key Findings`, `## Implications for Roadmap`, and `## Sources`, not merely the brief `## SYNTHESIS COMPLETE` confirmation — the false-refusal fired: write that returned document to `.planning/research/SUMMARY.md` with the Write tool, then commit ALL research artifacts the synthesizer owns (it commits on behalf of the four researchers) with `
|
|
1142
|
+
2. If it is MISSING or invalid AND the synthesizer's return message contains the FULL SUMMARY.md document — recognizable by the template's top-level markers `# Project Research Summary`, `## Key Findings`, `## Implications for Roadmap`, and `## Sources`, not merely the brief `## SYNTHESIS COMPLETE` confirmation — the false-refusal fired: write that returned document to `.planning/research/SUMMARY.md` with the Write tool, then commit ALL research artifacts the synthesizer owns (it commits on behalf of the four researchers) with `pp_run query commit "docs(planning): complete project research" --files .planning/research/` unless they are already committed. Log `⚠ #222 self-heal: synthesizer returned SUMMARY.md inline without writing it; orchestrator persisted the file.`
|
|
1142
1143
|
3. If it is MISSING or invalid AND the return is only a brief confirmation (no full SUMMARY document to recover), the synthesizer genuinely failed — surface the error and stop; do NOT spawn `pp-roadmapper` against a missing or incomplete SUMMARY.md.
|
|
1143
1144
|
|
|
1144
1145
|
This guarantees `pp-roadmapper` (which lists SUMMARY.md as required reading) never runs against a missing or truncated SUMMARY.md.
|
|
@@ -1312,7 +1313,7 @@ If "adjust": Return to scoping.
|
|
|
1312
1313
|
**Commit requirements:**
|
|
1313
1314
|
|
|
1314
1315
|
```bash
|
|
1315
|
-
pp_run query commit "docs: define v1 requirements" --files .planning/REQUIREMENTS.md
|
|
1316
|
+
pp_run query commit "docs(planning): define v1 requirements" --files .planning/REQUIREMENTS.md
|
|
1316
1317
|
```
|
|
1317
1318
|
|
|
1318
1319
|
## 7.5. Project Structure Mode
|
|
@@ -1496,7 +1497,7 @@ This ensures new projects get the default pp-core workflow-enforcement guidance
|
|
|
1496
1497
|
**Commit roadmap (after approval or auto mode):**
|
|
1497
1498
|
|
|
1498
1499
|
```bash
|
|
1499
|
-
pp_run query commit "docs: create roadmap ([N] phases)" --files .planning/ROADMAP.md .planning/STATE.md .planning/REQUIREMENTS.md "$INSTRUCTION_FILE"
|
|
1500
|
+
pp_run query commit "docs(planning): create roadmap ([N] phases)" --files .planning/ROADMAP.md .planning/STATE.md .planning/REQUIREMENTS.md "$INSTRUCTION_FILE"
|
|
1500
1501
|
```
|
|
1501
1502
|
|
|
1502
1503
|
## 9. Done
|
|
@@ -110,6 +110,7 @@ Before creating anything, validate:
|
|
|
110
110
|
|
|
111
111
|
1. **Target path** — must not exist or must be empty:
|
|
112
112
|
```bash
|
|
113
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
113
114
|
if [ -d "$TARGET_PATH" ] && [ "$(ls -A "$TARGET_PATH" 2>/dev/null)" ]; then
|
|
114
115
|
echo "Error: Target path already exists and is not empty: $TARGET_PATH"
|
|
115
116
|
echo "Choose a different --name or --path."
|
|
@@ -187,7 +187,7 @@ Choice [S]:
|
|
|
187
187
|
```
|
|
188
188
|
2. Commit the deferral record:
|
|
189
189
|
```bash
|
|
190
|
-
pp_run query commit "docs: defer incomplete Phase {src} items to backlog"
|
|
190
|
+
pp_run query commit "docs(planning): defer incomplete Phase {src} items to backlog"
|
|
191
191
|
```
|
|
192
192
|
3. Continue routing to `determine_next_action` immediately — no second prompt.
|
|
193
193
|
|
|
@@ -198,6 +198,7 @@ pp_run query commit "docs: defer incomplete Phase {src} items to backlog"
|
|
|
198
198
|
Check for pending spike/sketch work and surface a notice (does not change routing):
|
|
199
199
|
|
|
200
200
|
```bash
|
|
201
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
201
202
|
# Check for pending spikes (verdict: PENDING in any README)
|
|
202
203
|
PENDING_SPIKES=$(grep -rl 'verdict: PENDING' .planning/spikes/*/README.md 2>/dev/null | wc -l | tr -d ' ')
|
|
203
204
|
|
|
@@ -14,14 +14,15 @@ Read all files referenced by the invoking prompt's execution_context before star
|
|
|
14
14
|
Determine what kind of work is being paused and set the handoff destination accordingly:
|
|
15
15
|
|
|
16
16
|
```bash
|
|
17
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
17
18
|
# Check for active phase
|
|
18
|
-
phase=$(( ls -lt .planning/phases/*/PLAN.md 2>/dev/null || true ) | head -1 |
|
|
19
|
+
phase=$(( ls -lt .planning/phases/*/PLAN.md 2>/dev/null || true ) | head -1 | sed -n 's|.*phases/\([^/]*\)/.*|\1|p')
|
|
19
20
|
|
|
20
21
|
# Check for active spike
|
|
21
|
-
spike=$(( ls -lt .planning/spikes/*/SPIKE.md .planning/spikes/*/DESIGN.md .planning/spikes/*/README.md 2>/dev/null || true ) | head -1 |
|
|
22
|
+
spike=$(( ls -lt .planning/spikes/*/SPIKE.md .planning/spikes/*/DESIGN.md .planning/spikes/*/README.md 2>/dev/null || true ) | head -1 | sed -n 's|.*spikes/\([^/]*\)/.*|\1|p')
|
|
22
23
|
|
|
23
24
|
# Check for active sketch
|
|
24
|
-
sketch=$(( ls -lt .planning/sketches/*/README.md .planning/sketches/*/index.html 2>/dev/null || true ) | head -1 |
|
|
25
|
+
sketch=$(( ls -lt .planning/sketches/*/README.md .planning/sketches/*/index.html 2>/dev/null || true ) | head -1 | sed -n 's|.*sketches/\([^/]*\)/.*|\1|p')
|
|
25
26
|
|
|
26
27
|
# Check for active deliberation
|
|
27
28
|
deliberation=$(ls .planning/deliberations/*.md 2>/dev/null | head -1 || true)
|
|
@@ -57,6 +58,7 @@ Ask user for clarifications if needed via conversational questions.
|
|
|
57
58
|
|
|
58
59
|
**Also inspect SUMMARY.md files for false completions:**
|
|
59
60
|
```bash
|
|
61
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
60
62
|
# Check for placeholder content in existing summaries
|
|
61
63
|
grep -l "To be filled\|placeholder\|TBD" .planning/phases/*/*.md 2>/dev/null || true
|
|
62
64
|
```
|
|
@@ -214,7 +216,7 @@ timestamp=$(pp_run query current-timestamp full --raw)
|
|
|
214
216
|
|
|
215
217
|
<step name="commit">
|
|
216
218
|
```bash
|
|
217
|
-
pp_run query commit "
|
|
219
|
+
pp_run query commit "docs(planning): pause [context-name] at [X]/[Y]" --files [handoff-path] .planning/HANDOFF.json
|
|
218
220
|
```
|
|
219
221
|
</step>
|
|
220
222
|
|
|
@@ -11,6 +11,7 @@ Read all files referenced by the invoking prompt's execution_context before star
|
|
|
11
11
|
## 1. Load Audit Results
|
|
12
12
|
|
|
13
13
|
```bash
|
|
14
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
14
15
|
# Find the most recent audit file
|
|
15
16
|
(ls -t .planning/v*-MILESTONE-AUDIT.md 2>/dev/null || true) | head -1
|
|
16
17
|
```
|
|
@@ -65,6 +66,7 @@ Gap: Flow "View dashboard" broken at data fetch
|
|
|
65
66
|
Find highest existing phase:
|
|
66
67
|
```bash
|
|
67
68
|
_PP_SHIM_NAME="pp-tools.cjs"; _pp_root() { ( for _v in $(env | sed -n 's/^\(GIT_[A-Za-z0-9_]*\)=.*/\1/p'); do unset "$_v"; done; _c=$(git rev-parse --git-common-dir 2>/dev/null); if [ "${_c##*/}" = .git ] && cd "$_c/.." 2>/dev/null; then pwd -P; else git rev-parse --show-toplevel 2>/dev/null || pwd; fi ); }; pp_run() { case "$PP_TOOLS" in *.cjs) node "$PP_TOOLS" "$@";; *) "$PP_TOOLS" "$@";; esac; }; _PP_RUNTIME_ROOT="${RUNTIME_DIR:-$(_pp_root)}"; PP_TOOLS="${_PP_RUNTIME_ROOT}/pp-core/bin/${_PP_SHIM_NAME}"; if [ -f "$PP_TOOLS" ]; then :; elif [ -f "${_PP_RUNTIME_ROOT}/.claude/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${_PP_RUNTIME_ROOT}/.claude/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${_PP_RUNTIME_ROOT}/.codex/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${_PP_RUNTIME_ROOT}/.codex/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "$HOME/.claude/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="$HOME/.claude/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${HERMES_HOME:-$HOME/.hermes}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${HERMES_HOME:-$HOME/.hermes}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${CURSOR_CONFIG_DIR:-$HOME/.cursor}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${CURSOR_CONFIG_DIR:-$HOME/.cursor}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${CODEX_HOME:-$HOME/.codex}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${CODEX_HOME:-$HOME/.codex}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${GEMINI_CONFIG_DIR:-$HOME/.gemini}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${GEMINI_CONFIG_DIR:-$HOME/.gemini}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${COPILOT_CONFIG_DIR:-$HOME/.copilot}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${COPILOT_CONFIG_DIR:-$HOME/.copilot}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${AUGMENT_CONFIG_DIR:-$HOME/.augment}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${AUGMENT_CONFIG_DIR:-$HOME/.augment}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${TRAE_CONFIG_DIR:-$HOME/.trae}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${TRAE_CONFIG_DIR:-$HOME/.trae}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${QWEN_CONFIG_DIR:-$HOME/.qwen}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${QWEN_CONFIG_DIR:-$HOME/.qwen}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${CLINE_CONFIG_DIR:-$HOME/.cline}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${CLINE_CONFIG_DIR:-$HOME/.cline}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${GROK_AGENTS_HOME:-$HOME/.agents}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${GROK_AGENTS_HOME:-$HOME/.agents}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/pp-core/bin/${_PP_SHIM_NAME}"; elif command -v pp-tools >/dev/null 2>&1; then PP_TOOLS="$(command -v pp-tools)"; else echo "ERROR: pp-tools.cjs not found at $PP_TOOLS and pp-tools is not on PATH. Run: npx -y @pareto4/pp-core@latest --claude --local" >&2; exit 1; fi; if [ -n "${CLAUDE_ENV_FILE:-}" ] && [ -n "${PP_TOOLS:-}" ]; then printf "export PATH='%s':\"\$PATH\"\n" "${PP_TOOLS%/*}" >> "$CLAUDE_ENV_FILE" 2>/dev/null || true; fi
|
|
69
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
68
70
|
# Get sorted phase list, extract last one
|
|
69
71
|
HIGHEST=$(pp_run query phases.list --pick directories[-1])
|
|
70
72
|
```
|
|
@@ -154,7 +156,7 @@ Repeat for each gap-closure phase number. This produces `{CODE}-{NN}-{slug}/` wh
|
|
|
154
156
|
## 9. Commit Roadmap and Requirements Update
|
|
155
157
|
|
|
156
158
|
```bash
|
|
157
|
-
pp_run query commit "docs(
|
|
159
|
+
pp_run query commit "docs(planning): add gap closure phases {N}-{M}" --files .planning/ROADMAP.md .planning/REQUIREMENTS.md
|
|
158
160
|
```
|
|
159
161
|
|
|
160
162
|
## 10. Offer Next Steps
|
|
@@ -104,7 +104,7 @@ For each plan entry extracted from `PLAN-OUTLINE.md`:
|
|
|
104
104
|
5. **Commit per-plan:**
|
|
105
105
|
```bash
|
|
106
106
|
_PP_SHIM_NAME="pp-tools.cjs"; _pp_root() { ( for _v in $(env | sed -n 's/^\(GIT_[A-Za-z0-9_]*\)=.*/\1/p'); do unset "$_v"; done; _c=$(git rev-parse --git-common-dir 2>/dev/null); if [ "${_c##*/}" = .git ] && cd "$_c/.." 2>/dev/null; then pwd -P; else git rev-parse --show-toplevel 2>/dev/null || pwd; fi ); }; pp_run() { case "$PP_TOOLS" in *.cjs) node "$PP_TOOLS" "$@";; *) "$PP_TOOLS" "$@";; esac; }; _PP_RUNTIME_ROOT="${RUNTIME_DIR:-$(_pp_root)}"; PP_TOOLS="${_PP_RUNTIME_ROOT}/pp-core/bin/${_PP_SHIM_NAME}"; if [ -f "$PP_TOOLS" ]; then :; elif [ -f "${_PP_RUNTIME_ROOT}/.claude/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${_PP_RUNTIME_ROOT}/.claude/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${_PP_RUNTIME_ROOT}/.codex/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${_PP_RUNTIME_ROOT}/.codex/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "$HOME/.claude/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="$HOME/.claude/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${HERMES_HOME:-$HOME/.hermes}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${HERMES_HOME:-$HOME/.hermes}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${CURSOR_CONFIG_DIR:-$HOME/.cursor}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${CURSOR_CONFIG_DIR:-$HOME/.cursor}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${CODEX_HOME:-$HOME/.codex}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${CODEX_HOME:-$HOME/.codex}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${GEMINI_CONFIG_DIR:-$HOME/.gemini}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${GEMINI_CONFIG_DIR:-$HOME/.gemini}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${COPILOT_CONFIG_DIR:-$HOME/.copilot}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${COPILOT_CONFIG_DIR:-$HOME/.copilot}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${AUGMENT_CONFIG_DIR:-$HOME/.augment}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${AUGMENT_CONFIG_DIR:-$HOME/.augment}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${TRAE_CONFIG_DIR:-$HOME/.trae}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${TRAE_CONFIG_DIR:-$HOME/.trae}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${QWEN_CONFIG_DIR:-$HOME/.qwen}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${QWEN_CONFIG_DIR:-$HOME/.qwen}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${CLINE_CONFIG_DIR:-$HOME/.cline}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${CLINE_CONFIG_DIR:-$HOME/.cline}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${GROK_AGENTS_HOME:-$HOME/.agents}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${GROK_AGENTS_HOME:-$HOME/.agents}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/pp-core/bin/${_PP_SHIM_NAME}"; elif [ -f "${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/pp-core/bin/${_PP_SHIM_NAME}" ]; then PP_TOOLS="${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/pp-core/bin/${_PP_SHIM_NAME}"; elif command -v pp-tools >/dev/null 2>&1; then PP_TOOLS="$(command -v pp-tools)"; else echo "ERROR: pp-tools.cjs not found at $PP_TOOLS and pp-tools is not on PATH. Run: npx -y @pareto4/pp-core@latest --claude --local" >&2; exit 1; fi; if [ -n "${CLAUDE_ENV_FILE:-}" ] && [ -n "${PP_TOOLS:-}" ]; then printf "export PATH='%s':\"\$PATH\"\n" "${PP_TOOLS%/*}" >> "$CLAUDE_ENV_FILE" 2>/dev/null || true; fi
|
|
107
|
-
pp_run query commit "docs(
|
|
107
|
+
pp_run query commit "docs(planning): plan ${plan_id} (chunked)" --phase "${PADDED_PHASE}" --files "${PHASE_DIR}/${plan_id}-PLAN.md"
|
|
108
108
|
```
|
|
109
109
|
|
|
110
110
|
After all N plans are written and committed, treat this as `## PLANNING COMPLETE` and continue
|