rcf-lite 0.8.0 → 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 +41 -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 +2 -2
- 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/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 +45 -0
- package/src/cli/help.js +8 -0
- package/src/cli/init.js +20 -5
- package/src/cli/standards.js +127 -0
- package/src/core/store/ids.js +168 -18
- package/src/core/store/loader.js +27 -16
- package/src/core/store/walker.js +27 -15
- package/src/deployment/index.js +13 -0
- package/src/deployment/placeholder-detector.js +113 -0
- package/src/query/formatters/table.js +7 -10
- package/src/query/trace.js +45 -4
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,47 @@ 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
|
+
|
|
7
48
|
## [0.8.0] - 2026-08-12 (on `slug-train/0.8.0`, PR pending)
|
|
8
49
|
|
|
9
50
|
### Added (Car 4, verify updates per requirements doc)
|
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",
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
"#admissibility": "./src/admissibility/index.js"
|
|
59
59
|
},
|
|
60
60
|
"dependencies": {
|
|
61
|
-
"@stravica-ai/rcf-schemas": "0.4.
|
|
61
|
+
"@stravica-ai/rcf-schemas": "0.4.5",
|
|
62
62
|
"ajv": "^8.20.0",
|
|
63
63
|
"ajv-formats": "^3.0.1"
|
|
64
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
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"fbsId": "FBS-018",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"bsId": "BS-001",
|
|
5
|
+
"buildOrder": 18,
|
|
6
|
+
"executionStatus": "notStarted",
|
|
7
|
+
"title": "Standards ingestion: rcf standards add + reference-by-default",
|
|
8
|
+
"summary": "Introduce a `rcf standards <verb>` verb family (`add`, `list`) that registers standards packs on the project manifest. Reference-by-default when the source lives inside the project root; copy into `rcf/standards/<slug>/` only when the source lives outside. Manifest registration is authoritative; every add writes a `manifest.standards[]` entry per the 0.4.4 `standardsPackRecord` schema.",
|
|
9
|
+
"approach": "One dispatcher, one applier. src/cli/standards.js parses `add|list`; src/blueprint/standards.js resolves whether the source is inside or outside the project root (via node:path.relative + startsWith), copies when needed, and writes the manifest entry. Copy path is fs.cp recursive with a per-run overwrite guard (idempotent re-adds refuse to re-copy unless `--refresh` is passed; Phase 1 keeps to add-only + idempotent read, `refresh` verb deferred to Phase 3).",
|
|
10
|
+
"deliverables": [
|
|
11
|
+
"src/cli/standards.js: parseArgs + HELP + main() for add/list",
|
|
12
|
+
"src/blueprint/standards.js: registerStandardsPack(root, opts) — in-root vs out-of-root detection + optional copy + manifest.standards[] write",
|
|
13
|
+
"bin/rcf.js: `standards: standardsMain` on SUBCOMMANDS",
|
|
14
|
+
"src/cli/help.js: `standards <verb>` on the TOP_LEVEL block",
|
|
15
|
+
"test/blueprint/standards.test.js: in-root reference / out-of-root copy / idempotency cases keyed to AC-1003-1..4"
|
|
16
|
+
],
|
|
17
|
+
"acIds": [
|
|
18
|
+
"AC-1003-1",
|
|
19
|
+
"AC-1003-2",
|
|
20
|
+
"AC-1003-3",
|
|
21
|
+
"AC-1003-4"
|
|
22
|
+
],
|
|
23
|
+
"contextRequirements": {
|
|
24
|
+
"tacIds": [],
|
|
25
|
+
"adrIds": []
|
|
26
|
+
},
|
|
27
|
+
"dependsOnFbsIds": [],
|
|
28
|
+
"domain": "cli",
|
|
29
|
+
"estimatedSize": "small",
|
|
30
|
+
"riskLevel": "low",
|
|
31
|
+
"notes": "Reference-by-default is ratified decision 2 (design-brief.md v2). Copy path targets rcf/standards/<slug>/ (ratified decision 3).",
|
|
32
|
+
"createdAt": "2026-08-18T22:56:02.353Z",
|
|
33
|
+
"updatedAt": "2026-08-18T22:56:02.353Z"
|
|
34
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"fbsId": "FBS-019",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"bsId": "BS-001",
|
|
5
|
+
"buildOrder": 19,
|
|
6
|
+
"executionStatus": "notStarted",
|
|
7
|
+
"title": "Selective retrieval at bundle assembly (contextRequirements.standardIds)",
|
|
8
|
+
"summary": "Extend `src/build/bundle.js#assembleBundle` so its `context` section reads `contextRequirements.standardIds`. When the FBS carries an operator-authored `standardIds` array, that array is honoured verbatim. Otherwise a deterministic tag-scoring selector reads the FBS work text (title + summary + approach + notes + AC descriptions) against `manifest.standards[]` (tags + slug + summary) and returns the subset of slugs whose tags occur in the work text. The bundle's context.standardIds carries the selection; the standards' summaries render into the standards payload alongside TACs and ADRs.",
|
|
9
|
+
"approach": "The selector is a pure function in src/build/standards-selector.js — no wall clock, no random source, no network. Scoring is deterministic tag-hit counting with lowercase-normalised substring match; ties break by manifest order (standards[] is authored). The bundle assembler prefers operator-authored `contextRequirements.standardIds` when present (design principle 5 override path) and calls the selector otherwise. Empty selection is legitimate and never blocks. Phase 1 keeps the selector local and heuristic; the design brief allows a small model call, but adding an LLM dependency to a pure projection is out of scope for the mechanism landing — the heuristic satisfies the ACs and the seam is where a smarter selector plugs in.",
|
|
10
|
+
"deliverables": [
|
|
11
|
+
"src/build/standards-selector.js: selectStandards(fbs, standards) — deterministic tag-hit scoring returning the ordered subset of slugs",
|
|
12
|
+
"src/build/bundle.js: contextRequirements.standardIds hosts operator override or selector output; standards payload rendered into context alongside tacs/adrs",
|
|
13
|
+
"test/build/standards-selector.test.js: deterministic-selection cases keyed to AC-1004-1, AC-1004-3, AC-1004-4",
|
|
14
|
+
"test/build/bundle-standards.test.js: bundle-shape cases (default + override) keyed to AC-1004-1, AC-1004-2"
|
|
15
|
+
],
|
|
16
|
+
"acIds": [
|
|
17
|
+
"AC-1004-1",
|
|
18
|
+
"AC-1004-2",
|
|
19
|
+
"AC-1004-3",
|
|
20
|
+
"AC-1004-4"
|
|
21
|
+
],
|
|
22
|
+
"contextRequirements": {
|
|
23
|
+
"tacIds": [],
|
|
24
|
+
"adrIds": []
|
|
25
|
+
},
|
|
26
|
+
"dependsOnFbsIds": ["FBS-018"],
|
|
27
|
+
"domain": "build",
|
|
28
|
+
"estimatedSize": "small",
|
|
29
|
+
"riskLevel": "low",
|
|
30
|
+
"notes": "Ratified decision 4 (agentic at bundle-assembly time, operator override supported). Heuristic-tag selector satisfies the deterministic ACs; a smarter selector plugs into the same seam without touching the bundle assembler.",
|
|
31
|
+
"createdAt": "2026-08-18T22:56:02.353Z",
|
|
32
|
+
"updatedAt": "2026-08-18T22:56:02.353Z"
|
|
33
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"createdAt": "2026-08-18T22:54:27.031Z",
|
|
3
|
+
"updatedAt": "2026-08-18T22:57:45.660Z",
|
|
4
|
+
"description": "The framework provides a Blueprint mechanism the operator uses to compose blueprint packages (specifications + assets, not code) onto a project tree at any point in its life. Composition is many blueprints per project. Blueprint-contributed docs are namespaced by the blueprint's slug so multiple blueprints cannot collide on ids. Standards packs register at rcf init (or later via rcf standards add), reference-by-default, copied to rcf/standards/<slug>/ only when the source lives outside the project root. Manifest registration is authoritative. Selective retrieval populates fbs.contextRequirements.standardIds at bundle-assembly time by analysing the FBS work text against the standards tag vocabulary; operator override is supported by authoring the array on the FBS. scope:global ADR contributions surface as blocking conflicts at rcf blueprint add time.",
|
|
5
|
+
"reqId": "REQ-010",
|
|
6
|
+
"prdId": "PRD-001",
|
|
7
|
+
"title": "Blueprint library mechanism (composition, standards, selective retrieval)",
|
|
8
|
+
"category": "functional",
|
|
9
|
+
"domain": "cli",
|
|
10
|
+
"priority": "must",
|
|
11
|
+
"version": "0.1.0",
|
|
12
|
+
"status": "draft",
|
|
13
|
+
"shapeClassification": {
|
|
14
|
+
"shapes": [
|
|
15
|
+
"none"
|
|
16
|
+
],
|
|
17
|
+
"reason": "keyword-scan",
|
|
18
|
+
"classifiedAt": "2026-08-18T22:54:27.048Z"
|
|
19
|
+
}
|
|
20
|
+
}
|