rcf-lite 0.28.2 → 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 (327) hide show
  1. package/CHANGELOG.md +317 -0
  2. package/bin/rcf.js +8 -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-4120-canonical-json-hashing.json +30 -0
  15. package/rcf/adrs/adr-4121-define-sidecars.json +30 -0
  16. package/rcf/adrs/adr-4122-define-gates-blocking-and-optout.json +30 -0
  17. package/rcf/adrs/adr-4123-readiness-single-object.json +30 -0
  18. package/rcf/adrs/adr-4124-define-freeze-verb.json +30 -0
  19. package/rcf/adrs/adr-4126-persona-tagged-blockers-two-levels.json +40 -0
  20. package/rcf/adrs/adr-4127-readiness-tab-order-and-register.json +40 -0
  21. package/rcf/adrs/adr-4129-questions-harness-driven-loop.json +25 -0
  22. package/rcf/adrs/adr-4130-intake-harness-split-tool-scanned.json +20 -0
  23. package/rcf/adrs/adr-4132-prototypes-in-discovery-as-evidence.json +20 -0
  24. package/rcf/adrs/adr-4133-dag-dependency-depth-layout.json +40 -0
  25. package/rcf/adrs/adr-4134-index-json-route.json +35 -0
  26. package/rcf/adrs/adr-4135-readiness-po-register-and-adapter.json +35 -0
  27. package/rcf/adrs/adr-4136-embedding-host-fixture.json +35 -0
  28. package/rcf/code-nodes/cn-700.json +23 -0
  29. package/rcf/code-nodes/cn-701.json +14 -0
  30. package/rcf/code-nodes/cn-702.json +14 -0
  31. package/rcf/code-nodes/cn-703.json +16 -0
  32. package/rcf/code-nodes/cn-720.json +15 -0
  33. package/rcf/code-nodes/cn-721.json +15 -0
  34. package/rcf/code-nodes/cn-722.json +15 -0
  35. package/rcf/code-nodes/cn-723.json +18 -0
  36. package/rcf/code-nodes/cn-724.json +14 -0
  37. package/rcf/code-nodes/cn-725.json +37 -0
  38. package/rcf/code-nodes/cn-726.json +25 -0
  39. package/rcf/code-nodes/cn-727.json +23 -0
  40. package/rcf/code-nodes/cn-728.json +37 -0
  41. package/rcf/code-nodes/cn-729.json +26 -0
  42. package/rcf/code-nodes/cn-730.json +24 -0
  43. package/rcf/code-nodes/cn-731.json +20 -0
  44. package/rcf/code-nodes/cn-732.json +14 -0
  45. package/rcf/code-nodes/cn-733.json +14 -0
  46. package/rcf/code-nodes/cn-734.json +14 -0
  47. package/rcf/code-nodes/cn-735.json +20 -0
  48. package/rcf/code-nodes/cn-736.json +14 -0
  49. package/rcf/code-nodes/cn-737.json +14 -0
  50. package/rcf/code-nodes/cn-738.json +14 -0
  51. package/rcf/code-nodes/cn-739.json +18 -0
  52. package/rcf/code-nodes/cn-740.json +19 -0
  53. package/rcf/code-nodes/cn-741.json +16 -0
  54. package/rcf/code-nodes/cn-742.json +16 -0
  55. package/rcf/code-nodes/cn-743.json +15 -0
  56. package/rcf/code-nodes/cn-744.json +22 -0
  57. package/rcf/code-nodes/cn-745.json +16 -0
  58. package/rcf/code-nodes/cn-746.json +14 -0
  59. package/rcf/code-nodes/cn-747.json +18 -0
  60. package/rcf/code-nodes/cn-748.json +16 -0
  61. package/rcf/code-nodes/cn-749.json +16 -0
  62. package/rcf/code-nodes/cn-750.json +15 -0
  63. package/rcf/code-nodes/cn-751.json +18 -0
  64. package/rcf/code-nodes/cn-752.json +14 -0
  65. package/rcf/fbs/fbs-190.json +37 -0
  66. package/rcf/fbs/fbs-191.json +34 -0
  67. package/rcf/fbs/fbs-192.json +17 -0
  68. package/rcf/fbs/fbs-193.json +37 -0
  69. package/rcf/fbs/fbs-194.json +35 -0
  70. package/rcf/fbs/fbs-195.json +37 -0
  71. package/rcf/fbs/fbs-196.json +45 -0
  72. package/rcf/fbs/fbs-197.json +41 -0
  73. package/rcf/fbs/fbs-198.json +42 -0
  74. package/rcf/fbs/fbs-199.json +59 -0
  75. package/rcf/fbs/fbs-200.json +46 -0
  76. package/rcf/fbs/fbs-201.json +49 -0
  77. package/rcf/fbs/fbs-202.json +110 -0
  78. package/rcf/fbs/fbs-203.json +100 -0
  79. package/rcf/requirements/req-001.json +2 -1
  80. package/rcf/requirements/req-002.json +3 -2
  81. package/rcf/requirements/req-003.json +2 -1
  82. package/rcf/requirements/req-004.json +2 -1
  83. package/rcf/requirements/req-005.json +2 -1
  84. package/rcf/requirements/req-006.json +2 -1
  85. package/rcf/requirements/req-007.json +2 -1
  86. package/rcf/requirements/req-008.json +2 -1
  87. package/rcf/requirements/req-009.json +2 -1
  88. package/rcf/requirements/req-010.json +5 -2
  89. package/rcf/requirements/req-011.json +2 -1
  90. package/rcf/requirements/req-012.json +2 -1
  91. package/rcf/requirements/req-013.json +2 -1
  92. package/rcf/requirements/req-014.json +2 -1
  93. package/rcf/requirements/req-015.json +2 -1
  94. package/rcf/requirements/req-016.json +5 -2
  95. package/rcf/requirements/req-017.json +6 -2
  96. package/rcf/requirements/req-018.json +5 -2
  97. package/rcf/requirements/req-019.json +5 -2
  98. package/rcf/requirements/req-020.json +5 -2
  99. package/rcf/requirements/req-021.json +5 -2
  100. package/rcf/requirements/req-022.json +5 -2
  101. package/rcf/requirements/req-023.json +6 -4
  102. package/rcf/requirements/req-024.json +5 -2
  103. package/rcf/requirements/req-025.json +5 -2
  104. package/rcf/requirements/req-026.json +5 -2
  105. package/rcf/requirements/req-027.json +5 -2
  106. package/rcf/requirements/req-028.json +5 -2
  107. package/rcf/requirements/req-029.json +5 -2
  108. package/rcf/requirements/req-030.json +5 -2
  109. package/rcf/requirements/req-040.json +5 -2
  110. package/rcf/requirements/req-041.json +5 -2
  111. package/rcf/requirements/req-042.json +5 -2
  112. package/rcf/requirements/req-043.json +5 -2
  113. package/rcf/requirements/req-050.json +5 -2
  114. package/rcf/requirements/req-051.json +5 -2
  115. package/rcf/requirements/req-052.json +5 -2
  116. package/rcf/requirements/req-053.json +5 -2
  117. package/rcf/requirements/req-054.json +5 -2
  118. package/rcf/requirements/req-060.json +5 -2
  119. package/rcf/requirements/req-061.json +5 -2
  120. package/rcf/requirements/req-062.json +5 -2
  121. package/rcf/requirements/req-063.json +5 -2
  122. package/rcf/requirements/req-070.json +5 -2
  123. package/rcf/requirements/req-071.json +5 -2
  124. package/rcf/requirements/req-072.json +5 -2
  125. package/rcf/requirements/req-073.json +5 -2
  126. package/rcf/requirements/req-074.json +5 -2
  127. package/rcf/requirements/req-075.json +5 -2
  128. package/rcf/requirements/req-076.json +5 -2
  129. package/rcf/requirements/req-077.json +5 -2
  130. package/rcf/requirements/req-080.json +5 -2
  131. package/rcf/requirements/req-081.json +5 -2
  132. package/rcf/requirements/req-082.json +5 -2
  133. package/rcf/requirements/req-083.json +5 -2
  134. package/rcf/requirements/req-084.json +5 -2
  135. package/rcf/requirements/req-085.json +5 -2
  136. package/rcf/requirements/req-086.json +5 -2
  137. package/rcf/requirements/req-090.json +5 -2
  138. package/rcf/requirements/req-091.json +5 -2
  139. package/rcf/requirements/req-092.json +5 -2
  140. package/rcf/requirements/req-093.json +5 -2
  141. package/rcf/requirements/req-094.json +5 -2
  142. package/rcf/requirements/req-100.json +5 -2
  143. package/rcf/requirements/req-101.json +5 -2
  144. package/rcf/requirements/req-102.json +5 -2
  145. package/rcf/requirements/req-103.json +5 -2
  146. package/rcf/requirements/req-104.json +5 -2
  147. package/rcf/requirements/req-110.json +5 -2
  148. package/rcf/requirements/req-111.json +5 -2
  149. package/rcf/requirements/req-112.json +5 -2
  150. package/rcf/requirements/req-113.json +5 -2
  151. package/rcf/requirements/req-114.json +5 -2
  152. package/rcf/requirements/req-115.json +5 -2
  153. package/rcf/requirements/req-120.json +5 -2
  154. package/rcf/requirements/req-121.json +5 -2
  155. package/rcf/requirements/req-122.json +5 -2
  156. package/rcf/requirements/req-123.json +5 -2
  157. package/rcf/requirements/req-124.json +5 -2
  158. package/rcf/requirements/req-125.json +5 -2
  159. package/rcf/requirements/req-130.json +6 -2
  160. package/rcf/requirements/req-131.json +6 -2
  161. package/rcf/requirements/req-132.json +6 -2
  162. package/rcf/requirements/req-133.json +6 -2
  163. package/rcf/requirements/req-134.json +6 -2
  164. package/rcf/requirements/req-140.json +5 -2
  165. package/rcf/requirements/req-145.json +5 -2
  166. package/rcf/requirements/req-150.json +6 -2
  167. package/rcf/requirements/req-151.json +6 -2
  168. package/rcf/requirements/req-152.json +6 -2
  169. package/rcf/requirements/req-153.json +6 -2
  170. package/rcf/requirements/req-154.json +5 -2
  171. package/rcf/requirements/req-155.json +4 -1
  172. package/rcf/requirements/req-156.json +4 -1
  173. package/rcf/requirements/req-157.json +4 -1
  174. package/rcf/requirements/req-158.json +4 -1
  175. package/rcf/requirements/req-159.json +4 -1
  176. package/rcf/requirements/req-160.json +4 -1
  177. package/rcf/requirements/req-161.json +4 -1
  178. package/rcf/requirements/req-162.json +4 -1
  179. package/rcf/requirements/req-163.json +5 -2
  180. package/rcf/requirements/req-164.json +5 -2
  181. package/rcf/requirements/req-165.json +5 -2
  182. package/rcf/requirements/req-170.json +33 -0
  183. package/rcf/requirements/req-171.json +44 -0
  184. package/rcf/requirements/req-172.json +25 -0
  185. package/rcf/requirements/req-173.json +25 -0
  186. package/rcf/requirements/req-174.json +31 -0
  187. package/rcf/requirements/req-175.json +31 -0
  188. package/rcf/requirements/req-176.json +25 -0
  189. package/rcf/requirements/req-180.json +31 -0
  190. package/rcf/requirements/req-181.json +31 -0
  191. package/rcf/requirements/req-182.json +25 -0
  192. package/rcf/requirements/req-186.json +25 -0
  193. package/rcf/requirements/req-187.json +31 -0
  194. package/rcf/requirements/req-188.json +25 -0
  195. package/rcf/tacs/tac-4120-define-delta-and-freeze.json +21 -0
  196. package/rcf/tacs/tac-4121-define-ledgers.json +35 -0
  197. package/rcf/tacs/tac-4122-define-gates.json +61 -0
  198. package/rcf/tacs/tac-4123-define-readiness.json +61 -0
  199. package/rcf/tacs/tac-4124-define-freeze.json +28 -0
  200. package/rcf/tacs/tac-4127-readiness-view.json +49 -0
  201. package/rcf/tacs/tac-4128-define-guidance.json +53 -0
  202. package/rcf/tacs/tac-4129-define-questions.json +45 -0
  203. package/rcf/tacs/tac-4130-define-intake-brief.json +35 -0
  204. package/rcf/tacs/tac-4131-build-dag-view.json +39 -0
  205. package/rcf/tacs/tac-4132-id-lookup.json +42 -0
  206. package/rcf/tacs/tac-4133-readiness-po-layer.json +37 -0
  207. package/rcf/tacs/tac-4134-wespa-host-fixture.json +54 -0
  208. package/rcf/test-suites/ts-016.json +3 -3
  209. package/rcf/test-suites/ts-204.json +30 -0
  210. package/rcf/test-suites/ts-205.json +22 -0
  211. package/rcf/test-suites/ts-206.json +22 -0
  212. package/rcf/test-suites/ts-207.json +22 -0
  213. package/rcf/test-suites/ts-208.json +22 -0
  214. package/rcf/test-suites/ts-209.json +22 -0
  215. package/rcf/test-suites/ts-210.json +22 -0
  216. package/rcf/test-suites/ts-211.json +22 -0
  217. package/rcf/test-suites/ts-212.json +22 -0
  218. package/rcf/test-suites/ts-213.json +50 -0
  219. package/rcf/test-suites/ts-214.json +74 -0
  220. package/rcf/test-suites/ts-215.json +211 -0
  221. package/rcf/test-suites/ts-216.json +94 -0
  222. package/rcf/test-suites/ts-217.json +62 -0
  223. package/rcf/test-suites/ts-218.json +78 -0
  224. package/rcf/test-suites/ts-219.json +70 -0
  225. package/rcf/test-suites/ts-220.json +78 -0
  226. package/rcf/test-suites/ts-221.json +78 -0
  227. package/rcf/test-suites/ts-222.json +100 -0
  228. package/rcf/test-suites/ts-223.json +94 -0
  229. package/rcf/test-suites/ts-224.json +70 -0
  230. package/rcf/test-suites/ts-225.json +78 -0
  231. package/rcf/test-suites/ts-226.json +158 -0
  232. package/rcf/test-suites/ts-227.json +38 -0
  233. package/rcf/test-suites/ts-228.json +86 -0
  234. package/rcf/test-suites/ts-229.json +83 -0
  235. package/rcf/user-stories/us-15601.json +4 -4
  236. package/rcf/user-stories/us-17001.json +27 -0
  237. package/rcf/user-stories/us-17002.json +22 -0
  238. package/rcf/user-stories/us-17003.json +22 -0
  239. package/rcf/user-stories/us-17004.json +22 -0
  240. package/rcf/user-stories/us-17005.json +22 -0
  241. package/rcf/user-stories/us-17006.json +21 -0
  242. package/rcf/user-stories/us-17007.json +21 -0
  243. package/rcf/user-stories/us-17008.json +22 -0
  244. package/rcf/user-stories/us-17101.json +22 -0
  245. package/rcf/user-stories/us-17102.json +22 -0
  246. package/rcf/user-stories/us-17201.json +38 -0
  247. package/rcf/user-stories/us-17301.json +38 -0
  248. package/rcf/user-stories/us-17302.json +50 -0
  249. package/rcf/user-stories/us-17401.json +70 -0
  250. package/rcf/user-stories/us-17402.json +55 -0
  251. package/rcf/user-stories/us-17403.json +60 -0
  252. package/rcf/user-stories/us-17501.json +48 -0
  253. package/rcf/user-stories/us-17502.json +60 -0
  254. package/rcf/user-stories/us-17503.json +65 -0
  255. package/rcf/user-stories/us-17601.json +58 -0
  256. package/rcf/user-stories/us-18001.json +55 -0
  257. package/rcf/user-stories/us-18002.json +35 -0
  258. package/rcf/user-stories/us-18101.json +35 -0
  259. package/rcf/user-stories/us-18202.json +40 -0
  260. package/rcf/user-stories/us-18601.json +55 -0
  261. package/rcf/user-stories/us-18602.json +50 -0
  262. package/rcf/user-stories/us-18603.json +45 -0
  263. package/rcf/user-stories/us-18701.json +50 -0
  264. package/rcf/user-stories/us-18702.json +50 -0
  265. package/rcf/user-stories/us-18801.json +45 -0
  266. package/rcf/user-stories/us-204.json +59 -0
  267. package/rcf/user-stories/us-205.json +64 -0
  268. package/rcf/user-stories/us-206.json +54 -0
  269. package/releases/releases.yaml +31 -1
  270. package/src/cli/feedback.js +126 -10
  271. package/src/cli/freeze.js +730 -0
  272. package/src/cli/help.js +23 -0
  273. package/src/cli/ledger.js +615 -0
  274. package/src/cli/questions.js +288 -0
  275. package/src/cli/readiness.js +498 -0
  276. package/src/cli/view.js +29 -0
  277. package/src/core/store/writer.js +86 -6
  278. package/src/define/freeze-record.js +247 -0
  279. package/src/define/ledgers.js +712 -0
  280. package/src/feedback/redact.js +105 -19
  281. package/src/intake/index.js +1 -1
  282. package/src/intake/orchestrator.js +117 -0
  283. package/src/mcp/tools.js +354 -0
  284. package/src/query/delta.js +282 -0
  285. package/src/query/gates.js +1107 -0
  286. package/src/query/index.js +50 -0
  287. package/src/query/questions.js +438 -0
  288. package/src/query/readiness.js +574 -0
  289. package/src/server/index.js +60 -1
  290. package/src/server/routes.js +133 -4
  291. package/src/setup/identity-seed.js +17 -0
  292. package/src/view/build-dag.js +563 -0
  293. package/src/view/components/badge.js +41 -0
  294. package/src/view/components/diff.js +72 -0
  295. package/src/view/components/doc-row.js +62 -0
  296. package/src/view/components/empty-state.js +35 -0
  297. package/src/view/components/entity-selector.js +137 -0
  298. package/src/view/components/filter-bar.js +97 -0
  299. package/src/view/components/findings-list.js +49 -0
  300. package/src/view/components/index.js +12 -0
  301. package/src/view/components/pill.js +46 -0
  302. package/src/view/components/sub-tab-strip.js +43 -0
  303. package/src/view/components/toast.js +25 -0
  304. package/src/view/components-fixture.js +265 -0
  305. package/src/view/doc-renderers/architecture.js +304 -0
  306. package/src/view/doc-renderers/build.js +160 -0
  307. package/src/view/doc-renderers/helpers.js +2 -2
  308. package/src/view/doc-renderers/index.js +2 -0
  309. package/src/view/doc-renderers/prd.js +35 -6
  310. package/src/view/doc-renderers/req.js +10 -2
  311. package/src/view/doc-renderers/user-story.js +10 -5
  312. package/src/view/html-page.js +717 -300
  313. package/src/view/index.js +109 -3
  314. package/src/view/live-client.js +61 -8
  315. package/src/view/needs-work.js +79 -0
  316. package/src/view/page-init.js +2193 -0
  317. package/src/view/product-map.js +751 -0
  318. package/src/view/readiness/phrasebook.js +115 -0
  319. package/src/view/readiness/po-layer.js +288 -0
  320. package/src/view/readiness/question-adapter.js +329 -0
  321. package/src/view/readiness/stage-legend.js +71 -0
  322. package/src/view/readiness.js +505 -0
  323. package/src/view/style.css +2279 -266
  324. package/src/view/test-host/embed-client.js +121 -0
  325. package/src/view/test-host/fixture.js +183 -0
  326. package/src/view/test-host/lints.js +220 -0
  327. package/src/view/view-index.js +323 -0
