@pareto4/pp-core 1.18.0 → 1.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 +3 -1
- package/agents/pp-plan-checker.md +3 -0
- package/agents/pp-planner.md +5 -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-verifier.md +10 -2
- package/commands/pp-add-tests.md +1 -1
- package/commands/pp-debug.md +1 -0
- 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 +1 -1
- package/pp-core/bin/lib/capability-registry.cjs +2 -2
- 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-rollup.cjs +9 -6
- package/pp-core/bin/lib/discovery-screens.cjs +20 -2
- package/pp-core/bin/lib/discovery-sweep.cjs +12 -3
- 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/vault-coordinates.cjs +1 -1
- package/pp-core/bin/lib/vault-index.cjs +18 -5
- 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 +10 -4
- 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-id-conventions.md +35 -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-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/worktree-path-safety.md +1 -0
- package/pp-core/templates/milestone.md +5 -5
- 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/session-13-gates.md +1 -1
- package/pp-core/workflows/discovery-sprint/sessions/01-kick-off.md +51 -7
- package/pp-core/workflows/discovery-sprint/sessions/02-as-is.md +5 -3
- package/pp-core/workflows/discovery-sprint/sessions/03-to-be.md +10 -8
- package/pp-core/workflows/discovery-sprint/sessions/04-ux-design.md +11 -2
- package/pp-core/workflows/discovery-sprint/sessions/05-architecture.md +5 -5
- package/pp-core/workflows/discovery-sprint/sessions/06-security.md +3 -3
- package/pp-core/workflows/discovery-sprint/sessions/07-identity.md +2 -2
- package/pp-core/workflows/discovery-sprint/sessions/08-integration.md +14 -2
- package/pp-core/workflows/discovery-sprint/sessions/09-qa.md +2 -2
- package/pp-core/workflows/discovery-sprint/sessions/10-infrastructure.md +10 -10
- package/pp-core/workflows/discovery-sprint/sessions/11-roadmap.md +11 -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 +5 -3
- package/pp-core/workflows/discovery-sprint/templates/context-template.md +9 -3
- package/pp-core/workflows/discovery-sprint/vault-context.md +14 -3
- package/pp-core/workflows/discovery-sprint.md +11 -8
- package/pp-core/workflows/discovery-to-build/steps/architecture-deliverables.md +1 -0
- package/pp-core/workflows/discuss-phase-assumptions.md +5 -3
- package/pp-core/workflows/discuss-phase.md +8 -3
- 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 +9 -8
- 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.md +21 -6
- 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 +2 -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
|
@@ -167,6 +167,7 @@ fi
|
|
|
167
167
|
Look for a `.continue-here.md` in the current phase directory:
|
|
168
168
|
|
|
169
169
|
```bash
|
|
170
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
170
171
|
ls ${phase_dir}/.continue-here.md 2>/dev/null || true
|
|
171
172
|
```
|
|
172
173
|
|
|
@@ -186,6 +187,7 @@ Write these answers inline before continuing. If a blocking anti-pattern cannot
|
|
|
186
187
|
Check if a SPEC.md (from `/pp:spec-phase`) exists for this phase. SPEC.md locks requirements before implementation decisions.
|
|
187
188
|
|
|
188
189
|
```bash
|
|
190
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
189
191
|
ls ${phase_dir}/*-SPEC.md 2>/dev/null | grep -v AI-SPEC | head -1 || true
|
|
190
192
|
```
|
|
191
193
|
|
|
@@ -205,6 +207,7 @@ ls ${phase_dir}/*-SPEC.md 2>/dev/null | grep -v AI-SPEC | head -1 || true
|
|
|
205
207
|
Check if CONTEXT.md already exists using `has_context` from init.
|
|
206
208
|
|
|
207
209
|
```bash
|
|
210
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
208
211
|
ls ${phase_dir}/*-CONTEXT.md 2>/dev/null || true
|
|
209
212
|
```
|
|
210
213
|
|
|
@@ -218,6 +221,7 @@ ls ${phase_dir}/*-CONTEXT.md 2>/dev/null || true
|
|
|
218
221
|
|
|
219
222
|
Check for an interrupted discussion checkpoint:
|
|
220
223
|
```bash
|
|
224
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
221
225
|
ls ${phase_dir}/*-DISCUSS-CHECKPOINT.json 2>/dev/null || true
|
|
222
226
|
```
|
|
223
227
|
|
|
@@ -255,6 +259,7 @@ For each CONTEXT.md read: extract `<decisions>` (locked preferences), `<specific
|
|
|
255
259
|
|
|
256
260
|
**Spike/sketch findings:** Check for project-local skills:
|
|
257
261
|
```bash
|
|
262
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
258
263
|
SPIKE_FINDINGS=$(ls ./.claude/skills/spike-findings-*/SKILL.md 2>/dev/null | head -1 || true)
|
|
259
264
|
SKETCH_FINDINGS=$(ls ./.claude/skills/sketch-findings-*/SKILL.md 2>/dev/null | head -1 || true)
|
|
260
265
|
RAW_SPIKES=$(ls .planning/spikes/MANIFEST.md 2>/dev/null)
|
|
@@ -472,10 +477,10 @@ rm -f "${phase_dir}/${padded_phase}-DISCUSS-CHECKPOINT.json"
|
|
|
472
477
|
|
|
473
478
|
Commit phase context and discussion log:
|
|
474
479
|
```bash
|
|
475
|
-
pp_run query commit "docs(
|
|
480
|
+
pp_run query commit "docs(planning): capture phase context" --phase "${padded_phase}" --files "${phase_dir}/${padded_phase}-CONTEXT.md" "${phase_dir}/${padded_phase}-DISCUSSION-LOG.md"
|
|
476
481
|
```
|
|
477
482
|
|
|
478
|
-
Confirm: "Committed: docs(
|
|
483
|
+
Confirm: "Committed: docs(planning): capture phase context — Phase: ${padded_phase}"
|
|
479
484
|
</step>
|
|
480
485
|
|
|
481
486
|
<step name="update_state">
|
|
@@ -486,7 +491,7 @@ pp_run query state.record-session \
|
|
|
486
491
|
--stopped-at "Phase ${PHASE} context gathered" \
|
|
487
492
|
--resume-file "${phase_dir}/${padded_phase}-CONTEXT.md"
|
|
488
493
|
|
|
489
|
-
pp_run query commit "docs(
|
|
494
|
+
pp_run query commit "docs(planning): record phase ${PHASE} context session" --phase "${padded_phase}" --files .planning/STATE.md
|
|
490
495
|
```
|
|
491
496
|
</step>
|
|
492
497
|
|
|
@@ -709,6 +709,7 @@ After Wave 2 collection, generate per-package READMEs for each monorepo workspac
|
|
|
709
709
|
**Resolve workspace packages from glob patterns:**
|
|
710
710
|
|
|
711
711
|
```bash
|
|
712
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
712
713
|
# Expand workspace globs to actual package directories
|
|
713
714
|
for pattern in {monorepo_workspaces}; do
|
|
714
715
|
ls -d $pattern 2>/dev/null
|
|
@@ -35,6 +35,7 @@ Display banner:
|
|
|
35
35
|
## 1. Detect Input State
|
|
36
36
|
|
|
37
37
|
```bash
|
|
38
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
38
39
|
SUMMARY_FILES=$(ls "${PHASE_DIR}"/*-SUMMARY.md 2>/dev/null)
|
|
39
40
|
AI_SPEC_FILE=$(ls "${PHASE_DIR}"/*-AI-SPEC.md 2>/dev/null | head -1)
|
|
40
41
|
EVAL_REVIEW_FILE=$(ls "${PHASE_DIR}"/*-EVAL-REVIEW.md 2>/dev/null | head -1)
|
|
@@ -143,7 +144,7 @@ Read the written EVAL-REVIEW.md. Extract:
|
|
|
143
144
|
**If `commit_docs` is true:**
|
|
144
145
|
```bash
|
|
145
146
|
git add "${EVAL_REVIEW_FILE}"
|
|
146
|
-
git commit -m "docs(
|
|
147
|
+
git commit -m "docs(planning): add EVAL-REVIEW.md — score {overall_score}/100 ({verdict})" -m "Phase: {padded_phase}"
|
|
147
148
|
```
|
|
148
149
|
|
|
149
150
|
</process>
|
|
@@ -54,13 +54,13 @@ old numbers, which is how 05-13 shifted three rows ~200 lines into a different f
|
|
|
54
54
|
|
|
55
55
|
| Query | Handler branch / function | Emits boolean `block` on every path? | Emission site(s) |
|
|
56
56
|
|-------|---------------------------|--------------------------------------|------------------|
|
|
57
|
-
| `gap-analysis.plan-post` | `gap-analysis-plan-post` branch (`cmdGapAnalysisPlanPost`) | yes — always `false` (advisory by design) | `src/check-command-router.cts:
|
|
58
|
-
| `ship.platform-drift` | `ship-platform-drift` branch (`cmdShipPlatformDrift`) | yes — the only producer that can emit `block: true` from a threshold comparison | `src/check-command-router.cts:
|
|
59
|
-
| `tdd.review-checkpoint` | `tdd-review-checkpoint` branch | yes — `block = violations > 0`, advisory in the capability | `src/check-command-router.cts:
|
|
57
|
+
| `gap-analysis.plan-post` | `gap-analysis-plan-post` branch (`cmdGapAnalysisPlanPost`) | yes — always `false` (advisory by design) | `src/check-command-router.cts:1096` |
|
|
58
|
+
| `ship.platform-drift` | `ship-platform-drift` branch (`cmdShipPlatformDrift`) | yes — the only producer that can emit `block: true` from a threshold comparison | `src/check-command-router.cts:1198,1208,1217,1234,1276,1285,1299` |
|
|
59
|
+
| `tdd.review-checkpoint` | `tdd-review-checkpoint` branch | yes — `block = violations > 0`, advisory in the capability | `src/check-command-router.cts:977,1051` |
|
|
60
60
|
| `ui.plan-gate` | `ui-plan-gate` branch (`computeUiPlanGate`) | yes — `block = frontend && !hasUiSpec` | `src/check-command-router.cts:703` (emitted at `:727`) |
|
|
61
61
|
| `ui.safety-gate` | `ui-safety-gate` branch (`computeUiSafetyGate`) | yes — `block = frontend && hasUiFiles && !hasUiSpec` | `src/check-command-router.cts:830` (emitted at `:856`) |
|
|
62
|
-
| `vault.status` | `vault-status` branch (`cmdVaultStatus`) | yes — COMPUTED, not constant: `block` is the `vault.required` policy applied to the shared tier-keyed verdict leaf (`computeVaultVerdict`, GATE-01 / D-VH-4). It is `false` with the policy off (STRICT-01's byte-identical promise), on the inert path (`.platform-bindings.json` absent — that branch runs FIRST by requirement, T-02-28, because `tier !== 'client'` is true of `undefined` and would otherwise block every non-Pareto project), and for a present, fresh, client-tier vault; it is `true` on a required miss, on a fallback-tier load, on a stale client vault whatever its source (D-08-01; the block skips staleness only when `vault.cache_ttl_hours` is 0, D-08-28), and on a client cache fetched from a ref the project no longer configures (D-08-23). The attributed override (`applyVaultOverride`, GATE-07) then gets the last word on every blocking path, and that overwrite is the last emission site cited; and on a passing required-on verdict the envelope now carries a `message` (the success line, D-08-20) — the enforcer's every-run passthrough prints it. | `src/check-command-router.cts:
|
|
63
|
-
| `vault.trace` | `vault-trace` branch (`cmdVaultTrace`) — declared by the `vault` capability (`when: vault.enabled`) at **four** points, `plan:post`, `execute:post`, `ship:pre` and `verify:post`, all `blocking: true` / `onError: halt`, and once more at `ship:pre` as a seal gate (`onRecordedArtifacts: true`) that renders with `vault.enabled` off over a phase holding vault records (16-08). It judges each PLAN's `<vault_standards>` block and each SUMMARY's `## Standards Consulted` section through `src/vault-standards.cts` and fails closed on the `standards_*` kinds (`standards_block_absent`, `standards_block_duplicate`, `standards_block_unterminated`, `standards_block_malformed`, `standards_reason_invalid`, `standards_document_duplicate`, `standards_degraded_mixed`, `standards_none_without_reason`, `standards_path_not_resolved`, `standards_pin_mismatch`, `standards_cache_unreadable`, `standards_degraded_untrue`, `standards_consulted_absent`, `standards_consulted_mismatch`, `standards_plan_id_mismatch`, `standards_pair_missing`, `standards_orphan_summary`, `standards_anchor_malformed`). Reads `--stage` (04-03) and `--unpaired` (04-07, D-10); `ship:pre` sets `GATE_UNPAIRED=strict` unconditionally, `verify:post` sets it only on a full-phase run and leaves it unset when **either** partial-execution mode is active — the host's `WAVE_FILTER` set, or `--gaps-only` (04-12, CR-04; 04-18, WR-01) — and the other two leave the tolerant default | yes — `false` before any policy is read (inert), `false` with status `inactive` when `vault.enabled` is off and the phase holds no vault records, `true` once a standards record fails to validate; an agreeing degraded record with `vault.required` off is `false` with a message (D-29), and a recorded override is `false` at the tolerant points and `true` at the strict ones; `true` with status `disabled_with_artifacts` when `vault.enabled` is off and the positional's phase (or plan file) holds engine-written vault records (16-09, SEAL-02, D-21) — the answer the `ship:pre` seal gate dispatches for | `src/check-command-router.cts:
|
|
62
|
+
| `vault.status` | `vault-status` branch (`cmdVaultStatus`) | yes — COMPUTED, not constant: `block` is the `vault.required` policy applied to the shared tier-keyed verdict leaf (`computeVaultVerdict`, GATE-01 / D-VH-4). It is `false` with the policy off (STRICT-01's byte-identical promise), on the inert path (`.platform-bindings.json` absent — that branch runs FIRST by requirement, T-02-28, because `tier !== 'client'` is true of `undefined` and would otherwise block every non-Pareto project), and for a present, fresh, client-tier vault; it is `true` on a required miss, on a fallback-tier load, on a stale client vault whatever its source (D-08-01; the block skips staleness only when `vault.cache_ttl_hours` is 0, D-08-28), and on a client cache fetched from a ref the project no longer configures (D-08-23). The attributed override (`applyVaultOverride`, GATE-07) then gets the last word on every blocking path, and that overwrite is the last emission site cited; and on a passing required-on verdict the envelope now carries a `message` (the success line, D-08-20) — the enforcer's every-run passthrough prints it. | `src/check-command-router.cts:1655,1670,1709,1736,1797` (02-11: CHECKED by the same two-directional probe as the other rows — every cited line lies inside `cmdVaultStatus` and emits a block, and every emission site is cited. This was the one row the probe did NOT cover, so it is the row that rotted: wave 1 wrote the claim before 02-06 computed the block, and 05-13 shifted the citations arithmetically into the manifest-sanitiser, ~200 lines outside the handler) 14-06: + the envelope always carries `reason`, `status` may be `degraded` (index missing / unparseable / empty / unresolvable / unchecked, D-12), the flat index fields follow the override keys, and the healthy message is the one-line standards card (D-15); a degraded index blocks exactly when `vault.required` is on, through the same override (D-13), so it adds no emission site of its own. |
|
|
63
|
+
| `vault.trace` | `vault-trace` branch (`cmdVaultTrace`) — declared by the `vault` capability (`when: vault.enabled`) at **four** points, `plan:post`, `execute:post`, `ship:pre` and `verify:post`, all `blocking: true` / `onError: halt`, and once more at `ship:pre` as a seal gate (`onRecordedArtifacts: true`) that renders with `vault.enabled` off over a phase holding vault records (16-08). It judges each PLAN's `<vault_standards>` block and each SUMMARY's `## Standards Consulted` section through `src/vault-standards.cts` and fails closed on the `standards_*` kinds (`standards_block_absent`, `standards_block_duplicate`, `standards_block_unterminated`, `standards_block_malformed`, `standards_reason_invalid`, `standards_document_duplicate`, `standards_degraded_mixed`, `standards_none_without_reason`, `standards_path_not_resolved`, `standards_pin_mismatch`, `standards_cache_unreadable`, `standards_degraded_untrue`, `standards_consulted_absent`, `standards_consulted_mismatch`, `standards_plan_id_mismatch`, `standards_pair_missing`, `standards_orphan_summary`, `standards_anchor_malformed`). Reads `--stage` (04-03) and `--unpaired` (04-07, D-10); `ship:pre` sets `GATE_UNPAIRED=strict` unconditionally, `verify:post` sets it only on a full-phase run and leaves it unset when **either** partial-execution mode is active — the host's `WAVE_FILTER` set, or `--gaps-only` (04-12, CR-04; 04-18, WR-01) — and the other two leave the tolerant default | yes — `false` before any policy is read (inert), `false` with status `inactive` when `vault.enabled` is off and the phase holds no vault records, `true` once a standards record fails to validate; an agreeing degraded record with `vault.required` off is `false` with a message (D-29), and a recorded override is `false` at the tolerant points and `true` at the strict ones; `true` with status `disabled_with_artifacts` when `vault.enabled` is off and the positional's phase (or plan file) holds engine-written vault records (16-09, SEAL-02, D-21) — the answer the `ship:pre` seal gate dispatches for | `src/check-command-router.cts:3011,3023,3026,3058,3089,3114,3144,3170,3445` (04-16: CHECKED — a test asserts every line cited here lies inside `cmdVaultTrace` and carries a `block` emission, because four plans in this pass moved these numbers and nothing noticed). 16-07 (SEAL-01): at the strict points only, `appendSealProblems` compares the phase's recorded end anchors with `HEAD` through bounded git and adds `uncovered_source_commit` (a source commit after the ends that no record's start-end range covers), `anchor_missing`, `anchor_start_missing`, `anchor_unknown`, `anchor_not_ancestor` and `seal_could_not_check` (all blocking) and the `anchor_backfilled` note; it pushes problems into `checked` and owns no emission site and no status. 16-09 (SEAL-02): + the `disabled_with_artifacts` emission inside the switch-off guard. Standards-only vault: re-derived with the probe's own `handlerRange`/`emitsBlock` after the second record family, the invalid-config refusal and the envelope's mode tag left the handler. |
|
|
64
64
|
| `verify.codebase-drift` | `verify-codebase-drift` branch (`verify.cmdVerifyCodebaseDrift`) | yes — `block = action_required` | `src/verify.cts:2134,2149,2164,2186,2231,2246` |
|
|
65
65
|
| `verify.schema-drift` | `verify-schema-drift` branch (`verify.cmdVerifySchemaDrift`) | yes — `block = !skipped && driftDetected` | `src/verify.cts:2051,2071,2108` |
|
|
66
66
|
|
|
@@ -99,13 +99,14 @@ For each hook, bind `GATE_QUERY` to `hook.check.query`, `GATE_BLOCKING` to `hook
|
|
|
99
99
|
|
|
100
100
|
```bash
|
|
101
101
|
_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
|
|
102
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
102
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)
|
|
103
104
|
CHECK_EXIT=$?
|
|
104
105
|
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
|
|
105
106
|
echo "GATE_CHECK=failed"
|
|
106
107
|
else
|
|
107
108
|
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');}")
|
|
108
|
-
GATE_MESSAGE=$(printf '%s' "$GATE_RESULT" | node -e "const d=require('fs').readFileSync(0,'utf-8');try{const m=JSON.parse(d).message;process.stdout.write(typeof m==='string'?m.replace(
|
|
109
|
+
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('');}")
|
|
109
110
|
echo "GATE_CHECK=ok"
|
|
110
111
|
echo "GATE_BLOCK=$GATE_BLOCK"
|
|
111
112
|
if [ -n "$GATE_MESSAGE" ]; then printf 'GATE_MESSAGE=%s\n' "$GATE_MESSAGE"; fi
|
|
@@ -55,6 +55,7 @@ CROSS_AI_TIMEOUT=$(pp_run query config-get workflow.cross_ai_timeout 2>/dev/null
|
|
|
55
55
|
3. **Run the external command** from the project root, writing the prompt to stdin.
|
|
56
56
|
Never shell-interpolate the prompt — always pipe via stdin to prevent injection:
|
|
57
57
|
```bash
|
|
58
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
58
59
|
PP_GATE_BIN=$(printf '%s\n' "${PP_TOOLS:+${PP_TOOLS%/*}:}$PATH" | tr : '\n' | while IFS= read -r d; do if [ -r "$d/portable-timeout.sh" ]; then printf %s "$d"; break; fi; done)
|
|
59
60
|
if [ -r "$PP_GATE_BIN/portable-timeout.sh" ]; then
|
|
60
61
|
. "$PP_GATE_BIN/portable-timeout.sh"
|
|
@@ -55,6 +55,7 @@ The block below also records the verdict before and after the fetch and says so
|
|
|
55
55
|
**If an active vault step hook exists** (recognizable by `capId == "vault"` + `ref.command == "vault fetch"`) — or `VAULT_FETCH_DIRECT` is `true` with an empty payload:
|
|
56
56
|
|
|
57
57
|
```bash
|
|
58
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
58
59
|
# vault.required — read ONCE, with an explicit default (STRICT-03). The key is
|
|
59
60
|
# declared in `capabilities/vault/capability.json`, so this read returns the
|
|
60
61
|
# project's configured value; with it set true the hard-stop arm below is live.
|
|
@@ -123,4 +124,15 @@ else
|
|
|
123
124
|
# The claim is now reachable ONLY when summaryWritten is true.
|
|
124
125
|
echo "✓ vault fetch + summary complete: .planning/vault/SUMMARY.md"
|
|
125
126
|
fi
|
|
127
|
+
|
|
128
|
+
# Issue #12 item 18: after a real fetch, say when the vault has a newer stable
|
|
129
|
+
# tag than the pinned one. A report only — `vault update` without --yes writes
|
|
130
|
+
# nothing, and a lookup that fails prints nothing. A reused cache skips it, so
|
|
131
|
+
# the tag lookup runs at most once per cache TTL.
|
|
132
|
+
if [ "$VAULT_SOURCE" = "fetched" ]; then
|
|
133
|
+
VAULT_NEWER=$(pp_run vault update --raw 2>/dev/null | node -e "const d=require('fs').readFileSync(0,'utf-8');try{const p=JSON.parse(d);process.stdout.write(p.newer?p.from+' '+p.newer:'');}catch{process.stdout.write('');}")
|
|
134
|
+
if [ -n "$VAULT_NEWER" ]; then
|
|
135
|
+
echo "ℹ vault: ${VAULT_NEWER#* } is newer than the pinned ${VAULT_NEWER%% *}; the pin stays. To move: pp-tools vault update ${VAULT_NEWER#* }"
|
|
136
|
+
fi
|
|
137
|
+
fi
|
|
126
138
|
```
|
|
@@ -179,6 +179,7 @@ fi
|
|
|
179
179
|
|
|
180
180
|
Resolve `MVP_MODE` once via the centralized `phase.mvp-mode` query verb (precedence chain: CLI flag → ROADMAP `**Mode:** mvp` → `workflow.mvp_mode` config → false):
|
|
181
181
|
```bash
|
|
182
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
182
183
|
MVP_FLAG_ARG=""
|
|
183
184
|
if [[ "$ARGUMENTS" =~ (^|[[:space:]])--mvp([[:space:]]|$) ]]; then MVP_FLAG_ARG="--cli-flag"; fi
|
|
184
185
|
MVP_MODE=$(pp_run query phase.mvp-mode "${PHASE_NUMBER}" $MVP_FLAG_ARG --pick active)
|
|
@@ -218,7 +219,10 @@ Offer these recovery options:
|
|
|
218
219
|
if [ "$MVP_MODE" = "true" ] && [ "$TDD_MODE" = "true" ]; then
|
|
219
220
|
IS_BEHAVIOR_ADDING=$(pp_run query task.is-behavior-adding "$TASK_FILE" --pick is_behavior_adding)
|
|
220
221
|
if [ "$IS_BEHAVIOR_ADDING" = "true" ]; then
|
|
221
|
-
|
|
222
|
+
# A `test` commit (any scope) whose `Phase:` trailer is this plan; a `test(<plan>):`
|
|
223
|
+
# subject from before the trailer convention still counts.
|
|
224
|
+
RED_COMMIT=$(git log --format='%h%x09%s%x09%(trailers:key=Phase,valueonly,separator=%x2C)' -- "**/*.test.*" "**/*.spec.*" "tests/" \
|
|
225
|
+
| awk -F'\t' -v id="${PHASE_NUMBER}-${PLAN_ID}" '$2 ~ /^test(\([^)]*\))?!?:/ && ($3 == id || index($2, "(" id "):") > 0) { print; exit }')
|
|
222
226
|
if [ -z "$RED_COMMIT" ]; then
|
|
223
227
|
pp_run query state.update last_gate_trip "${PLAN_ID}/${TASK_ID}" || true
|
|
224
228
|
echo "MVP+TDD GATE TRIPPED: missing RED commit for ${PLAN_ID}/${TASK_ID}"
|
|
@@ -236,6 +240,7 @@ Pure doc-only / config-only / test-only tasks return `is_behavior_adding=false`
|
|
|
236
240
|
Look for a `.continue-here.md` in the current phase directory:
|
|
237
241
|
|
|
238
242
|
```bash
|
|
243
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
239
244
|
ls ${phase_dir}/.continue-here.md 2>/dev/null || true
|
|
240
245
|
```
|
|
241
246
|
|
|
@@ -755,6 +760,7 @@ increases monotonically across waves. `{status}` is `complete` (success),
|
|
|
755
760
|
rerun the same command. Do not fall back to broad worktree discovery.
|
|
756
761
|
|
|
757
762
|
```bash
|
|
763
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
758
764
|
[ -n "${WAVE_WORKTREE_MANIFEST:-}" ] && [ -f "$WAVE_WORKTREE_MANIFEST" ] || {
|
|
759
765
|
echo "BLOCKED: missing WAVE_WORKTREE_MANIFEST; refusing broad worktree cleanup (#3384)." >&2
|
|
760
766
|
exit 1
|
|
@@ -784,6 +790,7 @@ increases monotonically across waves. `{status}` is `complete` (success),
|
|
|
784
790
|
If the orchestrator deviated from the standard wave merge path (e.g., custom inter-worktree base-update merges with `merge: bring …` style messages), run this snippet after the custom merges are complete. It reads only `WAVE_WORKTREE_MANIFEST`; do not discover unrelated `worktree-agent-*` worktrees.
|
|
785
791
|
|
|
786
792
|
```bash
|
|
793
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
787
794
|
# Cleanup-tail: pin orchestrator CWD to its OWN worktree before cleanup-tail (#3174, #630).
|
|
788
795
|
# Same fix as the templated path: resolve the dispatch-time orchestrator root from the manifest,
|
|
789
796
|
# not `git worktree list`'s first entry (always the main checkout — wrong for a lane orchestrator).
|
|
@@ -858,7 +865,7 @@ increases monotonically across waves. `{status}` is `complete` (success),
|
|
|
858
865
|
|
|
859
866
|
# Only commit tracking files if they actually changed
|
|
860
867
|
if ! git diff --quiet .planning/ROADMAP.md .planning/STATE.md 2>/dev/null; then
|
|
861
|
-
pp_run query commit "docs(
|
|
868
|
+
pp_run query commit "docs(planning): update tracking after wave ${N}" --phase "${PHASE_NUMBER}" --files .planning/ROADMAP.md .planning/STATE.md
|
|
862
869
|
fi
|
|
863
870
|
elif [ "${TEST_EXIT}" -eq 124 ]; then
|
|
864
871
|
echo "⚠ Skipping tracking update — test suite timed out. Plans remain in-progress. Run tests manually to confirm."
|
|
@@ -1062,6 +1069,7 @@ After all waves:
|
|
|
1062
1069
|
|
|
1063
1070
|
**Security gate check:**
|
|
1064
1071
|
```bash
|
|
1072
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
1065
1073
|
VERIFY_POST_HOOKS_JSON=$(pp_run loop render-hooks verify:post --raw)
|
|
1066
1074
|
printf '%s' "$VERIFY_POST_HOOKS_JSON" | node -e "let h=[];try{h=JSON.parse(require('fs').readFileSync(0,'utf-8')).activeHooks||[]}catch{}console.log('VERIFY_POST_HOOKS_JSON='+JSON.stringify({activeHooks:h}))"
|
|
1067
1075
|
SECURITY_FILE=$(ls "${PHASE_DIR}"/*-SECURITY.md 2>/dev/null | head -1)
|
|
@@ -1213,7 +1221,8 @@ mv .planning/debug/{slug}.md .planning/debug/resolved/
|
|
|
1213
1221
|
|
|
1214
1222
|
**6. Commit updated artifacts:**
|
|
1215
1223
|
```bash
|
|
1216
|
-
|
|
1224
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
1225
|
+
pp_run query commit "docs(planning): resolve UAT gaps and debug sessions after ${PHASE_NUMBER} gap closure" --phase "${PARENT_PHASE}" --files .planning/phases/*${PARENT_PHASE}*/*-UAT.md .planning/debug/resolved/*.md
|
|
1217
1226
|
```
|
|
1218
1227
|
</step>
|
|
1219
1228
|
|
|
@@ -1376,7 +1385,7 @@ blocked: 0
|
|
|
1376
1385
|
|
|
1377
1386
|
Commit the file:
|
|
1378
1387
|
```bash
|
|
1379
|
-
pp_run query commit "
|
|
1388
|
+
pp_run query commit "docs(planning): persist human verification items as UAT" --phase "{phase_num}" --files "{phase_dir}/{phase_num}-UAT.md"
|
|
1380
1389
|
```
|
|
1381
1390
|
|
|
1382
1391
|
**Step B: Present to user:**
|
|
@@ -1456,7 +1465,8 @@ These items are tracked and will appear in `/pp:progress` and `/pp:audit-uat`.
|
|
|
1456
1465
|
```
|
|
1457
1466
|
|
|
1458
1467
|
```bash
|
|
1459
|
-
|
|
1468
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
1469
|
+
pp_run query commit "docs(planning): complete phase execution" --phase "{X}" --files .planning/ROADMAP.md .planning/STATE.md .planning/REQUIREMENTS.md {phase_dir}/*-VERIFICATION.md
|
|
1460
1470
|
```
|
|
1461
1471
|
</step>
|
|
1462
1472
|
|
|
@@ -1489,6 +1499,7 @@ Copy failure must NOT block phase completion.
|
|
|
1489
1499
|
This step runs AFTER `update_roadmap` marks the phase complete. It moves any pending todos that carry `resolves_phase: <current-phase-number>` to the completed directory.
|
|
1490
1500
|
|
|
1491
1501
|
```bash
|
|
1502
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
1492
1503
|
PHASE_NUM="${PHASE_NUMBER}"
|
|
1493
1504
|
PENDING_DIR=".planning/todos/pending"
|
|
1494
1505
|
COMPLETED_DIR=".planning/todos/completed"
|
|
@@ -1506,7 +1517,7 @@ for TODO_FILE in "$PENDING_DIR"/*.md; do
|
|
|
1506
1517
|
done
|
|
1507
1518
|
|
|
1508
1519
|
if [ ${#CLOSED[@]} -gt 0 ]; then
|
|
1509
|
-
pp_run query commit "docs(
|
|
1520
|
+
pp_run query commit "docs(planning): auto-close ${#CLOSED[@]} todo(s) resolved by this phase" --phase "${PHASE_NUMBER}" --files .planning/todos/completed/ .planning/STATE.md|| true
|
|
1510
1521
|
echo "◆ Closed ${#CLOSED[@]} todo(s) resolved by Phase ${PHASE_NUMBER}:"
|
|
1511
1522
|
for f in "${CLOSED[@]}"; do echo " ✓ $f"; done
|
|
1512
1523
|
fi
|
|
@@ -1531,7 +1542,7 @@ PROJECT.md falls behind silently over multiple phases.
|
|
|
1531
1542
|
5. Commit the change:
|
|
1532
1543
|
|
|
1533
1544
|
```bash
|
|
1534
|
-
pp_run query commit "docs(
|
|
1545
|
+
pp_run query commit "docs(planning): evolve PROJECT.md after phase completion" --phase "{X}" --files .planning/PROJECT.md
|
|
1535
1546
|
```
|
|
1536
1547
|
|
|
1537
1548
|
**Skip this step if** `.planning/PROJECT.md` does not exist.
|
|
@@ -1594,6 +1605,7 @@ Read and follow `~/.claude/pp-core/workflows/transition.md`, passing through the
|
|
|
1594
1605
|
Check whether CONTEXT.md already exists for the next phase:
|
|
1595
1606
|
|
|
1596
1607
|
```bash
|
|
1608
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
1597
1609
|
ls .planning/phases/*{next}*/{next}-CONTEXT.md 2>/dev/null || echo "no-context"
|
|
1598
1610
|
```
|
|
1599
1611
|
|
|
@@ -77,6 +77,7 @@ hooks, mechanically in the fence (D-30): no other capability's hook is run or
|
|
|
77
77
|
injected here, because execute-phase's dispatcher owns those for its own run.
|
|
78
78
|
|
|
79
79
|
```bash
|
|
80
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
80
81
|
EXECUTE_PRE_HOOKS_JSON=$(pp_run loop render-hooks execute:pre --raw | node -e "const d=require('fs').readFileSync(0,'utf-8');try{const j=JSON.parse(d);j.activeHooks=(j.activeHooks||[]).filter((x)=>x&&x.capId==='vault');process.stdout.write(JSON.stringify(j));}catch{process.stdout.write('');}")
|
|
81
82
|
printf '%s' "$EXECUTE_PRE_HOOKS_JSON" | node -e "let h=[];try{h=JSON.parse(require('fs').readFileSync(0,'utf-8')).activeHooks||[]}catch{}console.log('EXECUTE_PRE_HOOKS_JSON='+JSON.stringify({activeHooks:h}))"
|
|
82
83
|
```
|
|
@@ -91,6 +92,7 @@ the two-step contract, the halt and the message passthrough; none of them are re
|
|
|
91
92
|
|
|
92
93
|
<step name="identify_plan">
|
|
93
94
|
```bash
|
|
95
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
94
96
|
# Use plans/summaries from INIT JSON, or list files
|
|
95
97
|
(ls .planning/phases/XX-name/*-PLAN.md 2>/dev/null || true) | sort
|
|
96
98
|
(ls .planning/phases/XX-name/*-SUMMARY.md 2>/dev/null || true) | sort
|
|
@@ -122,6 +124,7 @@ positional is the plan file, not its phase directory: sibling plans mid-wave are
|
|
|
122
124
|
business, and `check vault.trace <plan file> --stage plan` by hand gives this gate's verdict.
|
|
123
125
|
|
|
124
126
|
```bash
|
|
127
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
125
128
|
PLAN_POST_HOOKS_JSON=$(pp_run loop render-hooks plan:post --raw | node -e "const d=require('fs').readFileSync(0,'utf-8');try{const j=JSON.parse(d);j.activeHooks=(j.activeHooks||[]).filter((x)=>x&&x.capId==='vault');process.stdout.write(JSON.stringify(j));}catch{process.stdout.write('');}")
|
|
126
129
|
printf '%s' "$PLAN_POST_HOOKS_JSON" | node -e "let h=[];try{h=JSON.parse(require('fs').readFileSync(0,'utf-8')).activeHooks||[]}catch{}console.log('PLAN_POST_HOOKS_JSON='+JSON.stringify({activeHooks:h}))"
|
|
127
130
|
```
|
|
@@ -312,9 +315,11 @@ End with: **Total deviations:** N auto-fixed (breakdown). **Impact:** assessment
|
|
|
312
315
|
For `type: tdd` plans — RED-GREEN-REFACTOR:
|
|
313
316
|
|
|
314
317
|
1. **Infrastructure** (first TDD plan only): detect project, install framework, config, verify empty suite
|
|
315
|
-
2. **RED:** Read `<behavior>` → failing test(s) → run (MUST fail) → commit: `test({
|
|
316
|
-
3. **GREEN:** Read `<implementation>` → minimal code → run (MUST pass) → commit: `feat({
|
|
317
|
-
4. **REFACTOR:** Clean up → tests MUST pass → commit: `refactor({
|
|
318
|
+
2. **RED:** Read `<behavior>` → failing test(s) → run (MUST fail) → commit: `test({area}): add failing test for [feature]`
|
|
319
|
+
3. **GREEN:** Read `<implementation>` → minimal code → run (MUST pass) → commit: `feat({area}): implement [feature]`
|
|
320
|
+
4. **REFACTOR:** Clean up → tests MUST pass → commit: `refactor({area}): clean up [feature]`
|
|
321
|
+
|
|
322
|
+
`{area}` names the part of the codebase (`auth`, `billing`), never the plan; every one of these commits ends with the trailer `Phase: {phase}-{plan}` after a blank line.
|
|
318
323
|
|
|
319
324
|
Errors: RED doesn't fail → investigate test/existing feature. GREEN doesn't pass → debug, iterate. REFACTOR breaks → undo.
|
|
320
325
|
|
|
@@ -348,7 +353,7 @@ If a commit is BLOCKED by a hook:
|
|
|
348
353
|
<task_commit>
|
|
349
354
|
## Task Commit Protocol
|
|
350
355
|
|
|
351
|
-
Canonical per-task commit rules live in **`agents/pp-executor.md`** (`<task_commit_protocol>`). Follow that section for staging, `{type}({phase}-{plan}
|
|
356
|
+
Canonical per-task commit rules live in **`agents/pp-executor.md`** (`<task_commit_protocol>`). Follow that section for staging, `{type}({area}): …` messages with the `Phase: {phase}-{plan}` trailer, `commit-to-subrepo` when `sub_repos` is set, post-commit checks, and untracked-file handling — do not duplicate or paraphrase the full protocol here (single source of truth).
|
|
352
357
|
|
|
353
358
|
**Orchestrator note:** After each task, the spawned executor reports commit hashes; this workflow does not re-specify commit semantics beyond pointing at the executor.
|
|
354
359
|
|
|
@@ -523,6 +528,7 @@ Counts PLAN vs SUMMARY files on disk and updates the progress-table row with the
|
|
|
523
528
|
Mark completed requirements from the PLAN.md frontmatter `requirements:` field:
|
|
524
529
|
|
|
525
530
|
```bash
|
|
531
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
526
532
|
pp_run query requirements.mark-complete ${REQ_IDS}
|
|
527
533
|
```
|
|
528
534
|
|
|
@@ -543,9 +549,9 @@ IS_WORKTREE=$([ -f .git ] && echo "true" || echo "false")
|
|
|
543
549
|
|
|
544
550
|
# In parallel mode: exclude STATE.md and ROADMAP.md (orchestrator commits these)
|
|
545
551
|
if [ "$IS_WORKTREE" = "true" ]; then
|
|
546
|
-
pp_run query commit "docs(
|
|
552
|
+
pp_run query commit "docs(planning): complete [plan-name] plan" --phase "{phase}-{plan}" --files .planning/phases/XX-name/{phase}-{plan}-SUMMARY.md .planning/REQUIREMENTS.md
|
|
547
553
|
else
|
|
548
|
-
pp_run query commit "docs(
|
|
554
|
+
pp_run query commit "docs(planning): complete [plan-name] plan" --phase "{phase}-{plan}" --files .planning/phases/XX-name/{phase}-{plan}-SUMMARY.md .planning/STATE.md .planning/ROADMAP.md .planning/REQUIREMENTS.md
|
|
549
555
|
fi
|
|
550
556
|
```
|
|
551
557
|
</step>
|
|
@@ -554,13 +560,17 @@ fi
|
|
|
554
560
|
If .planning/codebase/ doesn't exist: skip.
|
|
555
561
|
|
|
556
562
|
```bash
|
|
557
|
-
|
|
563
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
564
|
+
# Oldest feat/fix/test commit carrying the plan's `Phase:` trailer (or, from before the trailer, its scope)
|
|
565
|
+
FIRST_TASK=$(git log --reverse --format='%h%x09%s%x09%(trailers:key=Phase,valueonly,separator=%x2C)' \
|
|
566
|
+
| awk -F'\t' -v id="{phase}-{plan}" '$2 ~ /^(feat|fix|test)(\([^)]*\))?!?:/ && ($3 == id || index($2, "(" id "):") > 0) { print $1; exit }')
|
|
558
567
|
git diff --name-only ${FIRST_TASK}^..HEAD 2>/dev/null || true
|
|
559
568
|
```
|
|
560
569
|
|
|
561
570
|
Update only structural changes: new src/ dir → STRUCTURE.md | deps → STACK.md | file pattern → CONVENTIONS.md | API client → INTEGRATIONS.md | config → STACK.md | renamed → update paths. Skip code-only/bugfix/content changes.
|
|
562
571
|
|
|
563
572
|
```bash
|
|
573
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
564
574
|
pp_run query commit "" --files .planning/codebase/*.md --amend
|
|
565
575
|
```
|
|
566
576
|
</step>
|
|
@@ -569,6 +579,7 @@ pp_run query commit "" --files .planning/codebase/*.md --amend
|
|
|
569
579
|
If `USER_SETUP_CREATED=true`: display `⚠️ USER SETUP REQUIRED` with path + env/config tasks at TOP.
|
|
570
580
|
|
|
571
581
|
```bash
|
|
582
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
572
583
|
(ls -1 .planning/phases/[current-phase-dir]/*-PLAN.md 2>/dev/null || true) | wc -l
|
|
573
584
|
(ls -1 .planning/phases/[current-phase-dir]/*-SUMMARY.md 2>/dev/null || true) | wc -l
|
|
574
585
|
```
|
|
@@ -118,7 +118,7 @@ For each selected output, write the file:
|
|
|
118
118
|
Commit if `commit_docs` is enabled:
|
|
119
119
|
```bash
|
|
120
120
|
_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
|
|
121
|
-
pp_run query commit "docs: capture exploration — {topic_slug}" --files {file_list}
|
|
121
|
+
pp_run query commit "docs(planning): capture exploration — {topic_slug}" --files {file_list}
|
|
122
122
|
```
|
|
123
123
|
|
|
124
124
|
## Step 6: Close
|
|
@@ -64,6 +64,7 @@ Extract:
|
|
|
64
64
|
For each phase directory in `.planning/phases/*/`:
|
|
65
65
|
|
|
66
66
|
```bash
|
|
67
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
67
68
|
ls .planning/phases/*/
|
|
68
69
|
```
|
|
69
70
|
|
|
@@ -255,15 +256,16 @@ If actionable anomalies were found (HIGH or MEDIUM confidence):
|
|
|
255
256
|
|
|
256
257
|
If confirmed:
|
|
257
258
|
```bash
|
|
259
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
258
260
|
# Check if "bug" label exists before using it
|
|
259
|
-
BUG_LABEL=$(gh label list --repo
|
|
261
|
+
BUG_LABEL=$(gh label list --repo pareto000/pp-core --search "bug" --json name -q '.[0].name' 2>/dev/null)
|
|
260
262
|
LABEL_FLAG=""
|
|
261
263
|
if [ -n "$BUG_LABEL" ]; then
|
|
262
264
|
LABEL_FLAG="--label bug"
|
|
263
265
|
fi
|
|
264
266
|
|
|
265
267
|
gh issue create \
|
|
266
|
-
--repo
|
|
268
|
+
--repo pareto000/pp-core \
|
|
267
269
|
--title "bug: {concise description from anomaly}" \
|
|
268
270
|
$LABEL_FLAG \
|
|
269
271
|
--body "{formatted findings from report}"
|
|
@@ -42,6 +42,7 @@ Usage: /pp:import --from <path>
|
|
|
42
42
|
Verify the path does not contain traversal sequences and the file exists:
|
|
43
43
|
|
|
44
44
|
```bash
|
|
45
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
45
46
|
case "{FILEPATH}" in
|
|
46
47
|
*..* ) echo "SECURITY_ERROR: path contains traversal sequence"; exit 1 ;;
|
|
47
48
|
esac
|
|
@@ -228,7 +229,7 @@ Update `.planning/STATE.md` if appropriate (e.g., increment total plan count).
|
|
|
228
229
|
|
|
229
230
|
Commit the imported plan and updated files:
|
|
230
231
|
```bash
|
|
231
|
-
pp_run query commit "docs(
|
|
232
|
+
pp_run query commit "docs(planning): import plan from {basename FILEPATH}" --phase "{phase}" --files .planning/phases/{phase}/{plan}-PLAN.md .planning/ROADMAP.md
|
|
232
233
|
```
|
|
233
234
|
|
|
234
235
|
Display completion:
|
|
@@ -33,6 +33,7 @@ Parse `$ARGUMENTS`:
|
|
|
33
33
|
**Validate paths:**
|
|
34
34
|
|
|
35
35
|
```bash
|
|
36
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
36
37
|
case "{SCAN_PATH}" in *..*) echo "SECURITY_ERROR: path contains traversal sequence"; exit 1 ;; esac
|
|
37
38
|
test -d "{SCAN_PATH}" || echo "PATH_NOT_FOUND"
|
|
38
39
|
if [ -n "{MANIFEST_PATH}" ]; then
|
|
@@ -61,6 +61,7 @@ Capture these fields, in this order:
|
|
|
61
61
|
managed-block writer:
|
|
62
62
|
|
|
63
63
|
```bash
|
|
64
|
+
[ -z "${ZSH_VERSION:-}" ] || emulate -R sh
|
|
64
65
|
if [ "$(pp_run query platform-bindings --pick present 2>/dev/null)" = "true" ]; then
|
|
65
66
|
# Write collected values to a temp JSON file using node + JSON.stringify so that
|
|
66
67
|
# multi-line values, embedded quotes, backslashes, and $(...) sequences are encoded
|