@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
|
@@ -233,106 +233,4 @@ function assertFileBaseline({ label, current, baseline, fail, updateHint }) {
|
|
|
233
233
|
return { grown, shrunk, added, removed };
|
|
234
234
|
}
|
|
235
235
|
|
|
236
|
-
|
|
237
|
-
* Assert that each artifact's measured size stays within a per-change DELTA
|
|
238
|
-
* BUDGET of its committed baseline (workflow size budget policy, 2026-10-11).
|
|
239
|
-
*
|
|
240
|
-
* Unlike `assertFileBaseline` (exact-byte pins), small growth is absorbed by a
|
|
241
|
-
* slack so routine edits need no baseline commit, while large or cumulative
|
|
242
|
-
* growth still fails by name:
|
|
243
|
-
*
|
|
244
|
-
* - A file may exceed its baseline by at most `perFileSlack` bytes.
|
|
245
|
-
* - The SUM of all positive overages may not exceed `totalSlack` bytes, so many
|
|
246
|
-
* small growths cannot add up to a large one unseen.
|
|
247
|
-
* - Shrinking always passes and never needs a baseline commit.
|
|
248
|
-
* - A file with no baseline entry (ADDED) or a baseline entry with no file
|
|
249
|
-
* (REMOVED) fails: the baseline must name exactly the files on disk.
|
|
250
|
-
* Recording either needs no reason.
|
|
251
|
-
* - An EMPTY baseline fails: with no entries every file is "added", but an
|
|
252
|
-
* explicit message makes the vacuous-pass case impossible to misread.
|
|
253
|
-
*
|
|
254
|
-
* Overage is measured against the committed baseline, not the previous commit,
|
|
255
|
-
* so the slack is a budget that a re-baseline resets — not a per-commit
|
|
256
|
-
* allowance that can be spent again on every commit.
|
|
257
|
-
*
|
|
258
|
-
* @param {object} opts
|
|
259
|
-
* @param {string} opts.label - Guard name (used in messages).
|
|
260
|
-
* @param {Object<string, number>} opts.current - Measured sizes by name.
|
|
261
|
-
* @param {Object<string, number>} opts.baseline - Committed sizes by name
|
|
262
|
-
* (numbers only; strip metadata keys first).
|
|
263
|
-
* @param {number} opts.perFileSlack - Max bytes one file may exceed its baseline.
|
|
264
|
-
* @param {number} opts.totalSlack - Max sum of all positive overages.
|
|
265
|
-
* @param {function(string): void} opts.fail - Invoked once per violation category.
|
|
266
|
-
* @param {string} [opts.updateHint] - Remediation hint appended to growth failures.
|
|
267
|
-
* @returns {{ overages: Array<{name:string,from:number,to:number,delta:number}>,
|
|
268
|
-
* totalOverage: number,
|
|
269
|
-
* shrunk: Array<{name:string,from:number,to:number,delta:number}>,
|
|
270
|
-
* added: string[], removed: string[] }}
|
|
271
|
-
*/
|
|
272
|
-
function assertDeltaBudget({ label, current, baseline, perFileSlack, totalSlack, fail, updateHint }) {
|
|
273
|
-
const currentNames = new Set(Object.keys(current));
|
|
274
|
-
const baselineNames = new Set(Object.keys(baseline));
|
|
275
|
-
const hint = updateHint ? `\n${updateHint}` : '';
|
|
276
|
-
|
|
277
|
-
if (baselineNames.size === 0) {
|
|
278
|
-
fail(
|
|
279
|
-
`[${label}] the committed baseline has no size entries — an empty baseline would make ` +
|
|
280
|
-
`every growth check pass vacuously. Regenerate it with \`npm run size:baseline\`.`
|
|
281
|
-
);
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
const added = [...currentNames].filter((n) => !baselineNames.has(n)).sort();
|
|
285
|
-
const removed = [...baselineNames].filter((n) => !currentNames.has(n)).sort();
|
|
286
|
-
|
|
287
|
-
const overages = [];
|
|
288
|
-
const shrunk = [];
|
|
289
|
-
for (const name of [...currentNames].filter((n) => baselineNames.has(n)).sort()) {
|
|
290
|
-
const from = baseline[name];
|
|
291
|
-
const to = current[name];
|
|
292
|
-
if (!Number.isInteger(from) || from < 0) {
|
|
293
|
-
fail(`[${label}] baseline entry ${name} is not a non-negative integer byte size: ${JSON.stringify(from)}`);
|
|
294
|
-
continue;
|
|
295
|
-
}
|
|
296
|
-
if (to > from) overages.push({ name, from, to, delta: to - from });
|
|
297
|
-
else if (to < from) shrunk.push({ name, from, to, delta: from - to });
|
|
298
|
-
}
|
|
299
|
-
const totalOverage = overages.reduce((sum, o) => sum + o.delta, 0);
|
|
300
|
-
const fmt = (o) => ` - ${o.name}: ${o.from} → ${o.to} (+${o.delta})`;
|
|
301
|
-
|
|
302
|
-
const overFile = overages.filter((o) => o.delta > perFileSlack);
|
|
303
|
-
if (overFile.length > 0) {
|
|
304
|
-
fail(
|
|
305
|
-
`[${label}] ${overFile.length} file(s) grew more than the per-file slack of ${perFileSlack} bytes ` +
|
|
306
|
-
`past the committed baseline. Shrink them (extract content lazily), or re-baseline with a ` +
|
|
307
|
-
`reason: npm run size:baseline -- --reason "<why this growth is needed>"\n` +
|
|
308
|
-
`${overFile.map(fmt).join('\n')}${hint}`
|
|
309
|
-
);
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
if (totalOverage > totalSlack) {
|
|
313
|
-
fail(
|
|
314
|
-
`[${label}] total growth past the committed baseline is ${totalOverage} bytes, over the total ` +
|
|
315
|
-
`slack of ${totalSlack} bytes (each file may be under its own slack — the sum is what failed). ` +
|
|
316
|
-
`Shrink, or re-baseline with a reason: npm run size:baseline -- --reason "<why>"\n` +
|
|
317
|
-
`${overages.map(fmt).join('\n')}${hint}`
|
|
318
|
-
);
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
if (added.length > 0) {
|
|
322
|
-
fail(
|
|
323
|
-
`[${label}] ${added.length} file(s) are not in the baseline — run \`npm run size:baseline\` ` +
|
|
324
|
-
`to record them (no --reason needed for new files).\n${added.map((n) => ` - ${n}`).join('\n')}`
|
|
325
|
-
);
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
if (removed.length > 0) {
|
|
329
|
-
fail(
|
|
330
|
-
`[${label}] ${removed.length} baseline entry(ies) no longer exist — run \`npm run size:baseline\` ` +
|
|
331
|
-
`to drop them (no --reason needed).\n${removed.map((n) => ` - ${n}`).join('\n')}`
|
|
332
|
-
);
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
return { overages, totalOverage, shrunk, added, removed };
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
module.exports = { assertWithinAllowlist, assertTightCeiling, assertFileBaseline, assertDeltaBudget };
|
|
236
|
+
module.exports = { assertWithinAllowlist, assertTightCeiling, assertFileBaseline };
|
|
@@ -288,7 +288,6 @@
|
|
|
288
288
|
"tests/read-guard.test.cjs :: source-text-is-the-product",
|
|
289
289
|
"tests/reapply-patches.test.cjs :: source-text-is-the-product",
|
|
290
290
|
"tests/reapply-verify-hunks.test.cjs :: source-text-is-the-product",
|
|
291
|
-
"tests/release-coverage-scope.test.cjs :: source-text-is-the-product",
|
|
292
291
|
"tests/release-tarball-smoke-workflow.test.cjs :: source-text-is-the-product",
|
|
293
292
|
"tests/release-tarball-smoke.install.test.cjs :: integration-test-input",
|
|
294
293
|
"tests/research-agent-profiles.test.cjs :: <runtime-contract-is-the-product> research agent .md content is the governed surface",
|
|
@@ -321,7 +320,6 @@
|
|
|
321
320
|
"tests/windows-test-parity-guard.test.cjs :: structural-regression-guard",
|
|
322
321
|
"tests/workflow-compat.test.cjs :: source-text-is-the-product",
|
|
323
322
|
"tests/workflow-guard-registration.test.cjs :: structural-regression-guard",
|
|
324
|
-
"tests/workflow-maintainer-skip.test.cjs :: source-text-is-the-product",
|
|
325
323
|
"tests/workflow-shell-pinning.test.cjs :: file-scope prefilter, not a test assertion — we need to",
|
|
326
324
|
"tests/workflow-size-budget.test.cjs :: source-text-is-the-product",
|
|
327
325
|
"tests/workspace.test.cjs :: source-text-is-the-product",
|
|
File without changes
|
|
@@ -9,9 +9,7 @@ const { runMain } = require('./lib/cli-exit.cjs');
|
|
|
9
9
|
const ROOT = path.join(__dirname, '..');
|
|
10
10
|
|
|
11
11
|
const DEFAULT_RELATIVE_FILES = [
|
|
12
|
-
'.github/workflows/
|
|
13
|
-
'.github/workflows/pr-template-format.yml',
|
|
14
|
-
'.github/workflows/changeset-required.yml',
|
|
12
|
+
'.github/workflows/ci.yml',
|
|
15
13
|
'scripts/lint-command-contract.cjs',
|
|
16
14
|
'scripts/lint-skill-deps.cjs',
|
|
17
15
|
'scripts/lint-descriptions.cjs',
|
|
@@ -114,6 +114,14 @@
|
|
|
114
114
|
],
|
|
115
115
|
"issue": "180"
|
|
116
116
|
},
|
|
117
|
+
"vault-review": {
|
|
118
|
+
"files": [
|
|
119
|
+
"vault-review.integration.test.cjs",
|
|
120
|
+
"vault-review.security.test.cjs",
|
|
121
|
+
"vault-review.test.cjs"
|
|
122
|
+
],
|
|
123
|
+
"issue": "71924 — Vault Assurance phase 06 (06-03/06-04), three distinct concerns for pp-core/bin/lib/vault-review.cjs: vault-review.test (06-03 unit tests over every pure derivation — the verdict vocabularies, both derived-N-A arms, the counts arithmetic, the range resolver and the clean-render refusal predicate), vault-review.integration.test (06-04 SEAM tests — the deterministic validator of the agent-written artifact, plus the `check vault-review` arm driven through the real pp-core/bin/pp-tools.cjs, where the exit-0/no-block-key contract of D-06-01 and VERIFY-03 is proved at the boundary a gate enforcer actually reads, with RED control 2 proving that guard non-vacuous), and vault-review.security.test (06-04 ADVERSARIAL tests — a spoofed external-content fence-end marker, directive-shaped text and a forged tool-call block planted in real practice BODIES, proving 05-REVIEW's open Critical CR-02 is not repeated on this surface, plus the CR-03 class: no absolute filesystem path in any emitted byte). The split mirrors the `vault` cluster's own reasoning: the unit lane, the CLI seam and the security marker are independently load-bearing verification gates, and the `.security.test.cjs` marker is what makes the adversarial lane identifiable to a reader and to scripts/run-tests.cjs. Consolidating would blur three different questions into one file."
|
|
124
|
+
},
|
|
117
125
|
"verify": {
|
|
118
126
|
"files": [
|
|
119
127
|
"bug-2969-verify-reapply-patches.test.cjs",
|
|
@@ -179,21 +187,15 @@
|
|
|
179
187
|
},
|
|
180
188
|
"vault": {
|
|
181
189
|
"files": [
|
|
190
|
+
"feat-71924-vault-required-gate.test.cjs",
|
|
191
|
+
"vault-doors.integration.test.cjs",
|
|
182
192
|
"vault-practices.property.test.cjs",
|
|
183
193
|
"vault-read-path.test.cjs",
|
|
184
194
|
"vault-security.test.cjs",
|
|
185
195
|
"vault-status-check.test.cjs",
|
|
186
196
|
"vault.test.cjs"
|
|
187
197
|
],
|
|
188
|
-
"issue": "v1.7.0 Client Vault Load — four distinct concerns: vault.test (fetch/status/summary unit), vault-security (VSEC-02/03 write-guard + secret/fence), vault-read-path (VGATE-03 SUMMARY pointer), vault-status-check (VGATE-02 gate-query handler). Phase 24-02 added vault-practices.property.test.cjs (fast-check fuzz of the practices glob-fallback compiler + a practices-frontmatter round-trip, PRAC-02) — it is grouped under this bucket rather than \"vault-practices\" because the test-file-count lint's hyphen-prefix matcher treats \"vault-practices.property\" (period before \"property\") as starting with \"vault-\" before it can match the more specific \"vault-practices-\" prefix; the module it actually tests is pp-core/bin/lib/vault-practices.cjs, not vault.cjs."
|
|
189
|
-
},
|
|
190
|
-
"vault-review": {
|
|
191
|
-
"files": [
|
|
192
|
-
"vault-review.integration.test.cjs",
|
|
193
|
-
"vault-review.security.test.cjs",
|
|
194
|
-
"vault-review.test.cjs"
|
|
195
|
-
],
|
|
196
|
-
"issue": "Agent practice review (vault assurance R5) — three distinct concerns for pp-core/bin/lib/vault-review.cjs: vault-review.test (the pure derivations — vocabularies, both derived-N-A arms, the counts, the range, the clean-render refusal, the scaffold renderer and the line stamper — plus the require-graph barrier), vault-review.integration.test (the seams: the artifact validator and the check vault-review / vault review scaffold|finalize arms driven through the real pp-tools.cjs, where the exit-0 / no-block-key contract is proved), and vault-review.security.test (adversarial practice bodies: a spoofed fence marker, directive-shaped text, a client table inside the fence, an option-shaped base branch). The .security marker is what identifies the adversarial lane to scripts/run-tests.cjs; consolidating would blur three different questions into one file."
|
|
198
|
+
"issue": "v1.7.0 Client Vault Load — four distinct concerns: vault.test (fetch/status/summary unit), vault-security (VSEC-02/03 write-guard + secret/fence), vault-read-path (VGATE-03 SUMMARY pointer), vault-status-check (VGATE-02 gate-query handler). Phase 24-02 added vault-practices.property.test.cjs (fast-check fuzz of the practices glob-fallback compiler + a practices-frontmatter round-trip, PRAC-02) — it is grouped under this bucket rather than \"vault-practices\" because the test-file-count lint's hyphen-prefix matcher treats \"vault-practices.property\" (period before \"property\") as starting with \"vault-\" before it can match the more specific \"vault-practices-\" prefix; the module it actually tests is pp-core/bin/lib/vault-practices.cjs, not vault.cjs. Vault Assurance phase 02 (#71924) added feat-71924-vault-required-gate.test.cjs as the phase's ONE consolidated source-grep feature file — it owns the source-text assertions for GATE-02, GATE-03, GATE-06, GATE-08, GATE-09 and GATE-10 together, deliberately in a single file so the phase's six requirements do not each spawn a sibling; later plans in the phase extend it rather than adding files. Vault Assurance phase 16 plan 10 added vault-doors.integration.test.cjs as the phase's ONE door fence-proof owner (DOOR-01..05, D-09): every door's shipped fence (execute-plan, quick, fast, debug, the secondary doors) composed by tests/helpers/gate-fence-composer.cjs and run in bash and zsh, one describe per door plan, so 16-12..16-15 extend it rather than each adding a sibling. The hyphen-prefix matcher attributes it here because no vault-doors module exists; it tests workflow fences, not vault.cjs."
|
|
197
199
|
},
|
|
198
200
|
"vault-practices": {
|
|
199
201
|
"files": [
|
|
@@ -202,7 +204,7 @@
|
|
|
202
204
|
"vault-practices.slow.test.cjs",
|
|
203
205
|
"vault-practices.test.cjs"
|
|
204
206
|
],
|
|
205
|
-
"issue": "Phase 24 (24-01/24-02/24-04) — three distinct concerns for pp-core/bin/lib/vault-practices.cjs: vault-practices.test (24-01 parser/validation/discovery unit tests), vault-practices-matcher.test (24-02 glob matcher + two-bucket result + report unit tests), vault-practices-examples.test (24-04 shipped-example drift guard + minimal-comments global-bucket smoke case, PRAC-03 Success Criterion 3). All three test the same production module and are each independently load-bearing; consolidating would blur distinct plan-level verification gates.
|
|
207
|
+
"issue": "Phase 24 (24-01/24-02/24-04) — three distinct concerns for pp-core/bin/lib/vault-practices.cjs: vault-practices.test (24-01 parser/validation/discovery unit tests), vault-practices-matcher.test (24-02 glob matcher + two-bucket result + report unit tests), vault-practices-examples.test (24-04 shipped-example drift guard + minimal-comments global-bucket smoke case, PRAC-03 Success Criterion 3). All three test the same production module and are each independently load-bearing; consolidating would blur distinct plan-level verification gates. Vault Assurance phase 05 (#71924) added vault-practices.slow.test.cjs — the >5 s six-axis worst-case matcher corpus for the same production module (pp-core/bin/lib/vault-practices.cjs), split out per the .slow suffix convention so the default suite stays fast; attributed here once the count lint learned to strip the .slow suffix."
|
|
206
208
|
}
|
|
207
209
|
}
|
|
208
210
|
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"//": [
|
|
3
|
+
"Lines that carry a residue needle but restate NO fact the canonical block states.",
|
|
4
|
+
"Read by scripts/gen-practice-arithmetic-contract.cjs --check. Keys starting with // are comments.",
|
|
5
|
+
"sha256 is of the EXACT allowed line. Editing that line breaks its entry and forces re-justification;",
|
|
6
|
+
"an entry matching no line in its file fails as rotted. A reason is mandatory.",
|
|
7
|
+
"A WRAPPED finding — one visible only once adjacent lines are joined — is hashed over the joined,",
|
|
8
|
+
"whitespace-collapsed window text that --check prints beside it, not over any single line of the",
|
|
9
|
+
"file. That digest survives a reflow of the same words, because what an allowance justifies is the",
|
|
10
|
+
"sentence and not where its line breaks fell. All three entries below are per-LINE. 06-17, W13.",
|
|
11
|
+
"Every entry below is the same shape: a payload-KEY INVENTORY, where `derivedCounts` /",
|
|
12
|
+
"`derivedRateLine` are named as things the CLI hands the agent, and the very next clause points at",
|
|
13
|
+
"the generated contract block rather than saying what they mean. Naming a key is not restating a",
|
|
14
|
+
"contract. Keep this file as close to empty as the prose allows.",
|
|
15
|
+
"06-16, gap G10."
|
|
16
|
+
],
|
|
17
|
+
"pp-core/workflows/vault-review.md": [
|
|
18
|
+
{
|
|
19
|
+
"sha256": "1766709dca03a214fb8fa5496fe6b2aef06fc1b02e67832a6048eeac78e29d6a",
|
|
20
|
+
"reason": "Section 4 is the inventory of what REVIEW_PAYLOAD carries; this line names the two keys and its own continuation says what they describe is stated once in the contract block carried into the spawn prompt below. It states nothing itself."
|
|
21
|
+
}
|
|
22
|
+
],
|
|
23
|
+
"agents/pp-vault-reviewer.md": [
|
|
24
|
+
{
|
|
25
|
+
"sha256": "1fac53fb5988ab5278f2a262f1564b5dbef830531ec0a82f7200c9b940b45b8d",
|
|
26
|
+
"reason": "The left cell of the supplied-fact table, where the key name IS the row's subject. The right cell is a pointer to the contract block twelve lines below, in the same <derived_facts> element."
|
|
27
|
+
}
|
|
28
|
+
],
|
|
29
|
+
"pp-core/references/verifier-practice-verdicts.md": [
|
|
30
|
+
{
|
|
31
|
+
"sha256": "52872e6f4b821944e026667c5bd48a3c2319f6876e805e8721865cbf6eb27816",
|
|
32
|
+
"reason": "Section 6's inventory of what the check vault-review arm hands the verifier. The sentence that follows it points at section 7 and says explicitly that the rule is not restated here."
|
|
33
|
+
}
|
|
34
|
+
]
|
|
35
|
+
}
|
|
@@ -82,23 +82,28 @@ PATTERNS=(
|
|
|
82
82
|
# THIS file and reads the array bash actually expands — adding, removing or
|
|
83
83
|
# un-reasoning an entry here without editing the test turns the suite red.
|
|
84
84
|
ALLOWLIST=(
|
|
85
|
-
'scripts/prompt-injection-scan.sh::the PATTERNS array above is the literal source of every phrase this scanner looks for, so the file matches itself by construction; measured 4 pattern hits at HEAD on 2026-
|
|
86
|
-
'scripts/base64-scan.sh::decodes base64 blobs and re-scans the recovered plaintext against the same injection vocabulary, so it names those phrases inline; measured 2 pattern hits at HEAD on 2026-
|
|
87
|
-
'scripts/secret-scan.sh::third of the three diff-mode scan scripts CI runs together in the
|
|
88
|
-
'tests/security-scan.security.test.cjs::the behavioural suite for this very scanner, so every positive case embeds a real injection phrase as fixture input; measured 28 pattern hits at HEAD on 2026-
|
|
89
|
-
'tests/security.test.cjs::the adversarial suite for the library sanitisers, whose fixtures are real override and role-manipulation strings asserted to be neutralised; measured 54 pattern hits at HEAD on 2026-
|
|
90
|
-
'tests/prompt-injection-scan.security.test.cjs::drives scanForInjection in the compiled security library with crafted payloads, and carries a second allowlist of its own for that separate scanner; measured 11 pattern hits at HEAD on 2026-
|
|
91
|
-
'tests/
|
|
92
|
-
'
|
|
93
|
-
'tests/
|
|
94
|
-
'tests/
|
|
95
|
-
'
|
|
96
|
-
'tests/
|
|
97
|
-
'tests/
|
|
98
|
-
'tests/
|
|
99
|
-
'
|
|
100
|
-
'
|
|
101
|
-
'
|
|
85
|
+
'scripts/prompt-injection-scan.sh::the PATTERNS array above is the literal source of every phrase this scanner looks for, so the file matches itself by construction; measured 4 pattern hits at HEAD on 2026-09-19'
|
|
86
|
+
'scripts/base64-scan.sh::decodes base64 blobs and re-scans the recovered plaintext against the same injection vocabulary, so it names those phrases inline; measured 2 pattern hits at HEAD on 2026-09-19'
|
|
87
|
+
'scripts/secret-scan.sh::third of the three diff-mode scan scripts CI runs together in the security_scan job of .github/workflows/ci.yml; measured 0 pattern hits at HEAD on 2026-09-19, retained because its own exemption list at line 223 already names security-prompt-injection.security.test.cjs and grows with that vocabulary'
|
|
88
|
+
'tests/security-scan.security.test.cjs::the behavioural suite for this very scanner, so every positive case embeds a real injection phrase as fixture input; measured 28 pattern hits at HEAD on 2026-09-19'
|
|
89
|
+
'tests/security.test.cjs::the adversarial suite for the library sanitisers, whose fixtures are real override and role-manipulation strings asserted to be neutralised; measured 54 pattern hits at HEAD on 2026-09-19'
|
|
90
|
+
'tests/prompt-injection-scan.security.test.cjs::drives scanForInjection in the compiled security library with crafted payloads, and carries a second allowlist of its own for that separate scanner; measured 11 pattern hits at HEAD on 2026-09-19'
|
|
91
|
+
'tests/verify.test.cjs::the verification suite plants an instruction-override line in a phase artifact and asserts it is rejected, so the line is present as a negative fixture; measured 1 pattern hit at HEAD on 2026-09-19'
|
|
92
|
+
'pp-core/bin/lib/security.cjs::gitignored build output compiled from src/security.cts per .gitignore line 117, so it is unreachable in diff mode and matters only to a local dir-mode run; it carries the library injection patterns inline; measured 8 pattern hits at HEAD on 2026-09-19'
|
|
93
|
+
'tests/read-injection-scanner.security.test.cjs::exercises the read-time injection scanner hook with the payloads a hostile file would carry, each asserted to be blocked rather than obeyed; measured 14 pattern hits at HEAD on 2026-09-19'
|
|
94
|
+
'tests/security-prompt-injection.security.test.cjs::carries two deliberate NUL bytes at lines 631 and 881 so grep classifies it as binary and reports whole-file matches with no line numbers; 10 binary pattern matches measured at HEAD on 2026-09-19'
|
|
95
|
+
'tests/fixtures/adversarial/security/::a directory of adversarial corpus files whose entire purpose is to BE injection payloads for the suites above; measured 20 pattern hits across its 7 tracked files at HEAD on 2026-09-19'
|
|
96
|
+
'tests/discovery-vault-context.test.cjs::the DISCO-03/SC4 suite plants a real role-manipulation line (the PLANTED constant) into a fixture vault document and asserts the shipped scanner FINDS it, which is the non-vacuity partner for the assertion that the subflow itself scans clean; the payload has to be a literal for that half to mean anything, so the file matches the vocabulary it exists to prove is caught'
|
|
97
|
+
'tests/vault-status-check.test.cjs::sanitisation seeds for the vault status message carry a real instruction and a real control character on purpose, each paired with a non-vacuity assertion that the RENDERED message does not carry it intact; measured 5 pattern hits at HEAD on 2026-09-19'
|
|
98
|
+
'tests/vault-practices-matcher.test.cjs::the CR-01 fence-spoof suite plants a real instruction-override line and a forged end-fence marker inside practice bodies on purpose, each paired with an assertion that the RENDERED practices block keeps the planted text inside the fence and leaves exactly one genuine closer, so the payload must be a literal for the defang proof to mean anything; measured 3 pattern hits at HEAD b4dd6b3 on 2026-10-04'
|
|
99
|
+
'tests/vault-review.security.test.cjs::the CR-02 suite seeds a practice body with directive-shaped text aimed at the practice judge (the DIRECTIVE_TEXT constant) and asserts the rendered review entry carries it only between the fence markers, after the reference-data preamble, so the judge reads it as data; the text must be a literal for that assertion to mean anything; measured 1 pattern hit at HEAD b4dd6b3 on 2026-10-04'
|
|
100
|
+
'tests/practices-review-check-property.test.cjs::a false positive rather than a payload, since the fence-parsing invariance property builds a never-closed fence whose second-opener line is ordinary English about whether the client line becomes a cut point, and one role-pattern regex matches that plain wording; the fixture text stays as written; measured 1 pattern hit at HEAD b4dd6b3 on 2026-10-04'
|
|
101
|
+
'tests/vault-index.integration.test.cjs::the fence-spoof suite seeds a vault document heading and an INDEX description that carry a forged end-fence marker followed by an instruction-override phrase, and asserts the rendered SUMMARY keeps exactly one live end marker with the planted line defanged inside the fence, so the phrase must be a literal for the defang proof to mean anything; measured 4 pattern hits at HEAD 5ddb0b3 on 2026-10-12'
|
|
102
|
+
'tests/vault-seal.integration.test.cjs::the uncovered-commit suite builds a commit whose subject is an instruction-override phrase padded past the cap, modelling a hostile commit message, and asserts the subject leaving the seal leaf is controls-collapsed and bounded to SEAL_SUBJECT_CAP before it can reach a record; measured 1 pattern hit at HEAD 5ddb0b3 on 2026-10-12'
|
|
103
|
+
'tests/vault-standards.integration.test.cjs::the D-14 suites plant instruction-override lines in a standards document and in its INDEX description, each tagged with a random token, and assert that neither the token nor the phrase appears in any output of vault standards block or consulted, so the phrase must be a literal for the absence proof to mean anything; measured 6 pattern hits at HEAD 5ddb0b3 on 2026-10-12'
|
|
104
|
+
'SECURITY.md::the substring rule makes this exempt every path ending in SECURITY.md, including pp-core/templates/SECURITY.md and every per-phase threat register generated from that template; the breadth is accepted because a security policy is exactly where injection phrasing is legitimately quoted; measured 0 pattern hits across all 16 such files on disk at HEAD on 2026-09-19'
|
|
105
|
+
'TEST-EXAMPLES.md::documentation that demonstrates injection examples in order to explain what these scanners catch, so the example text is the point of the file rather than an attack; measured 1 pattern hit at HEAD on 2026-09-19'
|
|
106
|
+
'explanation/security-model.md::matches docs/explanation/security-model.md through the substring rule; it is the prose that explains the injection threat model and quotes the attack shapes pp-core defends against; measured 2 pattern hits at HEAD on 2026-09-19'
|
|
102
107
|
)
|
|
103
108
|
|
|
104
109
|
is_allowlisted() {
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* scripts/record-vault-mode-golden.cjs — the vault-mode golden recorder
|
|
6
|
+
* (Vault Assurance v1.2, phase 13; MODE-01, PARK-04; D-01).
|
|
7
|
+
*
|
|
8
|
+
* --write record every enablement cell (key absent — the canonical
|
|
9
|
+
* recording), normalise, and write tests/fixtures/vault-mode-golden/<cell>.json
|
|
10
|
+
* --check record the same and compare against the committed files; print
|
|
11
|
+
* every differing path and exit 1 on any difference
|
|
12
|
+
*
|
|
13
|
+
* Neither or both flags: usage, exit 2. No path argument: the golden directory
|
|
14
|
+
* is the harness's `GOLDEN_DIR`, so the recorder and the test cannot disagree
|
|
15
|
+
* about where the goldens live.
|
|
16
|
+
*
|
|
17
|
+
* A THIN CLI. Every fixture, capture, normalisation and comparison rule lives in
|
|
18
|
+
* the shared harness module required below, which the golden test requires too.
|
|
19
|
+
* This script is never run by the test suite: a re-record is a deliberate,
|
|
20
|
+
* reviewable re-baseline (D-01), and it must run on a tree whose practices-mode
|
|
21
|
+
* behaviour is the one being pinned.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
const fs = require('node:fs');
|
|
25
|
+
const path = require('node:path');
|
|
26
|
+
const harness = require('../tests/helpers/vault-mode-golden-harness.cjs');
|
|
27
|
+
|
|
28
|
+
const ROOT = path.resolve(__dirname, '..');
|
|
29
|
+
const USAGE = 'usage: record-vault-mode-golden.cjs (--write | --check)';
|
|
30
|
+
|
|
31
|
+
function describeDiff(d) {
|
|
32
|
+
const at = d.firstDiffAt === undefined ? '' : ` (first differing byte at ${d.firstDiffAt})`;
|
|
33
|
+
const show = (v) => (v === undefined ? '<absent>' : JSON.stringify(v).slice(0, 200));
|
|
34
|
+
return ` ${d.path}${at}\n expected: ${show(d.expected)}\n actual: ${show(d.actual)}`;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function main() {
|
|
38
|
+
const write = process.argv.includes('--write');
|
|
39
|
+
const check = process.argv.includes('--check');
|
|
40
|
+
if (write === check) {
|
|
41
|
+
console.error(USAGE);
|
|
42
|
+
process.exitCode = 2;
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
let failed = 0;
|
|
47
|
+
for (const cell of harness.ENABLEMENT_CELLS) {
|
|
48
|
+
const raw = harness.recordCell({ cell: cell.name, modeKey: harness.KEY_CONFIGS.absent });
|
|
49
|
+
const normalised = harness.normaliseRecording(raw);
|
|
50
|
+
const count = Object.keys(normalised.commands).length;
|
|
51
|
+
const dropped = Object.entries(raw.meta.droppedHookCounts)
|
|
52
|
+
.map(([id, n]) => `${id}=${n}`)
|
|
53
|
+
.join(' ');
|
|
54
|
+
const target = harness.goldenPathFor(cell.name);
|
|
55
|
+
const rel = path.relative(ROOT, target);
|
|
56
|
+
console.log(`${cell.name}: ${count} commands recorded (render-hooks projection dropped: ${dropped})`);
|
|
57
|
+
|
|
58
|
+
if (write) {
|
|
59
|
+
fs.mkdirSync(path.dirname(target), { recursive: true });
|
|
60
|
+
fs.writeFileSync(target, harness.serialise(normalised), 'utf8');
|
|
61
|
+
console.log(` wrote ${rel}`);
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
let expected;
|
|
66
|
+
try {
|
|
67
|
+
expected = JSON.parse(fs.readFileSync(target, 'utf8'));
|
|
68
|
+
} catch (e) {
|
|
69
|
+
console.error(` FAIL: ${rel} could not be read as JSON (${e.message})`);
|
|
70
|
+
failed++;
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
const { equal, diffs } = harness.compareRecordings(expected, normalised);
|
|
74
|
+
if (equal) {
|
|
75
|
+
console.log(` matches ${rel}`);
|
|
76
|
+
} else {
|
|
77
|
+
failed++;
|
|
78
|
+
console.error(` FAIL: ${rel} differs at ${diffs.length} path(s):`);
|
|
79
|
+
for (const d of diffs) console.error(describeDiff(d));
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (check && failed > 0) {
|
|
84
|
+
console.error(`\nFAIL: ${failed} golden cell(s) differ from a fresh recording.`);
|
|
85
|
+
process.exitCode = 1;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
main();
|
|
File without changes
|
|
@@ -11,10 +11,11 @@
|
|
|
11
11
|
* - VERSIONED_MANIFESTS — JSON runtime-integration manifests whose top-level
|
|
12
12
|
* `version` field MUST track the package version.
|
|
13
13
|
* - VERSIONED_TEXT_FILES — plain-text manifests whose ENTIRE content is the
|
|
14
|
-
* version followed by one newline. Root `VERSION` is the repo layout's
|
|
15
|
-
* version source for `
|
|
16
|
-
* repo build stamps `createdWith`
|
|
17
|
-
*
|
|
14
|
+
* version followed by one newline. Root `VERSION` is the repo layout's only
|
|
15
|
+
* version source for `resolveCreatedWithFrom` (src/compose-bindings.cts), so a
|
|
16
|
+
* repo build stamps `createdWith` and the practices block from it. It drifted
|
|
17
|
+
* from 1.11.1 through three releases because a plain-text file could not join
|
|
18
|
+
* the JSON loop (quick 261003-kmd closed the todo).
|
|
18
19
|
*
|
|
19
20
|
* Usage:
|
|
20
21
|
* node scripts/sync-manifest-versions.cjs # stamp + report
|