package/CHANGELOG.md CHANGED
@@ -6,6 +6,323 @@ 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
+
59
+ ## [0.28.4] - 2026-09-30
60
+
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.
62
+ ### Added
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
+
120
+ - **Product Map tab on the review surface (#238).** Merged on `main` at
121
+ `ab35dd7d`; grouped by shape, component, trace coverage, capability,
122
+ blueprint. This entry backfills the changelog now that the following
123
+ DEFINE-train slice rides on top of it.
124
+ - **DEFINE workflow: delta detection foundation (REQ-172, slice 1 of
125
+ the 0.29.0 train).** New pure module `src/query/delta.js` exports
126
+ `hashDocument`, `computeTreeHash` and `computeDelta`. `hashDocument`
127
+ is SHA-256 over the canonical JSON of the parsed document (keys
128
+ sorted recursively, no whitespace), so a hand reformat is not a
129
+ change; the tree hash is over the sorted `(id, docHash)` pairs.
130
+ `computeDelta(tree, freeze, ledgers)` returns the exact
131
+ `frozen / frozenAt / treeHash / currentTreeHash / changed / added /
132
+ removed / briefSince / unchanged` shape proposal 2026-09-22 v3
133
+ section 2.2 pins. Before the first freeze the delta is the whole
134
+ tree (`frozen: false`, everything in `added`). Reused unchanged:
135
+ `computeImpact`, `computeTrace`, `computeCoverage`.
136
+ - **DEFINE workflow: freeze record I/O (REQ-172, slice 1).** New
137
+ module `src/define/freeze-record.js` owns `rcf/define/freeze.json`
138
+ with a small local schema (until schemas 0.7 promotes it to
139
+ `manifest.freeze` per ADR-4121). `loadFreezeRecord` returns `null`
140
+ on a missing file; a malformed body raises `FreezeRecordError` with
141
+ a coded reason (`parseFailure | schemaFailure | ioFailure`) and a
142
+ named field. `saveFreezeRecord` validates first, so a bad
143
+ in-memory record never lands on disk; extension fields survive a
144
+ save / load round trip. The `rcf define freeze` verb is a
145
+ later-slice consumer; this slice ships the writer so the verb can
146
+ be built without a second refactor.
147
+ - **DEFINE workflow: four sidecar ledgers and `rcf define ledger`
148
+ (REQ-173, slice 1).** Four ledgers live under `rcf/define/`, one
149
+ JSON file each, each with one numbered sequence per project:
150
+ `brief-ledger.json` (D1 statements, kinded from the closed set
151
+ `capability | constraint | actor | entity | externalSystem |
152
+ surface | outOfScope | openQuestion | amendment`),
153
+ `decisions-ledger.json` (D7, printed in the numbered #241 format),
154
+ `concern-ledger.json` (D5, `applied | waived`),
155
+ `probe-ledger.json` (D6, `low | medium | high`).
156
+ `rcf define ledger <name> <verb>` covers `add`, `resolve` and
157
+ `list`; `brief add --from <file>` splits statements one per
158
+ non-empty line and mints sequential ids (the
159
+ intake-scan-against-frozen-statements hook is a named seam this
160
+ slice leaves for slice 2). `decisions list` prints the #241
161
+ numbered format. `list --json` emits `{ ledger, <arrayKey>: [...] }`.
162
+ A dedicated test proves the walker never surfaces any `rcf/define/`
163
+ path in `walkTree` errors or `tree.byId`.
164
+ - **DEFINE workflow: stage gates D1..D8 (REQ-174, slice 2 of the
165
+ 0.29.0 train).** New pure module `src/query/gates.js` exports one
166
+ check function per stage (`checkD1Brief`..`checkD8Freeze`) plus
167
+ the `STAGE_ORDER`, `STAGE_GATES`, `STAGE_SHORT_NAMES` and
168
+ `INTERFACE_KINDS` constants. Every function returns the exact
169
+ `{ stage, gate, state, checks[] }` shape proposal 2026-09-22 v3
170
+ section 2.4 specifies, with `checks[i]` in the `{ name, ok, over,
171
+ pass, total, failing }` form. Blocking in 0.29.0: D1 (define.brief),
172
+ D2 (define.skeleton), D4 floors (define.stories), D7
173
+ (define.decisions), D8 (define.freeze). Warn-with-ack in 0.29.0:
174
+ D3 (define.shapes), D5 (define.crosscut), D6 (define.consistency)
175
+ \- the state folds to `acknowledged` when the freeze record's
176
+ `gates[<gate>]` entry names `acknowledged` at the current tree
177
+ hash (ADR-4122). D4 per-class opt-outs reuse the existing
178
+ `manifest.baselineAcOptOuts[]` array with a baselineKey of
179
+ `'defineD4:failure'` or `'defineD4:mustNot'`; no new sidecar is
180
+ introduced. The template parser, entity join, D5 catalogue, D6
181
+ contradiction / unsatisfiable scans and probe runner remain as
182
+ named seams for 0.30.
183
+ - **DEFINE workflow: readiness compute and `rcf define readiness`
184
+ CLI (REQ-175, slice 2).** New pure module `src/query/readiness.js`
185
+ exports `computeReadiness(tree, { freeze, ledgers, profile,
186
+ testPointers })` returning the section 2.4 object exactly:
187
+ `{ tree, delta, stages, nextAction, coverage, decisions,
188
+ freezeable }`. The composer runs `computeDelta` once, calls
189
+ `computeImpact` per id in the union of changed and added (skipping
190
+ the fan-out on the unfrozen whole-tree case where the delta IS the
191
+ tree), runs the eight gate check functions over
192
+ `scope = changed union added union impacted`, calls
193
+ `computeCoverage` tree-wide plus once per REQ ancestor of the
194
+ delta, lists open decisions, and folds to `freezeable` and
195
+ `nextAction`. New verb `rcf define readiness [--json] [--check
196
+ <stage>|all]` (stage accepts D1..D8 or the short names
197
+ `brief | skeleton | shapes | stories | crosscut | consistency |
198
+ decisions | freeze`); text output = tree line, next action, chip
199
+ line, delta list, failing items; `--check` exits 4 on a
200
+ blocking-stage failure, exits 0 with a visible `[warn]` line on an
201
+ unacknowledged warn-with-ack failure. The producer is wrapped with
202
+ `runWithAdmissibilityGate` per the NV-BL-SR-03 addendum; on
203
+ admissibility refusal the CLI prints a `[warn]` note and still
204
+ runs the compute, because readiness is a diagnostic and refusing
205
+ to render is the opposite of what it exists to say (ADR-4123).
206
+ Slice 3's `rcf define freeze` will read `freezeable` and refuse
207
+ on any failing stage.
208
+
209
+ ### Fixed
210
+
211
+ - **US auto-mint extends flat legacy sequences instead of jumping to
212
+ the encoded slot (#256).** `nextIdForKind(tree, 'userStory', ...)`
213
+ in `src/core/store/writer.js` assumed every US id encodes
214
+ `US-<reqNum><localTwoDigit>`. On a legacy tree whose USes carry
215
+ flat sequential ids (`US-1`, ..., `US-163`, migrated in from a
216
+ WESPA v1 project) that decode failed and the allocator fell back
217
+ to `US-<reqNumLabel>01`, minting shapes like `US-5301` under
218
+ `REQ-053` next to the existing `US-163`. Classification now runs
219
+ before allocation: every US id is labelled ENCODED (id decomposes
220
+ as `<declaredReqNum><local in 01..99>`) or FLAT. An all-flat tree
221
+ extends past the tree-wide high-water mark (`US-164`), an
222
+ all-encoded tree preserves the historical rule, and a mixed tree
223
+ refuses with a message that names both example ids and asks the
224
+ operator to normalise one shape before retrying. AC auto-mint is
225
+ unchanged.
226
+ - **Slice-1 P3: `loadAllLedgers` omits absent ledger files
227
+ (AC-17501-6).** The `LedgerBundle` typedef on `computeDelta` said
228
+ "if a project has not authored any decisions, the caller passes
229
+ no `decisions` key and the delta records no `ledger:decisions`
230
+ docHash"; the previous implementation always returned the four
231
+ empty bodies. `loadAllLedgers` now `stat`s each ledger file first
232
+ and omits the key on ENOENT, so a project with no ledgers gets
233
+ zero `ledger:<name>` docHashes in the delta and a project with
234
+ only a brief ledger gets exactly one. `loadLedger` still returns
235
+ an empty ledger on ENOENT so single-ledger callers keep the
236
+ ergonomic default.
237
+ - **Slice-2 P3: D2 / D4 scaffold-TODO matcher narrowed to the literal
238
+ `TODO:` placeholder.** `src/query/gates.js`'s `TODO_RE` used to be
239
+ the whole-word `/\btodo\b/i`, which false-positived on prose
240
+ mentioning the word ("no AC description contains the scaffold TODO
241
+ placeholder" on US-17401 / AC-17401-4 tripped D4 against itself).
242
+ The regex is now `/\bTODO:/`: case-sensitive uppercase `TODO`
243
+ followed by a colon, matching every scaffold string
244
+ `src/core/store/init.js` and `src/core/store/writer.js` write for a
245
+ fresh `rcf init` / `rcf define create`. `src/cli/validate.js` keeps
246
+ its broader `\btodo\b/i` matcher for the informational tree-wide
247
+ notice, so incidental prose still surfaces there without failing
248
+ the D2 / D4 gates.
249
+
250
+ ## [0.28.3] - 2026-09-22
251
+
252
+ Batched fix release for the residuals Dex's 0.28.2 round-trip surfaced
253
+ and one HQ-side viewer bug caught the same day. Ships one chain
254
+ amendment (three design amendments on the same redactor AC) and four
255
+ build diffs behind it, plus one viewer-side snapshot fix.
256
+
257
+ ### Fixed
258
+
259
+ - **Feedback redactor no longer folds the git protocol sentinel
260
+ `git@<host>` inside git+ssh, ssh or git URLs as an email (#243).**
261
+ A `--evidence` pointer copied verbatim from a git remote or a clone
262
+ URL survives verbatim, so the operator can re-run the exact command
263
+ they hit. The bare-remote shape `git@<host>:<owner>/<repo>` is
264
+ covered by the same guard. Real emails in surrounding prose still
265
+ fold to `<email>`. The URL rule 4 also now handles git+ssh, ssh and
266
+ git schemes with optional userinfo, so a non-allowlisted host inside
267
+ a clone URL still folds to `<host>` while the sentinel is preserved.
268
+ - **Feedback redactor now treats single-letter trailing labels as
269
+ filename fragments, not hostnames (#247, Codex P1-5 deferred from
270
+ PR #242).** Tokens like `a.b.c` survive verbatim. Single-letter TLDs
271
+ are not registrable domains in normal prose; folding them yields
272
+ more false positives on short identifiers and abbreviated references
273
+ than legitimate redactions.
274
+ - **Feedback redactor emits a visible stderr warning when identity
275
+ folding is disabled (#246).** When `rcf/.identity/profile.md` is
276
+ missing, has no `## Name` heading, has a blank or placeholder Name
277
+ line, or the Name contains only reserved-noun tokens, one line on
278
+ stderr names the file and states that folding is disabled. The
279
+ operator is no longer left thinking their identity is in force when
280
+ it silently is not. Folding still skips per AC-15601-5.
281
+ - **`rcf feedback status --json` and text now expose the destination
282
+ resolution `source` field, matching preview (#244).** Programmatic
283
+ verifiers can now assert which resolver path picked the destination
284
+ (`library-manifest`, `package-bugs-url`, `derived`,
285
+ `sourceRef-derivation`, `library-slug-inference`) without parsing
286
+ preview text. The field is null when the resolver did not attach
287
+ one, e.g. for an unresolved library.
288
+ - **`rcf feedback add --evidence` pointers now render with the label
289
+ matching their shape, not always `(command)` (#245).** The help
290
+ text promises three labels (`command / path:line / id`); the
291
+ classifier now recognises `path:line` and bare paths ending in a
292
+ known file extension as `file`, canonical RCF ids
293
+ (`AC-15601-6`, `REQ-155`, `FBS-181`, `US-15701`) as `id`, and
294
+ everything else as `command`. Whitespace anywhere in the pointer
295
+ is a hard signal for `command`.
296
+ - **`rcf audit view` snapshots its shipped static assets at server
297
+ startup (#248).** The live-view server rendered the HTML body from
298
+ a tree walk captured at startup, but `/style.css`, `/mermaid.min.js`
299
+ and `/live-client.js` were `readFile`-d per request against the
300
+ on-disk file. A checkout branch switch during the server's lifetime
301
+ silently changed what got served; the 2026-09-22 Product Map
302
+ preview rendered unstyled for exactly this reason. All three
303
+ assets are now read once at startup into memory and served from
304
+ there. The tree walker remains the only path that re-reads disk on
305
+ `rcf/` change.
306
+
307
+ ### Chain
308
+
309
+ - AC-15601-6 amended with design amendments R5e (single-letter TLDs
310
+ are filename fragments), R5f (git protocol sentinel protection on
311
+ rule 3, extended URL rule 4 for git+ssh/ssh/git schemes) and R5g
312
+ (visible stderr warning when identity folding is disabled). All
313
+ three land on the same story so operators see one AC that names
314
+ the redactor's full posture.
315
+ - `rcf define validate`: clean. `rcf audit coverage --strict`: clean
316
+ (103 requirements, 0 uncovered).
317
+
318
+ ### Release mechanics
319
+
320
+ - Version bumped: `packages/rcf-lite/package.json` 0.28.2 -> 0.28.3.
321
+ - Changelog entry under `## [0.28.3]` (this section).
322
+ - Feed entry added under `releases/releases.yaml`; `latest` set to
323
+ 0.28.3.
324
+ - Tag / publish: Dave (not this PR).
325
+
9
326
  ## [0.28.2] - 2026-09-22
10
327
 
11
328
  Batched fix release for the seven defects Barry's WSD-lens dogfood on
package/bin/rcf.js CHANGED
@@ -51,6 +51,10 @@ import { main as reqClassifyMain } from '../src/cli/req-classify.js';
51
51
  import { main as reqBaselineMain } from '../src/cli/req-baseline.js';
52
52
  import { main as intakeMain } from '../src/cli/intake.js';
53
53
  import { main as evalMain } from '../src/cli/eval.js';
54
+ import { main as ledgerMain } from '../src/cli/ledger.js';
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';
54
58
 
55
59
  // Verify group members are handled by the verify-suite dispatch tree.
56
60
  import { main as verifyRunMain } from '../src/verify/cli/run.js';
@@ -95,6 +99,10 @@ export const GROUPS = {
95
99
  design: designMain,
96
100
  blueprint: blueprintMain,
97
101
  standards: standardsMain,
102
+ ledger: ledgerMain,
103
+ readiness: readinessMain,
104
+ questions: questionsMain,
105
+ freeze: freezeMain,
98
106
  },
99
107
  build: {
100
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-22-001",
5
- "createdAt": "2026-09-22T08:35:47.450Z",
6
- "buildVersion": "0.28.2-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-22-002",
38
- "createdAt": "2026-09-22T08:35:47.451Z",
39
- "buildVersion": "0.28.2-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-22-003",
71
- "createdAt": "2026-09-22T08:35:47.451Z",
72
- "buildVersion": "0.28.2-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.