rcf-lite 0.0.1 → 0.8.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 +344 -0
- package/LICENSE +202 -0
- package/README.md +92 -4
- package/bin/rcf-verify.js +122 -0
- package/bin/rcf.js +174 -0
- package/bin/view-supervisor-child.mjs +14 -0
- package/fixtures/canary-manifest.json +103 -0
- package/guidance/README.md +25 -0
- package/guidance/build-cycle-playbook.md +492 -0
- package/guidance/build-cycle.md +40 -0
- package/guidance/document-model.md +45 -0
- package/guidance/elicitation-playbook.md +442 -0
- package/guidance/harness-template.md +246 -0
- package/guidance/managed/README.md +63 -0
- package/guidance/managed/agent-instructions-block.hash +1 -0
- package/guidance/managed/agent-instructions-block.md +220 -0
- package/guidance/managed/legacy-fragment-hashes.json +22 -0
- package/guidance/manifest.json +21 -0
- package/guidance/overview.md +48 -0
- package/guidance/persona-programme.md +44 -0
- package/package.json +71 -8
- package/rcf/adrs/adr-001.json +25 -0
- package/rcf/adrs/adr-002.json +25 -0
- package/rcf/adrs/adr-003.json +25 -0
- package/rcf/adrs/adr-004.json +20 -0
- package/rcf/adrs/adr-005.json +20 -0
- package/rcf/adrs/adr-006.json +25 -0
- package/rcf/adrs/adr-007.json +25 -0
- package/rcf/adrs/adr-008.json +25 -0
- package/rcf/adrs/adr-009.json +25 -0
- package/rcf/build-sequence.json +11 -0
- package/rcf/code-nodes/cn-001.json +14 -0
- package/rcf/code-nodes/cn-002.json +14 -0
- package/rcf/code-nodes/cn-003.json +15 -0
- package/rcf/code-nodes/cn-004.json +17 -0
- package/rcf/code-nodes/cn-005.json +19 -0
- package/rcf/code-nodes/cn-006.json +17 -0
- package/rcf/code-nodes/cn-007.json +16 -0
- package/rcf/code-nodes/cn-008.json +19 -0
- package/rcf/code-nodes/cn-009.json +16 -0
- package/rcf/code-nodes/cn-010.json +18 -0
- package/rcf/code-nodes/cn-011.json +18 -0
- package/rcf/code-nodes/cn-012.json +18 -0
- package/rcf/code-nodes/cn-013.json +19 -0
- package/rcf/code-nodes/cn-014.json +16 -0
- package/rcf/code-nodes/cn-015.json +16 -0
- package/rcf/code-nodes/cn-016.json +16 -0
- package/rcf/code-nodes/cn-017.json +16 -0
- package/rcf/code-nodes/cn-018.json +15 -0
- package/rcf/code-nodes/cn-019.json +16 -0
- package/rcf/code-nodes/cn-020.json +16 -0
- package/rcf/code-nodes/cn-021.json +16 -0
- package/rcf/code-nodes/cn-022.json +16 -0
- package/rcf/code-nodes/cn-023.json +16 -0
- package/rcf/code-nodes/cn-024.json +16 -0
- package/rcf/code-nodes/cn-025.json +16 -0
- package/rcf/code-nodes/cn-026.json +16 -0
- package/rcf/code-nodes/cn-027.json +16 -0
- package/rcf/code-nodes/cn-028.json +16 -0
- package/rcf/code-nodes/cn-029.json +19 -0
- package/rcf/code-nodes/cn-030.json +14 -0
- package/rcf/code-nodes/cn-031.json +14 -0
- package/rcf/code-nodes/cn-032.json +14 -0
- package/rcf/code-nodes/cn-033.json +14 -0
- package/rcf/code-nodes/cn-034.json +14 -0
- package/rcf/code-nodes/cn-035.json +14 -0
- package/rcf/code-nodes/cn-036.json +14 -0
- package/rcf/code-nodes/cn-037.json +14 -0
- package/rcf/code-nodes/cn-038.json +14 -0
- package/rcf/code-nodes/cn-039.json +14 -0
- package/rcf/code-nodes/cn-040.json +14 -0
- package/rcf/code-nodes/cn-041.json +14 -0
- package/rcf/code-nodes/cn-042.json +14 -0
- package/rcf/code-nodes/cn-043.json +14 -0
- package/rcf/code-nodes/cn-044.json +14 -0
- package/rcf/code-nodes/cn-045.json +14 -0
- package/rcf/code-nodes/cn-046.json +14 -0
- package/rcf/code-nodes/cn-047.json +14 -0
- package/rcf/code-nodes/cn-048.json +14 -0
- package/rcf/code-nodes/cn-049.json +14 -0
- package/rcf/code-nodes/cn-050.json +14 -0
- package/rcf/code-nodes/cn-051.json +14 -0
- package/rcf/code-nodes/cn-052.json +14 -0
- package/rcf/code-nodes/cn-053.json +14 -0
- package/rcf/code-nodes/cn-054.json +14 -0
- package/rcf/code-nodes/cn-055.json +14 -0
- package/rcf/code-nodes/cn-056.json +14 -0
- package/rcf/code-nodes/cn-057.json +14 -0
- package/rcf/fbs/fbs-001.json +49 -0
- package/rcf/fbs/fbs-002.json +42 -0
- package/rcf/fbs/fbs-003.json +37 -0
- package/rcf/fbs/fbs-004.json +39 -0
- package/rcf/fbs/fbs-005.json +38 -0
- package/rcf/fbs/fbs-006.json +48 -0
- package/rcf/fbs/fbs-007.json +39 -0
- package/rcf/fbs/fbs-008.json +40 -0
- package/rcf/fbs/fbs-009.json +36 -0
- package/rcf/fbs/fbs-010.json +41 -0
- package/rcf/fbs/fbs-011.json +36 -0
- package/rcf/fbs/fbs-012.json +46 -0
- package/rcf/fbs/fbs-013.json +42 -0
- package/rcf/fbs/fbs-014.json +49 -0
- package/rcf/fbs/fbs-015.json +32 -0
- package/rcf/manifest.json +17 -0
- package/rcf/prd.json +47 -0
- package/rcf/requirements/req-001.json +19 -0
- package/rcf/requirements/req-002.json +19 -0
- package/rcf/requirements/req-003.json +19 -0
- package/rcf/requirements/req-004.json +19 -0
- package/rcf/requirements/req-005.json +19 -0
- package/rcf/requirements/req-006.json +19 -0
- package/rcf/requirements/req-007.json +19 -0
- package/rcf/requirements/req-008.json +19 -0
- package/rcf/requirements/req-009.json +19 -0
- package/rcf/tacs/tac-001.json +45 -0
- package/rcf/tacs/tac-002.json +109 -0
- package/rcf/tacs/tac-003.json +40 -0
- package/rcf/tacs/tac-004.json +51 -0
- package/rcf/tacs/tac-005.json +52 -0
- package/rcf/tacs/tac-006.json +104 -0
- package/rcf/tacs/tac-007.json +38 -0
- package/rcf/tacs/tac-008.json +51 -0
- package/rcf/tad.json +51 -0
- package/rcf/test-suites/PENDING.md +23 -0
- package/rcf/test-suites/ts-001.json +38 -0
- package/rcf/test-suites/ts-002.json +38 -0
- package/rcf/test-suites/ts-003.json +43 -0
- package/rcf/test-suites/ts-004.json +44 -0
- package/rcf/test-suites/ts-005.json +30 -0
- package/rcf/test-suites/ts-006.json +36 -0
- package/rcf/test-suites/ts-007.json +43 -0
- package/rcf/test-suites/ts-008.json +37 -0
- package/rcf/test-suites/ts-009.json +38 -0
- package/rcf/test-suites/ts-010.json +38 -0
- package/rcf/test-suites/ts-011.json +44 -0
- package/rcf/test-suites/ts-012.json +36 -0
- package/rcf/test-suites/ts-013.json +38 -0
- package/rcf/test-suites/ts-014.json +38 -0
- package/rcf/test-suites/ts-015.json +38 -0
- package/rcf/test-suites/ts-016.json +37 -0
- package/rcf/test-suites/ts-017.json +38 -0
- package/rcf/test-suites/ts-018.json +38 -0
- package/rcf/test-suites/ts-019.json +37 -0
- package/rcf/test-suites/ts-020.json +46 -0
- package/rcf/test-suites/ts-021.json +46 -0
- package/rcf/test-suites/ts-022.json +46 -0
- package/rcf/test-suites/ts-023.json +46 -0
- package/rcf/test-suites/ts-024.json +46 -0
- package/rcf/test-suites/ts-025.json +52 -0
- package/rcf/user-stories/us-101.json +40 -0
- package/rcf/user-stories/us-102.json +40 -0
- package/rcf/user-stories/us-201.json +40 -0
- package/rcf/user-stories/us-202.json +40 -0
- package/rcf/user-stories/us-203.json +32 -0
- package/rcf/user-stories/us-301.json +40 -0
- package/rcf/user-stories/us-302.json +40 -0
- package/rcf/user-stories/us-303.json +40 -0
- package/rcf/user-stories/us-304.json +40 -0
- package/rcf/user-stories/us-401.json +40 -0
- package/rcf/user-stories/us-402.json +40 -0
- package/rcf/user-stories/us-403.json +40 -0
- package/rcf/user-stories/us-501.json +40 -0
- package/rcf/user-stories/us-502.json +40 -0
- package/rcf/user-stories/us-503.json +40 -0
- package/rcf/user-stories/us-601.json +40 -0
- package/rcf/user-stories/us-602.json +40 -0
- package/rcf/user-stories/us-701.json +40 -0
- package/rcf/user-stories/us-702.json +40 -0
- package/rcf/user-stories/us-801.json +49 -0
- package/rcf/user-stories/us-802.json +49 -0
- package/rcf/user-stories/us-803.json +49 -0
- package/rcf/user-stories/us-804.json +49 -0
- package/rcf/user-stories/us-805.json +49 -0
- package/rcf/user-stories/us-901.json +40 -0
- package/src/.gitkeep +0 -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/browser-verify/auth-smoke.js +109 -0
- package/src/browser-verify/index.js +29 -0
- package/src/browser-verify/invariants.js +336 -0
- package/src/browser-verify/manifest-writer.js +189 -0
- package/src/browser-verify/runner.js +171 -0
- package/src/build/bundle.js +198 -0
- package/src/build/formatters/json.js +18 -0
- package/src/build/formatters/markdown.js +406 -0
- package/src/build/index.js +14 -0
- package/src/build/mark.js +177 -0
- package/src/build/queue.js +285 -0
- package/src/cli/browser-verify.js +231 -0
- package/src/cli/build.js +584 -0
- package/src/cli/coverage.js +219 -0
- package/src/cli/create.js +358 -0
- package/src/cli/delete.js +127 -0
- package/src/cli/design.js +353 -0
- package/src/cli/doctor.js +548 -0
- package/src/cli/fbs.js +171 -0
- package/src/cli/finalise.js +377 -0
- package/src/cli/guidance.js +206 -0
- package/src/cli/help.js +156 -0
- package/src/cli/impact.js +119 -0
- package/src/cli/init.js +282 -0
- package/src/cli/intake.js +153 -0
- package/src/cli/link.js +128 -0
- package/src/cli/mcp.js +160 -0
- package/src/cli/preflight.js +220 -0
- package/src/cli/read.js +168 -0
- package/src/cli/req-baseline.js +269 -0
- package/src/cli/req-classify.js +135 -0
- package/src/cli/review.js +295 -0
- package/src/cli/test-suite.js +221 -0
- package/src/cli/trace.js +172 -0
- package/src/cli/ui-baseline.js +292 -0
- package/src/cli/ui-classify.js +108 -0
- package/src/cli/update.js +197 -0
- package/src/cli/validate.js +168 -0
- package/src/cli/view.js +452 -0
- package/src/core/baseline-catalog/data/auth.json +42 -0
- package/src/core/baseline-catalog/data/http-api.json +42 -0
- package/src/core/baseline-catalog/data/notifications.json +33 -0
- package/src/core/baseline-catalog/data/persistence.json +33 -0
- package/src/core/baseline-catalog/data/web-ui.json +60 -0
- package/src/core/baseline-catalog/index.js +121 -0
- package/src/core/errors/index.js +167 -0
- package/src/core/fixtures/register-canary/canary-prompt-01.json +18 -0
- package/src/core/fixtures/register-canary/canary-prompt-02.json +21 -0
- package/src/core/fixtures/register-canary/canary-prompt-03.json +17 -0
- package/src/core/isolation/index.js +60 -0
- package/src/core/mcp/framing.js +103 -0
- package/src/core/mcp/index.js +8 -0
- package/src/core/mcp/server.js +228 -0
- package/src/core/patterns/register-canary.js +209 -0
- package/src/core/patterns/req-shapes.js +158 -0
- package/src/core/patterns/services.js +358 -0
- package/src/core/patterns/ui-shapes.js +166 -0
- package/src/core/store/cn-resolve.js +134 -0
- package/src/core/store/derive-deps.js +93 -0
- package/src/core/store/ids.js +78 -0
- package/src/core/store/index.js +20 -0
- package/src/core/store/init.js +255 -0
- package/src/core/store/loader.js +214 -0
- package/src/core/store/tp-resolve.js +176 -0
- package/src/core/store/validator.js +191 -0
- package/src/core/store/walker.js +944 -0
- package/src/core/store/writer.js +1879 -0
- package/src/design/index.js +11 -0
- package/src/design/writer.js +271 -0
- package/src/finalise/detect.js +151 -0
- package/src/finalise/index.js +31 -0
- package/src/finalise/ingest.js +160 -0
- package/src/finalise/install.js +119 -0
- package/src/finalise/ship-without-verified.js +131 -0
- package/src/finalise/spawn.js +84 -0
- package/src/intake/fidelity.js +105 -0
- package/src/intake/index.js +6 -0
- package/src/intake/manifest-writer.js +100 -0
- package/src/intake/orchestrator.js +138 -0
- package/src/intake/validate.js +80 -0
- package/src/mcp/map-errors.js +131 -0
- package/src/mcp/prompts.js +49 -0
- package/src/mcp/resources.js +244 -0
- package/src/mcp/tools.js +1212 -0
- package/src/preflight/design-shapes.js +185 -0
- package/src/preflight/index.js +90 -0
- package/src/preflight/manifest-writer.js +264 -0
- package/src/preflight/scanner.js +206 -0
- package/src/preflight/secrets.js +134 -0
- package/src/preflight/session.js +246 -0
- package/src/query/attestation.js +285 -0
- package/src/query/coverage.js +308 -0
- package/src/query/formatters/json.js +21 -0
- package/src/query/formatters/mermaid.js +209 -0
- package/src/query/formatters/table.js +203 -0
- package/src/query/impact.js +173 -0
- package/src/query/index.js +13 -0
- package/src/query/refuse-on-admissibility.js +73 -0
- package/src/query/trace.js +345 -0
- package/src/register-canary/fixture-loader.js +87 -0
- package/src/register-canary/index.js +10 -0
- package/src/register-canary/record-writer.js +132 -0
- package/src/register-canary/runner.js +156 -0
- package/src/req-baseline/gate.js +86 -0
- package/src/req-baseline/index.js +27 -0
- package/src/req-baseline/open-candidates.js +143 -0
- package/src/req-baseline/opt-out.js +195 -0
- package/src/req-baseline/sweep.js +230 -0
- package/src/req-detection/classifier.js +181 -0
- package/src/req-detection/index.js +9 -0
- package/src/req-detection/persist.js +55 -0
- package/src/review/index.js +325 -0
- package/src/review/mutation.js +117 -0
- package/src/review/ui-baseline-drift.js +138 -0
- package/src/ruleset/index.js +140 -0
- package/src/ruleset/ruleset.json +146 -0
- package/src/server/index.js +178 -0
- package/src/server/routes.js +110 -0
- package/src/server/sse.js +118 -0
- package/src/setup/agent-setup.js +362 -0
- package/src/setup/identity-seed.js +104 -0
- package/src/setup/knowledge-seed.js +123 -0
- package/src/setup/managed-block.js +193 -0
- package/src/setup/managed-gitignore.js +166 -0
- package/src/setup/managed-markers.js +49 -0
- package/src/ui-baseline/defaults.js +119 -0
- package/src/ui-baseline/index.js +25 -0
- package/src/ui-baseline/manifest-writer.js +282 -0
- package/src/ui-baseline/session.js +178 -0
- package/src/ui-detection/classifier.js +192 -0
- package/src/verify/chain/index.js +221 -0
- package/src/verify/cli/cleanup.js +61 -0
- package/src/verify/cli/help.js +56 -0
- package/src/verify/cli/mcp.js +98 -0
- package/src/verify/cli/provision.js +71 -0
- package/src/verify/cli/report.js +71 -0
- package/src/verify/cli/run.js +155 -0
- package/src/verify/engine/brief.js +87 -0
- package/src/verify/engine/index.js +177 -0
- package/src/verify/engine/launcher.js +307 -0
- package/src/verify/mcp/tools.js +107 -0
- package/src/verify/profile/index.js +146 -0
- package/src/verify/provision/index.js +256 -0
- package/src/verify/report/index.js +139 -0
- package/src/verify/report/renderer.js +118 -0
- package/src/verify/verdict/index.js +313 -0
- package/src/view/doc-renderers/adr.js +44 -0
- package/src/view/doc-renderers/build-sequence.js +40 -0
- package/src/view/doc-renderers/fbs.js +128 -0
- package/src/view/doc-renderers/helpers.js +159 -0
- package/src/view/doc-renderers/index.js +12 -0
- package/src/view/doc-renderers/prd.js +45 -0
- package/src/view/doc-renderers/req.js +43 -0
- package/src/view/doc-renderers/tac.js +38 -0
- package/src/view/doc-renderers/tad.js +74 -0
- package/src/view/doc-renderers/test-suite.js +45 -0
- package/src/view/doc-renderers/user-story.js +63 -0
- package/src/view/html-page.js +462 -0
- package/src/view/index.js +63 -0
- package/src/view/live-client.js +338 -0
- package/src/view/mermaid-diagram.js +178 -0
- package/src/view/style.css +735 -0
- package/src/view/tree-model.js +152 -0
- package/src/view/vendored/mermaid.min.js +2607 -0
- package/src/view-supervisor/index.js +26 -0
- package/src/view-supervisor/logs.js +32 -0
- package/src/view-supervisor/manifest-writer.js +178 -0
- package/src/view-supervisor/persist-until.js +85 -0
- package/src/view-supervisor/supervisor.js +276 -0
- package/src/watch/index.js +152 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented in this file.
|
|
4
|
+
|
|
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
|
+
|
|
7
|
+
## [0.8.0] - 2026-08-12 (on `slug-train/0.8.0`, PR pending)
|
|
8
|
+
|
|
9
|
+
### Added (Car 4, verify updates per requirements doc)
|
|
10
|
+
|
|
11
|
+
- **`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.
|
|
12
|
+
- **`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.
|
|
13
|
+
- **`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).
|
|
14
|
+
- **`src/finalise/index.js` re-exports** `findScopeMismatchAcs` and `reportHasScopeMismatch` alongside the pre-existing mock-only-declared predicates.
|
|
15
|
+
- **`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.
|
|
16
|
+
- **`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.
|
|
17
|
+
- **`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.
|
|
18
|
+
- **`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).
|
|
19
|
+
|
|
20
|
+
### Version bump
|
|
21
|
+
|
|
22
|
+
- **`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.
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
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.
|
|
27
|
+
|
|
28
|
+
### Added (Car 3, admissibility lint + drift refusal + refuse-by-default in query)
|
|
29
|
+
|
|
30
|
+
- **`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.
|
|
31
|
+
- `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).
|
|
32
|
+
- `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).
|
|
33
|
+
- `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.
|
|
34
|
+
- `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).
|
|
35
|
+
- `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.
|
|
36
|
+
- **`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`.
|
|
37
|
+
- **`#admissibility` package.json import specifier.** New subpath alias mapping to `./src/admissibility/index.js`.
|
|
38
|
+
- **`test/admissibility/scope-lint.test.js` (5 tests)** covering NV-BL-ADM-02 absent / unclassified / tolerance, NV-BL-ADM-03 narrower-fails / wider-passes.
|
|
39
|
+
- **`test/admissibility/markers.test.js` (4 tests)** covering the case-insensitive vocabulary scan, line/column offsets, empty input, and multi-file scan + ioFailure surfacing.
|
|
40
|
+
- **`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.
|
|
41
|
+
|
|
42
|
+
### Changed (Car 3, landmines + schemas pin)
|
|
43
|
+
|
|
44
|
+
- **`@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.
|
|
45
|
+
|
|
46
|
+
### Fixed (Car 3, w-2026-07-28-012 landmines)
|
|
47
|
+
|
|
48
|
+
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.
|
|
49
|
+
|
|
50
|
+
- **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.
|
|
51
|
+
- **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`.
|
|
52
|
+
- **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`.
|
|
53
|
+
- **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.
|
|
54
|
+
|
|
55
|
+
### Added (Car 2, shared standards ruleset)
|
|
56
|
+
|
|
57
|
+
- **`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.
|
|
58
|
+
- **`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.
|
|
59
|
+
- **`#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.
|
|
60
|
+
- **`docs/ruleset.md`.** Ruleset reference doc — artefact location, version policy (NV-BL-SR-02), content at v1 (NV-BL-SR-03), consumers, migration state.
|
|
61
|
+
- **`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.
|
|
62
|
+
|
|
63
|
+
## [0.7.0] - 2026-07-31
|
|
64
|
+
|
|
65
|
+
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.
|
|
66
|
+
|
|
67
|
+
### Added (Track C+D, 2026-07-31)
|
|
68
|
+
|
|
69
|
+
- **`rcf req-classify <req-id> [--all] [--json]` verb (spec §4.4).** Runs the REQ-shape classifier (`packages/build/src/req-detection/classifier.js`) against one requirement or the whole tree and writes the resulting `shapeClassification` block back onto the REQ. Deterministic keyword-scan over `title`, `description`, `rationale` plus parent PRD `intent`/`problem` as fallback context; signals from `@stravica-ai/rcf-lite-core/patterns/req-shapes` (single source of truth, `webUi` composed from Track B's `UI_SEED_PATTERNS_V1`). Multi-shape verdicts are legitimate; `[none]` records a pure business-rule REQ; `content-pending` marks a REQ whose description is empty or a TODO. Preserves any prior `operatorOverride` block on subsequent runs.
|
|
70
|
+
- **Automatic classification on write.** `rcf create req --description "..."` and `rcf update req <id> --description|--title|--rationale ...` fire the classifier post-write; the resulting shapes line prints alongside the create/update confirmation. Best-effort - a classification error surfaces on stderr but never fails the write (the REQ was already persisted; classification is provenance layered on top).
|
|
71
|
+
- **`rcf req-baseline <verb>` (spec §5).** Baseline-AC sweep and opt-out ledger for classified REQs. `rcf req-baseline sweep --req <id> | --all [--dry-run] [--yes] [--json] [--status]` walks every US under the target and proposes any baseline AC not yet present; interactive by default on a TTY, `--yes` accepts every candidate non-interactively. `rcf req-baseline opt-out --req <id> --key <baselineKey> --reason "..." [--scope req|project]` writes a `baselineAcOptOuts[]` entry (reason floor 20 characters per schema); `--remove` deletes an existing entry. The C+D-native verb sits alongside Track A's preflight design-shape write path so both surfaces feed the same ledger.
|
|
72
|
+
- **Silence-refuses-build (Stage-1) gate wired into `rcf build`.** `rcf build --next` and `rcf build <fbs-id>` refuse (exit 4) when the selected FBS binds an AC on a US that still has open baseline sweep candidates. The refusal message matches spec §5.4 verbatim in shape (candidate count, per-key description, `Resolve:` line pointing at `rcf req-baseline sweep --req ...`). Open-candidate state is derived from the tree (`packages/build/src/req-baseline/open-candidates.js`); a fresh US under a classified REQ auto-surfaces its unresolved baseline keys without any explicit queue-write (spec §5.3 moment 4).
|
|
73
|
+
- **Moment-4 signal on `rcf create us`.** Non-interactive US creation under a shape-classified REQ prints the list of baseline keys that are OPEN and names `rcf req-baseline sweep --req <id>` as the resolution command. The Stage-1 refusal is the single unbypassable gate; this signal surfaces the queue immediately rather than waiting for the operator to hit `rcf build --next`.
|
|
74
|
+
- **`rcf intake` verb (spec §6).** Variable-fidelity intake stage that runs BEFORE elicitation-playbook §3 when the operator supplies content. Three-phase flow: classify by fidelity (`none | napkin | briefLight | briefStrong | prd | prdPlusTad`), validate + challenge with deterministic scans (`impliedButNotStated`, `contradiction`, `missingLoadBearingConstraint`), record an `intakeClassification` on the manifest. `--artefact <path>` (repeatable / comma-separated), `--kind <hint>`, `--input <config.json>` (non-interactive), `--dry-run`, `--json`. The intake-worker subagent dispatch (spec §6.6) is fenced for a follow-up ship; the deterministic scans plus operator `otherDeclared` findings via `--input` cover phase 2 in v1.
|
|
75
|
+
- **Intake-worker subagent (spec §6.6) fenced for a follow-up ship.** The reader-driven findings the spec names (a worker reads the artefact end-to-end and adds findings the pattern scan cannot) are NOT produced by any LLM path in v1. What ships now: the three deterministic scans above cover the concrete failure classes cold-run analysis §6 named (Resend-key gap, negated-login vs admin-UI contradiction, web-UI without sign-in surface), and the seam for the worker is in place - `runIntakePhases({ input })` accepts operator-declared `otherDeclared` findings via `--input`, so wiring an Opus 4.7-pinned worker later is a code addition at that merge point, not a schema or record-shape change. This mirrors the mock-canary posture in the register-regression driver: an unwired driver honestly declared over silent theatre.
|
|
76
|
+
- **Register-regression canary (spec §7).** `npm run canary:register` in `packages/build/`, backed by `packages/build/scripts/canary-register.mjs` and the runner module under `packages/build/src/register-canary/`. Loads the fixture pack from `@stravica-ai/rcf-lite-core/fixtures/register-canary/*.json` (three v1 fixtures), injects the shipping build's guidance content (elicitation + build-cycle playbooks) as system context for a subagent driver, grades every first response with core's `REGISTER_CANARY_DIMENSIONS_V1` (five dimensions: `internalRuleCitation`, `unglossedJargon`, `redundantPermissionAsk`, `bypassOffer`, `wordCountBudget`), and appends one `registerCanary` record per fixture to `packages/build/fixtures/canary-manifest.json`. Exit 0 on aggregate pass, exit 4 on any fail; `--accept-fail --reason "..."` is the ship-despite-fail path for live-driver fails.
|
|
77
|
+
- **Distinguishable mock-driver runs.** The MOCK subagent driver produces a durably distinguishable record from any live-driver run: `buildVersion` is suffixed `-mockdriver`, the top-level verdict is FORCED to `fail`, and `shipDespiteFailReason` is stamped with `MOCK_DRIVER_MARKER`. This mirrors Track A N-2 (unwired mutation runner returning PASS is theatre) and Track B flagged-call-2 (stub browser driver forced to warn-never-pass). `--accept-fail` is refused on mock-driver runs so a release engineer cannot paper over the mock marker; the ship-despite-fail path is for live-driver fails only. Production driver (Anthropic Agent SDK dispatch pinned to Opus 4.7 per estate ladder) is fenced for a separate ship - the runner accepts a `driverMode: 'mock' | 'live'` argument so wiring the live driver is a one-line change at the CLI seam without touching the record contract.
|
|
78
|
+
- **`never-skip-RCF` platform invariant (spec §8).** The canonical paragraph lands byte-identically in three surfaces: `packages/build/guidance/elicitation-playbook.md` §11.1, `packages/build/guidance/build-cycle-playbook.md` §13 (opens the bug-triage section), and `packages/build/guidance/manifest.json` `platformInvariants[0].text`. A locking test (`packages/build/test/guidance/never-skip-rcf.test.js`) asserts byte-identity across all three; a wording edit in one surface without the same edit in the others fails CI. `rcf guidance invariants` prints the platform-invariants block from the manifest as a numbered list; editor guard-rail comments at the top of both playbooks name the release-block posture.
|
|
79
|
+
- **Elicitation-playbook additions.** New §5.5 ("REQ shape and its baselines") between §5 and §6 with sub-sections §5.5.1 (five shapes) and §5.5.2 (sweep + opt-out ledger). §8 done-bar gains item 6 (every classified REQ has completed its baseline sweep). §11.1 carries the never-skip-RCF invariant paragraph verbatim. Cross-references to Track A preflight and Track B `uiBaseline.defaults`.
|
|
80
|
+
- **Build-cycle-playbook additions.** §13 opens with the never-skip-RCF invariant paragraph verbatim (existing bug-triage text preserved after the invariant). §16 gains a cross-reference to the review-surface persistence (`rcf view start | status | stop | logs`).
|
|
81
|
+
- **`rcf view start | status | stop | logs` sub-verbs (spec §9).** `packages/build/src/view-supervisor/` with `bin/view-supervisor-child.mjs` as the detached child entry point. `rcf view start --detach` (default on an interactive TTY; explicit `--foreground` preserves the pre-0.7.0 behaviour for non-interactive callers) forks a supervised background process via `child_process.spawn({ detached: true, stdio: 'ignore' })`, writes `reviewSurface.viewServer` to the manifest, runs a 30-second heartbeat, and installs SIGTERM/SIGINT handlers that clear the manifest record and remove the pid file on shutdown. `rcf view status` reports `running | stale | not-started` (a heartbeat older than 2× the interval or a dead pid classifies as `stale`). `rcf view stop` sends SIGTERM and waits for clean shutdown. `rcf view logs [--tail <n>]` tails the supervisor log. `--persist-until <duration|iso>` keeps the supervisor alive across foreground-session death until the named deadline: accepts durations (`4h`, `30m`, `2h30m` - matches the spec §9.2 sample) or ISO timestamps (`2026-07-31T18:00:00Z`); unrecognised values refuse (exit 2) rather than silently no-op.
|
|
82
|
+
- **`.rcf/view-server.pid` and `.rcf/view-server.log` gitignored** via the 0.6.0 aggregator seam (`viewServerGitignoreEntry`, `viewServerLogGitignoreEntry` exported from `packages/build/src/view-supervisor/manifest-writer.js`, folded into `managedGitignoreEntries()`). Doctor's stale-hash check catches drift; the two-file addition follows the same one-import-two-lines pattern the 0.6.0 spec ratified.
|
|
83
|
+
- **`packages/build/guidance/persona-programme.md` new file (spec §10).** Ships the tail-interview template (five questions: response length + density, silent non-asks, first-impression posture, register drift, catch-all) as discoverable guidance. Registered on `guidance/manifest.json` as `slug: persona-programme`; `rcf guidance persona-programme` prints it and MCP-wired agents reach it via `rcf://docs/persona-programme`. No v1 runtime consumer wired inside build-lite; operator-side persona role definitions inherit the template in a separate ship (spec §12 seams claimed).
|
|
84
|
+
- **`rcf guidance invariants` verb.** Prints the platform-invariants block from `guidance/manifest.json` as a numbered list. Documented in the `guidance --help` under a distinct "Platform-invariant printer (Track C+D)" heading (kept out of the standard topic list so the byte-faithful topic-serving contract remains intact - `invariants` is a virtual verb, not a manifest doc topic).
|
|
85
|
+
|
|
86
|
+
### Added (Track B, 2026-07-31)
|
|
87
|
+
|
|
88
|
+
- **`rcf ui-classify <fbs-id> [--json]` verb.** Runs the UI-bearing classifier on demand against one FBS. Deterministic keyword scan over the FBS summary, in-scope AC prose, parent US iWant / soThat, ancestor REQ description / rationale, plus a `dependsOnServices[]` auth-shape signal. No writes; prints the verdict and matched signals with source anchors, and (when the verdict is `ui`) names the ratification command `rcf update <fbs-id> --set uiBearing=true`. Falls out of `rcf build --next` and `rcf build <fbs-id>` as a `[info]` line ahead of the bundle so the operator always sees the classifier's reasoning. Backed by `packages/build/src/ui-detection/classifier.js` and the shared `patterns/ui-shapes` seed set exported by `@stravica-ai/rcf-lite-core@0.3.0`. Spec sections 4.2, 4.4.
|
|
89
|
+
- **`rcf ui-baseline <verb>` verb (init | show | opt-out).** Manages the project's ruled UI defaults captured once as a `uiBaseline` record on the manifest (monotonic id `uib-YYYY-MM-DD-NNN`). `init` runs an enter-to-accept-all summary session (or `--input <file>` non-interactive) walking the eighteen ruled defaults from spec section 6.1 (theme mode, shared layout module, design tokens module, hex-in-view-files ban, contrast target, contrast-test-before-palette, focus rings, hover states, component vocabulary, single badge shape, typography defaults, interaction defaults, auth flow); every opt-out lands on `operatorOptOuts[]` with a plain-text reason of at least twenty characters, matching the spec's "explicit never by silence" property. `--reset` appends the previous record to `uiBaselineHistory[]`. The init flow reads the preflight seam (spec section 3.2): any Track A `preFlightConfig[].designShapeAnswers` entry whose `uiBaselineWritePath` targets `defaults.*` lands as a seeded override (newest answer wins), while the corresponding `baselineAcOptOuts[]` ledger entry stays put as the durable record. `show` prints the current record; `opt-out --field <path> --reason "..."` appends an entry idempotently.
|
|
90
|
+
- **`rcf design <fbs-id> [<sub-verb> ...]` verb.** Design substage (Stage 1.5) for UI-bearing FBSes. Sub-verbs write to the FBS's `designStage` block: `journeys add --id <slug> --actor "..." --goal "..." --step "..."` (repeated 2 to 8 times), `nav set --shape <shape> --route <path=label:auth> [--signed-in-as-affordance ...] [--notes ...]`, `theme-a11y set --mode <themeMode> --tokens <path> --contrast-test <path> --contrast-before-palette true|false`, `--mark-complete` (sets `designStageComplete: true` once all three artefacts are present and non-empty). `rcf design <fbs-id>` with no sub-verb prints the current state and names the next-move options. Positional-grammar constraint: the FBS positional MUST match `/^FBS-\d+$/`, and any positional in slot 0 that fails the pattern is a usage error, not an FBS lookup miss (spec section 5.5). Refuses any Design substage write when the FBS is uiBearing but no `uiBaseline` record exists on the manifest (spec section 6.2).
|
|
91
|
+
- **`rcf browser-verify <fbs-id>` verb.** Stage 5 browser-verification gate for a UI-bearing FBS. Two modes: `operatorSession` records the operator's ack (no captures required; the operator's ack is the evidence per spec section 8.2), `agentScreenshotCritique` drives an injectable browser driver over every enumerated route x theme, runs the versioned `UI_INVARIANTS_V1` set (spec section 8.3 - `sharedNavPresent`, `activeNavMarked`, `signedInAsAffordance`, `themeToggleVisible` with the widened recognition set, `themeDefaultsToLight`, `focusRingsVisible`, `sharedLayoutModule` structural compare) and the auth-REQ smoke pack (`GET /login` expects 200 + text/html, `POST /logout` expects 200 / 302 / 303, `GET /login/verify?token=` refuses the empty-token accept as a regression). Writes a `browserVerification[]` record on the manifest with a monotonic per-FBS id `bv-<fbsId>-<n>` and an aggregated verdict per spec section 8.5. `--ack` clears a warn verdict; `--dry-run` prints the record without writing. The stub driver default emits zero captures and surfaces a `warn` on a synthetic `agentDriverWired` invariant so the CLI is testable without a live Playwright, and production wiring lands via `deps.browserDriver` on the CLI. Rubric surfaced on stdout so the "quite frankly the UI looked really dated" defect is visible ahead of the invariant tables. Spec sections 8, 9.
|
|
92
|
+
- **`rcf build --mark complete` gates.** Refuses when the FBS is uiBearing and `designStageComplete` is not true (spec section 5.5), when `designStage.themeAndA11y.contrastTestAuthoredBeforePalette` is false (mandate 10, spec section 7), when the baseline disagrees with a paired `designStage` field and no `operatorOptOuts[]` entry excuses it (spec section 6.2 belt-and-braces), and when the browser-verification verdict is `block` or `warn` without operator ack. `--accept-block --reason "..."` (reason at least twenty characters) is the ship-without-verified escape hatch (spec section 8.6); the reason lands on `browserVerification.operatorShipDespiteBlockReason`. `--mark inProgress` on a uiBearing FBS with no `designStage` emits a soft `[warn]` naming `rcf design <fbs-id>` (spec section 5.2). Powered by three pure helpers on `packages/build/src/build/mark.js` (`checkDesignGate`, `checkContrastBeforePaletteGate`, existing CN gate).
|
|
93
|
+
- **REVIEW-stage `uiBaselineDrift` audit kind.** The Track A `rcf review <fbs-id>` audit now runs the Stage-3 UI-baseline drift check alongside the test-theatre findings for uiBearing FBSes: hex literals in view files (default glob `src/ui/**` minus the tokens module, configurable via `uiBaseline.defaults.viewFileGlobs`), and route files that fail to import the shared layout module (default glob `src/routes/**`). Findings land on the same `reviewAudit[].testTheatreFindings[]` record with `kind: uiBaselineDrift` (schema enum extension in `@stravica-ai/rcf-schemas@0.4.0`), severity `block` by default and demoted to `advisory` when `operatorOptOuts[]` names the field. One brief, one worker, one record per FBS - the same audit run emits findings across Track A and Track B kinds (spec section 12 O-12). Spec section 3.4.
|
|
94
|
+
- **FBS view renderer surfaces Design substage state.** `packages/build/src/view/doc-renderers/fbs.js` renders a "Design substage" section with `uiBearing`, `designStageComplete`, journey count, nav shape + route count, and themeMode for any FBS whose design block is populated (or where `uiBearing: true`). Renders nothing for non-UI FBSes (byte-preserving vs the pre-Track-B layout baseline).
|
|
95
|
+
|
|
96
|
+
### Fixed (Track B review pass, 2026-07-31)
|
|
97
|
+
|
|
98
|
+
- **B-1 blocker: `rcf build --mark complete --accept-block --reason "..."` on a uiBearing FBS with NO existing `browserVerification` record now refuses cleanly (exit 4).** The previous shape wrote the error to stderr, fell through the missing-record branch (because `if (!acceptBlock) return 4` did not short-circuit when acceptBlock was true), and marched the FBS to `complete` with only an ephemeral stderr line as evidence of the operator's ship-anyway reason. That reintroduced the exact "durable record or it did not happen" defect Track A's B-1 closed for `rcf finalise --ship-without-verified`. The fix returns 4 unconditionally in the missing-record branch and names the two-command dance in the refusal message (run `rcf browser-verify` first, then re-run `--accept-block --reason` against the resulting record so the ack anchors on a real verdict rather than inventing a synthetic one). Covered by a new dedicated CLI-level test file `packages/build/test/cli/build-browser-verify-gate.test.js` with four end-to-end tests: refuse-cleanly with `--accept-block` (the fix), refuse-cleanly without `--accept-block` (context-pin on the branch ordering), positive path with an existing block-verdict `bvRecord` (ack lands on `browserVerification.operatorShipDespiteBlockReason` as spec section 8.6 mandates), and warn-cleared-via-`--ack` context. `packages/build/src/cli/build.js:433-437`.
|
|
99
|
+
- **N-1: `packages/build/CHANGELOG.md` no longer carries the duplicate `### Fixed (Track A review pass, 2026-07-31)` heading** at line 23 (bare double-paste on the Track A pass).
|
|
100
|
+
- **N-3: unreachable `|| bvRecord.verdict === 'warn'` disjunct dropped** from the ship-without-verified ack writer at `packages/build/src/cli/build.js:451`. The earlier guard returns 4 on `warn && !operatorAckAt`, so acceptBlock could never reach the ack path on a warn record; the disjunct was live spec-drift, not code. The sanctioned warn clear remains `rcf browser-verify --ack` (spec section 8.5).
|
|
101
|
+
- **N-4: `preflightSeamOverrides` generalised across the design-shape catalogue.** The pickup now reads `uiBaselineWritePath` / `uiBaselineWriteValue` off the catalogue's per-choice metadata via a resolved question lookup (default `CATALOGUE_V1`, injectable for tests) rather than switching on `questionId === 'auth.htmlLoginPage'`. Any answered question whose selected choice carries a write path targeting `defaults.*` flows through the seam automatically; a future Track C+D catalogue addition needs no wiring change here. Test coverage extended with three new cases in `test/ui-baseline/preflight-seam.test.js`: a synthetic second-question catalogue that proves generality (auth + ui.themePolicy both landing), an unknown-questionId no-op, and a choice-without-writePath no-op. `packages/build/src/ui-baseline/manifest-writer.js:98-115`.
|
|
102
|
+
- **N-5: `uiBaselineDrift` findings now anchor on `anchorId` instead of smuggling the FBS id through the `tsId` slot** (rcf-schemas 0.4.2 additive change). The Track A schema required `tsId` on every finding, so the drift check populated `tsId: fbs.fbsId` to satisfy the constraint; a downstream reader assuming `tsId` names a real TS would then follow a broken pointer. Fixed contract-first: `@stravica-ai/rcf-schemas@0.4.2` adds an optional `anchorId` field and relaxes `tsId` from required for `uiBaselineDrift` (still required for the five test-theatre kinds). This repo's `@stravica-ai/rcf-schemas` dep bumped from `^0.4.1` to `^0.4.2` (`packages/build/package.json`, `packages/core/package.json`). The drift writer at `packages/build/src/review/ui-baseline-drift.js:73, 102` now emits `anchorId: fbs.fbsId` (no `tsId`), with three new tests in `test/review/ui-baseline-drift.test.js` covering the hex-literal + shared-layout paths and a schema-validation smoke on a drift-only reviewAudit record. Legacy 0.4.0/0.4.1 shapes with `tsId` on drift findings remain schema-valid (back-compat is spec-tested on the schemas side).
|
|
103
|
+
- **N-6: two em-dashes in newly-added Track B code comments swapped for ASCII punctuation** at `packages/build/src/cli/review.js:129, 234` (estate baseline: no em-dashes in any new prose, code comments included).
|
|
104
|
+
|
|
105
|
+
### Fixed (Track A review pass, 2026-07-31)
|
|
106
|
+
|
|
107
|
+
- **B-1 blocker: `rcf finalise --ship-without-verified` now records the operator ack on the manifest.** Previously the ack landed on stdout only, which is neither durable across sessions nor greppable at ship time. Ships a new `manifest.shipWithoutVerified[]` array (schema addition in `@stravica-ai/rcf-schemas` 0.4.1, this repo's `@stravica-ai/rcf-schemas` dep bumped from `^0.3.1`/`^0.4.0` to `^0.4.1` accordingly) with a monotonic per-FBS id `swv-<fbsId>-<n>`, the `fbsId`, `ackedAt`, the acknowledged per-AC verdicts (`MOCK-ONLY-DECLARED` or `BLOCKED-BY-DECLARATION` only), and the report path. The finalise confirmation line now names the ack id so an operator can grep the manifest for a specific record. Wired via a new `packages/build/src/finalise/ship-without-verified.js` module with the same atomic-write discipline the preflight writer uses; on manifest validation failure the on-disk manifest stays untouched and finalise exits 3. Spec section 5.2.
|
|
108
|
+
- **N-1: `rcf build --next` emits the preflight warning the elicitation and build-cycle playbooks already advertised.** When the selected FBS carries `dependsOnServices[]` entries whose service `id` is not named in any `preFlightConfig[].servicesInScope[].id`, the CLI prints one `[warn]` line naming the unbacked services and pointing at `rcf preflight`. Warn only (not exit 4): the Stage 1 warn-only ruling stands, the hard refuse still lives on `coverage --strict` at Stage 4. Powered by a new `scanUnbackedServices(tree, fbsId)` helper in `packages/build/src/query/attestation.js`.
|
|
109
|
+
- **N-2: default mutation-sampling runner (`mode: 'agent-v1-not-wired'`) now aggregates to `warn`, not `pass`.** An unwired runner was indistinguishable at the exit-code layer from a wired runner that killed every mutant, both landing `verdict: pass`. Warn forces the operator to wire a runner or pass `--skip-mutation` (mode `skipped`), which remains `pass` as an explicit operator choice. `aggregateVerdict` in `packages/build/src/review/index.js`; a `block` finding still wins over the warn.
|
|
110
|
+
- **N-3: `coverage --strict` warns when a preFlightConfig service has empty `affectedFbsIds`.** `findAttestationMissing` intentionally skips services without the back-reference (there is nothing to cross-check), but the operator saw no signal that the service was uncovered by the strict detector. One `[warn]` line per empty back-reference, additive (never turns a passing strict run into a failing one). New `findServicesWithEmptyAffectedFbsIds(tree)` helper alongside the other detectors.
|
|
111
|
+
- **N-5: `notShipped × mixed` matrix row now covered.** The `mixed` short-circuit runs before any attestation branch, so `notShipped × mixed` refuses like every other `× mixed` cell. Added to the MATRIX loop at `test/query/attestation.test.js` with a comment explaining why the anti-pattern discipline wins over the "notShipped does not gate ship" rule.
|
|
112
|
+
- **N-6: `CATALOGUE_V1` is deep-frozen.** `Object.freeze` is shallow; a caller could mutate a choice's `triggersOptOut` even on the outwardly frozen catalogue. Cosmetic hardening for a spec-committed data surface. `deepFreeze` helper in `packages/build/src/preflight/design-shapes.js`.
|
|
113
|
+
|
|
114
|
+
Total across the review pass: +17 tests on top of the Track A baseline (build suite 927 to 944; monorepo suite green including all sibling packages).
|
|
115
|
+
|
|
116
|
+
### Added
|
|
117
|
+
|
|
118
|
+
- **`rcf preflight` verb - elicit the pre-flight service-attestation record and any applicable design-shape answers before the build cycle starts.** Scans the PRD (and optionally a TAD) via the shared `patterns/services` seed set exported from `@stravica-ai/rcf-lite-core@0.3.0`, surfaces per-service candidates with provenance (doc id + section anchor + matched phrase), and forces one of the five attestation modes per candidate (`live` / `sandboxed` / `mocked` / `declaredMockOnly` / `notShipped`). Interactive by default when running on a TTY; non-interactive mode via `--input <file>` for CI and automation. The session writes a `preFlightConfig[]` record onto the manifest, monotonic id `pfc-YYYY-MM-DD-NNN`. Operator-added candidates are supported with zero source refs (`schemas@0.4.0` minItems:0). Credentials NEVER enter the chain: the session prompts for env-var names only and writes name-metadata plus a presence boolean to `.rcf/preflight-secrets.local.json`, the credentials side-file whose gitignore path rides the 0.6.0 managed-block aggregator seam as a genuine two-line extension (one import from `../preflight/secrets.js` and one array entry in `managedGitignoreEntries()`, exactly the shape the 0.6.0 spec §4.1 D-4 promised).
|
|
119
|
+
|
|
120
|
+
- **Design-shape sub-surface inside `rcf preflight` (ADDENDUM §A).** The v1 catalogue carries exactly one question: `auth.htmlLoginPage` ("HTML login page or API-only?"), posed against any REQ whose `shapeClassification.shapes[]` contains `auth` (or, when the classifier has not yet run on the tree, against any REQ whose title / description / rationale prose fires the shared `matchReqShapeSignals` matcher on the auth patterns). An "HTML login page" answer records a `designShapeAnswers[]` entry; an "API-only" answer additionally writes a `baselineAcOptOuts[]` entry with a `linkedPreFlightConfigRef` pointing at the pre-flight record's id plus the question path, so Track C+D's opt-out ledger inherits the ruling without a separate verb. The `uiBaseline.defaults.authFlow.htmlLoginPageRequired` write is fenced pending Track B; the linked-ref is the seam Track B will read when its train-car lands.
|
|
121
|
+
|
|
122
|
+
- **`rcf fbs <fbs-id> depends-on --service <id> --mode <mode> --acs <acIds>` verb.** Writes a `dependsOnServices[]` entry on the FBS at Define stage; idempotent by service id (a second call replaces the entry). Refuses `--acs` that reference an AC not on the FBS (bypass with `--force` for repair paths). `--preflight <pfc-id>` expands a bare pre-flight id into the composite `preFlightRef` (`pfc-...#services.<id>`) so the FBS binding traces back to the pre-flight ruling.
|
|
123
|
+
|
|
124
|
+
- **`rcf test-suite <ts-id> provenance --profile <profile> [--tc <tc-id>] [--env-var VAR ...] [--host host ...] [--notes ...]` verb.** Records `runtimeProvenance` on one TC or on every TC in the TS. Refuses to overwrite an existing block without `--force`. Refuses `--notes` that look like they contain a token or secret (a belt-and-braces grep, not a real secret scanner; the notes field is prose-only, never quotes credential material).
|
|
125
|
+
|
|
126
|
+
- **`rcf test-suite <ts-id> approve [--force]` verb, plus opt-in `rcf coverage --strict --require-approved` CI gate.** Writes `authoringStatus: approved` on the TS. Refuses to promote a `superseded` or `needsRevision` TS without `--force`. Stage-4 rule in the build-cycle playbook wires this into the automatic end-of-stage promotion; the CI gate refuses any TS still `draft` after Stage 4.
|
|
127
|
+
|
|
128
|
+
- **`rcf coverage --strict` extended with the §3.5 attestation × profile matrix.** Three additional exit-4 refusal classes on top of the existing per-AC coverage gate: (a) attestation missing (FBSes listed in a pre-flight record's `affectedFbsIds` but with no matching `dependsOnServices` entry - v1 stays honest and skips services whose `affectedFbsIds` is empty), (b) runtime provenance missing (a TC covers an AC that binds a service but has no `runtimeProvenance` block), (c) attestation drift (a TC's profile contradicts its AC's aggregated attestation per the matrix - `live × mock` / `sandboxed × fixture` / `mixed × anything` all refuse). `declaredMockOnly × live` is recorded as `passWithWarn` and surfaced by the review-stage audit rather than blocking coverage.
|
|
129
|
+
|
|
130
|
+
- **`rcf review <fbs-id>` verb - REVIEW-stage test-theatre audit + mutation-sampling coordinator.** Runs four deterministic detectors (mockOnlyIntegrationClaim, testPointerBroken, acIdsCoverageDrift, attestationDrift-as-otherDeclared) plus the mutation-sampling agent dispatch. The mutation runner is injected via `deps.mutationRunner`; the CLI default emits a valid schema record with a `notes` explaining that no runner was wired, so the reviewAudit record always validates. `--skip-mutation` records the skip explicitly. `--dry-run` runs the audit without writing. Writes a `reviewAudit[]` record on the manifest with a monotonic per-FBS id `ra-<fbsId>-<n>`, aggregates a verdict (block if any finding severity is block or any mutation survivor exists; warn if any warn; pass otherwise), and exits 0 on pass or 4 on warn / block, so the audit is a Stage 3 to Stage 4 gate.
|
|
131
|
+
|
|
132
|
+
- **`rcf finalise --ship-without-verified` flag, plus MOCK-ONLY-DECLARED disclosure in the finalise summary.** The gate reads per-AC verdicts from the verify report: any AC that comes back `MOCK-ONLY-DECLARED` / `BLOCKED-BY-DECLARATION` refuses the `complete -> verified` promotion unless the operator passes `--ship-without-verified`. The summary always discloses these verdicts (whether the FBS ships or not). Older verify reports without a `perAcVerdicts` field are handled gracefully - verify's train car may land later; older reports flow through with the pre-0.7.0 gate behaviour.
|
|
133
|
+
|
|
134
|
+
### Documentation
|
|
135
|
+
|
|
136
|
+
- **Elicitation playbook §8.5 "Pre-flight config".** New section sits between §8 "When to stop" and §9 "What this playbook deliberately does not do", covering what the pre-flight session is, why it belongs before the build starts, the five modes with one-line decision guidance, what "declared mock-only" costs at ship time, and the credentials-never-in-the-chain contract.
|
|
137
|
+
- **Build-cycle playbook additions.** Stage 1 (Define): a "third-party service dependencies belong on the FBS at Define" section wiring the `rcf fbs depends-on` verb into the plan. Stage 3 (Review): a second-gate section covering the `rcf review` audit's five finding categories, severities, and the exit-4-on-warn-or-block gate discipline. Stage 4 (Test): "runtime provenance is authored, not remembered" plus the TS-approval-as-Stage-4-outcome rule. Stage 5 (Finalise): "the finalise gate reads the attestation, not just the exit code" covering the MOCK-ONLY-DECLARED refusal and the `--ship-without-verified` acknowledgement path. Section 15 (Runtime-provenance): a paragraph on the chain being the source of truth from 0.7.0 onward, with the PR body as its rendering.
|
|
138
|
+
|
|
139
|
+
### Internal
|
|
140
|
+
|
|
141
|
+
- **`packages/build/src/preflight/`** - new module tree: scanner, secrets side-file loader, design-shapes catalogue + selector, manifest writer, interactive-session driver, barrel. Every module obeys the redaction discipline (values never accepted as input, never written, never quoted in error messages) and the "matchServiceSignals is IMPORTED not re-implemented" rule.
|
|
142
|
+
- **`packages/build/src/review/`** - new module tree: deterministic test-theatre detectors + verdict aggregation, mutation-sampling coordinator with an injectable runner.
|
|
143
|
+
- **`packages/build/src/query/attestation.js`** - the §3.5 matrix, aggregation, and the three refusal detectors that `coverage --strict` consumes.
|
|
144
|
+
- **`packages/build/src/setup/managed-gitignore.js`** - two-line extension riding the 0.6.0 aggregator seam: `import { preflightEntry } from '../preflight/secrets.js';` at the top; one `preflightEntry` entry in `managedGitignoreEntries()`. Direct-evidence test at `packages/build/test/preflight/aggregator-extension.test.js` makes the "genuinely two lines" claim falsifiable.
|
|
145
|
+
- **Test coverage: +60 tests on top of the 0.6.0 baseline.** Every Track A AC is covered by a green test; the attestation × profile matrix walks every row of §3.5; the review-stage detectors and verdict aggregation are covered per finding kind; the mock-only-declared disclosure and gate refusal are covered on the ingestion side and end-to-end via a stub rcf-verify subprocess; the preflight scanner is fixture-tested against the d-142 "email channel" miss and against the vendor-name promotion path.
|
|
146
|
+
|
|
147
|
+
## [0.6.0] - 2026-07-30
|
|
148
|
+
|
|
149
|
+
Init hygiene release ([#70](https://github.com/Stravica/rcf-lite/pull/70)). The CLAUDE.md/AGENTS.md fragment `rcf init` writes now sits inside a managed block that a new `rcf doctor` verb can detect drift on and repair; `rcf/knowledge/` and a per-clone `rcf/.identity/profile.md` are seeded on fresh init; a reusable managed `.gitignore` aggregator seam lands for later per-clone-local artefacts. No schema changes, no changes to the chain data model.
|
|
150
|
+
|
|
151
|
+
### Added
|
|
152
|
+
|
|
153
|
+
- **`rcf doctor` - new subcommand that detects and repairs init-hygiene drift.** Warn-only by default (exits 0 clean, 3 on drift); `--fix` rewrites the safe minimum. Four checks: `agent-instructions` (the managed CLAUDE.md/AGENTS.md block), `gitignore` (the managed `.gitignore` block), `knowledge` (`rcf/knowledge/` shape), `identity` (the seeded `rcf/.identity/profile.md`). The marker-driven checks share a drift enum: `missing-block`, `stale-hash`, `legacy-markers`, `orphan-marker`, `duplicate-block`. `--fix` rewrites only the marked region; every byte outside the markers is preserved verbatim, line endings and trailing whitespace included. Refused for `orphan-marker` and `duplicate-block` - structural corruption is hand-repair only. `--check <name>[,name]` runs a subset; `--json` emits `{ ok, drift[] }`; `--quiet` prints a summary line plus the first three drift items. The verb never auto-fires from `rcf init`, `rcf validate`, an MCP tool, or any hook: the only paths that mutate agent-instructions or `.gitignore` files are `rcf init` (bootstrap) and `rcf doctor --fix` (operator-invoked repair).
|
|
154
|
+
|
|
155
|
+
- **Managed CLAUDE.md/AGENTS.md block contract.** The agent-instructions fragment `rcf init` writes now sits inside `<!-- rcf:managed:begin -->` / `<!-- rcf:managed:end -->` markers and can drift as the package upgrades. `rcf doctor` surfaces the drift; `rcf doctor --fix` rewrites the block wholesale from the canonical text shipped in the package, leaving operator content outside the markers byte-identical. The block adds RULE 8 (never skip the method for speed), RULE 9 (write what you learn, pointing at `rcf/knowledge/`) and RULE 10 (read `rcf/.identity/profile.md` at session start if present), and carries the 0.5.2 operator-communication register forward alongside the existing rules. A SHA-256 of the canonical block ships in the tarball at `guidance/managed/agent-instructions-block.hash`; doctor uses it to detect a block whose inner content no longer matches the current package's canonical text (`stale-hash`).
|
|
156
|
+
|
|
157
|
+
- **`rcf/knowledge/` - per-project memory seeded on `rcf init`.** Fresh init creates `rcf/knowledge/{README.md, INDEX.md, notes/.gitkeep, docs/.gitkeep}` with canonical text. The convention: `notes/` for internal facts (decisions, gotchas, runtime facts), `docs/` for user-facing prose the project might surface elsewhere, one topic per file, `INDEX.md` as a human table of contents, write on learn, grep before asking. Convention only in this release: no CLI verb, no indexer, no retrieval machinery - real usage evidence will decide any later `rcf knowledge` addition. Doctor's `--check knowledge` warns on `missing-directory` or `missing-subdir`; `--fix` refuses in v1 (re-seed via `rcf init`). Init re-runs leave an existing knowledge tree alone; only a fully-deleted tree gets re-seeded.
|
|
158
|
+
|
|
159
|
+
- **`rcf/.identity/profile.md` - per-clone operator profile seeded on `rcf init`.** A short template the operator fills in locally (name, role, working style, project-scoped preferences); RULE 10 in the managed block tells the agent to read it at session start. The directory is gitignored by default via the new managed `.gitignore` block, so profile contents stay per-clone and do not travel with the repo. Doctor's `--check identity` covers seeded-template presence; the profile's contents are the operator's.
|
|
160
|
+
|
|
161
|
+
- **Managed `.gitignore` block with a reusable aggregator seam.** `packages/build/src/setup/managed-gitignore.js` composes a marked `.gitignore` block from an aggregator function whose registered array carries one entry per package feature that needs a default-ignore path. Today the array carries `identityEntry` (`rcf/.identity/`); the seam is the extension point for later per-clone-local artefacts. Adding an entry is a one-file change: import the feature module's exported entry constant, insert it into the `registered` array. Doctor's `--check gitignore` covers the same drift classes as the agent-instructions check; `--fix` rewrites only the marked region.
|
|
162
|
+
|
|
163
|
+
### Changed
|
|
164
|
+
|
|
165
|
+
- **Marker constants renamed `<!-- rcf:begin -->` -> `<!-- rcf:managed:begin -->`** (and end). The rename signals the block is managed, not merely marked. Existing repos on the legacy convention keep working: doctor's `agent-instructions` check reports `legacy-markers` and `--fix` migrates in place. The MCP setup-funnel notice at `packages/build/src/mcp/tools.js` recognises both marker generations, so a pre-0.6.0-inited repo does not see a spurious "Setup incomplete. Run `npx rcf init`" notice appended to every tool response for the server-process lifetime. Migration is operator-initiated; doctor never auto-fires.
|
|
166
|
+
|
|
167
|
+
- **Fail-safe hand-edit detection on legacy migration.** When `rcf doctor --fix` migrates a `legacy-markers` block, it hashes the existing inner content (trimmed) and checks membership in a whitelist of pre-0.6.0 canonical fragment hashes at `packages/build/guidance/managed/legacy-fragment-hashes.json` (build-v0.4.0, build-v0.5.0/1, build-v0.5.2). A whitelisted hash migrates transparently; any hash NOT in the whitelist is treated as hand-edited: on a TTY doctor warns and asks the operator to confirm, off-TTY it refuses without `--force`. The default is to preserve operator content the first time we see it.
|
|
168
|
+
|
|
169
|
+
### Documentation
|
|
170
|
+
|
|
171
|
+
- **The managed block carries the 0.5.2 operator-communication register forward.** The "how to talk to your operator" register (plain language, never cite rules, one to three sentences with one leading question, self-serve before asking, never re-ask granted permissions, tone of "it is in hand") and its before/after example from 0.5.2 now sit inside the canonical managed block and travel with every fresh `rcf init` or `rcf doctor --fix`. British English throughout; the canonical text and every seeded file are em-dash free and clear the American-English denylist checked at package-build time.
|
|
172
|
+
|
|
173
|
+
### Internal
|
|
174
|
+
|
|
175
|
+
- **`scripts/gen-managed-artefacts.mjs` - single canonical source for the managed block.** Generates `packages/build/guidance/managed/agent-instructions-block.hash` and regenerates the fenced fragment inside `packages/build/guidance/harness-template.md` from the canonical source `packages/build/guidance/managed/agent-instructions-block.md` at package-build time. Wired into `prepublishOnly`; a byte-match invariant test locks the harness-template fragment to the canonical source so the paste-in doc and the init-written block cannot drift.
|
|
176
|
+
|
|
177
|
+
- **Test coverage: +58 tests on top of the main baseline.** Across the doctor pipeline (agent-instructions, gitignore, knowledge, identity), init seeding, transitional marker handling, preserve-operator-content contract, the legacy migration path with fail-safe hand-edit detection, and an end-to-end doctor loop. Workspace total at PR HEAD: 1138 tests, 0 fail, 1 skipped.
|
|
178
|
+
|
|
179
|
+
## [0.5.2] - 2026-07-29
|
|
180
|
+
|
|
181
|
+
Guidance-only patch release: the seeded agent guidance gains an operator-communication register. No code, schema, validator or CLI behaviour changes.
|
|
182
|
+
|
|
183
|
+
### Fixed
|
|
184
|
+
|
|
185
|
+
- **The agent now speaks to the operator like a colleague, not a process narrator.** The first real cold run surfaced the gap: the guidance specified what the agent must do but nothing about how it speaks, so the agent's opening message cited harness rules by number, inventoried scaffold document ids at a non-technical operator, asked about git state it could have checked itself, re-asked an already-granted push permission, and buried the one genuine decision at the bottom of a four-section essay. The harness fragment that `rcf init` seeds into CLAUDE.md / AGENTS.md now opens with a "How to talk to your operator" register (plain language; never cite rules; one to three sentences with one leading question; self-serve before asking; never re-ask granted permissions; the operator steers, the agent drives) plus a before/after example of the first status message after setup.
|
|
186
|
+
|
|
187
|
+
### Documentation
|
|
188
|
+
|
|
189
|
+
- **Elicitation playbook**: new section 12, "Speaking to the operator" - the conversational register held across the whole elicitation, with the first message after init called out as where the pull to narrate is strongest. The pre-build review offer is now phrased in plain words instead of document names.
|
|
190
|
+
- **Build-cycle playbook**: new section 17, "Speaking to the operator" - chat register vs PR-body register (evidence depth goes in the PR, not chat), items named by title rather than id, escalations delivered as one plain-language decision. The section 8 escalation template now leads with the item's plain-language title, and the pre-build review gate is phrased in plain words.
|
|
191
|
+
- **Harness template**: the surrounding doc's failure-mode list and "Check it took" section now cover the communication failure mode (a fourth check reads the agent's first operator-facing message).
|
|
192
|
+
|
|
193
|
+
## [0.5.1] - 2026-07-29
|
|
194
|
+
|
|
195
|
+
Dependency-only fix release. Re-packs 0.5.0's runtime against `@stravica-ai/rcf-lite-core@0.2.0` so `rcf` actually boots when installed from the registry. No source, behaviour or surface changes vs 0.5.0.
|
|
196
|
+
|
|
197
|
+
### Fixed
|
|
198
|
+
|
|
199
|
+
- **`rcf` boots on `npm install @stravica-ai/rcf-build-lite`**. 0.5.0 packed against `@stravica-ai/rcf-lite-core@0.1.0` (pnpm's `workspace:*` rewrite locks the exact version at pack time) while its runtime hard-imports the new store surface added in this repo's HEAD core - `testCaseKey` and `resolveTestPointers` from `@stravica-ai/rcf-lite-core/store`. On the registry that resolves to core 0.1.0 which does not export either symbol, and every `rcf` invocation crashes at ESM link with `SyntaxError: The requested module '@stravica-ai/rcf-lite-core/store' does not provide an export named 'testCaseKey'` (from `src/query/coverage.js:29`). Every subcommand - including `rcf --version` - was affected. 0.5.1 packs against the newly-published `@stravica-ai/rcf-lite-core@0.2.0` (the additive minor exposing that surface) and is the recommended install. **Upgrade path:** `npm install @stravica-ai/rcf-build-lite@latest` (or `@0.5.1`); no changes required in consumer code or RCF trees. 0.5.0 remains on the registry pending an operator decision on deprecate/unpublish.
|
|
200
|
+
|
|
201
|
+
## [0.5.0] - 2026-07-29
|
|
202
|
+
|
|
203
|
+
Coverage becomes honest end-to-end (a "covered" AC now requires a resolving test), the build queue surfaces parallel-safe tiers, and forward trace stops conflating intent chains with FBS dependency graphs. Behaviour changes to `rcf coverage`, `rcf trace --forward`, `rcf read`, `rcf validate`, and the `rcf build` queue overview + JSON envelope. All work is in this package; `@stravica-ai/rcf-lite-core` and `@stravica-ai/rcf-verify-lite` are unchanged. Minor bump under the pre-1.0 breaking-is-minor convention.
|
|
204
|
+
|
|
205
|
+
### Added
|
|
206
|
+
|
|
207
|
+
- **Coverage is now resolution-gated: a Test Case counts as covering its AC only when its `testPointer` resolves to a real test in the working tree** ([#61](https://github.com/Stravica/rcf-lite/pull/61)). Previously "covered" meant only that a TC row with a matching `acId` existed on the tree; the pointer was accepted everywhere and checked nowhere, so a tree of stub TCs could report full coverage while pointing at nothing. Resolution is deterministic (file exists, plus a declaration-anchor regex finds the named test; JS/TS anchors ship now, structured so another language is one table entry) and runs on every coverage surface: CLI (`rcf coverage`), MCP (`rcf_coverage`), all three formats. A TC whose pointer does not resolve is reported as its own class, `covered-unresolved`, never silently counted either way: it appears in the summary counters, as `unresolved` in the per-REQ and per-AC table cells, as a `[unresolved]` marker on the TC id, in an "Unresolved test pointers" footer naming each pointer and why it failed (`file-missing`, `test-missing`, `malformed-pointer`, `unsupported-file-type`, `missing-pointer`), and with the `broken` class in mermaid output. `covered-unresolved` fails `--strict` (exit 4) exactly as uncovered does. The inherited honest limit, stated in the same terms as the Code Node check: a renamed test is caught, a gutted test that kept its name is not.
|
|
208
|
+
|
|
209
|
+
- **Parallel-safe tiers in the build queue** ([#64](https://github.com/Stravica/rcf-lite/pull/64)). `rcf build` queue overview gains a `tier` column and an explicit "Parallel-safe tiers" block (md); the JSON envelope carries `tier` on each item and a `tiers` array of parallel-safe groups. Tier computation ported from the platform's `computeTiers` (rcf-common build-graph) and reimplemented idiomatically as an iterative memoised longest-chain DFS in the queue module's own style. Cycle posture: cycle members and anything depending on them get tier `null`, join no group, and the walk cannot loop on a cyclic graph. Delivers FBS-010 / TAC-005 (specified since Phase 6, unbuilt in build-lite until now) and binds AC-502-2.
|
|
210
|
+
|
|
211
|
+
- **`rcf guidance [topic]`**: prints a method document out of the installed package to stdout ([#56](https://github.com/Stravica/rcf-lite/pull/56)). `rcf guidance` with no arguments lists the topics; `--list` emits bare slugs for scripting; `--path` prints the file's location instead of its contents. No project root is required.
|
|
212
|
+
|
|
213
|
+
This closes a gap for CLI-only agents. The guidance pack ships inside the package and is deliberately never scaffolded into your project, so an MCP-wired harness reached the playbooks through `rcf://docs/<slug>` resources and the `rcf_*` prompts while an agent without MCP had no route to them at all. The two deep playbooks are the sharp case: they are served as prompts only, with no `rcf://docs` resource, so the CLI fallback the guidance pointed at was the only route and it did not exist.
|
|
214
|
+
|
|
215
|
+
- **Elicitation deferral branch - "don't know yet / just exploring / not deploying" is now a first-class answer to the deploy-target question** ([#59](https://github.com/Stravica/rcf-lite/pull/59)). RULE 5 previously ordered target-before-stack but implicitly required the owner to have a target; the playbook now carries a capability-class-aware defer branch, distinct from the hosting-choice walkthrough, recorded as an ADR (never a silent stub). Deploy-target examples are reordered alphabetically rather than editorially. Guidance prose + drift tests only; no runtime CLI behaviour change.
|
|
216
|
+
|
|
217
|
+
### Changed
|
|
218
|
+
|
|
219
|
+
- **`testPointer` is required on every Test Case** ([#61](https://github.com/Stravica/rcf-lite/pull/61)). The published `@stravica-ai/rcf-schemas` bundle still declares it optional; Build Lite registers a documented strictness overlay (required, `minLength` 1) under the bundle's own `$id`, so every validation path (tree walk, post-write gate, write verbs) refuses a TC without a pointer. `rcf create tc` and the MCP `rcf_create` tool now require `--test-pointer` / `testPointer` and say so in their usage errors. Making the field required upstream in `rcf-schemas` is the durable home for this; the overlay is a pure tightening and will be dropped when that ships.
|
|
220
|
+
|
|
221
|
+
- **Coverage envelope shape** ([#61](https://github.com/Stravica/rcf-lite/pull/61)). `totals` gains `coveredUnresolved`; each requirement gains `coverageClass` (`covered` / `covered-unresolved` / `uncovered`); each AC gains `unresolvedTestCases`; the envelope gains a top-level `unresolvedTestPointers` list. `ok` is true only when every requirement in scope is covered by resolving test cases.
|
|
222
|
+
|
|
223
|
+
- **`rcf trace --forward` treats FBS as a leaf by default** ([#63](https://github.com/Stravica/rcf-lite/pull/63)). Forward trace was BFS-ing straight through the FBS dependency graph (`rcf trace AC-101-1 --forward` fanned out to dependent FBSs at depths 2-4), conflating intent-chain traversal with impact-blast semantics. Per the AC-402-3 ruling ("implementation tracks the AC"), `computeTrace` now surfaces delivering FBS as cross-link **leaves** rather than walking through them. `computeImpact` alone opts into the fan-out via `expandFbsDependents` - the D7 blast-radius semantics (including "a dependent of an affected FBS") are unchanged and now explicitly asserted. Trace goldens regenerated accordingly.
|
|
224
|
+
|
|
225
|
+
- **`rcf read` reports schema validity honestly instead of hiding it** ([#63](https://github.com/Stravica/rcf-lite/pull/63)). Validity is reported on stderr (stdout stays pure JSON, safe for pipes); a schema-invalid but present document is returned together with its validation errors, exit 0 - `read` is a retrieval verb, not a gate. Use `rcf validate` when you want failure on invalid state.
|
|
226
|
+
|
|
227
|
+
- **`rcf validate` now fails on duplicate ids** ([#55](https://github.com/Stravica/rcf-lite/pull/55)) - exit 3, `duplicateId`, rule `globallyUniqueIds`. Previously a tree with colliding ids validated clean, however the collision got there. The check covers standalone documents, inline acceptance criteria and inline test cases, and treats leading-zero spellings as one id (`REQ-001` and `REQ-0001` both name requirement 1, which the schema pattern `^REQ-\d{3,}$` legitimately permits). Every colliding location produces its own error naming the id and each claiming file, so a CI log identifies the whole collision rather than half of it:
|
|
228
|
+
|
|
229
|
+
```
|
|
230
|
+
[error] duplicateId US-101: Duplicate id AC-101-1: claimed by 2 locations: AC-101-1 in
|
|
231
|
+
rcf/user-stories/us-101.json (acceptanceCriteria[0].id), AC-101-1 in
|
|
232
|
+
rcf/user-stories/us-101.json (acceptanceCriteria[1].id).
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
Detection lives in the walker, not the schema: the schema is right to permit variable-width numeric runs, and it is uniqueness *after normalisation* that is being violated. `rcf validate --json` carries the same issue under `kind: "duplicateId"`.
|
|
236
|
+
|
|
237
|
+
- **`rcf help <subcommand>` and `rcf <subcommand> --help` stay byte-identical** ([#57](https://github.com/Stravica/rcf-lite/pull/57)). The help surface kept a private duplicate of most subcommand help blocks; nine had drifted and every divergence ran the same direction - the `rcf help` path (the discovery path an agent reaches for first) was the stale copy. `rcf help create` was hiding the `cn` kind and all four Code Node options, so a shipped feature was invisible from the help surface. Every subcommand's help now imports from the module's exported `HELP`, and a parity test makes that structural rather than lucky.
|
|
238
|
+
|
|
239
|
+
### Fixed
|
|
240
|
+
|
|
241
|
+
- **Guidance no longer points at unreachable `guidance/*.md` paths** ([#56](https://github.com/Stravica/rcf-lite/pull/56)). The agent-instructions fragment `rcf init` writes, the "Deep guidance" footer on every `rcf build --next` spec bundle, and the `rcf init --no-agent-setup` manual instructions all named bare `guidance/elicitation-playbook.md` / `guidance/build-cycle-playbook.md` paths. Those files exist only inside a clone of this repository, so the instruction was dead on arrival in a consumer project. All of them now name `rcf guidance <topic>`.
|
|
242
|
+
|
|
243
|
+
- **The build-cycle playbook no longer claims the independent verification gate is unbuilt** ([#56](https://github.com/Stravica/rcf-lite/pull/56)). Section 16 described the fresh-context self-review as an "interim stopgap until rcf-verify-lite exists", which stopped being true when `rcf-verify-lite` shipped and `rcf finalise` began running it. The playbook contradicted its own section 7, and the false claim was inside the fragment written into every initialised project's `CLAUDE.md`. The self-review is now positioned as what it actually is: the cheap in-loop check that runs between builds, subordinate to the `rcf finalise` gate rather than a placeholder for it, and never evidence for a `verified` mark. AC-805-4 and its drift test moved with the prose, and the test now fails if either file reacquires the stale claim.
|
|
244
|
+
|
|
245
|
+
### Documentation
|
|
246
|
+
|
|
247
|
+
- **`rcf init` documented as a brownfield-safe entry path** ([#60](https://github.com/Stravica/rcf-lite/pull/60)). Every claim was re-verified against current `main` source and observed at runtime: skips an existing `rcf/` tree untouched, merges `.mcp.json` preserving other servers and unknown keys, refreshes `CLAUDE.md` / `AGENTS.md` inside markers only, never invents the other convention's file. Two sharp edges also documented: the tree guard keys on `rcf/manifest.json` (so an `rcf/` directory without a manifest is treated as a fresh scaffold target), and init reformats `.mcp.json` to two-space indentation (content preserved, whitespace not). No `--dry-run` - the section names its absence and gives the git procedure instead.
|
|
248
|
+
|
|
249
|
+
### Internal
|
|
250
|
+
|
|
251
|
+
- **`rcf validate` + `rcf coverage --strict` now gate CI** ([#64](https://github.com/Stravica/rcf-lite/pull/64)). Both run from `packages/build` as required steps in `ci.yml`, before the suite. From this release on, a stub TC or a new uncovered AC fails CI; the whole 76/76 dogfood coverage state is locked in.
|
|
252
|
+
|
|
253
|
+
- **Dogfood coverage authored end-to-end** ([#62](https://github.com/Stravica/rcf-lite/pull/62), [#63](https://github.com/Stravica/rcf-lite/pull/63)). 76 acceptance criteria audited against the existing test corpus; 24 Test Suites + 76 Test Cases authored through `rcf create ts` / `rcf create tc --test-pointer` (the tool proving itself against itself). Final `rcf coverage --with-code`: `implemented-and-covered=76 implemented-uncovered=0 unimplemented=0`, `covered-unresolved=0`.
|
|
254
|
+
|
|
255
|
+
## [0.4.0] - 2026-07-22
|
|
256
|
+
|
|
257
|
+
Hardens the `verified` state so it can only be reached through the independent ship gate. Two changes close bypasses that let a builder write `verified` without a passing, ship-authoritative `rcf-verify` run, plus one documented contract-field rename. No new features; behaviour and one JSON contract key change, so this is a minor bump under the pre-1.0 breaking-is-minor convention.
|
|
258
|
+
|
|
259
|
+
### Changed
|
|
260
|
+
|
|
261
|
+
- **`rcf build <fbs-id> --mark verified` is now refused** ([#53](https://github.com/Stravica/rcf-lite/pull/53)): the `--mark` ladder caps at `complete`. Previously any forward lifecycle jump was legal, so `--mark verified` promoted `complete → verified` with no verify run at all - a one-flag bypass of the finalise gate's independence guarantee (spec §9). `--mark verified` now exits 4 (the mark-refusal family), writes nothing, and points to `rcf finalise`. `verified` is written only by the finalise gate, or by the sanctioned explicit override `rcf update <fbs-id> --set executionStatus=verified` (unchanged). **Migration:** anywhere you scripted `rcf build <id> --mark verified`, switch to `rcf finalise <id> --url <deploy-url>` (the ship gate) or, for a deliberate manual override with no verify run, `rcf update <id> --set executionStatus=verified`.
|
|
262
|
+
- **`rcf finalise` now gates on ship authority, not just exit code** ([#53](https://github.com/Stravica/rcf-lite/pull/53)): promotion to `verified` previously required only that the spawned `rcf-verify` subprocess exit 0, so a correctness-only pass (e.g. a bare `--profile ci` run) could write `verified`. Promotion now additionally requires the ingested report's `verdictAuthority === 'ship'` (spec §4) - a `deployed`-profile run, or a `ci`/`local-dev` run with `--parity-env`. A passing non-ship run, or an unreadable report on a pass, produces a clean explicit **HOLD** (state unchanged, exit 4), never a silent promotion and never an error. Re-verify of an already-verified item is unchanged.
|
|
263
|
+
- **`completionContract.markVerified` renamed to `completionContract.finalise`** ([#53](https://github.com/Stravica/rcf-lite/pull/53)): the JSON build bundle (`rcf build --format json`) and the MCP `rcf_build` result emit a `completionContract` object. Its `markVerified` key - which carried a `rcf build … --mark verified` command that is now refused - is renamed to `finalise` and carries `rcf finalise <id> --url <deploy-url>`. **This is a breaking change for any consumer that reads `completionContract.markVerified` from the JSON/MCP output** (the MCP `BUILD_OUTPUT_SCHEMA` `required` list changed to match). Read `completionContract.finalise` instead. The Stage-5 markdown runbook and the guidance pack (`build-cycle.md`, `build-cycle-playbook.md`, `getting-started.md`) are reworded to route ship through `rcf finalise`.
|
|
264
|
+
|
|
265
|
+
### Documentation
|
|
266
|
+
|
|
267
|
+
- **README consumability pass** ([#52](https://github.com/Stravica/rcf-lite/pull/52)): the build README was rewritten for a consumer landing on the npm package page cold - what the package is, install, first commands, and where the docs live.
|
|
268
|
+
|
|
269
|
+
## [0.3.0] - 2026-07-22
|
|
270
|
+
|
|
271
|
+
Deploy-aware, runtime-honest build guidance (Tier-1 hardening, REQ-008) plus the `rcf finalise` ship gate that hands the final verdict to an independent `rcf-verify` run. First release published from the `Stravica/rcf-lite` monorepo, and the first release to depend on the extracted `@stravica-ai/rcf-lite-core` package.
|
|
272
|
+
|
|
273
|
+
### Added
|
|
274
|
+
|
|
275
|
+
- **`rcf finalise <fbs-id> --url <deploy-url>` - the finalise gate** ([#50](https://github.com/Stravica/rcf-lite/pull/50)): promotes an FBS from `complete` to `verified` only when an independent `rcf-verify` run against the deployed app passes. `rcf-verify` is spawned as a **fresh OS subprocess** (never imported in-process) under `@stravica-ai/rcf-lite-core`'s isolation env (§7.3), so the verifier agent starts cold with zero build context. Exit code is the gate (0 → promote, non-zero → FBS left unchanged and findings surfaced); findings flow via a chain-node-addressed `--out` report file, not stdout scraping. Install-together posture (§8.3): if `rcf-verify` is absent, `finalise` prompts to install it on an interactive TTY or accepts an explicit `--install-verify` flag off a TTY - it never silently skips the gate and never silently auto-installs.
|
|
276
|
+
|
|
277
|
+
### Changed
|
|
278
|
+
|
|
279
|
+
- **Tier-1 hardening - deploy-aware, runtime-honest build guidance** ([#42](https://github.com/Stravica/rcf-lite/pull/42), REQ-008): closes the persona-programme root cause where the deploy runtime was absent from the tool's elicitation and verification loop. Elicitation now establishes the deploy target early (before any stack is committed), constrains the stack to what the target can host, captures the choice as an ADR, and includes a jargon-free hosting-choice walkthrough with honest account-holder-step isolation. The build cycle makes a working **local preview** the hosting-independent definition-of-done, requires **runtime-provenance labels** on every verified/tested claim (Cloudflare and non-Cloudflare worked examples, aligned with the deployed/ci/local-dev profile model), and adds an interim fresh-context self-review scoped honestly away from the independent gate. `harness-template.md` gains hard fragment RULE 5 (no stack before deploy target), RULE 6 (every build lands a local preview) and RULE 7 (verification claims name their runtime). Guidance, spec (US-801..805, 20 ACs, ADR-006..009, FBS-013/014) and drift-test changes only - no runtime CLI behaviour change.
|
|
280
|
+
|
|
281
|
+
### Repository
|
|
282
|
+
|
|
283
|
+
- **Repo renamed `rcf-build-lite` → `rcf-lite` (2026-07-21).** The GitHub repository was renamed and restructured into a pnpm-workspace monorepo, with this package relocated to `packages/build/`. The **published package name is unchanged** - it remains `@stravica-ai/rcf-build-lite` - and its npm provenance / trusted-publisher binding are preserved. Old `Stravica/rcf-build-lite` URLs redirect to `Stravica/rcf-lite` indefinitely; do not re-create a repo at the old name.
|
|
284
|
+
|
|
285
|
+
### Dependencies
|
|
286
|
+
|
|
287
|
+
- Now depends on **`@stravica-ai/rcf-lite-core`** (first published at `0.1.0` alongside this release) for the shared RCF-chain store, `RcfError` type, MCP protocol shell, and verifier isolation env. Previously-bundled internals were extracted into that package; consumers install it transitively.
|
|
288
|
+
|
|
289
|
+
## [0.2.1] - 2026-07-18
|
|
290
|
+
|
|
291
|
+
`rcf init` UX pass and agent-guidance hardening from the v0.2.0 manual-test review. No schema, runtime-API or dependency changes.
|
|
292
|
+
|
|
293
|
+
### Changed
|
|
294
|
+
|
|
295
|
+
- **`rcf init` is a bootstrap, not an elicitation session** ([#38](https://github.com/Stravica/rcf-build-lite/pull/38)): interactive init now prompts only for the project name and seeds a fully-placeholder tree identical to the non-interactive path (the early requirement-title, story-title and problem-statement prompts are dropped; the agent elicits them once the session starts). Completion output is a high-level summary - document chain / MCP server / agent instructions - with a `Next: start your agent session` step, replacing the per-file manifest.
|
|
296
|
+
- **Fresh-repo agent setup writes both `CLAUDE.md` and `AGENTS.md`** ([#38](https://github.com/Stravica/rcf-build-lite/pull/38)): vendor-neutral by default. Existing-file routing is unchanged (an existing `CLAUDE.md`, or an existing `AGENTS.md` when no `CLAUDE.md`, is refreshed in place; the other convention's file is not invented), and the marked-block idempotency / init-re-run-exits-0 contract is preserved.
|
|
297
|
+
- **Agent guidance pack hardened** ([#39](https://github.com/Stravica/rcf-build-lite/pull/39)): the build-cycle playbook gains whole-queue orchestration (drive `rcf build --next` to `Queue complete`, one write worker at a time, a docs-review gate and a handover protocol), evidence-first PR authoring, and bug-triage-via-acceptance-criterion-first; the elicitation playbook gains scenario-coverage criteria, a thin-vs-adequate AC example, and an elicitation-integrity section. Guidance and docs prose only - no `src/` behaviour change.
|
|
298
|
+
|
|
299
|
+
## [0.2.0] - 2026-07-10
|
|
300
|
+
|
|
301
|
+
The spec-to-code bridge (X2): `CN-*` Code Nodes make source code a first-class node in the same graph the spec chain already lives in, so `rcf validate` catches a dangling spec-to-code link the same way it catches a dangling spec-to-spec one.
|
|
302
|
+
|
|
303
|
+
### Added
|
|
304
|
+
|
|
305
|
+
- **Code Node document kind** (`CN-*`, `rcf/code-nodes/`), the 11th RCF document type, delivered via [`@stravica-ai/rcf-schemas@0.3.1`](https://github.com/Stravica/rcf-schemas). Identity is a working-tree path, optionally `#symbol`-suffixed; granularity (file vs symbol) is derived, never stored.
|
|
306
|
+
- **Staleness detection**: `rcf validate` fails (exit 3, `staleCode`) when a Code Node's path or symbol no longer resolves against the working tree; `--no-code` skips the pass.
|
|
307
|
+
- **Queries**: `rcf trace <path>` and `rcf trace <path>#symbol` walk backward from source to the requirements it serves; `--to-code` on `trace` / `impact` extends the forward fan-out into implementing and dependent Code Nodes; a Code Node id is a uniform pivot like any other. `rcf view` renders Code Nodes as a distinct cosmetic class.
|
|
308
|
+
- **CRUD**: `rcf create/update/delete cn`, mirroring the existing writer patterns; delete refused while another Code Node depends on it; post-write validation as with every other kind. `--derive-deps` optionally shells out to `dependency-cruiser` for file-level dependency auto-derivation - a dev-time-only assist, never a runtime dependency.
|
|
309
|
+
- **The mark-complete gate**: `rcf build --mark complete` refuses (exit 3, `missingCodeNodes`) when any acceptance criterion of the completed build spec carries no Code Node; `--no-code-nodes` declares a genuinely no-code (docs-only, config-only) spec, recorded on the FBS.
|
|
310
|
+
- **`rcf coverage --with-code`**: informational four-class code axis per acceptance criterion (`implemented-and-covered` / `implemented-uncovered` / `unimplemented` / `CN-orphaned`), never blocking.
|
|
311
|
+
- **MCP adapter**: `rcf_create` accepts kind `cn`; `rcf_trace` / `rcf_impact` gain `toCode` and path-mode; `rcf_coverage` gains `withCode`; `rcf_validate` gains `noCode`.
|
|
312
|
+
- **Guidance pack + build bundle**: the five-stage runbook and the build-cycle guidance now direct CN authoring during Stage 2 (Build) and name the Stage 5 gate.
|
|
313
|
+
- **Docs**: `docs/code-nodes.md` - the concept, authoring guidance, and an explicit honest-limits section (semantic drift, symbol rot, namesake false-cleans).
|
|
314
|
+
- **Full-tree dogfood**: every acceptance criterion in this repository's own tree carries a Code Node (29 nodes; the REQ-007 validation chain re-authored through the real CRUD verbs first, then extended tree-wide).
|
|
315
|
+
|
|
316
|
+
### Changed
|
|
317
|
+
|
|
318
|
+
- `@stravica-ai/rcf-schemas` dependency bumped `^0.2.1` -> `^0.3.1`.
|
|
319
|
+
|
|
320
|
+
## [0.1.0] - 2026-07-08
|
|
321
|
+
|
|
322
|
+
First public release.
|
|
323
|
+
|
|
324
|
+
### Added
|
|
325
|
+
|
|
326
|
+
- Schema-validated document chain: every RCF document type (PRD, requirements, user stories, acceptance criteria, TAD, build sequence) lives as JSON in your repository, validated against the [`@stravica-ai/rcf-schemas`](https://github.com/Stravica/rcf-schemas) contract.
|
|
327
|
+
- Dogfooded `rcf/` tree: this repository's own PRD, requirements, stories, acceptance criteria, TAD and build queue, built and maintained with the tool itself.
|
|
328
|
+
- `rcf view`: live HTML rendering of the full document graph in the browser.
|
|
329
|
+
- Unified `rcf` CLI with full create, read, update and delete coverage across the document chain.
|
|
330
|
+
- Traceability queries: coverage, trace forward and back through the chain, and impact analysis from any node.
|
|
331
|
+
- `rcf build`: SDD adapter that turns the build queue into staged, executable spec bundles.
|
|
332
|
+
- `rcf mcp`: MCP server exposing the toolset to coding agents, backed by the agent guidance pack in `guidance/`.
|
|
333
|
+
- Documentation set: install, getting started, how it works, and why it exists, under `docs/`.
|
|
334
|
+
|
|
335
|
+
[0.7.0]: https://github.com/Stravica/rcf-lite/releases/tag/build-v0.7.0
|
|
336
|
+
[0.6.0]: https://github.com/Stravica/rcf-lite/releases/tag/build-v0.6.0
|
|
337
|
+
[0.5.2]: https://github.com/Stravica/rcf-lite/releases/tag/build-v0.5.2
|
|
338
|
+
[0.5.1]: https://github.com/Stravica/rcf-lite/releases/tag/build-v0.5.1
|
|
339
|
+
[0.5.0]: https://github.com/Stravica/rcf-lite/releases/tag/build-v0.5.0
|
|
340
|
+
[0.4.0]: https://github.com/Stravica/rcf-lite/releases/tag/build-v0.4.0
|
|
341
|
+
[0.3.0]: https://github.com/Stravica/rcf-lite/releases/tag/v0.3.0
|
|
342
|
+
[0.2.1]: https://github.com/Stravica/rcf-build-lite/releases/tag/v0.2.1
|
|
343
|
+
[0.2.0]: https://github.com/Stravica/rcf-build-lite/releases/tag/v0.2.0
|
|
344
|
+
[0.1.0]: https://github.com/Stravica/rcf-build-lite/releases/tag/v0.1.0
|