@pareto4/pp-core 1.13.0 → 1.17.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +3 -3
- package/README.md +26 -9
- package/agents/pp-code-reviewer.md +2 -1
- package/agents/pp-debug-session-manager.md +9 -6
- package/agents/pp-executor.md +10 -13
- package/agents/pp-plan-checker.md +4 -4
- package/agents/pp-planner.md +23 -9
- package/agents/pp-vault-reviewer.md +244 -21
- package/agents/pp-verifier.md +7 -3
- package/bin/install.js +10 -3
- package/commands/pp-execute-phase.md +1 -3
- package/commands/pp-ns-review.md +1 -1
- package/commands/pp-plan-phase.md +1 -2
- package/commands/pp-vault-review.md +5 -3
- 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 +14 -19
- 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 +396 -82
- package/pp-core/bin/lib/capability-state.cjs +160 -4
- package/pp-core/bin/lib/capability-writer.cjs +19 -5
- package/pp-core/bin/lib/check-command-router.cjs +3334 -946
- 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 +154 -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 +13 -11
- package/pp-core/bin/lib/git-provider.cjs +4 -4
- package/pp-core/bin/lib/init-command-router.cjs +5 -8
- package/pp-core/bin/lib/init-contract.cjs +648 -738
- package/pp-core/bin/lib/init-interactive.cjs +76 -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 +8 -0
- package/pp-core/bin/lib/loop-resolver.cjs +189 -129
- package/pp-core/bin/lib/org-profile.cjs +469 -152
- 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/practices-review-check.cjs +15 -9
- 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-audit.cjs +650 -126
- package/pp-core/bin/lib/vault-command-router.cjs +2604 -367
- package/pp-core/bin/lib/vault-coordinates.cjs +13 -4
- package/pp-core/bin/lib/vault-index.cjs +699 -0
- package/pp-core/bin/lib/vault-mode.cjs +235 -0
- package/pp-core/bin/lib/vault-practices.cjs +139 -72
- package/pp-core/bin/lib/vault-review.cjs +194 -451
- package/pp-core/bin/lib/vault-seal.cjs +1936 -0
- package/pp-core/bin/lib/vault-standards.cjs +1505 -0
- package/pp-core/bin/lib/vault-trace.cjs +607 -254
- package/pp-core/bin/lib/vault-update.cjs +9 -33
- package/pp-core/bin/lib/vault-write-back.cjs +70 -42
- package/pp-core/bin/lib/vault.cjs +2734 -920
- 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 +184 -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-practices.md +17 -34
- package/pp-core/references/planner-vault-standards.md +320 -0
- package/pp-core/references/planning-config.md +0 -8
- package/pp-core/references/practice-arithmetic-contract.md +121 -0
- package/pp-core/references/tdd.md +0 -1
- package/pp-core/references/verifier-practice-verdicts.md +263 -0
- package/pp-core/templates/README.md +1 -0
- package/pp-core/templates/VAULT-REVIEW.md +202 -0
- package/pp-core/templates/phase-prompt.md +2 -6
- package/pp-core/templates/practices/README.md +20 -23
- 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 -1
- 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 +213 -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 +329 -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 +98 -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 +322 -20
- package/pp-core/workflows/execute-phase/steps/verifier-practice-payload.md +165 -0
- package/pp-core/workflows/execute-phase/steps/verify-post-gate.md +163 -0
- package/pp-core/workflows/execute-phase.md +155 -128
- package/pp-core/workflows/execute-plan.md +56 -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 +282 -22
- 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 +199 -11
- package/scripts/gen-practice-arithmetic-contract.cjs +412 -0
- 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 +12 -10
- package/scripts/practice-arithmetic-contract.allow.json +35 -0
- package/scripts/prompt-injection-scan.sh +22 -17
- package/scripts/record-vault-mode-golden.cjs +89 -0
- 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/vault-calibrate.cjs +996 -0
- 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/references/executor-vault-trace.md +0 -47
- package/pp-core/references/planner-plan-graph.md +0 -66
- 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
|
@@ -67,6 +67,47 @@ Present banner:
|
|
|
67
67
|
```
|
|
68
68
|
</step>
|
|
69
69
|
|
|
70
|
+
<step name="vault_admission_gate">
|
|
71
|
+
Vault admission and load gate (D-11, D-12, D-28): runs before a test is written or committed. A config the gate cannot
|
|
72
|
+
read halts here with the bindings present (D-05); without bindings, or with `vault.enabled` false,
|
|
73
|
+
nothing below prints or writes anything (D-13).
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
VAULT_ADMIT_PRESENT=$(pp_run query platform-bindings --pick present 2>/dev/null || echo true)
|
|
77
|
+
VAULT_ADMIT=inert
|
|
78
|
+
if [ "$VAULT_ADMIT_PRESENT" = true ]; then VAULT_ADMIT=$(pp_run vault admission 2>/dev/null || echo unrecognised); fi
|
|
79
|
+
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
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
**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
|
|
83
|
+
gate on the `execute:pre` payload, filtered in the fence to the `vault` and `vault-practices`
|
|
84
|
+
capabilities (D-30):
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
AT_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'||x.capId==='vault-practices'));process.stdout.write(JSON.stringify(j));}catch{process.stdout.write('');}")
|
|
88
|
+
printf '%s' "$AT_EXECUTE_PRE_HOOKS_JSON" | node -e "let h=[];try{h=JSON.parse(require('fs').readFileSync(0,'utf-8')).activeHooks||[]}catch{}console.log('AT_EXECUTE_PRE_HOOKS_JSON='+JSON.stringify({activeHooks:h}))"
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Set `VAULT_FETCH_HOOKS_JSON=$AT_EXECUTE_PRE_HOOKS_JSON`, then Read and execute
|
|
92
|
+
`pp-core/workflows/execute-phase/steps/vault-fetch.md` (hook mode). Then, in the
|
|
93
|
+
`AT_EXECUTE_PRE_HOOKS_JSON=` line that fence printed, find active entries where `kind == "gate"` and `check.query ==
|
|
94
|
+
"vault.status"`; if none, skip silently. Otherwise set `GATE_POINT=execute:pre` and
|
|
95
|
+
`GATE_HOOKS_JSON=$AT_EXECUTE_PRE_HOOKS_JSON`, leave `GATE_POSITIONAL_ARG`, `GATE_WS` and
|
|
96
|
+
`GATE_STAGE` empty, then Read and follow `pp-core/workflows/execute-phase/steps/check-query-gate.md`;
|
|
97
|
+
it owns the halt.
|
|
98
|
+
|
|
99
|
+
Then record the door's START anchor, before the first test file is written (`execute_tdd_generation`) (D-31):
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
pp_run vault door-record --begin --door add-tests --raw
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
It records HEAD in `.planning/.vault-door-starts.json`, where the record step reads it back: a shell
|
|
106
|
+
variable would not survive into that later step, and the agent never types a sha. It prints nothing
|
|
107
|
+
and writes nothing unless `vault admission` answers `on`.
|
|
108
|
+
Take `padded_phase` from the same init JSON for the record below.
|
|
109
|
+
</step>
|
|
110
|
+
|
|
70
111
|
<step name="analyze_implementation">
|
|
71
112
|
Extract the list of files modified by the phase from SUMMARY.md ("Files Changed" or equivalent section).
|
|
72
113
|
|
|
@@ -212,10 +253,6 @@ If "Cherry-pick": ask user which tests to include.
|
|
|
212
253
|
If "Adjust plan": apply changes and re-present.
|
|
213
254
|
</step>
|
|
214
255
|
|
|
215
|
-
<step name="vault_door_gate">
|
|
216
|
-
Before any test file is written, Read and execute `pp-core/workflows/execute-phase/steps/vault-door-gate.md`; a stop ends this run with no test written.
|
|
217
|
-
</step>
|
|
218
|
-
|
|
219
256
|
<step name="execute_tdd_generation">
|
|
220
257
|
For each approved TDD test:
|
|
221
258
|
|
|
@@ -315,6 +352,20 @@ git add {test files}
|
|
|
315
352
|
git commit -m "test(phase-${phase_number}): add unit and E2E tests from add-tests command"
|
|
316
353
|
```
|
|
317
354
|
|
|
355
|
+
Vault door record (D-12): after the door's last source commit, set `DOOR_DIR="${phase_dir}"`,
|
|
356
|
+
`DOOR_PADDED="${padded_phase}"` and `DOOR_PHASE="${phase_number}"`, then run:
|
|
357
|
+
|
|
358
|
+
```bash
|
|
359
|
+
DOOR_RUN=$(date -u +%Y%m%dT%H%M%SZ)
|
|
360
|
+
pp_run vault door-record --door add-tests --artifact "${DOOR_DIR}/${DOOR_PADDED}-door-${DOOR_RUN}-ADD-TESTS.md" --phase "$DOOR_PHASE" --raw
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
The verb writes a `## Vault Door Record` (mode, vault ref and sha, governing phase, the start `--begin`
|
|
364
|
+
recorded and the end commit; the agent never types a sha) into a fresh per-run artifact, because it refuses a second record
|
|
365
|
+
in one file (D-57) and a rewritten report would drop the earlier run's coverage (D-79). It prints
|
|
366
|
+
nothing and writes nothing unless `vault admission` answers `on`. When it wrote the file and
|
|
367
|
+
`commit_docs` is true, commit the `artifact` path it printed: `pp_run query commit "docs(phase-${phase_number}): vault door record for add-tests" --files "<that artifact>"`.
|
|
368
|
+
|
|
318
369
|
Present next steps:
|
|
319
370
|
|
|
320
371
|
```
|
|
@@ -91,9 +91,49 @@ If `--dry-run` was specified, **stop here and exit**. The classification table i
|
|
|
91
91
|
final output — do not proceed to fixing.
|
|
92
92
|
</step>
|
|
93
93
|
|
|
94
|
-
<step name="
|
|
95
|
-
|
|
94
|
+
<step name="vault_admission_gate">
|
|
95
|
+
Skipped under `--dry-run` (nothing is fixed).
|
|
96
|
+
|
|
97
|
+
Vault admission and load gate (D-11, D-12, D-28): runs before any finding is fixed. A config the gate cannot
|
|
98
|
+
read halts here with the bindings present (D-05); without bindings, or with `vault.enabled` false,
|
|
99
|
+
nothing below prints or writes anything (D-13).
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
VAULT_ADMIT_PRESENT=$(pp_run query platform-bindings --pick present 2>/dev/null || echo true)
|
|
103
|
+
VAULT_ADMIT=inert
|
|
104
|
+
if [ "$VAULT_ADMIT_PRESENT" = true ]; then VAULT_ADMIT=$(pp_run vault admission 2>/dev/null || echo unrecognised); fi
|
|
105
|
+
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
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
**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
|
|
109
|
+
gate on the `execute:pre` payload, filtered in the fence to the `vault` and `vault-practices`
|
|
110
|
+
capabilities (D-30):
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
AF_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'||x.capId==='vault-practices'));process.stdout.write(JSON.stringify(j));}catch{process.stdout.write('');}")
|
|
114
|
+
printf '%s' "$AF_EXECUTE_PRE_HOOKS_JSON" | node -e "let h=[];try{h=JSON.parse(require('fs').readFileSync(0,'utf-8')).activeHooks||[]}catch{}console.log('AF_EXECUTE_PRE_HOOKS_JSON='+JSON.stringify({activeHooks:h}))"
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Set `VAULT_FETCH_HOOKS_JSON=$AF_EXECUTE_PRE_HOOKS_JSON`, then Read and execute
|
|
118
|
+
`pp-core/workflows/execute-phase/steps/vault-fetch.md` (hook mode). Then, in the
|
|
119
|
+
`AF_EXECUTE_PRE_HOOKS_JSON=` line that fence printed, find active entries where `kind == "gate"` and `check.query ==
|
|
120
|
+
"vault.status"`; if none, skip silently. Otherwise set `GATE_POINT=execute:pre` and
|
|
121
|
+
`GATE_HOOKS_JSON=$AF_EXECUTE_PRE_HOOKS_JSON`, leave `GATE_POSITIONAL_ARG`, `GATE_WS` and
|
|
122
|
+
`GATE_STAGE` empty, then Read and follow `pp-core/workflows/execute-phase/steps/check-query-gate.md`;
|
|
123
|
+
it owns the halt.
|
|
124
|
+
|
|
125
|
+
Then record the door's START anchor, before the first `pp-executor` spawn of the fix loop (D-31):
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
pp_run vault door-record --begin --door audit-fix --raw
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
It records HEAD in `.planning/.vault-door-starts.json`, where the record step reads it back: a shell
|
|
132
|
+
variable would not survive into that later step, and the agent never types a sha. It prints nothing
|
|
133
|
+
and writes nothing unless `vault admission` answers `on`.
|
|
134
|
+
</step>
|
|
96
135
|
|
|
136
|
+
<step name="fix-loop">
|
|
97
137
|
For each **auto-fixable** finding (up to `--max`, ordered by severity desc):
|
|
98
138
|
|
|
99
139
|
**a. Spawn executor agent** (runs in a subagent — no output until it returns, ~1–5 min; expected, not a freeze)**:**
|
|
@@ -142,6 +182,27 @@ must halt to avoid cascading issues. Remaining auto-fixable findings will appear
|
|
|
142
182
|
report as `not-attempted`.
|
|
143
183
|
</step>
|
|
144
184
|
|
|
185
|
+
<step name="vault_door_record">
|
|
186
|
+
After the loop, once for EACH phase directory whose findings were fixed in this run (the directory of
|
|
187
|
+
the UAT or VERIFICATION file the finding came from): the record's range, from the start captured
|
|
188
|
+
before the loop to HEAD now, covers every finding commit, and it lands in each fixed phase so that
|
|
189
|
+
phase's gate sees it.
|
|
190
|
+
|
|
191
|
+
Vault door record (D-12): after the door's last source commit, set `DOOR_DIR="<that phase directory>"`,
|
|
192
|
+
`DOOR_PADDED="<its padded phase>"` and `DOOR_PHASE="<that phase directory>"`, then run:
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
DOOR_RUN=$(date -u +%Y%m%dT%H%M%SZ)
|
|
196
|
+
pp_run vault door-record --door audit-fix --artifact "${DOOR_DIR}/${DOOR_PADDED}-door-${DOOR_RUN}-AUDIT-FIX.md" --phase "$DOOR_PHASE" --raw
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
The verb writes a `## Vault Door Record` (mode, vault ref and sha, governing phase, the start `--begin`
|
|
200
|
+
recorded and the end commit; the agent never types a sha) into a fresh per-run artifact, because it refuses a second record
|
|
201
|
+
in one file (D-57) and a rewritten report would drop the earlier run's coverage (D-79). It prints
|
|
202
|
+
nothing and writes nothing unless `vault admission` answers `on`. When it wrote the file and
|
|
203
|
+
`commit_docs` is true, commit the `artifact` path it printed: `pp_run query commit "docs: vault door record for audit-fix" --files "<that artifact>"`.
|
|
204
|
+
</step>
|
|
205
|
+
|
|
145
206
|
<step name="report">
|
|
146
207
|
Present the final summary:
|
|
147
208
|
|
|
@@ -146,7 +146,7 @@ For each REQ-ID, determine status using all three sources:
|
|
|
146
146
|
Skip if the Nyquist capability is inactive.
|
|
147
147
|
|
|
148
148
|
```bash
|
|
149
|
-
VERIFY_POST_HOOKS_JSON=$(pp_run loop render-hooks verify:post --raw)
|
|
149
|
+
VERIFY_POST_HOOKS_JSON=$(pp_run loop render-hooks verify:post --raw)
|
|
150
150
|
```
|
|
151
151
|
|
|
152
152
|
Resolve active step hooks from `VERIFY_POST_HOOKS_JSON` where `kind == "step"` and `ref.skill == "validate-phase"`.
|
|
@@ -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` and `vault-practices`
|
|
199
|
+
capabilities (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'||x.capId==='vault-practices'));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 renders no practices contribution, so this runs 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"`.
|
|
@@ -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` and `vault-practices` capabilities (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'||x.capId==='vault-practices'));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
|