rcf-lite 0.28.4 → 0.29.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (168) hide show
  1. package/CHANGELOG.md +107 -1
  2. package/bin/rcf.js +4 -0
  3. package/fixtures/canary-manifest.json +9 -9
  4. package/guidance/define-draft-shapes.md +89 -0
  5. package/guidance/define-intake.md +97 -0
  6. package/guidance/define-intent.md +107 -0
  7. package/guidance/discover-prototype.md +67 -0
  8. package/guidance/discovery-prototypes.md +69 -0
  9. package/guidance/harness-template.md +34 -0
  10. package/guidance/managed/agent-instructions-block.hash +1 -1
  11. package/guidance/managed/agent-instructions-block.md +34 -0
  12. package/guidance/manifest.json +9 -2
  13. package/package.json +1 -1
  14. package/rcf/adrs/adr-4124-define-freeze-verb.json +30 -0
  15. package/rcf/adrs/adr-4126-persona-tagged-blockers-two-levels.json +40 -0
  16. package/rcf/adrs/adr-4127-readiness-tab-order-and-register.json +40 -0
  17. package/rcf/adrs/adr-4129-questions-harness-driven-loop.json +25 -0
  18. package/rcf/adrs/adr-4130-intake-harness-split-tool-scanned.json +20 -0
  19. package/rcf/adrs/adr-4132-prototypes-in-discovery-as-evidence.json +20 -0
  20. package/rcf/adrs/adr-4133-dag-dependency-depth-layout.json +40 -0
  21. package/rcf/adrs/adr-4134-index-json-route.json +35 -0
  22. package/rcf/adrs/adr-4135-readiness-po-register-and-adapter.json +35 -0
  23. package/rcf/adrs/adr-4136-embedding-host-fixture.json +35 -0
  24. package/rcf/code-nodes/cn-725.json +18 -2
  25. package/rcf/code-nodes/cn-726.json +10 -2
  26. package/rcf/code-nodes/cn-727.json +13 -4
  27. package/rcf/code-nodes/cn-728.json +18 -2
  28. package/rcf/code-nodes/cn-729.json +10 -2
  29. package/rcf/code-nodes/cn-730.json +13 -3
  30. package/rcf/code-nodes/cn-731.json +20 -0
  31. package/rcf/code-nodes/cn-732.json +14 -0
  32. package/rcf/code-nodes/cn-733.json +14 -0
  33. package/rcf/code-nodes/cn-734.json +14 -0
  34. package/rcf/code-nodes/cn-735.json +20 -0
  35. package/rcf/code-nodes/cn-736.json +14 -0
  36. package/rcf/code-nodes/cn-737.json +14 -0
  37. package/rcf/code-nodes/cn-738.json +14 -0
  38. package/rcf/code-nodes/cn-739.json +18 -0
  39. package/rcf/code-nodes/cn-740.json +19 -0
  40. package/rcf/code-nodes/cn-741.json +16 -0
  41. package/rcf/code-nodes/cn-742.json +16 -0
  42. package/rcf/code-nodes/cn-743.json +15 -0
  43. package/rcf/code-nodes/cn-744.json +22 -0
  44. package/rcf/code-nodes/cn-745.json +16 -0
  45. package/rcf/code-nodes/cn-746.json +14 -0
  46. package/rcf/code-nodes/cn-747.json +18 -0
  47. package/rcf/code-nodes/cn-748.json +16 -0
  48. package/rcf/code-nodes/cn-749.json +16 -0
  49. package/rcf/code-nodes/cn-750.json +15 -0
  50. package/rcf/code-nodes/cn-751.json +18 -0
  51. package/rcf/code-nodes/cn-752.json +14 -0
  52. package/rcf/fbs/fbs-196.json +13 -5
  53. package/rcf/fbs/fbs-198.json +42 -0
  54. package/rcf/fbs/fbs-199.json +59 -0
  55. package/rcf/fbs/fbs-200.json +46 -0
  56. package/rcf/fbs/fbs-201.json +49 -0
  57. package/rcf/fbs/fbs-202.json +110 -0
  58. package/rcf/fbs/fbs-203.json +100 -0
  59. package/rcf/requirements/req-002.json +2 -2
  60. package/rcf/requirements/req-173.json +2 -2
  61. package/rcf/requirements/req-174.json +10 -4
  62. package/rcf/requirements/req-175.json +10 -4
  63. package/rcf/requirements/req-176.json +25 -0
  64. package/rcf/requirements/req-180.json +31 -0
  65. package/rcf/requirements/req-181.json +31 -0
  66. package/rcf/requirements/req-182.json +25 -0
  67. package/rcf/requirements/req-186.json +25 -0
  68. package/rcf/requirements/req-187.json +31 -0
  69. package/rcf/requirements/req-188.json +25 -0
  70. package/rcf/tacs/tac-4121-define-ledgers.json +15 -3
  71. package/rcf/tacs/tac-4122-define-gates.json +40 -4
  72. package/rcf/tacs/tac-4123-define-readiness.json +39 -3
  73. package/rcf/tacs/tac-4124-define-freeze.json +28 -0
  74. package/rcf/tacs/tac-4127-readiness-view.json +49 -0
  75. package/rcf/tacs/tac-4128-define-guidance.json +53 -0
  76. package/rcf/tacs/tac-4129-define-questions.json +45 -0
  77. package/rcf/tacs/tac-4130-define-intake-brief.json +35 -0
  78. package/rcf/tacs/tac-4131-build-dag-view.json +39 -0
  79. package/rcf/tacs/tac-4132-id-lookup.json +42 -0
  80. package/rcf/tacs/tac-4133-readiness-po-layer.json +37 -0
  81. package/rcf/tacs/tac-4134-wespa-host-fixture.json +54 -0
  82. package/rcf/test-suites/ts-016.json +3 -3
  83. package/rcf/test-suites/ts-215.json +148 -4
  84. package/rcf/test-suites/ts-216.json +19 -3
  85. package/rcf/test-suites/ts-218.json +78 -0
  86. package/rcf/test-suites/ts-219.json +70 -0
  87. package/rcf/test-suites/ts-220.json +78 -0
  88. package/rcf/test-suites/ts-221.json +78 -0
  89. package/rcf/test-suites/ts-222.json +100 -0
  90. package/rcf/test-suites/ts-223.json +94 -0
  91. package/rcf/test-suites/ts-224.json +70 -0
  92. package/rcf/test-suites/ts-225.json +78 -0
  93. package/rcf/test-suites/ts-226.json +158 -0
  94. package/rcf/test-suites/ts-227.json +38 -0
  95. package/rcf/test-suites/ts-228.json +86 -0
  96. package/rcf/test-suites/ts-229.json +83 -0
  97. package/rcf/user-stories/us-17302.json +50 -0
  98. package/rcf/user-stories/us-17401.json +14 -2
  99. package/rcf/user-stories/us-17402.json +55 -0
  100. package/rcf/user-stories/us-17403.json +60 -0
  101. package/rcf/user-stories/us-17502.json +60 -0
  102. package/rcf/user-stories/us-17503.json +65 -0
  103. package/rcf/user-stories/us-17601.json +58 -0
  104. package/rcf/user-stories/us-18001.json +55 -0
  105. package/rcf/user-stories/us-18002.json +35 -0
  106. package/rcf/user-stories/us-18101.json +35 -0
  107. package/rcf/user-stories/us-18202.json +40 -0
  108. package/rcf/user-stories/us-18601.json +55 -0
  109. package/rcf/user-stories/us-18602.json +50 -0
  110. package/rcf/user-stories/us-18603.json +45 -0
  111. package/rcf/user-stories/us-18701.json +50 -0
  112. package/rcf/user-stories/us-18702.json +50 -0
  113. package/rcf/user-stories/us-18801.json +45 -0
  114. package/rcf/user-stories/us-204.json +59 -0
  115. package/rcf/user-stories/us-205.json +64 -0
  116. package/rcf/user-stories/us-206.json +54 -0
  117. package/releases/releases.yaml +11 -1
  118. package/src/cli/freeze.js +730 -0
  119. package/src/cli/help.js +12 -0
  120. package/src/cli/ledger.js +228 -12
  121. package/src/cli/questions.js +288 -0
  122. package/src/cli/readiness.js +267 -49
  123. package/src/cli/view.js +29 -0
  124. package/src/define/freeze-record.js +30 -15
  125. package/src/define/ledgers.js +210 -11
  126. package/src/intake/index.js +1 -1
  127. package/src/intake/orchestrator.js +117 -0
  128. package/src/mcp/tools.js +354 -0
  129. package/src/query/delta.js +6 -0
  130. package/src/query/gates.js +314 -39
  131. package/src/query/index.js +16 -2
  132. package/src/query/questions.js +438 -0
  133. package/src/query/readiness.js +248 -7
  134. package/src/server/index.js +24 -2
  135. package/src/server/routes.js +68 -1
  136. package/src/setup/identity-seed.js +17 -0
  137. package/src/view/build-dag.js +563 -0
  138. package/src/view/components/badge.js +41 -0
  139. package/src/view/components/diff.js +72 -0
  140. package/src/view/components/doc-row.js +62 -0
  141. package/src/view/components/empty-state.js +35 -0
  142. package/src/view/components/entity-selector.js +137 -0
  143. package/src/view/components/filter-bar.js +97 -0
  144. package/src/view/components/findings-list.js +49 -0
  145. package/src/view/components/index.js +12 -0
  146. package/src/view/components/pill.js +46 -0
  147. package/src/view/components/sub-tab-strip.js +43 -0
  148. package/src/view/components/toast.js +25 -0
  149. package/src/view/components-fixture.js +265 -0
  150. package/src/view/doc-renderers/architecture.js +304 -0
  151. package/src/view/doc-renderers/build.js +160 -0
  152. package/src/view/doc-renderers/index.js +2 -0
  153. package/src/view/doc-renderers/prd.js +35 -6
  154. package/src/view/html-page.js +700 -602
  155. package/src/view/index.js +96 -3
  156. package/src/view/live-client.js +39 -6
  157. package/src/view/needs-work.js +79 -0
  158. package/src/view/page-init.js +2193 -0
  159. package/src/view/readiness/phrasebook.js +115 -0
  160. package/src/view/readiness/po-layer.js +288 -0
  161. package/src/view/readiness/question-adapter.js +329 -0
  162. package/src/view/readiness/stage-legend.js +71 -0
  163. package/src/view/readiness.js +505 -0
  164. package/src/view/style.css +2017 -382
  165. package/src/view/test-host/embed-client.js +121 -0
  166. package/src/view/test-host/fixture.js +183 -0
  167. package/src/view/test-host/lints.js +220 -0
  168. package/src/view/view-index.js +323 -0
