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.
Files changed (168) hide show
  1. package/CHANGELOG.md +107 -1
  2. package/bin/rcf.js +4 -0
  3. package/fixtures/canary-manifest.json +9 -9
  4. package/guidance/define-draft-shapes.md +89 -0
  5. package/guidance/define-intake.md +97 -0
  6. package/guidance/define-intent.md +107 -0
  7. package/guidance/discover-prototype.md +67 -0
  8. package/guidance/discovery-prototypes.md +69 -0
  9. package/guidance/harness-template.md +34 -0
  10. package/guidance/managed/agent-instructions-block.hash +1 -1
  11. package/guidance/managed/agent-instructions-block.md +34 -0
  12. package/guidance/manifest.json +9 -2
  13. package/package.json +1 -1
  14. package/rcf/adrs/adr-4124-define-freeze-verb.json +30 -0
  15. package/rcf/adrs/adr-4126-persona-tagged-blockers-two-levels.json +40 -0
  16. package/rcf/adrs/adr-4127-readiness-tab-order-and-register.json +40 -0
  17. package/rcf/adrs/adr-4129-questions-harness-driven-loop.json +25 -0
  18. package/rcf/adrs/adr-4130-intake-harness-split-tool-scanned.json +20 -0
  19. package/rcf/adrs/adr-4132-prototypes-in-discovery-as-evidence.json +20 -0
  20. package/rcf/adrs/adr-4133-dag-dependency-depth-layout.json +40 -0
  21. package/rcf/adrs/adr-4134-index-json-route.json +35 -0
  22. package/rcf/adrs/adr-4135-readiness-po-register-and-adapter.json +35 -0
  23. package/rcf/adrs/adr-4136-embedding-host-fixture.json +35 -0
  24. package/rcf/code-nodes/cn-725.json +18 -2
  25. package/rcf/code-nodes/cn-726.json +10 -2
  26. package/rcf/code-nodes/cn-727.json +13 -4
  27. package/rcf/code-nodes/cn-728.json +18 -2
  28. package/rcf/code-nodes/cn-729.json +10 -2
  29. package/rcf/code-nodes/cn-730.json +13 -3
  30. package/rcf/code-nodes/cn-731.json +20 -0
  31. package/rcf/code-nodes/cn-732.json +14 -0
  32. package/rcf/code-nodes/cn-733.json +14 -0
  33. package/rcf/code-nodes/cn-734.json +14 -0
  34. package/rcf/code-nodes/cn-735.json +20 -0
  35. package/rcf/code-nodes/cn-736.json +14 -0
  36. package/rcf/code-nodes/cn-737.json +14 -0
  37. package/rcf/code-nodes/cn-738.json +14 -0
  38. package/rcf/code-nodes/cn-739.json +18 -0
  39. package/rcf/code-nodes/cn-740.json +19 -0
  40. package/rcf/code-nodes/cn-741.json +16 -0
  41. package/rcf/code-nodes/cn-742.json +16 -0
  42. package/rcf/code-nodes/cn-743.json +15 -0
  43. package/rcf/code-nodes/cn-744.json +22 -0
  44. package/rcf/code-nodes/cn-745.json +16 -0
  45. package/rcf/code-nodes/cn-746.json +14 -0
  46. package/rcf/code-nodes/cn-747.json +18 -0
  47. package/rcf/code-nodes/cn-748.json +16 -0
  48. package/rcf/code-nodes/cn-749.json +16 -0
  49. package/rcf/code-nodes/cn-750.json +15 -0
  50. package/rcf/code-nodes/cn-751.json +18 -0
  51. package/rcf/code-nodes/cn-752.json +14 -0
  52. package/rcf/fbs/fbs-196.json +13 -5
  53. package/rcf/fbs/fbs-198.json +42 -0
  54. package/rcf/fbs/fbs-199.json +59 -0
  55. package/rcf/fbs/fbs-200.json +46 -0
  56. package/rcf/fbs/fbs-201.json +49 -0
  57. package/rcf/fbs/fbs-202.json +110 -0
  58. package/rcf/fbs/fbs-203.json +100 -0
  59. package/rcf/requirements/req-002.json +2 -2
  60. package/rcf/requirements/req-173.json +2 -2
  61. package/rcf/requirements/req-174.json +10 -4
  62. package/rcf/requirements/req-175.json +10 -4
  63. package/rcf/requirements/req-176.json +25 -0
  64. package/rcf/requirements/req-180.json +31 -0
  65. package/rcf/requirements/req-181.json +31 -0
  66. package/rcf/requirements/req-182.json +25 -0
  67. package/rcf/requirements/req-186.json +25 -0
  68. package/rcf/requirements/req-187.json +31 -0
  69. package/rcf/requirements/req-188.json +25 -0
  70. package/rcf/tacs/tac-4121-define-ledgers.json +15 -3
  71. package/rcf/tacs/tac-4122-define-gates.json +40 -4
  72. package/rcf/tacs/tac-4123-define-readiness.json +39 -3
  73. package/rcf/tacs/tac-4124-define-freeze.json +28 -0
  74. package/rcf/tacs/tac-4127-readiness-view.json +49 -0
  75. package/rcf/tacs/tac-4128-define-guidance.json +53 -0
  76. package/rcf/tacs/tac-4129-define-questions.json +45 -0
  77. package/rcf/tacs/tac-4130-define-intake-brief.json +35 -0
  78. package/rcf/tacs/tac-4131-build-dag-view.json +39 -0
  79. package/rcf/tacs/tac-4132-id-lookup.json +42 -0
  80. package/rcf/tacs/tac-4133-readiness-po-layer.json +37 -0
  81. package/rcf/tacs/tac-4134-wespa-host-fixture.json +54 -0
  82. package/rcf/test-suites/ts-016.json +3 -3
  83. package/rcf/test-suites/ts-215.json +148 -4
  84. package/rcf/test-suites/ts-216.json +19 -3
  85. package/rcf/test-suites/ts-218.json +78 -0
  86. package/rcf/test-suites/ts-219.json +70 -0
  87. package/rcf/test-suites/ts-220.json +78 -0
  88. package/rcf/test-suites/ts-221.json +78 -0
  89. package/rcf/test-suites/ts-222.json +100 -0
  90. package/rcf/test-suites/ts-223.json +94 -0
  91. package/rcf/test-suites/ts-224.json +70 -0
  92. package/rcf/test-suites/ts-225.json +78 -0
  93. package/rcf/test-suites/ts-226.json +158 -0
  94. package/rcf/test-suites/ts-227.json +38 -0
  95. package/rcf/test-suites/ts-228.json +86 -0
  96. package/rcf/test-suites/ts-229.json +83 -0
  97. package/rcf/user-stories/us-17302.json +50 -0
  98. package/rcf/user-stories/us-17401.json +14 -2
  99. package/rcf/user-stories/us-17402.json +55 -0
  100. package/rcf/user-stories/us-17403.json +60 -0
  101. package/rcf/user-stories/us-17502.json +60 -0
  102. package/rcf/user-stories/us-17503.json +65 -0
  103. package/rcf/user-stories/us-17601.json +58 -0
  104. package/rcf/user-stories/us-18001.json +55 -0
  105. package/rcf/user-stories/us-18002.json +35 -0
  106. package/rcf/user-stories/us-18101.json +35 -0
  107. package/rcf/user-stories/us-18202.json +40 -0
  108. package/rcf/user-stories/us-18601.json +55 -0
  109. package/rcf/user-stories/us-18602.json +50 -0
  110. package/rcf/user-stories/us-18603.json +45 -0
  111. package/rcf/user-stories/us-18701.json +50 -0
  112. package/rcf/user-stories/us-18702.json +50 -0
  113. package/rcf/user-stories/us-18801.json +45 -0
  114. package/rcf/user-stories/us-204.json +59 -0
  115. package/rcf/user-stories/us-205.json +64 -0
  116. package/rcf/user-stories/us-206.json +54 -0
  117. package/releases/releases.yaml +11 -1
  118. package/src/cli/freeze.js +730 -0
  119. package/src/cli/help.js +12 -0
  120. package/src/cli/ledger.js +228 -12
  121. package/src/cli/questions.js +288 -0
  122. package/src/cli/readiness.js +267 -49
  123. package/src/cli/view.js +29 -0
  124. package/src/define/freeze-record.js +30 -15
  125. package/src/define/ledgers.js +210 -11
  126. package/src/intake/index.js +1 -1
  127. package/src/intake/orchestrator.js +117 -0
  128. package/src/mcp/tools.js +354 -0
  129. package/src/query/delta.js +6 -0
  130. package/src/query/gates.js +314 -39
  131. package/src/query/index.js +16 -2
  132. package/src/query/questions.js +438 -0
  133. package/src/query/readiness.js +248 -7
  134. package/src/server/index.js +24 -2
  135. package/src/server/routes.js +68 -1
  136. package/src/setup/identity-seed.js +17 -0
  137. package/src/view/build-dag.js +563 -0
  138. package/src/view/components/badge.js +41 -0
  139. package/src/view/components/diff.js +72 -0
  140. package/src/view/components/doc-row.js +62 -0
  141. package/src/view/components/empty-state.js +35 -0
  142. package/src/view/components/entity-selector.js +137 -0
  143. package/src/view/components/filter-bar.js +97 -0
  144. package/src/view/components/findings-list.js +49 -0
  145. package/src/view/components/index.js +12 -0
  146. package/src/view/components/pill.js +46 -0
  147. package/src/view/components/sub-tab-strip.js +43 -0
  148. package/src/view/components/toast.js +25 -0
  149. package/src/view/components-fixture.js +265 -0
  150. package/src/view/doc-renderers/architecture.js +304 -0
  151. package/src/view/doc-renderers/build.js +160 -0
  152. package/src/view/doc-renderers/index.js +2 -0
  153. package/src/view/doc-renderers/prd.js +35 -6
  154. package/src/view/html-page.js +700 -602
  155. package/src/view/index.js +96 -3
  156. package/src/view/live-client.js +39 -6
  157. package/src/view/needs-work.js +79 -0
  158. package/src/view/page-init.js +2193 -0
  159. package/src/view/readiness/phrasebook.js +115 -0
  160. package/src/view/readiness/po-layer.js +288 -0
  161. package/src/view/readiness/question-adapter.js +329 -0
  162. package/src/view/readiness/stage-legend.js +71 -0
  163. package/src/view/readiness.js +505 -0
  164. package/src/view/style.css +2017 -382
  165. package/src/view/test-host/embed-client.js +121 -0
  166. package/src/view/test-host/fixture.js +183 -0
  167. package/src/view/test-host/lints.js +220 -0
  168. 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:/` -- case-sensitive uppercase `TODO`
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-09-30-001",
5
- "createdAt": "2026-09-30T15:30:02.583Z",
6
- "buildVersion": "0.28.4-mockdriver",
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-09-30-002",
38
- "createdAt": "2026-09-30T15:30:02.584Z",
39
- "buildVersion": "0.28.4-mockdriver",
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-09-30-003",
71
- "createdAt": "2026-09-30T15:30:02.584Z",
72
- "buildVersion": "0.28.4-mockdriver",
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.