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
@@ -0,0 +1,21 @@
1
+ {
2
+ "createdAt": "2026-09-21T18:36:34.519Z",
3
+ "updatedAt": "2026-09-21T18:36:52.512Z",
4
+ "description": "a reviewer opening the review surface on a slow link the initial HTML payload well under 3 MB by rendering only the active grouping fully; the other three groupings emit only their bucket headings (label + count) and hydrate the REQ list on demand when the reader switches grouping or opens a bucket, so first paint is fast and the tab stays interactive on 100+ REQ trees",
5
+ "usId": "US-17007",
6
+ "prdId": "PRD-001",
7
+ "reqId": "REQ-170",
8
+ "version": "0.1.0",
9
+ "status": "draft",
10
+ "title": "Product Map: lazy first-load payload",
11
+ "asA": "a reviewer opening the review surface on a slow link",
12
+ "iWant": "an initial HTML payload well under 3 MB by rendering only the active grouping fully and hydrating the other groupings on demand from a partial endpoint",
13
+ "soThat": "first paint is fast and the tab stays interactive on 100-plus REQ trees",
14
+ "acceptanceCriteria": [
15
+ {
16
+ "id": "AC-17007-1",
17
+ "description": "The Product Map first-load payload target is well under 3 MB. The server emits the shape (default) grouping fully; the other three groupings emit only their bucket headings (label + total count + per-status mini counts) and each bucket carries a data-pm-lazy marker naming its grouping and bucket id. When the reader switches to a lazy grouping OR opens a lazy bucket, the client fetches that grouping fully once (from a partial endpoint the server exposes) and hydrates the bucket into the DOM; subsequent switches use the cached partial. The pass doc states the before/after first-load bytes.",
18
+ "testable": true
19
+ }
20
+ ]
21
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "usId": "US-17008",
3
+ "prdId": "PRD-001",
4
+ "reqId": "REQ-170",
5
+ "version": "0.1.0",
6
+ "status": "draft",
7
+ "title": "Product Map: blueprint badge and by-blueprint grouping",
8
+ "description": "User story under REQ-170. a product reader auditing what came from applied blueprints vs the project's own requirements a visible blueprint badge on every REQ row an applied blueprint contributed, plus a sixth grouping that buckets requirements by contributing blueprint (with an Application bucket for the project's own (non-blueprint) REQs) and a second-level capability split inside each bucket.",
9
+ "asA": "a product reader auditing what came from applied blueprints vs the project's own requirements",
10
+ "iWant": "a blueprint badge on every REQ row that was contributed by a blueprint plus a by-blueprint grouping (one bucket per applied blueprint plus an Application bucket) with capability as the second level inside each bucket",
11
+ "soThat": "I can see at a glance which parts of the tree ride on shared blueprints and which the project owns, and drill from a blueprint to the capabilities it contributed",
12
+ "acceptanceCriteria": [
13
+ {
14
+ "id": "AC-17008-1",
15
+ "description": "Every REQ row inside the Product Map tab that was contributed by an applied blueprint carries a compact blueprint badge (class pm-blueprint-badge) in its summary row, in every grouping (shape, component, trace coverage, capability, and the new by-blueprint grouping itself). The GROUPINGS list on the panel additionally includes 'blueprint'; the by-blueprint grouping enumerates one bucket per entry in manifest.blueprints[] (label: the blueprint's display name or slug, count: number of contributed REQs) plus an Application bucket for the project's own (non-blueprint) REQs (REQs with no blueprint attribution). Inside each blueprint or Application bucket, requirements are split by capability (existing capability:<slug> convention) as a second level, then the usual REQ->US->AC drill-down. The source of truth for blueprint attribution is manifest.blueprints[].contributions[] (parsed by scope.contributionsForBlueprint); the id-prefix fallback (kebab-slug prefix on reqId) is used only when the manifest carries no contributions record for a given blueprint. The hash schema round-trips as #tab=product-map&group=blueprint&status=<s>&open=<ids>, and the /product-map/blueprint partial endpoint serves the grouping body for the client's lazy-render fetch. A project with no applied blueprints renders a single Application bucket cleanly (not an error, not an empty tab).",
16
+ "testable": true
17
+ }
18
+ ],
19
+ "tags": [],
20
+ "createdAt": "2026-09-22T11:59:39Z",
21
+ "updatedAt": "2026-09-22T15:00:00Z"
22
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "usId": "US-17101",
3
+ "prdId": "PRD-001",
4
+ "reqId": "REQ-171",
5
+ "version": "0.1.0",
6
+ "status": "draft",
7
+ "title": "Dogfood chain carries capability tags on every requirement",
8
+ "description": "User story under REQ-171. the maintainer of the rcf-lite dogfood chain every REQ under rcf-lite/rcf to carry at least one capability:<slug> tag drawn from the documented taxonomy",
9
+ "asA": "the maintainer of the rcf-lite dogfood chain",
10
+ "iWant": "every REQ under rcf-lite/rcf to carry at least one capability:<slug> tag drawn from the documented taxonomy",
11
+ "soThat": "the by-capability Product Map view has something to bucket on, and the trial can be evaluated against real data rather than a fixture",
12
+ "acceptanceCriteria": [
13
+ {
14
+ "id": "AC-17101-1",
15
+ "description": "Every REQ under packages/rcf-lite/rcf/requirements/ carries at least one tag matching the regex ^capability:[a-z0-9]+(-[a-z0-9]+)*$, and every slug used maps to an entry in the documented capability taxonomy.",
16
+ "testable": true
17
+ }
18
+ ],
19
+ "tags": [],
20
+ "createdAt": "2026-09-21T17:00:00.000Z",
21
+ "updatedAt": "2026-09-21T17:00:00.000Z"
22
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "usId": "US-17102",
3
+ "prdId": "PRD-001",
4
+ "reqId": "REQ-171",
5
+ "version": "0.1.0",
6
+ "status": "draft",
7
+ "title": "Capability taxonomy is documented in the rcf-lite docs",
8
+ "description": "User story under REQ-171. a reader of the rcf-lite docs deciding whether to adopt the convention the capability:<slug> convention, the initial taxonomy and the rule for adding a new capability documented alongside the rest of the rcf-lite docs",
9
+ "asA": "a reader of the rcf-lite docs deciding whether to adopt the convention",
10
+ "iWant": "the capability:<slug> convention, the initial taxonomy and the rule for adding a new capability documented alongside the rest of the rcf-lite docs",
11
+ "soThat": "a new capability is added deliberately rather than by drift, and a reader can look up what each slug means",
12
+ "acceptanceCriteria": [
13
+ {
14
+ "id": "AC-17102-1",
15
+ "description": "packages/rcf-lite/docs contains a capability tags section listing every slug in the initial taxonomy with a one-line meaning, plus the rule for adding a new capability (single-word verb or noun, kebab-case, must map to a product surface). The section is linked from docs/README.md so it is reachable from the docs entry point.",
16
+ "testable": true
17
+ }
18
+ ],
19
+ "tags": [],
20
+ "createdAt": "2026-09-21T17:00:00.000Z",
21
+ "updatedAt": "2026-09-21T17:00:00.000Z"
22
+ }
@@ -0,0 +1,38 @@
1
+ {
2
+ "usId": "US-17201",
3
+ "prdId": "PRD-001",
4
+ "reqId": "REQ-172",
5
+ "version": "0.1.0",
6
+ "status": "draft",
7
+ "title": "Delta detection and freeze record land as reusable primitives",
8
+ "description": "User story under REQ-172. The detection-model foundation lands as pure, importable modules and one durable local record.",
9
+ "asA": "the maintainer of a rcf-lite tree",
10
+ "iWant": "hashDocument, computeTreeHash, computeDelta and the rcf/define/freeze.json reader/writer to land as pure modules exposed on the query surface, with a documented return shape that later DEFINE slices can call unchanged",
11
+ "soThat": "the gates, readiness view, freeze verb and bundle-side read all consume the same detection primitives, and a hand reformat of a document never surfaces as a change",
12
+ "acceptanceCriteria": [
13
+ {
14
+ "id": "AC-17201-1",
15
+ "description": "computeDelta(tree, freeze, ledgers) returns the exact object shape proposal 2026-09-22 v3 section 2.2 specifies (frozen, frozenAt, treeHash, currentTreeHash, changed, added, removed, briefSince, unchanged); given a matching freeze the delta reports empty changed / added / removed and unchanged equal to the number of docHashes; given divergent tree state changed / added / removed classify every id correctly against the freeze record.",
16
+ "testable": true
17
+ },
18
+ {
19
+ "id": "AC-17201-2",
20
+ "description": "hashDocument returns a sha256:<64-hex> string over the canonical JSON form of the parsed document (keys sorted recursively, no whitespace), and is invariant under a whitespace-only reformat or a key reorder: two documents that parse to the same object hash identically.",
21
+ "testable": true
22
+ },
23
+ {
24
+ "id": "AC-17201-3",
25
+ "description": "Loading rcf/define/freeze.json when the file is absent returns null; loading a malformed file (bad JSON, missing docHashes, non-sha256 hash value, negative briefStatements) raises FreezeRecordError with a code (parseFailure or schemaFailure) and a named field so a caller can log the exact failure.",
26
+ "testable": true
27
+ },
28
+ {
29
+ "id": "AC-17201-4",
30
+ "description": "Saving then loading a freeze record round-trips every documented field including extension fields the schema does not police (counts, litmus, versions, note), and saveFreezeRecord refuses to persist an invalid record: no file is written on validation failure.",
31
+ "testable": true
32
+ }
33
+ ],
34
+ "tacIds": ["TAC-4120-define-delta-and-freeze"],
35
+ "tags": [],
36
+ "createdAt": "2026-09-24T12:00:00Z",
37
+ "updatedAt": "2026-09-24T12:00:00Z"
38
+ }
@@ -0,0 +1,38 @@
1
+ {
2
+ "usId": "US-17301",
3
+ "prdId": "PRD-001",
4
+ "reqId": "REQ-173",
5
+ "version": "0.1.0",
6
+ "status": "draft",
7
+ "title": "rcf define ledger reads and writes the four sidecars under rcf/define/",
8
+ "description": "User story under REQ-173. The operator-facing CLI for the four sidecar ledgers lands with add / resolve / list on every ledger name.",
9
+ "asA": "an operator staging or reviewing a DEFINE change",
10
+ "iWant": "rcf define ledger to author brief statements, decisions, concern dispositions and probe findings under rcf/define/ with numbered ids stable for the life of the project, and to leave every ledger invisible to the walker",
11
+ "soThat": "the freeze record's high-water mark, the D7 decisions list, D5 concern coverage and D6 probe findings all have a written record and every later DEFINE slice reads the same seam without discovering a second source of truth",
12
+ "acceptanceCriteria": [
13
+ {
14
+ "id": "AC-17301-1",
15
+ "description": "rcf define ledger brief add --kind <k> --text <t> appends a numbered statement to rcf/define/brief-ledger.json, mints the next id (highest current + 1), stamps status open and addedAt (ISO-8601), refuses an unknown kind with a usage-class error, and refuses --text combined with --from with a usage-class error.",
16
+ "testable": true
17
+ },
18
+ {
19
+ "id": "AC-17301-2",
20
+ "description": "rcf define ledger decisions list prints the numbered #241 format: one decision per item (id. question), options rendered as 'letter) text', the default letter labelled 'default:', and what it blocks labelled 'blocks:'. rcf define ledger <name> list --json emits the machine-readable envelope { ledger, <arrayKey>: [...] }.",
21
+ "testable": true
22
+ },
23
+ {
24
+ "id": "AC-17301-3",
25
+ "description": "rcf define ledger brief add --from <file> reads the file, splits it into one statement per non-empty line (stripping leading '- ', '* ' or '<n>. ' bullets), mints sequential ids for every statement, refuses if the file produced zero non-empty lines, and stamps the file path as source unless --source overrides it. The intake-scan-against-frozen-statements hook is a named seam in the writer, not called in this slice.",
26
+ "testable": true
27
+ },
28
+ {
29
+ "id": "AC-17301-4",
30
+ "description": "walkTree run over a project that carries rcf/define/freeze.json, all four ledger files, and a bug-bait file named req-999.json under rcf/define/ never surfaces any rcf/define/ file as a tree.byId document and reports no walker error naming a rcf/define/ path. The sidecar directory is invisible to every consumer of walkTree.",
31
+ "testable": true
32
+ }
33
+ ],
34
+ "tacIds": ["TAC-4121-define-ledgers"],
35
+ "tags": [],
36
+ "createdAt": "2026-09-24T12:00:00Z",
37
+ "updatedAt": "2026-09-24T12:00:00Z"
38
+ }
@@ -0,0 +1,50 @@
1
+ {
2
+ "usId": "US-17302",
3
+ "prdId": "PRD-001",
4
+ "reqId": "REQ-173",
5
+ "version": "0.1.0",
6
+ "status": "draft",
7
+ "title": "update and the pointer grammar",
8
+ "description": "User story under REQ-173. Every ledger supports `update <id>` with field patches validated as `add` validates; `resolvedBy` on a brief statement is a closed pointer grammar validated by D2.",
9
+ "asA": "harness",
10
+ "iWant": "to patch a statement's kind, text or resolution",
11
+ "soThat": "a correction does not mint a duplicate",
12
+ "acceptanceCriteria": [
13
+ {
14
+ "id": "AC-17302-1",
15
+ "description": "[happy] given statement 7, when rcf define ledger brief update 7 --kind constraint --resolved-by REQ-003 runs, then the statement carries kind constraint and resolvedBy REQ-003 and its id and addedAt are unchanged.",
16
+ "testable": true
17
+ },
18
+ {
19
+ "id": "AC-17302-2",
20
+ "description": "[happy] given decision 2 with one option, when rcf define ledger decisions update 2 --option a:x --option b:y --default a runs, then decisions:wellFormed passes it.",
21
+ "testable": true
22
+ },
23
+ {
24
+ "id": "AC-17302-3",
25
+ "description": "[happy] given each pointer form REQ-nnn, TAD.entity:<name>, PRD.user:<name>, TAD.system:<name>, TAC-nnnn and omitted:<reason> resolving on the fixture, when D2 runs, then skeleton:resolvedBy passes the statement.",
26
+ "testable": true
27
+ },
28
+ {
29
+ "id": "AC-17302-4",
30
+ "description": "[failure] given --resolved-by \"loan thing\", when update runs, then it exits 2 naming the grammar and writes nothing.",
31
+ "testable": true
32
+ },
33
+ {
34
+ "id": "AC-17302-5",
35
+ "description": "[failure] given --resolved-by REQ-999 on a tree with no REQ-999, when D2 runs, then skeleton:resolvedBy fails the statement with \"pointer does not resolve\".",
36
+ "testable": true
37
+ },
38
+ {
39
+ "id": "AC-17302-6",
40
+ "description": "[must-not] given a statement whose text contains an existing REQ title and no resolvedBy, when D2 runs in 0.30.0, then skeleton:resolvedBy does not pass it on the title hit.",
41
+ "testable": true
42
+ }
43
+ ],
44
+ "tacIds": [
45
+ "TAC-4121-define-ledgers"
46
+ ],
47
+ "tags": [],
48
+ "createdAt": "2026-10-02T16:40:00Z",
49
+ "updatedAt": "2026-10-02T16:40:00Z"
50
+ }
@@ -0,0 +1,70 @@
1
+ {
2
+ "usId": "US-17401",
3
+ "prdId": "PRD-001",
4
+ "reqId": "REQ-174",
5
+ "version": "0.1.0",
6
+ "status": "draft",
7
+ "title": "Stage gates land as pure check functions with per-stage state",
8
+ "description": "User story under REQ-174. Eight stage-gate check functions land in src/query/gates.js with a stable per-stage return shape that computeReadiness and every later slice can consume unchanged.",
9
+ "asA": "a downstream consumer of DEFINE gates (readiness, freeze, viewer)",
10
+ "iWant": "gates.js to expose one pure check function per stage D1..D8, each returning a { stage, gate, state, checks[] } object with checks in the { name, ok, over: 'delta'|'tree', pass, total, failing: [{ id, why }] } shape",
11
+ "soThat": "computeReadiness composes the eight checks, the freeze verb refuses on any failing state, and the viewer's Readiness tab prints the same rows the CLI does with no schema translation",
12
+ "acceptanceCriteria": [
13
+ {
14
+ "id": "AC-17401-1",
15
+ "description": "src/query/gates.js exports one check function per stage D1..D8 (checkD1Brief, checkD2Skeleton, checkD3Shapes, checkD4Stories, checkD5Crosscut, checkD6Consistency, checkD7Decisions, checkD8Freeze), each taking (tree, { ledgers, profile, scope, freeze, delta, validateErrors, probeOpenCount, coverageTree }) and returning { stage, gate, state, checks[] }; every entry in checks is { name, ok, over: 'delta'|'tree', pass, total, failing: [{ id, why }] } (failing empty on ok).",
16
+ "testable": true
17
+ },
18
+ {
19
+ "id": "AC-17401-2",
20
+ "description": "Blocking stages in 0.29.0 (D1, D2, D4, D7, D8) report state 'passed' when every check ok is true, 'failing' when any check ok is false; warn-with-ack stages (D3, D5, D6) report 'passed' when every check ok is true, 'failing' when any check ok is false and the freeze record does NOT acknowledge that gate at the current tree hash, and 'acknowledged' when the freeze.gates[<gate>] entry names state 'acknowledged' and at.hash === currentTreeHash and any check ok is false.",
21
+ "testable": true
22
+ },
23
+ {
24
+ "id": "AC-17401-3",
25
+ "description": "notApplicable is decided per stage per proposal section 3.2: D2 notApplicable when no statement of a resolving kind (capability, constraint, entity, actor, externalSystem, surface) is in the delta AND no REQ, PRD or TAD is in scope; D3 notApplicable when no TAC and no shaped REQ (httpApi/persistence/auth) is in scope; D5 notApplicable when no REQ is in scope; D7 notApplicable when no open decisions exist AND the profile sets skipReviewFor: singleDocument AND the delta holds exactly one document; D4 and D6 use their own rules; D1 and D8 never notApplicable.",
26
+ "testable": true
27
+ },
28
+ {
29
+ "id": "AC-17401-4",
30
+ "description": "checkD4Stories enforces the D4 floors: every REQ in scope has a US (fail: 'no owning user story'), every US in scope has a testable AC ('missing testable AC'), a failure AC (parsed by the bracketed [failure] prefix on AC description) or a reasoned opt-out per class (manifest.baselineAcOptOuts[] entry with baselineKey 'defineD4:failure' and matching scope), a must-not AC (parsed by [must-not] prefix) or a reasoned opt-out per class (baselineKey 'defineD4:mustNot'), tacIds non-empty and every named tac resolving to a real TAC, and no AC description contains the scaffold TODO placeholder.",
31
+ "testable": true
32
+ },
33
+ {
34
+ "id": "AC-17401-5",
35
+ "description": "checkD3Shapes runs only cheap data-backed checks in 0.29.0: every TAC in scope has at least one interface (fail: 'no interfaces authored'), and every interface's kind is in the closed vocabulary { recordShape, httpRoute, event, cliCommand, uiRoute, port, fileFormat, fixture, other } (fail: 'unknown interface kind <k>'). The template parser, entity-name join, ownerRef and path resolution are named seams (not called this slice) and D3 stays warn-with-ack.",
36
+ "testable": true
37
+ },
38
+ {
39
+ "id": "AC-17401-6",
40
+ "description": "checkD5Crosscut runs only cheap data-backed checks in 0.29.0: TAD.securityArchitecture non-empty when the tree carries any REQ whose shapeClassification.shapes includes 'auth' or 'httpApi'; TAD.operationalConcerns non-empty when any AC description carries the '[deployed]' marker (a cheap presence signal proposal section 3.2 D5 lists as 'deployed-scope AC'); concern-ledger entries in scope disposed as 'applied' or 'waived' (no dangling 'open' concerns on REQs in scope). The full catalogue and per-pair enumeration are named seams for 0.30.",
41
+ "testable": true
42
+ },
43
+ {
44
+ "id": "AC-17401-7",
45
+ "description": "checkD6Consistency runs only cheap data-backed checks in 0.29.0: validate is clean tree-wide (validateErrors is empty; the caller passes the walker + validator's error list), and probe-ledger holds zero 'open' probe entries. Contradiction-lite, unsatisfiable-lite, duplicates and orphan-interface scans, plus the probe runner, are named seams for 0.30.",
46
+ "testable": true
47
+ },
48
+ {
49
+ "id": "AC-17401-8",
50
+ "description": "checkD8Freeze enforces the tree-wide gate: every prior stage state (D1..D7 as computeReadiness composes them) is passed or acknowledged at the current hash; every AC id in the tree is bound by exactly one FBS (walker's fbsByAcId map has length 1); the queue head (computeQueue.nextActionable) is not null; validateErrors is empty. The stage is never notApplicable.",
51
+ "testable": true
52
+ },
53
+ {
54
+ "id": "AC-17401-9",
55
+ "description": "checkD2Skeleton reads tad.dataArchitecture.dataStores and tad.dataArchitecture.coreEntities (not top-level) when evaluating skeleton:tadPersistence; a tree whose TAD places both arrays under dataArchitecture per rcf-schemas 0.6.3 passes the check and a tree with the arrays missing or empty under dataArchitecture fails with { id: 'TAD.dataArchitecture.dataStores' } / { id: 'TAD.dataArchitecture.coreEntities' }.",
56
+ "testable": true
57
+ },
58
+ {
59
+ "id": "AC-17401-10",
60
+ "description": "src/setup/identity-seed.js IDENTITY_TEMPLATE seeds a '## Surface' section containing one line that is one of 'viewer' | 'runningApp' | 'prDiff' (default 'prDiff' with explanatory text matching the Register section's style) so that a project immediately after 'rcf init' passes checkD1Brief's profile:surface check without further operator action. The seed stays idempotent (an existing profile.md is left byte-identical, per the slice-1 'kept' contract).",
61
+ "testable": true
62
+ }
63
+ ],
64
+ "tacIds": [
65
+ "TAC-4122-define-gates"
66
+ ],
67
+ "tags": [],
68
+ "createdAt": "2026-09-24T14:30:00Z",
69
+ "updatedAt": "2026-10-01T13:03:38Z"
70
+ }
@@ -0,0 +1,55 @@
1
+ {
2
+ "usId": "US-17402",
3
+ "prdId": "PRD-001",
4
+ "reqId": "REQ-174",
5
+ "version": "0.1.0",
6
+ "status": "draft",
7
+ "title": "Persona tag on every gate check",
8
+ "description": "User story under REQ-174. Every entry in stages[].checks[] carries an owning persona (productOwner | engineer) declared in code next to the check, so readiness consumers (the CLI, the viewer tab, delivery-stream artefacts) can route a failing check to whoever is actually blocked.",
9
+ "asA": "an engineer reading a readiness report",
10
+ "iWant": "every failing check to say whose question it is",
11
+ "soThat": "product-owner questions reach the product owner and engineering gaps stay with me",
12
+ "acceptanceCriteria": [
13
+ {
14
+ "id": "AC-17402-1",
15
+ "description": "[happy] Given any tree, when readiness is computed, then every entry in stages[].checks[] carries persona equal to 'productOwner' or 'engineer' and a non-empty question string.",
16
+ "testable": true
17
+ },
18
+ {
19
+ "id": "AC-17402-2",
20
+ "description": "[happy] Given the D1 checks, when readiness is computed, then brief:sinceFreeze, brief:kinds, brief:openQuestions and brief:profile carry persona 'productOwner'.",
21
+ "testable": true
22
+ },
23
+ {
24
+ "id": "AC-17402-3",
25
+ "description": "[happy] Given the D2 checks, when readiness is computed, then skeleton:resolvedBy and skeleton:reqIntent carry persona 'productOwner' and skeleton:reqShape, skeleton:tadPersistence and skeleton:deployAdr carry persona 'engineer'.",
26
+ "testable": true
27
+ },
28
+ {
29
+ "id": "AC-17402-4",
30
+ "description": "[happy] Given the D4 and D7 checks, when readiness is computed, then stories:reqHasUs and decisions:wellFormed carry persona 'productOwner' and stories:usFloors and decisions:allAnswered carry persona 'engineer'.",
31
+ "testable": true
32
+ },
33
+ {
34
+ "id": "AC-17402-5",
35
+ "description": "[happy] Given the D3, D5, D6 and D8 checks, when readiness is computed, then every check carries persona 'engineer'.",
36
+ "testable": true
37
+ },
38
+ {
39
+ "id": "AC-17402-6",
40
+ "description": "[must-not] Given any check, when readiness is computed, then no check carries a persona value other than 'productOwner' or 'engineer', and no failing item carries its own persona.",
41
+ "testable": true
42
+ },
43
+ {
44
+ "id": "AC-17402-7",
45
+ "description": "[failure] Given a notApplicable stage, when readiness is computed, then its stage:<D>:scope placeholder check carries the stage's STAGE_FALLBACK_PERSONA and ok true.",
46
+ "testable": true
47
+ }
48
+ ],
49
+ "tacIds": [
50
+ "TAC-4122-define-gates"
51
+ ],
52
+ "tags": [],
53
+ "createdAt": "2026-10-01T14:30:00Z",
54
+ "updatedAt": "2026-10-01T14:30:00Z"
55
+ }
@@ -0,0 +1,60 @@
1
+ {
2
+ "usId": "US-17403",
3
+ "prdId": "PRD-001",
4
+ "reqId": "REQ-174",
5
+ "version": "0.1.0",
6
+ "status": "draft",
7
+ "title": "Split heterogeneous checks and detect the D3 draft marker",
8
+ "description": "User story under REQ-174. skeleton:reqFields and decisions:allAnswered split into homogeneous checks (per persona), and a new D3 shapes:draftSettled flags any interface whose description still carries the leading [draft] marker. L1 pre-populated shapes stay distinguishable from engineer-settled ones.",
9
+ "asA": "an engineer",
10
+ "iWant": "the mixed checks split and a draft interface distinguishable from a settled one",
11
+ "soThat": "a shape the L1 agent pre-populated never reads as my finished work",
12
+ "acceptanceCriteria": [
13
+ {
14
+ "id": "AC-17403-1",
15
+ "description": "[happy] Given a REQ in scope with a TODO description and no shapeClassification, when D2 runs, then skeleton:reqIntent fails the REQ for the description and skeleton:reqShape fails the same REQ for the missing shapes.",
16
+ "testable": true
17
+ },
18
+ {
19
+ "id": "AC-17403-2",
20
+ "description": "[happy] Given a REQ in scope with a description and shapes but no domain, when D2 runs, then skeleton:reqIntent fails the REQ with 'domain missing' and skeleton:reqShape passes it.",
21
+ "testable": true
22
+ },
23
+ {
24
+ "id": "AC-17403-3",
25
+ "description": "[happy] Given a TAC in scope whose only interface description starts with [draft], when D3 runs, then shapes:tacHasInterface passes the TAC and shapes:draftSettled fails <tacId>:<name> with 'draft interface pre-populated at L1, not yet settled'.",
26
+ "testable": true
27
+ },
28
+ {
29
+ "id": "AC-17403-4",
30
+ "description": "[happy] Given the same TAC after the [draft] marker is removed, when D3 runs, then shapes:draftSettled passes it.",
31
+ "testable": true
32
+ },
33
+ {
34
+ "id": "AC-17403-5",
35
+ "description": "[failure] Given a [draft] interface whose kind is not in INTERFACE_KINDS, when D3 runs, then shapes:kindVocabulary fails it exactly as it would a settled interface.",
36
+ "testable": true
37
+ },
38
+ {
39
+ "id": "AC-17403-6",
40
+ "description": "[happy] Given a decisions ledger with one open entry that has a question, two options and a default, when D7 runs, then decisions:wellFormed passes and decisions:allAnswered fails the entry.",
41
+ "testable": true
42
+ },
43
+ {
44
+ "id": "AC-17403-7",
45
+ "description": "[failure] Given a decisions ledger entry with one option and no default, when D7 runs, then decisions:wellFormed fails it with 'decision is not enumerated (question, two or more options, a default)'.",
46
+ "testable": true
47
+ },
48
+ {
49
+ "id": "AC-17403-8",
50
+ "description": "[must-not] Given any tree, when D2 or D7 runs, then no check named skeleton:reqFields is emitted and the stage envelope shape (stage, gate, state, checks) is unchanged.",
51
+ "testable": true
52
+ }
53
+ ],
54
+ "tacIds": [
55
+ "TAC-4122-define-gates"
56
+ ],
57
+ "tags": [],
58
+ "createdAt": "2026-10-01T14:30:00Z",
59
+ "updatedAt": "2026-10-01T14:30:00Z"
60
+ }
@@ -0,0 +1,48 @@
1
+ {
2
+ "usId": "US-17501",
3
+ "prdId": "PRD-001",
4
+ "reqId": "REQ-175",
5
+ "version": "0.1.0",
6
+ "status": "draft",
7
+ "title": "computeReadiness and rcf define readiness render the same object",
8
+ "description": "User story under REQ-175. computeReadiness lands as a pure module and rcf define readiness as its CLI twin. The viewer's Readiness tab (slice 5) will render the same object with no schema translation.",
9
+ "asA": "an operator asking 'can I build, and if not what is in the way'",
10
+ "iWant": "one pure compute that composes delta, fan-out, gates, coverage and decisions into a single object, and one CLI that prints it in a compact form or emits it as JSON",
11
+ "soThat": "the tree line, next action, stage chips, delta list and failing items are the same wherever they are shown, and slice 3's rcf define freeze refuses on the same freezeable flag the CLI reports",
12
+ "acceptanceCriteria": [
13
+ {
14
+ "id": "AC-17501-1",
15
+ "description": "computeReadiness(tree, { freeze, ledgers, profile, testPointers }) returns the exact section 2.4 shape: tree { frozen, frozenAt, treeHash, currentTreeHash, buildAt, fbsTotal }, delta { changed, added, removed, briefSince, impacted, impactedFbs }, stages [{ stage, gate, state, checks }], nextAction { stage, check, ids, command } or null, coverage { tree, delta }, decisions [...open in #241 format], freezeable boolean. freezeable is true when every stage state is 'passed', 'acknowledged' or 'notApplicable'.",
16
+ "testable": true
17
+ },
18
+ {
19
+ "id": "AC-17501-2",
20
+ "description": "Fan-out is computed by calling computeImpact once per id in the union of changed and added; impacted is the union of every impact node id excluding the pivots; impactedFbs is the subset whose kind is 'fbs' and actionNeeded is 're-execute'. Gates run over scope = changed union added union impacted (with duplicates removed).",
21
+ "testable": true
22
+ },
23
+ {
24
+ "id": "AC-17501-3",
25
+ "description": "Coverage is tree-wide plus per REQ ancestor of the delta: coverage.tree is computeCoverage(tree, { testPointers, strict: true }) once over the whole tree; coverage.delta is an array with one CoverageResult per unique REQ id reachable by walking back from every delta id (changed union added) through parentByChild until the reqId is found, using scopeId per invocation. testPointers is the map the CLI produced with resolveTestPointers.",
26
+ "testable": true
27
+ },
28
+ {
29
+ "id": "AC-17501-4",
30
+ "description": "nextAction picks the first stage in D1..D8 order whose state is 'failing', then the first failing check in that stage's checks[] (or the check with the largest failing.length when tie); it names the stage id, the check name, the failing ids (deduped), and a command string like 'rcf define readiness --check <stage-short-name> after editing'. nextAction is null when every stage is passed / acknowledged / notApplicable.",
31
+ "testable": true
32
+ },
33
+ {
34
+ "id": "AC-17501-5",
35
+ "description": "rcf define readiness prints a text summary: the tree line ('Frozen at <shortHash> on <frozenAt>. N documents changed since, M impacted. Build at <fbsId> of <total>; K FBS impacted.' or 'Unfrozen. N documents; the whole tree is the delta.'), the next action line, a chip line 'D1:passed D2:failing D3:acknowledged D4:notApplicable ...', and the failing-items list per stage. --json emits the full computeReadiness object under `${JSON.stringify(result, null, 2)}\\n`. --check <stage> (D1..D8 or short name brief|skeleton|shapes|stories|crosscut|consistency|decisions|freeze) prints only that stage and exits 0 when its state is 'passed' or 'acknowledged' or 'notApplicable', exit 4 on 'failing' for blocking stages (D1, D2, D4, D7, D8), exit 0 with a visible '[warn]' line on 'failing' for warn-with-ack stages (D3, D5, D6). The verb wraps its producer with runWithAdmissibilityGate and, on admissibility refusal, prints the refusal on stderr and exits 4.",
36
+ "testable": true
37
+ },
38
+ {
39
+ "id": "AC-17501-6",
40
+ "description": "loadAllLedgers({ projectRoot }) returns a LedgerBundle that OMITS a ledger key when the sidecar file does not exist (ENOENT), so computeDelta records no docHash for absent ledgers; the docstring on computeDelta (LedgerBundle typedef) and the loader implementation agree. A project that has authored a brief ledger and no others sees exactly one 'ledger:brief' entry in the delta docHashes; a project that has authored no ledgers sees zero 'ledger:*' entries.",
41
+ "testable": true
42
+ }
43
+ ],
44
+ "tacIds": ["TAC-4123-define-readiness"],
45
+ "tags": [],
46
+ "createdAt": "2026-09-24T14:30:00Z",
47
+ "updatedAt": "2026-09-24T14:30:00Z"
48
+ }
@@ -0,0 +1,60 @@
1
+ {
2
+ "usId": "US-17502",
3
+ "prdId": "PRD-001",
4
+ "reqId": "REQ-175",
5
+ "version": "0.1.0",
6
+ "status": "draft",
7
+ "title": "Two levels folded on one readiness object",
8
+ "description": "User story under REQ-175. computeReadiness folds levels (intentComplete, readyToBuild) and personas (productOwner, engineer) from stages[].checks[] on every read; nothing new is written. The `rcf define readiness --level intent --json` output at a tree hash is the artefact a delivery stream picks up.",
9
+ "asA": "a delivery stream",
10
+ "iWant": "`rcf define readiness --level intent --json` at a tree hash to be the artefact that says the product owner's part is done",
11
+ "soThat": "I can pick a tree up without a hand-over meeting",
12
+ "acceptanceCriteria": [
13
+ {
14
+ "id": "AC-17502-1",
15
+ "description": "[happy] Given a tree where every productOwner check is ok and at least one engineer check fails, when readiness is computed, then levels.intentComplete.ok is true and levels.readyToBuild.ok is false.",
16
+ "testable": true
17
+ },
18
+ {
19
+ "id": "AC-17502-2",
20
+ "description": "[happy] Given a tree where freezeable is true, when readiness is computed, then levels.readyToBuild.ok is true and levels.intentComplete.ok is true.",
21
+ "testable": true
22
+ },
23
+ {
24
+ "id": "AC-17502-3",
25
+ "description": "[failure] Given a tree where brief:profile fails, when readiness is computed, then levels.intentComplete.ok is false and levels.intentComplete.blockedBy holds one blocker for D1 brief:profile with persona productOwner and ids profile:surface and profile:register.",
26
+ "testable": true
27
+ },
28
+ {
29
+ "id": "AC-17502-4",
30
+ "description": "[happy] Given a D3 stage acknowledged at the current hash with a failing engineer check, when readiness is computed, then that check is absent from levels.readyToBuild.blockedBy.",
31
+ "testable": true
32
+ },
33
+ {
34
+ "id": "AC-17502-5",
35
+ "description": "[happy] Given any tree, when readiness is computed, then personas.productOwner.blockers deep-equals levels.intentComplete.blockedBy and levels.readyToBuild.nextAction deep-equals nextAction.",
36
+ "testable": true
37
+ },
38
+ {
39
+ "id": "AC-17502-6",
40
+ "description": "[happy] Given failing engineer checks in D2 and D4 and a failing productOwner check in D4 only, when readiness is computed, then personas.productOwner.nextAction names D4 and personas.engineer.nextAction names D2.",
41
+ "testable": true
42
+ },
43
+ {
44
+ "id": "AC-17502-7",
45
+ "description": "[must-not] Given any invocation of `rcf define readiness`, when it completes, then no file under rcf/ has been created or modified.",
46
+ "testable": true
47
+ },
48
+ {
49
+ "id": "AC-17502-8",
50
+ "description": "[must-not] Given the 0.28.4 JSON consumer fields (tree, delta, stages, nextAction, coverage, decisions, freezeable), when readiness is emitted under 0.29.0, then every one of them is present with its 0.28.4 type.",
51
+ "testable": true
52
+ }
53
+ ],
54
+ "tacIds": [
55
+ "TAC-4123-define-readiness"
56
+ ],
57
+ "tags": [],
58
+ "createdAt": "2026-10-01T14:30:00Z",
59
+ "updatedAt": "2026-10-01T14:30:00Z"
60
+ }
@@ -0,0 +1,65 @@
1
+ {
2
+ "usId": "US-17503",
3
+ "prdId": "PRD-001",
4
+ "reqId": "REQ-175",
5
+ "version": "0.1.0",
6
+ "status": "draft",
7
+ "title": "Level and persona flags on rcf define readiness",
8
+ "description": "User story under REQ-175. The verb exposes the two levels folded in US-17502 through --level intent|build and groups the text report by persona via --persona productOwner|engineer. --level drives the exit code against levels.<which>.ok (stricter than --check all on warn-with-ack failures per ADR-4126 and decision 4 of the step 2 spec); --persona is a display filter and never affects the exit code or JSON content. The JSON gains a _meta.level marker when --level is set; both verdict lines always print at the top of the text report. See the DEFINE step 2 persona-levels spec dated 2026-10-01 (section 3) for the full flag table and exit matrix.",
9
+ "asA": "an operator",
10
+ "iWant": "--level intent|build and --persona on rcf define readiness",
11
+ "soThat": "a script exits on the verdict it cares about and a person sees their own questions first",
12
+ "acceptanceCriteria": [
13
+ {
14
+ "id": "AC-17503-1",
15
+ "description": "[happy] Given no --level and no --check, when the verb runs on a failing tree, then it prints both verdict lines and exits 0.",
16
+ "testable": true
17
+ },
18
+ {
19
+ "id": "AC-17503-2",
20
+ "description": "[happy] Given --level intent on a tree where only engineer checks fail, when the verb runs, then it prints 'Intent-complete: yes.' and exits 0.",
21
+ "testable": true
22
+ },
23
+ {
24
+ "id": "AC-17503-3",
25
+ "description": "[failure] Given --level intent on a tree where a productOwner check fails, when the verb runs, then it exits 4.",
26
+ "testable": true
27
+ },
28
+ {
29
+ "id": "AC-17503-4",
30
+ "description": "[failure] Given --level build on a tree with an unacknowledged D3 failure and every blocking stage passed, when the verb runs, then it prints the [warn] line and exits 4.",
31
+ "testable": true
32
+ },
33
+ {
34
+ "id": "AC-17503-5",
35
+ "description": "[happy] Given --check all on the same tree, when the verb runs, then it exits 0, unchanged from 0.28.4.",
36
+ "testable": true
37
+ },
38
+ {
39
+ "id": "AC-17503-6",
40
+ "description": "[happy] Given --persona productOwner, when the verb runs in text mode, then the engineer block is one line with its check count and the exit code is the same as without the flag.",
41
+ "testable": true
42
+ },
43
+ {
44
+ "id": "AC-17503-7",
45
+ "description": "[failure] Given --level ship or --persona architect, when the verb runs, then it exits 2 with a usage line naming the accepted values.",
46
+ "testable": true
47
+ },
48
+ {
49
+ "id": "AC-17503-8",
50
+ "description": "[happy] Given --json --level intent, when the verb runs, then _meta.level is 'intent' and the object carries levels and personas.",
51
+ "testable": true
52
+ },
53
+ {
54
+ "id": "AC-17503-9",
55
+ "description": "[happy] Given the text report on a failing tree, when it renders, then the product-owner block precedes the engineer block and each failing check line carries its persona inside the parenthesis after over.",
56
+ "testable": true
57
+ }
58
+ ],
59
+ "tacIds": [
60
+ "TAC-4123-define-readiness"
61
+ ],
62
+ "tags": [],
63
+ "createdAt": "2026-10-01T16:00:00Z",
64
+ "updatedAt": "2026-10-01T16:00:00Z"
65
+ }