rcf-lite 0.28.4 → 0.29.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +107 -1
- package/bin/rcf.js +4 -0
- package/fixtures/canary-manifest.json +9 -9
- package/guidance/define-draft-shapes.md +89 -0
- package/guidance/define-intake.md +97 -0
- package/guidance/define-intent.md +107 -0
- package/guidance/discover-prototype.md +67 -0
- package/guidance/discovery-prototypes.md +69 -0
- package/guidance/harness-template.md +34 -0
- package/guidance/managed/agent-instructions-block.hash +1 -1
- package/guidance/managed/agent-instructions-block.md +34 -0
- package/guidance/manifest.json +9 -2
- package/package.json +1 -1
- package/rcf/adrs/adr-4124-define-freeze-verb.json +30 -0
- package/rcf/adrs/adr-4126-persona-tagged-blockers-two-levels.json +40 -0
- package/rcf/adrs/adr-4127-readiness-tab-order-and-register.json +40 -0
- package/rcf/adrs/adr-4129-questions-harness-driven-loop.json +25 -0
- package/rcf/adrs/adr-4130-intake-harness-split-tool-scanned.json +20 -0
- package/rcf/adrs/adr-4132-prototypes-in-discovery-as-evidence.json +20 -0
- package/rcf/adrs/adr-4133-dag-dependency-depth-layout.json +40 -0
- package/rcf/adrs/adr-4134-index-json-route.json +35 -0
- package/rcf/adrs/adr-4135-readiness-po-register-and-adapter.json +35 -0
- package/rcf/adrs/adr-4136-embedding-host-fixture.json +35 -0
- package/rcf/code-nodes/cn-725.json +18 -2
- package/rcf/code-nodes/cn-726.json +10 -2
- package/rcf/code-nodes/cn-727.json +13 -4
- package/rcf/code-nodes/cn-728.json +18 -2
- package/rcf/code-nodes/cn-729.json +10 -2
- package/rcf/code-nodes/cn-730.json +13 -3
- package/rcf/code-nodes/cn-731.json +20 -0
- package/rcf/code-nodes/cn-732.json +14 -0
- package/rcf/code-nodes/cn-733.json +14 -0
- package/rcf/code-nodes/cn-734.json +14 -0
- package/rcf/code-nodes/cn-735.json +20 -0
- package/rcf/code-nodes/cn-736.json +14 -0
- package/rcf/code-nodes/cn-737.json +14 -0
- package/rcf/code-nodes/cn-738.json +14 -0
- package/rcf/code-nodes/cn-739.json +18 -0
- package/rcf/code-nodes/cn-740.json +19 -0
- package/rcf/code-nodes/cn-741.json +16 -0
- package/rcf/code-nodes/cn-742.json +16 -0
- package/rcf/code-nodes/cn-743.json +15 -0
- package/rcf/code-nodes/cn-744.json +22 -0
- package/rcf/code-nodes/cn-745.json +16 -0
- package/rcf/code-nodes/cn-746.json +14 -0
- package/rcf/code-nodes/cn-747.json +18 -0
- package/rcf/code-nodes/cn-748.json +16 -0
- package/rcf/code-nodes/cn-749.json +16 -0
- package/rcf/code-nodes/cn-750.json +15 -0
- package/rcf/code-nodes/cn-751.json +18 -0
- package/rcf/code-nodes/cn-752.json +14 -0
- package/rcf/fbs/fbs-196.json +13 -5
- package/rcf/fbs/fbs-198.json +42 -0
- package/rcf/fbs/fbs-199.json +59 -0
- package/rcf/fbs/fbs-200.json +46 -0
- package/rcf/fbs/fbs-201.json +49 -0
- package/rcf/fbs/fbs-202.json +110 -0
- package/rcf/fbs/fbs-203.json +100 -0
- package/rcf/requirements/req-002.json +2 -2
- package/rcf/requirements/req-173.json +2 -2
- package/rcf/requirements/req-174.json +10 -4
- package/rcf/requirements/req-175.json +10 -4
- package/rcf/requirements/req-176.json +25 -0
- package/rcf/requirements/req-180.json +31 -0
- package/rcf/requirements/req-181.json +31 -0
- package/rcf/requirements/req-182.json +25 -0
- package/rcf/requirements/req-186.json +25 -0
- package/rcf/requirements/req-187.json +31 -0
- package/rcf/requirements/req-188.json +25 -0
- package/rcf/tacs/tac-4121-define-ledgers.json +15 -3
- package/rcf/tacs/tac-4122-define-gates.json +40 -4
- package/rcf/tacs/tac-4123-define-readiness.json +39 -3
- package/rcf/tacs/tac-4124-define-freeze.json +28 -0
- package/rcf/tacs/tac-4127-readiness-view.json +49 -0
- package/rcf/tacs/tac-4128-define-guidance.json +53 -0
- package/rcf/tacs/tac-4129-define-questions.json +45 -0
- package/rcf/tacs/tac-4130-define-intake-brief.json +35 -0
- package/rcf/tacs/tac-4131-build-dag-view.json +39 -0
- package/rcf/tacs/tac-4132-id-lookup.json +42 -0
- package/rcf/tacs/tac-4133-readiness-po-layer.json +37 -0
- package/rcf/tacs/tac-4134-wespa-host-fixture.json +54 -0
- package/rcf/test-suites/ts-016.json +3 -3
- package/rcf/test-suites/ts-215.json +148 -4
- package/rcf/test-suites/ts-216.json +19 -3
- package/rcf/test-suites/ts-218.json +78 -0
- package/rcf/test-suites/ts-219.json +70 -0
- package/rcf/test-suites/ts-220.json +78 -0
- package/rcf/test-suites/ts-221.json +78 -0
- package/rcf/test-suites/ts-222.json +100 -0
- package/rcf/test-suites/ts-223.json +94 -0
- package/rcf/test-suites/ts-224.json +70 -0
- package/rcf/test-suites/ts-225.json +78 -0
- package/rcf/test-suites/ts-226.json +158 -0
- package/rcf/test-suites/ts-227.json +38 -0
- package/rcf/test-suites/ts-228.json +86 -0
- package/rcf/test-suites/ts-229.json +83 -0
- package/rcf/user-stories/us-17302.json +50 -0
- package/rcf/user-stories/us-17401.json +14 -2
- package/rcf/user-stories/us-17402.json +55 -0
- package/rcf/user-stories/us-17403.json +60 -0
- package/rcf/user-stories/us-17502.json +60 -0
- package/rcf/user-stories/us-17503.json +65 -0
- package/rcf/user-stories/us-17601.json +58 -0
- package/rcf/user-stories/us-18001.json +55 -0
- package/rcf/user-stories/us-18002.json +35 -0
- package/rcf/user-stories/us-18101.json +35 -0
- package/rcf/user-stories/us-18202.json +40 -0
- package/rcf/user-stories/us-18601.json +55 -0
- package/rcf/user-stories/us-18602.json +50 -0
- package/rcf/user-stories/us-18603.json +45 -0
- package/rcf/user-stories/us-18701.json +50 -0
- package/rcf/user-stories/us-18702.json +50 -0
- package/rcf/user-stories/us-18801.json +45 -0
- package/rcf/user-stories/us-204.json +59 -0
- package/rcf/user-stories/us-205.json +64 -0
- package/rcf/user-stories/us-206.json +54 -0
- package/releases/releases.yaml +11 -1
- package/src/cli/freeze.js +730 -0
- package/src/cli/help.js +12 -0
- package/src/cli/ledger.js +228 -12
- package/src/cli/questions.js +288 -0
- package/src/cli/readiness.js +267 -49
- package/src/cli/view.js +29 -0
- package/src/define/freeze-record.js +30 -15
- package/src/define/ledgers.js +210 -11
- package/src/intake/index.js +1 -1
- package/src/intake/orchestrator.js +117 -0
- package/src/mcp/tools.js +354 -0
- package/src/query/delta.js +6 -0
- package/src/query/gates.js +314 -39
- package/src/query/index.js +16 -2
- package/src/query/questions.js +438 -0
- package/src/query/readiness.js +248 -7
- package/src/server/index.js +24 -2
- package/src/server/routes.js +68 -1
- package/src/setup/identity-seed.js +17 -0
- package/src/view/build-dag.js +563 -0
- package/src/view/components/badge.js +41 -0
- package/src/view/components/diff.js +72 -0
- package/src/view/components/doc-row.js +62 -0
- package/src/view/components/empty-state.js +35 -0
- package/src/view/components/entity-selector.js +137 -0
- package/src/view/components/filter-bar.js +97 -0
- package/src/view/components/findings-list.js +49 -0
- package/src/view/components/index.js +12 -0
- package/src/view/components/pill.js +46 -0
- package/src/view/components/sub-tab-strip.js +43 -0
- package/src/view/components/toast.js +25 -0
- package/src/view/components-fixture.js +265 -0
- package/src/view/doc-renderers/architecture.js +304 -0
- package/src/view/doc-renderers/build.js +160 -0
- package/src/view/doc-renderers/index.js +2 -0
- package/src/view/doc-renderers/prd.js +35 -6
- package/src/view/html-page.js +700 -602
- package/src/view/index.js +96 -3
- package/src/view/live-client.js +39 -6
- package/src/view/needs-work.js +79 -0
- package/src/view/page-init.js +2193 -0
- package/src/view/readiness/phrasebook.js +115 -0
- package/src/view/readiness/po-layer.js +288 -0
- package/src/view/readiness/question-adapter.js +329 -0
- package/src/view/readiness/stage-legend.js +71 -0
- package/src/view/readiness.js +505 -0
- package/src/view/style.css +2017 -382
- package/src/view/test-host/embed-client.js +121 -0
- package/src/view/test-host/fixture.js +183 -0
- package/src/view/test-host/lints.js +220 -0
- package/src/view/view-index.js +323 -0
package/CHANGELOG.md
CHANGED
|
@@ -6,11 +6,117 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
|
|
10
|
+
## [0.29.0] - 2026-10-03
|
|
11
|
+
|
|
12
|
+
0.29.0 lands the viewer UI refresh train (nine PRs that rebuild the shell, add shared components, redesign the Requirements, Architecture, Build and Readiness tabs, ship a Build DAG sub-tab, add fast ID lookup, and prove the embedding contract with a same-origin test-host fixture), the DEFINE readiness persona split (two readiness levels, `--level` and `--persona` on `rcf define readiness`, a Readiness tab as tab 1), and the first three DEFINE step 3 PRs (document intake into the brief ledger with the closed `resolvedBy` grammar, a `rcf define questions` verb with three new MCP tools and two argument-free prompts for the harness loop, and the `[draft]` shapes gate across TAC purpose, interface and core-entity homes with a DISCOVERY prototypes doctrine). The brief said 0.29.0 was never tagged; it is tagged here, and the spec sections that referred to those D2 behaviours as "0.30.0" now read 0.29.0.
|
|
13
|
+
|
|
14
|
+
Scope note: DEFINE step 3 PR 5 (D3 bite) is still on the cloud at cut time and is NOT included; it rides a later minor. Spec amendment note: `projects/rcf-lite-wsd/specs/2026-10-01_define-step3-po-elicitation-spec.md` section 16 and every "0.30.0" reference to the D2 `skeleton:resolvedBy` tightening, the `rcf define ledger <name> update <id>` subverb and the `resolvedBy` closed grammar should read "0.29.0" at the next amendment pass.
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
|
|
18
|
+
- **Viewer UI refresh PR 1 of 9: shell, brand tokens, theme contract, embed contract, Router and relative asset refs (`#263` + `#265`; w-2026-10-02-dave-017).** AppShell with a compact header (icon mark, product block, sticky tabstrip, tools well) and a one-line footer carrying version, GitHub, docs links and the live-update pill. Full `--sv-*` Stravica brand token set under `:root[data-theme="light"]` and `:root[data-theme="dark"]` with a `prefers-color-scheme` fallback; pre-PR-1 `--colour-*` names kept as aliases so doc-renderer, Mermaid and Product Map rules get dark theme for free. `theme=light|dark|auto` and `embed=1` on `/`; live theme switch via same-origin `postMessage({ type: "rcf-view-theme", theme })` (origin checked). Router (`#tab=&sub=&entity=`) with bare-id compatibility and query-string preservation on every hash write. Relative asset and stream refs for embedding: `./style.css`, `./mermaid.min.js`, `./page-init.js`, `./live-client.js`, `./events`, `./scope.json`, `./product-map/<group>`. Inline-script-free shell: the former inline IIFE lives in `src/view/page-init.js` served by a new relative route (see "For embedders" below).
|
|
19
|
+
- **Viewer UI refresh PR 2 of 9: shared components layer and shell polish (#266; w-2026-10-02-dave-010).** Six shared component helpers under `src/view/components/` land for the per-tab cutover PRs: `DocRow`, `FilterBar`, `Badge`, `EmptyState`, `Toast`, `SubTabStrip`, with matching `.rcf-*` CSS. Toast container mounted once in the shell outside `#rcf-live-content` so the SSE innerHTML swap cannot blow it away. `/_fixtures/components` route renders every shared component in isolation with sample data. Shell polish per decision 17: `resolveProductHeader()` returns the project name only; no technology chip under any register.
|
|
20
|
+
- **Viewer UI refresh PR 3 of 9: Requirements tab and PRD EntitySelector (#268; w-2026-10-02-dave-025).** Requirements tab under `#tab=requirements` ships a FilterBar (text, Area, Priority, Status, Needs-work toggle), Expand/Collapse all and a live count; FilterBar state mirrors into the hash. DocRow per REQ carries `data-domain`, `data-priority`, `data-status`, `data-needswork`, `data-text`; row body has nested per-US DocRows with the full renderUserStory body, slice diagram and raw-JSON disclosure as collapsed `<details>` so first-paint stays cheap. `#entity=US-304` resolves to REQ-003 and US-304; bare `#entity=<id>` works. Needs-work set sourced from `model.readiness.levels.intentComplete.blockedBy` filtered to the engineer-plain reasons (viewer never re-runs gates). PRD tab (`#tab=overview` for hash backwards compatibility) collapses the five lists into `<details>` with count badges, drops the 109 inline requirement links, and mounts a shared EntitySelector below the article (bold total line, type-ahead jump input, 21 area chips deep-linking into `#tab=requirements&domain=<area>`). Component payload data rides on `data-*` attributes, never inline `<script>` bodies.
|
|
21
|
+
- **Viewer UI refresh PR 4 of 9: Architecture tab with TAD sections and TAC/ADR filters (#269; w-2026-10-02-dave-026).** Six TAD sections (`systemOverview`, `architecturePrinciples`, `integrationArchitecture`, `operationalConcerns`, `dataArchitecture`, `securityArchitecture`) render as shared `DocRow` with a one-line preview, closed by default. Absent sections keep their heading, read "Nothing written yet" with an `empty` badge, and name the exact authoring command `rcf define update TAD-001 --set <section>.<field>="..."`. Components (TAC) and Decisions (ADR) panels each use shared `FilterBar` plus `DocRow` list; TAC rows carry interface and dependency count badges, ADR rows carry a status pill sized against the dogfood vocabulary. Hash scheme extends: `#tab=architecture[&cq=...][&cstatus=...][&dq=...][&dstatus=...][&open=<tad-section-keys>]`. Raw TAD JSON kept as a muted collapsed disclosure at the foot of the tab.
|
|
22
|
+
- **Viewer UI refresh PR 5 of 9: Build tab with Specs and sub-tab strip (#271; w-2026-10-02-dave-027).** SubTabStrip "Specs | DAG" inside the Build tab (DAG is a placeholder empty state at PR 5; PR 6 wires it). BuildStats card with six totals read from `computeQueue({ fbsItems })` (items, verified, complete, in progress, not started, buildable now = `queue.totals.actionable`). Specs FilterBar (text, status, area, size, Buildable-now toggle) over a shared DocRow list. Expanded Spec body: summary, approach, AC and dep links, deliverables, context links (TACs, ADRs, TAD sections), "Show in the DAG" pointer, raw JSON disclosure. Hash scheme extends: `#tab=build[&sub=specs|dag][&q=][&status=][&domain=][&size=][&buildable=1]`.
|
|
23
|
+
- **Viewer UI refresh PR 6 of 9: Build/DAG sub-tab (#272; w-2026-10-02-dave-031).** Lands DagCanvas, DagInspector, DagToolbar and the unconnected lane: depth-by-`dependsOnFbsIds` columns, buildOrder rows, node-count critical path (longest chain), hidden unconnected lane with a visible count. Click-to-highlight closure (upstream outlined in link colour, downstream in warning, rest dimmed); inspector lists direct needs and waits-on with Open-in-Specs; `#tab=build&sub=dag&entity=FBS-<n>` deep-links. Inspector payload rides on a `data-rcf-dag-inspector-data` attribute, never an inline `<script>` body. Chain: REQ-002 amended, US-204 new (seven ACs), TAC-4131, ADR-4133.
|
|
24
|
+
- **Viewer UI refresh PR 7 of 9: ID lookup over `./index.json` (#275; REQ-002 / US-205; TAC-4132; ADR-4134).** The viewer serves a new relative route `./index.json` built from `BuiltTreeModel` on every rewalk, one row per document id plus one per AC, carrying `{ id, kind, title, snippet, parent, tab }` (`src/view/view-index.js` + `src/server/routes.js` + `src/server/index.js`). A SearchButton renders to the right of the tabstrip and a LookupModal mounts outside `#rcf-live-content` so the 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 is fetched lazily on first open and refreshed when the next SSE `tree-update` event lands (`__rcfLookupDirty` is set in `src/view/live-client.js`). A pick writes `#tab=<tab>&entity=<id>` through the existing writeHash so `?embed=` and `?theme=` survive every navigation. Keyboard: up/down/Enter/Esc; the modal is a `role="dialog"` with `aria-modal`, labelled live-region status, and the SearchButton is `aria-label`-ed as `Find any document or AC (Cmd/Ctrl+F)`. The new relative viewer route is `./index.json` (released alongside PR 1's `./page-init.js`; wespa's reverse-proxy allow-list is extended before the version pin bump).
|
|
25
|
+
- **Viewer UI refresh PR 8 of 9: Readiness tab Product Owner redesign (#277; REQ-180 / US-18002 / TAC-4133 / ADR-4135; w-2026-10-02-dave-033).** PO layer with two equal-height VerdictCards (muted chain term on both), QuestionCards grouped by source span, Requirements-that-still-need-work table, and a "For engineers" DocRow at the foot that collapses the pre-PR-8 engineer rendering (never removed from the DOM in any register, per AC-18002-3). Readiness phrasebook ships now. Feature-detected adapter seam 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. `src/view/index.js` folds `computeQuestions(readiness, { tree, ledgers, profileText, persona: 'productOwner' })` onto `readiness.{questions,questionGroups,questionOptional,questionEngineer}` before the view reads it, so the two sources render identical labels on the dogfood tree.
|
|
26
|
+
- **Viewer UI refresh PR 9 of 9: embedding proof via a same-origin test-host fixture (#279; REQ-002 / US-206; TAC-4134; ADR-4136; w-2026-10-02-dave-034).** `src/view/test-host/` (`fixture.js`, `embed-client.js`, `lints.js`) 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. The fixture ships a 56 px header, a resizable sidebar (64 to 400 px) and a toggle posting `rcf-view-theme`. Three in-suite guards pin the embedding contract: framing headers absent (no `X-Frame-Options`, no CSP), zero `target="_top"` across all served responses, and every `src/view` storage key under the `rcf-view:v1:` namespace.
|
|
27
|
+
- **DEFINE viewer: Readiness tab as tab 1 and Overview-to-PRD rename (#262; REQ-180 / REQ-181 / US-18001 / US-18101; TAC-4127; ADR-4127; w-2026-10-01-dave-003 PR C).** `src/view/readiness.js` lands and `src/view/html-page.js` wires it as the first tab of the HTML review surface. 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). The tab renders the `computeReadiness` object top-to-bottom in the layout spec section 5 pins: tree line, two verdict pills with `formatVerdictLines` strings as labels, two per-persona next-action lines, D1 to D8 state chips, blockers grouped by persona (register orders the pair; the non-register group collapses with its count visible, never omitted), delta list grouped by REQ ancestor with a document-level `diff` on changed items, per-stage check detail, coverage tree-versus-delta, decisions outstanding, a Freeze now control enabled iff `levels.readyToBuild.ok`, and the loaded freeze record. The renderer is pure: it never recomputes readiness or hits disk. Three shared view components (`src/view/components/{pill,findings-list,diff}.js`) land as additive modules.
|
|
28
|
+
- **DEFINE readiness CLI: `--level` and `--persona` flags, persona-grouped text report (#261; ADR-4126; REQ-175 / US-17503; TAC-4123; w-2026-10-01-dave-003 PR B).** `rcf define readiness` gains `--level intent|build` and `--persona productOwner|engineer`. `--level intent` exits 4 iff `levels.intentComplete.ok === false`, `--level build` exits 4 iff `levels.readyToBuild.ok === false` (stricter than `--check all` on unacknowledged warn-with-ack failures; the `[warn]` line still prints). When both `--check` and `--level` are given, the invocation exits 4 if either policy says 4. With neither flag the exit code stays 0. `--persona` is a display filter only: it never affects the exit code or `--json` content, and is ignored under `--json`. Unknown values exit 2 with a usage line naming the accepted set. 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 (PO first when `register: productOwner` or when the marker is `unstated`/absent; engineer first when `register: engineer`). The JSON gains `_meta.level` reflecting the invocation (`"intent"`, `"build"` or `null`).
|
|
29
|
+
- **DEFINE readiness: persona tags on every gate check, two readiness levels (#260; ADR-4126; REQ-174 / US-17402 / US-17403 and REQ-175 / US-17502; TAC-4122 and TAC-4123; w-2026-10-01-dave-003 PR A).** Every entry in `stages[].checks[]` carries `persona` (`productOwner` | `engineer`) and a one-sentence `question` heading, declared in `CHECK_PERSONA` / `CHECK_QUESTION` maps in `src/query/gates.js`. The `notApplicable` placeholder (`stage:<D>:scope`) carries the `STAGE_FALLBACK_PERSONA` for its stage so the per-check vocabulary is total. `skeleton:reqFields` splits into `skeleton:reqIntent` (productOwner: description without TODO + domain) and `skeleton:reqShape` (engineer: shapeClassification.shapes), each evaluating every REQ independently. `decisions:allAnswered` splits into `decisions:wellFormed` (productOwner) and `decisions:allAnswered` (engineer). A new D3 check `shapes:draftSettled` fails any interface whose `description` starts with `[draft]` (leading whitespace tolerated). `computeReadiness` folds `levels.intentComplete`, `levels.readyToBuild`, `personas.productOwner.blockers` and `personas.engineer.blockers` on every read. `deriveNextAction(stages, persona?)` gains an optional persona filter. New shared helper `formatVerdictLines(result)` builds the two verdict strings. All additions are strictly additive; `rcf define freeze` is untouched and remains L2-only.
|
|
30
|
+
- **DEFINE step 3 PR 1: document intake into the brief ledger, `rcf define ledger <name> update <id>` subverb, closed `resolvedBy` grammar (#270; REQ-187 / US-18701 / US-18702; REQ-173 amended / US-17302; TAC-4121 amended, TAC-4130 new).** `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`; unknown `[kind]` exits 2 before any write. The mechanical intake scans run over new statements against existing ones and append `openQuestion` statements per finding (`--no-scan` with `--findings` exits 2). 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 before any write. The D2 `skeleton:resolvedBy` check now parses the pointer against the closed grammar (`REQ-nnn`, `TAD.entity:<name>`, `PRD.user:<name>`, `TAD.system:<name>`, `TAC-nnnn`, `omitted:<reason>`); see Changed for the dropped title-hit fallback. Chain: FBS-202 new (holds the new ACs with `executionStatus: notStarted`; the CN axis is deferred); `docs/capability-tags.md` grows a `define-intake` slug.
|
|
31
|
+
- **DEFINE step 3 PR 2: `rcf define questions` verb, three MCP tools and two argument-free prompts (#274; REQ-186 / US-18601 / US-18602 / US-18603; TAC-4128, TAC-4129; ADR-4129, ADR-4130).** `rcf define questions` turns every failing product-owner check into one plain question carrying its exact write-back (real three-step `create req; define update <REQ-id> --set description=... --set domain=...; ledger brief update ... --resolved-by <REQ-id>` for new REQ; real `create us --parent --title`, `define update <US-id> --json --set story='{...}'` and `create ac --parent --description "[happy] ..."` sequence for 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 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 (not 20). Termination under `--stage` is `result.ok` alone (not `result.ok || result.remaining === 0`). Stable sort of questions by `(stageIndex, sourceSpan, originalIndex)`.
|
|
32
|
+
- **DEFINE step 3 PR 3: `[draft]` shapes across TAC purpose, interface and core-entity homes; DISCOVERY prototypes doctrine; two new argument-free prompts (#278; REQ-188 / US-18801; REQ-182 / US-18202; ADR-4132).** `parseInterfaceDraft` becomes a thin wrapper over a shared `hasDraftMarker` string test; two sibling readers `parseTacPurposeDraft` and `parseCoreEntityDraft` cover the new homes. `checkD3Shapes` enumerates all three draft homes and emits `shapes:draftSettled` findings with ids `<tacId>:<name>`, `<tacId>` and `TAD.entity:<name>`. D3 `notApplicable` widens to include any tree-wide `[draft]` core entity so a draft-only tree reports under D3 rather than being skipped. `guidance/discovery-prototypes.md` (slug `discovery-prototypes`, `rcf://docs/discovery-prototypes`) 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. `guidance/manifest.json` registers the slug and the two prompts; the managed block gains the "Prototypes in DISCOVERY (ADR-4132)" rule beside the existing "Prototype rule". `docs/capability-tags.md` grows a `define-drafts` slug.
|
|
33
|
+
|
|
34
|
+
### Changed
|
|
35
|
+
|
|
36
|
+
- **DEFINE D2 `skeleton:resolvedBy` tightens to the closed pointer grammar (PR #270, breaking under the pre-1.0 convention; spec amendment: 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 (`REQ-nnn`, `TAD.entity:<name>`, `PRD.user:<name>`, `TAD.system:<name>`, `TAC-nnnn`, `omitted:<reason>`) now fails `skeleton:resolvedBy` on D2. Operators with brief ledgers written against 0.28.4 must rewrite non-conforming `resolvedBy` values to the closed grammar; `rcf define ledger brief update <id> --resolved-by <pointer>` validates before write.
|
|
37
|
+
- **Managed agent-instructions block regenerated: adds the "Prototypes in DISCOVERY (ADR-4132)" rule and registers the four argument-free DEFINE/DISCOVERY prompts (PRs #274 and #278).** `scripts/gen-managed-artefacts.mjs` reran on PR 2 and PR 3 of DEFINE step 3; the block hash changed. Agents update their copy of the managed block by rerunning `rcf init` (`minAgentAction: rerun-init`).
|
|
38
|
+
|
|
39
|
+
### Removed
|
|
40
|
+
|
|
41
|
+
- **Viewer Build tab: the "FBS slots" ordered list and the "Test suites" section are gone (PR #271).** The Build tab's "Specs" sub-tab replaces both. Suites stay reachable via AC links and PR 7's ID lookup (Cmd/Ctrl+F). Consumers that embedded a deep link into the old Build-tab FBS-slots list need to update to `#tab=build&sub=specs&entity=FBS-<n>` or to the DAG sub-tab `#tab=build&sub=dag&entity=FBS-<n>`.
|
|
42
|
+
|
|
43
|
+
### Fixed
|
|
44
|
+
|
|
45
|
+
- **DEFINE D2 skeleton gate reads TAD at the schema-authorised path (#259; w-2026-09-25-dave-004 defect A, REQ-174 / US-17401 / TAC-4122).** `checkD2Skeleton` in `src/query/gates.js` now reads `tad.dataArchitecture.dataStores` and `tad.dataArchitecture.coreEntities` instead of the top-level `tad.dataStores` / `tad.coreEntities` that slice-2 drifted onto. The authority is rcf-schemas 0.6.3 (`tad.schema.json` requires both arrays under `dataArchitecture`), so the previous top-level reads failed `skeleton:tadPersistence` on every valid tree carrying a persistence REQ. The `failing` entry ids tracked the move to `TAD.dataArchitecture.dataStores` and `TAD.dataArchitecture.coreEntities`.
|
|
46
|
+
- **DEFINE D1 brief gate: a fresh `rcf init` tree now satisfies the review-surface marker without operator edits (#259; w-2026-09-25-dave-004 defect B, REQ-174 / US-17401 / TAC-4122).** `src/setup/identity-seed.js` IDENTITY_TEMPLATE now carries a `## Surface` section between `## Register` and `## Project-scoped notes`, mirroring the Register section's shape: a short italicised explanation, one bullet each for `viewer` / `runningApp` / `prDiff`, and a bare `prDiff` line as the default. `checkD1Brief`'s `profile:surface` check now passes on a clean post-init tree. The slice-1 idempotency contract (an existing profile.md is left byte-identical) is preserved.
|
|
47
|
+
|
|
48
|
+
### For embedders (wespa reverse-proxy)
|
|
49
|
+
|
|
50
|
+
- **New relative routes shipped since 0.28.4.** `GET /page-init.js` (PR 1), `GET ./index.json` (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).
|
|
51
|
+
- **No new allow-list routes from PR 9.** `GET /test-host.html` and `GET /test-host.js` are served ONLY when `--test-host` (CLI) or `RCF_VIEW_TEST_HOST=1` (env) is set, and return 404 otherwise. Production wespa does not set the flag, so the allow-list is unchanged by PR 9.
|
|
52
|
+
- **Removed inline script in the viewer shell (PR 1).** CSP hash pin for the inline shell IIFE is no longer needed; the IIFE lives in `src/view/page-init.js` (served by `GET /page-init.js`). Wespa's CSP for `/rcf-viewer/*` should allow the external script in place of the previous inline hash pin.
|
|
53
|
+
- **Live update pill in the footer (PR 1).** Carries connection state (connecting, open, retrying, closed); styled through the `--sv-*` tokens so it tracks the theme.
|
|
54
|
+
- **`embed=1` and `theme=light|dark|auto` query params (PR 1).** `embed=1` stamps `data-embed="1"` on `<html>`, suppresses the title block and footer, and left-aligns the tabstrip; the icon mark and project name remain. `theme` on `/` either stamps `data-theme` (explicit value), clears it (`auto`), or leaves the default light (absent).
|
|
55
|
+
- **Live theme switch via `postMessage({ type: "rcf-view-theme", theme })` (PR 1).** Same-origin only; the viewer's listener checks `event.origin`.
|
|
56
|
+
- **Hash contract (PR 1, extended by PRs 3 to 9).** `#tab=<name>&sub=<name>&entity=<id>` is the canonical hash form; bare `#<id>` and `#entity=<id>` keep working. `?embed=` and `?theme=` and unknown query params survive every in-viewer navigation.
|
|
57
|
+
- **`./index.json` (PR 7).** Lazy JSON index served from the viewer root; refreshed on every SSE `tree-update`.
|
|
58
|
+
|
|
9
59
|
## [0.28.4] - 2026-09-30
|
|
10
60
|
|
|
11
61
|
Note: 0.28.3 (2026-09-22 below) was never tagged or published; its entries ship in 0.28.4 together with the ones here.
|
|
12
62
|
### Added
|
|
13
63
|
|
|
64
|
+
- **DEFINE workflow: `rcf define freeze` CLI verb (REQ-176, first slice of the 0.29.0 train; slices 1 and 2 shipped in 0.28.4 on 2026-09-30).** New module `src/cli/freeze.js` is the only
|
|
65
|
+
writer of `rcf/define/freeze.json` in the shipped product. It runs
|
|
66
|
+
`computeReadiness` once (REQ-175) over the live tree, freeze record
|
|
67
|
+
and four ledgers; refuses (exit 4) on any stage state `failing`
|
|
68
|
+
after applying any `--ack` acknowledgements; and, on success, writes
|
|
69
|
+
the freeze record via `saveFreezeRecord` (REQ-172) plus the
|
|
70
|
+
proposal 2026-09-22 v3 §2.5 summary line the operator signs off.
|
|
71
|
+
`--ack <gate> --reason <text>` is accepted only for the three
|
|
72
|
+
warn-with-ack gates (`define.shapes` / D3 / shapes,
|
|
73
|
+
`define.crosscut` / D5 / crosscut, `define.consistency` / D6 /
|
|
74
|
+
consistency); `--ack` on any other gate is a usage refusal
|
|
75
|
+
(exit 2) with a stderr message naming the accepted set. Ack pairs
|
|
76
|
+
are folded in-memory at the current tree hash and the readiness
|
|
77
|
+
compute runs with a synthesised freeze context so D8's
|
|
78
|
+
`priorGates` check sees the acked stages as `acknowledged`. On
|
|
79
|
+
success the record carries `frozenAt` (ISO UTC now), `treeHash`
|
|
80
|
+
(from `computeDelta`), `docHashes`, `briefStatements`,
|
|
81
|
+
`gates` (per-stage envelope including acked entries),
|
|
82
|
+
`counts` (`req` / `us` / `ac` / `acByClass` / `tac` /
|
|
83
|
+
`interfaces` by kind / `adr` / `fbs`), `litmus`
|
|
84
|
+
(`{ attestedAt: [], readers: 0 }` default; `--litmus-attested
|
|
85
|
+
D3,D6` records the agent's attestation per proposal §9 decision
|
|
86
|
+
7), `versions` (`rcfLite` / `ruleset` / `schemas` read from
|
|
87
|
+
package.json, `src/ruleset/ruleset.json` and the installed
|
|
88
|
+
`@stravica-ai/rcf-schemas`), `note` and `override: null`. The
|
|
89
|
+
producer is wrapped with `runWithAdmissibilityGate` per ADR-4124;
|
|
90
|
+
refused admissibility is informational (a stderr `[warn]` line)
|
|
91
|
+
and never a freeze refusal (ADR-4123 carried). `--status` prints
|
|
92
|
+
the current record and the live delta summary without running any
|
|
93
|
+
gates and without writing; `--status --json` emits
|
|
94
|
+
`{ record, delta }`. `--json` on a freeze success emits
|
|
95
|
+
`{ record, summary, delta }`. The `--litmus <n>` real-dispatch
|
|
96
|
+
runner is a named 0.30 seam.
|
|
97
|
+
|
|
98
|
+
### Changed
|
|
99
|
+
|
|
100
|
+
- **Freeze record `override` is now a required-nullable field
|
|
101
|
+
(slice 3, resolves the slice-1 P3).** `validateFreezeRecord` in
|
|
102
|
+
`src/define/freeze-record.js` throws `FreezeRecordError` with
|
|
103
|
+
`field: 'override'` when the key is missing; `saveFreezeRecord`
|
|
104
|
+
refuses to write a body that omits override. `loadFreezeRecord`
|
|
105
|
+
defaults a missing key to `null` on read so pre-slice-3
|
|
106
|
+
freeze.json records survive without a migration step. Every
|
|
107
|
+
fresh freeze written by the new CLI stamps `override: null`, so
|
|
108
|
+
the on-disk shape converges on the current schema the next time
|
|
109
|
+
a project freezes.
|
|
110
|
+
|
|
111
|
+
### Fixed
|
|
112
|
+
|
|
113
|
+
- **DEFINE hygiene: the ` -- ` double-dash is gone from the
|
|
114
|
+
readiness CLI stage header and the CHANGELOG's TODO-regex line
|
|
115
|
+
(slice 3).** The readiness `rcf define readiness` stage block
|
|
116
|
+
now uses `: ` between the stage id / gate and the state label
|
|
117
|
+
(`D1 (define.brief): failing`); the CHANGELOG's `The regex is
|
|
118
|
+
now /\bTODO:/` line likewise uses a colon.
|
|
119
|
+
|
|
14
120
|
- **Product Map tab on the review surface (#238).** Merged on `main` at
|
|
15
121
|
`ab35dd7d`; grouped by shape, component, trace coverage, capability,
|
|
16
122
|
blueprint. This entry backfills the changelog now that the following
|
|
@@ -133,7 +239,7 @@ Note: 0.28.3 (2026-09-22 below) was never tagged or published; its entries ship
|
|
|
133
239
|
the whole-word `/\btodo\b/i`, which false-positived on prose
|
|
134
240
|
mentioning the word ("no AC description contains the scaffold TODO
|
|
135
241
|
placeholder" on US-17401 / AC-17401-4 tripped D4 against itself).
|
|
136
|
-
The regex is now `/\bTODO
|
|
242
|
+
The regex is now `/\bTODO:/`: case-sensitive uppercase `TODO`
|
|
137
243
|
followed by a colon, matching every scaffold string
|
|
138
244
|
`src/core/store/init.js` and `src/core/store/writer.js` write for a
|
|
139
245
|
fresh `rcf init` / `rcf define create`. `src/cli/validate.js` keeps
|
package/bin/rcf.js
CHANGED
|
@@ -53,6 +53,8 @@ import { main as intakeMain } from '../src/cli/intake.js';
|
|
|
53
53
|
import { main as evalMain } from '../src/cli/eval.js';
|
|
54
54
|
import { main as ledgerMain } from '../src/cli/ledger.js';
|
|
55
55
|
import { main as readinessMain } from '../src/cli/readiness.js';
|
|
56
|
+
import { main as questionsMain } from '../src/cli/questions.js';
|
|
57
|
+
import { main as freezeMain } from '../src/cli/freeze.js';
|
|
56
58
|
|
|
57
59
|
// Verify group members are handled by the verify-suite dispatch tree.
|
|
58
60
|
import { main as verifyRunMain } from '../src/verify/cli/run.js';
|
|
@@ -99,6 +101,8 @@ export const GROUPS = {
|
|
|
99
101
|
standards: standardsMain,
|
|
100
102
|
ledger: ledgerMain,
|
|
101
103
|
readiness: readinessMain,
|
|
104
|
+
questions: questionsMain,
|
|
105
|
+
freeze: freezeMain,
|
|
102
106
|
},
|
|
103
107
|
build: {
|
|
104
108
|
// build sub-verbs are dispatched by build.js internally (queue |
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"registerCanary": [
|
|
3
3
|
{
|
|
4
|
-
"id": "rc-2026-
|
|
5
|
-
"createdAt": "2026-
|
|
6
|
-
"buildVersion": "0.
|
|
4
|
+
"id": "rc-2026-10-03-001",
|
|
5
|
+
"createdAt": "2026-10-03T12:16:10.630Z",
|
|
6
|
+
"buildVersion": "0.29.0-mockdriver",
|
|
7
7
|
"fixturePromptId": "canary-prompt-01",
|
|
8
8
|
"responseWordCount": 55,
|
|
9
9
|
"grades": {
|
|
@@ -34,9 +34,9 @@
|
|
|
34
34
|
"shipDespiteFailReason": "mock canary driver used; no real subagent was dispatched. This record verifies canary infrastructure only, not the register itself."
|
|
35
35
|
},
|
|
36
36
|
{
|
|
37
|
-
"id": "rc-2026-
|
|
38
|
-
"createdAt": "2026-
|
|
39
|
-
"buildVersion": "0.
|
|
37
|
+
"id": "rc-2026-10-03-002",
|
|
38
|
+
"createdAt": "2026-10-03T12:16:10.631Z",
|
|
39
|
+
"buildVersion": "0.29.0-mockdriver",
|
|
40
40
|
"fixturePromptId": "canary-prompt-02",
|
|
41
41
|
"responseWordCount": 55,
|
|
42
42
|
"grades": {
|
|
@@ -67,9 +67,9 @@
|
|
|
67
67
|
"shipDespiteFailReason": "mock canary driver used; no real subagent was dispatched. This record verifies canary infrastructure only, not the register itself."
|
|
68
68
|
},
|
|
69
69
|
{
|
|
70
|
-
"id": "rc-2026-
|
|
71
|
-
"createdAt": "2026-
|
|
72
|
-
"buildVersion": "0.
|
|
70
|
+
"id": "rc-2026-10-03-003",
|
|
71
|
+
"createdAt": "2026-10-03T12:16:10.631Z",
|
|
72
|
+
"buildVersion": "0.29.0-mockdriver",
|
|
73
73
|
"fixturePromptId": "canary-prompt-03",
|
|
74
74
|
"responseWordCount": 55,
|
|
75
75
|
"grades": {
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# Drafting the engineer's entry shapes
|
|
2
|
+
|
|
3
|
+
This document is the content of the `rcf_define_draft_shapes` MCP
|
|
4
|
+
prompt served argument-free by the server. The agent reads it once
|
|
5
|
+
per session and runs the draft pass after L1 is green. The product
|
|
6
|
+
owner is not in the room; the agent populates `[draft]`-marked
|
|
7
|
+
entities, components and interfaces so the engineer walks into a tree
|
|
8
|
+
whose shape is honest about what is still owed.
|
|
9
|
+
|
|
10
|
+
## When to run
|
|
11
|
+
|
|
12
|
+
Run this pass once `rcf define readiness --level intent` prints
|
|
13
|
+
`levels.intentComplete.ok === true` and the product owner has stepped
|
|
14
|
+
back. Not before. The draft pass reads only the brief ledger, the
|
|
15
|
+
decisions ledger and the current tree; it writes only `[draft]`-marked
|
|
16
|
+
content. `shapes:draftSettled` then lists exactly what the engineer
|
|
17
|
+
has yet to own.
|
|
18
|
+
|
|
19
|
+
Nothing in the draft pass can fail a product-owner check. That is the
|
|
20
|
+
property that keeps L1 and the draft pass independent. If an edit
|
|
21
|
+
would fail any check in the `productOwner` persona, stop and raise it
|
|
22
|
+
back to the intent loop (it was not an engineer-only question).
|
|
23
|
+
|
|
24
|
+
## The three homes
|
|
25
|
+
|
|
26
|
+
The `[draft]` marker lives on three homes in 0.30.0. The agent writes
|
|
27
|
+
to all three; `shapes:draftSettled` reads back from all three.
|
|
28
|
+
|
|
29
|
+
- `TAD.dataArchitecture.coreEntities[].description` begins `[draft]`
|
|
30
|
+
for every entity minted from an `entity` statement. The marker
|
|
31
|
+
reports under id `TAD.entity:<name>`.
|
|
32
|
+
- `TAC.purpose` begins `[draft]` for every TAC stub minted from a
|
|
33
|
+
`surface` or `externalSystem` cluster. The marker reports under id
|
|
34
|
+
`<tacId>`.
|
|
35
|
+
- `TAC.interfaces[].description` begins `[draft]` for every interface
|
|
36
|
+
pre-populated inside a draft stub. The marker reports under id
|
|
37
|
+
`<tacId>:<name>`.
|
|
38
|
+
|
|
39
|
+
Each marker is `[draft]` followed by a space and the one-sentence
|
|
40
|
+
seed body. Leading whitespace is tolerated by the reader; keep the
|
|
41
|
+
marker at the start of the string regardless.
|
|
42
|
+
|
|
43
|
+
## The four writes
|
|
44
|
+
|
|
45
|
+
Walk the brief in this order; each step writes `[draft]` content only.
|
|
46
|
+
|
|
47
|
+
1. One `TAD.dataArchitecture.coreEntities[]` entry per `entity`
|
|
48
|
+
statement. `description` begins `[draft]` and quotes the
|
|
49
|
+
statement's source so the engineer can trace it. Use the statement
|
|
50
|
+
text to pick a name in UpperCamel; the engineer renames when the
|
|
51
|
+
entity is owned.
|
|
52
|
+
2. One TAC stub per `surface` or `externalSystem` cluster when no
|
|
53
|
+
TAC exists for it. `purpose` begins `[draft]`; `responsibilities`
|
|
54
|
+
lists the statements the surface or external system serves (one
|
|
55
|
+
bullet per statement, in the brief's words). Pick a `tacId` of the
|
|
56
|
+
next free number and a descriptive slug; the engineer renames when
|
|
57
|
+
the TAC is owned.
|
|
58
|
+
3. On each draft TAC, `[draft]` interfaces with real kinds from the
|
|
59
|
+
closed vocabulary (`recordShape`, `httpRoute`, `event`,
|
|
60
|
+
`cliCommand`, `uiRoute`, `port`, `fileFormat`, `fixture`,
|
|
61
|
+
`other`). Draft one of each kind the surface uses:
|
|
62
|
+
- a `recordShape` per entity the surface owns, with `fields:`
|
|
63
|
+
guessed from the brief;
|
|
64
|
+
- a `uiRoute` per surface;
|
|
65
|
+
- an `httpRoute` per exchange with an external system.
|
|
66
|
+
`description` begins `[draft]` with the one-line what-this-is.
|
|
67
|
+
4. `rcf discover req-classify` over every REQ created in the loop, so
|
|
68
|
+
`skeleton:reqShape` passes where the classifier is confident and
|
|
69
|
+
the engineer sees only the rest. The classifier is already
|
|
70
|
+
available under `src/review/` or `src/discover/`; this prompt only
|
|
71
|
+
invokes it.
|
|
72
|
+
|
|
73
|
+
## The read-back
|
|
74
|
+
|
|
75
|
+
After the pass, run `rcf define readiness --json` and read
|
|
76
|
+
`stages[].checks[]`. `shapes:draftSettled` is the engineer's entry
|
|
77
|
+
list: every id it names is a shape the agent pre-populated and the
|
|
78
|
+
engineer still has to settle. `shapes:tacHasInterface` and
|
|
79
|
+
`shapes:kindVocabulary` have already applied to drafts, so an empty
|
|
80
|
+
`shapes:tacHasInterface` finding means every stub carries at least
|
|
81
|
+
one interface and an empty `shapes:kindVocabulary` finding means
|
|
82
|
+
every interface's kind is in the closed vocabulary. The template
|
|
83
|
+
marker check and the entity join arrive in a later PR; the draft
|
|
84
|
+
pass does not need them to be honest about what is drafted.
|
|
85
|
+
|
|
86
|
+
Hand over by naming the three id forms the engineer will see
|
|
87
|
+
(`<tacId>:<name>`, `<tacId>`, `TAD.entity:<name>`) and the one verb
|
|
88
|
+
they will run to walk them (`rcf define readiness`). Nothing further
|
|
89
|
+
is said; the engineer owns the ladder from here.
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# Document intake into the brief ledger
|
|
2
|
+
|
|
3
|
+
This document is the content of the `rcf_define_intake` MCP prompt
|
|
4
|
+
served argument-free by the server. It walks the harness through
|
|
5
|
+
intake and lands every finding as an open-question statement the
|
|
6
|
+
intent loop then asks.
|
|
7
|
+
|
|
8
|
+
## What intake is
|
|
9
|
+
|
|
10
|
+
The owner hands over a folder. One file is the brief (short, prose,
|
|
11
|
+
the "what we are building" document); the rest are supporting
|
|
12
|
+
documents (ADRs, spec sketches, old READMEs, OpenAPI YAML, meeting
|
|
13
|
+
notes). The split that reaches the brief ledger is the harness's
|
|
14
|
+
work; the mechanical scans and the follow-up questions are
|
|
15
|
+
rcf-lite's.
|
|
16
|
+
|
|
17
|
+
Intake is harness-split and tool-scanned. The harness writes
|
|
18
|
+
`<source>.statements.md` beside each source; rcf-lite mints the
|
|
19
|
+
statements, runs the three mechanical scans against the existing
|
|
20
|
+
body, and appends one `openQuestion` statement per finding. The loop
|
|
21
|
+
then reads one check (`brief:openQuestions`) and the owner answers
|
|
22
|
+
in one place (ADR-4130).
|
|
23
|
+
|
|
24
|
+
## The walk
|
|
25
|
+
|
|
26
|
+
Walk the folder brief-first. For each source, in this order:
|
|
27
|
+
|
|
28
|
+
1. Open the source.
|
|
29
|
+
2. Split it into one statement per line. A statement is a sentence
|
|
30
|
+
that stands on its own: a capability (something the product must
|
|
31
|
+
do), a constraint (a rule it must obey), an actor (a person or
|
|
32
|
+
role), an entity (a thing it keeps track of), an externalSystem
|
|
33
|
+
(another system), a surface (a screen or channel), outOfScope
|
|
34
|
+
(something explicitly not in), an openQuestion (a question still
|
|
35
|
+
to answer), or an amendment (a correction to an earlier
|
|
36
|
+
statement).
|
|
37
|
+
3. Write `<source>.statements.md` next to the source. Each line is
|
|
38
|
+
one statement with a leading `[kind]` marker and a trailing
|
|
39
|
+
`(source: <path>:<line-span>)` marker.
|
|
40
|
+
4. Show the file to the owner in one message. Correct based on their
|
|
41
|
+
reply.
|
|
42
|
+
5. Run `rcf define ledger brief add --from <path>` (or the
|
|
43
|
+
`rcf_define_ledger` MCP tool with `verb: add`, `from: <path>`).
|
|
44
|
+
The mechanical scans run by default; findings are appended as
|
|
45
|
+
openQuestion statements. Report the scan findings as plain
|
|
46
|
+
questions.
|
|
47
|
+
6. Move to the next source.
|
|
48
|
+
|
|
49
|
+
Never add two sources through one `brief add --from`. Each `add`
|
|
50
|
+
scans the new ids against the existing body, and the scan source
|
|
51
|
+
marker `scan:<name>:<ids>` names the ids from both sides.
|
|
52
|
+
|
|
53
|
+
## The line grammar
|
|
54
|
+
|
|
55
|
+
Each line of a statement file is a statement. The grammar:
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
[<kind>] <text> (source: <path>:<line-span>)
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
- `[<kind>]` is one of the nine kinds above. When absent, the kind
|
|
62
|
+
defaults to the harness's `--kind` flag (default `capability`), or
|
|
63
|
+
to `openQuestion` when the line ends with `?` or begins with
|
|
64
|
+
`TBC`, `TBD`, `Open:` or `Question:`.
|
|
65
|
+
- `(source: ...)` names the file and the line range in the source.
|
|
66
|
+
When absent, the harness's `--source` flag or the file path itself
|
|
67
|
+
is used.
|
|
68
|
+
- Everything between the two markers is the statement text,
|
|
69
|
+
verbatim.
|
|
70
|
+
|
|
71
|
+
## What the owner sees
|
|
72
|
+
|
|
73
|
+
A statement file is operator prose. The owner reads it; the harness
|
|
74
|
+
corrects based on their reply. Example:
|
|
75
|
+
|
|
76
|
+
```
|
|
77
|
+
[capability] Officers can put a loan on hold for up to 30 days. (source: briefs/loans.md:12-14)
|
|
78
|
+
[constraint] A loan on hold must not accrue late fees. (source: briefs/loans.md:15)
|
|
79
|
+
[openQuestion] Who approves a hold longer than 30 days? (source: briefs/loans.md:16)
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
After `brief add --from` runs, the loop will ask about each of these
|
|
83
|
+
through `rcf define questions --persona productOwner`.
|
|
84
|
+
|
|
85
|
+
## After intake
|
|
86
|
+
|
|
87
|
+
Run `rcf define questions --persona productOwner`. The next set is
|
|
88
|
+
the `resolvedBy` questions for every capability, constraint, entity,
|
|
89
|
+
actor, externalSystem and surface statement, suggesting existing
|
|
90
|
+
REQ titles that share two or more words of 4+ characters. The owner
|
|
91
|
+
decides which become new REQs, which point at existing REQs, and
|
|
92
|
+
which are omitted.
|
|
93
|
+
|
|
94
|
+
At L1 (`levels.intentComplete.ok === true`) the agent pre-populates
|
|
95
|
+
`[draft]` entities, components and interfaces as engineer entry
|
|
96
|
+
material. These are drafts the engineer refines; they are never a
|
|
97
|
+
product-owner blocker.
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# The product-owner intent loop
|
|
2
|
+
|
|
3
|
+
This document is the operator-side reference for the DEFINE step 3
|
|
4
|
+
intent-complete loop. It is the content of the `rcf_define_intent` MCP
|
|
5
|
+
prompt and the `rcf://docs/define-intent` resource. The agent reads it
|
|
6
|
+
once per session and drives the loop; the product owner never sees any
|
|
7
|
+
of it.
|
|
8
|
+
|
|
9
|
+
## The shape of a turn
|
|
10
|
+
|
|
11
|
+
A turn is four steps and nothing else.
|
|
12
|
+
|
|
13
|
+
1. Run `rcf define questions --persona productOwner` (or
|
|
14
|
+
`rcf_define_questions` over MCP). The call returns the next question
|
|
15
|
+
set from the readiness object. Nothing is stored for the loop; the
|
|
16
|
+
tree, the four ledgers (`rcf/define/`) and the profile
|
|
17
|
+
(`rcf/.identity/profile.md`) are the state.
|
|
18
|
+
2. Ask the first one to three questions in one group, in plain words,
|
|
19
|
+
with the passage from the document quoted exactly. Never show more
|
|
20
|
+
than one group at a time; never show ids, verbs or stage names
|
|
21
|
+
unless the owner asks.
|
|
22
|
+
3. Run the write-back the question carries. Every question's
|
|
23
|
+
`writeBack[]` names one command per answer kind; pick the one that
|
|
24
|
+
matches the owner's reply and run it. The write-back is idempotent:
|
|
25
|
+
running it twice does not change the tree.
|
|
26
|
+
4. Re-run `rcf define readiness --level intent` (or
|
|
27
|
+
`rcf_define_readiness`). On exit 0 the loop is finished and you
|
|
28
|
+
print the verdict (section below). On exit 4 the loop continues:
|
|
29
|
+
go back to step 1.
|
|
30
|
+
|
|
31
|
+
The loop is monotone. Each answer removes its item or converts it into
|
|
32
|
+
at most two further product-owner items (an openQuestion promoted to a
|
|
33
|
+
decision asks `wellFormed` once if the harness under-fills it; a
|
|
34
|
+
statement resolved to a new REQ asks `reqHasUs` once). No engineer
|
|
35
|
+
edit can re-open the PO loop.
|
|
36
|
+
|
|
37
|
+
## The register
|
|
38
|
+
|
|
39
|
+
The first turn's first act is replacing the Register choice list in
|
|
40
|
+
`rcf/.identity/profile.md` with `productOwner` when the person
|
|
41
|
+
driving is the product owner. The profile is operator prose; you edit
|
|
42
|
+
it directly (no verb owns it). The same holds for the Surface choice
|
|
43
|
+
list.
|
|
44
|
+
|
|
45
|
+
The PO register has three wording rules.
|
|
46
|
+
|
|
47
|
+
- Plain sentences. No method terms. "What this is for" beats
|
|
48
|
+
"capability statement". "Who uses this" beats "AC-18602-4 user story
|
|
49
|
+
elicitation".
|
|
50
|
+
- Quote the passage. When the question is about a brief statement,
|
|
51
|
+
quote the statement text in double quotes. The owner recognises their
|
|
52
|
+
own words. "Your document says 'Officers can put a loan on hold.'"
|
|
53
|
+
beats "statement 7".
|
|
54
|
+
- One group at a time. The question object groups by source span so
|
|
55
|
+
the owner thinks about one passage before moving on. Never collapse
|
|
56
|
+
two groups into one prompt.
|
|
57
|
+
|
|
58
|
+
## Starting a session
|
|
59
|
+
|
|
60
|
+
A product-owner session starts with `rcf define questions --persona
|
|
61
|
+
productOwner`. If the brief is empty, the only question the loop
|
|
62
|
+
returns is `brief:sinceFreeze`: hand me your document, or tell me in a
|
|
63
|
+
few sentences what this is for. Walk the folder with the intake prompt
|
|
64
|
+
(`rcf_define_intake`) first when the owner has supplied one; otherwise
|
|
65
|
+
take their sentences and feed them in through `rcf define ledger brief
|
|
66
|
+
add --text "<text>"`.
|
|
67
|
+
|
|
68
|
+
## Ending a session
|
|
69
|
+
|
|
70
|
+
When `rcf define readiness --level intent` returns ok, print exactly
|
|
71
|
+
these lines:
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
Intent-complete: yes.
|
|
75
|
+
Your document has been turned into N requirements with M user stories.
|
|
76
|
+
The engineer blockers remaining are K.
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Then run `rcf define readiness --level intent --json` and save the
|
|
80
|
+
output beside the source folder as `<folder>.intent-complete.json`
|
|
81
|
+
(outside `rcf/`; readiness writes nothing itself). Commit the tree.
|
|
82
|
+
The Readiness tab URL is the artefact a delivery stream attaches.
|
|
83
|
+
|
|
84
|
+
## The engineer register
|
|
85
|
+
|
|
86
|
+
The same compute runs with `--persona engineer`: the question set is
|
|
87
|
+
the engineer blockers in failing stages, and its exit is
|
|
88
|
+
`levels.readyToBuild.ok`. Per-check question templates and per-check
|
|
89
|
+
write-backs for the engineer register are NOT part of DEFINE step 3
|
|
90
|
+
PR 2 (spec §1.1: "The engineer register is the same mechanism with
|
|
91
|
+
`--persona engineer`; it is not designed here beyond that flag and
|
|
92
|
+
is what step 4 inherits."). Until step 4 lands, the engineer-persona
|
|
93
|
+
questions return the shared compute shape with empty `writeBack` and
|
|
94
|
+
`answerKinds`; the harness reads the raw blocker and runs the
|
|
95
|
+
engineer verb that matches the check by hand.
|
|
96
|
+
|
|
97
|
+
## What the loop does NOT do
|
|
98
|
+
|
|
99
|
+
- No conversation state in rcf-lite. The tree, the ledgers and the
|
|
100
|
+
profile are the state (ADR-4129).
|
|
101
|
+
- No separate findings list. Intake scan findings become
|
|
102
|
+
`openQuestion` statements and the loop reads one check
|
|
103
|
+
(`brief:openQuestions`) rather than two surfaces (ADR-4130).
|
|
104
|
+
- No stale title-hit fallback. A statement whose `resolvedBy` is a
|
|
105
|
+
REQ id outside the closed grammar fails `skeleton:resolvedBy`; the
|
|
106
|
+
question returns the title hit as a suggestion rather than the
|
|
107
|
+
compute accepting it silently.
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# Recording a prototype in DISCOVERY
|
|
2
|
+
|
|
3
|
+
This document is the content of the `rcf_discover_prototype` MCP
|
|
4
|
+
prompt served argument-free by the server. It walks the agent
|
|
5
|
+
through the only path a prototype takes into the chain: as evidence,
|
|
6
|
+
with code burned, and with salvage by re-derivation.
|
|
7
|
+
|
|
8
|
+
The posture is ADR-4132. The code of a prototype is reference only;
|
|
9
|
+
no shape in the project tree is promoted from it. The whole worth of
|
|
10
|
+
the method is that every requirement, story, AC and shape has a
|
|
11
|
+
known origin, and a promotion path would smuggle unowned choices
|
|
12
|
+
past the chain.
|
|
13
|
+
|
|
14
|
+
## What a prototype is
|
|
15
|
+
|
|
16
|
+
An elicitation instrument built in DISCOVERY to learn what to ask.
|
|
17
|
+
It is recorded in the intake classification as an artefact of kind
|
|
18
|
+
`other` with the prototype's name.
|
|
19
|
+
|
|
20
|
+
## What is recorded
|
|
21
|
+
|
|
22
|
+
The prototype's outputs are brief statements with source spans
|
|
23
|
+
`prototype:<name>:<observation>`:
|
|
24
|
+
|
|
25
|
+
- Capabilities: what people did with it.
|
|
26
|
+
- Constraints: what they refused or asked for; what they would not
|
|
27
|
+
do without.
|
|
28
|
+
- Open questions: what the prototype raised that the brief had not.
|
|
29
|
+
- Out of scope: what the prototype was never allowed to do.
|
|
30
|
+
|
|
31
|
+
Reactions that need a ruling become decisions with options and a
|
|
32
|
+
default (the enumerated form D7 reads).
|
|
33
|
+
|
|
34
|
+
## What is burned
|
|
35
|
+
|
|
36
|
+
The code. The burn is one brief statement, kind `constraint`:
|
|
37
|
+
|
|
38
|
+
> Prototype <name> (commit <sha>, burned <date>) is reference only;
|
|
39
|
+
> no code from it is promoted.
|
|
40
|
+
|
|
41
|
+
The build that follows starts from the tree, never from the
|
|
42
|
+
prototype. The constraint sits beside the capabilities and open
|
|
43
|
+
questions the prototype produced; the chain reads them all through
|
|
44
|
+
the same `brief:openQuestions` / `skeleton:resolvedBy` loop as any
|
|
45
|
+
document.
|
|
46
|
+
|
|
47
|
+
## Salvage by re-derivation
|
|
48
|
+
|
|
49
|
+
The only middle path. Extract requirements from a promising
|
|
50
|
+
prototype as evidence (statements sourced to its files and lines),
|
|
51
|
+
run them through intake and the PO loop like any document, and
|
|
52
|
+
rebuild from the tree. The prototype is a quarry.
|
|
53
|
+
|
|
54
|
+
"Grow the prototype" is rejected. The provenance reason is the one
|
|
55
|
+
Dex's note gives: a shape reaching the project tree without the PO
|
|
56
|
+
loop that owns every settled shape is a shape without a known
|
|
57
|
+
origin, and no amount of auditing after the fact can restore the
|
|
58
|
+
owner.
|
|
59
|
+
|
|
60
|
+
## The managed-block rule
|
|
61
|
+
|
|
62
|
+
A statement sourced to `prototype:` is evidence. A document that
|
|
63
|
+
cites prototype code as its implementation is a D2 finding the
|
|
64
|
+
engineer resolves by re-deriving. That rule is prose; no check is
|
|
65
|
+
added in 0.30.0, and the engineer running D2 sees the finding
|
|
66
|
+
through the same `skeleton:resolvedBy` surface that reports every
|
|
67
|
+
other pointer.
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# DISCOVERY home for prototypes
|
|
2
|
+
|
|
3
|
+
This document is the doctrine and the ledger conventions for
|
|
4
|
+
prototypes. It is served under the slug `discovery-prototypes`,
|
|
5
|
+
through `rcf://docs/discovery-prototypes`, and through the
|
|
6
|
+
`rcf_discover_prototype` prompt that wraps it with the walk.
|
|
7
|
+
|
|
8
|
+
The posture is ADR-4132: prototypes live in DISCOVERY as evidence;
|
|
9
|
+
code is burned; salvage is re-derivation.
|
|
10
|
+
|
|
11
|
+
## What a prototype is
|
|
12
|
+
|
|
13
|
+
An elicitation instrument built in DISCOVERY to learn what to ask.
|
|
14
|
+
It is recorded in the intake classification as an artefact of kind
|
|
15
|
+
`other` with the prototype's name. The prototype belongs to
|
|
16
|
+
DISCOVERY, not DEFINE: it is a tool for learning, not a draft of
|
|
17
|
+
what gets built.
|
|
18
|
+
|
|
19
|
+
## What is recorded
|
|
20
|
+
|
|
21
|
+
Its outputs are brief statements with source spans
|
|
22
|
+
`prototype:<name>:<observation>`:
|
|
23
|
+
|
|
24
|
+
- Capabilities: what people did with it.
|
|
25
|
+
- Constraints: what they refused or asked for.
|
|
26
|
+
- Open questions: what it raised that the brief had not.
|
|
27
|
+
- Out of scope: what it was never allowed to do.
|
|
28
|
+
|
|
29
|
+
Reactions that need a ruling become decisions with options and a
|
|
30
|
+
default. The intent-complete loop then reads one check
|
|
31
|
+
(`brief:openQuestions`) and the owner answers in one place; the
|
|
32
|
+
prototype's observations ride the same ladder as every other brief
|
|
33
|
+
statement.
|
|
34
|
+
|
|
35
|
+
## What is burned
|
|
36
|
+
|
|
37
|
+
The code. The burn is one brief statement, kind `constraint`:
|
|
38
|
+
|
|
39
|
+
> Prototype <name> (commit <sha>, burned <date>) is reference only;
|
|
40
|
+
> no code from it is promoted.
|
|
41
|
+
|
|
42
|
+
The build that follows starts from the tree, never from the
|
|
43
|
+
prototype. The brief ledger holds the burn statement alongside the
|
|
44
|
+
other statements the prototype produced; nothing further is said in
|
|
45
|
+
code or in configuration.
|
|
46
|
+
|
|
47
|
+
## Salvage by re-derivation
|
|
48
|
+
|
|
49
|
+
The only middle path. Extract requirements from a promising
|
|
50
|
+
prototype as evidence (statements sourced to its files and lines),
|
|
51
|
+
run them through intake and the PO loop like any document, and
|
|
52
|
+
rebuild from the tree. The prototype is a quarry.
|
|
53
|
+
|
|
54
|
+
"Grow the prototype" is named here as rejected, with the provenance
|
|
55
|
+
reason from Dex's note: a shape reaching the project tree without
|
|
56
|
+
the PO loop that owns every settled shape is a shape without a known
|
|
57
|
+
origin, and no amount of auditing after the fact can restore the
|
|
58
|
+
owner.
|
|
59
|
+
|
|
60
|
+
## The managed-block rule
|
|
61
|
+
|
|
62
|
+
The managed block gains one rule the harness picks up through
|
|
63
|
+
`rcf doctor`:
|
|
64
|
+
|
|
65
|
+
> A statement sourced to `prototype:` is evidence. A document that
|
|
66
|
+
> cites prototype code as its implementation is a D2 finding the
|
|
67
|
+
> engineer resolves by re-deriving.
|
|
68
|
+
|
|
69
|
+
That rule is prose; no check is added in 0.30.0.
|