Changelog
RCF Lite changelog: release notes
Every release entry is kept here, newest first, with the technical changes and any action needed.
Expect a fast cadence: the package is 0.x, the surface still moves between minors, and a breaking change is signalled by a minor bump. This page is the canonical human record of those releases; the same record is published machine-readably at /docs/rcf/releases.json, which is what rcf version --check reads. To see whether you are behind right now:
rcf version --check
Each entry below says what changed and, more usefully, what it means for you. The package's own CHANGELOG carries the engineering-grade detail.
0.31.0, 5 October 2026
0.31.0 ships three themes from rcf-lite PRs 291, 292 and 293: a standalone theme control and an AA contrast pass on the tree viewer, the remaining DEFINE step 3 rulings (R1 to R8 and R13 land here; R9 to R12 shipped in 0.30.0 and were confirmed on the same pass, so the full R1 to R13 set is now in), and idempotent --id write-backs on rcf define create and rcf define ledger <name> add.
Breaking under the pre-1.0 convention, for three reasons: rcf define create <kind> --id and rcf define ledger <name> add --id now exit 3 when the id exists with different content; the readiness envelope for a scope-empty stage with a failing tree-wide check is failing (or acknowledged when acked at the current hash on a warn-with-ack stage), not notApplicable; and shapes:draftSettled is tree-wide, so a [draft] marker outside the D3 scope now fails the check. The managed agent-instructions block did not change (minAgentAction null), so no agent re-init is needed.
Viewer: standalone theme control (ADR-4137). A three-state Light, Dark and Auto control is server-rendered in the shell header's tools group, to the right of the FIND button. It is keyboard-operable (a role="group" of three buttons carrying aria-pressed) and applies the chosen theme live through data-theme on <html>. Outside embed mode the boot order is: an explicit ?theme= query parameter wins; then a stored value under localStorage['rcf-view:v1:theme']; then auto, where prefers-color-scheme decides. The rcf-view-theme postMessage from an embedding host still applies live in both modes and never writes the stored key. ADR-4137 records the one deliberate deviation from the viewer design's "storing nothing" line and scopes it to standalone use: under embed=1 the control is absent from the DOM and the key is never read or written. The key sits under the shared rcf-view:v1: namespace, so the storage namespace lint stays green.
Viewer: WCAG 2.1 AA contrast audit and the fixes it found. A new static-analysis test parses the viewer stylesheet, resolves the --sv-* token blocks for the light and dark themes, pairs every rule that sets a text colour with every reachable background across the state variants (default, hover, focus, focus-visible, active, aria-pressed, aria-selected, .is-active, disabled), and asserts 4.5:1 for text and 3:1 for large text and non-text UI boundaries in both themes. Pairs it cannot resolve statically are composited against the three surface tokens and recorded as approximate. A change that drops any pair below AA fails the suite with the selector, state, theme, both colours, the ratio and the threshold named. The audit found and fixed: the FIND button's hover and focus fell back to a hard-coded light grey because --sv-surface-hover was never declared, which painted dark ink on light grey in dark mode (now --sv-active with the --sv-control border and the --sv-focus outline); the same undeclared-token fallback on the lookup modal's row hover, active row and reload button (now --sv-active) and on its input (now --sv-surface with a --sv-control border); three muted labels in the footer and Product Map at 3.51:1 in light (now --sv-muted, 5.60:1 light and 7.78:1 dark); and two state borders moved from --sv-border to --sv-control. No new tokens were added.
R1: ledger add is idempotent by id. rcf define ledger <name> add (brief, decisions, concerns, probes) takes an optional --id <n> that a harness carries on a replayed turn. A replay whose id already exists with identical content exits 0 and prints <ledger>-ledger: unchanged <id> (with --json, {"status":"unchanged","id":<n>,"entry":{...}}). A replay whose id exists with different content refuses with exit 3 and names the id and the differing field keys. Identity is carried by the id: a replay without --id still mints the next id, so the harness has to thread --id back. brief add --id together with --from is refused as a usage error, because --from mints several entries.
R1 extended to rcf define create. rcf define create <kind> --id <id> is idempotent by id for every kind (req, us, tac, adr, fbs, ts, the inline ac and tc, and cn) under the same rule. A same-id replay with identical content exits 0, prints <id>: unchanged (<filePath>) (the inline kinds name the parent US or TS file) and writes nothing; different content refuses with exit 3, names the differing fields and writes nothing. That stdout line is the whole output: rcf define create has no --json flag and --quiet suppresses the line. Without --id, a tc whose derived slug collides still refuses with exit 2, and a schema-invalid existing document still refuses unconditionally. The comparison ignores writer- and classifier-owned fields (createdAt, updatedAt and the shapeClassification block the requirement classifier stamps), so a verbatim replay is a no-op; lifecycle fields another verb has since changed, such as a test case status or an FBS executionStatus, count as content. The --id help text and the rcf_create MCP tool's id description both state the rule.
R2: shapes:draftSettled is tree-wide. A [draft] marker on any TAC purpose, any interface description or any core-entity description fails the check regardless of the D3 scope, and the check's over label moves from delta to tree.
R5, R7 and R13: tree-wide checks run before any scope short-circuit (ADR-4138). One shared helper now governs every tree-wide check: shapes:draftSettled and shapes:entityJoin on D3, skeleton:standardsCited and skeleton:deployAdr on D2, and crosscut:securityArchitecture and crosscut:operationalConcerns on D5. A narrowed D3 scope that excludes every TAC and shaped requirement still reports an unjoined core entity or an unsettled [draft]; a narrowed D2 scope still reports an uncited standards pack or a missing (or doubled) Deploy ADR; a narrowed D5 scope still reports an empty TAD.securityArchitecture when any requirement anywhere has shape auth or httpApi, and an empty TAD.operationalConcerns when any acceptance criterion anywhere carries [deployed]. The helper delegates the warn-with-ack fold to the same code that owns the ack-at-current-hash rule, so the envelope is failing, or acknowledged on a warn-with-ack stage acked at the current hash, with no reason field. The notApplicable result the viewer and CLI pills read is unchanged when nothing tree-wide fails. Delta-only checks (shapes:templateMarkers, shapes:pathsResolve, stories:closedSets, stories:ownerRefResolves) and D4 and D6 are unaffected.
R6: bare repo names resolve as paths. shapes:pathsResolve now checks a token such as path: Dockerfile. The whitelist covers Dockerfile, Containerfile, Makefile, LICENSE, Procfile, Justfile, Rakefile, Gemfile and CODEOWNERS; everything else still needs a slash or an extension to count as a path.
R8: applied satisfies skeleton:standardsCited. A standards:<pack> concern-ledger entry with disposition applied now satisfies the check alongside waived and a citation. The check's question reads "Every registered standards pack is cited, applied or waived".
R3 and R4: wording only. The rcf_define_draft_shapes prompt now says the engineer drafts shapes in parallel with the product-owner loop and reconciles when Intent completes, rather than waiting for intent-complete; nothing in the draft pass changes the product-owner question set. ADR-4131's prose now matches the code: stagePolicy() returns warnWithAck for D3, D5 and D6. Neither change moved the managed block hash.
PR 292 follow-ups. A failing D3 no longer prints the stage's notApplicable reason after "failing" in the CLI text report, and the D3 notApplicable reason drops its stale "and no [draft] core entity in scope" trailer now that draft-settled is tree-wide. The R2 test was rewritten so it actually exercises a [draft] outside the narrowed scope, and ADR-4138's prose was corrected to the shipped helper signature and envelope.
For embedders (wespa reverse-proxy). Nothing changes under embed=1 and no new route is added. renderPage({ embed: true }) omits the theme-control markup; the production server does not pass embed, so the viewer's boot script strips the control from the DOM when ?embed=1 is on the URL. The rcf-view:v1:theme key is never read or written under embed, and the rcf-view-theme postMessage contract is unchanged. The 0.29.0 allow-list for /page-init.js and /index.json remains the requirement.
What this means for you. A project on 0.30.0 upgrades with npm install rcf-lite@0.31.0; no rcf init rerun is needed. If your harness or CI passes --id to rcf define create, an existing id with different content now exits 3 rather than 2, and an identical replay now exits 0 instead of refusing. If it passes --id to rcf define ledger <name> add, treat exit 3 as a hard refusal and use the update verb to change content at a known id; a harness that replays the exact prior invocation without --id still mints a duplicate, as before. Anything that reads rcf define readiness --json should expect failing (or acknowledged) where a scope-empty stage used to report notApplicable if a tree-wide check fails, and a [draft] marker anywhere in the tree now fails D3. Open rcf audit view and the theme control sits in the header next to FIND.
0.30.0, 3 October 2026
0.30.0 lands the DEFINE step 3 gates bite in one release. The Remi path (PRs 1 to 3) shipped in 0.29.0. This release carries the gates bite (PRs 5, 6 and 7), the bundle refuse / override / skip plus validate findings plus NV-DL ruleset flip (PR 8), and the R11 ownerRef / deliveredBy grammar widening plus blueprint recount plus admissibility wrap plus test tightening (PR 9). A follow-up fix lands ruling R12 (the NV-DL-ADM-02 override channel is freeze.override only).
Spec note: the DEFINE step 3 spec section 16 and prose name certain D2 behaviours "0.30.0" that in fact shipped in 0.29.0 (the skeleton:resolvedBy closed grammar, the rcf define ledger <name> update <id> subverb and the resolvedBy closed grammar). The spec will be amended on the next pass.
Breaking under the pre-1.0 convention: rcf define readiness --check, rcf build bundle --next and rcf define validate all change exit behaviour on verbs consumers run in CI. The migration section at the foot of this entry is the authoritative pointer; the "For consumers (upgrading)" summary in the package CHANGELOG carries the exact flags and override channels.
PR 5: D3 bite. shapes:templateMarkers enforces per-kind marker presence on interfaces[].description (recordShape needs fields:, httpRoute needs method, path, request, response and errors, fixture needs instances:, event needs payload:, cliCommand needs usage:, uiRoute needs path, port needs protocol, fileFormat needs format:, other needs a note); drafts included. shapes:entityJoin fails every coreEntities[].name not named by exactly one recordShape tree-wide. shapes:pathsResolve fails any path:-like token on an interface description that does not resolve on disk (the readiness compute collects candidates; the CLI and viewer tab pass resolvedPaths in the stage context). ackable(stage) returns true for D3, D5 and D6 and false otherwise; --check exits 4 unacked and 0 at the current hash.
PR 6: D4 closed sets and ownerRef as findings, D5 concern catalogue, standards citation. stories:closedSets fails an acceptance criterion whose description carries an enumeration cue ("one of", "any of", "the following", "types of", "status is") without an inline bracketed list or an ownerRef. stories:ownerRefResolves fails every ownerRef { tacId, field } that does not resolve to interfaces[<name>] on that TAC. The eight-concern catalogue ships keyed by requirement shape; crosscut:catalogue enumerates every applicable pair per in-scope requirement against the concern ledger. skeleton:standardsCited fails every registered standards pack neither cited in a requirement rationale or an ADR nor waived by a concern-ledger entry with key standards:<pack>. D5 is ackable through the --check crosscut fold.
PR 7: D6 consistency scans, probe seam, --litmus and rcf_define_litmus. Four D6 scans: consistency:contradictions (two acceptance criteria on one story sharing a when clause with a negated then), consistency:unsatisfiable (a then naming a field no recordShape fields: defines; a field in a [draft] recordShape counts as defined), consistency:duplicates (identical acceptance-criterion descriptions across stories) and consistency:orphanInterfaces (no acceptance-criterion ownerRef and no requirement deliveredBy reaches an interface). computeReadiness(tree, { probeRunner }) accepts an injectable runner and findings land as probe-ledger entries; no runner ships in 0.30.0, so consumers wire their own if they want D6 probes to execute. --litmus <n> on readiness and freeze requires n distinct readers to have recorded a litmus reading at the current litmus hash (tree.litmusHash, the tree hash computed with the probes ledger excluded per R9 amendment 2026-10-03); readiness --json prints the litmus hash. The rcf_define_litmus prompt tells the harness to spawn n fresh-context readers and land their readings.
PR 8: bundle refuse, override and skip; validate findings; NV-DL enforced. rcf build bundle --next refuses on an unfrozen tree with exit 4 (the message points at rcf define readiness and the --override "<reason>" channel), accepts --override "<reason>" which writes freeze.override { reason, by, at } through applyOverrideToFreezeRecord and proceeds, skips re-execute specs impacted by the delta with the reason on stderr and hands out the next unimpacted spec; when every actionable spec is impacted and no override is given the verb exits 4 (NV-DL-ADM-01 and NV-DL-ADM-05). rcf define validate grows four findings: an interface kind outside the closed vocabulary, a bracketed acceptance-criterion class prefix outside the five known classes, a tacIds naming a non-TAC, and an unresolving ownerRef or object-form deliveredBy. Absence of a class marker is not a validate finding (D4 reports absence as the floor). The ruleset gains NV-DL-ADM-01 through 05 with refuseByDefault: true and overrideChannel: recordedInChain. The readiness compute still runs and prints under NV-DL refusal (readiness stays informational on the compute).
PR 9: R11 ownerRef and deliveredBy grammar, blueprint recount, admissibility wrap, test tightening. resolveOwnerRefField(doc, field) widens the D4 stories:ownerRefResolves check and the rcf define validate defineValidate:ownerRefResolves and defineValidate:deliveredByResolves findings beyond interfaces[<name>] to every bracket-grammar path on the owning TAC or ADR: interfaces[<name>], responsibilities[<n>], dependencies[<name>], alternativesConsidered[<n>], and a bare schema field name (purpose, internalStructure, decision, context, consequences, name, tradeoffs, notes, description, title, and the arrays themselves). Dotted grammar is refused; validate names the dotted field so the author can rewrite. The ADR branch of ownerRef { adrId, field } now resolves (pre-R11 code recognised only tacId). rcf define validate now checks the object form of deliveredBy ({ tacId | adrId, field }), which was silently skipped before PR 9. freeze.override.by is resolved by resolveOverrideBy({ projectRoot }) with the preference order git config user.email, GITHUB_ACTOR, USER, USERNAME, literal operator; each failing arm falls through silently to the next. The admissibility wrap now cites NV-DL-ADM-02 (failing D4), NV-DL-ADM-03 (failing D3) and NV-DL-ADM-04 (non-empty validate errors) alongside the NV-BL rules. The sweep script packages/rcf-lite/scripts/blueprint-r11-sweep.mjs rewrites every dotted interfaces.<name>, responsibilities.<key>, dependencies.<name> and decision.<key> to bracket grammar across the shipped blueprint corpus, then collapses every dead bracket name to its bare parent field or drops the ownerRef or deliveredBy where even the parent is empty; the script is idempotent and tally-reports per blueprint. The shipped blueprints are clean under R11 after the sweep: 31 dotted-to-bracket rewrites across 16 blueprints, 493 dead-bracket collapses, 12 drops where the parent was empty across the full shelf of 39 blueprints; rcf define validate reports zero findings and D4 reports zero stories:ownerRefResolves failures on direct contribution-tree recount.
R12 fix: NV-DL-ADM-02 override channel wording. The PR 9 admissibility wrap, REQ-179 and the ruleset notes named --ack <gate>=<reason> as the override channel for NV-DL-ADM-02. ADM-02 maps to D4 (the stories floor), and decision 9 keeps ackable to D3, D5 and D6 only, so D4 cannot be masked by an ack. The only recorded-in-chain override channel for ADM-02 is freeze.override written by rcf build bundle --next --override "<reason>"; the normal path is to fix the failing D4 findings. ADM-03 (D3) keeps --ack; ADM-04 keeps the chain-document correction committed to git.
Changed. Eighteen TAC files in the dogfood tree are remapped off legacy interface kinds (64 interfaces across TAC-001 to 008, TAC-4101 to 4108, TAC-4129 and TAC-4134 carried pre-DEFINE-era kind labels). 284 shipped blueprint contribution files are remapped off legacy interface kinds and dotted ownerRef grammar: 40 blueprints under blueprints/ carried pre-DEFINE-era interface kinds (47 distinct labels across 330 interfaces) and 252 ownerRefs written in the interfaces.<name> form. The mapping (function, mcpTool, prompt, constant, moduleApi, interface to other; command to cliCommand; type to recordShape; artifact or artefact to fileFormat; everything else to other) is applied mechanically and the legacy label is kept in the interface description for provenance. rcf define validate is now clean on the dogfood tree and on the application-onboarding-tour blueprint applied to a fresh project.
Known gaps and parked rulings. Write-back idempotency of the add and create verbs; D3 draft scope tree-wide vs delta; the stagePolicy label drift, D3 notApplicable ordering and Dockerfile-token path findings from the PR 5 review; skeleton:standardsCited inside the D2 scope early-return and a standards:<pack> ledger entry with disposition applied counting as a waiver from the PR 6 review; anything PR 7's review parked (the R9 litmus-hash amendment landed, other PR 7 parked rulings carried forward). Decision 9 and decision 10 are binding: --ack remains the recorded override for D3, D5 and D6; validate reports no finding for a missing acceptance-criterion class marker.
For embedders (wespa reverse-proxy). No new routes relative to 0.29.0; the viewer surface is unchanged in 0.30.0. The 0.29.0 allow-list for /page-init.js and /index.json remains the requirement.
What this means for you. A project on 0.29.0 upgrades with npm install rcf-lite@0.30.0. Three verbs that run in CI change exit behaviour: rcf define readiness --check now bites on D3, D5 and D6 (clear with --ack <gate>=<reason>); rcf build bundle --next now refuses on an unfrozen tree (clear with --override "<reason>"); rcf define validate grows four new finding kinds and exits 3 on any of them. Migrate any legacy interface kinds through the remap table before the first validate run and rewrite any dotted ownerRef or deliveredBy fields to the bracket grammar or the bare schema field. The upgrade is flagged breaking under the pre-1.0 breaking-is-minor convention; existing chains revalidate once the migration is applied.
Migrating existing trees. Consumers see one new failure class on upgrade. On a fresh project with an existing tree, rcf define validate now exits 3 under PR 8 for any of: an interface kind outside the closed vocabulary (recordShape, httpRoute, event, cliCommand, uiRoute, port, fileFormat, fixture, other); a bracketed acceptance-criterion class prefix outside the five known classes ([happy], [edge], [failure], [must-not], [non-functional]); a tacIds field naming a non-TAC; or an unresolving ownerRef or object-form deliveredBy. Mechanical remap table (safe conservative default): legacy function, mcpTool, prompt, constant, moduleApi and interface go to other; command goes to cliCommand; type goes to recordShape; artifact and artefact go to fileFormat; anything else goes to other. Keep the original kind in the interface description for provenance. For ownerRef and object-form deliveredBy, bracket grammar is the only accepted form: rewrite interfaces.<name> to interfaces[<name>], responsibilities.<key> to responsibilities[<key>], dependencies.<name> to dependencies[<name>], and decision.<key> to the bare field decision. R11 broadens resolution so a bracket path or bare schema field name resolves when it exists on the owning document. Any ownerRef that still resolves to nothing can be collapsed to its bare parent field (which does resolve while the owning doc carries a non-empty value under that key) or dropped (the walker treats ownerRef as optional). rcf define validate now checks the object form of deliveredBy under the same R11 grammar; deliveredBy without a field resolves on the owner's presence alone. freeze.override.by is written from the preference order git config user.email, GITHUB_ACTOR, USER, USERNAME, literal operator; CI runners that set GITHUB_ACTOR get the actor identity on an unconfigured git. For NV-DL-ADM, override channels differ by rule: for ADM-03 the channel is --ack <gate>=<reason> recorded on freeze.gates at the current tree hash (D3 is ackable); for ADM-02 the channel is freeze.override only (D4 is not ackable); for ADM-04 the override is a chain-document correction committed to git. The sweep script at packages/rcf-lite/scripts/blueprint-r11-sweep.mjs can be run on a consumer tree with --dry-run to see what would change before any write; the script is idempotent either way.
0.29.0, 3 October 2026
0.29.0 lands three bodies of work in one release: the tree viewer UI refresh train (nine PRs), the DEFINE readiness persona split, and the first three PRs of the DEFINE step 3 product-owner elicitation train.
Tree viewer, rebuilt. The viewer shell is new: a compact header (icon mark, product block, sticky tabstrip, tools well) and a one-line footer carrying version, docs links and a live-update pill. The full Stravica brand token set (--sv-*) lands under :root[data-theme="light"] and :root[data-theme="dark"] with a prefers-color-scheme fallback; the pre-refresh --colour-* names are kept as aliases so doc-renderer, Mermaid and Product Map rules get dark theme for free. theme=light|dark|auto and embed=1 on / plus a same-origin postMessage({ type: "rcf-view-theme", theme }) listener wire the embed contract. A new hash router (#tab=&sub=&entity=) carries state in and out of every tab; bare #<id> and #entity=<id> keep working. Assets and streams are referenced relatively (./style.css, ./mermaid.min.js, ./page-init.js, ./live-client.js, ./events, ./scope.json, ./product-map/<group>, ./index.json) so the viewer embeds under a reverse proxy without rewriting URLs. Six shared component helpers under src/view/components/ (DocRow, FilterBar, Badge, EmptyState, Toast, SubTabStrip) back every tab cutover.
Requirements, Architecture, Build. The Requirements tab ships a FilterBar (text, Area, Priority, Status, Needs-work toggle), Expand/Collapse all, a live count, and per-REQ DocRows with nested per-US DocRows carrying slice diagrams and the full user story body as collapsed <details> so first-paint stays cheap; the Needs-work set is sourced from model.readiness.levels.intentComplete.blockedBy filtered to engineer-plain reasons (the viewer never re-runs gates). The former Overview tab is renamed PRD (label-only; the data-tab="overview" identifier and id="tab-overview" are preserved so every existing #tab-overview hash link still resolves); it collapses the five lists into <details> with count badges, drops the 109 inline requirement links, and mounts a shared EntitySelector below the article with a type-ahead jump input and 21 area chips. The Architecture tab renders six TAD sections (systemOverview, architecturePrinciples, integrationArchitecture, operationalConcerns, dataArchitecture, securityArchitecture) as closed DocRows with a one-line preview; absent sections keep their heading and name the exact authoring command. TAC and ADR panels each carry their own FilterBar plus DocRow list, with interface and dependency count badges on TAC rows and a status pill on ADR rows. The Build tab ships a SubTabStrip (Specs | DAG) and a BuildStats card with six totals (items, verified, complete, in progress, not started, buildable now). The Specs sub-tab replaces the pre-0.29 "FBS slots" ordered list and the "Test suites" section (both gone); suites stay reachable via AC links and the new ID lookup. The DAG sub-tab lands DagCanvas, DagInspector and DagToolbar: depth-by-dependsOnFbsIds columns, buildOrder rows, a node-count critical path, a hidden unconnected lane with a visible count, click-to-highlight closure (upstream in link colour, downstream in warning, rest dimmed) and #tab=build&sub=dag&entity=FBS-<n> deep links.
ID lookup and the embedding proof. The viewer serves ./index.json built from the live tree on every rewalk, one row per document id plus one per AC, carrying { id, kind, title, snippet, parent, tab }. A SearchButton sits beside the tabstrip and a LookupModal mounts outside #rcf-live-content (so an SSE innerHTML swap cannot blow it away); Cmd/Ctrl+F opens the modal from any tab, Cmd/Ctrl+Shift+F stays the browser's in-page find. Type-ahead ranks id matches first (exact > prefix > contains), then every query word must match title or snippet, title above snippet; a single character searches ids only; 20 results, matches marked. The index refreshes when the next SSE tree-update event lands. Embedding is proven by a same-origin test-host fixture (src/view/test-host/) and routes GET /test-host.html and GET /test-host.js served ONLY behind --test-host (CLI) or RCF_VIEW_TEST_HOST=1 (env), 404 by default so wespa's reverse-proxy allow-list is unaffected. Three in-suite guards pin the contract: framing headers absent (no X-Frame-Options, no CSP that blocks framing), zero target="_top" across every served response, and every src/view storage key under the rcf-view:v1: namespace.
Readiness for product owners. The Readiness tab moves to tab one of the review surface and is rendered by a new src/view/readiness.js module. The PO layer carries two equal-height VerdictCards (one per level, muted chain term on both), QuestionCards grouped by source span, a Requirements-that-still-need-work table, and a "For engineers" DocRow at the foot that collapses the pre-0.29 engineer rendering (never removed from the DOM in any register). The readiness phrasebook ships now; a feature-detected adapter consumes DEFINE step 3 PR 2's computeQuestions output on the real path and falls back to the blockers path with phrasebook asks when it is absent, so the two sources render identical labels on the dogfood tree.
DEFINE readiness persona split. Every entry in stages[].checks[] carries persona (productOwner | engineer) and a one-sentence question heading, declared in CHECK_PERSONA and CHECK_QUESTION maps in src/query/gates.js. skeleton:reqFields splits into skeleton:reqIntent (PO: description without TODO plus domain) and skeleton:reqShape (engineer: shape classification), each evaluating every REQ independently. decisions:allAnswered splits into decisions:wellFormed (PO) and decisions:allAnswered (engineer). A new D3 check shapes:draftSettled fails any interface whose description starts with [draft]. computeReadiness folds levels.intentComplete, levels.readyToBuild, personas.productOwner.blockers and personas.engineer.blockers on every read; a new helper formatVerdictLines(result) builds the two verdict strings. rcf define readiness gains --level intent|build and --persona productOwner|engineer: --level intent exits 4 iff levels.intentComplete.ok is false, --level build exits 4 iff levels.readyToBuild.ok is false, and --persona is a display filter only (ignored under --json). The text report prints both verdict lines at the top, then groups blockers into a Product owner: N question(s) section and an Engineer: N check(s) blocking section, ordered by the profile.md register.
DEFINE step 3 PR 1: intake into the brief ledger. rcf define ledger brief add grows --from <statement-file>, --scan / --no-scan, --findings <path>, --dry-run and --json; the parser recognises [kind] and (source: ...) text markers (with --kind and --source defaults) and promotes ? / TBC / TBD / Open: / Question: to openQuestion. A new rcf define ledger <name> update <id> subverb lands on every ledger with the add-side validation; brief --resolved-by validates the closed pointer grammar (REQ-nnn, TAD.entity:<name>, PRD.user:<name>, TAD.system:<name>, TAC-nnnn, omitted:<reason>) before any write.
DEFINE step 3 PR 2: rcf define questions, three MCP tools, two argument-free prompts. rcf define questions turns every failing product-owner check into one plain question carrying its exact write-back (real create req; define update <REQ-id> --set description=... --set domain=...; ledger brief update ... --resolved-by <REQ-id> for a new REQ; real create us --parent --title, define update <US-id> --json --set story='{...}' and create ac --parent --description "[happy] ..." for a new US; decisions add ...; ledger brief resolve <N> --answer "decision <id>" for brief:openQuestions). Three new MCP tools expose the same compute: rcf_define_questions, rcf_define_readiness, rcf_define_ledger; two new argument-free prompts (rcf_define_intent, rcf_define_intake) steer the harness through the loop. The question extractor reads the full readiness.stages[].checks[].failing[] so a check with 25 failing items yields 25 questions.
DEFINE step 3 PR 3: [draft] shapes, DISCOVERY prototypes doctrine, two more prompts. parseInterfaceDraft becomes a thin wrapper over a shared hasDraftMarker; two sibling readers parseTacPurposeDraft and parseCoreEntityDraft cover the new homes. checkD3Shapes enumerates all three draft homes and emits shapes:draftSettled findings. guidance/discovery-prototypes.md lands the doctrine (prototype as elicitation instrument; outputs as prototype:<name>:<observation> statements; code burned by a single constraint; salvage by re-derivation only); guidance/discover-prototype.md wraps it as the argument-free rcf_discover_prototype prompt; guidance/define-draft-shapes.md lands the argument-free rcf_define_draft_shapes prompt. The managed agent-instructions block gains the "Prototypes in DISCOVERY (ADR-4132)" rule beside the existing "Prototype rule".
Changed. The D2 skeleton:resolvedBy check tightens to the closed pointer grammar (this behaviour was previously named "0.30.0" in the DEFINE step 3 spec section 16 and now ships at 0.29.0). The 0.28.4 title-hit fallback (a brief statement with resolvedBy left as free-form title text was quietly accepted if the title matched any downstream document) is dropped. A pointer that does not parse against the closed grammar now fails skeleton:resolvedBy on D2. Operators with brief ledgers written against 0.28.4 must rewrite non-conforming resolvedBy values; rcf define ledger brief update <id> --resolved-by <pointer> validates before write. The managed agent-instructions block is regenerated by PR 2 and PR 3 and the block hash changes.
Removed. The Build tab's pre-0.29 "FBS slots" ordered list and the "Test suites" section are gone. The Specs sub-tab replaces both. Consumers that embedded a deep link into the old list need to update to #tab=build&sub=specs&entity=FBS-<n> or #tab=build&sub=dag&entity=FBS-<n>.
Fixed. checkD2Skeleton now reads tad.dataArchitecture.dataStores and tad.dataArchitecture.coreEntities instead of the top-level paths that slice-2 drifted onto, so a valid tree carrying a persistence REQ no longer trips skeleton:tadPersistence. A fresh rcf init tree now satisfies the review-surface marker without operator edits: IDENTITY_TEMPLATE carries a ## Surface section between ## Register and ## Project-scoped notes, with a bare prDiff line as the default; checkD1Brief's profile:surface check now passes on a clean post-init tree.
For embedders (wespa reverse-proxy). Two new relative routes ship: GET /page-init.js (viewer PR 1) and GET /index.json (viewer PR 7). Both must be allow-listed on the wespa reverse-proxy for /rcf-viewer/* before the version pin bump, or the proxy returns 404 for /rcf-viewer/page-init.js (losing tab wiring, Mermaid lazy render, product-map interactivity, theme boot, embed stamp, origin-checked postMessage listener and the hash router) and /rcf-viewer/index.json (losing the Cmd/Ctrl+F ID lookup). GET /test-host.html and GET /test-host.js are served ONLY when --test-host or RCF_VIEW_TEST_HOST=1 is set and return 404 otherwise, so production wespa is unaffected by the embedding-proof fixture. The inline shell IIFE is gone from the viewer HTML (now in src/view/page-init.js); wespa's CSP for /rcf-viewer/* should allow the external script in place of the previous inline hash pin. The live-update pill in the footer carries connection state (connecting, open, retrying, closed) and tracks the theme through the --sv-* tokens.
What this means for you. A project on 0.28.4 upgrades with npm install rcf-lite@0.29.0 and rerun rcf init to pick up the regenerated managed instructions block (the Prototypes in DISCOVERY rule and the four new DEFINE and DISCOVERY prompts). Open rcf audit view and the tree now reads under the Stravica brand, with the Readiness tab as tab one, PRD where Overview used to be, the Build tab's Specs and DAG sub-tabs where the FBS slots list and Test suites section used to be, and Cmd or Ctrl plus F from any tab for fast ID lookup. If you embed the viewer behind wespa, extend the reverse-proxy allow-list to /page-init.js and /index.json before pinning your service to 0.29.0. If you have authored brief ledger entries whose resolvedBy leans on the 0.28.4 title-hit fallback, rewrite them to the closed pointer grammar; rcf define ledger brief update <id> --resolved-by <pointer> validates before write. The upgrade is flagged breaking under the pre-1.0 breaking-is-minor convention; existing chains revalidate cleanly otherwise.
0.25.0, 8 September 2026
The Hetzner line opens with three blueprints in one round: a shipped Linux VM shape on Hetzner Cloud with the estate hardening baseline and a snapshot cadence, a docker-compose platform on top with healthchecks, secrets as file mounts and a first-class reverse-proxy artefact, and a Cloudflare Tunnel bridge that composes with Access when Zero Trust is applied and drops to public-hostname mode when it is not. The Cloudflare-line shelf from 0.24.0 keeps its shape; the Hetzner-line shelf is a sibling on the same reference, not a replacement. Every real-account probe across the round ships accountBoundSkipped for now, pending an operator ruling on the Hetzner and Cloudflare token vault; the local probes carry the ship-time verdicts and the throwaway-server CI fixture is shared across the three tracks. The follow-up Hetzner Object Storage adapter ships as a sequential PR under object-storage-s3 v1.1.0 after this release; the rcf-lite package version does not bump for it. The schema floor stays at @stravica-ai/rcf-schemas 0.6.1.
deploy-hetzner-server v1.0.0 joins the shelf. A Hetzner Cloud server provisioner with an hcloud-shaped adapter as the sole reader of the Hetzner API token through the applied security-secrets-management facade, a canonical server manifest under hetzner/servers/<name>.json, a cloud-init template that lands the estate hardening baseline on first boot (SSH key-only, root disabled, UFW default-deny incoming, a DOCKER-USER iptables chain, a fail2ban SSH jail, unattended-upgrades, a /live probe on a private interface), a Hetzner Cloud Firewall contract, and a snapshots-and-backups posture with a weekly snapshot as the default, daily and off as alternatives, and Hetzner-managed backups as the elicited paid option. Sits alongside deploy-cloudflare-workers on the deploy shelf; the deploy-family one-target-per-project rule applies at apply time (a project picks one deploy foot). Local probes cover cloud-init render, manifest schema and an hcloud dry-run; the three throwaway-server real-account probes (provision, cloud-init hardened, snapshot on demand) ship accountBoundSkipped pending the Hetzner token vault ruling. Ships the shared throwaway-server CI fixture the T-2 and T-3 tracks reuse (label-scoped provision, destroy and orphan sweep, hcloud pulled into a checksummed scratchpad, no system install). Declares capabilities: ["cloudHost"]. Mints the new global topics linuxCloudHostContract and snapshotAndBackupCadence.
platform-docker-compose-host v1.0.0 joins the shelf. A docker engine and compose plugin install invoked from the T-1 cloud-init playbook, a canonical compose layout (compose.yaml at the repo root, service-per-container, named networks and volumes), a healthcheck-required contract for every service, a restart discipline (restart: unless-stopped for long-running services, on-failure for jobs), a zero-downtime reload shape for the reverse proxy, secrets as compose file mounts referencing the applied secrets facade at 0o400, and log shipping to the elicited observability-logging sink (default journald, opt-in loki). Caddy is the shipped default reverse proxy with Traefik as the elicited alternative; Coolify was considered and rejected (the platform blueprint is the compose contract itself, not a wrapper around a hosted panel that keeps its own state). The reverse-proxy config is a first-class versioned artefact under caddy/Caddyfile or traefik/traefik.yaml with a smoke curl after every apply. Local probes drive real docker 29.6.2 and the caddy:2 container image (docker compose config lint, a secrets-as-files scan, a Caddyfile validate); the two real-account probes (minimal-stack-up, reload-burst) ship accountBoundSkipped. Extends the T-1 throwaway-server fixture in place with a two-service compose stack. Declares capabilities: ["containerHost"]. Mints the new global topic containerHostContract.
edge-cloudflare-tunnel v1.0.0 joins the shelf. cloudflared as a compose service (the default when containerHost is applied) or a systemd unit (the alternative for a bare cloudHost, per the vendor's cloudflared-as-a-service documentation), a tunnel manifest under cloudflare/tunnels/<name>.yaml (tunnel id, credentials reference into the applied secrets facade, ingress rules mapping a public hostname to an internal service URL with a mandatory catch-all http_status:404), and a hostname-management contract that creates the DNS route via the Cloudflare API. Composes with edge-cloudflare-access via zeroTrustGate: when Access is applied the ingress rule attaches the Access AUD in originRequest.access and the connector-side JWT check refuses requests without a valid Access assertion; when Access is not applied the tunnel ships in public-hostname mode. Tunnel is its own blueprint rather than an adapter on Access. Local probes cover manifest schema, cloudflared tunnel ingress validate and an AUD-presence sidecar-read check; the two real-account probes (connector-healthy, tunnel-hostname-routes) ship accountBoundSkipped pending the Cloudflare token vault ruling. Declares capabilities: ["tunnelBridge"]. Mints the new global topic edgeIngressBridge.
Verifying against the real engine. The three new blueprints extend the round-6 verification shape without adding a browser pack: every probe is node-only, and every probe that would need a real Hetzner or Cloudflare account for its full-fat behaviour is accountBound: true and records skipped with a stable reason on a CI run without one. The Caddyfile-validate probe on platform-docker-compose-host drives the caddy:2 container image directly through docker run --rm, so a run that says the reverse-proxy artefact validates has genuinely put it through Caddy. The hcloud probe on deploy-hetzner-server runs a dry-run against the Hetzner API with a token drawn through the secrets facade. The cloudflared tunnel ingress validate probe on edge-cloudflare-tunnel reads the shipped manifest and asserts the AUD is attached when Access is composed. All the probe reports land under .rcf/reports/blueprints/<slug>/ in the shape earlier probe packs set. The shared throwaway-server CI fixture is a T-1 contribution the other two tracks import; a real-account acceptance run against a throwaway Hetzner server (label-scoped, orphan-swept) lands once the token vault ruling is in.
Also in this release: an authoring-standard capability table extension. packages/rcf-lite/docs/blueprint-authoring.md section 6a gains three new capability rows to match the shelf: cloudHost, containerHost, tunnelBridge. Loader unchanged; the append is chunk-zero style.
What this means for you. A project on 0.24.0 upgrades with npm install rcf-lite@0.25.0 and every existing chain revalidates cleanly. If your product has outgrown Workers, or wants a persistent runtime alongside its Cloudflare edge, the three new blueprints give you a straight path from the visual shelf to a Hetzner-hosted backend without inventing the shapes yourself: deploy-hetzner-server for the VM, platform-docker-compose-host for the compose stack on top, and edge-cloudflare-tunnel for the ingress bridge back to the Cloudflare edge (with Access in front when you want a Zero-Trust gate). The Hetzner deploy foot sits next to deploy-cloudflare-workers on the shelf: pick one deploy target per project. The upgrade is not flagged breaking. For the whole picture, when to reach for the Hetzner line and how the three blueprints compose with the round-6 Cloudflare shelf, see Cloudflare-first projects (the four new sections at the foot of that page cover the round-7 additions).
0.24.0, 8 September 2026
Six Cloudflare-line blueprints land on the shelf and, with them, a coherent story for a whole product hosted on Cloudflare: a Workers KV facade, cron triggers with an expression-router, durable objects covering the strong-consistency single-cell shape and the hibernatable WebSocket hub shape, a Zero-Trust Access gate that the admin console reads to switch its sign-in surface, Turnstile with the pinned test keys running under a Playwright pack, and edge rate limiting with a committed manifest. Each blueprint verifies against the real Cloudflare engine through node-only probes (the fixtures drive miniflare and wrangler dev on the shared cf-platform fixture root), and one blueprint pack runs in a real browser against Cloudflare's live siteverify endpoint using the vendor's own public test keys so a run that says the surface works has genuinely put the thing under load. In the same release, application-admin-console moves to v1.1.0 and declares optional consumption of the new zeroTrustGate capability. The schema floor stays at @stravica-ai/rcf-schemas 0.6.1.
platform-cloudflare-kv v1.0.0 joins the shelf. A Workers KV facade as the sole reader of the KV namespace binding, a cache-aside helper, put, get, list with a prefix, TTL, and metadata-only lifecycle events (facadeReady, kvHit, kvMiss, kvWrite). Probes drive miniflare inside the shared packages/rcf-lite/test/fixtures/cf-platform/ fixture, plus one accountBound-skipped real-account eventual-consistency smoke. Declares capabilities: ["keyValueStore"]. Mints the new global topic keyValueStoreContract.
platform-cloudflare-cron-triggers v1.0.0 joins the shelf. A scheduled() handler contract with an expression-router, a skew-tolerance discipline, and metadata-only lifecycle events (cronReady, cronFired, cronSkewed, cronStalled, cronUnmatched). Probes drive wrangler dev --test-scheduled against the shared cf-platform fixture, plus one accountBound-skipped real-account scheduled smoke. Composes with jobs-background when the applied scheduler mode is workerCron. Declares capabilities: ["scheduledTrigger"]. Mints the new global topic scheduledTriggerContract.
platform-cloudflare-durable-objects v1.0.0 joins the shelf. Two shapes in one blueprint: a strong-consistency single-cell and a hibernatable WebSocket hub, alongside a sole-reader AST scan on the DO namespace binding, a storage round-trip, an alarm-fires-once check, and a hub-broadcast check. Probes drive wrangler dev on workerd against the shared cf-platform fixture (the round-6 gate lesson is that a probe that names an engine has to drive that engine, not a mock), plus one accountBound-skipped real-account storage-backend smoke. Declares capabilities: ["strongConsistencyCell", "hibernatableWebSocket"]. Mints the new global topics strongConsistencyCellContract and websocketHubContract.
edge-cloudflare-access v1.0.0 joins the shelf, and application-admin-console bumps to v1.1.0 in the same release to consume it. Access ships a JWT validator as the sole reader of the Cf-Access-Jwt-Assertion header, an Access application shape, an audit-event record with metadata-only secrecy, and a real-account gated-URL probe that runs accountBound-skipped without a Cloudflare account. Declares capabilities: ["zeroTrustGate"]. Mints the new global topic edgeAuthenticationGate. When Access is applied, the admin console reads the applied-sidecar and switches its sign-in surface to the Access-gated shape (no local login form; the principal reduction reads from request.auth). Absent zeroTrustGate, the admin console falls back to the v1.0.0 behaviour unchanged.
edge-cloudflare-turnstile v1.0.0 joins the shelf. Client widget mount pinned to the Cloudflare Turnstile host only, server-side siteverify against https://challenges.cloudflare.com/turnstile/v0/siteverify, a refuse-if-token-missing guard, and a magic-link mint-surface hook. Node probes drive the fixture, and a Playwright pack runs four checks against Cloudflare's live siteverify using the pinned public test sitekeys 1x00000000000000000000AA (always-pass), 2x00000000000000000000AB (always-fail) and 3x00000000000000000000FF (forced-interactive) with their paired secrets, so a CI run needs no real Turnstile credentials to exercise the deterministic branches. Declares capabilities: ["humanCheck"]. Mints the new global topic humanVerificationGate. First uiBearing: true blueprint on the Cloudflare-line shelf.
edge-cloudflare-rate-limiting v1.0.0 joins the shelf. A local manifest under cloudflare/rate-limits/*.json, manifest presence and schema validation, a drift-audit shape against the applied Cloudflare account, and metadata-only rate-limit events. One accountBound-skipped real-account burst-and-429 probe. Declares capabilities: ["edgeRateLimit"]. Mints the new global topic edgeThrottleContract.
Verifying against the real engine. The six new blueprints share the round-5 verification shape: each ships a small set of probes that drive a real Cloudflare engine rather than a mock. wrangler dev, workerd through wrangler dev, and miniflare each show up under their own probe rather than being papered over by a fake. The Turnstile blueprint is the round's exception on shape: it ships a Playwright pack with the pinned test sitekeys, so the browser-side widget and the server-side siteverify are both exercised end to end without a real vendor credential. Every probe that would need a real Cloudflare account for its full-fat behaviour is accountBound: true and records skipped with a stable reason on a CI run without one; the aggregate verdict counts those honestly. All the probe reports land under .rcf/reports/blueprints/<slug>/ in the shape earlier probe packs set.
Also in this release: an authoring-standard capability table extension. packages/rcf-lite/docs/blueprint-authoring.md section 6a gains seven new capability rows to match the shelf: keyValueStore, scheduledTrigger, strongConsistencyCell, hibernatableWebSocket, zeroTrustGate, humanCheck, edgeRateLimit. Loader unchanged; the append is chunk-zero style.
What this means for you. A project on 0.23.0 upgrades with npm install rcf-lite@0.24.0 and every existing chain revalidates cleanly. If your product is heading to Cloudflare, the six new blueprints give you a straight path from the visual shelf to a whole Cloudflare-hosted backend without inventing any of the shapes yourself: platform-cloudflare-kv for a KV facade, platform-cloudflare-cron-triggers for scheduled work, platform-cloudflare-durable-objects for strong-consistency cells or hibernatable WebSocket hubs, edge-cloudflare-access in front of admin surfaces (the admin console picks the gated shape up automatically at v1.1.0), edge-cloudflare-turnstile on public forms and mint surfaces, and edge-cloudflare-rate-limiting as the zone-level guard. If you have already applied application-admin-console at v1.0.0, re-apply to pick up v1.1.0 and the optional zeroTrustGate consumption; without Access on the project the behaviour is unchanged. The upgrade is not flagged breaking. For the whole Cloudflare-first story, when to reach for it and what to escape to Hetzner via the round-7 tunnel for, see Cloudflare-first projects.
0.23.0, 7 September 2026
Four infrastructure blueprints land on the shelf and, with them, the shape of a real product's backend: a Postgres store, an S3-shape object store, a Cloudflare Queues producer and consumer, and a background-jobs discipline that refuses to apply until a queue is applied. Each blueprint verifies against its real engine with node-only probes, so a run that says the surface works has genuinely put the thing under load rather than mocked it out. The security-secrets-management blueprint picks up a capabilities[] declaration in the same release so the object-store's refusal fires end to end. In the same release, deploy-cloudflare-workers moves to v1.2.0 to bless the Workers-with-static-assets shape as the SPA-on-Workers deploy target, and a small CLI fix stops stdout being truncated on very large outputs. The schema floor stays at @stravica-ai/rcf-schemas 0.6.1.
persistence-data-postgres v1.0.0 joins the shelf. A Postgres-backed durable store behind a single facade that is the sole reader of the pg client. Numbered forward-only migrations run inside per-file transactions, prepared-statement discipline is enforced by a source-tree AST scan (so a raw string concatenation on a query cannot slip through review), a transactional-atomicity helper composes multi-step writes, recovery pairs scheduled pg_dump with the vendor's point-in-time recovery, and a connection-pool posture is picked per deploy target. Declares capabilities: ["relationalStore"]. Six probes drive postgres:17-alpine in a shared fixture and land their reports under .rcf/reports/blueprints/persistence-data-postgres/. Conflicts by design with persistence-data-sqlite and persistence-data-d1 on the store choice and the migration discipline: adopting one of the three is a decision your project makes once. The round-6 Hyperdrive adapter slot is reserved at the driver boundary.
object-storage-s3 v1.0.0 joins the shelf, with security-secrets-management v1.0.1 as its enabling minor. An S3-API facade with Cloudflare R2 as the first adapter and MinIO as the local dev target: put, get, delete, list, a presigned-URL contract with a bounded TTL, multipart upload above an elicited threshold, and metadata-only lifecycle events. Declares capabilities: ["objectStorage"]. The blueprint refuses to apply on a project that has not applied security-secrets-management first, so a credential-holding surface cannot land without the machinery to look up its credentials; the deliberate escape hatch is --allow-no-secrets-yet, which records the acknowledgement on the sidecar and lets the store apply with a note that the secret source is not yet wired. In the same release, security-secrets-management moves to v1.0.1 and declares capabilities: ["secretsProvider"] so the refusal on the object-store fires end to end. Five probes run against MinIO plus one accountBound-skipped R2 smoke that runs against a real Cloudflare account when CI_HAS_CLOUDFLARE_ACCOUNT is set and records skipped otherwise.
messaging-queue-cloudflare v1.0.0 joins the shelf. A Cloudflare Queues producer facade, consumer registration on the Worker's queue handler, publish, consume, ack, retry with the attempt counter, dead-letter contract per Cloudflare's own defaults (3 retries, 4-day DLQ retention), batch consume, and metadata-only lifecycle events. Declares capabilities: ["queue"]. Five probes drive wrangler dev locally plus one accountBound-skipped concurrency smoke against a real account. The Postgres-backed queue sibling is reserved by slug (messaging-queue-postgres) for the projects that would rather run everything on the one database, and lands when demand is there.
jobs-background v1.0.0 joins the shelf. A background-jobs contract: named job definitions with a handler, an input schema, a retry policy and a timeout; a scheduler that takes cron expressions and one-shot delayed runs; retries on top of the applied queue; and a metadata-only run-log. Declares capabilities: ["backgroundJobs"]. The blueprint refuses to apply on a project that has not applied a queue blueprint first: it needs somewhere to enqueue work. The refusal fires with exit 3 and the stable message id jobs-background-no-queue; --allow-no-queue-yet is the deliberate escape hatch that records the acknowledgement on the sidecar and lets the shell apply with the surfaces gated on the queue disabled until a queue lands. Five probes: the apply-time refusal, the override behaviour, a fake-clock cron test, a retry-and-fail case, and an event-secrecy check on the run-log. The round-6 Workflows scheduler-mode slot is reserved at the ADR boundary.
Verifying against the real engine. The four new blueprints share a shape: each ships a small set of node-only probes that drive a real engine rather than a mock. Postgres runs as a container. MinIO stands in for the S3 API in local dev, and the R2 smoke runs against a real Cloudflare account when one is available. The queue and jobs probes drive an in-memory driver the fixture ships alongside the wrangler configuration, so the round-trip is exercised without a live wrangler process. Where a probe genuinely needs an account that CI does not have, it records skipped with a stable reason rather than silently passing; the aggregate verdict counts those honestly and the ship gate stays trustworthy about what was actually probed. All the probe reports land under .rcf/reports/blueprints/<slug>/ in the shape earlier probe packs set.
Also in this release: the SPA deploy target. deploy-cloudflare-workers moves to v1.2.0. The minor bump blesses the Workers-with-static-assets shape as the SPA-on-Workers deploy shape and lands two new elicits (assets-directory, run-worker-first), an ADR carrying Cloudflare's own landing-page recommendation, a shared sample-app fixture under the same fixture root the other round-5 blueprints use, and an assets-manifest-scan probe that reads the applied fixture's wrangler.toml and asserts the [assets] block is present, run_worker_first is set, and the Pages-only pages_build_output_dir field is absent. No new capability, no new topic; the v1.1.0 contribution set carries through unchanged.
Also in this release: a stdout truncation fix. bin/rcf.js now flushes stdout before process.exit at both exit sites. Before the fix, a command with a large output (first spotted on rcf audit coverage --format mermaid on the umbrella tree) could truncate at the 65536-byte pipe buffer.
What this means for you. A project on 0.22.0 upgrades with npm install rcf-lite@0.23.0 and every existing chain revalidates cleanly. The four new blueprints give you a straight path from the visual shelf you already had to a persistent, event-driven backend without inventing the shape yourself: apply security-secrets-management first, then persistence-data-postgres for a durable store, object-storage-s3 for files and blobs, messaging-queue-cloudflare for a queue, and jobs-background on top for scheduled and delayed work. Each one refuses to apply where a required predecessor is missing, and each refusal has a named override for a deliberate scaffolding pass. If your SPA already deploys with deploy-cloudflare-workers, re-apply to pick up v1.2.0 and the two new elicits: your existing wrangler configuration keeps working, and the new probe reads what you already had. The upgrade is not flagged breaking.
0.22.0, 7 September 2026
Five application blueprints fill in the visual shelf and, with them, a small but useful reuse: application-account-settings picks up the capability-gating mechanism the admin console shipped in 0.21.0, so the settings surfaces only render when the applied auth blueprint can back them. The four shipped auth blueprints and the logging blueprint pick up additive capability declarations in the same release. No new CLI verbs, no new flags, no new exit codes; the schema floor stays at @stravica-ai/rcf-schemas 0.6.1. Two more blueprints land quietly on the shelf ahead of their own 0.23.0 notes: persistence-data-postgres v1.0.0, object-storage-s3 v1.0.0, and a security-secrets-management v1.0.1 minor.
application-empty-error-states v1.0.0 joins the shelf. An eight-state contract for the moments a surface has nothing useful to say: not-found, forbidden, server-error, offline, permission-denied, empty-list, no-search-results, and the last-resort error boundary. Each state has an RFC 9110 status backing it where the status applies, a WCAG 2.2 AA accessible name and description, and an offline write-buffer contract that a reconnected surface must drain before it stops rendering the offline state. The shipped probe pack anchors eight surface-observable checks (one per state) so the ship gate refuses while any state's DOM claim goes missing.
application-file-upload v1.0.0 joins the shelf. A file-upload surface with the WCAG 2.5.7 keyboard-alternative gate on by default, a chunked and resumable transport contract (tus.io is the elicited alternative when a project already runs one), MIME-type, size and virus-scan refusals with explicit fail messages, and four break switches for exercising each refusal in a fixture. The shipped probe pack has four checks anchored to the keyboard-alternative, the chunk resume, the refusal messages and the tus.io round-trip.
application-forms-wizard v1.0.0 joins the shelf. The GOV.UK Design System's task-list and summary-list patterns as a multi-step wizard: per-step validation timing (blur, submit, or on-change with a debounce), an error-summary at the top with skip-links to the offending field, and a save-and-return contract with a draft-store transport left elicited on purpose (the wizard cannot ship a default when the drafts might land in a database, in local storage, or in your session store). Its probe pack anchors the task-list, the summary-list, the error-summary, and the save-and-return round-trip.
application-account-settings v1.0.0 joins the shelf. A self-service settings area with five capability-gated surfaces: profile, security, sessions, notification preferences, and theme. The blueprint reuses the admin-console capability-gating mechanism from 0.21.0, so a settings surface only renders when the applied auth blueprint (or an elicited custom auth answer) declares the capability that backs it. Applying without any auth blueprint refuses at add time with the same spec-verbatim message the admin console uses, and the deliberate escape hatch is --allow-no-auth-yet, which records the acknowledgement on the sidecar and lets the shell apply with every gated surface disabled. The shipped probe pack has five capability-gated checks; a check whose required capability is not on any applied blueprint records applicable: false rather than a pass or a fail, so the aggregate verdict stays honest about what was actually probed. A hosted-UI bridge is shipped for projects that link out to (or embed) a vendor's hosted identity portal, alongside the in-place self-service surface for projects that own their own auth.
Alongside account settings, the four shipped auth blueprints and the logging blueprint pick up additive capabilities[] declarations for three new strings: credentialSelfService (the vendor exposes an in-place password change and MFA surface), sessionInventory (the vendor exposes an inventory of active sessions with device labels and a terminate action) and hostedIdentityUi (the vendor points at a hosted portal the security tab can link out to or embed). security-auth-clerk moves to 1.3.0, security-auth-keycloak to 1.2.0, security-auth-oauth2 to 1.2.0, security-auth-magic-link to 1.2.0, observability-logging to 1.2.0. A project already applying one of these gets the new declarations automatically on the next apply, and the settings blueprint discovers the applied capability set the same way the admin console does.
application-onboarding-tour v1.0.0 joins the shelf. A first-run tour built on the ARIA APG dialog-modal pattern's tooltip-as-dialog shape: keyboard-only Escape and focus-return contracts, a checklist-on-dashboard fallback that collapses gracefully into the settings surface, and completion-state persistence with per-principal (when the auth blueprint declares principalDirectory) or local-storage layers. Four pack checks anchor the dialog contract, the Escape-and-return behaviour, the checklist collapse and the completion-state persistence.
Also on the shelf at this release, ahead of their own 0.23.0 notes. persistence-data-postgres v1.0.0 and object-storage-s3 v1.0.0 are the first round-5 blueprints to land, alongside the security-secrets-management v1.0.1 minor. Their own operator-facing notes and reference rows ship with 0.23.0; for now, the CLI lists them under rcf define blueprint list and applying either goes through the normal blueprint-add flow.
What this means for you. No CLI change and no schema move: a project on 0.21.0 upgrades with npm install rcf-lite@0.22.0 and every existing chain revalidates cleanly. If you are building a small product with a UI, one of the five new visual blueprints likely covers a surface you were about to invent from scratch: rcf define blueprint add @stock/application-empty-error-states, @stock/application-file-upload, @stock/application-forms-wizard, @stock/application-account-settings or @stock/application-onboarding-tour. If you have already composed one of the four auth blueprints, adding account settings picks up whatever capabilities that auth declares; if you have not yet composed an auth blueprint and want the settings shell in place first, apply it under --allow-no-auth-yet and add auth later. The upgrade is not flagged breaking.
0.21.0, 5 September 2026
Five visual-feature blueprints land on the shelf (data table, charts, dashboard, in-app notifications, admin console) and, with them, the mechanism that proves them: a blueprint can now ship a Playwright probe pack that rcf verify browser runs against your running app in a real browser, and the ship gate refuses while a surface check fails. The admin console only offers the surfaces your applied auth blueprint can support, because blueprints can now declare capabilities and ask you questions at apply time. The schema floor moves to @stravica-ai/rcf-schemas 0.6.1.
A probe pack is a small file a blueprint ships alongside its chain documents: an accessible-name check, a specific control on the shell header, an audit row's column set, driven against your app in an actual headless browser rather than a mock. The runner discovers packs on every applied blueprint, imports each one, and runs the checks each appliesTo predicate matches for the FBS you are verifying. rcf verify browser <fbs-id> is the entry point. --probe-pack <name> restricts a run to one pack by name; --no-browser skips provisioning a browser (a pack that calls browser.* sees browser=null); --no-boot disables a pack's declared bootCommand fallback when the runtime URL is unreachable. When the runtime is already answering, the boot block is skipped and the running server is used unchanged; the dev server is the normal path. Provisioning goes through the pinned Playwright MCP server by default, or through a playwright your project already resolves from its own node_modules when that shorter route is available. Every pack result rides on the manifest under browserVerification.probePacks[] and the ship gate reads them alongside the existing verdicts.
application-datatable v1.0.0 joins the shelf. The base grid: an aria-rowcount claim that matches the count of rendered rows plus one for the header, a total-row-count element with the same rendered number and a screen-reader hint, and a pagination summary with the exact showing <n> of <total> phrasing. Its shipped probe pack anchors the two ACs to the DOM: AC-19102-1 for the header semantics and AC-19105-1 for pagination-summary parity. Two more ACs are called out in the blueprint's Known mechanism-reach gaps section for probes to grow into later.
application-charts v1.0.0 joins the shelf. Chart shells that are readable by both a screen-reader user and a keyboard-only user: a text alternative announced through role="figure" and aria-labelledby, focusable data points that keep a visible focus ring, and, on the sparkline shape, a tooltip that both fills [aria-live="polite"] and updates the parent's aria-describedby. The shipped probe pack anchors three ACs on the chart shell, sparkline, and interactive plot. The remaining runtime-observable ACs (WCAG figure structure at scale, keyboard-focus behaviour beyond the tab set) are listed as gaps and covered by unit and anatomy tests until a probe reaches them.
application-dashboard v1.0.0 joins the shelf, with a packaged design-guidance asset. The dashboard blueprint ships a real component-library-agnostic layout brief inside its guide/ directory alongside the usual anatomy, so the agent implementing the surface has a design frame to build against rather than inventing one. Its Playwright probe pack anchors five ACs across the shell layout, the topline metric strip, the grid at desktop and mobile widths, and the responsive collapse (using a new pack.browser.resize({ width, height }) seam the runner exposes). The desktop-mobile pair is a first: earlier probe packs assumed a single viewport.
application-notifications-in-app v1.0.0 joins the shelf, with the family-prefix reservation for sibling channels. It ships the in-app notification shape (a toast region, an inbox surface, an unread badge with an accessible count) and a probe pack that anchors the toast region, the inbox row shape and the badge announcement. The blueprint reserves the application-notifications- family prefix on the shelf, so future siblings for the other channels (-email, -push, -webhook) compose on the same topic vocabulary without a rename.
application-admin-console v1.0.0 joins the shelf, with conditional surfaces and the new capability-declaration mechanism. The console shell always renders; the users directory renders only when your applied auth blueprint declares principalDirectory, the permissions matrix only when roleModel is declared, the org switcher only when tenancy is declared, and the audit log only when auditLog is declared. security-auth-magic-link v1.1.0 declares [principalDirectory] (no roles surface out of the box), security-auth-clerk v1.2.0, security-auth-oauth2 v1.1.0 and security-auth-keycloak v1.1.0 each declare [principalDirectory, roleModel]; add any of them and the admin console adapts. Applying application-admin-console with no auth blueprint applied refuses at add time with a spec-verbatim message naming security-auth-*; the deliberate escape hatch is --allow-no-auth-yet, which records the acknowledgement on the sidecar and lets the shell apply with every capability-gated surface disabled until you compose an auth blueprint. Its probe pack has four capability-gated checks: an absent required capability records applicable: false on that check rather than a pass or a fail, so the aggregate verdict stays honest.
Blueprints can now ask you questions at apply time. A blueprint declares elicits[] in its blueprint.json (each entry an id, a prompt, a kind of enum, string or boolean, an optional default, options for the enum kind, and an optional when predicate on already-applied capabilities). rcf define blueprint add prompts you interactively for each answer that applies to your project, and records the resolved answer bag on the per-blueprint sidecar at rcf/blueprints/<slug>.applied.json alongside the discovered capabilities. The admin console blueprint uses four elicits: the baseline-role roster when the auth blueprint declares roleModel, the tenancy shape when it declares tenancy, the invite transport (email by default), and the audit-retention window in days when it declares auditLog. For scripted apply, --answer <id>=<value> (repeatable) supplies one answer per flag and --answers <file> reads a JSON object mapping ids to values; a later --answer overrides an entry from --answers, so shell-level tweaks are easy.
The refusal at apply time when a blueprint's declared requiresAppliedCapabilities is not satisfied speaks a new exit code path: exit 3, the same code every other tree-soundness refusal uses. The message names the specific capability set your project is missing and the security-auth-* prefix so an operator can go and add the right auth blueprint; the escape hatch is the blueprint's own allowSkipFlag, which for the admin console is --allow-no-auth-yet.
The schema floor moves to @stravica-ai/rcf-schemas 0.6.1. The additive minor adds the optional browserVerification.probePacks[] field on the manifest record so a non-dry-run rcf verify browser --probe-pack <slug> can persist pack results into the manifest, per the visual round spec. Existing chains revalidate cleanly; a project on rcf-schemas 0.6.0 upgrades automatically when it bumps rcf-lite.
What this means for you. If you are building a small product with a UI, one of these five blueprints likely covers a surface you were about to invent from scratch: rcf define blueprint add @stock/application-datatable, @stock/application-charts, @stock/application-dashboard, @stock/application-notifications-in-app or @stock/application-admin-console. The four auth blueprints picked up minor bumps in the same release; a project already applying one gets the new capabilities[] declaration automatically on the next apply. If you want the admin console on a project that does not yet have an auth blueprint applied, either compose one of the four auth options first, or apply the admin console under --allow-no-auth-yet and add auth later. Running rcf verify browser <fbs-id> from now on picks up every applicable probe pack shipped by the blueprints you have composed; use --probe-pack <name> to narrow a run, and --no-browser if you want a smoke run with browser-driven checks skipped. The upgrade is not flagged breaking: the schema floor moved by a minor, and every new mechanism is opt-in.
0.20.0, 4 September 2026
An optional evaluation step joins the chain, for acceptance criteria whose outcome cannot be checked deterministically. You mark such a criterion when you define it, attach an EVAL document with its own pass threshold, and the audit, verify and finalise steps refuse to ship while it is missing. There is one explicit opt-out that records its reason on the manifest. The schema floor moves to @stravica-ai/rcf-schemas 0.6.0.
An EVAL is a graded example set for one or more acceptance criteria: cases the system under test is run against, criteria those cases are scored on, a judge (a rubric, an LLM run under your subscription, or a scripted metric), and a pass threshold. It sits alongside TS and TC as a peer contract on a non-deterministic AC. Determinism is per criterion, not per feature: a feature can carry both deterministic ACs (existing TS/TC coverage) and non-deterministic ACs (existing coverage plus an EVAL) side by side. A chain that carries no non-deterministic ACs is untouched by any of this.
rcf audit eval coverage [scope-id] is a new sibling of rcf audit coverage. It reports which non-deterministic ACs on the scoped subtree carry a resolving EVAL and which do not, where a resolving EVAL is a non-superseded document whose most recent runRecord[] entry is not pending. --strict exits 4 on any gap. --require-approved is an extra --strict gate that refuses any EVAL still at authoringStatus: draft. --format table | json | mermaid matches the coverage audit; the mermaid render colours a deterministic AC green (out of scope for eval), an amber node when a non-deterministic AC has a resolving EVAL, and a red node when it does not. A chain with zero non-deterministic ACs passes trivially at every level.
rcf verify run learns two per-AC verdicts on the report and prints one new preflight line. EVAL-MISSING fires on any non-deterministic AC without a resolving EVAL; EVAL-BELOW-THRESHOLD fires on any AC whose bound EVAL's most recent run fell below its declared threshold or hit a critical failure. Both ride report.perAcVerdicts[] alongside the 0.7.0 classes; the top-level verdict set is unchanged, so existing report readers keep working. The preflight prints EVAL coverage: nonDeterministic=<n>, covered=<k>, missing=<n-k> (or EVAL coverage: no nonDeterministic ACs on this chain), and the same numbers land on report.run.runStats.evalCoverage for a later re-render.
rcf build finalise refuses promotion to verified on either of the new verdicts, exit 4, with the spec-verbatim messages: finalise refused: EVAL missing on AC(s) <ids>; author an EVAL or --ship-without-eval "reason" and finalise refused: EVAL below threshold on AC(s) <ids>; investigate the run record or --ship-without-eval "reason". The sister opt-out --ship-without-eval "<reason>" acknowledges the verdict and lets finalise proceed with an audit-log entry on the manifest under a new optional shipWithoutEval[] array. The reason string is mandatory; a missing reason exits 2. This is the deliberate degraded-mode path for a harness offline in CI or a threshold under review; the acknowledgement is verbose in the console output and durable on the manifest.
rcf define create ac --determinism deterministic | nonDeterministic writes the marker onto the inline AC at author time. Absence writes no field, so existing chains stay byte-stable and every consumer resolves to deterministic by default. The enum guard fires the spec-verbatim message --determinism expects 'deterministic' or 'nonDeterministic', got '<value>' and exits 2. The LLM-as-judge invocation stays under the estate subscription-only rule: the runner spawns claude (or codex) by bare name and hands it a per-case prompt on stdin, the same pattern the verify launcher already uses. No API keys, no direct HTTP calls to Anthropic or OpenAI enter rcf-lite.
rcf init now scaffolds an rcf/evals/ directory alongside the other document families, and rcf define validate knows the twelfth document kind. Cross-links are integrity-checked at validate time: an EVAL's usId must resolve, every acIds[] entry must exist on the parent US, and cross-US EVAL bindings refuse. The core store's inversion map gains tree.evalByAcId, keyed on acId, so trace and impact walks reach EVALs from any AC they cover.
The release is flagged breaking under the pre-1.0 breaking-is-minor convention because the schema floor moves. A project on @stravica-ai/rcf-schemas 0.5.x cannot understand the EVAL document type or the AC-level determinism field; upgrading rcf-lite pulls the 0.6.0 schemas in. The chain revalidates cleanly because absence of determinism on existing ACs resolves to deterministic at every consumer.
What this means for you. If your chain has no non-deterministic behaviour, rcf audit eval coverage reports zero and the finalise gate reads no EVAL. Nothing changes. If your chain does, decide which ACs are non-deterministic, mark them at author time with rcf define create ac --determinism nonDeterministic (or reclassify an existing AC with rcf define update <ac-id> --set determinism=nonDeterministic), author an EVAL against each (rcf/evals/EVAL-NNN.json, one file per EVAL), and let the finalise gate refuse until the coverage is real. Two audit steps run alongside each other from here on: rcf audit coverage --strict for the mechanical test contract and rcf audit eval coverage --strict for the graded-output contract. Rerun rcf init in the project directory after the upgrade so the new rcf/evals/ directory is scaffolded alongside the other document families.
0.19.0, 4 September 2026
Core companions train. Two new general-enterprise-practice blueprints land on the shipped shelf, a companion-suggestion mechanism baked into every blueprint's manifest, and the standards-derived-blueprint discipline written into the authoring standard as section 8a. Nothing on the shelf breaks; every existing blueprint that does not declare suggestedCompanions[] loads clean and prints no block.
observability-logging v1.0.0 joins the shelf. It ships the ECS-neutral single-line JSON emission contract, correlation-identifier acceptance and propagation, PII redaction at the emission boundary by named category, an operator-elicited minimum level per environment, and a hermetic in-memory capture mode for tests. It declares providesRoles: ["logging"] and mints itself as the shelf-canonical scope: global claimant on the logging topic; application-api-rest-ADR-304 is retained on api-rest as historical context without scope: global from api-rest v2.1.0. Contributes five REQs, eight USs, two TACs and four ADRs under US band 15101 to 15899 and ADR/TAC suffix block 16xx.
application-error-handling v1.0.0 joins the shelf. Process-level and framework-level boundaries, the shared internal error record shape (code, category, message, correlationId, cause chain, redacted context), the transient / permanent / unknown classification vocabulary, and delegation of the wire mapping through a substitutable transportWriter interface. Declares providesRoles: ["errorHandling"] and suggestedCompanions: [{role: "logging", ...}] so the two blueprints work as a pair by default. errorHandling is a distinct topic from errorEnvelope, which stays with application-api-rest as the REST wire shape.
The companion-suggestion mechanism itself is additive on every blueprint. A blueprint that provides an infrastructural role declares providesRoles: string[] alongside its paired scope: global ADR on the topic. A service blueprint that recommends companions declares suggestedCompanions: [{role, reason}]. rcf define blueprint add walks a deterministic tier ladder for each recommended role (applied provider > project pin in rcf/companions.json > registered library provider > core-shelf provider) and prints one line per role in a Suggested companions this blueprint recommends alongside it: block after a successful apply, with an origin annotation on each. The apply itself never adopts a companion; that is the operator's decision. --companion <role>=<slug> on add (repeatable) pins a specific provider for one run and writes it to rcf/companions.json; --no-companion-suggestions suppresses the block. A new subverb pair rcf define blueprint companions set <role> <slug> and unset <role> writes and clears project-level pins; rcf define blueprint companions <slug> prints the resolved companion set for an already-applied service blueprint with the origin annotations. Two library candidates for one role with no pin refuse exit 3 with a three-path resolution message. rcf define validate refuses exit 3 on a pin that no applied blueprint, registered library or shelf provider satisfies.
application-api-rest moves to v2.1.0. Minor bump for the additive suggestedCompanions: [{role: "logging", ...}, {role: "errorHandling", ...}]; ADR-304-application-api-rest-logging is retained on the blueprint without scope: global and re-titled as historical context, superseded by observability-logging-ADR-1601 as the shelf-canonical logging owner from api-rest v2.1.0. Existing chains that referenced ADR-304 keep the reference intact; only the global-topic claim was dropped.
application-spa moves to v1.5.0. Minor bump for the same additive suggestedCompanions pair on logging and errorHandling.
The authoring standard grows section 8a on standards-derived blueprints. A MUST clause that binds a testable runtime or artefact behaviour becomes an AC; a MUST that binds an operator choice may land as a recommendedDefault: true ADR carrying the clause id on standardsTraceClause; a SHOULD becomes a recommended ADR default, a MAY becomes an elicited ADR choice, and a not-carried clause stays allowed with a named reason. Three additive optional per-ADR fields (recommendedDefault, elicited, standardsTraceClause) plus one blueprint-level field (standardsTrace: [{id, version}]) support the discipline; when standardsTrace[] is declared, every ADR contribution must carry a non-null standardsTraceClause (or the sentinel "generic enterprise practice").
The managed agent-instructions block gains one paragraph under How to talk to your operator teaching the agent to surface resolved companions verbally, prefer the library provider over the shelf when a library is registered, and never apply a companion without the operator's explicit go. Rerun rcf init in your project directory to refresh the block in place; rcf doctor --fix does the same if you prefer.
What this means for you. If your project is on application-api-rest v2.0.0 or application-spa v1.4.0, re-apply each with rcf define blueprint add <path-to>/blueprints/<slug> to pick up the additive suggestedCompanions; both bumps are minor and existing acceptance criteria carry across. If you want the shelf logging role, rcf define blueprint add @stock/observability-logging; for the shelf errorHandling role, rcf define blueprint add @stock/application-error-handling. A project that already superseded the logging topic at project level under v1.x keeps the supersede as historical context; the shelf-canonical claimant is observability-logging from this train onward, and rcf define blueprint remove-resolution <adr-id> clears any redundant resolution that a re-apply exposes. And rerun rcf init to pick up the new companions paragraph in the agent-instructions block.
0.18.0, 4 September 2026
Core shelf probe-path alignment. One shelf blueprint now owns the probe-path binding across the whole shelf, so a project that composes more than one of the observability and API blueprints no longer reconciles duplicate scope: global claims by hand. observability-probe-endpoints v1.1.0 is the sole claimant and gains an optional Kubernetes /startup path (off by default); observability-essentials v2.0.0 and application-api-rest v2.0.0 drop their shipped /healthz and /readyz defaults and defer to the resolved paths. rcf doctor grows a probe-path-owner check, and rcf define blueprint remove-resolution is the paired remedy verb for dropping a historical resolution that a blueprint bump has made redundant.
observability-probe-endpoints moves to v1.1.0. It is the sole shelf-wide scope: global claimant on healthProbes and readinessSemantics, and gains an optional Kubernetes-profile startup path (default /startup, off by default, enabled per project by probeInterface.options.kubernetes.startup.enabled: true). Two paired acceptance criteria cover the additive surface: three-path resolution on US-14102 and a three-entry auth-exempt list on US-14107. Downstream blueprints read the emitted path set via TAC-1501 getExemptPathSet.
observability-essentials moves to v2.0.0. It drops its scope: global claims on healthProbes and readinessSemantics, restates REQ-001 and REQ-002 path-neutral, and drops the shipped /healthz and /readyz defaults from TAC-801 and TAC-802 (the path field becomes required config with no default). ADR-801 and ADR-802 stay on disk as scope-local historical context. Two new ACs (AC-7101-4 and AC-7102-4) cover the stable-coded PROBE_INTERFACE_PATHS_MISSING boot refusal, so an essentials-alone project that forgets the config sees one loud message with a named code at boot rather than a probe missing at runtime.
application-api-rest moves to v2.0.0. It drops the literal /healthz/live, /healthz/ready, and /healthz/startup bindings from REQ-006, US-2108, TAC-306, and the US-2103 versioning-exemption AC. It defers to the resolved probe path set from observability-probe-endpoints v1.1.0 via TAC-1501 getExemptPathSet, or to a project-supplied probeInterface.paths in the essentials-alone case.
rcf doctor gains a probe-path-owner check that fires when more than one applied blueprint teaches probe paths. The paired remedy verb is rcf define blueprint remove-resolution <adr-id>, which drops a single manifest.resolutions[] entry by its resolvedByAdrId. It writes nothing else: the project-level ADR file at rcf/adrs/<adr-id>.json stays in place as historical context. Malformed or unknown ids refuse exit 2; re-running on a valid id that no longer names a resolution prints nothing to remove and exits 0.
What this means for you. If your project applies only observability-essentials v1.x, re-applying to v2.0.0 needs one line of configuration per environment (probeInterface.paths.liveness and probeInterface.paths.readiness), unless you also compose observability-probe-endpoints v1.1.0 or later, which supplies the paths automatically. If your project applies both observability-essentials v1.x and observability-probe-endpoints v1.0.0 with a project-level ADR superseding both on healthProbes and readinessSemantics, after re-apply the resolutions read as redundant historical context and the probe-path-owner check flags them with the remove-resolution hint. If your project applies application-api-rest v1.x, any FBS or TC that binds a literal /healthz/live, /healthz/ready, or /healthz/startup string needs one edit each to bind the resolved path set; rcf audit coverage --strict catches project-side TCs that still hold the literal strings after re-apply.
0.17.0, 4 September 2026
The e2e verification release for browser-facing projects. Verify pins the Playwright MCP browser tooling instead of pulling @latest, doctor gains four checks that fire only where they apply, rcf init learns not to trample an existing Playwright MCP entry, and two blueprints declare a browser surface so the tools know which projects the browser-facing checks concern. The materialiser that turns the shipped e2e job description into an actual running job lands in a follow-up train, so what ships here is a documentation contract: the shape is settled, the paperwork ships now, the runtime follows.
rcf verify run no longer provisions Playwright's browser MCP from @latest. It composes an explicit pin against @playwright/mcp@0.0.80, prints Playwright MCP: pinned to @playwright/mcp@<version> on preflight, and lands the effective pin on the report as runStats.playwrightMcpVersion, so a report re-read tells you which browser tooling that pass actually ran against. A new --playwright-mcp-version <semver> flag overrides the pin for one run (emergency use, fires a loud stderr notice, refuses non-semver values with an exit-2 message). A pin bump is a deliberate rcf-lite change from here on, with its own commit, its own changelog line, and a re-run of the verify test set against the pinned tooling where behaviour is affected.
rcf doctor learns to talk about the browser. Four new checks route through an applied blueprint's browserSurface: playwright-present confirms Playwright is installed in the project, browser-present finds either a system Chrome or a Playwright-managed cache, playwright-mcp-reachable proves the MCP itself starts and answers, and playwright-mcp-redundant catches a project-scope entry shadowing a user-scope one. API-only projects skip the four in one line naming them (--check <name> overrides the skip if you want to run one anyway), so the noise floor stays flat for projects that never open a browser. @playwright/mcp and playwright are declared as optional peer dependencies, so npm and pnpm still install rcf-lite cleanly on a project that never plans to use them.
rcf init grew a discipline of its own around the Playwright MCP entry. It writes one only when it cannot find one already: the project-scope .mcp.json's own entries first (matched by command tail, so a differently-named entry pointing at @playwright/mcp still counts), then claude mcp list for whichever scope the harness reports (5 second timeout, text-output parse). When it cannot prove absence (no claude on PATH, non-zero exit, unreadable output) it writes a distinctly named playwright-rcf project-scope entry that shadows nothing by naming convention and prints a could not probe notice explaining what it did and how to opt out. rcf init --no-playwright-mcp suppresses the write step entirely; the probe still runs so the print-out remains honest.
The application-spa blueprint moves to v1.4.0 and delivery-ci-workflows to v2.2.0. application-spa grows a top-level browserSurface object on its manifest ({ declared: true, routes: [...], themes: [...] }) and contributes two acceptance-criteria-bearing stories: an icon renders across declared themes on the home route, and an unauthenticated visit to a protected route lands on the sign-in page. delivery-ci-workflows v2.2.0 contributes a story that binds a paired acceptance criterion on the elicited e2e check: the materialised pull-request-checks workflow gains a distinct e2e job iff at least one applied blueprint declares browserSurface.declared: true and checkSet.e2e is not explicitly false. The shipped example workflow and the alternate-provider notes (GitLab CI, CircleCI, Buildkite, Jenkins) each ship the e2e job as a documented example. browserSurface lives on the source blueprint.json only, deliberately: the applied-blueprint record schema stays additionalProperties: false for this release, and doctor and the workflow materialiser both read the field back through the applied record's source reference. The additive schema change to the applied record lands in a separate @stravica-ai/rcf-schemas release.
What this means for you. If your project has a browser surface, apply or re-apply application-spa and delivery-ci-workflows to pick up the new stories, and run rcf doctor to see the four new checks report. If Playwright is missing from your machine, doctor will say so before verify does. If your project is API-only, nothing changes: the four checks skip in one line and verify's browser tooling never enters the picture. And if your .mcp.json already carries a Playwright MCP entry (from an earlier rcf init run or from your own hand), a fresh rcf init will leave it alone.
0.16.0, 3 September 2026
External blueprint libraries complete. Phase 2c lands git and tarball fetchers with an on-disk cache checked into the tree, so a fresh clone lists library blueprints without a network round-trip. A refresh path re-resolves the tag or digest and refuses on drift. Two amendments follow: plain-path adds are now library-aware so an author's local edit loop stamps the same identity a qualified add would, and the managed agent-instructions block gains a paragraph teaching the operator-chooses conversational shape.
rcf define blueprint library add now accepts git+<url>#<annotated-tag-or-sha> and tarball URLs (with --sha256 <hex> for the pin). Fetched content lands under rcf/.blueprint-libraries/<libraryPrefix>/<libraryRef>/ and is checked into git as ordinary tree content, so anyone cloning your repo can rcf define blueprint list and see the library's blueprints without fetching anything themselves. Floating branches refuse categorically (main, master, HEAD, latest, develop, trunk), lightweight tags refuse with a diagnostic that points at annotation as the fix, and a tarball digest mismatch refuses the fetch and writes nothing. rcf define blueprint library refresh <prefix> re-resolves the annotated tag's peeled commit for git sources or re-downloads and re-verifies the digest for tarball sources, and refuses on drift. remove drops the on-disk cache for network sources. Zero new runtime dependencies: the git side shells out to your ambient git CLI, the tarball side uses built-in fetch(), zlib and a bundled minimal tar parser. Authentication is out of scope for this v1; ambient git access is the model, and no-access is definitive.
rcf define blueprint add <path> now walks up from the target directory looking for a library.json file. On a hit, the resolver requires the target to sit at <library-root>/blueprints/<slug> and stamps the same effective slug and identity a qualified <prefix>:<slug> add would after registration. Library-qualified addressing and plain-path addressing now produce identical stamped ids, so an author's "edit the file, apply from the path" inner loop lines up cleanly with the "register the library, apply the slug" outer loop. A path with no library.json in any ancestor keeps the earlier behaviour byte-for-byte. The trade-off is deliberate: an unregistered local library bypasses the review-on-add card, and the local provenance warning on apply is the mitigation.
The managed agent-instructions block grew a new paragraph under "How to talk to your operator". It teaches the plain-language shape you want out of your agent: the agent enumerates the blueprints and any registered libraries and offers one that fits; you choose, the agent never picks; qualified names and command lines belong in files and rcf output, not in the conversation. rcf doctor --fix refreshes the block in place if your project has an older version.
A new authoring standard doc lands inside the package at docs/library-authoring.md covering the library shape, the library.json field contract, prefix and band rules, the local-path authoring loop, registration, refresh and drift handling, and how a library interacts with core. It ships alongside a minimum-viable worked-example library the docs and the test suite both consume, so a drift in either trips the suite.
What this means for you. If you were waiting on git or tarball libraries to move beyond a local path, they land here: library add git+<url>#<tag> or a tarball URL with --sha256, and the fetched content rides in your repo from there. If you author blueprints inside a library folder in a project, a path-based add now stamps the library identity for you, so your inner loop matches your outer loop. Re-run rcf init to refresh the managed agent-instructions block with the new blueprint paragraph. And if you have a bit of your own reading to catch up on, the new authoring doc is the place.
0.15.0, 31 August 2026
A same-evening fix wave on top of 0.14.0. Four PRs closing off the last surface before the WSD handover, none of them breaking. If you were happy on 0.14.0 you can update casually; there is nothing to migrate.
Library-applied records now carry a durable ownership stamp. A blueprint that resolved through a registered external library gets a libraryPrefix field written onto its manifest record, and blueprint library remove reads that stamp as the authoritative signal for which records to unwind. Pre-0.15 records fall back to the source prefix, so nothing you have already applied is orphaned. The upshot is that re-registering a library on your project under a different prefix (a rename, a split, a publisher change) no longer strands records that came from it. Records applied from the shelf or from a local path still write no prefix, because those routes are not library-owned in the first place. The stamp needs the paired schema, so the @stravica-ai/rcf-schemas pin is now exact at 0.5.1.
The review-on-add card grew two lines that the earlier release should have carried. When you point rcf define blueprint library add at a library, the review card now prints a "Global topics these blueprints claim" section listing every blueprint in the library that would take a project-wide ADR (one topic per line, and the section disappears entirely when no blueprint claims one), and a new unconditional "Prefix check" line that reports the collision-gate outcome alongside the existing band-check line. The cross-topic surface of a library is visible before you commit to registering it, which is what section 8.1 of the external-libraries spec asked for.
blueprint supersede --incoming now accepts every source form that add does. Before this release the verb only recognised local paths, so @stock/<slug> and bare kebab slugs came back with "no blueprint.json found" even though they resolve fine on the add path. The persona re-run caught it in the second arc of the day. The verb now routes --incoming through the same resolver add uses, so paths, @stock/<slug>, bare kebab slugs and colon-qualified <libraryPrefix>:<slug> all work verbatim, and library-qualified sources record their effective slug on the supersedes entry the same way apply already does.
The delivery-ci-workflows blueprint moves to v2.1 with three additive workflowShape fields. packageManager is elicited (pnpm default, npm and yarn and bun recognised), and defaultBranch and trunkBranch both default to main. The guide teaches the per-manager install and cache blocks, the shipped GitHub Actions assets carry substitution markers so the material output reflects your project's real branch model and package manager, and a new "Bootstrap posture (the guaranteed-red first run)" section in the guide and README, plus a shipped starting-point ADR under assets/bootstrap/, name and demote the coverage-strict bootstrap trap the second dogfood run surfaced. Existing v2.0.0 applications keep validating; nothing regenerates automatically.
What this means for you. Update whenever you next open the tool. If you had blueprint library add reviews land without a global-topics or prefix-check line, they will now; if you tried blueprint supersede --incoming @stock/<slug> and got a not-found error, it will resolve; and if you re-apply the delivery-ci-workflows blueprint, you will see the new elicitation for package manager and branch names. Everyone else, rcf version --check remains the honest way to know when you are behind.
0.14.0, 31 August 2026
The update-awareness release, plus one breaking rename. The ci-pipeline blueprint is now delivery-ci-workflows, and it grew up in the same move: you declare your workflow shape once in a small config file and the blueprint composes a two-tier check catalogue (validation and strict coverage always; linting, type checks, unit tests and security scanning as you choose them), a release workflow in one of four modes from plain tagging up to a deploy handoff, and an optional scheduled audit. rcf define blueprint add ci-pipeline no longer resolves; the refusal names the new slug.
The update-awareness half is why this page now has a machine-readable twin. rcf version prints the installed version with no network call, and rcf version --check fetches the release feed this site publishes at /docs/rcf/releases.json, compares it against your install, and tells you in one line whether you are behind. The result is cached for hours, there is no telemetry in either direction, and a kill switch exists if you want the check off entirely. A new agent rule runs the check once at session start, so your agent mentions a newer release and offers the upgrade; it never installs anything without your explicit go.
Smaller pieces in the same release. External blueprint libraries reached the next stage: a local folder of your own blueprints can be registered as a named library and applied with a library:slug reference alongside the stock shelf (git and tarball sources are still to come). The live docs viewer gained scoped deep links, so rcf audit view open --blueprint <slug> lands you directly on what that blueprint contributed. The Clerk auth blueprint picked up Workers-runtime samples at v1.1.0. The product identity is now RCF Lite in every string the tooling prints, matching the package name. And a fix worth naming: applied blueprints had stopped recording where they came from, which made the viewer's scope report count every contribution as missing and collapsed blueprint list into one uncategorised heap; both behave again.
What this means for you. If any script, CI step or note of yours says ci-pipeline, swap in delivery-ci-workflows before your next compose; chains that already applied the old slug keep validating, nothing regenerates behind your back. Everyone else, update and run rcf version --check once: from this release onwards your install can tell you when it is behind, which makes this the last release you should have to discover by accident.
0.13.0, 31 August 2026
The packaging release: a fresh npm install rcf-lite now behaves the way the docs say it does. The fourteen stock blueprints ship inside the package itself, and rcf define blueprint add accepts the bare slug (deploy-cloudflare-workers) or the @stock/ form; no repository checkout, no filesystem path. Installing on Node 23 or older now refuses outright with a message naming the version it found, where previously npm would quietly resolve an ancient placeholder package and leave you wondering why nothing worked. The placeholder acceptance criterion seeded when a story is created is now replaced by your first real one instead of hanging around as an unmet criterion in coverage. And rcf init writes the agent wiring as a portable npx command, so a project moved to another machine keeps working without a re-init, then signs off by pointing you at rcf doctor.
The deploy-cloudflare-workers blueprint also took its first content bump, to v1.1.0: seven fixes found by following its own teaching against the real wrangler CLI. The ones worth knowing about: static assets are now taught to run the Worker first on gated paths, closing a default where a file at the right path would silently skip your auth; the invented [secrets] config block is gone, replaced by how the platform actually enforces secrets (every env.<NAME> your Worker reads is checked at deploy time); the vendor's version id and the git commit sha are now treated as the two different identifiers they are, both carried on the promote record and reconciled by the verifier; and the one bootstrap sequence that is verified piece-by-piece rather than end to end says so, in the asset, honestly.
What this means for you. Update, especially if your install sits behind a Node version manager: if you installed on Node 22 or 23 and got a strangely inert rcf, this release is why, and a reinstall on Node 24 gets you the real package. Blueprint commands in the stock blueprints reference now work as written on a clean install. If you applied the deploy blueprint at v1.0.0, re-apply it to pick up the corrected teaching and the new auth-gate acceptance criterion; the contribution ids do not change, so your chain absorbs it cleanly.
The shelf grew, 31 August 2026
Round two of the stock blueprint shelf shipped: eight new blueprints, and the six original ones renamed to category-qualified slugs. The shelf now carries fourteen blueprints across seven categories. The new arrivals are security-secrets-management, email-smtp-resend, security-auth-clerk, security-auth-oauth2, security-auth-keycloak, deploy-cloudflare-workers, persistence-data-d1 and observability-probe-endpoints. The renames are spa to application-spa, rest to application-api-rest, auth to security-auth-magic-link, persistence to persistence-data-sqlite and observability to observability-essentials; ci-pipeline kept its name. Several new blueprints deliberately conflict with siblings on shared decisions: the four auth-family blueprints conflict on the project's authentication model, the two persistence blueprints conflict on the durable-store engine and migration discipline, and the two observability blueprints conflict on the health-probe interface and readiness semantics. The conflict machinery treats these the same as any other: the add refuses, both sides are shown, and the resolution you pick is recorded on the chain.
What this means for you. If your rcf define blueprint add commands or CI notes reference the old slugs (spa, rest, auth, persistence, observability), swap in the new ones next time you compose. Your existing chains carry the slug they were applied with and keep validating; nothing regenerates automatically. If you want any of the new capabilities, the stock blueprints reference lists what each one gives you and how to apply it.
0.12.0, 28 August 2026
Test-pointer honesty moved into the shared schema. A test case that claims passing or failing must now point at a real executable test, enforced by @stravica-ai/rcf-schemas 0.5.0 rather than by a local workaround inside rcf-lite; a pending or skipped test case no longer needs a pointer at all, because "no executable has landed yet" is exactly what those statuses mean.
What this means for you. Most projects need no change. If your chain carried a pointer on every test case, it keeps validating. If your agent had been inventing placeholder pointers just to get pending test cases past validation, that workaround can retire: pointer-less pending and skipped cases are now legitimate. A passing claim with no pointer behind it was refused before and is still refused, which is the point.
0.11.0, 27 August 2026
A guidance-only release: no CLI, schema or runtime changes. The shipped pack gained three driving rules for the agent: validate the chain before acting on it, report method findings in your language rather than method vocabulary, and treat the method's failure modes as its own self-checks rather than something you are expected to diagnose.
What this means for you. Update and your agent simply behaves better in the driving loop: fewer stale-chain surprises, and findings arrive as "the sign-in story has no check for expiry" rather than a wall of document ids. Nothing for you to run or migrate.
0.10.0, 26 August 2026
Breaking: the CLI reorganised around the five stages of the method. Every verb now lives in a group, rcf audit coverage rather than rcf coverage, rcf define validate rather than rcf validate, with a small core set (init, doctor, guidance, mcp, help) staying at the top level. Old forms fail with a message naming the new form. The separate rcf-verify binary is gone; verify lives at rcf verify inside the one CLI.
What this means for you. If your agent drives the tooling over MCP, nothing changes: the MCP tool names did not move. If you have shell scripts, CI steps or notes that invoke the CLI directly, rewrite them to the grouped form; the cheatsheet shows the whole surface as it now stands. The error message on an old form tells you the new one, so migration is mechanical.
0.9.0, 25 August 2026
The blueprint release. rcf define blueprint landed: compose a pre-built implementation pattern onto your chain, list and remove what is applied, and resolve genuine conflicts between blueprints deliberately instead of silently. The first six stock blueprints were built on the mechanism in the same cycle: SPA, REST, auth, persistence, CI pipeline and observability.
What this means for you. Capabilities most products need stop being blank-page inventions. How it works explains the idea; the stock blueprints reference lists what is on the shelf today and how to apply it.
0.7.1 and 0.8.0, 12 August 2026
The first releases under the rcf-lite name, bringing the previously separate tooling together as one package on the public npm registry. 0.8.0 added the shared standards ruleset and taught the verifier to catch a subtle dishonesty class: a test that is narrower in scope than the check it claims to prove, such as a mocked test standing behind a check that promises deployed behaviour.
What this means for you. These are the releases that made npm install rcf-lite a sentence. If you are on anything from this era, update: everything above applies.
Earlier
Before August 2026 the tooling shipped as separate per-piece packages under different names. That history is preserved in the repository's tags and changelogs but is not useful for running the product today.