@@ -0,0 +1,40 @@
1
+ {
2
+ "usId": "US-18202",
3
+ "prdId": "PRD-001",
4
+ "reqId": "REQ-182",
5
+ "version": "0.1.0",
6
+ "status": "draft",
7
+ "title": "the DEFINE-stage guidance pack",
8
+ "description": "User story under REQ-182. The guidance pack prints its slugs through `rcf guidance`, the MCP server advertises every argument-free DEFINE prompt, the register scan protects every new file from em-dashes, and the managed block regeneration never removes an existing rule.",
9
+ "asA": "harness",
10
+ "iWant": "the DEFINE-stage guidance pack served through one surface",
11
+ "soThat": "the loop reads one slug per topic and the register scans and managed-block rules apply everywhere",
12
+ "acceptanceCriteria": [
13
+ {
14
+ "id": "AC-18202-1",
15
+ "description": "[happy] given the pack, when rcf guidance define-intent and rcf guidance discovery-prototypes run, then each prints its file.",
16
+ "testable": true
17
+ },
18
+ {
19
+ "id": "AC-18202-2",
20
+ "description": "[happy] given the manifest, when the MCP server lists prompts, then rcf_define_intent, rcf_define_intake, rcf_define_draft_shapes, rcf_define_litmus and rcf_discover_prototype are present and argument-free.",
21
+ "testable": true
22
+ },
23
+ {
24
+ "id": "AC-18202-3",
25
+ "description": "[failure] given a new guidance file containing an em-dash, when the register scan runs, then it fails.",
26
+ "testable": true
27
+ },
28
+ {
29
+ "id": "AC-18202-4",
30
+ "description": "[must-not] given the managed block, when regenerated, then no existing rule is removed.",
31
+ "testable": true
32
+ }
33
+ ],
34
+ "tacIds": [
35
+ "TAC-4128-define-guidance"
36
+ ],
37
+ "tags": [],
38
+ "createdAt": "2026-10-03T00:00:00Z",
39
+ "updatedAt": "2026-10-03T00:00:00Z"
40
+ }
@@ -0,0 +1,55 @@
1
+ {
2
+ "usId": "US-18601",
3
+ "prdId": "PRD-001",
4
+ "reqId": "REQ-186",
5
+ "version": "0.1.0",
6
+ "status": "draft",
7
+ "title": "the question set",
8
+ "description": "User story under REQ-186. computeQuestions turns every failing product-owner item into one plain question with its write-back, so the harness can ask without reading gate internals.",
9
+ "asA": "harness serving a product owner",
10
+ "iWant": "computeQuestions to turn every failing product-owner item into one plain question with its write-back",
11
+ "soThat": "I can ask without reading gate internals",
12
+ "acceptanceCriteria": [
13
+ {
14
+ "id": "AC-18601-1",
15
+ "description": "[happy] given a tree where brief:openQuestions, skeleton:resolvedBy and stories:reqHasUs each fail at least one item, when computeQuestions runs with persona productOwner, then questions[] holds exactly one entry per failing item with id, stage, check, itemId, heading, ask, answerKinds, writeBack and blocks intent.",
16
+ "testable": true
17
+ },
18
+ {
19
+ "id": "AC-18601-2",
20
+ "description": "[happy] given the same tree, when computeQuestions runs twice, then the two questions[] arrays are deep-equal and ordered D1, D2, D4, D7 then by source span.",
21
+ "testable": true
22
+ },
23
+ {
24
+ "id": "AC-18601-3",
25
+ "description": "[happy] given an open decision with two options and a default, when computeQuestions runs, then it appears in optional[] with blocks build and not in questions[].",
26
+ "testable": true
27
+ },
28
+ {
29
+ "id": "AC-18601-4",
30
+ "description": "[happy] given a tree where levels.intentComplete.ok is true, when computeQuestions runs with persona productOwner, then questions[] is empty and ok is true.",
31
+ "testable": true
32
+ },
33
+ {
34
+ "id": "AC-18601-5",
35
+ "description": "[happy] given persona engineer, when computeQuestions runs, then questions[] holds one entry per failing engineer item in failing stages and blocks is build.",
36
+ "testable": true
37
+ },
38
+ {
39
+ "id": "AC-18601-6",
40
+ "description": "[failure] given a persona value outside productOwner and engineer, when computeQuestions runs, then it throws a usage error naming the accepted values.",
41
+ "testable": true
42
+ },
43
+ {
44
+ "id": "AC-18601-7",
45
+ "description": "[must-not] given any tree, when computeQuestions runs, then no file under rcf/ is created or modified and no question carries a writeBack command whose verb is not registered in the CLI help.",
46
+ "testable": true
47
+ }
48
+ ],
49
+ "tacIds": [
50
+ "TAC-4129-define-questions"
51
+ ],
52
+ "tags": [],
53
+ "createdAt": "2026-10-02T18:00:00Z",
54
+ "updatedAt": "2026-10-02T18:00:00Z"
55
+ }
@@ -0,0 +1,50 @@
1
+ {
2
+ "usId": "US-18602",
3
+ "prdId": "PRD-001",
4
+ "reqId": "REQ-186",
5
+ "version": "0.1.0",
6
+ "status": "draft",
7
+ "title": "the verb and the tools",
8
+ "description": "User story under REQ-186. `rcf define questions` and `rcf_define_questions` return the same object, so the CLI loop and the MCP loop cannot disagree.",
9
+ "asA": "operator or harness",
10
+ "iWant": "the verb and the MCP tool to return the same object",
11
+ "soThat": "the two loops cannot disagree",
12
+ "acceptanceCriteria": [
13
+ {
14
+ "id": "AC-18602-1",
15
+ "description": "[happy] given a failing tree, when rcf define questions --json runs, then stdout is the computeQuestions object and the exit code is 0.",
16
+ "testable": true
17
+ },
18
+ {
19
+ "id": "AC-18602-2",
20
+ "description": "[happy] given no --persona, when the verb runs on a profile whose register is engineer, then persona is engineer; with no profile it is productOwner.",
21
+ "testable": true
22
+ },
23
+ {
24
+ "id": "AC-18602-3",
25
+ "description": "[happy] given --stage skeleton and --limit 2, when the verb runs, then questions[] holds at most two D2 entries and remaining counts every D2 item.",
26
+ "testable": true
27
+ },
28
+ {
29
+ "id": "AC-18602-4",
30
+ "description": "[happy] given the MCP tool rcf_define_questions with the same arguments, when it is called, then structuredContent deep-equals the verb's --json output.",
31
+ "testable": true
32
+ },
33
+ {
34
+ "id": "AC-18602-5",
35
+ "description": "[failure] given --persona architect, when the verb runs, then it exits 2 with the usage line naming productOwner and engineer.",
36
+ "testable": true
37
+ },
38
+ {
39
+ "id": "AC-18602-6",
40
+ "description": "[must-not] given any invocation of rcf define questions, when it completes, then no file under rcf/ has been created or modified.",
41
+ "testable": true
42
+ }
43
+ ],
44
+ "tacIds": [
45
+ "TAC-4129-define-questions"
46
+ ],
47
+ "tags": [],
48
+ "createdAt": "2026-10-02T18:00:00Z",
49
+ "updatedAt": "2026-10-02T18:00:00Z"
50
+ }
@@ -0,0 +1,45 @@
1
+ {
2
+ "usId": "US-18603",
3
+ "prdId": "PRD-001",
4
+ "reqId": "REQ-186",
5
+ "version": "0.1.0",
6
+ "status": "draft",
7
+ "title": "write-back and termination",
8
+ "description": "User story under REQ-186. Every answer lands through a verb and the loop ends at the computed verdict, so nothing about intent lives only in a chat.",
9
+ "asA": "product owner",
10
+ "iWant": "every answer to land through a verb and the loop to end at the computed verdict",
11
+ "soThat": "nothing about my intent lives only in a chat",
12
+ "acceptanceCriteria": [
13
+ {
14
+ "id": "AC-18603-1",
15
+ "description": "[happy] given the scripted loop fixture, when every writeBack the question set returns is applied and readiness recomputed each turn, then the question count strictly decreases every turn and reaches zero.",
16
+ "testable": true
17
+ },
18
+ {
19
+ "id": "AC-18603-2",
20
+ "description": "[happy] given a statement resolved to a newly created REQ carrying description and domain, when readiness recomputes, then skeleton:reqIntent passes that REQ and stories:reqHasUs asks for it once.",
21
+ "testable": true
22
+ },
23
+ {
24
+ "id": "AC-18603-3",
25
+ "description": "[happy] given a tree at L1, when [draft] entities, TAC stubs and interfaces are added, then levels.intentComplete.ok stays true and the product-owner question set stays empty.",
26
+ "testable": true
27
+ },
28
+ {
29
+ "id": "AC-18603-4",
30
+ "description": "[failure] given an openQuestion promoted to a decision with one option and no default, when readiness recomputes, then decisions:wellFormed asks once and brief:openQuestions does not.",
31
+ "testable": true
32
+ },
33
+ {
34
+ "id": "AC-18603-5",
35
+ "description": "[must-not] given any product-owner check, when readiness recomputes after an engineer-only edit, then no product-owner check changes from ok to failing.",
36
+ "testable": true
37
+ }
38
+ ],
39
+ "tacIds": [
40
+ "TAC-4129-define-questions"
41
+ ],
42
+ "tags": [],
43
+ "createdAt": "2026-10-02T18:00:00Z",
44
+ "updatedAt": "2026-10-02T18:00:00Z"
45
+ }
@@ -0,0 +1,50 @@
1
+ {
2
+ "usId": "US-18701",
3
+ "prdId": "PRD-001",
4
+ "reqId": "REQ-187",
5
+ "version": "0.1.0",
6
+ "status": "draft",
7
+ "title": "the statement file",
8
+ "description": "User story under REQ-187. The harness writes a statement file beside each source with a leading bracketed kind and a trailing (source: ...) marker; `brief add --from` parses the markers and mints the statements.",
9
+ "asA": "harness",
10
+ "iWant": "a line grammar for kind and source",
11
+ "soThat": "the split I propose to the owner is what gets minted",
12
+ "acceptanceCriteria": [
13
+ {
14
+ "id": "AC-18701-1",
15
+ "description": "[happy] given a line \"- [constraint] A loan on hold must not accrue late fees. (source: briefs/x.md:15)\", when brief add --from runs, then one statement is minted with kind constraint, that text and that source.",
16
+ "testable": true
17
+ },
18
+ {
19
+ "id": "AC-18701-2",
20
+ "description": "[happy] given a line with no markers under --kind actor --source doc.md, when brief add --from runs, then the statement has kind actor and source doc.md.",
21
+ "testable": true
22
+ },
23
+ {
24
+ "id": "AC-18701-3",
25
+ "description": "[happy] given a line ending with \"?\" and no kind marker, when brief add --from runs, then the statement has kind openQuestion.",
26
+ "testable": true
27
+ },
28
+ {
29
+ "id": "AC-18701-4",
30
+ "description": "[happy] given a 0.29.0 line-per-statement file, when brief add --from runs, then the minted statements equal the 0.29.0 output.",
31
+ "testable": true
32
+ },
33
+ {
34
+ "id": "AC-18701-5",
35
+ "description": "[failure] given a line \"[gadget] text\", when brief add --from runs, then it exits 2 naming the accepted kinds and writes nothing.",
36
+ "testable": true
37
+ },
38
+ {
39
+ "id": "AC-18701-6",
40
+ "description": "[must-not] given --dry-run, when brief add --from runs, then rcf/define/brief-ledger.json is not created or modified.",
41
+ "testable": true
42
+ }
43
+ ],
44
+ "tacIds": [
45
+ "TAC-4130-define-intake-brief"
46
+ ],
47
+ "tags": [],
48
+ "createdAt": "2026-10-02T16:40:00Z",
49
+ "updatedAt": "2026-10-02T16:40:00Z"
50
+ }
@@ -0,0 +1,50 @@
1
+ {
2
+ "usId": "US-18702",
3
+ "prdId": "PRD-001",
4
+ "reqId": "REQ-187",
5
+ "version": "0.1.0",
6
+ "status": "draft",
7
+ "title": "scans into open questions",
8
+ "description": "User story under REQ-187. The intake scans run inside `brief add --from` over the new statements against every existing statement, and every finding becomes an openQuestion statement with source `scan:<name>:<ids>`.",
9
+ "asA": "product owner",
10
+ "iWant": "contradictions and gaps the tool can see to reach me as questions",
11
+ "soThat": "the first readiness run tells me what is still mine",
12
+ "acceptanceCriteria": [
13
+ {
14
+ "id": "AC-18702-1",
15
+ "description": "[happy] given two new statements the contradiction scan flags, when brief add --from runs with scans on, then one openQuestion statement is appended with source scan:contradiction:<id>,<id> and brief:openQuestions fails it.",
16
+ "testable": true
17
+ },
18
+ {
19
+ "id": "AC-18702-2",
20
+ "description": "[happy] given a --findings file with two findings, when brief add --from runs, then two openQuestion statements are appended with source scan:<name>.",
21
+ "testable": true
22
+ },
23
+ {
24
+ "id": "AC-18702-3",
25
+ "description": "[happy] given a frozen tree, when brief add --from runs, then the scans compare the new statements against every existing statement.",
26
+ "testable": true
27
+ },
28
+ {
29
+ "id": "AC-18702-4",
30
+ "description": "[happy] given --json, when brief add --from runs, then stdout holds added[] and findings[].",
31
+ "testable": true
32
+ },
33
+ {
34
+ "id": "AC-18702-5",
35
+ "description": "[failure] given --no-scan together with --findings, when brief add runs, then it exits 2.",
36
+ "testable": true
37
+ },
38
+ {
39
+ "id": "AC-18702-6",
40
+ "description": "[must-not] given --text, when brief add runs, then no scan runs and no openQuestion statement is appended.",
41
+ "testable": true
42
+ }
43
+ ],
44
+ "tacIds": [
45
+ "TAC-4130-define-intake-brief"
46
+ ],
47
+ "tags": [],
48
+ "createdAt": "2026-10-02T16:40:00Z",
49
+ "updatedAt": "2026-10-02T16:40:00Z"
50
+ }
@@ -0,0 +1,45 @@
1
+ {
2
+ "usId": "US-18801",
3
+ "prdId": "PRD-001",
4
+ "reqId": "REQ-188",
5
+ "version": "0.1.0",
6
+ "status": "draft",
7
+ "title": "the draft homes",
8
+ "description": "User story under REQ-188. Every pre-populated shape across the three draft homes (`TAC.purpose`, `coreEntities[].description`, `TAC.interfaces[].description`) carries the `[draft]` marker; `shapes:draftSettled` reports all three id forms so nothing drafted reads as settled.",
9
+ "asA": "engineer picking up an intent-complete tree",
10
+ "iWant": "every pre-populated shape marked",
11
+ "soThat": "nothing drafted reads as settled",
12
+ "acceptanceCriteria": [
13
+ {
14
+ "id": "AC-18801-1",
15
+ "description": "[happy] given a coreEntities entry whose description starts with [draft], when D3 runs, then shapes:draftSettled fails TAD.entity:<name>.",
16
+ "testable": true
17
+ },
18
+ {
19
+ "id": "AC-18801-2",
20
+ "description": "[happy] given a TAC whose purpose starts with [draft], when D3 runs, then shapes:draftSettled fails <tacId> and shapes:tacHasInterface treats the TAC as present.",
21
+ "testable": true
22
+ },
23
+ {
24
+ "id": "AC-18801-3",
25
+ "description": "[happy] given the three marker homes cleared, when D3 runs, then shapes:draftSettled passes.",
26
+ "testable": true
27
+ },
28
+ {
29
+ "id": "AC-18801-4",
30
+ "description": "[failure] given a [draft] recordShape without fields:, when D3 runs, then shapes:templateMarkers fails it exactly as a settled one.",
31
+ "testable": true
32
+ },
33
+ {
34
+ "id": "AC-18801-5",
35
+ "description": "[must-not] given any [draft] content, when readiness runs, then no productOwner check reads it.",
36
+ "testable": true
37
+ }
38
+ ],
39
+ "tacIds": [
40
+ "TAC-4122-define-gates"
41
+ ],
42
+ "tags": [],
43
+ "createdAt": "2026-10-03T00:00:00Z",
44
+ "updatedAt": "2026-10-03T00:00:00Z"
45
+ }
@@ -0,0 +1,59 @@
1
+ {
2
+ "usId": "US-204",
3
+ "prdId": "PRD-001",
4
+ "reqId": "REQ-002",
5
+ "version": "0.1.0",
6
+ "status": "draft",
7
+ "title": "An engineer sees the FBS DAG",
8
+ "description": "The Build tab's DAG sub-tab lays FBS out by dependency depth from `dependsOnFbsIds` with click-to-highlight closure, a dependency inspector, status/area/Buildable-now/Critical-path/Show-unconnected filters, a hidden unconnected lane with a count, and `#tab=build&sub=dag&entity=<id>` deep links so a node is a link. The canvas scrolls inside its own box and the viewer never scrolls horizontally. See viewer UI refresh design doc section 7.",
9
+ "asA": "an engineer looking at the build sequence",
10
+ "iWant": "a dependency DAG of the FBS with click-to-highlight closure, an inspector and filters",
11
+ "soThat": "I can see what feeds what, pick the next buildable work and spot the critical path without reading JSON",
12
+ "acceptanceCriteria": [
13
+ {
14
+ "id": "AC-204-1",
15
+ "description": "[happy] Given the Build tab's DAG sub-tab, when it renders, then every connected FBS sits in a column whose index equals its longest dependency depth from `dependsOnFbsIds` (0 for no dependency) and rows inside a column are ordered by `buildOrder` ascending.",
16
+ "testable": true
17
+ },
18
+ {
19
+ "id": "AC-204-2",
20
+ "description": "[happy] Given the DAG canvas, when a node is clicked, then it is selected, its upstream closure outlines in the link colour and its downstream closure outlines in the warning colour; a second click on the same node clears the selection.",
21
+ "testable": true
22
+ },
23
+ {
24
+ "id": "AC-204-3",
25
+ "description": "[happy] Given a selected FBS, when the inspector renders, then it lists status, area, AC count, size, build order, a buildable-now flag, direct and transitive needs, direct and transitive waits-on and an \"Open in Specs\" link that moves to `#tab=build&sub=specs&entity=<id>`.",
26
+ "testable": true
27
+ },
28
+ {
29
+ "id": "AC-204-4",
30
+ "description": "[happy] Given a selection, when it is set or cleared, then the hash becomes `#tab=build&sub=dag&entity=<id>` (or drops the entity key when cleared) and a reload with that hash restores the selection and scrolls the node into view.",
31
+ "testable": true
32
+ },
33
+ {
34
+ "id": "AC-204-5",
35
+ "description": "[happy] Given the DAG toolbar, when the Status, Area, Buildable-now, Critical-path or Show-unconnected filter changes, then the visible nodes update and the current selection is kept.",
36
+ "testable": true
37
+ },
38
+ {
39
+ "id": "AC-204-6",
40
+ "description": "[failure] Given a `dependsOnFbsIds` cycle on disk, when the DAG renders, then the cycle is reported as a finding in the toolbar area and the remaining non-cycle FBS still render.",
41
+ "testable": true
42
+ },
43
+ {
44
+ "id": "AC-204-7",
45
+ "description": "[must-not] Given the DAG canvas, when a node is clicked, filtered or inspected, then no `postMessage` is sent to the parent window and no outbound network request is made.",
46
+ "testable": true
47
+ }
48
+ ],
49
+ "tacIds": [
50
+ "TAC-4131-build-dag-view"
51
+ ],
52
+ "tags": [
53
+ "view",
54
+ "build",
55
+ "dag"
56
+ ],
57
+ "createdAt": "2026-10-02T18:00:00Z",
58
+ "updatedAt": "2026-10-02T18:00:00Z"
59
+ }
@@ -0,0 +1,64 @@
1
+ {
2
+ "usId": "US-205",
3
+ "prdId": "PRD-001",
4
+ "reqId": "REQ-002",
5
+ "version": "0.1.0",
6
+ "status": "draft",
7
+ "title": "An engineer jumps to any document or AC by id",
8
+ "description": "A SearchButton to the right of the tabstrip and the Cmd/Ctrl+F keyboard binding open a LookupModal with type-ahead over a server-built `./index.json` carrying every document id and every AC. Id matches rank first (exact, prefix, contains), then every query word must match title or snippet, title above snippet; a single character searches ids only; 20 results. A pick sets `#tab=<tab>&entity=<id>`; the Router activates the tab, opens every ancestor DocRow and flashes the target. `embed` and `theme` survive every hash write. See viewer UI refresh design doc section 6.",
9
+ "asA": "an engineer looking at any tab of the review surface",
10
+ "iWant": "a modal that lets me jump to any document or AC by typing part of its id or title",
11
+ "soThat": "I can navigate the tree by id without hunting through the tabs",
12
+ "acceptanceCriteria": [
13
+ {
14
+ "id": "AC-205-1",
15
+ "description": "[happy] Given the review surface, when the SearchButton is pressed or Cmd/Ctrl+F is typed from any tab, then the LookupModal opens; typing an exact id (`REQ-002`) or a prefix (`REQ-00`) ranks that id first and the first result row is pre-highlighted.",
16
+ "testable": true
17
+ },
18
+ {
19
+ "id": "AC-205-2",
20
+ "description": "[happy] Given the LookupModal, when a word query matches a document's title and another document's snippet, then the title match ranks above the snippet match.",
21
+ "testable": true
22
+ },
23
+ {
24
+ "id": "AC-205-3",
25
+ "description": "[happy] Given the LookupModal, when a query of exactly one character is typed, then only ids whose identifier contains that character rank, and the title / snippet word-match pass is skipped.",
26
+ "testable": true
27
+ },
28
+ {
29
+ "id": "AC-205-4",
30
+ "description": "[happy] Given a pre-highlighted result for `US-304`, when Enter is pressed, then the hash becomes `#tab=requirements&entity=US-304`, the Router activates the Requirements tab, opens the REQ-003 ancestor DocRow and the US-304 row, scrolls the target into view and flashes it.",
31
+ "testable": true
32
+ },
33
+ {
34
+ "id": "AC-205-5",
35
+ "description": "[happy] Given a mount URL `?tab=requirements&entity=US-304`, when the shell first paints, then the Router lands on the same position: Requirements tab active, REQ-003 and US-304 DocRows open, US-304 scrolled into view.",
36
+ "testable": true
37
+ },
38
+ {
39
+ "id": "AC-205-6",
40
+ "description": "[happy] Given `?embed=1&theme=dark` on the viewer URL, when a result is picked from the LookupModal, then the resulting URL still carries `embed=1` and `theme=dark` in the query string and the hash is `#tab=<tab>&entity=<id>`.",
41
+ "testable": true
42
+ },
43
+ {
44
+ "id": "AC-205-7",
45
+ "description": "[failure] Given a `./index.json` fetch that returns a non-2xx status or a malformed body, when the LookupModal is opened, then an empty state renders with a reload affordance that re-fetches the index, and no result rows show.",
46
+ "testable": true
47
+ },
48
+ {
49
+ "id": "AC-205-8",
50
+ "description": "[must-not] Given the LookupModal, when the user types a query, picks a result or closes the modal, then no `postMessage` is sent to the parent window, no outbound network request beyond the `./index.json` fetch is made, and no search term is written to `localStorage` / `sessionStorage` / cookies.",
51
+ "testable": true
52
+ }
53
+ ],
54
+ "tacIds": [
55
+ "TAC-4132-id-lookup"
56
+ ],
57
+ "tags": [
58
+ "view",
59
+ "lookup",
60
+ "navigation"
61
+ ],
62
+ "createdAt": "2026-10-02T19:00:00Z",
63
+ "updatedAt": "2026-10-02T19:00:00Z"
64
+ }
@@ -0,0 +1,54 @@
1
+ {
2
+ "usId": "US-206",
3
+ "prdId": "PRD-001",
4
+ "reqId": "REQ-002",
5
+ "version": "0.1.0",
6
+ "status": "draft",
7
+ "title": "wespa's embedding contract is proved by a CI host fixture",
8
+ "description": "A same-origin test-host fixture served by the viewer's dev server (route `/test-host.html` behind a `--test-host` flag or an env guard; off by default so wespa's proxy allow-list is unaffected) mimics the wespa shell: a 56px header, a resizable sidebar (64px collapsed, 200-400px expanded, user-resizable live via a drag handle), a content pane carrying an `<iframe src=\"./?embed=1&theme=light\">`. The host posts `{ type: \"rcf-view-theme\", theme: \"light\"|\"dark\" }` on a toggle control; it stores no theme itself so a passing run proves the iframe reads the message. The viewer sends no outbound postMessage. Three lints run in the test suite: (1) framing lint (`GET /` returns no `X-Frame-Options`, no CSP `frame-ancestors` that forbids same-origin, and the fixture loads the iframe without a browser error); (2) target lint (no `target=\"_top\"` string in the server-rendered HTML); (3) localStorage namespace lint (every `localStorage.{setItem,getItem,removeItem}` and shared `storage.*` call site in `src/view/**` uses a key starting with `rcf-view:v1:`). See viewer UI refresh design doc section 9 and Dex's wespa requirements of 2026-10-02.",
9
+ "asA": "Dex integrating the rcf-lite viewer behind wespa's reverse proxy",
10
+ "iWant": "a CI host fixture that proves the viewer honours the embedding contract and three lints that keep framing, target='_top' and localStorage namespace in place over time",
11
+ "soThat": "regressions in the embedding contract are caught in the viewer's own suite before they reach wespa",
12
+ "acceptanceCriteria": [
13
+ {
14
+ "id": "AC-206-1",
15
+ "description": "[happy] Given the test-host fixture at `/test-host.html`, when the page loads with the viewer served from the same origin, then the iframe `src` is `./?embed=1&theme=light`, the title block and footer of the iframed viewer are hidden (`<html data-embed=\"1\">`), the tab nav is visible and the host's 56px header plus the resizable sidebar render around it.",
16
+ "testable": true
17
+ },
18
+ {
19
+ "id": "AC-206-2",
20
+ "description": "[happy] Given the test-host fixture with the iframe loaded, when the host's theme toggle posts `{ type: \"rcf-view-theme\", theme: \"dark\" }` to the iframe's `contentWindow`, then the iframe's `<html data-theme>` flips to `dark` without a reload and the content repaints in the dark token set.",
21
+ "testable": true
22
+ },
23
+ {
24
+ "id": "AC-206-3",
25
+ "description": "[happy] Given the test-host fixture with the iframe loaded at `./?embed=1&theme=dark`, when a hash-only navigation inside the iframe writes `#tab=requirements&entity=REQ-002`, then the iframe's query still carries `embed=1` and `theme=dark` and the viewer's inner `<html data-embed=\"1\" data-theme=\"dark\">` is preserved.",
26
+ "testable": true
27
+ },
28
+ {
29
+ "id": "AC-206-4",
30
+ "description": "[failure] Given the viewer page listening for `rcf-view-theme` postMessages, when a message with `event.origin` different from `window.location.origin` is delivered, then the message is ignored and `<html data-theme>` is not changed.",
31
+ "testable": true
32
+ },
33
+ {
34
+ "id": "AC-206-5",
35
+ "description": "[must-not] Given the viewer's `GET /` response, when the three lints run in the test suite, then (a) no `X-Frame-Options` header is set and no CSP `frame-ancestors` directive forbids same-origin framing, (b) `target=\"_top\"` appears zero times in the rendered HTML across every tab, (c) every `localStorage.{setItem,getItem,removeItem}` and shared `storage.*` call site under `src/view/**` uses a key starting with `rcf-view:v1:`.",
36
+ "testable": true
37
+ },
38
+ {
39
+ "id": "AC-206-6",
40
+ "description": "[must-not] Given the test-host fixture and the viewer page, when either is loaded, then neither posts any outbound message beyond the host's `rcf-view-theme`; the viewer sends no `postMessage` of any shape, and the test-host adds no new postMessage shape.",
41
+ "testable": true
42
+ }
43
+ ],
44
+ "tacIds": [
45
+ "TAC-4134-wespa-host-fixture"
46
+ ],
47
+ "tags": [
48
+ "view",
49
+ "embedding",
50
+ "lint"
51
+ ],
52
+ "createdAt": "2026-10-02T20:00:00Z",
53
+ "updatedAt": "2026-10-02T20:00:00Z"
54
+ }
@@ -40,8 +40,18 @@
40
40
  # `npm install rcf-lite`.
