rcf-lite 0.32.4 → 0.33.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +42 -0
- package/fixtures/canary-manifest.json +9 -9
- package/guidance/discovery/README.md +22 -0
- package/guidance/discovery/discovery-viewer-command-page-1-layout.html +191 -0
- package/guidance/discovery/discovery-viewer-command-page-2-coverage.html +193 -0
- package/guidance/discovery/discovery-viewer-command-page-3-trace-matrix.html +195 -0
- package/guidance/discovery/discovery-viewer-command-page-4-tables.html +196 -0
- package/guidance/discovery/discovery-viewer-command-page-5-subtabs.html +224 -0
- package/guidance/discovery/discovery-viewer-command-page-6-one-page.html +280 -0
- package/guidance/discovery/discovery-viewer-command-page.md +301 -0
- package/package.json +1 -1
- package/rcf/adrs/adr-4139-readiness-tables-read-only-no-commands.json +30 -0
- package/rcf/adrs/adr-4140-view-query-routes-per-pivot-matrix-no-mermaid.json +30 -0
- package/rcf/adrs/adr-4141-verify-modes.json +25 -0
- package/rcf/code-nodes/cn-771.json +3 -2
- package/rcf/code-nodes/cn-779.json +19 -0
- package/rcf/code-nodes/cn-780.json +14 -0
- package/rcf/code-nodes/cn-781.json +14 -0
- package/rcf/code-nodes/cn-782.json +15 -0
- package/rcf/code-nodes/cn-783.json +17 -0
- package/rcf/code-nodes/cn-784.json +20 -0
- package/rcf/code-nodes/cn-785.json +14 -0
- package/rcf/code-nodes/cn-786.json +14 -0
- package/rcf/code-nodes/cn-787.json +18 -0
- package/rcf/code-nodes/cn-788.json +14 -0
- package/rcf/code-nodes/cn-789.json +14 -0
- package/rcf/code-nodes/cn-790.json +15 -0
- package/rcf/code-nodes/cn-791.json +14 -0
- package/rcf/code-nodes/cn-792.json +17 -0
- package/rcf/code-nodes/cn-793.json +17 -0
- package/rcf/code-nodes/cn-794.json +18 -0
- package/rcf/code-nodes/cn-795.json +15 -0
- package/rcf/code-nodes/cn-796.json +14 -0
- package/rcf/code-nodes/cn-797.json +14 -0
- package/rcf/code-nodes/cn-798.json +14 -0
- package/rcf/define/brief-ledger.json +47 -0
- package/rcf/define/decisions-ledger.json +113 -0
- package/rcf/fbs/fbs-204.json +46 -0
- package/rcf/fbs/fbs-205.json +46 -0
- package/rcf/fbs/fbs-206.json +49 -0
- package/rcf/fbs/fbs-207.json +43 -0
- package/rcf/fbs/fbs-208.json +47 -0
- package/rcf/fbs/fbs-209.json +22 -0
- package/rcf/requirements/req-002.json +5 -2
- package/rcf/requirements/req-180.json +6 -3
- package/rcf/tacs/tac-4127-readiness-view.json +2 -2
- package/rcf/tacs/tac-4133-readiness-po-layer.json +2 -2
- package/rcf/tacs/tac-4135-readiness-command-page.json +94 -0
- package/rcf/tacs/tac-4136-view-query-routes.json +68 -0
- package/rcf/tacs/tac-4141-verify-modes.json +25 -0
- package/rcf/test-suites/ts-223.json +7 -7
- package/rcf/test-suites/ts-237.json +78 -0
- package/rcf/test-suites/ts-238.json +70 -0
- package/rcf/test-suites/ts-239.json +78 -0
- package/rcf/test-suites/ts-240.json +70 -0
- package/rcf/test-suites/ts-241.json +70 -0
- package/rcf/test-suites/ts-242.json +46 -0
- package/rcf/user-stories/us-16503.json +51 -0
- package/rcf/user-stories/us-18001.json +4 -4
- package/rcf/user-stories/us-18003.json +79 -0
- package/rcf/user-stories/us-18004.json +70 -0
- package/rcf/user-stories/us-18005.json +79 -0
- package/rcf/user-stories/us-208.json +74 -0
- package/rcf/user-stories/us-209.json +70 -0
- package/releases/releases.yaml +18 -1
- package/src/cli/finalise.js +141 -2
- package/src/cli/view.js +13 -1
- package/src/define/ledgers.js +9 -1
- package/src/finalise/spawn.js +2 -0
- package/src/server/index.js +104 -39
- package/src/server/routes.js +169 -0
- package/src/verify/cli/run.js +40 -0
- package/src/verify/engine/deterministic.js +150 -0
- package/src/verify/engine/index.js +27 -4
- package/src/view/doc-renderers/req.js +11 -9
- package/src/view/html-page.js +15 -11
- package/src/view/index.js +7 -1
- package/src/view/live-client.js +4 -0
- package/src/view/page-init.js +842 -1
- package/src/view/readiness/composite-id.js +35 -0
- package/src/view/readiness/coverage-summary.js +293 -0
- package/src/view/readiness/delta-counts.js +156 -0
- package/src/view/readiness/grid.js +175 -0
- package/src/view/readiness/po-layer.js +110 -220
- package/src/view/readiness/tables.js +500 -0
- package/src/view/readiness/thin-reqs.js +237 -0
- package/src/view/readiness/trace-matrix.js +392 -0
- package/src/view/readiness.js +359 -370
- package/src/view/style.css +594 -0
- package/src/watch/index.js +75 -17
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"reqId": "REQ-002",
|
|
3
3
|
"prdId": "PRD-001",
|
|
4
4
|
"title": "Visual review surface",
|
|
5
|
-
"description": "Build Lite renders the whole RCF tree as a diagram and as a browsable static page, so a non-coding owner can see the documents and their links without reading any JSON. The view is read-only and generated from the on-disk tree on demand. Build/DAG sub-tab lays FBS by `dependsOnFbsIds` depth with click-to-highlight closure, dependency inspector, filters, unconnected lane and `#tab=build&sub=dag&entity=` deep links, per viewer UI refresh design section 7. ID lookup over a server-built `./index.json` of every document id and AC, opened by the SearchButton or Cmd/Ctrl+F, navigates to `#tab=<tab>&entity=<id>` preserving `embed` and `theme`, per viewer UI refresh design section 6. Embedding proof: a same-origin test-host fixture mounts the viewer with `embed=1` and `theme=` and the three lints keep framing headers, `target='_top'` and localStorage namespace in place, per viewer UI refresh design section 9 and Dex's wespa requirements of 2026-10-02. Standalone viewer carries a visible three-state theme control (Light|Dark|Auto) in the header right of the SearchButton that persists its setting under `rcf-view:v1:theme` in non-embed mode only (ADR-4137); under `embed=1` the control is absent from the DOM and the key is never read or written. Every text and control colour pair meets WCAG 2.1 AA (>= 4.5:1 for text, >= 3:1 for large text and non-text UI boundaries) in both themes, pinned by a static CSS-contrast audit test (US-207) that enumerates every rule and state in `src/view/style.css` and fails the suite on any below-threshold pair.",
|
|
5
|
+
"description": "Build Lite renders the whole RCF tree as a diagram and as a browsable static page, so a non-coding owner can see the documents and their links without reading any JSON. The view is read-only and generated from the on-disk tree on demand. Build/DAG sub-tab lays FBS by `dependsOnFbsIds` depth with click-to-highlight closure, dependency inspector, filters, unconnected lane and `#tab=build&sub=dag&entity=` deep links, per viewer UI refresh design section 7. ID lookup over a server-built `./index.json` of every document id and AC, opened by the SearchButton or Cmd/Ctrl+F, navigates to `#tab=<tab>&entity=<id>` preserving `embed` and `theme`, per viewer UI refresh design section 6. Embedding proof: a same-origin test-host fixture mounts the viewer with `embed=1` and `theme=` and the three lints keep framing headers, `target='_top'` and localStorage namespace in place, per viewer UI refresh design section 9 and Dex's wespa requirements of 2026-10-02. Standalone viewer carries a visible three-state theme control (Light|Dark|Auto) in the header right of the SearchButton that persists its setting under `rcf-view:v1:theme` in non-embed mode only (ADR-4137); under `embed=1` the control is absent from the DOM and the key is never read or written. Every text and control colour pair meets WCAG 2.1 AA (>= 4.5:1 for text, >= 3:1 for large text and non-text UI boundaries) in both themes, pinned by a static CSS-contrast audit test (US-207) that enumerates every rule and state in `src/view/style.css` and fails the suite on any below-threshold pair. Query routes and the trace matrix (DEFINE 2026-10-07, discovery-viewer-command-page): the viewer serves trace, impact and coverage for a selected node as three GET JSON routes (./trace.json, ./impact.json, ./coverage.json) computed from the current walked state and cached by state.version, bypassing the admissibility gate as the CLI coverage, impact and trace verbs do; the Readiness tab's Trace sub-tab renders a trace matrix for a pivot chosen through the lookup modal or a Trace action on any id (rows: stories and criteria; columns: suites, cases, build specs, components; cells coloured by resolution), and the per-requirement Mermaid slice on the Requirements tab is retired so no Mermaid is user-facing on these surfaces.",
|
|
6
6
|
"category": "functional",
|
|
7
7
|
"domain": "view",
|
|
8
8
|
"priority": "must",
|
|
@@ -16,5 +16,8 @@
|
|
|
16
16
|
"version": "0.1.0",
|
|
17
17
|
"status": "draft",
|
|
18
18
|
"createdAt": "2026-06-25T00:00:00Z",
|
|
19
|
-
"updatedAt": "2026-10-
|
|
19
|
+
"updatedAt": "2026-10-07T13:46:36.188Z",
|
|
20
|
+
"deliveredBy": {
|
|
21
|
+
"tacId": "TAC-4136-view-query-routes"
|
|
22
|
+
}
|
|
20
23
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"createdAt": "2026-10-01T18:00:00Z",
|
|
3
|
-
"updatedAt": "2026-10-
|
|
3
|
+
"updatedAt": "2026-10-07T13:46:35.361Z",
|
|
4
4
|
"reqId": "REQ-180",
|
|
5
5
|
"prdId": "PRD-001",
|
|
6
6
|
"title": "Readiness tab as tab 1 and the Overview-to-PRD rename",
|
|
7
|
-
"description": "src/view/readiness.js lands and html-page.js wires it as the first tab. The former Overview tab becomes PRD (same panel content; the rename is label-only). The Readiness panel renders the computeReadiness object
|
|
7
|
+
"description": "src/view/readiness.js lands and html-page.js wires it as the first tab. The former Overview tab becomes PRD (same panel content; the rename is label-only). The Readiness panel is the command page (DEFINE 2026-10-07, discovery-viewer-command-page): it renders the computeReadiness object as linked tables, counts and links, split into sub-tabs (Overview, Questions, Blocking, Coverage, Trace) whose key rides in the hash as sub=. Overview: tree line (formatTreeLine), two verdict cards at equal height (Ready for engineers, Ready to build; each count a link into the table it counts; chain term muted), a stage grid (D1 to D8 by tree and delta scope, pass/total per cell, failing count linked into the blocking table, acknowledged state with its reason from stages[].state), delta as counts with an on-demand per-document list, decisions outstanding in the #241 numbered format, and the freeze state in words (what blocks a freeze and what resolves it; no button, no command text). Questions: one table row per readiness.questions[] entry carrying number, the plain question, where it lives as a link, what settles it in plain words, a one-line copy handle (id plus ask, no command) and state; grouped by source span as a column. Blocking: one table row per failing item across every stage with stage, check, id as a resolving link (composite ids split on the first colon), the gate's why and what resolved looks like; no row cap; filterable by stage and persona. Coverage: a coverage summary with family counts, the three class totals as a stacked bar with the percentage, and an unresolved-pointers table, followed by the thin-requirements table fed by every signal that names a thin requirement (no story, zero criteria, criteria with no resolving test, D4 floor failures, no plain description). The For-engineers DocRow wrapper, the question cards, the blocker cards and the Freeze now control are retired; every engineer item survives in a named table or block (AC-18002-3). The profile register orders the first paint (product owner first unless the profile says engineer) and never hides a block (ADR-4127, ADR-4135). The view is pure: it never recomputes readiness, never renders a shell command and never writes, so the tab and rcf define readiness --json cannot disagree on the same tree hash. Every colour is an existing --sv-* token; the panel stays embed-safe under embed=1 and both themes.",
|
|
8
8
|
"category": "functional",
|
|
9
9
|
"domain": "defineDetection",
|
|
10
10
|
"priority": "must",
|
|
@@ -27,5 +27,8 @@
|
|
|
27
27
|
"rationale": "Baz ruling 2026-09-22 (DEFINE step 2 spec section 2.4, decision 2): one object, two renderers. The CLI (REQ-175, PR B) and the tab (REQ-180, PR C) read the same computeReadiness result so they cannot disagree. Readiness is where an operator starts, so it must be tab 1. The Overview panel is just the PRD body today (phase 3.6 dropped the diagram) so the rename is honest; keeping the hash-anchor `#tab-overview` preserves every existing link into the surface. The L1 pre-population posture (ADR-4126) requires the tab to visibly distinguish [draft] shapes from settled ones, which the shapes:draftSettled check row makes legible.",
|
|
28
28
|
"tags": [
|
|
29
29
|
"capability:define-detection"
|
|
30
|
-
]
|
|
30
|
+
],
|
|
31
|
+
"deliveredBy": {
|
|
32
|
+
"tacId": "TAC-4135-readiness-command-page"
|
|
33
|
+
}
|
|
31
34
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"createdAt": "2026-10-01T18:00:00Z",
|
|
3
|
-
"updatedAt": "2026-10-
|
|
3
|
+
"updatedAt": "2026-10-07T13:46:37.736Z",
|
|
4
4
|
"tacId": "TAC-4127-readiness-view",
|
|
5
5
|
"prdId": "PRD-001",
|
|
6
6
|
"tadId": "TAD-001",
|
|
@@ -46,5 +46,5 @@
|
|
|
46
46
|
"description": "[draft] Decide persona ordering from profile.md text; same contract as the CLI helper (productOwner | engineer | unstated)."
|
|
47
47
|
}
|
|
48
48
|
],
|
|
49
|
-
"notes": "The 0.29.0 scope keeps the diff component document-level only; criterion-level before-and-after is deferred to the UX review per ADR-4127. The pill component is additive and never changes the Product Map `pm-mini` or Requirements `status-chip` markup in this PR; those swaps are follow-ups once a mechanical mapping is established."
|
|
49
|
+
"notes": "The 0.29.0 scope keeps the diff component document-level only; criterion-level before-and-after is deferred to the UX review per ADR-4127. The pill component is additive and never changes the Product Map `pm-mini` or Requirements `status-chip` markup in this PR; those swaps are follow-ups once a mechanical mapping is established. Amended by DEFINE 2026-10-07 (TAC-4135-readiness-command-page, ADR-4139): the Freeze now control is removed (Q4: the freeze block shows the state and what resolves it, no button, no command text), the first-paint per-document delta list becomes counts with an on-demand list (Q2), the blocker cards and their 20-id cap become the blocking table, and renderCoverage is replaced by renderCoverageSummary reading coverage.tree.totals."
|
|
50
50
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"createdAt": "2026-10-02T19:30:00Z",
|
|
3
|
-
"updatedAt": "2026-10-
|
|
3
|
+
"updatedAt": "2026-10-07T13:46:36.966Z",
|
|
4
4
|
"tacId": "TAC-4133-readiness-po-layer",
|
|
5
5
|
"prdId": "PRD-001",
|
|
6
6
|
"tadId": "TAD-001",
|
|
@@ -33,5 +33,5 @@
|
|
|
33
33
|
"description": "[draft] renderStageLegend(stages) returns the StageLegend dialog HTML (D1..D8 by name, one-line meaning, posture)."
|
|
34
34
|
}
|
|
35
35
|
],
|
|
36
|
-
"notes": "Depends on PR 2's DocRow component, PR 1's AppShell and relative-script policy, and PR 2's SubTabStrip (not used here but shared vocabulary). Amends TAC-4127-readiness-view: the old engineer rendering is kept but is now the body of the For-engineers DocRow at the foot of the panel; nothing is removed from the engineer-level DOM (AC-18002-3). The phrasebook ships now (design doc section 11 recommendation 4); when DEFINE step 3 PR 2 lands `readiness.questions`, the adapter switches source with a one-line feature detect and the call site is unchanged. No em-dash is ever written in the phrasebook strings."
|
|
36
|
+
"notes": "Depends on PR 2's DocRow component, PR 1's AppShell and relative-script policy, and PR 2's SubTabStrip (not used here but shared vocabulary). Amends TAC-4127-readiness-view: the old engineer rendering is kept but is now the body of the For-engineers DocRow at the foot of the panel; nothing is removed from the engineer-level DOM (AC-18002-3). The phrasebook ships now (design doc section 11 recommendation 4); when DEFINE step 3 PR 2 lands `readiness.questions`, the adapter switches source with a one-line feature detect and the call site is unchanged. No em-dash is ever written in the phrasebook strings. Amended by DEFINE 2026-10-07 (TAC-4135-readiness-command-page, ADR-4139): the question cards and the For-engineers DocRow are superseded by the questions table and the blocking table; renderReadinessPO keeps its name and composes the tables; toQuestions and the phrasebook are unchanged; AC-18002-3 is satisfied by the blocking table (nothing engineer-level leaves the DOM)."
|
|
37
37
|
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
{
|
|
2
|
+
"createdAt": "2026-10-07T13:46:20.782Z",
|
|
3
|
+
"updatedAt": "2026-10-07T13:46:20.782Z",
|
|
4
|
+
"purpose": "Render the Readiness tab as the command page: every question and every blocking item is a row in a linked table, counts are links into the tables they count, the delta is counts with an on-demand list, coverage is a summary with real numbers, thin requirements are fed by every signal that names one, and the panel is split into sub-tabs (Overview, Questions, Blocking, Coverage, Trace) whose key rides in the hash as sub=. The page is read-only: it never renders a shell command, never offers a write control and never writes under rcf/. Each row carries what a human needs to brief their agent: the item id, the plain-English ask or finding, the chain location, a link that opens the item in full context, and what resolved looks like; the questions table adds a one-line copy handle (id plus ask, no command text). Sub-tabs are the designed shape; one long page with anchor navigation is the named alternative (decision Q5 is ruled on the rendered sketches, see notes).",
|
|
5
|
+
"responsibilities": [
|
|
6
|
+
"src/view/readiness/tables.js: renderQuestionsTable(readiness) and renderBlockingTable(readiness, opts) emit one HTML table each from readiness.questions[] and stages[].checks[].failing[]; no row cap; composite ids split through splitCompositeId; every href is a hash route the page-init router resolves.",
|
|
7
|
+
"src/view/readiness/coverage-summary.js: renderCoverageSummary(readiness, model) reads coverage.tree.totals, requirements[].coverageClass and unresolvedTestPointers[] plus family counts from the tree model; prints numbers or the words coverage unavailable, never a blank.",
|
|
8
|
+
"src/view/readiness/thin-reqs.js: buildThinReqRows(readiness, model) joins D4 stories:usFloors failing US ids to their REQ via us.reqId, stories with zero criteria, criteria with no resolving test from coverage acs[].covered, D2 skeleton:reqIntent and stories:reqHasUs; renderThinReqsTable renders the rows the two verdict cards link to.",
|
|
9
|
+
"src/view/readiness/grid.js: renderVerdictGrid(readiness) groups stages[].checks[] by stage and over (tree, delta), prints pass/total per cell and links the failing count into the blocking table filtered to that stage; the acknowledged state and its reason come from stages[].state and one reason helper, never from freezeRecord.gates directly.",
|
|
10
|
+
"src/view/readiness.js: renderReadinessPanel keeps its signature; it now composes the sub-tab strip (SubTabStrip with hashKey readiness) and the five sub-views; the For-engineers DocRow wrapper, the Freeze now control, the per-document delta list on first paint and the blocker cards are removed, their content living in the named tables and blocks; the CLI verdict strings still render so parity with rcf define readiness --json is unchanged.",
|
|
11
|
+
"src/view/page-init.js: the router reads sub= for the readiness tab the way it does for build, restores it after an SSE swap, drops an unknown value back to overview, and wires the Copy for your agent control through the existing toast component.",
|
|
12
|
+
"src/view/style.css: new .rcf-cmd-* rules use only existing --sv-* tokens on known surfaces so test/view/contrast-aa.test.js stays green in both themes; tables collapse to stacked rows under 720px and never force horizontal page scroll under data-embed=1."
|
|
13
|
+
],
|
|
14
|
+
"internalStructure": "Pure server-rendered HTML string builders under src/view/readiness/ (tables.js, coverage-summary.js, thin-reqs.js, grid.js, composite-id.js), one composition site in src/view/readiness.js, and client wiring in page-init.js for the sub-tab strip and the copy handle. No new query module: every number is read from the computeReadiness result that src/view/index.js already folds (readiness.questions, stages, delta, coverage, levels, personas) and from BuiltTreeModel lengths. computeReadiness keeps its signature; renderModelToPage keeps its return additive. No inline script; no new localStorage key; no new dependency.",
|
|
15
|
+
"interfaces": [
|
|
16
|
+
{
|
|
17
|
+
"name": "renderQuestionsTable",
|
|
18
|
+
"kind": "other",
|
|
19
|
+
"description": "renderQuestionsTable(readiness) returns the questions table HTML: one QuestionRow per readiness.questions[] entry, group label as a sortable column, the location link, what settles it in plain words, the copy handle, the state. Empty questions[] renders the intent-complete verdict line (AC-18002-2 preserved)."
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"name": "renderBlockingTable",
|
|
23
|
+
"kind": "other",
|
|
24
|
+
"description": "renderBlockingTable(readiness, { stage, persona }) returns the blocking table HTML: one BlockingRow per failing item across stages[].checks[].failing[], filterable by stage and persona through the existing FilterBar, no row cap, every id a resolving link."
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"name": "splitCompositeId",
|
|
28
|
+
"kind": "other",
|
|
29
|
+
"description": "splitCompositeId(id) returns { docId, fragment } by splitting on the first colon; a plain document id returns fragment null. Used for every href the tables emit so a composite finding id such as AC-060-3:userID links to AC-060-3."
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"name": "renderCoverageSummary",
|
|
33
|
+
"kind": "other",
|
|
34
|
+
"description": "renderCoverageSummary(readiness, model) returns the coverage block HTML: family stat tiles, one stacked bar from the three class totals, the percentage covered and the unresolved-pointers table; prints coverage unavailable when totals are absent."
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"name": "renderThinReqsTable",
|
|
38
|
+
"kind": "other",
|
|
39
|
+
"description": "renderThinReqsTable(rows) returns the thin-requirements table HTML from ThinReqRow[]; sortable, filterable by reason; the row count is the number the verdict card links to."
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"name": "renderVerdictGrid",
|
|
43
|
+
"kind": "other",
|
|
44
|
+
"description": "renderVerdictGrid(readiness) returns the stage grid HTML: eight stage rows, tree and delta columns, pass/total per VerdictGridCell, failing count linked into the blocking table filtered to that stage; replaces the chip row and the stage detail on the Overview sub-tab."
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
"name": "renderDeltaCounts",
|
|
48
|
+
"kind": "other",
|
|
49
|
+
"description": "renderDeltaCounts(readiness, freezeRecord) returns the delta block HTML as six counts (DeltaCounts) with a details element that renders the per-document list and diff only when the reader expands it; the first paint never carries the per-document rows."
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"name": "readinessSubTabs",
|
|
53
|
+
"kind": "other",
|
|
54
|
+
"description": "The readiness tab's SubTabStrip (hashKey readiness) with keys overview, questions, blocking, coverage and trace. The router writes and reads sub= for readiness exactly as it does for build, restores it after an SSE innerHTML swap and resolves an unknown key to overview."
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"name": "QuestionRow",
|
|
58
|
+
"kind": "recordShape",
|
|
59
|
+
"description": "One row of the questions table.\nfields: number, id, ask, location, locationHref, settles, briefHandle, state\nnotes: number is the display ordinal; id is the readiness question id; location is the chain location in words (statement n, profile field, requirement id); locationHref is the hash route that opens the item in full context; settles is the plain-English resolved state; briefHandle is the one-line id-plus-ask copy text; state is open or answered."
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
"name": "BlockingRow",
|
|
63
|
+
"kind": "recordShape",
|
|
64
|
+
"description": "One row of the blocking table.\nfields: stage, check, id, docId, fragment, href, why, resolved\nnotes: stage is D1 to D8; check is the check id; id is the finding id as the gate emitted it; docId and fragment are the splitCompositeId halves; href is the resolving hash route; why is the gate's finding text; resolved is what the resolved state looks like in plain words."
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
"name": "ThinReqRow",
|
|
68
|
+
"kind": "recordShape",
|
|
69
|
+
"description": "One row of the thin-requirements table.\nfields: reqId, stories, criteria, covered, thinReason, openHref, traceHref\nnotes: stories and criteria are counts; covered is the count of criteria with a resolving test; thinReason is the thin reason in words; openHref opens the requirement; traceHref opens the Trace sub-tab pivoted on it."
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
"name": "CoverageSummary",
|
|
73
|
+
"kind": "recordShape",
|
|
74
|
+
"description": "The coverage block's data.\nfields: families, totals, percentCovered, unresolvedPointers\nnotes: families is the per-family document count (requirements, stories, criteria, suites, cases, buildSpecs); totals is coverage.tree.totals verbatim; percentCovered is covered over requirements; unresolvedPointers is coverage.tree.unresolvedTestPointers verbatim."
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
"name": "VerdictGridCell",
|
|
78
|
+
"kind": "recordShape",
|
|
79
|
+
"description": "One cell of the stage grid.\nfields: stage, over, pass, total, failing, state, href\nnotes: over is tree or delta; pass and total are summed over the stage's checks in that scope; failing is the count of failing items; state is the stage state (passed, failing, acknowledged, notApplicable); href links into the blocking table filtered to the stage."
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
"name": "DeltaCounts",
|
|
83
|
+
"kind": "recordShape",
|
|
84
|
+
"description": "The delta block's data on first paint.\nfields: changed, added, removed, briefSince, impacted, impactedFbs, expanded\nnotes: the six counts are readiness.delta lengths; expanded is false on first paint and true only after the reader opens the per-document list."
|
|
85
|
+
}
|
|
86
|
+
],
|
|
87
|
+
"notes": "Supersedes the layout pinned by REQ-180's earlier description and the question-card and For-engineers DocRow blocks of TAC-4133-readiness-po-layer (renderReadinessPO keeps its name and now composes the tables; toQuestions is unchanged); amends TAC-4127-readiness-view by removing the Freeze now control and the first-paint delta list. Rulings carried: Q1 (viewer read-only, no CLI command text anywhere on the page, rows carry id, ask or finding, chain location, link, resolved state; the copy handle is a design candidate shown in the wireframe); Q2 (delta on an unfrozen tree is counts only with on-demand expand); Q3 (thin requirements table lists all three flavours: zero criteria, unresolved tests, D4 floor failures); Q4 (no freeze button, no command text; show the state and what resolves it). Q5 alternative: one long page with anchor navigation instead of sub-tabs; the two sketches discovery-viewer-command-page-5-subtabs.html and discovery-viewer-command-page-6-one-page.html under guidance/discovery/ carry the same data in both shapes and the product owner rules on the render; if the one-page shape is chosen, readinessSubTabs becomes an anchor strip and sub= is dropped, nothing else in this TAC changes. Embed and theme contract (issues 263 and 264): every href is relative or a hash route, no new route is added by this TAC, no new localStorage key, the control row stays inside the panel under data-embed=1, and every colour is an existing --sv-* token on a known surface. On-me vocabulary: the Overview sub-tab names what waits on the product owner as On me and what waits on engineers as On engineers. No Mermaid anywhere on the tab.",
|
|
88
|
+
"tacId": "TAC-4135-readiness-command-page",
|
|
89
|
+
"prdId": "PRD-001",
|
|
90
|
+
"tadId": "TAD-001",
|
|
91
|
+
"version": "0.1.0",
|
|
92
|
+
"status": "draft",
|
|
93
|
+
"name": "Readiness command page: linked tables, verdict grid, delta counts, coverage summary, thin requirements, sub-tabs"
|
|
94
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
{
|
|
2
|
+
"createdAt": "2026-10-07T13:46:28.216Z",
|
|
3
|
+
"updatedAt": "2026-10-07T13:46:28.216Z",
|
|
4
|
+
"purpose": "Expose the pure trace, impact and coverage computes the CLI already calls as three GET JSON routes on the viewer server, computed from the current walked state and cached per state.version, and render a trace matrix for a selected node on the Readiness tab's Trace sub-tab with a Trace action on every id. Admissibility statement: the three routes do NOT call runWithAdmissibilityGate; they bypass the gate exactly as src/cli/coverage.js, src/cli/impact.js and src/cli/trace.js do (issues 316 and 317 context), so a tree that fails admissibility still answers trace, impact and coverage in the viewer; only readiness and freeze consult the gate. The routes are read-only, GET and HEAD only like every other route, and never write under rcf/.",
|
|
5
|
+
"responsibilities": [
|
|
6
|
+
"src/server/routes.js: three handlers after /index.json, each reading deps.currentState(), answering 503 view server initialising before the first walk, 404 unknown-id for an unknown pivot, 400 bad-direction for a bad direction, and application/json with cache-control: no-store otherwise. Relative to the viewer mount so a reverse proxy sees ./trace.json under the mount point; release-noted so host allow-lists (the WESPA proxy added ./page-init.js by hand for 0.29.0) are extended before a version pin bump.",
|
|
7
|
+
"src/view/index.js: renderModelToPage keeps the walked tree on the returned state (additive) so the routes compute per request from the same tree the page was rendered from; a per-version memo (queryCache) keyed by state.version and the pivot plus direction holds each computed result so a repeated request is served from memory and a rewalk discards the previous version's entries.",
|
|
8
|
+
"src/query/: unchanged. computeTrace(tree, { id, direction }), computeImpact(tree, { id }) and computeCoverage(tree, { testPointers, mode }) are imported as they are; no new query module.",
|
|
9
|
+
"src/view/readiness/trace-matrix.js: renderTraceMatrix(trace, coverage, model) builds the matrix from a forward trace: rows are the stories and criteria under the pivot, columns are suites, cases, build specs and components (component via usByTacId), cells coloured by resolution from coverage acs[]; a row filter appears past 200 rows; the empty state names an unknown pivot.",
|
|
10
|
+
"src/view/page-init.js: wireTraceMatrix fetches ./trace.json and ./coverage.json for the pivot from the hash (entity= on sub=trace), caches the result in memory keyed by state.version, re-renders after an SSE swap and marks the result stale until the next fetch; every table row's Trace action and the lookup modal's readiness hits write #tab=readiness&sub=trace&entity=<id>.",
|
|
11
|
+
"src/view/html-page.js and src/view/mermaid-diagram.js: the per-requirement Mermaid slice (allRequirementSubdiagrams and the rcf-req-slice details) is removed; no Mermaid is rendered user-facing by this capability."
|
|
12
|
+
],
|
|
13
|
+
"internalStructure": "Server half: route handlers in src/server/routes.js that call the pure query functions on the state's tree and memoise by (version, pivot, direction) in a Map held on the server closure; the memo is replaced wholesale on every rewalk. Client half: wireTraceMatrix in page-init.js (fetch, cache, render, stale marking) and the pure renderer in src/view/readiness/trace-matrix.js. No inline script; no new dependency; no new localStorage key (the cache is a page-lifetime Map); theme by --sv-* tokens only.",
|
|
14
|
+
"interfaces": [
|
|
15
|
+
{
|
|
16
|
+
"name": "GET /trace.json",
|
|
17
|
+
"kind": "httpRoute",
|
|
18
|
+
"description": "method: GET\npath: /trace.json?id=<id>&direction=<forward|back|both>\nrequest: query id (a document id or inline AC or TC id), direction defaulting to forward\nresponse: application/json, the computeTrace result verbatim (pivot, direction, found, nodes[], edges[] or ancestors[] and descendants[] for both); cache-control: no-store\nerrors: 503 text before the first walk; 404 QueryRouteError unknown-id; 400 QueryRouteError bad-direction; 405 for any method other than GET or HEAD"
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"name": "GET /impact.json",
|
|
22
|
+
"kind": "httpRoute",
|
|
23
|
+
"description": "method: GET\npath: /impact.json?id=<id>\nrequest: query id\nresponse: application/json, the computeImpact result verbatim (pivot, found, nodes[] with actionNeeded, edges[]); cache-control: no-store\nerrors: 503 text before the first walk; 404 QueryRouteError unknown-id; 405 for any method other than GET or HEAD"
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"name": "GET /coverage.json",
|
|
27
|
+
"kind": "httpRoute",
|
|
28
|
+
"description": "method: GET\npath: /coverage.json?scope=<id>\nrequest: optional query scope narrowing to a PRD, REQ or US subtree as the CLI positional does; omitted means the whole tree; strict per-AC mode always\nresponse: application/json, the computeCoverage result verbatim (totals, requirements[] with acs[], unresolvedTestPointers[]); cache-control: no-store\nerrors: 503 text before the first walk; 400 QueryRouteError bad-scope for a below-AC or unknown scope id; 405 for any method other than GET or HEAD"
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"name": "queryCache",
|
|
32
|
+
"kind": "other",
|
|
33
|
+
"description": "Server-side memo keyed by state.version plus pivot plus direction (or scope). One compute per key per version; replaced wholesale when the walker publishes a new version. Never persisted; never written under rcf/."
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"name": "renderTraceMatrix",
|
|
37
|
+
"kind": "other",
|
|
38
|
+
"description": "renderTraceMatrix(trace, coverage, model) returns the matrix HTML for a forward trace: TraceMatrixRow per story and criterion, columns for suites, cases, build specs and components, TraceMatrixCell per intersection coloured by resolution; empty state when trace.found is false; row filter when rows exceed 200."
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"name": "wireTraceMatrix",
|
|
42
|
+
"kind": "other",
|
|
43
|
+
"description": "Client wiring in page-init.js: reads entity= under sub=trace, fetches ./trace.json and ./coverage.json relative to the mount, caches by state.version in a page-lifetime Map, renders through renderTraceMatrix's client mirror, re-renders after an SSE innerHTML swap and marks stale; also decorates every id in the readiness tables with the Trace action and routes lookup hits for readiness rows."
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"name": "TraceMatrixRow",
|
|
47
|
+
"kind": "recordShape",
|
|
48
|
+
"description": "One row of the matrix.\nfields: usId, acId, title, cells\nnotes: usId and acId identify the story and criterion; title is the criterion text; cells is the TraceMatrixCell list in column order."
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
"name": "TraceMatrixCell",
|
|
52
|
+
"kind": "recordShape",
|
|
53
|
+
"description": "One cell of the matrix.\nfields: columnId, columnKind, reached, resolution\nnotes: columnKind is ts, tc, fbs or tac; reached is true when the trace reaches the column from the row's criterion; resolution is resolving, unresolved or none, read from coverage acs[] for tc columns and none otherwise."
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"name": "QueryRouteError",
|
|
57
|
+
"kind": "recordShape",
|
|
58
|
+
"description": "The JSON error body the three routes return on 400 and 404.\nfields: error, id, direction, scope\nnotes: error is unknown-id, bad-direction or bad-scope; id, direction and scope echo the request values that were present."
|
|
59
|
+
}
|
|
60
|
+
],
|
|
61
|
+
"notes": "Decision taken (ADR-4140): GET per pivot, cached by version, no whole-tree dump (PRD-001 forward on the largest consumer tree is 2,972 nodes and 1.5 MB of JSON), matrix not sunburst, no Mermaid user-facing, and the admissibility bypass stated above. Embed and theme contract (issues 263 and 264): the three routes are relative to the mount and release-noted for proxy allow-lists; the client cache is a page-lifetime Map, not localStorage; the matrix uses only --sv-success, --sv-warning, --sv-danger and --sv-muted on --sv-surface so test/view/contrast-aa.test.js is unaffected. Deferred and named: an impact sub-view with action labels per row and keyboard row navigation (discovery capabilities 10 and 13), a readiness timeline (17), and the Product Map trace bucket realignment to resolution-gated coverage; none of them is in the five FBS of this DEFINE.",
|
|
62
|
+
"tacId": "TAC-4136-view-query-routes",
|
|
63
|
+
"prdId": "PRD-001",
|
|
64
|
+
"tadId": "TAD-001",
|
|
65
|
+
"version": "0.1.0",
|
|
66
|
+
"status": "draft",
|
|
67
|
+
"name": "View query routes: trace, impact and coverage as JSON, the trace matrix and Trace actions"
|
|
68
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"createdAt": "2026-10-08T15:39:45.639Z",
|
|
3
|
+
"updatedAt": "2026-10-08T15:39:45.639Z",
|
|
4
|
+
"purpose": "Implement the ADR-4141 decision: `rcf verify run` gains a `--mode <agentScreenshotCritique|deterministic>` flag (default agentScreenshotCritique); the deterministic engine runs in-process (`src/verify/engine/deterministic.js`) with a reachability HTTP probe on runStats and a per-AC skip ledger recorded on blockedAcs[] as critique-only, so the aggregate verdict is BLOCKED. The CLI stamps runStats.mode and runStats.counts on the report. `rcf build finalise` gains the same `--mode` flag, threads it through to the fresh verify subprocess via buildVerifyArgs, preseeds the --out path with a `{ status: pending, launchFailure.reason: preseed }` stub BEFORE the spawn, overwrites that stub with a `{ status: aborted }` record if verify exits non-zero without writing (so ingest never surfaces ENOENT), and refuses promotion with the counts line when a deterministic run skipped any AC (ADR-4112 verified invariant). The HOLD-authority branch treats a preseed-only report as unreadable (NIT-3 'unreadable is not a pass').",
|
|
5
|
+
"responsibilities": [
|
|
6
|
+
"Add src/verify/engine/deterministic.js with VERIFY_MODES, DEFAULT_VERIFY_MODE, isVerifyMode, probeHttpReachability, and runDeterministic. The last returns { findings: [], blockedAcs: [{acId, reason: 'critique-only...', mode: 'deterministic'}], runStats: { mode, httpProbe, counts, startedAtMs, finishedAtMs } }.",
|
|
7
|
+
"Branch the engine's launcher step on opts.mode === 'deterministic': call runDeterministic in-process, merge its blockedAcs into the provisioning-side list, and skip the agent CLI launcher entirely.",
|
|
8
|
+
"Stamp runStats.mode on every report path (normal, NOT-DEPLOYED, LAUNCH-FAILURE).",
|
|
9
|
+
"Add `--mode` to src/verify/cli/run.js and src/cli/finalise.js with an isVerifyMode guard (unknown value exits 2).",
|
|
10
|
+
"Thread `--mode` through src/finalise/spawn.js buildVerifyArgs.",
|
|
11
|
+
"Preseed the --out path in finalise before spawn with `{ verdict: 'LAUNCH-FAILURE', verdictAuthority: null, launchFailure: { status: 'aborted', reason: 'preseed' } }`.",
|
|
12
|
+
"On a non-zero spawn exit whose report is still the preseed, overwrite with a real `{ status: 'aborted', reason: 'rcf verify exited <code> without writing a report', exitCode }` record.",
|
|
13
|
+
"In the HOLD-authority branch, detect a preseed-only report and surface it as unreadable (never a silent promotion).",
|
|
14
|
+
"Add the deterministic refusal line: if runStats.mode === 'deterministic' and (counts.skipped > 0 OR counts.verified < counts.total), refuse promotion with the counts line and reference ADR-4112."
|
|
15
|
+
],
|
|
16
|
+
"internalStructure": "Branch at step 6 of runVerification. Deterministic is a straight-line reducer over chain.acs; agent mode is unchanged. The CLI changes are a flag + a one-line thread-through. Finalise's preseed is an upfront writeFile; the overwrite is in the gate-NOT-passed branch, guarded by `report?.launchFailure?.reason === 'preseed'` so a legitimate verify-authored launch-failure report is not clobbered.",
|
|
17
|
+
"interfaces": [],
|
|
18
|
+
"notes": "Behavioural addition, not a change: agent-mode runs are unchanged. Deterministic mode's BLOCKED verdict already trips the existing gate (verify exit 5 -> finalise exit 4); the new refusal line is UX for the operator so they see the counts and the ADR reference immediately. No rcf-schemas bump: runStats and launchFailure both accept additional fields today.",
|
|
19
|
+
"tacId": "TAC-4141-verify-modes",
|
|
20
|
+
"prdId": "PRD-001",
|
|
21
|
+
"tadId": "TAD-001",
|
|
22
|
+
"version": "0.1.0",
|
|
23
|
+
"status": "draft",
|
|
24
|
+
"name": "verify modes CLI + deterministic engine + preseed partial report"
|
|
25
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"createdAt": "2026-10-01T18:00:00Z",
|
|
3
|
-
"updatedAt": "2026-10-
|
|
3
|
+
"updatedAt": "2026-10-08T16:43:35.128Z",
|
|
4
4
|
"purpose": "Cover US-18001 (Readiness as tab 1 and the PRD rename, plus the live-client resync SSOT guard added for issue 297) and US-18101 (shared pill, findings-list and diff components). Shares the readiness fixture builders with TS-222 so the tab and the CLI assertions ride the same shapes.",
|
|
5
5
|
"testLevel": "unit",
|
|
6
6
|
"acIds": [
|
|
@@ -37,16 +37,16 @@
|
|
|
37
37
|
{
|
|
38
38
|
"id": "TC-223-po-blockers-as-findings-list",
|
|
39
39
|
"acId": "AC-18001-3",
|
|
40
|
-
"description": "Each PO blocker
|
|
40
|
+
"description": "Each PO blocker id appears in the questions table under its question group with the id as an anchor link into the document tabs.",
|
|
41
41
|
"status": "pending",
|
|
42
|
-
"testPointer": "test/view/readiness-tab.test.js::readiness tab: AC-18001-3 PO
|
|
42
|
+
"testPointer": "test/view/readiness-tab.test.js::readiness tab: AC-18001-3 PO blocker ids appear in the questions table"
|
|
43
43
|
},
|
|
44
44
|
{
|
|
45
45
|
"id": "TC-223-register-orders-persona-groups",
|
|
46
46
|
"acId": "AC-18001-4",
|
|
47
|
-
"description": "With a profile register of productOwner, the
|
|
47
|
+
"description": "With a profile register of productOwner, the questions table precedes the blocking table.",
|
|
48
48
|
"status": "pending",
|
|
49
|
-
"testPointer": "test/view/readiness-tab.test.js::readiness tab: AC-18001-4 register orders the
|
|
49
|
+
"testPointer": "test/view/readiness-tab.test.js::readiness tab: AC-18001-4 register orders the questions and blocking tables"
|
|
50
50
|
},
|
|
51
51
|
{
|
|
52
52
|
"id": "TC-223-no-blocker-id-omitted",
|
|
@@ -58,9 +58,9 @@
|
|
|
58
58
|
{
|
|
59
59
|
"id": "TC-223-freeze-now-disabled",
|
|
60
60
|
"acId": "AC-18001-6",
|
|
61
|
-
"description": "When levels.readyToBuild.ok is false the
|
|
61
|
+
"description": "When levels.readyToBuild.ok is false the freeze state block names the failing gates from levels.readyToBuild.blockedBy in plain words and no freeze control is rendered.",
|
|
62
62
|
"status": "pending",
|
|
63
|
-
"testPointer": "test/view/readiness-tab.test.js::readiness tab: AC-18001-6
|
|
63
|
+
"testPointer": "test/view/readiness-tab.test.js::readiness tab: AC-18001-6 freeze state names failing gates in plain words, no freeze control"
|
|
64
64
|
},
|
|
65
65
|
{
|
|
66
66
|
"id": "TC-223-ids-on-tab-match-cli-json",
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
{
|
|
2
|
+
"createdAt": "2026-10-07T13:47:03.889Z",
|
|
3
|
+
"updatedAt": "2026-10-08T17:03:01.078Z",
|
|
4
|
+
"purpose": "Cover every acceptance criterion of US-18003 with one node:test case each in test/view/readiness-tables.test.js; DEFINE lands the named declarations flagged not yet built so the strict coverage audit binds each criterion, and BUILD (FBS-204) removes the flags as it makes them pass.",
|
|
5
|
+
"testLevel": "unit",
|
|
6
|
+
"acIds": [
|
|
7
|
+
"AC-18003-1",
|
|
8
|
+
"AC-18003-2",
|
|
9
|
+
"AC-18003-3",
|
|
10
|
+
"AC-18003-4",
|
|
11
|
+
"AC-18003-5",
|
|
12
|
+
"AC-18003-6",
|
|
13
|
+
"AC-18003-7",
|
|
14
|
+
"AC-18003-8"
|
|
15
|
+
],
|
|
16
|
+
"testCases": [
|
|
17
|
+
{
|
|
18
|
+
"id": "TC-237-18003-1-happy",
|
|
19
|
+
"acId": "AC-18003-1",
|
|
20
|
+
"description": "[happy] Given readiness.questions is non-empty, when the questions sub-view renders, then it is one table with one QuestionRow per question carrying QuestionRow.number, QuestionRow.ask, QuestionRow.location as a link that opens the item in full context, QuestionRow.settles in plain words and QuestionRow.state, and the group label is a sortable column rather than a heading.",
|
|
21
|
+
"status": "pending",
|
|
22
|
+
"testPointer": "test/view/readiness-tables.test.js::AC-18003-1 happy: readinessquestions is nonempty"
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"id": "TC-237-18003-2-edge",
|
|
26
|
+
"acId": "AC-18003-2",
|
|
27
|
+
"description": "[edge] Given a question whose itemId is not a document id (a brief statement such as \"brief-ledger\" or a profile field such as \"profile:surface\"), when the row renders, then QuestionRow.locationHref is \"#tab=readiness&sub=questions&entity=<itemId>\" and the router lands on that row, so the page never emits a dead anchor.",
|
|
28
|
+
"status": "pending",
|
|
29
|
+
"testPointer": "test/view/readiness-tables.test.js::AC-18003-2 edge: a question whose itemid is not a document id a b"
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"id": "TC-237-18003-3-happy",
|
|
33
|
+
"acId": "AC-18003-3",
|
|
34
|
+
"description": "[happy] Given every failing check across stages, when the blocking sub-view renders, then it is one table with one BlockingRow per failing item carrying BlockingRow.stage, BlockingRow.check, BlockingRow.docId as a link, BlockingRow.why from the gate and BlockingRow.resolved in plain words, with no cap on the number of rows and a FilterBar by stage and persona.",
|
|
35
|
+
"status": "pending",
|
|
36
|
+
"testPointer": "test/view/readiness-tables.test.js::AC-18003-3 happy: every failing check across stages"
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"id": "TC-237-18003-4-edge",
|
|
40
|
+
"acId": "AC-18003-4",
|
|
41
|
+
"description": "[edge] Given a composite failing id such as \"AC-060-3:userID\" or \"TAC-4122-define-gates:checkPersona\", when its row renders, then BlockingRow.docId is the text before the first colon, BlockingRow.fragment is the remainder and BlockingRow.href targets the document id so the link resolves through findByDocId.",
|
|
42
|
+
"status": "pending",
|
|
43
|
+
"testPointer": "test/view/readiness-tables.test.js::AC-18003-4 edge: a composite failing id such as ac0603userid or t"
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"id": "TC-237-18003-5-happy",
|
|
47
|
+
"acId": "AC-18003-5",
|
|
48
|
+
"description": "[happy] Given a question row, when the copy control renders, then QuestionRow.briefHandle is one line holding the item id and the plain-English ask, the control is labelled \"Copy for your agent\" and copies that line through the existing toast feedback, and the line holds no command text.",
|
|
49
|
+
"status": "pending",
|
|
50
|
+
"testPointer": "test/view/readiness-tables.test.js::AC-18003-5 happy: a question row"
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"id": "TC-237-18003-6-failure",
|
|
54
|
+
"acId": "AC-18003-6",
|
|
55
|
+
"description": "[failure] Given readiness could not be computed (the readiness object is null), when the Readiness tab renders, then the existing \"could not be computed\" placeholder is shown and no table is rendered.",
|
|
56
|
+
"status": "pending",
|
|
57
|
+
"testPointer": "test/view/readiness-tables.test.js::AC-18003-6 failure: readiness could not be computed the readiness ob"
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"id": "TC-237-18003-7-mustnot",
|
|
61
|
+
"acId": "AC-18003-7",
|
|
62
|
+
"description": "[must-not] Given any register and any tree, when the panel renders for the command page, then the viewer emits no shell command text: no code element carries a command, no Run or Freeze-now affordance exists; chain ids are content, rendered as a prefix link with a plain-English label from the chain, and the full composite id stays in the DOM in a data attribute.",
|
|
63
|
+
"status": "pending",
|
|
64
|
+
"testPointer": "test/view/readiness-tables.test.js::AC-18003-7 must-not: no shell command text, chain ids as prefix link with full id in data attribute"
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
"id": "TC-237-18003-8-happy",
|
|
68
|
+
"acId": "AC-18003-8",
|
|
69
|
+
"description": "[happy] Given the profile register is \"engineer\", when the tab first paints, then the blocking table precedes the questions table; given \"productOwner\" or no profile, the questions table precedes the blocking table; in both cases both tables are present in the DOM.",
|
|
70
|
+
"status": "pending",
|
|
71
|
+
"testPointer": "test/view/readiness-tables.test.js::AC-18003-8 happy: the profile register is engineer"
|
|
72
|
+
}
|
|
73
|
+
],
|
|
74
|
+
"id": "TS-237",
|
|
75
|
+
"usId": "US-18003",
|
|
76
|
+
"title": "US-18003 command page suite (readiness-tables)",
|
|
77
|
+
"status": "draft"
|
|
78
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
{
|
|
2
|
+
"createdAt": "2026-10-07T13:47:04.672Z",
|
|
3
|
+
"updatedAt": "2026-10-09T10:01:25.009Z",
|
|
4
|
+
"purpose": "Cover every acceptance criterion of US-18004 with one node:test case each in test/view/readiness-coverage-summary.test.js; DEFINE lands the named declarations flagged not yet built so the strict coverage audit binds each criterion, and BUILD (FBS-205) removes the flags as it makes them pass.",
|
|
5
|
+
"testLevel": "unit",
|
|
6
|
+
"acIds": [
|
|
7
|
+
"AC-18004-1",
|
|
8
|
+
"AC-18004-2",
|
|
9
|
+
"AC-18004-3",
|
|
10
|
+
"AC-18004-4",
|
|
11
|
+
"AC-18004-5",
|
|
12
|
+
"AC-18004-6",
|
|
13
|
+
"AC-18004-7"
|
|
14
|
+
],
|
|
15
|
+
"testCases": [
|
|
16
|
+
{
|
|
17
|
+
"id": "TC-238-18004-1-happy",
|
|
18
|
+
"acId": "AC-18004-1",
|
|
19
|
+
"description": "[happy] Given readiness.coverage.tree carries totals, when the coverage sub-view renders, then CoverageSummary.totals shows requirements, covered, coveredUnresolved and uncovered as numbers and CoverageSummary.percentCovered as a percentage, never a blank value.",
|
|
20
|
+
"status": "pending",
|
|
21
|
+
"testPointer": "test/view/readiness-coverage-summary.test.js::AC-18004-1 happy: readinesscoveragetree carries totals"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"id": "TC-238-18004-2-happy",
|
|
25
|
+
"acId": "AC-18004-2",
|
|
26
|
+
"description": "[happy] Given the tree model, when the coverage sub-view renders, then CoverageSummary.families lists the document counts per family (requirements, stories, criteria, suites, cases, build specs) as stat tiles and one stacked bar whose three widths are the three class totals, using only the --sv-success, --sv-warning and --sv-danger tokens on --sv-surface.",
|
|
27
|
+
"status": "pending",
|
|
28
|
+
"testPointer": "test/view/readiness-coverage-summary.test.js::AC-18004-2 happy: the tree model"
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"id": "TC-238-18004-3-happy",
|
|
32
|
+
"acId": "AC-18004-3",
|
|
33
|
+
"description": "[happy] Given coverage.tree.unresolvedTestPointers is non-empty, when the coverage sub-view renders, then an unresolved-pointers table lists each pointer with its suite id as a link, its case id, the pointer text and the reason word the CLI prints (for example \"test-missing\" or \"file-missing\").",
|
|
34
|
+
"status": "pending",
|
|
35
|
+
"testPointer": "test/view/readiness-coverage-summary.test.js::AC-18004-3 happy: coveragetreeunresolvedtestpointers is nonempty"
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"id": "TC-238-18004-4-happy",
|
|
39
|
+
"acId": "AC-18004-4",
|
|
40
|
+
"description": "[happy] Given a requirement that fails at least one thin reason from the list [no story | zero criteria on a story | a criterion with no resolving test | a story failing the D4 floors | no plain description], when the thin-requirements table renders, then it carries one ThinReqRow for that requirement with ThinReqRow.stories, ThinReqRow.criteria, ThinReqRow.covered, ThinReqRow.thinReason, ThinReqRow.openHref and ThinReqRow.traceHref.",
|
|
41
|
+
"status": "pending",
|
|
42
|
+
"testPointer": "test/view/readiness-coverage-summary.test.js::AC-18004-4 happy: a requirement that fails at least one thin reaso"
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"id": "TC-238-18004-5-happy",
|
|
46
|
+
"acId": "AC-18004-5",
|
|
47
|
+
"description": "[happy] Given the two verdict cards, when the overview sub-view renders, then the question count on the Ready for engineers card is a link to the questions table, the engineer item count on the Ready to build card is a link to the blocking table, and the former What happens next paragraph is folded into the cards as one sentence each.",
|
|
48
|
+
"status": "pending",
|
|
49
|
+
"testPointer": "test/view/readiness-coverage-summary.test.js::AC-18004-5 happy: the two verdict cards"
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"id": "TC-238-18004-6-failure",
|
|
53
|
+
"acId": "AC-18004-6",
|
|
54
|
+
"description": "[failure] Given a coverage result with no totals (a partial tree or an older compute), when the coverage sub-view renders, then it shows the words \"coverage unavailable\" and the rest of the panel still renders.",
|
|
55
|
+
"status": "pending",
|
|
56
|
+
"testPointer": "test/view/readiness-coverage-summary.test.js::AC-18004-6 failure: a coverage result with no totals a partial tree"
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
"id": "TC-238-18004-7-mustnot",
|
|
60
|
+
"acId": "AC-18004-7",
|
|
61
|
+
"description": "[must-not] Given any tree, when the coverage sub-view renders, then it never prints an empty number: a value the coverage result does not carry renders as \"coverage unavailable\", not as a blank.",
|
|
62
|
+
"status": "pending",
|
|
63
|
+
"testPointer": "test/view/readiness-coverage-summary.test.js::AC-18004-7 must-not: any tree"
|
|
64
|
+
}
|
|
65
|
+
],
|
|
66
|
+
"id": "TS-238",
|
|
67
|
+
"usId": "US-18004",
|
|
68
|
+
"title": "US-18004 command page suite (readiness-coverage-summary)",
|
|
69
|
+
"status": "draft"
|
|
70
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
{
|
|
2
|
+
"createdAt": "2026-10-07T13:47:05.533Z",
|
|
3
|
+
"updatedAt": "2026-10-09T12:09:27.300Z",
|
|
4
|
+
"purpose": "Cover every acceptance criterion of US-18005 with one node:test case each in test/view/readiness-layout.test.js; DEFINE lands the named declarations flagged not yet built so the strict coverage audit binds each criterion, and BUILD (FBS-206) removes the flags as it makes them pass.",
|
|
5
|
+
"testLevel": "unit",
|
|
6
|
+
"acIds": [
|
|
7
|
+
"AC-18005-1",
|
|
8
|
+
"AC-18005-2",
|
|
9
|
+
"AC-18005-3",
|
|
10
|
+
"AC-18005-4",
|
|
11
|
+
"AC-18005-5",
|
|
12
|
+
"AC-18005-6",
|
|
13
|
+
"AC-18005-7",
|
|
14
|
+
"AC-18005-8"
|
|
15
|
+
],
|
|
16
|
+
"testCases": [
|
|
17
|
+
{
|
|
18
|
+
"id": "TC-239-18005-1-happy",
|
|
19
|
+
"acId": "AC-18005-1",
|
|
20
|
+
"description": "[happy] Given readiness.stages, when the overview sub-view renders, then a stage grid shows each stage as a row and the scopes \"tree\" and \"delta\" as columns, each VerdictGridCell carrying VerdictGridCell.pass, VerdictGridCell.total and VerdictGridCell.state, with VerdictGridCell.failing rendered as a link into the blocking table filtered to that stage.",
|
|
21
|
+
"status": "pending",
|
|
22
|
+
"testPointer": "test/view/readiness-layout.test.js::AC-18005-1 happy: stage grid renders rows x (tree, delta) with pass/total/state and failing-count link"
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"id": "TC-239-18005-2-happy",
|
|
26
|
+
"acId": "AC-18005-2",
|
|
27
|
+
"description": "[happy] Given the Readiness tab, when it renders, then a SubTabStrip offers \"Overview\", \"Questions\", \"Blocking\", \"Coverage\" and \"Trace\", the active key is written into the hash as sub=, and the router restores it on load and after an SSE innerHTML swap of #rcf-live-content.",
|
|
28
|
+
"status": "pending",
|
|
29
|
+
"testPointer": "test/view/readiness-layout.test.js::AC-18005-2 happy: the SubTabStrip offers five keys, activeSub is reflected, and the router restores sub= on load and after an SSE swap"
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"id": "TC-239-18005-3-happy",
|
|
33
|
+
"acId": "AC-18005-3",
|
|
34
|
+
"description": "[happy] Given an unfrozen tree, when the delta block renders, then DeltaCounts.changed, DeltaCounts.added, DeltaCounts.removed, DeltaCounts.briefSince, DeltaCounts.impacted and DeltaCounts.impactedFbs render as numbers and the per-document list with its diff widgets renders only after the reader expands the details element (DeltaCounts.expanded true).",
|
|
35
|
+
"status": "pending",
|
|
36
|
+
"testPointer": "test/view/readiness-layout.test.js::AC-18005-3 happy: delta counts render six numbers; per-document list only after expand"
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"id": "TC-239-18005-4-happy",
|
|
40
|
+
"acId": "AC-18005-4",
|
|
41
|
+
"description": "[happy] Given the profile register is \"engineer\", when the tab renders, then the For-engineers DocRow wrapper is absent and every engineer item (failing ids with why, next action, stage states, coverage counts, decisions outstanding, freeze state) is present in a named table or block of the sub-views.",
|
|
42
|
+
"status": "pending",
|
|
43
|
+
"testPointer": "test/view/readiness-layout.test.js::AC-18005-4 happy: engineer register has no For-engineers DocRow wrapper and every engineer item is present in a named block"
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"id": "TC-239-18005-5-happy",
|
|
47
|
+
"acId": "AC-18005-5",
|
|
48
|
+
"description": "[happy] Given ready-to-build is \"no\", when the freeze block renders, then it names each failing gate in plain words with what resolves it, with no button and no command text; given ready-to-build is \"yes\", it states that the tree can be frozen and what a freeze would record.",
|
|
49
|
+
"status": "pending",
|
|
50
|
+
"testPointer": "test/view/readiness-layout.test.js::AC-18005-5 happy: freeze state words - names failing gates when not ready; names what a freeze records when ready"
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"id": "TC-239-18005-6-edge",
|
|
54
|
+
"acId": "AC-18005-6",
|
|
55
|
+
"description": "[edge] Given a stage acknowledged at the current tree hash, when the grid renders, then VerdictGridCell.state is \"acknowledged\" and the reason shows on hover, read from stages[].state and one reason helper rather than from freezeRecord.gates directly.",
|
|
56
|
+
"status": "pending",
|
|
57
|
+
"testPointer": "test/view/readiness-layout.test.js::AC-18005-6 edge: acknowledged cell state comes from stages[].state and the ack reason via one helper"
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"id": "TC-239-18005-7-mustnot",
|
|
61
|
+
"acId": "AC-18005-7",
|
|
62
|
+
"description": "[must-not] Given embed mode (data-embed=\"1\") and a viewport narrower than 720px, when the Readiness tab renders, then no table forces horizontal page scroll: tables collapse to stacked rows and the SubTabStrip stays inside the panel.",
|
|
63
|
+
"status": "pending",
|
|
64
|
+
"testPointer": "test/view/readiness-layout.test.js::AC-18005-7 must-not: embed + <720px keeps tables stacked and SubTabStrip inside the panel"
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
"id": "TC-239-18005-8-failure",
|
|
68
|
+
"acId": "AC-18005-8",
|
|
69
|
+
"description": "[failure] Given a hash whose sub= value is not a known readiness sub-tab key, when the router runs, then the overview sub-view is activated and the unknown value is dropped from the hash.",
|
|
70
|
+
"status": "pending",
|
|
71
|
+
"testPointer": "test/view/readiness-layout.test.js::AC-18005-8 failure: unknown sub= drops to overview and is removed from the hash"
|
|
72
|
+
}
|
|
73
|
+
],
|
|
74
|
+
"id": "TS-239",
|
|
75
|
+
"usId": "US-18005",
|
|
76
|
+
"title": "US-18005 command page suite (readiness-layout)",
|
|
77
|
+
"status": "draft"
|
|
78
|
+
}
|