@pareto4/pp-core 1.13.0 → 1.18.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 +3 -3
- package/README.md +31 -12
- package/agents/pp-code-fixer.md +0 -11
- package/agents/pp-code-reviewer.md +1 -77
- package/agents/pp-debug-session-manager.md +9 -6
- package/agents/pp-executor.md +12 -29
- package/agents/pp-plan-checker.md +4 -4
- package/agents/pp-planner.md +34 -20
- package/agents/pp-vault-reviewer.md +100 -23
- package/agents/pp-verifier.md +1 -3
- package/bin/install.js +10 -3
- package/commands/pp-execute-phase.md +1 -3
- package/commands/pp-ns-manage.md +1 -1
- package/commands/pp-ns-review.md +1 -1
- package/commands/pp-plan-phase.md +1 -2
- package/commands/pp-vault-promote.md +7 -8
- package/commands/pp-vault-review.md +6 -5
- package/commands/pp-verify-work.md +1 -2
- package/gemini-extension.json +1 -1
- package/hooks/dist/pp-check-update.js +0 -0
- package/hooks/dist/pp-cursor-session-start.js +1 -1
- package/hooks/dist/pp-statusline.js +1 -1
- package/hooks/dist/pp-update-banner.js +0 -0
- package/hooks/pp-check-update.js +0 -0
- package/hooks/pp-cursor-session-start.js +1 -1
- package/hooks/pp-statusline.js +1 -1
- package/hooks/pp-update-banner.js +0 -0
- package/package.json +10 -18
- package/pareto-skills/_shared/create-project-board.sh +0 -0
- package/pareto-skills/pp-project-setup/SKILL.md +1 -1
- package/pp-core/bin/check-latest-version.cjs +0 -0
- package/pp-core/bin/detect-build-commands.sh +2 -2
- package/pp-core/bin/lib/capability-activation.cjs +83 -9
- package/pp-core/bin/lib/capability-registry.cjs +201 -229
- package/pp-core/bin/lib/capability-state.cjs +93 -1
- package/pp-core/bin/lib/capability-writer.cjs +3 -3
- package/pp-core/bin/lib/check-command-router.cjs +1906 -1514
- package/pp-core/bin/lib/clusters.cjs +3 -0
- package/pp-core/bin/lib/command-aliases.cjs +0 -35
- package/pp-core/bin/lib/commands.cjs +9 -4
- package/pp-core/bin/lib/compose-bindings.cjs +251 -88
- package/pp-core/bin/lib/config-loader.cjs +7 -103
- package/pp-core/bin/lib/config-schema.cjs +1 -1
- package/pp-core/bin/lib/config.cjs +151 -62
- package/pp-core/bin/lib/decisions.cjs +4 -4
- package/pp-core/bin/lib/discovery-vault-check.cjs +246 -0
- package/pp-core/bin/lib/frontmatter.cjs +1 -38
- package/pp-core/bin/lib/git-base-branch.cjs +11 -12
- package/pp-core/bin/lib/git-provider.cjs +9 -10
- package/pp-core/bin/lib/init-command-router.cjs +5 -8
- package/pp-core/bin/lib/init-contract.cjs +620 -738
- package/pp-core/bin/lib/init-interactive.cjs +62 -4
- package/pp-core/bin/lib/init.cjs +24 -51
- package/pp-core/bin/lib/install-profiles.cjs +1 -1
- package/pp-core/bin/lib/io.cjs +4 -2
- package/pp-core/bin/lib/loop-resolver.cjs +165 -129
- package/pp-core/bin/lib/org-profile.cjs +402 -161
- package/pp-core/bin/lib/package-identity.cjs +3 -3
- package/pp-core/bin/lib/phase-command-router.cjs +1 -29
- package/pp-core/bin/lib/phase-scope.cjs +1 -1
- package/pp-core/bin/lib/phase.cjs +11 -253
- package/pp-core/bin/lib/platform-bindings.cjs +40 -19
- package/pp-core/bin/lib/profile-output.cjs +1 -1
- package/pp-core/bin/lib/shell-command-projection.cjs +104 -1
- package/pp-core/bin/lib/state.cjs +11 -85
- package/pp-core/bin/lib/template.cjs +1 -1
- package/pp-core/bin/lib/vault-command-router.cjs +1682 -477
- package/pp-core/bin/lib/vault-coordinates.cjs +16 -7
- package/pp-core/bin/lib/vault-index.cjs +656 -0
- package/pp-core/bin/lib/vault-seal.cjs +1851 -0
- package/pp-core/bin/lib/vault-standards-promote.cjs +577 -0
- package/pp-core/bin/lib/vault-standards-review.cjs +293 -0
- package/pp-core/bin/lib/vault-standards.cjs +1504 -0
- package/pp-core/bin/lib/vault-trace.cjs +155 -2778
- package/pp-core/bin/lib/vault-update.cjs +10 -59
- package/pp-core/bin/lib/vault.cjs +2570 -950
- package/pp-core/bin/lib/verify.cjs +0 -11
- package/pp-core/bin/portable-timeout.sh +1 -1
- package/pp-core/bin/pp-tools.cjs +157 -54
- package/pp-core/bin/shared/config-defaults.manifest.json +0 -7
- package/pp-core/bin/shared/config-schema.manifest.json +0 -3
- package/pp-core/bin/shared/model-catalog.json +2 -2
- package/pp-core/bin/verify-reapply-patches.cjs +0 -0
- package/pp-core/org-profile.json +26 -0
- package/pp-core/references/autonomous-best-effort.md +8 -7
- package/pp-core/references/loop-hook-dispatch.md +0 -25
- package/pp-core/references/planner-gap-closure.md +0 -1
- package/pp-core/references/planner-tdd.md +0 -1
- package/pp-core/references/planner-vault-standards.md +311 -0
- package/pp-core/references/planning-config.md +0 -8
- package/pp-core/references/tdd.md +0 -1
- package/pp-core/templates/README.md +1 -0
- package/pp-core/templates/VAULT-REVIEW.md +56 -0
- package/pp-core/templates/phase-prompt.md +2 -6
- package/pp-core/workflows/_runtime-launcher.snippet.sh +0 -0
- package/pp-core/workflows/add-tests.md +55 -4
- package/pp-core/workflows/audit-fix.md +63 -2
- package/pp-core/workflows/audit-milestone.md +1 -1
- package/pp-core/workflows/autonomous.md +85 -11
- package/pp-core/workflows/check-todos.md +13 -2
- package/pp-core/workflows/code-review-fix.md +59 -3
- package/pp-core/workflows/code-review.md +10 -57
- package/pp-core/workflows/complete-milestone.md +1 -1
- package/pp-core/workflows/debug.md +54 -4
- package/pp-core/workflows/discovery-sprint/prefill.md +19 -7
- package/pp-core/workflows/discovery-sprint/prototype.md +46 -49
- package/pp-core/workflows/discovery-sprint/session-13-gates.md +2 -0
- package/pp-core/workflows/discovery-sprint/sessions/01-kick-off.md +1 -3
- package/pp-core/workflows/discovery-sprint/sessions/02-as-is.md +1 -3
- package/pp-core/workflows/discovery-sprint/sessions/03-to-be.md +1 -3
- package/pp-core/workflows/discovery-sprint/sessions/04-ux-design.md +20 -24
- package/pp-core/workflows/discovery-sprint/sessions/05-architecture.md +1 -3
- package/pp-core/workflows/discovery-sprint/sessions/06-security.md +1 -3
- package/pp-core/workflows/discovery-sprint/sessions/07-identity.md +1 -3
- package/pp-core/workflows/discovery-sprint/sessions/08-integration.md +1 -3
- package/pp-core/workflows/discovery-sprint/sessions/09-qa.md +1 -3
- package/pp-core/workflows/discovery-sprint/sessions/10-infrastructure.md +1 -6
- package/pp-core/workflows/discovery-sprint/sessions/11-roadmap.md +1 -3
- package/pp-core/workflows/discovery-sprint/sessions/12-delivery-model.md +1 -3
- package/pp-core/workflows/discovery-sprint/sessions/13-wrap-up.md +1 -3
- package/pp-core/workflows/discovery-sprint/templates/context-template.md +1 -1
- package/pp-core/workflows/discovery-sprint/vault-context.md +207 -0
- package/pp-core/workflows/discovery-sprint.md +7 -3
- package/pp-core/workflows/discovery-to-build/steps/architecture-deliverables.md +4 -4
- package/pp-core/workflows/discovery-to-build/templates/pp-handoff.md +43 -1
- package/pp-core/workflows/discovery-to-build.md +10 -2
- package/pp-core/workflows/discuss-phase.md +3 -10
- package/pp-core/workflows/execute-phase/steps/check-query-gate.md +327 -0
- package/pp-core/workflows/execute-phase/steps/client-context-gate.md +3 -2
- package/pp-core/workflows/execute-phase/steps/cross-ai-delegation.md +1 -1
- package/pp-core/workflows/execute-phase/steps/execute-pre-dispatch.md +78 -0
- package/pp-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +94 -0
- package/pp-core/workflows/execute-phase/steps/post-merge-gate.md +6 -8
- package/pp-core/workflows/execute-phase/steps/vault-fetch.md +115 -14
- package/pp-core/workflows/execute-phase/steps/vault-load-gate.md +219 -20
- package/pp-core/workflows/execute-phase/steps/verify-post-gate.md +147 -0
- package/pp-core/workflows/execute-phase.md +152 -128
- package/pp-core/workflows/execute-plan.md +54 -6
- package/pp-core/workflows/fast.md +53 -4
- package/pp-core/workflows/help/modes/full.md +3 -3
- package/pp-core/workflows/init/steps/client-context-capture.md +101 -0
- package/pp-core/workflows/init/steps/gitlab-provisioning.md +130 -0
- package/pp-core/workflows/init/steps/project-md-deferral-narration.md +66 -0
- package/pp-core/workflows/init/steps/reachability-outcome.md +70 -0
- package/pp-core/workflows/init.md +232 -272
- package/pp-core/workflows/new-project.md +31 -23
- package/pp-core/workflows/plan-phase.md +98 -45
- package/pp-core/workflows/quick.md +117 -3
- package/pp-core/workflows/secure-phase.md +1 -1
- package/pp-core/workflows/ship.md +57 -28
- package/pp-core/workflows/undo.md +1 -1
- package/pp-core/workflows/update.md +3 -3
- package/pp-core/workflows/validate-phase.md +58 -3
- package/pp-core/workflows/vault-review.md +161 -23
- package/pp-core/workflows/vault-write-back.md +73 -110
- package/pp-core/workflows/verify-work.md +12 -14
- package/scripts/changeset/cli.cjs +6 -5
- package/scripts/changeset/lint.cjs +0 -0
- package/scripts/changeset/new.cjs +33 -50
- package/scripts/dev-env.cjs +25 -85
- package/scripts/gen-capability-registry.cjs +120 -13
- package/scripts/lib/allowlist-ratchet.cjs +1 -103
- package/scripts/lint-allow-test-rule-refs.allowlist.json +0 -2
- package/scripts/lint-docs-required.cjs +0 -0
- package/scripts/lint-pr-check-project-dir.cjs +1 -3
- package/scripts/lint-test-file-count.allowlist.json +3 -19
- package/scripts/lint-test-file-count.cjs +5 -6
- package/scripts/prompt-injection-scan.sh +19 -17
- package/scripts/release-channel.cjs +0 -0
- package/scripts/sync-manifest-versions.cjs +5 -4
- package/scripts/sync-rulesets.sh +1 -1
- package/scripts/update-size-baseline.cjs +30 -274
- package/scripts/verify-opengsd-sweep.cjs +3 -5
- package/scripts/workflow-size.cjs +9 -61
- package/pp-core/bin/lib/dispatch-plan.cjs +0 -483
- package/pp-core/bin/lib/install-run.cjs +0 -536
- package/pp-core/bin/lib/loop-gates.cjs +0 -213
- package/pp-core/bin/lib/phase-manifest.cjs +0 -527
- package/pp-core/bin/lib/phase-tier.cjs +0 -480
- package/pp-core/bin/lib/plan-graph.cjs +0 -368
- package/pp-core/bin/lib/practices-review-check.cjs +0 -938
- package/pp-core/bin/lib/vault-audit.cjs +0 -2070
- package/pp-core/bin/lib/vault-practices.cjs +0 -1990
- package/pp-core/bin/lib/vault-review.cjs +0 -2359
- package/pp-core/bin/lib/vault-write-back.cjs +0 -877
- package/pp-core/references/executor-vault-trace.md +0 -47
- package/pp-core/references/planner-plan-graph.md +0 -66
- package/pp-core/references/planner-vault-practices.md +0 -112
- package/pp-core/templates/practices/README.md +0 -251
- package/pp-core/templates/practices/error-handling.md +0 -18
- package/pp-core/templates/practices/minimal-comments.md +0 -14
- package/pp-core/templates/practices/naming-convention.md +0 -18
- package/pp-core/templates/practices/practice-template.md +0 -23
- package/pp-core/workflows/discovery-sprint/vault-fetch.md +0 -37
- package/pp-core/workflows/execute-phase/steps/checkpoint-handling.md +0 -45
- package/pp-core/workflows/execute-phase/steps/install-run.md +0 -29
- package/pp-core/workflows/execute-phase/steps/phase-close-rebaseline.md +0 -23
- package/pp-core/workflows/execute-phase/steps/serial-group-dispatch.md +0 -73
- package/pp-core/workflows/execute-phase/steps/vault-door-gate.md +0 -19
- package/pp-core/workflows/plan-phase/steps/phase-tier.md +0 -43
- package/scripts/lib/size-budget.cjs +0 -311
- package/scripts/lint-neutrality-names.cjs +0 -694
- package/scripts/lint-org-coordinates.allowlist.json +0 -35
- package/scripts/lint-org-coordinates.cjs +0 -426
|
@@ -267,18 +267,65 @@ PHASE_STATE=$(pp_run query init.phase-op ${PHASE_NUM})
|
|
|
267
267
|
|
|
268
268
|
Check `has_context`. If false → go to handle_blocker: "Discuss for phase ${PHASE_NUM} did not produce CONTEXT.md."
|
|
269
269
|
|
|
270
|
-
**3a.5.
|
|
270
|
+
**3a.5. plan:pre dispatch — fetch, design contract, then gate**
|
|
271
|
+
|
|
272
|
+
Admission first (D-28): a config the gate cannot read renders no vault hook, so this runs before the render.
|
|
273
|
+
|
|
274
|
+
```bash
|
|
275
|
+
VAULT_ADMIT_PRESENT=$(pp_run query platform-bindings --pick present 2>/dev/null || echo true)
|
|
276
|
+
VAULT_ADMIT=inert
|
|
277
|
+
if [ "$VAULT_ADMIT_PRESENT" = true ]; then VAULT_ADMIT=$(pp_run vault admission 2>/dev/null || echo unrecognised); fi
|
|
278
|
+
case "$VAULT_ADMIT" in on) echo "VAULT_ADMIT=on" ;; off|inert) : ;; *) pp_run vault admission --explain; echo "PARETO_GATE_BLOCKED:vault.admission"; exit 1 ;; esac
|
|
279
|
+
```
|
|
271
280
|
|
|
272
281
|
Resolve active `plan:pre` hooks:
|
|
273
282
|
|
|
274
283
|
```bash
|
|
275
284
|
UI_SPEC_FILE=$(ls "${PHASE_DIR}"/*-UI-SPEC.md 2>/dev/null | head -1)
|
|
276
|
-
HOOKS_JSON=$(pp_run loop render-hooks plan:pre --raw
|
|
285
|
+
HOOKS_JSON=$(pp_run loop render-hooks plan:pre --raw)
|
|
286
|
+
printf '%s' "$HOOKS_JSON" | node -e "let h=[];try{h=JSON.parse(require('fs').readFileSync(0,'utf-8')).activeHooks||[]}catch{}console.log('HOOKS_JSON='+JSON.stringify({activeHooks:h}))"
|
|
277
287
|
```
|
|
278
288
|
|
|
279
|
-
Read the `activeHooks` array directly from `HOOKS_JSON
|
|
289
|
+
Read the `activeHooks` array directly from the printed `HOOKS_JSON=` line (in-context — do NOT invoke a shell pipeline).
|
|
290
|
+
|
|
291
|
+
**Policy — pipeline mode is a reason to gate, not a reason to skip (D-VH-6).** Autonomous **runs**
|
|
292
|
+
the `plan:pre` gate, and its step filter admits `ref.command`-shaped hooks as well as `ref.skill`
|
|
293
|
+
ones. Both reverse what this section previously shipped. `--auto` dispatches every step-hook shape
|
|
294
|
+
it understands, then runs the gate, in that order.
|
|
295
|
+
|
|
296
|
+
Run the three sub-steps below **in order**. §3a.5-iii is reached on every path — the early exits in
|
|
297
|
+
§3a.5-ii skip to it, never past it.
|
|
298
|
+
|
|
299
|
+
**3a.5-i. Step hooks — fetch first.**
|
|
300
|
+
|
|
301
|
+
**Compute the active step hooks** = entries from `activeHooks` where `kind == "step"`. Route each by
|
|
302
|
+
the shape of its `ref`, in array order:
|
|
303
|
+
|
|
304
|
+
- **`ref.skill` is set** → a skill-shaped step hook; it is handled by §3a.5-ii below (this is the
|
|
305
|
+
UI-SPEC path and its existing behaviour is unchanged).
|
|
306
|
+
- **`ref.command` is set and `capId == "vault"`** → set `VAULT_FETCH_HOOKS_JSON=$HOOKS_JSON`,
|
|
307
|
+
then Read and execute
|
|
308
|
+
`pp-core/workflows/execute-phase/steps/vault-fetch.md`, the same bespoke `plan:pre` vault fetch +
|
|
309
|
+
summary dispatch `plan-phase.md` uses. Do not invent a second shape for it.
|
|
310
|
+
- **`ref.command` is set and `capId` is anything else** → not handled here. Display
|
|
311
|
+
`⚠ plan:pre step hook from capability '${capId}' has an unhandled ref shape (ref.command) and was skipped in autonomous mode.`
|
|
312
|
+
and continue — a silently dropped hook shape is the defect this section exists to fix.
|
|
313
|
+
|
|
314
|
+
**If there are NO active step hooks at all →** Continue to §3a.5-ii anyway: there is nothing to dispatch here, but §3a.5-ii owns `ui.plan-gate` on every activation set that renders it — the gate-only set included — while §3a.5-iii skips that entry unconditionally, and §3a.5-ii self-skips silently when no UI hook of either kind is active.
|
|
280
315
|
|
|
281
|
-
|
|
316
|
+
**3a.5-ii. UI design contract (frontend phases).**
|
|
317
|
+
|
|
318
|
+
Let the **active UI step hooks** be the `kind == "step"` entries with `ref.skill` set, and the **UI
|
|
319
|
+
gate entry** be a `kind == "gate"` entry whose `check.query` is `ui.plan-gate`. Run this sub-step
|
|
320
|
+
whenever **any** `plan:pre` UI hook is active — step hooks, the gate entry, or both — mirroring
|
|
321
|
+
`plan-phase.md` §5.6's own rule. **If there is no active step hook AND no gate entry → skip silently
|
|
322
|
+
to 3a.5-iii** (`workflow.ui_phase` and `workflow.ui_safety_gate` both off; unchanged inertness).
|
|
323
|
+
|
|
324
|
+
This sub-step OWNS `ui.plan-gate` on every activation set that renders it — the gate-only set
|
|
325
|
+
(`ui_phase=false` + `ui_safety_gate=true`, producing `activeHooks=[{kind:"gate"}]`) included, where
|
|
326
|
+
there is no UI step to dispatch but the gate is still active and still gets run here.
|
|
327
|
+
|
|
328
|
+
Run the UI-SPEC gate:
|
|
282
329
|
|
|
283
330
|
```bash
|
|
284
331
|
GATE=$(pp_run check ui-plan-gate "${PHASE_NUM}" --raw)
|
|
@@ -286,17 +333,19 @@ GATE=$(pp_run check ui-plan-gate "${PHASE_NUM}" --raw)
|
|
|
286
333
|
|
|
287
334
|
Read `frontend` and `hasUiSpec` from `GATE` (in-context).
|
|
288
335
|
|
|
289
|
-
**If `frontend` is false:** Skip silently to
|
|
336
|
+
**If `frontend` is false:** Skip silently to 3a.5-iii.
|
|
290
337
|
|
|
291
|
-
**If `hasUiSpec` is true (UI-SPEC already exists):** Skip silently to
|
|
338
|
+
**If `hasUiSpec` is true (UI-SPEC already exists):** Skip silently to 3a.5-iii.
|
|
292
339
|
|
|
293
|
-
**Otherwise (frontend phase + no UI-SPEC)
|
|
340
|
+
**Otherwise (frontend phase + no UI-SPEC) with no active step hook — the gate-only set:** Display warning `Phase ${PHASE_NUM}: no active UI step hook can generate the missing UI-SPEC — continuing without design contract.` and proceed to 3a.5-iii. NON-BLOCKING, the pipeline-mode outcome `plan-phase.md` Branch 5 is designed for.
|
|
341
|
+
|
|
342
|
+
**Otherwise (frontend phase + no UI-SPEC) with active step hooks:** For each active step hook (the `kind == "step"` set from above, in array order):
|
|
294
343
|
|
|
295
344
|
```
|
|
296
345
|
Skill(skill="pp-${ref.skill}", args="${PHASE_NUM}")
|
|
297
346
|
```
|
|
298
347
|
|
|
299
|
-
(Prepend `pp-` to `ref.skill` — so `ui-phase` → `pp-ui-phase`. Bare `${PHASE_NUM}` args — autonomous style, same pattern as the verify:post dispatch.) Entries where `kind == "gate"` are
|
|
348
|
+
(Prepend `pp-` to `ref.skill` — so `ui-phase` → `pp-ui-phase`. Bare `${PHASE_NUM}` args — autonomous style, same pattern as the verify:post dispatch.) Entries where `kind == "gate"` are not dispatched *here*; they are handled by §3a.5-iii below, which owns every gate at this point except `ui.plan-gate` — this sub-step owns that one, on every activation set that renders it.
|
|
300
349
|
|
|
301
350
|
After all step hooks return, re-read:
|
|
302
351
|
|
|
@@ -304,7 +353,32 @@ After all step hooks return, re-read:
|
|
|
304
353
|
UI_SPEC_FILE=$(ls "${PHASE_DIR}"/*-UI-SPEC.md 2>/dev/null | head -1)
|
|
305
354
|
```
|
|
306
355
|
|
|
307
|
-
**If `UI_SPEC_FILE` is still empty:** Display warning `Phase ${PHASE_NUM}: UI-SPEC generation did not produce output — continuing without design contract.` and proceed to
|
|
356
|
+
**If `UI_SPEC_FILE` is still empty:** Display warning `Phase ${PHASE_NUM}: UI-SPEC generation did not produce output — continuing without design contract.` and proceed to 3a.5-iii. NON-BLOCKING.
|
|
357
|
+
|
|
358
|
+
**3a.5-iii. The plan:pre gate.**
|
|
359
|
+
|
|
360
|
+
Reached on every path through §3a.5, including the ones that skipped the UI work. It runs *after*
|
|
361
|
+
§3a.5-i so the vault fetch has already been attempted — fetch first, then decide (GATE-03), so a
|
|
362
|
+
fresh clone with a reachable vault passes rather than being blocked for a cache it never had a
|
|
363
|
+
chance to populate.
|
|
364
|
+
|
|
365
|
+
`ui.plan-gate` is handled *before* this dispatch — §3a.5-ii ran it with its own `${PHASE_NUM}`
|
|
366
|
+
positional and owns its outcome on every activation set that renders it — so skip that entry; the
|
|
367
|
+
enforcer never sees it.
|
|
368
|
+
|
|
369
|
+
Set `GATE_POINT=plan:pre`, `GATE_HOOKS_JSON=$HOOKS_JSON` (the array already rendered above) and
|
|
370
|
+
leave `GATE_POSITIONAL_ARG` empty deliberately (`vault.status` reads project state, not a phase;
|
|
371
|
+
every plan:pre gate needing one is caller-handled — D-VH-7), then Read and follow
|
|
372
|
+
`pp-core/workflows/execute-phase/steps/check-query-gate.md` — the single generic `check.query` gate
|
|
373
|
+
enforcer (GATE-02). It owns the halt decision, the two-step contract and the message passthrough;
|
|
374
|
+
do not restate any of them here.
|
|
375
|
+
|
|
376
|
+
If no `kind == "gate"` entry is active, the enforcer's own inertness guard returns immediately and
|
|
377
|
+
prints nothing, so a project with the capability off is unaffected. When a gate does block, the
|
|
378
|
+
enforcer prints its named token and runs `exit 1`, stopping the unattended chain rather than
|
|
379
|
+
building the phase with no client standards loaded.
|
|
380
|
+
|
|
381
|
+
Then proceed to 3b.
|
|
308
382
|
|
|
309
383
|
**3b. Plan**
|
|
310
384
|
|
|
@@ -406,7 +480,7 @@ Auto-invoke code review and fix chain. Autonomous mode chains both review and fi
|
|
|
406
480
|
|
|
407
481
|
**Capability dispatch:**
|
|
408
482
|
```bash
|
|
409
|
-
EXECUTE_POST_HOOKS_JSON=$(pp_run loop render-hooks execute:post --raw
|
|
483
|
+
EXECUTE_POST_HOOKS_JSON=$(pp_run loop render-hooks execute:post --raw)
|
|
410
484
|
```
|
|
411
485
|
|
|
412
486
|
Resolve active step hooks from `EXECUTE_POST_HOOKS_JSON` where `kind == "step"` and `ref.skill == "code-review"`.
|
|
@@ -481,7 +555,7 @@ Resolve the active post-verification hooks and the UI-SPEC gate:
|
|
|
481
555
|
|
|
482
556
|
```bash
|
|
483
557
|
UI_SPEC_FILE=$(ls "${PHASE_DIR}"/*-UI-SPEC.md 2>/dev/null | head -1)
|
|
484
|
-
HOOKS_JSON=$(pp_run loop render-hooks verify:post --raw
|
|
558
|
+
HOOKS_JSON=$(pp_run loop render-hooks verify:post --raw)
|
|
485
559
|
```
|
|
486
560
|
|
|
487
561
|
Read the `activeHooks` array directly from the `HOOKS_JSON` value already in context (do not invoke a shell `jq` pipeline — parse as the JSON object it is). **If `activeHooks` is empty or absent:** skip silently to the iterate step.
|
|
@@ -127,11 +127,22 @@ Use AskUserQuestion:
|
|
|
127
127
|
</step>
|
|
128
128
|
|
|
129
129
|
<step name="execute_action">
|
|
130
|
-
**Work on it now:** first
|
|
130
|
+
**Work on it now:** admission first (D-11, D-12, D-28):
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
VAULT_ADMIT_PRESENT=$(pp_run query platform-bindings --pick present 2>/dev/null || echo true)
|
|
134
|
+
VAULT_ADMIT=inert
|
|
135
|
+
if [ "$VAULT_ADMIT_PRESENT" = true ]; then VAULT_ADMIT=$(pp_run vault admission 2>/dev/null || echo unrecognised); fi
|
|
136
|
+
case "$VAULT_ADMIT" in on) echo "VAULT_ADMIT=on" ;; off|inert) : ;; *) pp_run vault admission --explain; echo "PARETO_GATE_BLOCKED:vault.admission"; exit 1 ;; esac
|
|
137
|
+
```
|
|
138
|
+
|
|
131
139
|
```bash
|
|
132
140
|
mv ".planning/todos/pending/[filename]" ".planning/todos/completed/"
|
|
133
141
|
```
|
|
134
|
-
Update STATE.md todo count.
|
|
142
|
+
Update STATE.md todo count. **If the admission fence printed `VAULT_ADMIT=on`:** do not do the work inline; invoke
|
|
143
|
+
`/pp-quick "[todo title]"` via SlashCommand, so the work carries the vault mode's record and the trace
|
|
144
|
+
gates (no artifact here could hold a door record; quick owns ad-hoc governed source), then continue
|
|
145
|
+
below. **Otherwise:** present problem/solution context and begin work or ask how to proceed, as before.
|
|
135
146
|
|
|
136
147
|
**Add to phase plan:**
|
|
137
148
|
Note todo reference in phase planning notes. Keep in pending. Return to list or exit.
|
|
@@ -77,7 +77,7 @@ FIX_REPORT_PATH="${PHASE_DIR}/${PADDED_PHASE}-REVIEW-FIX.md"
|
|
|
77
77
|
Check if code review is active via the capability registry:
|
|
78
78
|
|
|
79
79
|
```bash
|
|
80
|
-
EXECUTE_POST_HOOKS_JSON=$(pp_run loop render-hooks execute:post --raw)
|
|
80
|
+
EXECUTE_POST_HOOKS_JSON=$(pp_run loop render-hooks execute:post --raw)
|
|
81
81
|
```
|
|
82
82
|
|
|
83
83
|
Resolve active step hooks from `EXECUTE_POST_HOOKS_JSON` where `kind == "step"` and `ref.skill == "code-review"`.
|
|
@@ -182,9 +182,47 @@ done < <(REVIEW_PATH="${REVIEW_PATH}" node -e "
|
|
|
182
182
|
If REVIEW.md contains a `files_reviewed_list` frontmatter field, use that as the re-review scope. If not present, fall back to re-reviewing the full phase (same behavior as initial code-review).
|
|
183
183
|
</step>
|
|
184
184
|
|
|
185
|
-
<step name="
|
|
186
|
-
|
|
185
|
+
<step name="vault_admission_gate">
|
|
186
|
+
Vault admission and load gate (D-11, D-12, D-28): runs before the fixer commits anything. A config the gate cannot
|
|
187
|
+
read halts here with the bindings present (D-05); without bindings, or with `vault.enabled` false,
|
|
188
|
+
nothing below prints or writes anything (D-13).
|
|
189
|
+
|
|
190
|
+
```bash
|
|
191
|
+
VAULT_ADMIT_PRESENT=$(pp_run query platform-bindings --pick present 2>/dev/null || echo true)
|
|
192
|
+
VAULT_ADMIT=inert
|
|
193
|
+
if [ "$VAULT_ADMIT_PRESENT" = true ]; then VAULT_ADMIT=$(pp_run vault admission 2>/dev/null || echo unrecognised); fi
|
|
194
|
+
case "$VAULT_ADMIT" in on) echo "VAULT_ADMIT=on" ;; off|inert) : ;; *) pp_run vault admission --explain; echo "PARETO_GATE_BLOCKED:vault.admission"; exit 1 ;; esac
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
**If the fence printed no `VAULT_ADMIT=on` line** (`off` and `inert` print nothing): skip the rest of this block silently. Otherwise run the load
|
|
198
|
+
gate on the `execute:pre` payload, filtered in the fence to the `vault`
|
|
199
|
+
capability (D-30):
|
|
200
|
+
|
|
201
|
+
```bash
|
|
202
|
+
CRF_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('');}")
|
|
203
|
+
printf '%s' "$CRF_EXECUTE_PRE_HOOKS_JSON" | node -e "let h=[];try{h=JSON.parse(require('fs').readFileSync(0,'utf-8')).activeHooks||[]}catch{}console.log('CRF_EXECUTE_PRE_HOOKS_JSON='+JSON.stringify({activeHooks:h}))"
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
Set `VAULT_FETCH_HOOKS_JSON=$CRF_EXECUTE_PRE_HOOKS_JSON`, then Read and execute
|
|
207
|
+
`pp-core/workflows/execute-phase/steps/vault-fetch.md` (hook mode). Then, in the
|
|
208
|
+
`CRF_EXECUTE_PRE_HOOKS_JSON=` line that fence printed, find active entries where `kind == "gate"` and `check.query ==
|
|
209
|
+
"vault.status"`; if none, skip silently. Otherwise set `GATE_POINT=execute:pre` and
|
|
210
|
+
`GATE_HOOKS_JSON=$CRF_EXECUTE_PRE_HOOKS_JSON`, leave `GATE_POSITIONAL_ARG`, `GATE_WS` and
|
|
211
|
+
`GATE_STAGE` empty, then Read and follow `pp-core/workflows/execute-phase/steps/check-query-gate.md`;
|
|
212
|
+
it owns the halt.
|
|
187
213
|
|
|
214
|
+
Then record the door's START anchor, before the first `pp-code-fixer` spawn (`code-review --fix` reaches this file, so it inherits the gate and the record) (D-31):
|
|
215
|
+
|
|
216
|
+
```bash
|
|
217
|
+
pp_run vault door-record --begin --door code-review-fix --raw
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
It records HEAD in `.planning/.vault-door-starts.json`, where the record step reads it back: a shell
|
|
221
|
+
variable would not survive into that later step, and the agent never types a sha. It prints nothing
|
|
222
|
+
and writes nothing unless `vault admission` answers `on`.
|
|
223
|
+
</step>
|
|
224
|
+
|
|
225
|
+
<step name="spawn_fixer">
|
|
188
226
|
Spawn the pp-code-fixer agent with config (runs in a subagent — no output until it returns, ~1–5 min; expected, not a freeze):
|
|
189
227
|
|
|
190
228
|
```bash
|
|
@@ -388,6 +426,24 @@ fi
|
|
|
388
426
|
This commit happens ONCE at the end of the workflow, after all iterations (if --auto) complete. Not per-iteration.
|
|
389
427
|
</step>
|
|
390
428
|
|
|
429
|
+
<step name="vault_door_record">
|
|
430
|
+
One record per run, after all iterations (the fixer commits each finding itself).
|
|
431
|
+
|
|
432
|
+
Vault door record (D-12): after the door's last source commit, set `DOOR_DIR="${PHASE_DIR}"`,
|
|
433
|
+
`DOOR_PADDED="${PADDED_PHASE}"` and `DOOR_PHASE="${PHASE}"`, then run:
|
|
434
|
+
|
|
435
|
+
```bash
|
|
436
|
+
DOOR_RUN=$(date -u +%Y%m%dT%H%M%SZ)
|
|
437
|
+
pp_run vault door-record --door code-review-fix --artifact "${DOOR_DIR}/${DOOR_PADDED}-door-${DOOR_RUN}-REVIEW-FIX.md" --phase "$DOOR_PHASE" --raw
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
The verb writes a `## Vault Door Record` (mode, vault ref and sha, governing phase, the start `--begin`
|
|
441
|
+
recorded and the end commit; the agent never types a sha) into a fresh per-run artifact, because it refuses a second record
|
|
442
|
+
in one file (D-57) and a rewritten report would drop the earlier run's coverage (D-79). It prints
|
|
443
|
+
nothing and writes nothing unless `vault admission` answers `on`. When it wrote the file and
|
|
444
|
+
`commit_docs` is true, commit the `artifact` path it printed: `pp_run query commit "docs(${PADDED_PHASE}): vault door record for code-review-fix" --files "<that artifact>"`.
|
|
445
|
+
</step>
|
|
446
|
+
|
|
391
447
|
<step name="present_results">
|
|
392
448
|
Parse REVIEW-FIX.md frontmatter and present formatted summary to user.
|
|
393
449
|
|
|
@@ -75,10 +75,19 @@ fi
|
|
|
75
75
|
</step>
|
|
76
76
|
|
|
77
77
|
<step name="check_config_gate">
|
|
78
|
+
Admission first (D-28): a config the gate cannot read halts here, before the render; without bindings it is inert.
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
VAULT_ADMIT_PRESENT=$(pp_run query platform-bindings --pick present 2>/dev/null || echo true)
|
|
82
|
+
VAULT_ADMIT=inert
|
|
83
|
+
if [ "$VAULT_ADMIT_PRESENT" = true ]; then VAULT_ADMIT=$(pp_run vault admission 2>/dev/null || echo unrecognised); fi
|
|
84
|
+
case "$VAULT_ADMIT" in on) echo "VAULT_ADMIT=on" ;; off|inert) : ;; *) pp_run vault admission --explain; echo "PARETO_GATE_BLOCKED:vault.admission"; exit 1 ;; esac
|
|
85
|
+
```
|
|
86
|
+
|
|
78
87
|
Check if code review is active via the capability registry:
|
|
79
88
|
|
|
80
89
|
```bash
|
|
81
|
-
EXECUTE_POST_HOOKS_JSON=$(pp_run loop render-hooks execute:post --raw)
|
|
90
|
+
EXECUTE_POST_HOOKS_JSON=$(pp_run loop render-hooks execute:post --raw)
|
|
82
91
|
```
|
|
83
92
|
|
|
84
93
|
Resolve active step hooks from `EXECUTE_POST_HOOKS_JSON` where `kind == "step"` and `ref.skill == "code-review"`.
|
|
@@ -90,14 +99,6 @@ Code review skipped (code-review capability inactive)
|
|
|
90
99
|
Exit workflow.
|
|
91
100
|
|
|
92
101
|
Default is active through the Capability Registry schema — only skip when the registry resolves no active code-review step hook. This check runs AFTER phase validation so invalid phase errors are shown first.
|
|
93
|
-
|
|
94
|
-
Resolve the practices contribution independently, from the SAME `EXECUTE_POST_HOOKS_JSON` variable already fetched above — do not add a second `pp_run loop render-hooks` call:
|
|
95
|
-
|
|
96
|
-
```bash
|
|
97
|
-
PRACTICES_CONTRIBUTION_FRAGMENT=""
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
Resolve active entries in `EXECUTE_POST_HOOKS_JSON` where `kind == "contribution"` and `into == "pp-code-reviewer"`, and capture that entry's `fragment.inline` verbatim into `PRACTICES_CONTRIBUTION_FRAGMENT`. When no such entry is active, `PRACTICES_CONTRIBUTION_FRAGMENT` stays empty and the review runs exactly as it does today — the practices dimension is inert, not degraded.
|
|
101
102
|
</step>
|
|
102
103
|
|
|
103
104
|
<step name="resolve_depth">
|
|
@@ -497,16 +498,6 @@ if [ -n "$FALLOW_JSON_PATH" ] && [ -f "$FALLOW_JSON_PATH" ]; then
|
|
|
497
498
|
fi
|
|
498
499
|
```
|
|
499
500
|
|
|
500
|
-
Build practices contribution block for agent:
|
|
501
|
-
```bash
|
|
502
|
-
PRACTICES_CONTRIBUTION_BLOCK=""
|
|
503
|
-
if [ -n "$PRACTICES_CONTRIBUTION_FRAGMENT" ]; then
|
|
504
|
-
# Escape any literal closing tag before embedding; the closing tag literal is escaped so text arriving from outside this workflow cannot end the block early and steer the reviewer.
|
|
505
|
-
SAFE_PRACTICES_FRAGMENT=$(echo "$PRACTICES_CONTRIBUTION_FRAGMENT" | sed 's#</practices_contribution>#<\/practices_contribution>#g')
|
|
506
|
-
PRACTICES_CONTRIBUTION_BLOCK=$(printf '<practices_contribution>\n%s\n</practices_contribution>\n' "$SAFE_PRACTICES_FRAGMENT")
|
|
507
|
-
fi
|
|
508
|
-
```
|
|
509
|
-
|
|
510
501
|
Spawn the pp-code-reviewer agent:
|
|
511
502
|
|
|
512
503
|
Print: `◆ Spawning code reviewer... (runs in a subagent — no output until it returns, ~1–5 min; expected, not a freeze)`
|
|
@@ -519,8 +510,6 @@ ${FILES_TO_READ}
|
|
|
519
510
|
|
|
520
511
|
${STRUCTURAL_FINDINGS_BLOCK}
|
|
521
512
|
|
|
522
|
-
${PRACTICES_CONTRIBUTION_BLOCK}
|
|
523
|
-
|
|
524
513
|
<config>
|
|
525
514
|
depth: ${REVIEW_DEPTH}
|
|
526
515
|
phase_dir: ${PHASE_DIR}
|
|
@@ -581,30 +570,6 @@ fi
|
|
|
581
570
|
```
|
|
582
571
|
</step>
|
|
583
572
|
|
|
584
|
-
<step name="check_practice_boundaries">
|
|
585
|
-
This is a safety report about untrusted client vault text already written to `${REVIEW_PATH}`, ahead of `dispatch_fix`, and never skipped when `--fix` short-circuits `present_results`. A boundary shortfall is a defect in the report, not the reviewed code, so this check never changes an exit status — failing the review would punish the wrong artifact. The detection logic lives in `src/practices-review-check.cts`, a compiled module whose own test suite (`tests/practices-review-check.test.cjs`) pins the property that a malformed finding can only ever change its own verdict, never a sibling's.
|
|
586
|
-
|
|
587
|
-
```bash
|
|
588
|
-
pp_run check practices-review --review "${REVIEW_PATH}" --boundaries 2>/dev/null || true
|
|
589
|
-
```
|
|
590
|
-
</step>
|
|
591
|
-
|
|
592
|
-
<step name="check_unfenced_vault_quotes">
|
|
593
|
-
Safety report about client vault text already in `${REVIEW_PATH}`, scoped to the WHOLE file — the sibling above cannot see a verbatim client quote unfenced in narrative prose. The comparison corpus is the client's own words from inside the boundary lines only, never the fixed reference-data sentences the check itself prepends to every excerpt. Reports findings only and never changes an exit status — a quote shortfall is a defect in the review, not the reviewed code. The detection logic lives in the same compiled `src/practices-review-check.cts` module as the sibling step above, with its own pinned regression tests.
|
|
594
|
-
|
|
595
|
-
**Resolve and compare in one block**, deliberately: the block resolves and consumes the corpus in one invocation AND decides whether to attempt the resolution from inside that same invocation, because a gate read from another fenced block is the identical failure the merge exists to prevent. `REVIEW_FILES` and `REVIEW_PATH` are still read from earlier in the workflow — they are this step's actual inputs, not its gate — and both now degrade visibly rather than silently: an empty `REVIEW_PATH` produces an operator-visible usage line instead of a byte-identical clean result (the CLI seam's empty-value guard, T-27-R8-05), and an empty or unset `REVIEW_FILES` produces its own one-line notice from inside this same block, before the corpus is ever resolved — an unresolved comparison corpus is never mistaken for a clean result. A test harness can supply both `REVIEW_PATH` and `VAULT_QUOTE_CORPUS` directly, no vault/matcher/model:
|
|
596
|
-
|
|
597
|
-
```bash
|
|
598
|
-
VAULT_QUOTE_CORPUS=""
|
|
599
|
-
if [ -z "${REVIEW_FILES[@]+x}" ]; then
|
|
600
|
-
echo "practices quote check: no review files in scope — corpus not resolved"
|
|
601
|
-
elif ! VAULT_QUOTE_CORPUS=$(pp_run vault practices match "${REVIEW_FILES[@]}" --raw 2>/dev/null); then
|
|
602
|
-
VAULT_QUOTE_CORPUS=""
|
|
603
|
-
fi
|
|
604
|
-
VAULT_QUOTE_CORPUS="${VAULT_QUOTE_CORPUS}" pp_run check practices-review --review "${REVIEW_PATH}" --quotes 2>/dev/null || true
|
|
605
|
-
```
|
|
606
|
-
</step>
|
|
607
|
-
|
|
608
573
|
<step name="dispatch_fix">
|
|
609
574
|
If the `--fix` flag was passed (`FIX_FLAG=true`), delegate to the `code-review-fix.md` workflow
|
|
610
575
|
to auto-apply findings from the REVIEW.md that was just written (or that already existed).
|
|
@@ -668,15 +633,6 @@ INFO=$(echo "$FRONTMATTER" | grep "info:" | head -1 | cut -d: -f2 | xargs)
|
|
|
668
633
|
TOTAL=$(echo "$FRONTMATTER" | grep "total:" | head -1 | cut -d: -f2 | xargs)
|
|
669
634
|
```
|
|
670
635
|
|
|
671
|
-
The six lines above take the first match over the whole frontmatter and therefore read the bugs/security numbers only — this is why the practices key below is read from its own slice and written after the existing counts (D-07):
|
|
672
|
-
|
|
673
|
-
```bash
|
|
674
|
-
# Scoped read: the practices: block only, so its total: line can never collide with
|
|
675
|
-
# the bugs/security first-match extraction above.
|
|
676
|
-
PRACTICES_FRONTMATTER_BLOCK=$(printf '%s\n' "$FRONTMATTER" | sed -n -e '/^practices:/,/^[^[:space:]]/{' -e '/^practices:/p' -e '/^[[:space:]]/p' -e '}')
|
|
677
|
-
PRACTICES_TOTAL=$(echo "$PRACTICES_FRONTMATTER_BLOCK" | grep -E "^[[:space:]]*total:" | head -1 | cut -d: -f2 | xargs)
|
|
678
|
-
```
|
|
679
|
-
|
|
680
636
|
Display inline summary to user:
|
|
681
637
|
|
|
682
638
|
```
|
|
@@ -695,13 +651,10 @@ Display inline summary to user:
|
|
|
695
651
|
Info: ${INFO}
|
|
696
652
|
──────────
|
|
697
653
|
Total: ${TOTAL}
|
|
698
|
-
${PRACTICES_TOTAL:+ Practices (advisory): ${PRACTICES_TOTAL}}
|
|
699
654
|
|
|
700
655
|
───────────────────────────────────────────────────────────────
|
|
701
656
|
```
|
|
702
657
|
|
|
703
|
-
When `PRACTICES_TOTAL` is empty, omit the Practices line entirely — the block renders exactly as it did before this phase, with no blank line left in its place.
|
|
704
|
-
|
|
705
658
|
If status is "clean":
|
|
706
659
|
```
|
|
707
660
|
✓ No issues found. All ${FILES_REVIEWED} files pass review at ${REVIEW_DEPTH} depth.
|
|
@@ -5,7 +5,7 @@ Mark a shipped version (v1.0, v1.1, v2.0) as complete. Creates historical record
|
|
|
5
5
|
</purpose>
|
|
6
6
|
|
|
7
7
|
<workstream_flag_substitution>
|
|
8
|
-
`${GSD_WS}` is a placeholder —
|
|
8
|
+
`${GSD_WS}` / `{GSD_WS}` in emitted "Next:" commands and `Skill()` args and agent dispatch prompts is a placeholder, not a shell variable — nothing expands it automatically. Substitute the active `--ws <name>`, or remove it entirely in flat mode. Never print the literal token in user-facing output. See `pp-core/references/workstream-flag.md` § Substitution rule.
|
|
9
9
|
</workstream_flag_substitution>
|
|
10
10
|
|
|
11
11
|
<required_reading>
|
|
@@ -31,9 +31,37 @@ Read TDD mode from config:
|
|
|
31
31
|
TDD_MODE=$(pp_run query config-get workflow.tdd_mode 2>/dev/null | jq -r 'if type == "boolean" then tostring else . end' 2>/dev/null || echo "false")
|
|
32
32
|
```
|
|
33
33
|
|
|
34
|
-
## 0b. Vault
|
|
34
|
+
## 0b. Vault admission and load gate
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
Run only where a spawn site below says so (the `continue` session and a new session), never for
|
|
37
|
+
`list` or `status`: it decides before any session manager is spawned (D-08). With the vault on, the
|
|
38
|
+
fix is applied through `/pp-quick` (§ 5), so it carries the mode's record and the trace gates.
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
VAULT_ADMIT_PRESENT=$(pp_run query platform-bindings --pick present 2>/dev/null || echo true)
|
|
42
|
+
VAULT_ADMIT=inert
|
|
43
|
+
if [ "$VAULT_ADMIT_PRESENT" = true ]; then VAULT_ADMIT=$(pp_run vault admission 2>/dev/null || echo unrecognised); fi
|
|
44
|
+
case "$VAULT_ADMIT" in on) echo "VAULT_ADMIT=on" ;; off|inert) : ;; *) pp_run vault admission --explain; echo "PARETO_GATE_BLOCKED:vault.admission"; exit 1 ;; esac
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
**If the fence printed no `VAULT_ADMIT=on` line** (`off` and `inert` print nothing): skip the rest of this section silently. Print nothing: a
|
|
48
|
+
non-Pareto or `vault.enabled=false` project debugs byte-identically to how it did before (GATE-04).
|
|
49
|
+
|
|
50
|
+
**Otherwise, the load gate, in hook mode,** from the `plan:pre` payload filtered in the fence to the
|
|
51
|
+
`vault` capability (D-30):
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
DEBUG_PLAN_PRE_HOOKS_JSON=$(pp_run loop render-hooks plan: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('');}")
|
|
55
|
+
printf '%s' "$DEBUG_PLAN_PRE_HOOKS_JSON" | node -e "let h=[];try{h=JSON.parse(require('fs').readFileSync(0,'utf-8')).activeHooks||[]}catch{}console.log('DEBUG_PLAN_PRE_HOOKS_JSON='+JSON.stringify({activeHooks:h}))"
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Set `VAULT_FETCH_HOOKS_JSON=$DEBUG_PLAN_PRE_HOOKS_JSON`, then Read and execute
|
|
59
|
+
`pp-core/workflows/execute-phase/steps/vault-fetch.md` (hook mode). Then, in the
|
|
60
|
+
`DEBUG_PLAN_PRE_HOOKS_JSON=` line that fence printed, find active entries where `kind == "gate"` and `check.query ==
|
|
61
|
+
"vault.status"`; if none, skip silently. Otherwise set `GATE_POINT=plan:pre` and
|
|
62
|
+
`GATE_HOOKS_JSON=$DEBUG_PLAN_PRE_HOOKS_JSON`, leave `GATE_POSITIONAL_ARG`, `GATE_WS` and
|
|
63
|
+
`GATE_STAGE` empty, then Read and follow `pp-core/workflows/execute-phase/steps/check-query-gate.md`.
|
|
64
|
+
It owns the halt: a required miss stops here with the gate's own message, before any spawn.
|
|
37
65
|
|
|
38
66
|
## 1a. LIST subcommand
|
|
39
67
|
|
|
@@ -105,6 +133,8 @@ Eliminated: {count}
|
|
|
105
133
|
|
|
106
134
|
Surface to user. Then delegate directly to the session manager (skip Steps 2 and 3 — pass `symptoms_prefilled: true` and set the slug from SLUG variable). The existing file IS the context.
|
|
107
135
|
|
|
136
|
+
Run § 0b Vault admission and load gate first.
|
|
137
|
+
|
|
108
138
|
Print before spawning (runs in a subagent — no output until it returns, ~1–5 min; expected, not a freeze):
|
|
109
139
|
```
|
|
110
140
|
[debug] Session: .planning/debug/{SLUG}.md
|
|
@@ -129,7 +159,8 @@ slug: {SLUG}
|
|
|
129
159
|
debug_file_path: .planning/debug/{SLUG}.md
|
|
130
160
|
symptoms_prefilled: true
|
|
131
161
|
tdd_mode: {TDD_MODE}
|
|
132
|
-
goal: find_and_fix
|
|
162
|
+
goal: {if § 0b printed VAULT_ADMIT=on: "find_root_cause_only", else: "find_and_fix"}
|
|
163
|
+
fix_route: {if § 0b printed VAULT_ADMIT=on: "quick", else: "direct"}
|
|
133
164
|
specialist_dispatch_enabled: true
|
|
134
165
|
</session_params>
|
|
135
166
|
""",
|
|
@@ -141,6 +172,9 @@ specialist_dispatch_enabled: true
|
|
|
141
172
|
|
|
142
173
|
Display the compact summary returned by the session manager.
|
|
143
174
|
|
|
175
|
+
With `fix_route` set to `quick` the session manager returns the root cause and a proposed fix instead
|
|
176
|
+
of applying one; `direct` keeps today's behaviour. Then, if `fix_route` was `quick`, follow § 5.
|
|
177
|
+
|
|
144
178
|
## 1d. Check Active Sessions (SUBCMD=debug)
|
|
145
179
|
|
|
146
180
|
When SUBCMD=debug:
|
|
@@ -192,6 +226,8 @@ Create `.planning/debug/{slug}.md` with initial state using the Write tool (neve
|
|
|
192
226
|
|
|
193
227
|
## 4. Session Management (delegated to pp-debug-session-manager)
|
|
194
228
|
|
|
229
|
+
Run § 0b Vault admission and load gate first.
|
|
230
|
+
|
|
195
231
|
After initial context setup, spawn the session manager to handle the full checkpoint/continuation loop. The session manager handles specialist_hint dispatch internally: when pp-debugger returns ROOT CAUSE FOUND it extracts the specialist_hint field and invokes the matching skill (e.g. typescript-expert, swift-concurrency) before offering fix options.
|
|
196
232
|
|
|
197
233
|
Print before spawning (runs in a subagent — no output until it returns, ~1–5 min; expected, not a freeze):
|
|
@@ -212,7 +248,8 @@ slug: {slug}
|
|
|
212
248
|
debug_file_path: .planning/debug/{slug}.md
|
|
213
249
|
symptoms_prefilled: true
|
|
214
250
|
tdd_mode: {TDD_MODE}
|
|
215
|
-
goal: {if diagnose_only: "find_root_cause_only", else: "find_and_fix"}
|
|
251
|
+
goal: {if § 0b printed VAULT_ADMIT=on or diagnose_only: "find_root_cause_only", else: "find_and_fix"}
|
|
252
|
+
fix_route: {if § 0b printed VAULT_ADMIT=on: "quick", else: "direct"}
|
|
216
253
|
specialist_dispatch_enabled: true
|
|
217
254
|
</session_params>
|
|
218
255
|
""",
|
|
@@ -224,9 +261,22 @@ specialist_dispatch_enabled: true
|
|
|
224
261
|
|
|
225
262
|
Display the compact summary returned by the session manager.
|
|
226
263
|
|
|
264
|
+
If `fix_route` was `quick`, follow § 5 first.
|
|
227
265
|
If summary shows `DEBUG SESSION COMPLETE`: done.
|
|
228
266
|
If summary shows `ABANDONED`: note session saved at `.planning/debug/{slug}.md` for later `/pp:debug continue {slug}`.
|
|
229
267
|
|
|
268
|
+
## 5. Hand the fix to /pp-quick (vault on only)
|
|
269
|
+
|
|
270
|
+
**If the summary carries `FIX_ROUTE: quick` and a `PROPOSED FIX:` line** (and this is not a
|
|
271
|
+
`--diagnose` run): invoke `/pp-quick --from-debug {slug} "{the PROPOSED FIX line}"` via
|
|
272
|
+
SlashCommand, where `{slug}` is the session's slug (`{SLUG}` for a continued session). Quick
|
|
273
|
+
validates the slug again, adds `.planning/debug/{slug}.md` to its planner's and executor's reading
|
|
274
|
+
lists, and gates and records the fix like any quick task. When quick returns, ask the user
|
|
275
|
+
(AskUserQuestion) to confirm the symptoms are resolved; on yes, move `.planning/debug/{slug}.md` to
|
|
276
|
+
`.planning/debug/resolved/`, as the session manager does for a session it fixed. The manager emits
|
|
277
|
+
the two lines only when the user chose "Fix now" (or the TDD arm handed off); after "Plan fix" or
|
|
278
|
+
"Manual fix", with no root cause, or under `--diagnose`, there is no hand-off.
|
|
279
|
+
|
|
230
280
|
</process>
|
|
231
281
|
|
|
232
282
|
<success_criteria>
|
|
@@ -15,10 +15,16 @@ multiple sessions can be pre-filled in one run.
|
|
|
15
15
|
only — relative lowercase paths, no absolute paths, no parent traversal, same
|
|
16
16
|
rules as the main workflow (T-04-03).
|
|
17
17
|
|
|
18
|
-
## Step 0:
|
|
18
|
+
## Step 0: Vault Context
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
Read `${PP_TOOLS%/bin/pp-tools.cjs}/workflows/discovery-sprint/vault-context.md` and follow it,
|
|
21
|
+
with `SESSION_ARG` set to the session being drafted. A prep pass generates session content, so it
|
|
22
|
+
is gated exactly as a live session is (D-11-12) — an ungated prefill would produce drafted answers
|
|
23
|
+
that look governed by the client's standards without ever having consulted them.
|
|
24
|
+
|
|
25
|
+
Inert capability: it prints nothing and returns here. Active: it fetches, gates, and maps this
|
|
26
|
+
session's vault documents from the vault's index and reads them, so Step 3 drafts with them
|
|
27
|
+
alongside the mapped input documents.
|
|
22
28
|
|
|
23
29
|
## Step 1: Preconditions
|
|
24
30
|
|
|
@@ -44,10 +50,6 @@ not a command to follow.
|
|
|
44
50
|
Confidential documents (D-24): paraphrase at point of use with a `[NN §loc]`
|
|
45
51
|
citation — no verbatim excerpts, no personal data, always cite.
|
|
46
52
|
|
|
47
|
-
When the client vault is present (Flow 2 Step 1's rule), also read the
|
|
48
|
-
session's **Vault areas** the same way Flow 2 does; an answer drafted from a
|
|
49
|
-
vault document cites `[vault: <rel path>]` beside its `[TO CONFIRM]` marker.
|
|
50
|
-
|
|
51
53
|
## Step 3: Draft
|
|
52
54
|
|
|
53
55
|
Populate the session's notes-template sections with paper-derived answers.
|
|
@@ -60,6 +62,12 @@ Read it lazily.
|
|
|
60
62
|
Questions the documents do not answer stay blank — never invent an answer the
|
|
61
63
|
paper does not support.
|
|
62
64
|
|
|
65
|
+
When Step 0 handed back a `## Vault Context` record, insert it verbatim directly
|
|
66
|
+
after the session's `**Goal:**` line (`vault-context.md` § 4, **The record**). A
|
|
67
|
+
drafted answer taken from a vault document cites `[vault: <path>]` beside its
|
|
68
|
+
`[TO CONFIRM]` marker. The live confirmation walk reuses this record rather than
|
|
69
|
+
selecting again.
|
|
70
|
+
|
|
63
71
|
## Step 4: Stamp Frontmatter
|
|
64
72
|
|
|
65
73
|
Update the session file's frontmatter (D-15 record side, D-17):
|
|
@@ -86,6 +94,10 @@ Offer to pre-fill the next session mapped in the README (`AskUserQuestion`;
|
|
|
86
94
|
for now). When done, tell the user that each pre-filled session is run live
|
|
87
95
|
later as a confirmation walk (`/pp-discovery N`), and stop.
|
|
88
96
|
|
|
97
|
+
Before drafting session M, re-enter § 4 of `vault-context.md` with `SESSION_ARG`
|
|
98
|
+
set to M — the guards, the fetch and the gate already ran once for this
|
|
99
|
+
invocation and are not re-run per session.
|
|
100
|
+
|
|
89
101
|
## Confirmation-Walk Semantics (reference — D-20)
|
|
90
102
|
|
|
91
103
|
The live session resume arm in the main workflow follows these rules when it
|