@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
|
@@ -18,10 +18,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
18
18
|
* no vault cache is present.
|
|
19
19
|
*
|
|
20
20
|
* Responsibility (Phase 24-02 — matcher + global-bucket + formatter half):
|
|
21
|
-
* `globMatch`/`fallbackGlobToRegex` provide deterministic glob matching
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
21
|
+
* `globMatch`/`fallbackGlobToRegex` provide deterministic glob matching,
|
|
22
|
+
* feature-detecting `path.posix.matchesGlob` (Node >=22.5.0) with a hand-
|
|
23
|
+
* rolled, linear-time regex fallback for the 22.0–22.4 gap (engines floor
|
|
24
|
+
* is >=22.0.0). `matchPractices` partitions discovered practices into a
|
|
25
25
|
* glob-matched `matched` bucket and an always-surfaced `global` bucket (a
|
|
26
26
|
* bounded, fenced excerpt per global practice — the matcher itself makes
|
|
27
27
|
* ZERO calls to any hosted model or scoring service; relevance of globals
|
|
@@ -35,8 +35,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
35
35
|
* - `./vault.cjs` (`usableFiles`, `isSecretFile`, `readManifest`,
|
|
36
36
|
* `readHeadBounded`) — the existing vault-tier discovery/secret/manifest/
|
|
37
37
|
* bounded-read helpers.
|
|
38
|
-
* -
|
|
39
|
-
*
|
|
38
|
+
* - `node:path`'s `path.posix.matchesGlob` (feature-detected) — no
|
|
39
|
+
* `minimatch`/`picomatch` dependency (RESEARCH STACK.md).
|
|
40
40
|
*
|
|
41
41
|
* Out of scope here (later plans): the CLI `practices match` router wiring
|
|
42
42
|
* and cross-tier client-beats-shared id dedup (explicitly DEFERRED to
|
|
@@ -59,14 +59,16 @@ const node_fs_1 = __importDefault(require("node:fs"));
|
|
|
59
59
|
const fmMod = require("./frontmatter.cjs");
|
|
60
60
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
61
61
|
const vaultMod = require("./vault.cjs");
|
|
62
|
-
//
|
|
62
|
+
// D-17/D-26 (14-04): the fence markers and their defang have ONE owner, the
|
|
63
|
+
// dependency-free vault-index leaf, which src/vault.cts can import without the
|
|
64
|
+
// cycle this module's vault.cjs import would create.
|
|
65
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
66
|
+
const vaultIndexLeaf = require("./vault-index.cjs");
|
|
67
|
+
// Quick 261003-jby (FIX-3): the ONE version resolver — the same function and
|
|
63
68
|
// candidate ladder `project.createdWith` is written from — so the block's
|
|
64
69
|
// status stamp and the bindings can never name different engine versions.
|
|
65
70
|
// compose-bindings imports nothing from vault-practices, so no cycle.
|
|
66
71
|
const compose_bindings_cjs_1 = require("./compose-bindings.cjs");
|
|
67
|
-
// The one source/non-source predicate (plan graph). A leaf with no imports of
|
|
68
|
-
// its own, so no cycle.
|
|
69
|
-
const plan_graph_cjs_1 = require("./plan-graph.cjs");
|
|
70
72
|
const { extractFrontmatter } = fmMod;
|
|
71
73
|
// ─── Constants ─────────────────────────────────────────────────────────────────
|
|
72
74
|
// DoS-guard cap (T-24-04) mirroring vault.cts's SUMMARY_FILE_CAP discipline —
|
|
@@ -82,7 +84,7 @@ const PRACTICES_SUBDIR = 'practices/';
|
|
|
82
84
|
// retained + warned, never dropped).
|
|
83
85
|
//
|
|
84
86
|
// `check` joined the set in 05-01 and `enforced-by` in 10-03 (MECH-03,
|
|
85
|
-
// D-10-04). Both are step 1 of
|
|
87
|
+
// D-10-04). Both are step 1 of ADR-71924 §5's fixed rollout order (engine
|
|
86
88
|
// release → verified rollout → vault-repo merge): the engine admits the key
|
|
87
89
|
// first, the rollout is verified, and only then does the vault repo merge
|
|
88
90
|
// practices that use it. Neither addition bumped PRACTICE_SCHEMA_VERSION
|
|
@@ -114,7 +116,7 @@ const GLOB_PATTERN_MAX = 200;
|
|
|
114
116
|
// Bounded markdown-body excerpt size for scope:global practices (D-15) —
|
|
115
117
|
// mirrors vault.cts's SUMMARY_READ_BYTES bounded-read discipline.
|
|
116
118
|
const PRACTICE_EXCERPT_BYTES = 1024;
|
|
117
|
-
// Over-read factor for the excerpt's bounded read (FIX-1).
|
|
119
|
+
// Over-read factor for the excerpt's bounded read (quick 261003-jby, FIX-1).
|
|
118
120
|
// The excerpt is normalised to LF before it is capped, and every carriage
|
|
119
121
|
// return that normalisation removes consumed a raw byte as half of a CRLF pair.
|
|
120
122
|
// Reading `PRACTICE_EXCERPT_BYTES * 2` body bytes therefore guarantees the cap
|
|
@@ -124,12 +126,17 @@ const EXCERPT_CRLF_OVERREAD_FACTOR = 2;
|
|
|
124
126
|
// Matched-file list cap per practice (T-24-04) — matchedCount still carries
|
|
125
127
|
// the true total so callers know the cap was hit.
|
|
126
128
|
const MATCHED_FILES_CAP = 20;
|
|
127
|
-
// The unmatched-source-file note's candidate set (
|
|
128
|
-
//
|
|
129
|
-
//
|
|
130
|
-
//
|
|
129
|
+
// The unmatched-source-file note's candidate set (quick 261003-jby, FIX-2,
|
|
130
|
+
// QD-2): a file passed to the matcher whose basename ends with one of these
|
|
131
|
+
// extensions (case-insensitive), or starts with the Dockerfile prefix (exact),
|
|
132
|
+
// is one a scoped practice is EXPECTED to govern in the client's stacks. When
|
|
133
|
+
// such a file matched no scoped practice the block says so in one plain line,
|
|
131
134
|
// because a vault laid out for a different folder structure otherwise drops its
|
|
132
|
-
// scoped practices with no word at all
|
|
135
|
+
// scoped practices with no word at all (probe test 6: 20 scoped practices, 5 of
|
|
136
|
+
// them critical, silently matched nothing). Frozen constants so widening the
|
|
137
|
+
// set is a one-line edit, not a decision buried in a predicate.
|
|
138
|
+
const UNMATCHED_NOTE_SOURCE_EXTENSIONS = Object.freeze(['.cs', '.sql', '.ts', '.vue', '.kt']);
|
|
139
|
+
const UNMATCHED_NOTE_BASENAME_PREFIX = 'Dockerfile';
|
|
133
140
|
// Bounded prefix read for practice files during DISCOVERY (CR-03) — frontmatter
|
|
134
141
|
// + bodyOffset comfortably fit well inside this; the whole file is NEVER read.
|
|
135
142
|
// Mirrors vault.cts's SUMMARY_READ_BYTES bounded-read discipline.
|
|
@@ -154,9 +161,6 @@ const WARNING_TOKEN_MAX = 80;
|
|
|
154
161
|
// pre-22.5 fallback matcher 0.098 ms / pair (same corpus, feature
|
|
155
162
|
// detect deleted before require)
|
|
156
163
|
//
|
|
157
|
-
// (The fallback matcher is now the only shipped engine — see `globMatch`.
|
|
158
|
-
// The native figure is kept as the measurement the caps below were sized on.)
|
|
159
|
-
//
|
|
160
164
|
// 05-RESEARCH § OQ1 measured 1.47 ms/pair native over three points that were
|
|
161
165
|
// linear in pair count, so `cost ≈ pairs × rate` is a measured model rather
|
|
162
166
|
// than a hoped-for one. Its 5.0 ms/pair fallback figure did NOT reproduce on
|
|
@@ -181,8 +185,8 @@ const WARNING_TOKEN_MAX = 80;
|
|
|
181
185
|
// makes the verdict machine-dependent, which is exactly the non-determinism
|
|
182
186
|
// VERIFY-03 bars from a deterministic gate).
|
|
183
187
|
//
|
|
184
|
-
// Sized above the legitimate ceiling and well below the hostile one:
|
|
185
|
-
//
|
|
188
|
+
// Sized above the legitimate ceiling and well below the hostile one: the real
|
|
189
|
+
// client vault's 92 globs against the 2000-file ship diff cap is 184,000
|
|
186
190
|
// pairs, so this leaves ~5× headroom over any honest corpus while sitting
|
|
187
191
|
// ~7.8× below the 7,800,000-pair hostile saturation bound.
|
|
188
192
|
//
|
|
@@ -239,13 +243,13 @@ const PRACTICES_VAULT_UNREADABLE_SENTENCE = 'Practices were NOT checked — the
|
|
|
239
243
|
*/
|
|
240
244
|
const PRACTICES_VAULT_ABSENT_SENTENCE = 'Practices were NOT checked — no client vault has been fetched. Run the vault fetch first.';
|
|
241
245
|
/**
|
|
242
|
-
* The FOURTH member of the family (FIX-4, QD-5).
|
|
246
|
+
* The FOURTH member of the family (quick 261003-jby, FIX-4, QD-5).
|
|
243
247
|
*
|
|
244
248
|
* A fetch that failed every tier with no prior copy leaves a manifest recording
|
|
245
249
|
* a miss: no tier, no sha, no files. The vault directory is present, nothing
|
|
246
250
|
* failed to READ, and discovery yields zero practices — so the ladder fell
|
|
247
251
|
* through to "none found in the vault", telling a code-writing agent its client
|
|
248
|
-
* documented no standards about a fetch that reached nothing.
|
|
252
|
+
* documented no standards about a fetch that reached nothing (probe test 2).
|
|
249
253
|
*
|
|
250
254
|
* The documented "could not be checked: <reason>." form, with the reason
|
|
251
255
|
* phrase copied from the practice trace's own miss reason (`resolvePin` in
|
|
@@ -253,7 +257,18 @@ const PRACTICES_VAULT_ABSENT_SENTENCE = 'Practices were NOT checked — no clien
|
|
|
253
257
|
*/
|
|
254
258
|
const PRACTICES_VAULT_MISS_SENTENCE = 'Practices could not be checked: the vault manifest records a miss — no vault content was reached.';
|
|
255
259
|
/**
|
|
256
|
-
* The
|
|
260
|
+
* The FIFTH member of the family (quick 261015-at3, Vince 2026-10-15).
|
|
261
|
+
*
|
|
262
|
+
* The vault was fetched and read, and it is a standards vault: `INDEX.md` at
|
|
263
|
+
* its root and no practice files. The project reads it in practices mode, so
|
|
264
|
+
* discovery yields zero practices and the ladder fell through to "none found in
|
|
265
|
+
* the vault" — telling a code-writing agent the client documented no practices,
|
|
266
|
+
* about a vault whose standards the project is not reading at all. Names the
|
|
267
|
+
* one repair: the mode, and the engine version that has it.
|
|
268
|
+
*/
|
|
269
|
+
const PRACTICES_VAULT_STANDARDS_ONLY_SENTENCE = 'Practices were NOT checked — this vault holds standards (INDEX.md) and no practice files, but the project reads it in practices mode. Set "vault": {"mode": "standards"} in .planning/config.json (pp-core 1.16.0 or later) and re-plan.';
|
|
270
|
+
/**
|
|
271
|
+
* The status stamp's fixed opening (quick 261003-jby, FIX-3, QD-4).
|
|
257
272
|
*
|
|
258
273
|
* Every rendered `<vault_practices>` block carries ONE HTML comment as its
|
|
259
274
|
* first inner line, written by this module, naming the vault ref, short sha,
|
|
@@ -273,6 +288,9 @@ const PRACTICES_STAMP_STATES = Object.freeze({
|
|
|
273
288
|
VAULT_UNREADABLE: 'vault-unreadable',
|
|
274
289
|
VAULT_ABSENT: 'vault-absent',
|
|
275
290
|
VAULT_MISS: 'vault-miss',
|
|
291
|
+
// Quick 261015-at3: a standards vault (INDEX.md, no practice files) read in
|
|
292
|
+
// practices mode.
|
|
293
|
+
STANDARDS_ONLY: 'standards-only',
|
|
276
294
|
ALL_REFUSED: 'all-refused',
|
|
277
295
|
NONE_FOUND: 'none-found',
|
|
278
296
|
NONE_APPLY: 'none-apply',
|
|
@@ -358,6 +376,12 @@ function boundedToken(v) {
|
|
|
358
376
|
const s = safeStringify(v).replace(/[\r\n]+/g, ' ');
|
|
359
377
|
return s.length > WARNING_TOKEN_MAX ? `${s.slice(0, WARNING_TOKEN_MAX)}…` : s;
|
|
360
378
|
}
|
|
379
|
+
// ─── Glob matching (PRAC-02) ───────────────────────────────────────────────────
|
|
380
|
+
// Feature-detect once at module scope: `path.posix.matchesGlob` landed in
|
|
381
|
+
// Node 22.5.0 and stabilized in 22.20.0 (RESEARCH STACK.md), but this repo's
|
|
382
|
+
// engines floor is >=22.0.0 — the 22.0–22.4 gap must fall back to the
|
|
383
|
+
// hand-rolled matcher below rather than throwing `TypeError: not a function`.
|
|
384
|
+
const hasMatchesGlob = typeof node_path_1.default.posix?.matchesGlob === 'function';
|
|
361
385
|
const NEVER_MATCHES = { test: () => false };
|
|
362
386
|
// Bounds the total number of concrete patterns a `{a,b,c}` expansion can
|
|
363
387
|
// produce (T-24-04) — client-authored globs never legitimately need more.
|
|
@@ -498,7 +522,7 @@ function globSegmentsMatch(patternSegs, subjectSegs) {
|
|
|
498
522
|
*
|
|
499
523
|
* ON THE NAME (05-04). Despite it, this function constructs NO `RegExp` — it
|
|
500
524
|
* returns an object literal whose `test` runs the two-pointer matcher above.
|
|
501
|
-
*
|
|
525
|
+
* ADR-71924 §3 says the same thing ("despite its name") and the confusion has
|
|
502
526
|
* now cost more than one verification pass, so it is stated here at the
|
|
503
527
|
* definition rather than only in the ADR. A rename to `compileGlobMatcher`
|
|
504
528
|
* was considered and REJECTED: the rename guard's 2331-file baseline is not
|
|
@@ -521,18 +545,23 @@ function fallbackGlobToRegex(pattern) {
|
|
|
521
545
|
}
|
|
522
546
|
/**
|
|
523
547
|
* True when `filePath` matches `pattern`. Normalizes `\` → `/` (Windows path
|
|
524
|
-
* input) before matching
|
|
525
|
-
*
|
|
526
|
-
*
|
|
527
|
-
* identical boolean (PRAC-02).
|
|
548
|
+
* input) before matching. Uses `path.posix.matchesGlob` when the runtime
|
|
549
|
+
* supports it (feature-detected once at module scope), else the linear/
|
|
550
|
+
* polynomial-time `fallbackGlobToRegex` matcher. Deterministic: identical
|
|
551
|
+
* inputs always yield the identical boolean (PRAC-02).
|
|
528
552
|
*/
|
|
529
553
|
function globMatch(filePath, pattern) {
|
|
530
|
-
//
|
|
531
|
-
//
|
|
554
|
+
// Pre-dispatch length guard (T-24-04, gap #1 verifier ask b): apply
|
|
555
|
+
// GLOB_PATTERN_MAX BEFORE choosing an engine so the cap holds for the
|
|
556
|
+
// native `path.posix.matchesGlob` path too, not only the fallback
|
|
557
|
+
// compiler's internal check.
|
|
532
558
|
if (typeof pattern !== 'string' || pattern.length === 0 || pattern.length > GLOB_PATTERN_MAX) {
|
|
533
559
|
return false;
|
|
534
560
|
}
|
|
535
561
|
const normalized = filePath.replace(/\\/g, '/');
|
|
562
|
+
if (hasMatchesGlob) {
|
|
563
|
+
return node_path_1.default.posix.matchesGlob(normalized, pattern);
|
|
564
|
+
}
|
|
536
565
|
return fallbackGlobToRegex(pattern).test(normalized);
|
|
537
566
|
}
|
|
538
567
|
// Unsupported glob metacharacters (gap #1 closure option a, D-14/D-07):
|
|
@@ -642,13 +671,13 @@ function normalizeCheckBoolean(v) {
|
|
|
642
671
|
}
|
|
643
672
|
/**
|
|
644
673
|
* Parse and validate a practice's `check:` block. THE ONLY parser for this
|
|
645
|
-
* shape (
|
|
674
|
+
* shape (ADR-71924 §2): 05-05's evaluator receives a validated record and
|
|
646
675
|
* validates nothing itself, so a rule that is not enforced here is not
|
|
647
676
|
* enforced anywhere.
|
|
648
677
|
*
|
|
649
678
|
* A violation never skips the practice. The block is dropped whole — never
|
|
650
679
|
* half-built — and one bounded, single-line `checkInvalid` records the defect,
|
|
651
|
-
* because the practice's prose still applies (
|
|
680
|
+
* because the practice's prose still applies (ADR §5). 05-05 maps
|
|
652
681
|
* `checkInvalid` to a fail-closed FAIL so a broken block can never read as a
|
|
653
682
|
* pass, nor be mistaken for "this practice was never checkable".
|
|
654
683
|
*
|
|
@@ -657,7 +686,7 @@ function normalizeCheckBoolean(v) {
|
|
|
657
686
|
* the evaluator and the reader drifting apart. The literal half is bounded by
|
|
658
687
|
* CHECK_TOKEN_COUNT_CAP and CHECK_TOKEN_MAX, and is compared only by plain
|
|
659
688
|
* substring containment: no client-authored byte reaches a RegExp constructor
|
|
660
|
-
* or any other pattern compiler (
|
|
689
|
+
* or any other pattern compiler (ADR §3, T-5-05).
|
|
661
690
|
*/
|
|
662
691
|
function parseCheckBlock(id, rawCheck) {
|
|
663
692
|
const invalid = (defect) => ({
|
|
@@ -827,7 +856,7 @@ function parsePracticeFile(filePath, raw) {
|
|
|
827
856
|
// Unknown-key DEGRADE (IN-05, inverted by CHECK-02 in 05-01).
|
|
828
857
|
//
|
|
829
858
|
// This branch used to `return { ok: false }`, dropping the whole practice.
|
|
830
|
-
//
|
|
859
|
+
// ADR-71924 §5 requires the opposite: an engine that meets a key it does
|
|
831
860
|
// not recognize must degrade LOUDLY — retain the practice, apply its prose
|
|
832
861
|
// through the normal path, and warn naming the key. Dropping it meant the
|
|
833
862
|
// practice silently governed nothing, which is the "governance check that
|
|
@@ -939,7 +968,7 @@ function parsePracticeFile(filePath, raw) {
|
|
|
939
968
|
// Note the asymmetry with the `< 1` / non-integer arm just above, which
|
|
940
969
|
// stays a HARD skip: a malformed value is not a forward-compat signal,
|
|
941
970
|
// it is a broken file. Only a well-formed version this engine is too old
|
|
942
|
-
// to understand degrades — that is the case
|
|
971
|
+
// to understand degrades — that is the case ADR-71924 §5's rollout order
|
|
943
972
|
// exists to make legible rather than silent.
|
|
944
973
|
if (parsed > PRACTICE_SCHEMA_VERSION) {
|
|
945
974
|
degradedWarnings.push(`${safePath} degraded: schemaVersion ${parsed} is newer than this pp-core supports ` +
|
|
@@ -951,7 +980,7 @@ function parsePracticeFile(filePath, raw) {
|
|
|
951
980
|
const fmMatch = raw.match(/^---\r?\n[\s\S]+?\r?\n---/);
|
|
952
981
|
const bodyOffset = fmMatch ? fmMatch[0].length : 0;
|
|
953
982
|
// The check: block is validated HERE, alongside every other parse-time
|
|
954
|
-
// rule, so there is exactly one parser for it (
|
|
983
|
+
// rule, so there is exactly one parser for it (ADR-71924 §2). An invalid
|
|
955
984
|
// block never skips the practice — see `parseCheckBlock`.
|
|
956
985
|
const checkOutcome = fm.check === undefined ? null : parseCheckBlock(id, fm.check);
|
|
957
986
|
// `enforced-by:` is read HERE, in the position parseCheckBlock occupies —
|
|
@@ -1062,7 +1091,8 @@ function probePracticesDir(practicesDirPath) {
|
|
|
1062
1091
|
*
|
|
1063
1092
|
* @param cwd Project root (parent of `.planning/`).
|
|
1064
1093
|
* @param vaultDir Optional cache directory to read instead of
|
|
1065
|
-
* `<cwd>/.planning/vault` (
|
|
1094
|
+
* `<cwd>/.planning/vault` (260915-ms2, UAT-6-F3 — the trace writer passes the
|
|
1095
|
+
* owning main checkout's cache from a linked worktree). Defaults to the cwd
|
|
1066
1096
|
* join, so the absent-versus-unreadable distinction below is unchanged for
|
|
1067
1097
|
* every caller that does not pass it.
|
|
1068
1098
|
*/
|
|
@@ -1078,7 +1108,7 @@ function discoverPracticeFiles(cwd, vaultDir) {
|
|
|
1078
1108
|
// grounds stay separable for whoever has to repair it.
|
|
1079
1109
|
return {
|
|
1080
1110
|
practices: [], skipped: [], degraded: [], tier: null, notes: [], vaultPresent: false, readFailed: false,
|
|
1081
|
-
vaultRef: null, vaultSha: null, vaultMiss: false,
|
|
1111
|
+
vaultRef: null, vaultSha: null, vaultMiss: false, vaultStandardsOnly: false,
|
|
1082
1112
|
};
|
|
1083
1113
|
}
|
|
1084
1114
|
const probe = probePracticesDir(node_path_1.default.join(vaultDirPath, PRACTICES_SUBDIR.slice(0, -1)));
|
|
@@ -1095,12 +1125,24 @@ function discoverPracticeFiles(cwd, vaultDir) {
|
|
|
1095
1125
|
}
|
|
1096
1126
|
const manifest = vaultMod.readManifest(vaultDirPath);
|
|
1097
1127
|
const tier = manifest && manifest.tier ? manifest.tier : null;
|
|
1098
|
-
// FIX-3/FIX-4: the coordinates the status stamp carries,
|
|
1128
|
+
// Quick 261003-jby (FIX-3/FIX-4): the coordinates the status stamp carries,
|
|
1099
1129
|
// and the recorded-miss fact the sentence ladder states. Typed facts on the
|
|
1100
1130
|
// result, never sniffed out of notes prose.
|
|
1101
1131
|
const vaultRef = manifest && typeof manifest.ref === 'string' ? manifest.ref : null;
|
|
1102
1132
|
const vaultSha = manifest && typeof manifest.resolvedSha === 'string' ? manifest.resolvedSha : null;
|
|
1103
1133
|
const vaultMiss = vaultMod.manifestRecordsMiss(manifest);
|
|
1134
|
+
// Quick 261015-at3 (Vince 2026-10-15): a standards vault read in practices
|
|
1135
|
+
// mode. Two facts from the ONE `allFiles` listing the practice filter read
|
|
1136
|
+
// above (exact-case INDEX match, the standards reader's own contract) plus
|
|
1137
|
+
// one mode read. The mode is part of the owner on purpose: the audit's and
|
|
1138
|
+
// the trace's readers have no standards-mode short-circuit of their own, so
|
|
1139
|
+
// a caller that forgot one still cannot trip this flag in standards mode.
|
|
1140
|
+
const modeVerdict = vaultMod.vaultModeVerdict(cwd);
|
|
1141
|
+
const vaultStandardsOnly = modeVerdict.active === true
|
|
1142
|
+
&& modeVerdict.ok === true
|
|
1143
|
+
&& modeVerdict.mode === 'practices'
|
|
1144
|
+
&& allFiles.includes(vaultIndexLeaf.VAULT_INDEX_FILENAME)
|
|
1145
|
+
&& practiceFiles.length === 0;
|
|
1104
1146
|
const practices = [];
|
|
1105
1147
|
const skipped = [];
|
|
1106
1148
|
const degraded = [];
|
|
@@ -1142,7 +1184,7 @@ function discoverPracticeFiles(cwd, vaultDir) {
|
|
|
1142
1184
|
}
|
|
1143
1185
|
return {
|
|
1144
1186
|
practices, skipped, degraded, tier, notes, vaultPresent: true, readFailed: probe.failed,
|
|
1145
|
-
vaultRef, vaultSha, vaultMiss,
|
|
1187
|
+
vaultRef, vaultSha, vaultMiss, vaultStandardsOnly,
|
|
1146
1188
|
};
|
|
1147
1189
|
}
|
|
1148
1190
|
catch (e) {
|
|
@@ -1168,16 +1210,16 @@ function discoverPracticeFiles(cwd, vaultDir) {
|
|
|
1168
1210
|
vaultRef: null,
|
|
1169
1211
|
vaultSha: null,
|
|
1170
1212
|
vaultMiss: false,
|
|
1213
|
+
vaultStandardsOnly: false,
|
|
1171
1214
|
};
|
|
1172
1215
|
}
|
|
1173
1216
|
}
|
|
1174
1217
|
// ─── Matching + report (PRAC-02 / PRAC-03 / COMM-01) ───────────────────────────
|
|
1175
|
-
// External-content fence (D-15 /
|
|
1176
|
-
// owner
|
|
1177
|
-
//
|
|
1178
|
-
//
|
|
1179
|
-
|
|
1180
|
-
const { EXTERNAL_CONTENT_FENCE_START, EXTERNAL_CONTENT_FENCE_END, defangFenceMarkers } = vaultMod;
|
|
1218
|
+
// External-content fence markers and `defangFenceMarkers` (D-15 / CR-01 /
|
|
1219
|
+
// T-24-05): the owner moved to the vault-index leaf (D-17/D-26, 14-04), and
|
|
1220
|
+
// these bindings re-export it by reference so every consumer of this module
|
|
1221
|
+
// measures the leaf's one function rather than a copy.
|
|
1222
|
+
const { EXTERNAL_CONTENT_FENCE_START, EXTERNAL_CONTENT_FENCE_END, defangFenceMarkers } = vaultIndexLeaf;
|
|
1181
1223
|
/**
|
|
1182
1224
|
* Read a BOUNDED prefix of a practice file's markdown BODY (frontmatter
|
|
1183
1225
|
* stripped) and wrap it in the `vault:external-content` fence + untrusted-
|
|
@@ -1189,16 +1231,16 @@ const { EXTERNAL_CONTENT_FENCE_START, EXTERNAL_CONTENT_FENCE_END, defangFenceMar
|
|
|
1189
1231
|
* neutralized via `defangFenceMarkers` BEFORE being placed between the real
|
|
1190
1232
|
* markers (CR-01), so an untrusted body can never spoof an early fence closer.
|
|
1191
1233
|
*
|
|
1192
|
-
* LINE ENDINGS (FIX-1). The body is sliced at `bodyOffset`
|
|
1234
|
+
* LINE ENDINGS (quick 261003-jby, FIX-1). The body is sliced at `bodyOffset`
|
|
1193
1235
|
* FIRST — it is an index into the raw text, computed by `parsePracticeFile` on
|
|
1194
1236
|
* the same bytes — and THEN normalised by deleting every carriage return, which
|
|
1195
1237
|
* turns each CRLF pair into LF and drops any lone carriage return (a control
|
|
1196
1238
|
* character that must not reach an agent context). Only then is it trimmed and capped, so the
|
|
1197
1239
|
* `PRACTICE_EXCERPT_BYTES` cap is measured on normalised text and a CRLF
|
|
1198
1240
|
* checkout renders the same excerpt as its LF twin. Before this, the cap was
|
|
1199
|
-
* applied to raw text:
|
|
1200
|
-
*
|
|
1201
|
-
* executor-facing block.
|
|
1241
|
+
* applied to raw text: probe test 4 measured 8 of 55 practices losing 3–18
|
|
1242
|
+
* chars on a `core.autocrlf=true` checkout, and 610 carriage returns reaching
|
|
1243
|
+
* the executor-facing block.
|
|
1202
1244
|
*
|
|
1203
1245
|
* @param filePath Absolute path to the practice `.md` file on disk.
|
|
1204
1246
|
* @param bodyOffset Byte index where the markdown body begins (from the
|
|
@@ -1225,16 +1267,19 @@ function boundedFencedExcerpt(filePath, bodyOffset) {
|
|
|
1225
1267
|
}
|
|
1226
1268
|
/**
|
|
1227
1269
|
* Is this file one the unmatched-source-file note reports when no scoped
|
|
1228
|
-
* practice matched it? (FIX-2, QD-2.)
|
|
1270
|
+
* practice matched it? (quick 261003-jby, FIX-2, QD-2.)
|
|
1229
1271
|
*
|
|
1230
|
-
*
|
|
1231
|
-
*
|
|
1232
|
-
* is. Windows separators are normalised first.
|
|
1272
|
+
* POSIX basename (Windows separators are normalised first); the extension
|
|
1273
|
+
* compare is case-insensitive, the `Dockerfile` prefix compare is exact.
|
|
1233
1274
|
*
|
|
1234
1275
|
* @param filePath A project-relative file path, either separator.
|
|
1235
1276
|
*/
|
|
1236
1277
|
function isUnmatchedNoteCandidate(filePath) {
|
|
1237
|
-
|
|
1278
|
+
const base = node_path_1.default.posix.basename(String(filePath).replace(/\\/g, '/'));
|
|
1279
|
+
if (base.startsWith(UNMATCHED_NOTE_BASENAME_PREFIX))
|
|
1280
|
+
return true;
|
|
1281
|
+
const lower = base.toLowerCase();
|
|
1282
|
+
return UNMATCHED_NOTE_SOURCE_EXTENSIONS.some((ext) => lower.endsWith(ext));
|
|
1238
1283
|
}
|
|
1239
1284
|
/**
|
|
1240
1285
|
* Match discovered practices against a candidate file list, partitioning
|
|
@@ -1306,6 +1351,8 @@ function matchPractices(opts) {
|
|
|
1306
1351
|
vaultRef: discovery.vaultRef,
|
|
1307
1352
|
vaultSha: discovery.vaultSha,
|
|
1308
1353
|
vaultMiss: discovery.vaultMiss,
|
|
1354
|
+
// Quick 261015-at3: threaded on BOTH return sites (05-13 rule).
|
|
1355
|
+
vaultStandardsOnly: discovery.vaultStandardsOnly === true,
|
|
1309
1356
|
pairBudget: {
|
|
1310
1357
|
pairs,
|
|
1311
1358
|
cap: MATCH_PAIR_CAP,
|
|
@@ -1412,10 +1459,12 @@ function matchPractices(opts) {
|
|
|
1412
1459
|
vaultAbsent: discovery.vaultPresent === false,
|
|
1413
1460
|
unmatchedSourceFiles,
|
|
1414
1461
|
// The manifest coordinates and recorded-miss fact, carried verbatim from
|
|
1415
|
-
// discovery (FIX-3/FIX-4).
|
|
1462
|
+
// discovery (quick 261003-jby, FIX-3/FIX-4).
|
|
1416
1463
|
vaultRef: discovery.vaultRef,
|
|
1417
1464
|
vaultSha: discovery.vaultSha,
|
|
1418
1465
|
vaultMiss: discovery.vaultMiss,
|
|
1466
|
+
// Quick 261015-at3: the standards-vault-in-practices-mode fact, verbatim.
|
|
1467
|
+
vaultStandardsOnly: discovery.vaultStandardsOnly === true,
|
|
1419
1468
|
pairBudget: {
|
|
1420
1469
|
pairs,
|
|
1421
1470
|
cap: MATCH_PAIR_CAP,
|
|
@@ -1490,7 +1539,7 @@ function renderSkippedLines(skipped) {
|
|
|
1490
1539
|
}
|
|
1491
1540
|
/**
|
|
1492
1541
|
* The one-line note naming candidate files that matched no scoped practice
|
|
1493
|
-
* (FIX-2). `null` when there are none.
|
|
1542
|
+
* (quick 261003-jby, FIX-2). `null` when there are none.
|
|
1494
1543
|
*
|
|
1495
1544
|
* The paths are project-authored — the plan's `files_modified` or the
|
|
1496
1545
|
* operator's argv, the same trust class `matched_files` already renders — so
|
|
@@ -1629,8 +1678,8 @@ function unwrapFencedExcerpt(fenced) {
|
|
|
1629
1678
|
* `id` and `source` just as much as the excerpt prose — and this block is read
|
|
1630
1679
|
* by a code-WRITING executor in Phase 26. So every field passes through
|
|
1631
1680
|
* `boundedToken` (length bound, control-character strip) AND
|
|
1632
|
-
* `defangFenceMarkers` (so a planted
|
|
1633
|
-
* cannot terminate the fence early and smuggle text out of the data region)
|
|
1681
|
+
* `defangFenceMarkers` (so a planted end-of-fence marker, spelled only in the
|
|
1682
|
+
* vault-index leaf, cannot terminate the fence early and smuggle text out of the data region)
|
|
1634
1683
|
* before it is placed between the markers. Nothing vault-authored is emitted
|
|
1635
1684
|
* outside a fence anywhere in this block.
|
|
1636
1685
|
*/
|
|
@@ -1671,7 +1720,8 @@ function stampSha(sha) {
|
|
|
1671
1720
|
return hex.length >= 8 ? hex.slice(0, 8) : '(none)';
|
|
1672
1721
|
}
|
|
1673
1722
|
/**
|
|
1674
|
-
* Render the block's status stamp — ONE line, an HTML comment (
|
|
1723
|
+
* Render the block's status stamp — ONE line, an HTML comment (quick
|
|
1724
|
+
* 261003-jby, FIX-3, QD-4).
|
|
1675
1725
|
*
|
|
1676
1726
|
* `ref=` and `sha=` name the vault read, `entries=<n>` counts the fenced
|
|
1677
1727
|
* practice entries rendered OR `state=<token>` names the degraded state —
|
|
@@ -1696,7 +1746,7 @@ function renderPracticesStamp(parts) {
|
|
|
1696
1746
|
}
|
|
1697
1747
|
/**
|
|
1698
1748
|
* Choose the sentence an entry-less block states AND its stamp token, in ONE
|
|
1699
|
-
* place so the two cannot drift (FIX-3/FIX-4).
|
|
1749
|
+
* place so the two cannot drift (quick 261003-jby, FIX-3/FIX-4).
|
|
1700
1750
|
*
|
|
1701
1751
|
* ORDER IS LOAD-BEARING and pinned rung by rung. The pair-cap refusal stays
|
|
1702
1752
|
* FIRST: it is a statement about work this engine declined to do. Read
|
|
@@ -1705,6 +1755,12 @@ function renderPracticesStamp(parts) {
|
|
|
1705
1755
|
* none-found rungs, which are facts about a vault that WAS read. The miss rung
|
|
1706
1756
|
* (FIX-4) sits after absence (an absent directory has no manifest to record a
|
|
1707
1757
|
* miss in, so absence is the more basic fact) and before all-refused.
|
|
1758
|
+
*
|
|
1759
|
+
* The standards-only rung (quick 261015-at3) sits after the miss — a miss
|
|
1760
|
+
* reached no vault that could hold an index, so it is the more basic fact —
|
|
1761
|
+
* and ABOVE all-refused and none-found. It is a statement about a vault that
|
|
1762
|
+
* WAS read, which is why it is below the unread family; and "none found" is
|
|
1763
|
+
* false of a vault whose practice layer the project is not even reading.
|
|
1708
1764
|
*/
|
|
1709
1765
|
function selectEmptyBlockSentence(result, skippedCount) {
|
|
1710
1766
|
if (result?.pairBudget?.exceeded === true) {
|
|
@@ -1720,11 +1776,16 @@ function selectEmptyBlockSentence(result, skippedCount) {
|
|
|
1720
1776
|
if (result?.vaultAbsent === true) {
|
|
1721
1777
|
return { sentence: PRACTICES_VAULT_ABSENT_SENTENCE, state: PRACTICES_STAMP_STATES.VAULT_ABSENT };
|
|
1722
1778
|
}
|
|
1723
|
-
// FIX-4: a manifest that records a miss — the fetch ran
|
|
1779
|
+
// Quick 261003-jby (FIX-4): a manifest that records a miss — the fetch ran
|
|
1724
1780
|
// and reached nothing.
|
|
1725
1781
|
if (result?.vaultMiss === true) {
|
|
1726
1782
|
return { sentence: PRACTICES_VAULT_MISS_SENTENCE, state: PRACTICES_STAMP_STATES.VAULT_MISS };
|
|
1727
1783
|
}
|
|
1784
|
+
// Quick 261015-at3: a standards vault (INDEX.md, no practice files) read in
|
|
1785
|
+
// practices mode — NOT checked, never none-found.
|
|
1786
|
+
if (result?.vaultStandardsOnly === true) {
|
|
1787
|
+
return { sentence: PRACTICES_VAULT_STANDARDS_ONLY_SENTENCE, state: PRACTICES_STAMP_STATES.STANDARDS_ONLY };
|
|
1788
|
+
}
|
|
1728
1789
|
if (result && result.practicesProcessed === 0 && skippedCount > 0) {
|
|
1729
1790
|
// 05-REVIEW WR-02, the fifth rung. `practicesProcessed === 0` is true of a
|
|
1730
1791
|
// THIRD kind of vault as well: one that holds practice files and had every
|
|
@@ -1759,7 +1820,7 @@ function selectEmptyBlockSentence(result, skippedCount) {
|
|
|
1759
1820
|
function renderPracticesBlock(result, reason) {
|
|
1760
1821
|
const open = '<vault_practices>';
|
|
1761
1822
|
const close = '</vault_practices>';
|
|
1762
|
-
// FIX-3: the status stamp is the first line inside the
|
|
1823
|
+
// FIX-3 (quick 261003-jby): the status stamp is the first line inside the
|
|
1763
1824
|
// block on all three return paths, then the blank line, then the preamble.
|
|
1764
1825
|
const engine = (0, compose_bindings_cjs_1.resolveCreatedWithFrom)(__dirname);
|
|
1765
1826
|
const headWith = (stamp) => [
|
|
@@ -1850,7 +1911,7 @@ function renderPracticesBlock(result, reason) {
|
|
|
1850
1911
|
'',
|
|
1851
1912
|
]
|
|
1852
1913
|
: [];
|
|
1853
|
-
// FIX-2: candidate files no scoped practice matched. The
|
|
1914
|
+
// FIX-2 (quick 261003-jby): candidate files no scoped practice matched. The
|
|
1854
1915
|
// matcher owns the gating (QD-3); the renderer renders whenever the array is
|
|
1855
1916
|
// non-empty. Engine-composed text around project-authored, bounded and
|
|
1856
1917
|
// defanged paths — nothing vault-authored — so it sits outside a fence.
|
|
@@ -1876,7 +1937,7 @@ function renderPracticesBlock(result, reason) {
|
|
|
1876
1937
|
//
|
|
1877
1938
|
// The rungs themselves — and their order — live in
|
|
1878
1939
|
// `selectEmptyBlockSentence`, which picks the sentence and the stamp token
|
|
1879
|
-
// together so the two cannot drift.
|
|
1940
|
+
// together (quick 261003-jby) so the two cannot drift.
|
|
1880
1941
|
const { sentence, state } = selectEmptyBlockSentence(result, skipped.length);
|
|
1881
1942
|
const head = headWith({ state });
|
|
1882
1943
|
return [...head, ...notesSection, ...degradedSection, ...refusedSection, ...noteSection, sentence, '', close].join('\n');
|
|
@@ -1911,7 +1972,7 @@ module.exports = {
|
|
|
1911
1972
|
// class comes back: a second renderer is a second place a client-authored byte
|
|
1912
1973
|
// can reach an agent context unfenced. Purely additive; no call site changed.
|
|
1913
1974
|
renderPracticeEntry,
|
|
1914
|
-
// D-05-07: exported so the trace scaffold digests the SAME
|
|
1975
|
+
// 261003-j89 (D-05-07 closed): exported so the trace scaffold digests the SAME
|
|
1915
1976
|
// text `renderPracticeEntry` places under `ask:`/`excerpt:` — one unwrap, two
|
|
1916
1977
|
// readers. A second unwrap in src/vault-trace.cts would be a second place the
|
|
1917
1978
|
// fence-stripping rule could drift, and the digest would then disagree with
|
|
@@ -1973,17 +2034,23 @@ module.exports = {
|
|
|
1973
2034
|
// exact hazard (see its doc comment) — never a raw Node error message, which
|
|
1974
2035
|
// interpolates the absolute path CLAUDE.md § Logging forbids surfacing.
|
|
1975
2036
|
errnoOf,
|
|
1976
|
-
// FIX-1: the excerpt's CRLF over-read factor, exported so
|
|
2037
|
+
// Quick 261003-jby (FIX-1): the excerpt's CRLF over-read factor, exported so
|
|
1977
2038
|
// the bounded-read test and the contract page HARVEST it.
|
|
1978
2039
|
EXCERPT_CRLF_OVERREAD_FACTOR,
|
|
1979
|
-
// FIX-2: the unmatched-source-file note's
|
|
1980
|
-
// exported so tests and
|
|
2040
|
+
// Quick 261003-jby (FIX-2): the unmatched-source-file note's candidate set,
|
|
2041
|
+
// predicate and one-line composer — exported so tests and the contract page
|
|
2042
|
+
// harvest them and both rendered channels compose the line in one place.
|
|
2043
|
+
UNMATCHED_NOTE_SOURCE_EXTENSIONS,
|
|
2044
|
+
UNMATCHED_NOTE_BASENAME_PREFIX,
|
|
1981
2045
|
isUnmatchedNoteCandidate,
|
|
1982
2046
|
renderUnmatchedSourceNote,
|
|
1983
|
-
// FIX-3/FIX-4: the status stamp's prefix, state vocabulary
|
|
2047
|
+
// Quick 261003-jby (FIX-3/FIX-4): the status stamp's prefix, state vocabulary
|
|
1984
2048
|
// and renderer, and the recorded-miss sentence — exported so tests and the
|
|
1985
2049
|
// contract page harvest them rather than copy them.
|
|
1986
2050
|
PRACTICES_VAULT_MISS_SENTENCE,
|
|
2051
|
+
// Quick 261015-at3: the standards-vault-in-practices-mode sentence, exported
|
|
2052
|
+
// on the same harvest rule.
|
|
2053
|
+
PRACTICES_VAULT_STANDARDS_ONLY_SENTENCE,
|
|
1987
2054
|
PRACTICES_STAMP_PREFIX,
|
|
1988
2055
|
PRACTICES_STAMP_STATES,
|
|
1989
2056
|
renderPracticesStamp,
|