41
41
 
42
42
  feedVersion: 1
43
- latest: "0.28.4"
43
+ latest: "0.29.0"
44
44
  releases:
45
+ - version: "0.29.0"
46
+ date: "2026-10-03"
47
+ breaking: true
48
+ headlines:
49
+ - "rcf-lite 0.29.0 lands the viewer UI refresh train in one release: a rebuilt shell with the Stravica brand tokens, light and dark theme and an embed contract; shared components across Requirements, Architecture, Build and Readiness; a Build DAG sub-tab with click-to-highlight closure, dependency inspector and an unconnected lane; fast ID lookup over a new ./index.json served from the viewer root (Cmd/Ctrl+F from any tab); the Readiness tab Product Owner redesign; and a same-origin test-host fixture that pins the embedding contract with three in-suite guards. For wespa embedders, the reverse-proxy allow-list for /rcf-viewer/* MUST add /page-init.js and /index.json before the version pin bump; /test-host.html and /test-host.js stay 404 by default so the allow-list is unchanged by the embedding-proof fixture."
50
+ - "The DEFINE readiness persona split arrives too: every gate check carries a persona (product owner or engineer), two readiness levels (intent-complete, ready-to-build), the Readiness tab moves to tab one, and rcf define readiness gains --level and --persona flags with a persona-grouped text report."
51
+ - "The first three DEFINE step 3 PRs ship: document intake into the brief ledger via a statement file parser and the mechanical intake scans; a new rcf define ledger <name> update <id> subverb with a closed resolvedBy pointer grammar (REQ-nnn, TAD.entity:<name>, PRD.user:<name>, TAD.system:<name>, TAC-nnnn, omitted:<reason>) and the D2 skeleton:resolvedBy title-hit fallback dropped; a rcf define questions verb with three new MCP tools and two argument-free prompts for the harness-driven loop; and the [draft] shapes gate across TAC purpose, interface and core-entity homes with a DISCOVERY prototypes doctrine."
52
+ minAgentAction: rerun-init
53
+ notesUrl: "https://stravica.ai/docs/rcf/changelog/"
54
+
45
55
  - version: "0.28.4"
46
56
  date: "2026-09-30"
47
57
  breaking: false