rcf-lite 0.7.1 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +97 -0
- package/bin/rcf.js +6 -0
- package/fixtures/canary-manifest.json +9 -9
- package/guidance/harness-template.md +11 -0
- package/guidance/managed/agent-instructions-block.hash +1 -1
- package/guidance/managed/agent-instructions-block.md +11 -0
- package/package.json +5 -3
- package/rcf/adrs/adr-010.json +30 -0
- package/rcf/code-nodes/cn-058.json +18 -0
- package/rcf/code-nodes/cn-059.json +14 -0
- package/rcf/code-nodes/cn-060.json +14 -0
- package/rcf/code-nodes/cn-061.json +14 -0
- package/rcf/code-nodes/cn-062.json +14 -0
- package/rcf/code-nodes/cn-063.json +15 -0
- package/rcf/code-nodes/cn-064.json +15 -0
- package/rcf/code-nodes/cn-065.json +16 -0
- package/rcf/code-nodes/cn-066.json +14 -0
- package/rcf/code-nodes/cn-067.json +15 -0
- package/rcf/code-nodes/cn-068.json +15 -0
- package/rcf/code-nodes/cn-069.json +16 -0
- package/rcf/fbs/fbs-016.json +39 -0
- package/rcf/fbs/fbs-017.json +40 -0
- package/rcf/fbs/fbs-018.json +34 -0
- package/rcf/fbs/fbs-019.json +33 -0
- package/rcf/requirements/req-010.json +20 -0
- package/rcf/test-suites/ts-026.json +54 -0
- package/rcf/test-suites/ts-027.json +115 -0
- package/rcf/test-suites/ts-028.json +46 -0
- package/rcf/test-suites/ts-029.json +46 -0
- package/rcf/user-stories/us-1001.json +56 -0
- package/rcf/user-stories/us-1002.json +96 -0
- package/rcf/user-stories/us-1003.json +48 -0
- package/rcf/user-stories/us-1004.json +48 -0
- package/src/admissibility/enforce.js +142 -0
- package/src/admissibility/index.js +8 -0
- package/src/admissibility/markers.js +104 -0
- package/src/admissibility/scope-lint.js +163 -0
- package/src/blueprint/apply.js +464 -0
- package/src/blueprint/conflicts.js +351 -0
- package/src/blueprint/diff.js +82 -0
- package/src/blueprint/index.js +12 -0
- package/src/blueprint/list.js +21 -0
- package/src/blueprint/loader.js +163 -0
- package/src/blueprint/manifest-writer.js +49 -0
- package/src/blueprint/namespace.js +145 -0
- package/src/blueprint/remove.js +105 -0
- package/src/blueprint/resolutions.js +83 -0
- package/src/blueprint/standards.js +148 -0
- package/src/blueprint/supersede.js +318 -0
- package/src/browser-verify/invariants.js +33 -6
- package/src/build/bundle.js +34 -11
- package/src/build/standards-selector.js +52 -0
- package/src/cli/blueprint.js +325 -0
- package/src/cli/create.js +49 -1
- package/src/cli/help.js +8 -0
- package/src/cli/init.js +20 -5
- package/src/cli/read.js +7 -1
- package/src/cli/standards.js +127 -0
- package/src/cli/test-suite.js +7 -2
- package/src/core/store/ids.js +168 -18
- package/src/core/store/loader.js +31 -17
- package/src/core/store/walker.js +62 -4
- package/src/core/store/writer.js +41 -11
- package/src/deployment/index.js +13 -0
- package/src/deployment/placeholder-detector.js +113 -0
- package/src/finalise/detect.js +51 -29
- package/src/finalise/index.js +16 -2
- package/src/finalise/ingest.js +41 -0
- package/src/mcp/tools.js +10 -2
- package/src/query/formatters/table.js +7 -10
- package/src/query/index.js +4 -0
- package/src/query/refuse-on-admissibility.js +73 -0
- package/src/query/trace.js +45 -4
- package/src/ruleset/index.js +140 -0
- package/src/ruleset/ruleset.json +146 -0
- package/src/verify/chain/index.js +31 -0
- package/src/verify/verdict/index.js +67 -0
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,103 @@ All notable changes to this project are documented in this file.
|
|
|
4
4
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). Pre-1.0, breaking changes are signalled by a minor version bump.
|
|
6
6
|
|
|
7
|
+
## [0.9.0] - 2026-08-25
|
|
8
|
+
|
|
9
|
+
The blueprint-mechanism release. Ships Phase 1 blueprint composition (standards + selective retrieval), Phase 3.5 conflict-resolution verbs, the 0.4.4 prefix-family id grammar seam, and the first content packages built on the mechanism: SPA (v1.0.0 through v1.3.0 including the styled-under-CSP and deployment-gate cures), auth (v1.0.0 magic-link + opaque cookie sessions), persistence (v1.0.0 SQLite-first store), ci-pipeline (v1.0.0), observability (v1.0.0), and REST (16 REQ / 20 US / 117 AC doc set). Consumes `@stravica-ai/rcf-schemas@0.4.5` (exact pin, additive-only from 0.4.3 through 0.4.5).
|
|
10
|
+
|
|
11
|
+
### Added (release cycle roll-up)
|
|
12
|
+
|
|
13
|
+
Detailed entries below cover the Phase 3.5 verbs (PR #90). The following merges since 0.8.0 also ship in this release and are not itemised further here; each landed with its own tests, docs, and (where applicable) fbs / us / adr chain:
|
|
14
|
+
|
|
15
|
+
- **PR #83 Phase 1 blueprint mechanism.** Blueprint composition, standards ruleset wiring, selective retrieval. Foundation for every `blueprint/*-v1.0.0` PR that follows.
|
|
16
|
+
- **PR #84 walker + loader for the 0.4.4 prefix-family id grammar (w-2026-08-19-001).** Teaches the store walker and loader the widened id shapes admitted by `@stravica-ai/rcf-schemas@0.4.4` so prefix-family ids (e.g. `FBS-004-user-login`, `US-1002`, four-digit TS / TC ids) round-trip through the graph without silent detachment.
|
|
17
|
+
- **PR #86 SPA blueprint content package (w-2026-08-19-001).** First content package on the blueprint mechanism.
|
|
18
|
+
- **PR #87 Phase 1 blueprint mechanism, eight post-review nits.**
|
|
19
|
+
- **PR #88 blueprint ownership fix (w-2026-08-19-005).** Ownership checks consult the authoritative manifest record, not string grammar.
|
|
20
|
+
- **PR #89 REST blueprint content package (w-2026-08-19-005, d-2026-08-19-007).** 16 REQ / 20 US (117 AC) / 6 TAC / 8 ADR doc set with OpenAPI skeleton, auth-class reference, samples, guide, topics vocabulary.
|
|
21
|
+
- **PR #91 blueprint authoring documentation.** Standard, walkthrough, checklist, plus their registration in the links manifest.
|
|
22
|
+
- **PR #92 pre-handover fix batch.** Three CLI paper-cuts, doc fixes, agent-block nudges.
|
|
23
|
+
- **PR #93 auth blueprint v1.0.0.** Passwordless magic-link plus opaque cookie sessions.
|
|
24
|
+
- **PR #94 persistence blueprint v1.0.0.** SQLite-first store with a forward-only migration runner.
|
|
25
|
+
- **PR #95 ci-pipeline blueprint v1.0.0.**
|
|
26
|
+
- **PR #96 observability blueprint v1.0.0.** Two-endpoint HTTP health probes, public status page, notification-outcome sink.
|
|
27
|
+
- **PR #97 SPA blueprint v1.1.0.** Icon and token mechanism-reach cure.
|
|
28
|
+
- **PR #98 SPA blueprint v1.2.0.** Styled-under-shipped-CSP mechanism-reach cure, plus the `noInlineStyleBlocks` invariant on the rcf-lite side.
|
|
29
|
+
- **PR #99 SPA blueprint v1.3.0 (w-2026-08-24-006).** External-dep provisioning, core-flow E2E deployment-gate class cure, plus the rcf-lite placeholder-shape detector.
|
|
30
|
+
|
|
31
|
+
### Added (blueprint conflict-resolution verbs, w-2026-08-19-008)
|
|
32
|
+
|
|
33
|
+
- **`src/blueprint/resolutions.js`.** Pure helpers on top of the new `manifest.resolutions[]` seam (rcf-schemas 0.4.5): `nextResolutionId(manifest, now)` mints monotonic `res-YYYY-MM-DD-NNN` ids; `matchingResolution(manifest, { topic, incoming, existing })` returns the resolution record that resolves a specific globalAdrTopic conflict pair, matching on kind + topic + both `{slug, adrId}` pairs listed in `supersedes[]` (superset OK, subset not).
|
|
34
|
+
- **`src/blueprint/supersede.js` + `rcf blueprint supersede <topic>` verb.** Scaffolds a project-level ADR at `rcf/adrs/adr-NNN-<topic>.json` (well-formed against `adr.schema.json`, editable stubs) that supersedes every applied blueprint's scope:global ADR on the topic, and appends a `manifest.resolutions[]` record so the detector honours the resolution on subsequent `rcf blueprint add` runs. Refuses when the topic has fewer than two applied scope:global ADRs, when the manifest is missing prd or tad, and when a file already exists at the scaffolded ADR path. Optional `--reason` operator note; whitespace-only reasons are refused at the writer edge.
|
|
35
|
+
- **`rcf blueprint add --resolve <topic>=project:<ADR-id>` flag.** Repeatable per conflicted topic. Records a `manifest.resolutions[]` entry in-memory BEFORE conflict detection runs, so a freshly declared resolution is honoured; the record then persists via the manifest write alongside the applied-blueprint update. Refuses declarations whose topic does not match a scope:global ADR on the incoming blueprint, whose topic has no matching applied blueprint, whose `resolvedByAdrId` is mis-shaped, or whose `--reason` is whitespace-only.
|
|
36
|
+
- **`src/blueprint/conflicts.js` reshape.** `detectGlobalAdrConflicts` accepts an optional manifest and honours matching resolutions. `renderConflictReport` now leads each conflict block with per-side `blueprint <slug>: <title> — <decision>` headers (falls back to `<id> at <path>` when the tree did not carry the ADR body), footers ids + paths under `refs:`, and names four honest resolution paths (adopt-incoming, keep-existing, supersede via project ADR, declare-on-add via `--resolve`) with the actual conflicting blueprint slugs already substituted — no `<slug>` placeholders. New `conflictReportJson(conflicts)` returns the same shape as a machine-readable object for agent-driven composition.
|
|
37
|
+
- **`src/blueprint/apply.js` enrichment.** ADR title + one-sentence decision are pulled off `tree.byId` for the existing side and threaded onto the conflict record so the renderer's per-side headers render cleanly.
|
|
38
|
+
- **`src/blueprint/diff.js` + `rcf blueprint diff <topic>` verb.** Read-only side-by-side view of every applied blueprint's scope:global ADR on a topic: id, path, title, status, decision.
|
|
39
|
+
- **`src/cli/blueprint.js` wiring.** New verbs `supersede`, `diff`; new flags `--resolve` (repeatable), `--reason`, `--json` on `add`.
|
|
40
|
+
- **`src/blueprint/index.js` re-exports** the new APIs: `nextResolutionId`, `matchingResolution`, `supersedeBlueprintTopic`, `diffBlueprintTopic`, `renderDiff`, `conflictReportJson`, `detectCrossBlueprintClaims`.
|
|
41
|
+
- **New tests.** `test/blueprint/resolutions.test.js` (10), `test/blueprint/supersede.test.js` (5), `test/blueprint/coresidence.test.js` (3 — the SPA + REST co-residence money paths via supersede-first, declare-on-add, and honour-idempotency), `test/blueprint/diff.test.js` (4), plus 5 new cases on `test/blueprint/cli.test.js` (--resolve success + reshape refuse, --json refuse + apply, supersede verb, diff verb, --resolve validation) and 2 updated cases on `test/blueprint/conflicts.test.js` (reshape assertions).
|
|
42
|
+
- **`fbs-017` + `us-1002` prose refresh (residual fold-in).** `fbs/fbs-017.json` approach + notes now name the manifest-record ownership model (Phase 3.5 rewrite of the earlier grammar narrative) and the Phase 3.5 verbs; `user-stories/us-1002.json` AC-1002-3 now describes the reshaped four-honest-paths message rather than the pre-Phase-3.5 three-path placeholder prose. `test/view/fixtures/phase-3-6-static.html` regenerated to match.
|
|
43
|
+
|
|
44
|
+
### Changed
|
|
45
|
+
|
|
46
|
+
- **`packages/rcf-lite/package.json`** dependency `@stravica-ai/rcf-schemas` bumped `0.4.4 -> 0.4.5` (exact pin, per the umbrella exact-pin doctrine). 0.4.5 is an additive-only patch adding `manifest.resolutions[]`.
|
|
47
|
+
|
|
48
|
+
## [0.8.0] - 2026-08-12 (on `slug-train/0.8.0`, PR pending)
|
|
49
|
+
|
|
50
|
+
### Added (Car 4, verify updates per requirements doc)
|
|
51
|
+
|
|
52
|
+
- **`src/verify/chain/index.js` (`readChain`) surfaces AC `scope` and per-TC `boundTcs`.** Every flattened AC now carries the schema-declared scope tag (or `undefined` for bootstrap-era ACs) plus a `boundTcs[]` list of `{ tsId, tcId, scope }` for every bound TC. Verify's downstream verdict layer runs the scope check off this shape, matching the shape the admissibility lint's `scanTcScopeVsAc` consumes at build stage.
|
|
53
|
+
- **`src/verify/verdict/index.js` (`scopePerAcVerdict`, extended `derivePerAcVerdicts`).** New `SCOPE-MISMATCH` per-AC verdict (NV-BL-GATE-01 + NV-BL-ADM-03). Fires when an AC declares a scope tag AND every bound TC's scope is narrower than the AC's scope AND at least one bound TC declares a scope tag (bootstrap-era TCs without a tag are silent -- the admissibility lint handles that class). At least one TC at or wider than the AC scope clears the mismatch (a wider TC is always admissible). Emitted alongside the four 0.7.0 per-AC verdict classes on `report.perAcVerdicts[]`. Existing report validator (`src/verify/report/index.js`) admits the new class via the widened `PER_AC_VERDICTS` enum.
|
|
54
|
+
- **`src/finalise/ingest.js` (`findScopeMismatchAcs`, `reportHasScopeMismatch`; extended `summariseReport`).** NV-BL-GATE-01 REVIEW-stage consumers (`rcf review <fbs-id>`, `rcf finalise`) read the same shape via new predicates. `summariseReport` renders a dedicated `scope mismatches (N)` section when the report carries any SCOPE-MISMATCH entries (silent when none, so pre-0.8.0 reports remain byte-identical in the summary output).
|
|
55
|
+
- **`src/finalise/index.js` re-exports** `findScopeMismatchAcs` and `reportHasScopeMismatch` alongside the pre-existing mock-only-declared predicates.
|
|
56
|
+
- **`test/verify/chain/scope-derivation-0-8-0.test.js` (2 tests):** chain reader hands through AC.scope + per-TC scope on boundTcs; leaves AC.scope undefined when the AC has no tag.
|
|
57
|
+
- **`test/verify/verdict/scope-mismatch-0-8-0.test.js` (7 tests):** narrower TC surfaces SCOPE-MISMATCH; wider or equal TC clears; deployed TC covering runtime AC is fine; AC without scope is silent; TC without scope is silent; AC with no bound TCs is silent; `derivePerAcVerdicts` emits SCOPE-MISMATCH alongside MOCK-ONLY-DECLARED on the same AC when both apply.
|
|
58
|
+
- **`test/finalise/scope-mismatch-0-8-0.test.js` (5 tests):** `findScopeMismatchAcs` extracts SCOPE-MISMATCH only; graceful with absent perAcVerdicts; `reportHasScopeMismatch` truthiness; `summariseReport` renders a dedicated section; silent when no mismatches present.
|
|
59
|
+
- **`test/verify/verdict/per-ac-verdicts-0-7-0.test.js` PER_AC_VERDICTS assertion updated** to include SCOPE-MISMATCH (0.8.0 slug-train car 4).
|
|
60
|
+
|
|
61
|
+
### Version bump
|
|
62
|
+
|
|
63
|
+
- **`package.json` version 0.7.1 -> 0.8.0.** Consumes `@stravica-ai/rcf-schemas@0.4.3` (exact pin per the umbrella exact-pin doctrine ratified alongside item 18; the 0.4.3 diff is additive-only and preserved by the existing back-compat fixtures on the schemas side). The `rcf-lite@0.8.0` tag + publish is out of this train's scope and Dave will cut it post-merge.
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
The `0.8.0` admissibility-and-ruleset release, cut against the ratified next-version plan (`projects/rcf-build-lite/docs/2026-08-06_next-version-plan-amendment.md`) and requirements (`projects/rcf-build-lite/docs/2026-08-06_build-lite-nextver-requirements.md`). Ships the shared standards ruleset bundled inside this umbrella package, wires build-lite's fitness tracks around it (admissibility lint refuse-by-default, build-stage drift refusal, gate tightenings), and pulls verify's per-AC scope check into REVIEW. Car 1 of the slug-train, `@stravica-ai/rcf-schemas@0.4.3`, published to npm on 2026-08-12 and is EXACT-PINNED here (no caret, no range) per the umbrella exact-pin doctrine ratified alongside item 18. The 0.4.3 diff is additive-only: widened id patterns to accept an optional kebab-case slug tail on FBS / CN / ADR / TAC ids, widened TS/TC to drop the 999 cap, added the shared `scopeTag` vocabulary in `common.schema.json`, and added optional `scope` fields on AC and TC. Every existing chain continues to validate; no retro-slugging is performed.
|
|
68
|
+
|
|
69
|
+
### Added (Car 3, admissibility lint + drift refusal + refuse-by-default in query)
|
|
70
|
+
|
|
71
|
+
- **`src/admissibility/` module (`#admissibility`).** Chain-admissibility gate wiring per NV-BL-ADM-02, -03, -04, -05, -06. Refuse-first per ratified ruling-sheet item 1.
|
|
72
|
+
- `scanAcScopeCoverage(tree, { tolerateUnclassified })` (NV-BL-ADM-02): every AC must carry a known scope tag from the shared vocabulary. `unclassified` is tolerated during the migration window (default; `tolerateUnclassified: false` fails those too after the window closes).
|
|
73
|
+
- `scanTcScopeVsAc(tree, opts)` (NV-BL-ADM-03): every bound TC's scope must be equal to or wider than the covered AC's scope. `library` < `runtime` < `deployed`; a wider TC on a narrower AC is admissible (opposite trips a finding).
|
|
74
|
+
- `scanSourceStringForMarkers(source, { filePath, markers })` and `scanFilesForMarkers(filePaths)` (NV-BL-ADM-04): scan source for the ratified marker vocabulary (`TODO`, `FIXME`, `XXX`, `HACK`, `placeholder`, `v1 refinement`, `deferred`, `stub`; case-insensitive). Line + column offsets on each finding. Vocabulary is read from the ruleset at call time so a future ruleset revision picks up without recompiling this module.
|
|
75
|
+
- `enforceAdmissibility({ tree, chainRulesetVersion, overrides, opts })` (NV-BL-ADM-05 + -06): the top-level refuse-first gate. Combines the scope scans with `detectRulesetDrift`; applies recorded overrides per rule id + optional documentId; emits `{ verdict: 'pass' | 'refuse' | 'passWithOverrides', findings, unresolved, appliedOverrides, drift }`. Guardrail: NV-BL-ADM-04 findings can NEVER be masked through the generic override channel (ruling-sheet item 16 narrowed override to ADR-only for source markers).
|
|
76
|
+
- `getRulesetToolScope()`: exposes the ruleset's `toolScope` block so consumers decide whether to apply the traceability-and-query-tools refusal per NV-BL-SR-03 addendum.
|
|
77
|
+
- **`src/query/refuse-on-admissibility.js` (`runWithAdmissibilityGate`).** NV-BL-SR-03 addendum wiring (ruling-sheet item 1): traceability and query tools share the refuse-first posture. Wraps a query producer such that a REFUSE verdict short-circuits the query and returns a refusal envelope naming the unresolved rule ids; PASS lets the producer run and returns its payload. Re-exported from `src/query/index.js`.
|
|
78
|
+
- **`#admissibility` package.json import specifier.** New subpath alias mapping to `./src/admissibility/index.js`.
|
|
79
|
+
- **`test/admissibility/scope-lint.test.js` (5 tests)** covering NV-BL-ADM-02 absent / unclassified / tolerance, NV-BL-ADM-03 narrower-fails / wider-passes.
|
|
80
|
+
- **`test/admissibility/markers.test.js` (4 tests)** covering the case-insensitive vocabulary scan, line/column offsets, empty input, and multi-file scan + ioFailure surfacing.
|
|
81
|
+
- **`test/admissibility/enforce.test.js` (7 tests)** covering NV-BL-ADM-06 missing-version + behavioural drift refusal, NV-BL-ADM-05 override application, the NV-BL-ADM-04 override guardrail, `getRulesetToolScope`, and `runWithAdmissibilityGate` short-circuit + pass paths.
|
|
82
|
+
|
|
83
|
+
### Changed (Car 3, landmines + schemas pin)
|
|
84
|
+
|
|
85
|
+
- **`@stravica-ai/rcf-schemas` bumped to EXACT `0.4.3`** (no caret, no range) per the ratified umbrella exact-pin doctrine (item 18 alongside the 0.4.3 release). The 0.4.3 diff is additive-only: widened `fbsId` / `cnId` / `adrId` / `tacId` to accept an optional kebab-case slug tail, widened `tsId` / `tcId` from `\d{3}` to `\d{3,}` (drops the 999 cap), added `common.$defs.scopeTag` (`library | runtime | deployed | unclassified`), added OPTIONAL `scope` on the AC subschema (`user-story.schema.json`) and TC subschema (`test-suite.schema.json`). Every pre-0.4.3 chain continues to validate; no retro-slugging is performed (the design is preferred-with-numeric-fallback per w-2026-07-28-012). Pin review: the additive-only nature is asserted by the schemas repo's `manifest-004-pre-040-backcompat.json` fixture round-tripping cleanly under 0.4.3, and by the existing writer / walker tests continuing to pass with the bumped pin.
|
|
86
|
+
|
|
87
|
+
### Fixed (Car 3, w-2026-07-28-012 landmines)
|
|
88
|
+
|
|
89
|
+
Four landmine fixes lifted from `w-2026-07-28-012` (design notes + d-2026-07-28-011 recon), each landing WITH its regression test. Every fix is a precondition for the slug-consuming changes that follow it in the same car; the walker prefix-only-uppercase fix lands first, per the ratified sequencing.
|
|
90
|
+
|
|
91
|
+
- **Landmine 1: `packages/rcf-lite/src/core/store/walker.js` (loadChildKind).** The walker used to derive tree ids by upper-casing the whole filename stem (`stem.toUpperCase()`). Lossless while every id was `<PREFIX>-<digits>`; the moment a slug lands (`fbs-004-user-login.json` -> body `fbsId: "FBS-004-user-login"`), the whole-stem fold produced `FBS-004-USER-LOGIN` in `tree.byId` / `kindById` / `parentByChild` while every inbound reference used the lower-case form. The graph silently detached. The fix (`idFromFilenameStem`) upper-cases the prefix segment only and leaves the slug tail verbatim. Regression: `test/store/walker.test.js` `walkTree preserves case on slug tails when deriving id from filename`; also asserts a valid inbound `dependsOnFbsIds` reference resolves to the byId entry.
|
|
92
|
+
- **Landmine 2: `packages/rcf-lite/src/core/store/writer.js` (nextFlatId).** The allocator's high-water mark used a slug-blind regex `^${prefix}-(\d+)$`; a slugged id was invisible to the max and the allocator reset to 001, re-issuing taken numbers. The fix replaces the local regex with the shared `idNumber(id, prefix)` helper (`ids.js:72-78`, pattern `^${prefix}-(\d+)(?:-|$)`) which parses both numeric-only and slugged shapes into the same numeric key. Regression: `test/core/store/writer.test.js` `nextIdForKind sees slugged ids in the occupancy set` and `nextIdForKind never re-issues a slugged FBS number even without a companion numeric-only FBS at the same slot`.
|
|
93
|
+
- **Landmine 3: hardcoded three-digit id patterns across seven walker/writer sites AND three consumer-path stragglers.** The moment a TS crosses 999 (rcf-schemas 0.4.3 admits `TS-1000`), the walker's `idPrefixMatchesParent` rule silently skipped every inline TC under that TS, and the writer's `nextIdForKind tc` refused with "unrecognised TS id" even though the schema admitted the parent. Widened all sites to `\d{3,}` in lockstep with the schema. Walker + writer sites (7 total): `packages/rcf-lite/src/core/store/walker.js:851/854` and `writer.js:252/908/1163` (four regex sites), plus the corresponding comments and the resolveInlineId TC branch on writer.js widened for consistency. Consumer-path stragglers (3 sites, folded in as a rework commit after the initial car 3.1 landed): `packages/rcf-lite/src/cli/test-suite.js:85` (hard-refused any TS >= 1000 in `rcf test-suite <id> {provenance|approve}` with an error text citing "TS-015"; widened + error text updated to cite both "TS-015" and "TS-1000"), `packages/rcf-lite/src/cli/read.js:122` (`rcf read TC-1000-x` silently fell through to null even when the TC existed under a widened TS; widened the inline-TC guard), and `packages/rcf-lite/src/mcp/tools.js:765` (same silent-null pattern via the MCP read tool). Regressions: `test/core/store/writer.test.js` `nextIdForKind tc admits a TS beyond 999` + `walker inline-TC prefix-match rule fires for TS beyond 999`; `test/cli/test-suite-cli.test.js` `rcf test-suite TS-1000 provenance accepts a four-digit TS id` + `rcf test-suite TS-1000 approve accepts a four-digit TS id` + `rcf test-suite refuses a non-TS positional and cites both three-digit and four-digit shapes`; `test/cli/read.test.js` `rcf read TC-1000-first-case resolves the inline TC on a widened (four-digit) TS`; `test/mcp/tools.test.js` `rcf_read: resolves an inline TC on a widened (four-digit) TS`.
|
|
94
|
+
- **Landmine 4: `packages/rcf-lite/src/core/store/writer.js` (`deriveSlug`).** Returned the literal `'tc'` on empty derivation. Every non-TC caller (FBS, CN, ADR, TAC create paths) would silently produce an id ending in `-tc` when the source description derived to empty -- wrong kind label baked in as a slug. The fix returns `''` at the source and moves the `|| 'tc'` fallback to the TC-specific callers (`writer.js` `createInlineTc`, `mcp/tools.js`, `cli/create.js`). Regression: `deriveSlug lowercases and squashes non-alphanumeric runs` updated (`!!!` now maps to `''`, not `'tc'`) and a new `0.8.0 slug-train (landmine 4): deriveSlug returns empty string, not the "tc" literal` test.
|
|
95
|
+
|
|
96
|
+
### Added (Car 2, shared standards ruleset)
|
|
97
|
+
|
|
98
|
+
- **`src/ruleset/ruleset.json` (NV-BL-SR-01).** Single machine-readable artefact bundled inside the umbrella package, camelCase per estate convention. Names the admissibility rule identifiers (`NV-BL-ADM-01`..`NV-BL-ADM-06`), the gate rule identifiers (`NV-BL-GATE-01`..`NV-BL-GATE-04`), the scope-tag vocabulary reference (points at `@stravica-ai/rcf-schemas` `common.schema.json#/$defs/scopeTag` rather than owning the enum, ratified 2026-08-11 item 11), the source-comment marker vocabulary (`TODO`, `FIXME`, `XXX`, `HACK`, `placeholder`, `v1 refinement`, `deferred`, `stub` — all case-insensitive per NV-BL-ADM-04), the canonical TC template family identifiers (`TCT-SERVER-BOOT`, `TCT-CLI-INVOKE`, `TCT-CONTAINER-RUN` — NV-BL-GATE-03), and the light-mechanical ruling-consistency check family (`RCC-EXTERNAL-RESOURCE-CONTRADICTION`, `RCC-TIER-CAPABILITY-MISMATCH` — NV-BL-GATE-04; probabilistic/suitability checks live in rcf-define-lite under DL-REQ-VALIDATE-04). `toolScope` covers chain admissibility AND traceability/query tools per the ratified addendum on item 1.
|
|
99
|
+
- **`src/ruleset/index.js` (`#ruleset`).** Loader for the artefact. `getRuleset()` returns the frozen artefact with `rulesetVersion` stamped at read time from the umbrella `package.json` (NV-BL-SR-02: the ruleset has no separate semver; its version IS the umbrella version). `detectRulesetDrift({ chainRulesetVersion })` classifies chain-vs-shipping version mismatch as `none | additive | behavioural | missing`, feeding `NV-BL-ADM-06` (build-stage refusal on behavioural drift) and `DL-REQ-VALIDATE-03` (define-stage warning). `getUmbrellaVersion()` exposes the same version so callers do not re-parse `package.json`. `resetRulesetCache()` for tests.
|
|
100
|
+
- **`#ruleset` package.json import specifier.** New subpath alias mapping to `./src/ruleset/index.js` so consumers reach the loader without hard-coding a relative path.
|
|
101
|
+
- **`docs/ruleset.md`.** Ruleset reference doc — artefact location, version policy (NV-BL-SR-02), content at v1 (NV-BL-SR-03), consumers, migration state.
|
|
102
|
+
- **`test/ruleset/ruleset.test.js`.** 14 tests covering NV-BL-SR-01 shape, NV-BL-SR-02 version stamping (umbrella-authoritative; baked-in `rulesetVersion` on the JSON refused), NV-BL-SR-03 content (every ADM/GATE id present, every ADM rule `refuseByDefault: true`, scope-tag vocabulary points at schemas, marker list matches NV-BL-ADM-04 vocabulary, TC template family matches NV-BL-GATE-03 surfaces, ruling-consistency checks are light-mechanical), and `detectRulesetDrift` classes.
|
|
103
|
+
|
|
7
104
|
## [0.7.0] - 2026-07-31
|
|
8
105
|
|
|
9
106
|
The cold-run response train. Four tracks land together in one release, each closing a systemic gap the 0.5.2 watchpost cold run exposed. Ships alongside `@stravica-ai/rcf-lite-core@0.3.0` (shared pattern sets, baseline catalog, canary fixtures) and `@stravica-ai/rcf-verify-lite@0.2.0` (per-AC verdict classes, chain-reader derivation); `@stravica-ai/rcf-schemas@0.4.2` already carries the full 0.7.0 surface additively so every new chain field is optional at the schema layer. Track A (verification integrity) ships the primitives that keep a mocked integration test from ever again looking identical to a live one: the chain gains an honest record of what the tests actually verified against. Track B (UI design gate + quality baseline) ships the Design substage (Stage 1.5), the ruled UI baseline, and the browser-verification gate for UI-bearing FBSes. Tracks C and D (elicitation upstream + playbook hardening) ship the REQ-shape classifier and baseline-AC catalog with silence-refuses-build enforcement (Track C), the variable-fidelity intake stage (Track C), and the release-time register canary, never-skip-RCF invariant, review-surface persistence and persona tail-interview template (Track D). Every field is optional at schema; the ENFORCEMENT (elicitation, `coverage --strict`, the review-stage audit, the finalise gate, `--mark complete` refusals, the Stage-1 sweep gate) is what makes them de-facto required for new chains from 0.7.0 onward.
|
package/bin/rcf.js
CHANGED
|
@@ -36,6 +36,9 @@ import { main as uiBaselineMain } from '../src/cli/ui-baseline.js';
|
|
|
36
36
|
import { main as uiClassifyMain } from '../src/cli/ui-classify.js';
|
|
37
37
|
import { main as designMain } from '../src/cli/design.js';
|
|
38
38
|
import { main as browserVerifyMain } from '../src/cli/browser-verify.js';
|
|
39
|
+
// Blueprint mechanism (Phase 1, w-2026-08-18-016).
|
|
40
|
+
import { main as blueprintMain } from '../src/cli/blueprint.js';
|
|
41
|
+
import { main as standardsMain } from '../src/cli/standards.js';
|
|
39
42
|
import { main as updateMain } from '../src/cli/update.js';
|
|
40
43
|
import { main as validateMain } from '../src/cli/validate.js';
|
|
41
44
|
import { main as viewMain } from '../src/cli/view.js';
|
|
@@ -76,6 +79,9 @@ export const SUBCOMMANDS = {
|
|
|
76
79
|
'ui-baseline': uiBaselineMain,
|
|
77
80
|
design: designMain,
|
|
78
81
|
'browser-verify': browserVerifyMain,
|
|
82
|
+
// Blueprint mechanism (Phase 1, w-2026-08-18-016).
|
|
83
|
+
blueprint: blueprintMain,
|
|
84
|
+
standards: standardsMain,
|
|
79
85
|
// Track C+D (elicitation-and-playbook-hardening-0.7.0) verbs.
|
|
80
86
|
'req-classify': reqClassifyMain,
|
|
81
87
|
'req-baseline': reqBaselineMain,
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"registerCanary": [
|
|
3
3
|
{
|
|
4
|
-
"id": "rc-2026-08-
|
|
5
|
-
"createdAt": "2026-08-
|
|
6
|
-
"buildVersion": "0.
|
|
4
|
+
"id": "rc-2026-08-25-001",
|
|
5
|
+
"createdAt": "2026-08-25T14:47:32.185Z",
|
|
6
|
+
"buildVersion": "0.9.0-mockdriver",
|
|
7
7
|
"fixturePromptId": "canary-prompt-01",
|
|
8
8
|
"responseWordCount": 55,
|
|
9
9
|
"grades": {
|
|
@@ -34,9 +34,9 @@
|
|
|
34
34
|
"shipDespiteFailReason": "mock canary driver used; no real subagent was dispatched. This record verifies canary infrastructure only, not the register itself."
|
|
35
35
|
},
|
|
36
36
|
{
|
|
37
|
-
"id": "rc-2026-08-
|
|
38
|
-
"createdAt": "2026-08-
|
|
39
|
-
"buildVersion": "0.
|
|
37
|
+
"id": "rc-2026-08-25-002",
|
|
38
|
+
"createdAt": "2026-08-25T14:47:32.185Z",
|
|
39
|
+
"buildVersion": "0.9.0-mockdriver",
|
|
40
40
|
"fixturePromptId": "canary-prompt-02",
|
|
41
41
|
"responseWordCount": 55,
|
|
42
42
|
"grades": {
|
|
@@ -67,9 +67,9 @@
|
|
|
67
67
|
"shipDespiteFailReason": "mock canary driver used; no real subagent was dispatched. This record verifies canary infrastructure only, not the register itself."
|
|
68
68
|
},
|
|
69
69
|
{
|
|
70
|
-
"id": "rc-2026-08-
|
|
71
|
-
"createdAt": "2026-08-
|
|
72
|
-
"buildVersion": "0.
|
|
70
|
+
"id": "rc-2026-08-25-003",
|
|
71
|
+
"createdAt": "2026-08-25T14:47:32.185Z",
|
|
72
|
+
"buildVersion": "0.9.0-mockdriver",
|
|
73
73
|
"fixturePromptId": "canary-prompt-03",
|
|
74
74
|
"responseWordCount": 55,
|
|
75
75
|
"grades": {
|
|
@@ -42,6 +42,17 @@ non-technical; the method must be invisible in what they read.
|
|
|
42
42
|
not ask the operator to look it up for you.
|
|
43
43
|
- Never re-ask a granted permission. Track what the operator has
|
|
44
44
|
authorised and act on it. Asking again reads as not listening.
|
|
45
|
+
- Do not announce work you are about to do; do it, then report.
|
|
46
|
+
"I'll now run coverage and check the tree" burns a turn. Run the
|
|
47
|
+
check, report the outcome. Announce only when the work needs
|
|
48
|
+
authorisation you do not already have, or when it will take long
|
|
49
|
+
enough that silence would look like a stall.
|
|
50
|
+
- When the operator asks whether something works, answer with
|
|
51
|
+
evidence. Run the check, cite the command and the output. "Yes,
|
|
52
|
+
the health endpoint returns 200 - `curl -sS localhost:8080/health`
|
|
53
|
+
-> `{ok:true}`" is the shape. Never answer from memory of what
|
|
54
|
+
should be true; the method exists to make that class of answer
|
|
55
|
+
impossible.
|
|
45
56
|
- Tone: it is in hand. The operator steers; you drive. Confident
|
|
46
57
|
without hedging, and plainly honest when something is genuinely
|
|
47
58
|
blocked or ambiguous.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
7f5e3c3bd4c2c6c4bc7d98d77f7d715c7c43278a39e5ecfd0e85ed8d64e199f5
|
|
@@ -29,6 +29,17 @@ non-technical; the method must be invisible in what they read.
|
|
|
29
29
|
not ask the operator to look it up for you.
|
|
30
30
|
- Never re-ask a granted permission. Track what the operator has
|
|
31
31
|
authorised and act on it. Asking again reads as not listening.
|
|
32
|
+
- Do not announce work you are about to do; do it, then report.
|
|
33
|
+
"I'll now run coverage and check the tree" burns a turn. Run the
|
|
34
|
+
check, report the outcome. Announce only when the work needs
|
|
35
|
+
authorisation you do not already have, or when it will take long
|
|
36
|
+
enough that silence would look like a stall.
|
|
37
|
+
- When the operator asks whether something works, answer with
|
|
38
|
+
evidence. Run the check, cite the command and the output. "Yes,
|
|
39
|
+
the health endpoint returns 200 - `curl -sS localhost:8080/health`
|
|
40
|
+
-> `{ok:true}`" is the shape. Never answer from memory of what
|
|
41
|
+
should be true; the method exists to make that class of answer
|
|
42
|
+
impossible.
|
|
32
43
|
- Tone: it is in hand. The operator steers; you drive. Confident
|
|
33
44
|
without hedging, and plainly honest when something is genuinely
|
|
34
45
|
blocked or ambiguous.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rcf-lite",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "One-install tooling for the Requirements Confidence Framework (RCF): the unified `rcf` CLI (init, view, validate, build, verify, finalise and 25+ more verbs), an MCP server, the live tree viewer and the fresh-context adversarial ship-gate verifier. Consumes @stravica-ai/rcf-schemas.",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -53,10 +53,12 @@
|
|
|
53
53
|
"#core/patterns/services": "./src/core/patterns/services.js",
|
|
54
54
|
"#core/patterns/register-canary": "./src/core/patterns/register-canary.js",
|
|
55
55
|
"#core/baseline-catalog": "./src/core/baseline-catalog/index.js",
|
|
56
|
-
"#core/fixtures/register-canary/*": "./src/core/fixtures/register-canary/*"
|
|
56
|
+
"#core/fixtures/register-canary/*": "./src/core/fixtures/register-canary/*",
|
|
57
|
+
"#ruleset": "./src/ruleset/index.js",
|
|
58
|
+
"#admissibility": "./src/admissibility/index.js"
|
|
57
59
|
},
|
|
58
60
|
"dependencies": {
|
|
59
|
-
"@stravica-ai/rcf-schemas": "0.4.
|
|
61
|
+
"@stravica-ai/rcf-schemas": "0.4.5",
|
|
60
62
|
"ajv": "^8.20.0",
|
|
61
63
|
"ajv-formats": "^3.0.1"
|
|
62
64
|
},
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"adrId": "ADR-010",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"tadId": "TAD-001",
|
|
5
|
+
"version": "1.0.0",
|
|
6
|
+
"status": "accepted",
|
|
7
|
+
"title": "Blueprint conflict-topic vocabulary is a free-label lookup key (camelCase canonical on shipped blueprints)",
|
|
8
|
+
"context": "Round-1 of Phase 3.5 (w-2026-08-19-008) gate-tightened the topic vocabulary at the supersede writer by requiring topics to be kebab slugs; the SHIPPED SPA and REST blueprints declare their scope:global ADR topics in camelCase (authModel, errorEnvelope, clientRouting, theming, clientState, apiVersioning, logging), so following the reshaped conflict message's option 3 exactly as printed exited 2 with 'not a valid kebab slug' on every shipped topic. The 0.4.5 manifest schema is silent on topic character class (minLength: 1) and the schema docs cite errorEnvelope as an example. Gate-tightening past the schema is a first-class defect on this estate.",
|
|
9
|
+
"decision": "The blueprint conflict-topic vocabulary is a FREE LABEL — a lookup key used by the conflict detector (exact-match between an incoming ADR's declared topic and each applied ADR's declared topic) and by the resolution record (verbatim on manifest.resolutions[].topic). No character-class constraint beyond the schema's own minLength: 1 plus a writer-edge whitespace-only refuse. The shipped blueprint packs are canonical: their topics MUST be camelCase kebab-free single-word or camelCase identifiers (authModel, errorEnvelope, clientRouting, ...); new shipped blueprints follow the same convention. When a topic string must be projected into an id grammar that does require a kebab slug (specifically the scaffolded project-ADR id tail, whose grammar is `^ADR-\\d{3,}(-[a-z0-9]+(?:-[a-z0-9]+)*)?$`), the writer kebab-ifies at the projection edge (`authModel` -> `ADR-NNN-auth-model`) and never at the vocabulary edge.",
|
|
10
|
+
"consequences": "The reshaped conflict message's option 3 executes verbatim from the refused-add state against the shipped SPA + REST blueprints. Topic strings on manifest.resolutions[].topic remain byte-identical to the topic strings on the applied blueprint's ADR.contributions[].topic, so exact-match lookup is trivial to reason about. Kebab-ification is confined to the project-ADR id tail; the same topic string may appear verbatim in the manifest and kebab-cased inside an ADR id in the same tree without conflict. Blueprint authors who ship non-camelCase topics (kebab-case, snake_case) still validate against the schema; the exact-match detector still functions; only the ADR id tail projection changes.",
|
|
11
|
+
"alternativesConsidered": [
|
|
12
|
+
{
|
|
13
|
+
"name": "Enforce kebab-slug topics at the writer edge",
|
|
14
|
+
"summary": "Reject any topic string that is not `[a-z][a-z0-9]*(?:-[a-z0-9]+)*` at supersede and add --resolve.",
|
|
15
|
+
"reasonNotChosen": "Gate-tightens past the manifest schema (which is minLength: 1 with no character constraint), incompatible with the shipped SPA + REST blueprints' camelCase topic vocabulary, and made option 3 unexecutable as printed against the shipped packs."
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"name": "Retroactively kebab-case the shipped blueprint packs' topics",
|
|
19
|
+
"summary": "Change SPA + REST blueprints to declare kebab topics (auth-model, error-envelope, ...); consumers migrate.",
|
|
20
|
+
"reasonNotChosen": "The blueprint packs are canonical content the mechanism serves; the mechanism does not get to dictate the packs' vocabulary. camelCase is a legitimate identifier shape (the schema examples confirm it)."
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"name": "Normalise topics at the detector",
|
|
24
|
+
"summary": "Fold both sides to a canonical form (kebab or lowercased-strip-nonalnum) before comparing.",
|
|
25
|
+
"reasonNotChosen": "Introduces vocabulary drift (two different topic strings comparing equal) and makes the operator's mental model of what matches what harder, not easier. Exact-match on the free label is the least surprising rule."
|
|
26
|
+
}
|
|
27
|
+
],
|
|
28
|
+
"createdAt": "2026-08-19T15:45:00.000Z",
|
|
29
|
+
"updatedAt": "2026-08-19T15:45:00.000Z"
|
|
30
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"cnId": "CN-058",
|
|
3
|
+
"path": "src/blueprint/apply.js#applyBlueprint",
|
|
4
|
+
"title": "Blueprint apply orchestrator",
|
|
5
|
+
"description": "Loads a blueprint from a source directory, runs the conflict-detection pass BEFORE any file write, stamps contribution ids into the blueprint's namespace, copies contribution files into the tree, and appends a validated entry to manifest.blueprints[]. Idempotent on same-slug + same-version re-apply. From Phase 3.5 (w-2026-08-19-008) also composes any operator --resolve declarations into manifest.resolutions[] BEFORE detection so the resolution is honoured this run and persists alongside the applied-blueprint update, wires the singular --reason onto every generated declaration (whitespace-only refused at the writer edge), and dedupes duplicate --resolve topics within a single add (first-wins) surfacing a warning to the caller.",
|
|
6
|
+
"implementsAcIds": [
|
|
7
|
+
"AC-1001-1",
|
|
8
|
+
"AC-1001-4",
|
|
9
|
+
"AC-1002-2",
|
|
10
|
+
"AC-1002-6",
|
|
11
|
+
"AC-1002-7"
|
|
12
|
+
],
|
|
13
|
+
"dependencies": [],
|
|
14
|
+
"version": "0.1.0",
|
|
15
|
+
"status": "draft",
|
|
16
|
+
"createdAt": "2026-08-19T00:00:00Z",
|
|
17
|
+
"updatedAt": "2026-08-19T00:00:00Z"
|
|
18
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"cnId": "CN-059",
|
|
3
|
+
"path": "src/blueprint/list.js#listBlueprints",
|
|
4
|
+
"title": "Blueprint list projection",
|
|
5
|
+
"description": "Reads manifest.blueprints[] and returns rows in appliedAt order.",
|
|
6
|
+
"implementsAcIds": [
|
|
7
|
+
"AC-1001-2"
|
|
8
|
+
],
|
|
9
|
+
"dependencies": [],
|
|
10
|
+
"version": "0.1.0",
|
|
11
|
+
"status": "draft",
|
|
12
|
+
"createdAt": "2026-08-19T00:00:00Z",
|
|
13
|
+
"updatedAt": "2026-08-19T00:00:00Z"
|
|
14
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"cnId": "CN-060",
|
|
3
|
+
"path": "src/blueprint/remove.js#removeBlueprint",
|
|
4
|
+
"title": "Blueprint remove with referring-doc guard",
|
|
5
|
+
"description": "Refuses when any project-authored doc references a contribution id; otherwise unlinks contribution files and rewrites the manifest.",
|
|
6
|
+
"implementsAcIds": [
|
|
7
|
+
"AC-1001-3"
|
|
8
|
+
],
|
|
9
|
+
"dependencies": [],
|
|
10
|
+
"version": "0.1.0",
|
|
11
|
+
"status": "draft",
|
|
12
|
+
"createdAt": "2026-08-19T00:00:00Z",
|
|
13
|
+
"updatedAt": "2026-08-19T00:00:00Z"
|
|
14
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"cnId": "CN-061",
|
|
3
|
+
"path": "src/cli/blueprint.js#main",
|
|
4
|
+
"title": "rcf blueprint CLI dispatcher",
|
|
5
|
+
"description": "Wires the blueprint verb family into the unified rcf bin; dispatches add|list|remove.",
|
|
6
|
+
"implementsAcIds": [
|
|
7
|
+
"AC-1001-5"
|
|
8
|
+
],
|
|
9
|
+
"dependencies": [],
|
|
10
|
+
"version": "0.1.0",
|
|
11
|
+
"status": "draft",
|
|
12
|
+
"createdAt": "2026-08-19T00:00:00Z",
|
|
13
|
+
"updatedAt": "2026-08-19T00:00:00Z"
|
|
14
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"cnId": "CN-062",
|
|
3
|
+
"path": "src/blueprint/namespace.js#stampId",
|
|
4
|
+
"title": "Blueprint id namespacing (prefix + suffix families)",
|
|
5
|
+
"description": "Stamps a doc id with a blueprint slug according to family: prefix for REQ/US/PRD/BS/TAD/TS, suffix for ADR/TAC/FBS/CN.",
|
|
6
|
+
"implementsAcIds": [
|
|
7
|
+
"AC-1002-1"
|
|
8
|
+
],
|
|
9
|
+
"dependencies": [],
|
|
10
|
+
"version": "0.1.0",
|
|
11
|
+
"status": "draft",
|
|
12
|
+
"createdAt": "2026-08-19T00:00:00Z",
|
|
13
|
+
"updatedAt": "2026-08-19T00:00:00Z"
|
|
14
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"cnId": "CN-063",
|
|
3
|
+
"path": "src/blueprint/conflicts.js#detectGlobalAdrConflicts",
|
|
4
|
+
"title": "scope:global ADR conflict detection",
|
|
5
|
+
"description": "Detects two applied blueprints each contributing a scope:global ADR on the same topic; returns Conflict records.",
|
|
6
|
+
"implementsAcIds": [
|
|
7
|
+
"AC-1002-2",
|
|
8
|
+
"AC-1002-4"
|
|
9
|
+
],
|
|
10
|
+
"dependencies": [],
|
|
11
|
+
"version": "0.1.0",
|
|
12
|
+
"status": "draft",
|
|
13
|
+
"createdAt": "2026-08-19T00:00:00Z",
|
|
14
|
+
"updatedAt": "2026-08-19T00:00:00Z"
|
|
15
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"cnId": "CN-064",
|
|
3
|
+
"path": "src/blueprint/conflicts.js#renderConflictReport",
|
|
4
|
+
"title": "Conflict-presentation report writer",
|
|
5
|
+
"description": "Renders a Conflict[] list into an operator-facing block with per-side `blueprint <slug>: <title> — <decision>` headers (Phase 3.5 reshape; falls back to `<id> at <path>` when the tree did not carry the ADR body), a refs footer, and four honest resolution paths with actual conflicting blueprint slugs substituted. Symmetric enrichment: BOTH sides (incoming from the blueprint's ADR file on disk, existing from the walker's tree) are decorated with title + one-sentence decision before rendering. A parallel `conflictReportJson(conflicts)` returns the same shape as a JSON object with per-conflict `resolutions[]` triples for agent-driven composition.",
|
|
6
|
+
"implementsAcIds": [
|
|
7
|
+
"AC-1002-3",
|
|
8
|
+
"AC-1002-8"
|
|
9
|
+
],
|
|
10
|
+
"dependencies": [],
|
|
11
|
+
"version": "0.1.0",
|
|
12
|
+
"status": "draft",
|
|
13
|
+
"createdAt": "2026-08-19T00:00:00Z",
|
|
14
|
+
"updatedAt": "2026-08-19T00:00:00Z"
|
|
15
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"cnId": "CN-065",
|
|
3
|
+
"path": "src/blueprint/standards.js#registerStandardsPack",
|
|
4
|
+
"title": "Standards ingestion (reference-by-default + out-of-root copy)",
|
|
5
|
+
"description": "Detects whether the source lives inside the project root; references-in-place when yes, copies into rcf/standards/<slug>/ when no; writes the manifest.standards[] entry.",
|
|
6
|
+
"implementsAcIds": [
|
|
7
|
+
"AC-1003-1",
|
|
8
|
+
"AC-1003-2",
|
|
9
|
+
"AC-1003-3"
|
|
10
|
+
],
|
|
11
|
+
"dependencies": [],
|
|
12
|
+
"version": "0.1.0",
|
|
13
|
+
"status": "draft",
|
|
14
|
+
"createdAt": "2026-08-19T00:00:00Z",
|
|
15
|
+
"updatedAt": "2026-08-19T00:00:00Z"
|
|
16
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"cnId": "CN-066",
|
|
3
|
+
"path": "src/cli/standards.js#main",
|
|
4
|
+
"title": "rcf standards CLI dispatcher",
|
|
5
|
+
"description": "Wires the standards verb family into the unified rcf bin; dispatches add|list.",
|
|
6
|
+
"implementsAcIds": [
|
|
7
|
+
"AC-1003-4"
|
|
8
|
+
],
|
|
9
|
+
"dependencies": [],
|
|
10
|
+
"version": "0.1.0",
|
|
11
|
+
"status": "draft",
|
|
12
|
+
"createdAt": "2026-08-19T00:00:00Z",
|
|
13
|
+
"updatedAt": "2026-08-19T00:00:00Z"
|
|
14
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"cnId": "CN-067",
|
|
3
|
+
"path": "src/build/standards-selector.js#selectStandards",
|
|
4
|
+
"title": "Deterministic tag-scoring standards selector",
|
|
5
|
+
"description": "Reads FBS work text against manifest standards tags and returns the deterministic subset of relevant slugs.",
|
|
6
|
+
"implementsAcIds": [
|
|
7
|
+
"AC-1004-1",
|
|
8
|
+
"AC-1004-4"
|
|
9
|
+
],
|
|
10
|
+
"dependencies": [],
|
|
11
|
+
"version": "0.1.0",
|
|
12
|
+
"status": "draft",
|
|
13
|
+
"createdAt": "2026-08-19T00:00:00Z",
|
|
14
|
+
"updatedAt": "2026-08-19T00:00:00Z"
|
|
15
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"cnId": "CN-068",
|
|
3
|
+
"path": "src/build/bundle.js#assembleBundle",
|
|
4
|
+
"title": "Bundle assembler standardIds host (0.4.4)",
|
|
5
|
+
"description": "Bundle assembler branch that hosts operator-authored contextRequirements.standardIds override + agentic selection, and renders the standards payload alongside TACs/ADRs.",
|
|
6
|
+
"implementsAcIds": [
|
|
7
|
+
"AC-1004-2",
|
|
8
|
+
"AC-1004-3"
|
|
9
|
+
],
|
|
10
|
+
"dependencies": [],
|
|
11
|
+
"version": "0.1.0",
|
|
12
|
+
"status": "draft",
|
|
13
|
+
"createdAt": "2026-08-19T00:00:00Z",
|
|
14
|
+
"updatedAt": "2026-08-19T00:00:00Z"
|
|
15
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"cnId": "CN-069",
|
|
3
|
+
"path": "src/blueprint/supersede.js#supersedeBlueprintTopic",
|
|
4
|
+
"title": "Project-ADR supersession scaffolder (conflict-pair second side)",
|
|
5
|
+
"description": "Scaffolds a project-level ADR under rcf/adrs/adr-NNN-<kebab-topic>.json that supersedes the CONFLICT PAIR on the topic (one currently-applied blueprint's scope:global ADR + one incoming blueprint's scope:global ADR — Baz ruling, w-2026-08-19-008 round 3), and appends a matching manifest.resolutions[] record so the conflict detector honours the resolution when the operator re-runs `rcf blueprint add <incoming source>`. The verb accepts an optional `--incoming <source>` argument (required when applied count on the topic is < 2; informational when >= 2): the verb loads the incoming blueprint from disk, finds its scope:global ADR on the topic, stamps the id into the incoming blueprint's namespace, and uses that {slug, adrId} as the second side of supersedes[]. This lets option 3 as printed by the reshaped conflict message execute VERBATIM from the refused-add state — no --resolve prep, no menu-copy weakening. Topic is a LOOKUP KEY (see ADR-010): any string that exact-matches an applied ADR's declared topic is accepted (schema minLength:1, whitespace-only refused at the writer edge; camelCase, snake_case and kebab-case all pass). The scaffolded ADR id derives its slug tail by kebab-ifying the topic (`authModel` -> `ADR-NNN-auth-model`) so the ADR grammar's `[a-z0-9](-[a-z0-9]+)*` tail is satisfied. Every rcfError message returned by this module is prefix-free (no `blueprint supersede: ` in the message body); the CLI edge prepends the single `[error] blueprint supersede: ` line. Refuses when the manifest is missing prd or tad, when applied+incoming count on the topic is < 2, and when a file already exists at the scaffolded ADR path.",
|
|
6
|
+
"implementsAcIds": [
|
|
7
|
+
"AC-1002-5",
|
|
8
|
+
"AC-1002-9",
|
|
9
|
+
"AC-1002-10"
|
|
10
|
+
],
|
|
11
|
+
"dependencies": [],
|
|
12
|
+
"version": "0.1.0",
|
|
13
|
+
"status": "draft",
|
|
14
|
+
"createdAt": "2026-08-19T14:35:00.000Z",
|
|
15
|
+
"updatedAt": "2026-08-19T14:35:00.000Z"
|
|
16
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"fbsId": "FBS-016",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"bsId": "BS-001",
|
|
5
|
+
"buildOrder": 16,
|
|
6
|
+
"executionStatus": "notStarted",
|
|
7
|
+
"title": "Blueprint verb family (add, list, remove, upgrade) with manifest.blueprints[] writes",
|
|
8
|
+
"summary": "Introduce the `rcf blueprint <verb>` verb family and its manifest-writing path. Adds `src/blueprint/` module (loader, applier, contribution-writer) and `src/cli/blueprint.js` (parseArgs, dispatch, HELP block). Adds `blueprint` to the top-level SUBCOMMANDS map on `bin/rcf.js` and to the `TOP_LEVEL` block on `src/cli/help.js` so `rcf --help` advertises it. Every apply writes an entry to `manifest.blueprints[]` per the 0.4.4 schema (slug, version, appliedAt, source, namespace, contributions[]). `add` is idempotent on a clean re-apply; `remove` refuses when any project-authored doc references a contribution id.",
|
|
9
|
+
"approach": "One dispatcher, one loader, one applier, one writer. bin/rcf.js gains `blueprint: blueprintMain` on SUBCOMMANDS; src/cli/blueprint.js parses `add|list|remove|upgrade` and dispatches to src/blueprint/ handlers. Blueprint loading is a small package-metadata reader (slug, version, ADR contributions with optional scope, doc contributions manifest); Phase 1 keeps the resolver `file://` and `link:` only, with the registry/git-ref shape captured in the source string so the schema forward-compat holds. Contribution writing goes through the existing store writer paths so a blueprint apply produces the same doc files a hand-created doc would. Removal is a manifest patch + contribution-path unlink; the referring-doc check reuses the existing tree walker to enumerate every string field for id occurrences.",
|
|
10
|
+
"deliverables": [
|
|
11
|
+
"src/cli/blueprint.js: parseArgs + HELP + main() dispatching add/list/remove/upgrade",
|
|
12
|
+
"src/blueprint/index.js: barrel re-exporting apply, list, remove, upgrade, loadBlueprint, detectGlobalAdrConflicts",
|
|
13
|
+
"src/blueprint/apply.js: apply(tree, blueprint, opts) — idempotency + conflict detection + contribution writes + manifest update",
|
|
14
|
+
"src/blueprint/loader.js: loadBlueprint(source) — reads a blueprint's metadata (slug, version, ADR contributions with scope, doc contributions)",
|
|
15
|
+
"src/blueprint/remove.js: remove(tree, slug, opts) — referring-doc scan + manifest patch + file unlinks",
|
|
16
|
+
"src/blueprint/list.js: list(tree) — reads manifest.blueprints[] and returns rows",
|
|
17
|
+
"bin/rcf.js: `blueprint: blueprintMain` on SUBCOMMANDS",
|
|
18
|
+
"src/cli/help.js: `blueprint <verb>` on the TOP_LEVEL block, `help blueprint` prints the blueprint HELP",
|
|
19
|
+
"test/blueprint/apply.test.js, list.test.js, remove.test.js, cli.test.js — behaviour tests keyed to AC-1001-1..5"
|
|
20
|
+
],
|
|
21
|
+
"acIds": [
|
|
22
|
+
"AC-1001-1",
|
|
23
|
+
"AC-1001-2",
|
|
24
|
+
"AC-1001-3",
|
|
25
|
+
"AC-1001-4",
|
|
26
|
+
"AC-1001-5"
|
|
27
|
+
],
|
|
28
|
+
"contextRequirements": {
|
|
29
|
+
"tacIds": [],
|
|
30
|
+
"adrIds": []
|
|
31
|
+
},
|
|
32
|
+
"dependsOnFbsIds": [],
|
|
33
|
+
"domain": "cli",
|
|
34
|
+
"estimatedSize": "medium",
|
|
35
|
+
"riskLevel": "low",
|
|
36
|
+
"notes": "Landing car of Phase 1 blueprint mechanism (w-2026-08-18-016, design-brief.md v2 §Composition model). Written against @stravica-ai/rcf-schemas 0.4.4 (blueprints[] host schema); dev pin to feature/blueprint-additive-0.4.4 on the schemas repo carries until the Baz 2FA publish flips the pin to registry-resolved 0.4.4.",
|
|
37
|
+
"createdAt": "2026-08-18T22:56:02.353Z",
|
|
38
|
+
"updatedAt": "2026-08-18T22:56:02.353Z"
|
|
39
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"fbsId": "FBS-017",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"bsId": "BS-001",
|
|
5
|
+
"buildOrder": 17,
|
|
6
|
+
"executionStatus": "notStarted",
|
|
7
|
+
"title": "Namespaced blueprint ids and scope:global ADR conflict surfacing",
|
|
8
|
+
"summary": "Blueprint-contributed docs are namespaced by the blueprint's slug: REQ/US/PRD/BS/TAD/TS via the 0.4.4 slug PREFIX (e.g. `spa-REQ-001`), and ADR/TAC/FBS/CN via the 0.4.3 kebab SUFFIX (e.g. `ADR-005-rest-versioning`). `rcf blueprint add` runs a conflict-detection pass BEFORE writing anything: two blueprints both contributing an ADR tagged `scope: global` on the same topic exit non-zero with both sides printed and four honest resolution paths named (adopt-incoming, keep-existing, supersede via project ADR, declare-on-add via `--resolve`). Non-global TACs, ADRs, REQs, USs and FBSes namespace cleanly and cannot topic-conflict; cross-blueprint id claims (an incoming id already recorded on another applied blueprint) are refused via the authoritative manifest record, not string grammar.",
|
|
9
|
+
"approach": "Namespacing is enforced at the loader: contribution ids are stamped with the blueprint slug at load time; a contribution whose declared id already carries a namespace is trusted verbatim (author declaration is the truth for what that blueprint owns; the earlier grammar-veto of legitimate slug-tail ids like `ADR-201-spa-theme` under blueprint `spa` was retired in w-2026-08-19-005). Ownership of a written contribution is answered by the manifest's `appliedBlueprintRecord.contributions[]` list — the authoritative record — not by re-parsing the id string. Conflict detection reads the applied `blueprints[]` and the applying blueprint's contributions, and scores collisions along two axes: `scope: global` ADR topic collision (two applied ADRs both tagged `scope: global` with a matching `topic` field), and cross-blueprint ownership (an incoming id whose manifest record is on a DIFFERENT applied blueprint's contribution list — the class the record consultation catches once grammar stopped being a trust surface). Presentation: per-conflict block leads with both ADR titles and their one-sentence decisions, ids and paths as a footer, and four honest resolution paths with actual blueprint slugs filled in — no placeholders. A `--json` output shape is available for agent-driven composition. Phase 3.5 (w-2026-08-19-008) added the `supersede` and `diff` verbs plus the `--resolve` add-time flag, backed by `manifest.resolutions[]` on the 0.4.5 schema; both blueprint ADRs may now co-reside on disk as superseded history alongside a project-level ADR that supersedes them.",
|
|
10
|
+
"deliverables": [
|
|
11
|
+
"src/blueprint/namespace.js: pure functions that stamp/verify contribution namespacing for all doc kinds",
|
|
12
|
+
"src/blueprint/conflicts.js: detectGlobalAdrConflicts(appliedBlueprints, incomingContributions) returning zero-or-more Conflict records",
|
|
13
|
+
"Updates to src/blueprint/apply.js: conflict pass runs BEFORE any file write; non-empty conflict list short-circuits with a printed report + non-zero exit",
|
|
14
|
+
"test/blueprint/namespace.test.js: prefix/suffix stamping tests keyed to AC-1002-1",
|
|
15
|
+
"test/blueprint/conflicts.test.js: global-ADR conflict cases keyed to AC-1002-2 / AC-1002-3, non-conflict cases for AC-1002-4"
|
|
16
|
+
],
|
|
17
|
+
"acIds": [
|
|
18
|
+
"AC-1002-1",
|
|
19
|
+
"AC-1002-2",
|
|
20
|
+
"AC-1002-3",
|
|
21
|
+
"AC-1002-4",
|
|
22
|
+
"AC-1002-5",
|
|
23
|
+
"AC-1002-6",
|
|
24
|
+
"AC-1002-7",
|
|
25
|
+
"AC-1002-8",
|
|
26
|
+
"AC-1002-9",
|
|
27
|
+
"AC-1002-10"
|
|
28
|
+
],
|
|
29
|
+
"contextRequirements": {
|
|
30
|
+
"tacIds": [],
|
|
31
|
+
"adrIds": []
|
|
32
|
+
},
|
|
33
|
+
"dependsOnFbsIds": ["FBS-016"],
|
|
34
|
+
"domain": "cli",
|
|
35
|
+
"estimatedSize": "medium",
|
|
36
|
+
"riskLevel": "medium",
|
|
37
|
+
"notes": "Prototype-unknown #1 (design-brief.md v2 §Depth for v1) — conflict-presentation ergonomics settled here as first pass; Phase 3 (REST blueprint) exposed the ergonomic friction against the real SPA+REST conflict; Phase 3.5 (w-2026-08-19-008) reshaped the message and added the supersede / diff / --resolve verbs plus the `manifest.resolutions[]` seam (rcf-schemas 0.4.5). Ownership-via-manifest-record rewrite landed separately in w-2026-08-19-005.",
|
|
38
|
+
"createdAt": "2026-08-18T22:56:02.353Z",
|
|
39
|
+
"updatedAt": "2026-08-18T22:56:02.353Z"
|
|
40
|
+
}
|