rcf-lite 0.30.0 → 0.32.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 +67 -0
- package/blueprints/deploy-cloudflare-workers/contributions/user-stories/deploy-cloudflare-workers-us-12113.json +1 -1
- package/fixtures/canary-manifest.json +9 -9
- package/guidance/define-draft-shapes.md +15 -10
- package/package.json +1 -1
- package/rcf/adrs/adr-4131-gates-bite-ack-recorded-override.json +3 -3
- package/rcf/adrs/adr-4137-standalone-theme-persistence.json +30 -0
- package/rcf/adrs/adr-4138-tree-wide-checks-before-scope-shortcircuit.json +35 -0
- package/rcf/code-nodes/cn-017.json +4 -2
- package/rcf/code-nodes/cn-771.json +15 -0
- package/rcf/code-nodes/cn-772.json +14 -0
- package/rcf/code-nodes/cn-773.json +16 -0
- package/rcf/code-nodes/cn-774.json +20 -0
- package/rcf/code-nodes/cn-775.json +15 -0
- package/rcf/code-nodes/cn-776.json +17 -0
- package/rcf/code-nodes/cn-777.json +21 -0
- package/rcf/code-nodes/cn-778.json +14 -0
- package/rcf/fbs/fbs-004.json +4 -1
- package/rcf/fbs/fbs-201.json +2 -1
- package/rcf/fbs/fbs-202.json +18 -2
- package/rcf/fbs/fbs-203.json +12 -4
- package/rcf/requirements/req-002.json +2 -2
- package/rcf/requirements/req-173.json +2 -2
- package/rcf/requirements/req-174.json +2 -2
- package/rcf/tacs/tac-4122-define-gates.json +7 -2
- package/rcf/tacs/tac-4127-readiness-view.json +3 -2
- package/rcf/test-suites/ts-004.json +82 -2
- package/rcf/test-suites/ts-007.json +1 -1
- package/rcf/test-suites/ts-215.json +64 -1
- package/rcf/test-suites/ts-216.json +18 -2
- package/rcf/test-suites/ts-219.json +10 -2
- package/rcf/test-suites/ts-220.json +18 -2
- package/rcf/test-suites/ts-223.json +24 -2
- package/rcf/test-suites/ts-225.json +10 -2
- package/rcf/test-suites/ts-229.json +49 -3
- package/rcf/test-suites/ts-230.json +26 -2
- package/rcf/test-suites/ts-231.json +16 -1
- package/rcf/test-suites/ts-236.json +44 -0
- package/rcf/user-stories/us-17302.json +36 -1
- package/rcf/user-stories/us-17401.json +11 -1
- package/rcf/user-stories/us-17402.json +6 -1
- package/rcf/user-stories/us-17403.json +11 -1
- package/rcf/user-stories/us-17404.json +16 -1
- package/rcf/user-stories/us-17405.json +7 -2
- package/rcf/user-stories/us-18001.json +6 -1
- package/rcf/user-stories/us-202.json +25 -1
- package/rcf/user-stories/us-205.json +6 -1
- package/rcf/user-stories/us-206.json +25 -4
- package/rcf/user-stories/us-207.json +36 -0
- package/releases/releases.yaml +20 -1
- package/src/cli/create.js +22 -2
- package/src/cli/freeze.js +8 -0
- package/src/cli/ledger.js +96 -4
- package/src/cli/readiness.js +17 -39
- package/src/core/errors/index.js +7 -1
- package/src/core/store/writer.js +181 -13
- package/src/define/interface-paths.js +47 -0
- package/src/define/ledgers.js +86 -7
- package/src/mcp/tools.js +1 -1
- package/src/query/gates.js +431 -163
- package/src/view/html-page.js +43 -13
- package/src/view/live-client.js +18 -10
- package/src/view/page-init.js +149 -8
- package/src/view/style.css +107 -20
- package/src/view/view-index.js +22 -0
package/rcf/fbs/fbs-203.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"createdAt": "2026-10-02T19:00:00Z",
|
|
3
|
-
"updatedAt": "2026-10-
|
|
3
|
+
"updatedAt": "2026-10-04T14:00:00Z",
|
|
4
4
|
"acIds": [
|
|
5
5
|
"AC-204-1",
|
|
6
6
|
"AC-204-2",
|
|
@@ -25,7 +25,14 @@
|
|
|
25
25
|
"AC-206-3",
|
|
26
26
|
"AC-206-4",
|
|
27
27
|
"AC-206-5",
|
|
28
|
-
"AC-206-6"
|
|
28
|
+
"AC-206-6",
|
|
29
|
+
"AC-206-7",
|
|
30
|
+
"AC-206-8",
|
|
31
|
+
"AC-206-9",
|
|
32
|
+
"AC-206-10",
|
|
33
|
+
"AC-205-9",
|
|
34
|
+
"AC-207-1",
|
|
35
|
+
"AC-207-2"
|
|
29
36
|
],
|
|
30
37
|
"fbsId": "FBS-203",
|
|
31
38
|
"prdId": "PRD-001",
|
|
@@ -45,7 +52,8 @@
|
|
|
45
52
|
"adrIds": [
|
|
46
53
|
"ADR-4133-dag-dependency-depth-layout",
|
|
47
54
|
"ADR-4134-index-json-route",
|
|
48
|
-
"ADR-4136-embedding-host-fixture"
|
|
55
|
+
"ADR-4136-embedding-host-fixture",
|
|
56
|
+
"ADR-4137-standalone-theme-persistence"
|
|
49
57
|
]
|
|
50
58
|
},
|
|
51
59
|
"deliverables": [
|
|
@@ -96,5 +104,5 @@
|
|
|
96
104
|
"riskLevel": "low",
|
|
97
105
|
"domain": "reviewSurface",
|
|
98
106
|
"estimatedSize": "large",
|
|
99
|
-
"notes": "Single FBS for the whole viewer UI refresh build stream (ruling 2026-10-02): keeping one FBS avoids a sprawl of near-duplicate FBS entries for the same renderer family. PRs 7 to 9 extended the acIds list under this file as AC-205-*, AC-18002-* and AC-206-* arrived. Status stays `inProgress`
|
|
107
|
+
"notes": "Single FBS for the whole viewer UI refresh build stream (ruling 2026-10-02): keeping one FBS avoids a sprawl of near-duplicate FBS entries for the same renderer family. PRs 7 to 9 extended the acIds list under this file as AC-205-*, AC-18002-* and AC-206-* arrived; the 2026-10-04 amendment (`w-2026-10-04-dave-001`) adds AC-205-9 (SearchButton hover/focus contrast), AC-206-7..10 (standalone theme control + storage ruling per ADR-4137) and AC-207-1..2 (WCAG 2.1 AA contrast audit) under this file. Status stays `inProgress` while the amendment ships. The amendment also adds `packages/rcf-lite/test/view/contrast-aa.test.js` (static WCAG AA audit over `src/view/style.css`), extends `renderPage` in `html-page.js` with `renderThemeControl()` right of the SearchButton (gated on `data-embed=\"1\"`), extends `page-init.js` with `wireThemeControl()` (persistence under `rcf-view:v1:theme`, embed-mode absent, boot precedence `?theme=` -> stored -> auto) and fixes the dark-mode SearchButton hover and focus states plus every AA failure the audit surfaces in `src/view/style.css`."
|
|
100
108
|
}
|
|
@@ -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.",
|
|
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.",
|
|
6
6
|
"category": "functional",
|
|
7
7
|
"domain": "view",
|
|
8
8
|
"priority": "must",
|
|
@@ -16,5 +16,5 @@
|
|
|
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-04T14:00:00.000Z"
|
|
20
20
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"createdAt": "2026-09-24T12:00:00Z",
|
|
3
|
-
"updatedAt": "2026-10-
|
|
3
|
+
"updatedAt": "2026-10-05T18:00:00Z",
|
|
4
4
|
"reqId": "REQ-173",
|
|
5
5
|
"prdId": "PRD-001",
|
|
6
6
|
"title": "Sidecar ledgers under rcf/define/ and the rcf define ledger verb",
|
|
7
|
-
"description": "Four sidecars live under rcf/define/, each one JSON file, each with one numbered sequence for the life of the project (proposal 2026-09-22 v3 section 2.5, 3.2, 8.2). Names and shapes: brief-ledger.json (statements[] kinded from a closed set), decisions-ledger.json (decisions[] in the numbered #241 format), concern-ledger.json (concerns[] with disposition applied or waived), probe-ledger.json (probes[] with severity low, medium, high). A local schema in rcf-lite validates every write until schemas 0.7. Reading a missing ledger file returns an empty ledger so callers can compose without a per-file null check; a malformed file raises a clear error. The rcf define ledger name verb pattern (brief, decisions, concerns, probes; add, resolve, list) is the operator surface. brief add --from <file> splits statements one per non-empty line, mints sequential ids and writes; the intake-scan-against-frozen-statements hook is a named seam this slice leaves for a later one. decisions list prints the #241 numbered format (one decision per item, options with letters, the default, what it blocks). The walker never reads under rcf/define/ so the sidecars stay invisible to every existing tree consumer. Every ledger supports `update <id>` with field patches validated as `add` validates; `resolvedBy` on a brief statement is a closed pointer grammar (REQ-nnn, TAD.entity:<name>, PRD.user:<name>, TAD.system:<name>, TAC-nnnn, omitted:<reason>) validated by D2.",
|
|
7
|
+
"description": "Four sidecars live under rcf/define/, each one JSON file, each with one numbered sequence for the life of the project (proposal 2026-09-22 v3 section 2.5, 3.2, 8.2). Names and shapes: brief-ledger.json (statements[] kinded from a closed set), decisions-ledger.json (decisions[] in the numbered #241 format), concern-ledger.json (concerns[] with disposition applied or waived), probe-ledger.json (probes[] with severity low, medium, high). A local schema in rcf-lite validates every write until schemas 0.7. Reading a missing ledger file returns an empty ledger so callers can compose without a per-file null check; a malformed file raises a clear error. The rcf define ledger name verb pattern (brief, decisions, concerns, probes; add, resolve, list, update) is the operator surface. brief add --from <file> splits statements one per non-empty line, mints sequential ids and writes; the intake-scan-against-frozen-statements hook is a named seam this slice leaves for a later one. decisions list prints the #241 numbered format (one decision per item, options with letters, the default, what it blocks). The walker never reads under rcf/define/ so the sidecars stay invisible to every existing tree consumer. Every ledger supports `update <id>` with field patches validated as `add` validates; `resolvedBy` on a brief statement is a closed pointer grammar (REQ-nnn, TAD.entity:<name>, PRD.user:<name>, TAD.system:<name>, TAC-nnnn, omitted:<reason>) validated by D2. Ruling R1 2026-10-05 (write-back idempotency): the question-set write-back verbs (`rcf define ledger <name> add`, in particular `brief add`, and `rcf define create`) are idempotent by id. Both `add` and `create` take an optional `--id <n>` the harness can carry when it replays a turn; a repeat whose id already exists with identical content exits 0, prints `<ledger>-ledger: unchanged <id>` or `<kind>: unchanged <id>` on stdout and emits `{\"status\":\"unchanged\",\"id\":<n>,...}` under `--json`; a repeat whose id already exists with different content refuses with exit 3 and a message naming the id and the differing field keys (never silently overwrite; `update` is the verb for that). When the write-back payload carries no id (nothing recorded from the earlier turn), the add / create path mints the next id as before; the harness is responsible for threading `--id` back into the replayed verb for idempotency. The create path extends ruling R1 under the PR 292 follow-up (w-2026-10-05-dave-013): pre-follow-up `create --id` always refused on collision with exit 2 and `[error] usage create <kind>: id ${id} is already taken`; post-follow-up the writer compares the proposed body to the on-disk entry (per-kind own-id field, parent linkage, timestamps and the fields the walker loads) and returns the unchanged-vs-conflict split per the same identity rule the add path uses.",
|
|
8
8
|
"category": "functional",
|
|
9
9
|
"domain": "defineLedgers",
|
|
10
10
|
"priority": "must",
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"createdAt": "2026-09-24T14:30:00Z",
|
|
3
|
-
"updatedAt": "2026-10-
|
|
3
|
+
"updatedAt": "2026-10-05T18:00:00Z",
|
|
4
4
|
"reqId": "REQ-174",
|
|
5
5
|
"prdId": "PRD-001",
|
|
6
6
|
"title": "DEFINE stage gates D1..D8 as pure check functions",
|
|
7
|
-
"description": "rcf-lite gains src/query/gates.js with one check function per stage D1..D8. Each function takes (tree, ledgers, profile, scope) and returns { stage, gate, state, checks[] } where every check is { name, ok, over: 'delta'|'tree', pass, total, failing: [{ id, why }] }. Stage state is 'passed' | 'failing' | 'acknowledged' (only for D3, D5, D6 and only when the freeze record acknowledges that gate at the current hash) | 'notApplicable' (the stage decides that itself from the scope per the proposal 2026-09-22 v3 section 3.2 rules and the summary table in section 2.7). Blocking in 0.29.0: D1 brief, D2 skeleton, D4 floors (every REQ in scope has a US; every US in scope has a testable AC, a failure AC and a must-not AC, or a reasoned opt-out per class; tacIds non-empty and resolving; no scaffold placeholder), D7 decisions, D8 freeze (prior gates passed or acknowledged at the current hash, every AC owned by exactly one FBS, queue head actionable and not a placeholder, validate clean; preflight and ui-baseline presence as the section 3.2 rules specify). Warn-with-ack in 0.29.0: D3, D5, D6 build only the cheap data-backed checks (D3: every TAC in scope has at least one interface and each interface kind is in the closed vocabulary of section 5.2; D5: TAD securityArchitecture present when any auth or httpApi REQ exists, operationalConcerns present when deployed-scope ACs exist, concern-ledger entries applied or waived where they exist; D6: validate clean tree-wide plus open probe-ledger count). The D3 template parser, entity join, D5 catalogue, D6 contradiction and unsatisfiable scans, and the probe runner are 0.30 and left as named seams. AC class is a bracketed prefix on AC description ('[failure] ...', '[must-not] ...', '[happy]', '[edge]', '[non-functional]', decision 6); opt-out per class reuses the existing manifest.baselineAcOptOuts[] array with a baselineKey of the shape 'defineD4:failure' or 'defineD4:mustNot' (recorded in ADR-4122). No storage state, no 'stale' state. ADR-4126 (0.29.0) amendment: every gate check declares an owning persona, `productOwner` or `engineer`, and a one-sentence `question` in that persona’s register. A check that would need both personas is split so every check is homogeneous: `skeleton:reqFields` becomes `skeleton:reqIntent` (productOwner: description + domain) + `skeleton:reqShape` (engineer: shapeClassification.shapes); `decisions:allAnswered` becomes `decisions:wellFormed` (productOwner: enumerated per #241 format) + `decisions:allAnswered` (engineer: zero open). A new D3 check `shapes:draftSettled` fails every interface whose description still carries the leading `[draft]` marker so an L1-pre-populated interface stays distinguishable from one the engineer has settled. 0.30.0 PR 5 (ADR-4131) amendment: D3, D5 and D6 run the substantive checks of proposal 3.2 and exit 4 under `--check`; `--ack` remains their recorded override. D4 reports closed sets and `ownerRef` resolution as findings. D2 validates `resolvedBy` pointers and the standards citation. The three D3 bite checks land in this PR: `shapes:templateMarkers` (per-kind marker presence on `interfaces[].description`, over delta, ids `<tacId>:<name>`, why names the missing marker, drafts included), `shapes:entityJoin` (every `coreEntities[].name` named by exactly one `recordShape` tree-wide, ids `TAD.entity:<name>` with 'no record shape' or 'N record shapes'), `shapes:pathsResolve` (any `path:`-like token in an interface description resolves against `resolvedPaths` in the stage context or the description carries `authoredAt: D3`, over delta). The CLI readiness `--check shapes` exits 4 on an unacknowledged D3 failure and 0 when acked at the current hash; `ackable(stage)` returns true for D3, D5, D6 and false for D1, D2, D4, D7, D8; `--ack` on D1, D2, D4, D7 or D8 exits 2 unchanged.",
|
|
7
|
+
"description": "rcf-lite gains src/query/gates.js with one check function per stage D1..D8. Each function takes (tree, ledgers, profile, scope) and returns { stage, gate, state, checks[] } where every check is { name, ok, over: 'delta'|'tree', pass, total, failing: [{ id, why }] }. Stage state is 'passed' | 'failing' | 'acknowledged' (only for D3, D5, D6 and only when the freeze record acknowledges that gate at the current hash) | 'notApplicable' (the stage decides that itself from the scope per the proposal 2026-09-22 v3 section 3.2 rules and the summary table in section 2.7). Blocking in 0.29.0: D1 brief, D2 skeleton, D4 floors (every REQ in scope has a US; every US in scope has a testable AC, a failure AC and a must-not AC, or a reasoned opt-out per class; tacIds non-empty and resolving; no scaffold placeholder), D7 decisions, D8 freeze (prior gates passed or acknowledged at the current hash, every AC owned by exactly one FBS, queue head actionable and not a placeholder, validate clean; preflight and ui-baseline presence as the section 3.2 rules specify). Warn-with-ack in 0.29.0: D3, D5, D6 build only the cheap data-backed checks (D3: every TAC in scope has at least one interface and each interface kind is in the closed vocabulary of section 5.2; D5: TAD securityArchitecture present when any auth or httpApi REQ exists, operationalConcerns present when deployed-scope ACs exist, concern-ledger entries applied or waived where they exist; D6: validate clean tree-wide plus open probe-ledger count). The D3 template parser, entity join, D5 catalogue, D6 contradiction and unsatisfiable scans, and the probe runner are 0.30 and left as named seams. AC class is a bracketed prefix on AC description ('[failure] ...', '[must-not] ...', '[happy]', '[edge]', '[non-functional]', decision 6); opt-out per class reuses the existing manifest.baselineAcOptOuts[] array with a baselineKey of the shape 'defineD4:failure' or 'defineD4:mustNot' (recorded in ADR-4122). No storage state, no 'stale' state. ADR-4126 (0.29.0) amendment: every gate check declares an owning persona, `productOwner` or `engineer`, and a one-sentence `question` in that persona’s register. A check that would need both personas is split so every check is homogeneous: `skeleton:reqFields` becomes `skeleton:reqIntent` (productOwner: description + domain) + `skeleton:reqShape` (engineer: shapeClassification.shapes); `decisions:allAnswered` becomes `decisions:wellFormed` (productOwner: enumerated per #241 format) + `decisions:allAnswered` (engineer: zero open). A new D3 check `shapes:draftSettled` fails every interface whose description still carries the leading `[draft]` marker so an L1-pre-populated interface stays distinguishable from one the engineer has settled. 0.30.0 PR 5 (ADR-4131) amendment: D3, D5 and D6 run the substantive checks of proposal 3.2 and exit 4 under `--check`; `--ack` remains their recorded override. D4 reports closed sets and `ownerRef` resolution as findings. D2 validates `resolvedBy` pointers and the standards citation. The three D3 bite checks land in this PR: `shapes:templateMarkers` (per-kind marker presence on `interfaces[].description`, over delta, ids `<tacId>:<name>`, why names the missing marker, drafts included), `shapes:entityJoin` (every `coreEntities[].name` named by exactly one `recordShape` tree-wide, ids `TAD.entity:<name>` with 'no record shape' or 'N record shapes'), `shapes:pathsResolve` (any `path:`-like token in an interface description resolves against `resolvedPaths` in the stage context or the description carries `authoredAt: D3`, over delta). The CLI readiness `--check shapes` exits 4 on an unacknowledged D3 failure and 0 when acked at the current hash; `ackable(stage)` returns true for D3, D5, D6 and false for D1, D2, D4, D7, D8; `--ack` on D1, D2, D4, D7 or D8 exits 2 unchanged. DEFINE step 3 rulings R2, R5, R6, R7, R8 2026-10-05 (w-2026-10-05-dave-001): `shapes:draftSettled` is a tree-wide check that runs regardless of the D3 scope's own early-return (R2); `shapes:entityJoin` is tree-wide by definition and runs before any `notApplicable` short-circuit via the shared helper ADR-4138 lands (R5); `extractInterfacePathTokens` honours a short whitelist of known bare repo names so `Dockerfile`, `Makefile`, `LICENSE`, `Procfile`, `Containerfile`, `Justfile`, `Rakefile`, `Gemfile` and `CODEOWNERS` are checked by `shapes:pathsResolve` (R6; the slash-or-extension rule stays for everything else, and the whitelist is exported for tests); `skeleton:standardsCited` runs tree-wide regardless of the D2 scope's own early-return and shares the ADR-4138 helper (R7); and for `standards:<pack>` concern-ledger entries both `applied` and `waived` dispositions satisfy `skeleton:standardsCited` alongside a citation (R8; the check question reads 'Every registered standards pack is cited, applied or waived'). DEFINE step 3 ruling R13 2026-10-05 (w-2026-10-05-dave-013, PR 292 follow-up): the tree-wide-before-scope principle covers every tree-wide check, not only the three R2/R5/R7 named. The ADR-4138 helper is extended to govern D2 `skeleton:deployAdr` (exactly one Deploy target or Deploy deferral ADR exists; a title-prefix scan over the whole `tree.adrs`), D5 `crosscut:securityArchitecture` (TAD.securityArchitecture non-empty when any REQ carries shape `auth` or `httpApi` tree-wide) and D5 `crosscut:operationalConcerns` (TAD.operationalConcerns non-empty when any AC carries `[deployed]` tree-wide). D4 and D6 are unchanged. The `treeWideFailureEnvelope` helper now folds its warn-with-ack acknowledgement through `foldState` so one implementation owns the ack rule and the failing envelope carries no stale `notApplicable` reason text.",
|
|
8
8
|
"category": "functional",
|
|
9
9
|
"domain": "defineDetection",
|
|
10
10
|
"priority": "must",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"createdAt": "2026-09-24T14:30:00Z",
|
|
3
|
-
"updatedAt": "2026-10-
|
|
3
|
+
"updatedAt": "2026-10-05T12:00:00Z",
|
|
4
4
|
"tacId": "TAC-4122-define-gates",
|
|
5
5
|
"prdId": "PRD-001",
|
|
6
6
|
"tadId": "TAD-001",
|
|
@@ -35,7 +35,12 @@
|
|
|
35
35
|
"`consistency:contradictions` (0.30.0 PR 7, spec section 4 row 'D6 scans and the injectable probe runner'): engineer, over delta. Two ACs on one story sharing a `when` clause with a negated `then` fail the story; failing ids name the story and both AC ids. The named false-positive guard: a negation inside a double-quoted substring in a `then` does not fail the story (the shared quoted-substring guard with D4).",
|
|
36
36
|
"`consistency:unsatisfiable` (0.30.0 PR 7): engineer, over delta. A `then` naming a field that no `recordShape` defines fails the AC; a field defined in a `[draft]` recordShape counts as defined. Failing ids `<acId>:<field>`.",
|
|
37
37
|
"`consistency:duplicates` (0.30.0 PR 7): engineer, over tree. Identical AC descriptions across stories fail both ACs with id `<acId>` and why 'duplicate description'. The comparison trims leading whitespace and the leading `[class]` marker.",
|
|
38
|
-
"`consistency:orphanInterfaces` (0.30.0 PR 7): engineer, over tree. An interface on a TAC that no AC's `ownerRef` points at and that no REQ's `deliveredBy` reaches fails with id `<tacId>:<name>` and why 'no AC ownerRef and no REQ deliveredBy reaches it'. Shares the `interfaces[<name>]` pointer grammar with D4 `stories:ownerRefResolves`."
|
|
38
|
+
"`consistency:orphanInterfaces` (0.30.0 PR 7): engineer, over tree. An interface on a TAC that no AC's `ownerRef` points at and that no REQ's `deliveredBy` reaches fails with id `<tacId>:<name>` and why 'no AC ownerRef and no REQ deliveredBy reaches it'. Shares the `interfaces[<name>]` pointer grammar with D4 `stories:ownerRefResolves`.",
|
|
39
|
+
"DEFINE step 3 ruling R2 2026-10-05 (w-2026-10-05-dave-001): `shapes:draftSettled` is tree-wide (a `[draft]` anywhere in the tree is unfinished work); the check runs through the shared tree-wide-before-scope helper ADR-4138 lands, so a narrowed D3 scope that excludes every TAC and shaped REQ still reports a `[draft]` core entity. `shapes:templateMarkers`, `shapes:entityJoin` (R5) and `shapes:pathsResolve` keep their spec section 4 `over` labels (delta, tree, delta respectively).",
|
|
40
|
+
"DEFINE step 3 ruling R5 2026-10-05: `shapes:entityJoin` is tree-wide by definition and runs before any scope-driven `notApplicable` short-circuit (ADR-4138's `evaluateTreeWideChecks` helper). D4, D5 and D6 inherited the same ordering shape in PRs 6 and 7; the helper governs every stage with a tree-wide check (`shapes:draftSettled`, `shapes:entityJoin`, `skeleton:standardsCited`). A narrowed scope that excludes every recordShape still reports an entityJoin finding.",
|
|
41
|
+
"DEFINE step 3 ruling R6 2026-10-05: `extractInterfacePathTokens` whitelists the usual bare repo names (`Dockerfile`, `Makefile`, `LICENSE`, `Procfile`, `Containerfile`, `Justfile`, `Rakefile`, `Gemfile`, `CODEOWNERS`) so `shapes:pathsResolve` checks a `path: Dockerfile` token. The slash-or-extension rule stays for everything else; the whitelist is exported from `gates.js` for the test.",
|
|
42
|
+
"DEFINE step 3 ruling R7 2026-10-05: `skeleton:standardsCited` runs tree-wide regardless of the D2 scope's own early-return; the check sits inside D2's `checks[]` under the ADR-4138 helper, so a narrowed D2 scope that excludes every REQ/PRD/TAD/brief statement still reports an uncited pack.",
|
|
43
|
+
"DEFINE step 3 ruling R8 2026-10-05: for `standards:<pack>` concern-ledger entries, both `applied` and `waived` dispositions satisfy `skeleton:standardsCited` alongside a citation. The CHECK_QUESTION heading reads 'Every registered standards pack is cited, applied or waived' (spec section 4 row 'Standards-ingestion check' amended)."
|
|
39
44
|
],
|
|
40
45
|
"internalStructure": "Every stage function follows the same shape: 1) decide notApplicable per section 3.2 and return { state: 'notApplicable' } with a single-check summary; 2) build checks[] as a list of { name, ok, over, pass, total, failing: [{ id, why }] }; 3) fold to state: 'passed' if every ok is true; 'failing' otherwise, unless the stage is D3/D5/D6 AND freeze.gates[<gate>].state === 'acknowledged' AND freeze.gates[<gate>].at.hash === currentTreeHash, in which case state is 'acknowledged'. Blocking-vs-warn is a property of the stage, not of the state: D3/D5/D6 use the acknowledged fold, D1/D2/D4/D7/D8 do not. The caller (readiness) folds the array of stage results into freezeable and nextAction.",
|
|
41
46
|
"interfaces": [
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"createdAt": "2026-10-01T18:00:00Z",
|
|
3
|
-
"updatedAt": "2026-10-
|
|
3
|
+
"updatedAt": "2026-10-06T12:00:00Z",
|
|
4
4
|
"tacId": "TAC-4127-readiness-view",
|
|
5
5
|
"prdId": "PRD-001",
|
|
6
6
|
"tadId": "TAD-001",
|
|
@@ -15,7 +15,8 @@
|
|
|
15
15
|
"src/view/components/findings-list.js: findingsList({ heading, count, items }) returns `<div class=\"rcf-findings-list\"><h4>{heading} <span class=\"rcf-findings-list__count\">{count}</span></h4><ul>...<li><a href={anchor}>{id}</a>: {why}</li>...</ul></div>` with ids capped at 20 and a `... N more suppressed` line beyond.",
|
|
16
16
|
"src/view/components/diff.js: diff(before, after) returns a two-column rendering of two document bodies for the delta list; criterion-level before-and-after is deferred per ADR-4127.",
|
|
17
17
|
"src/view/html-page.js: Readiness button and tabpanel are the first entries; the former Overview button and panel are relabelled PRD; the data-tab=overview and id=tab-overview identifiers are preserved so existing hash anchors still resolve; the inline-script TABS array gains 'readiness' as the first entry (default active tab) and keeps the existing four entries in order.",
|
|
18
|
-
"src/view/index.js: renderModelToPage loads the freeze record, ledgers, test pointers and profile text once, invokes computeReadiness via the pure src/query/ seam, and threads the result into the model so renderPage and renderContent carry one computed object; the SSE tree-update broadcast rewalks and recomputes on every change under rcf/."
|
|
18
|
+
"src/view/index.js: renderModelToPage loads the freeze record, ledgers, test pointers and profile text once, invokes computeReadiness via the pure src/query/ seam, and threads the result into the model so renderPage and renderContent carry one computed object; the SSE tree-update broadcast rewalks and recomputes on every change under rcf/.",
|
|
19
|
+
"src/view/live-client.js: resyncTabsAfterSwap derives the list of tabs from the server-rendered nav.tabs (every [role=tab][data-tab] under it) rather than carrying a parallel array. The SSE swap re-emits every panel with the Phase 3.6 hidden-by-default layout; the resync reads the aria-selected button from the surviving header and makes exactly that panel visible for every tab the server rendered, Readiness included (AC-18001-8). The overview fallback stays for the genuinely-unknown-or-missing selection case."
|
|
19
20
|
],
|
|
20
21
|
"internalStructure": "readiness.js is a sequence of eleven small block builders calling the three shared components; each block consumes exactly one top-level field of the readiness result so a wire-level JSON diff ties to a visible block. The register ordering is picked once at the top via pickRegister (same helper the CLI uses) and threaded down. Hash anchors are built with the same `#<docId>` convention the existing tabs use so blocker-id links open the right tab and expand the right <details> through the existing resolveHash routine.",
|
|
21
22
|
"interfaces": [
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"createdAt": "2026-07-29T12:57:18.038Z",
|
|
3
|
-
"updatedAt": "2026-
|
|
3
|
+
"updatedAt": "2026-10-06T10:12:36.226Z",
|
|
4
4
|
"purpose": "Verify documents render as readable curated fields with working inter-document links. AC-202-1 is pending: its static-files-no-server clause predates the Phase 3.8 server-only view (see test-suites/PENDING.md).",
|
|
5
5
|
"testLevel": "unit",
|
|
6
6
|
"acIds": [
|
|
7
7
|
"AC-202-2",
|
|
8
|
-
"AC-202-3"
|
|
8
|
+
"AC-202-3",
|
|
9
|
+
"AC-202-4",
|
|
10
|
+
"AC-202-5",
|
|
11
|
+
"AC-202-6"
|
|
9
12
|
],
|
|
10
13
|
"id": "TS-004",
|
|
11
14
|
"usId": "US-202",
|
|
@@ -38,6 +41,83 @@
|
|
|
38
41
|
"description": "the view serves from a local server process and never writes files to disk",
|
|
39
42
|
"status": "pending",
|
|
40
43
|
"testPointer": "test/view/cli.test.js::rcf audit view never writes any files to disk (regression against static mode)"
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"id": "TC-004-tabs-cannot-shrink",
|
|
47
|
+
"acId": "AC-202-4",
|
|
48
|
+
"description": "style.css nav.tabs has flex-shrink: 0 and no min-width: 0, so the tablist never clips the Build tab under a long project name",
|
|
49
|
+
"status": "passing",
|
|
50
|
+
"testPointer": "test/view/shell-header-layout.test.js::AC-202-4: nav.tabs cannot shrink below its intrinsic width"
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"id": "TC-004-tools-cannot-shrink",
|
|
54
|
+
"acId": "AC-202-4",
|
|
55
|
+
"description": "style.css .tools has flex-shrink: 0 so the Find button and theme control never shrink into the tablist",
|
|
56
|
+
"status": "passing",
|
|
57
|
+
"testPointer": "test/view/shell-header-layout.test.js::AC-202-4: .tools cannot shrink below its intrinsic width"
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"id": "TC-004-product-yields-first",
|
|
61
|
+
"acId": "AC-202-4",
|
|
62
|
+
"description": "style.css .product has min-width: 0 so it yields to the tablist and tools before clipping anything",
|
|
63
|
+
"status": "passing",
|
|
64
|
+
"testPointer": "test/view/shell-header-layout.test.js::AC-202-4: .product yields first via min-width:0"
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
"id": "TC-004-name-min-width-zero",
|
|
68
|
+
"acId": "AC-202-4",
|
|
69
|
+
"description": "style.css .product .name has min-width: 0 so text-overflow: ellipsis triggers inside the flex .product",
|
|
70
|
+
"status": "passing",
|
|
71
|
+
"testPointer": "test/view/shell-header-layout.test.js::AC-202-4: .product .name has min-width:0 so the ellipsis triggers"
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
"id": "TC-004-name-title-attribute",
|
|
75
|
+
"acId": "AC-202-5",
|
|
76
|
+
"description": "renderPage emits a title=\"<full name>\" attribute on .product .name so hover reveals the whole name under ellipsis",
|
|
77
|
+
"status": "passing",
|
|
78
|
+
"testPointer": "test/view/shell-header-layout.test.js::AC-202-5: renderPage emits title=\"<full name>\" on .product .name"
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
"id": "TC-004-name-title-escaped",
|
|
82
|
+
"acId": "AC-202-5",
|
|
83
|
+
"description": "the title attribute shares the escapeHtml path with the inner text so a projectName of \"<script>\" renders as title=\"<script>\"",
|
|
84
|
+
"status": "passing",
|
|
85
|
+
"testPointer": "test/view/shell-header-layout.test.js::AC-202-5: the title attribute is HTML-escaped alongside the body"
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
"id": "TC-004-name-title-absent-on-collapse",
|
|
89
|
+
"acId": "AC-202-5",
|
|
90
|
+
"description": "no title attribute is emitted when the product block collapses (no projectName)",
|
|
91
|
+
"status": "passing",
|
|
92
|
+
"testPointer": "test/view/shell-header-layout.test.js::AC-202-5: no title attribute when the product block collapses"
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
"id": "TC-004-prd-productname-wins",
|
|
96
|
+
"acId": "AC-202-6",
|
|
97
|
+
"description": "resolveProductHeader prefers prd.productName over manifest.projectName when both are set",
|
|
98
|
+
"status": "passing",
|
|
99
|
+
"testPointer": "test/view/product-name-precedence.test.js::AC-202-6: prd.productName wins over manifest.projectName when both are set"
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
"id": "TC-004-manifest-fallback",
|
|
103
|
+
"acId": "AC-202-6",
|
|
104
|
+
"description": "resolveProductHeader falls back to manifest.projectName when the PRD carries no productName",
|
|
105
|
+
"status": "passing",
|
|
106
|
+
"testPointer": "test/view/product-name-precedence.test.js::AC-202-6: manifest.projectName is the first fallback when PRD has no productName"
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
"id": "TC-004-prd-producttitle-fallback",
|
|
110
|
+
"acId": "AC-202-6",
|
|
111
|
+
"description": "resolveProductHeader falls back to prd.productTitle when neither productName nor manifest is set",
|
|
112
|
+
"status": "passing",
|
|
113
|
+
"testPointer": "test/view/product-name-precedence.test.js::AC-202-6: prd.productTitle is the last fallback (brief-stage trees without productName or manifest)"
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
"id": "TC-004-render-reflects-precedence",
|
|
117
|
+
"acId": "AC-202-6",
|
|
118
|
+
"description": "the renderPage DOM reflects the flipped precedence; the manifest value does not reach the header slice when prd.productName is set",
|
|
119
|
+
"status": "passing",
|
|
120
|
+
"testPointer": "test/view/product-name-precedence.test.js::AC-202-6: renderPage reflects the flipped precedence in the DOM"
|
|
41
121
|
}
|
|
42
122
|
],
|
|
43
123
|
"status": "draft"
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"acId": "AC-302-2",
|
|
16
16
|
"description": "create with a conflicting id returns a clear conflict error and writes nothing",
|
|
17
17
|
"status": "pending",
|
|
18
|
-
"testPointer": "test/core/store/writer.test.js::createDocument refuses on id collision (exit
|
|
18
|
+
"testPointer": "test/core/store/writer.test.js::createDocument refuses on id collision with different content (exit 3 conflict) and writes nothing (AC-302-2 / R1 extension 2026-10-05)"
|
|
19
19
|
},
|
|
20
20
|
{
|
|
21
21
|
"id": "TC-007-create-writes-validating-child",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"createdAt": "2026-09-24T12:00:00Z",
|
|
3
|
-
"updatedAt": "2026-10-
|
|
3
|
+
"updatedAt": "2026-10-05T19:00:00Z",
|
|
4
4
|
"purpose": "Cover the four sidecar ledgers, the rcf define ledger CLI (add / resolve / list with --json) and the walker-invisibility invariant on rcf/define/ (AC-17301-1..4 on US-17301), the update subverb and the closed resolvedBy pointer grammar (AC-17302-1..6 on US-17302), the statement-file markers (AC-18701-1..6 on US-18701) and the scan wiring (AC-18702-1..6 on US-18702).",
|
|
5
5
|
"testLevel": "integration",
|
|
6
6
|
"acIds": [
|
|
@@ -14,6 +14,13 @@
|
|
|
14
14
|
"AC-17302-4",
|
|
15
15
|
"AC-17302-5",
|
|
16
16
|
"AC-17302-6",
|
|
17
|
+
"AC-17302-7",
|
|
18
|
+
"AC-17302-8",
|
|
19
|
+
"AC-17302-9",
|
|
20
|
+
"AC-17302-10",
|
|
21
|
+
"AC-17302-11",
|
|
22
|
+
"AC-17302-12",
|
|
23
|
+
"AC-17302-13",
|
|
17
24
|
"AC-18701-1",
|
|
18
25
|
"AC-18701-2",
|
|
19
26
|
"AC-18701-3",
|
|
@@ -205,6 +212,62 @@
|
|
|
205
212
|
"description": "brief add --text runs no scan and appends no openQuestion statement.",
|
|
206
213
|
"status": "pending",
|
|
207
214
|
"testPointer": "test/cli/ledger.test.js::ledger CLI (AC-18702-6): --text runs no scan and appends no openQuestion"
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
"id": "TC-215-r1-add-same-id-same-content-unchanged",
|
|
218
|
+
"acId": "AC-17302-7",
|
|
219
|
+
"description": "brief add --id 3 with identical content on a ledger whose entry 3 already matches exits 0 and prints 'unchanged'; --json emits {status:unchanged,id:3}; the ledger is not rewritten.",
|
|
220
|
+
"status": "pending",
|
|
221
|
+
"testPointer": "test/cli/ledger.test.js::ledger CLI (R1, AC-17302-7): add --id on same-content is unchanged exit 0"
|
|
222
|
+
},
|
|
223
|
+
{
|
|
224
|
+
"id": "TC-215-r1-add-same-id-diff-content-exit-3",
|
|
225
|
+
"acId": "AC-17302-8",
|
|
226
|
+
"description": "brief add --id 3 with different content exits 3; stderr names the id and the differing fields; the ledger is not rewritten.",
|
|
227
|
+
"status": "pending",
|
|
228
|
+
"testPointer": "test/cli/ledger.test.js::ledger CLI (R1, AC-17302-8): add --id on different-content exits 3 naming fields"
|
|
229
|
+
},
|
|
230
|
+
{
|
|
231
|
+
"id": "TC-215-r1-add-no-id-mints-next",
|
|
232
|
+
"acId": "AC-17302-9",
|
|
233
|
+
"description": "brief add --text with no --id mints the next id (idempotency opt-in is id-carried; the harness threads --id back on replay).",
|
|
234
|
+
"status": "pending",
|
|
235
|
+
"testPointer": "test/cli/ledger.test.js::ledger CLI (R1, AC-17302-9): add without --id mints next id"
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
"id": "TC-215-r1-create-ac-id-unchanged-and-conflict",
|
|
239
|
+
"acId": "AC-17302-10",
|
|
240
|
+
"description": "rcf define create ac --parent US-101 --id AC-101-1 replayed with identical content exits 0 printing 'AC-101-1: unchanged (rcf/user-stories/us-101.json)' and leaves the US file byte-identical; the same verb with a different --description exits 3 naming AC-101-1 and description and leaves the file byte-identical.",
|
|
241
|
+
"status": "pending",
|
|
242
|
+
"testPointer": "test/cli/create.test.js::create CLI (R1 extension, AC-17302-10): create ac --id replay is unchanged exit 0, different content exits 3"
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
"id": "TC-215-r1-create-tc-id-unchanged-and-conflict",
|
|
246
|
+
"acId": "AC-17302-11",
|
|
247
|
+
"description": "rcf define create tc --id replayed with identical content exits 0 printing the unchanged line and leaves the TS file byte-identical; a different --description exits 3 naming description; a derived-slug collision without --id still exits 2.",
|
|
248
|
+
"status": "pending",
|
|
249
|
+
"testPointer": "test/cli/create.test.js::create CLI (R1 extension, AC-17302-11): create tc --id replay is unchanged exit 0, different content exits 3"
|
|
250
|
+
},
|
|
251
|
+
{
|
|
252
|
+
"id": "TC-215-r1-create-cn-id-unchanged-and-conflict",
|
|
253
|
+
"acId": "AC-17302-12",
|
|
254
|
+
"description": "rcf define create cn --id replayed with identical content exits 0 printing the unchanged line and leaves the CN file byte-identical; a different --path exits 3 naming path.",
|
|
255
|
+
"status": "pending",
|
|
256
|
+
"testPointer": "test/cli/create.test.js::create CLI (R1 extension, AC-17302-12): create cn --id replay is unchanged exit 0, different content exits 3"
|
|
257
|
+
},
|
|
258
|
+
{
|
|
259
|
+
"id": "TC-215-r1-create-req-verbatim-replay-unchanged",
|
|
260
|
+
"acId": "AC-17302-13",
|
|
261
|
+
"description": "rcf define create req --id REQ-050 replayed verbatim after the classifier stamped shapeClassification exits 0 printing the unchanged line; a different --description exits 3 naming description.",
|
|
262
|
+
"status": "pending",
|
|
263
|
+
"testPointer": "test/cli/create.test.js::create CLI (R1 extension, AC-17302-13): create req --id verbatim replay is unchanged despite classifier stamp"
|
|
264
|
+
},
|
|
265
|
+
{
|
|
266
|
+
"id": "TC-215-r1-create-tac-id-unchanged-and-conflict",
|
|
267
|
+
"acId": "AC-17302-13",
|
|
268
|
+
"description": "rcf define create tac --id replayed with identical content exits 0 printing the unchanged line; a different --purpose exits 3 naming purpose (document-kind path, no post-create side effect).",
|
|
269
|
+
"status": "pending",
|
|
270
|
+
"testPointer": "test/cli/create.test.js::create CLI (R1 extension, AC-17302-13): create tac --id replay is unchanged exit 0, different content exits 3"
|
|
208
271
|
}
|
|
209
272
|
],
|
|
210
273
|
"status": "draft"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"createdAt": "2026-09-24T14:30:00Z",
|
|
3
|
-
"updatedAt": "2026-10-
|
|
3
|
+
"updatedAt": "2026-10-05T18:00:00Z",
|
|
4
4
|
"purpose": "Cover the DEFINE stage-gate check functions D1..D8 (AC-17401-1..8) with unit tests over hand-built TreeModel and ledger fixtures.",
|
|
5
5
|
"testLevel": "unit",
|
|
6
6
|
"acIds": [
|
|
@@ -13,7 +13,9 @@
|
|
|
13
13
|
"AC-17401-7",
|
|
14
14
|
"AC-17401-8",
|
|
15
15
|
"AC-17401-9",
|
|
16
|
-
"AC-17401-10"
|
|
16
|
+
"AC-17401-10",
|
|
17
|
+
"AC-17401-11",
|
|
18
|
+
"AC-17401-12"
|
|
17
19
|
],
|
|
18
20
|
"id": "TS-216",
|
|
19
21
|
"usId": "US-17401",
|
|
@@ -88,6 +90,20 @@
|
|
|
88
90
|
"description": "IDENTITY_TEMPLATE carries a '## Surface' section between '## Register' and '## Project-scoped notes' naming viewer/runningApp/prDiff and seeded to 'prDiff'; writeIdentityTemplate on a fresh dir seeds a profile that satisfies checkD1Brief surface markers; an existing profile.md is left byte-identical (slice-1 'kept' contract).",
|
|
89
91
|
"status": "pending",
|
|
90
92
|
"testPointer": "test/setup/identity-register.test.js::IDENTITY_TEMPLATE carries a ## Surface heading between ## Register and ## Project-scoped notes"
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
"id": "TC-216-r13-crosscut-security-tree-wide",
|
|
96
|
+
"acId": "AC-17401-11",
|
|
97
|
+
"description": "A D5 scope narrowed so no REQ is in scope but the tree carries an auth or httpApi REQ with TAD.securityArchitecture empty still fails crosscut:securityArchitecture; stage state is failing (not notApplicable) via the ADR-4138 shared helper.",
|
|
98
|
+
"status": "pending",
|
|
99
|
+
"testPointer": "test/query/gates.test.js::gates (R13, AC-17401-11): crosscut:securityArchitecture runs tree-wide under narrowed D5 scope"
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
"id": "TC-216-r13-crosscut-operational-tree-wide",
|
|
103
|
+
"acId": "AC-17401-12",
|
|
104
|
+
"description": "A D5 scope narrowed so no REQ is in scope but the tree carries an AC with the '[deployed]' marker and TAD.operationalConcerns empty still fails crosscut:operationalConcerns; stage state is failing (not notApplicable) via the ADR-4138 shared helper.",
|
|
105
|
+
"status": "pending",
|
|
106
|
+
"testPointer": "test/query/gates.test.js::gates (R13, AC-17401-12): crosscut:operationalConcerns runs tree-wide under narrowed D5 scope"
|
|
91
107
|
}
|
|
92
108
|
],
|
|
93
109
|
"status": "draft"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"createdAt": "2026-10-01T14:30:00Z",
|
|
3
|
-
"updatedAt": "2026-10-
|
|
3
|
+
"updatedAt": "2026-10-05T18:00:00Z",
|
|
4
4
|
"purpose": "Cover US-17402: every entry in stages[].checks[] carries persona (productOwner | engineer) and a non-empty question string; CHECK_PERSONA / CHECK_QUESTION / STAGE_FALLBACK_PERSONA maps are total; the notApplicable placeholder uses the stage fallback (ADR-4126).",
|
|
5
5
|
"testLevel": "unit",
|
|
6
6
|
"acIds": [
|
|
@@ -10,7 +10,8 @@
|
|
|
10
10
|
"AC-17402-4",
|
|
11
11
|
"AC-17402-5",
|
|
12
12
|
"AC-17402-6",
|
|
13
|
-
"AC-17402-7"
|
|
13
|
+
"AC-17402-7",
|
|
14
|
+
"AC-17402-8"
|
|
14
15
|
],
|
|
15
16
|
"id": "TS-219",
|
|
16
17
|
"usId": "US-17402",
|
|
@@ -64,6 +65,13 @@
|
|
|
64
65
|
"description": "A notApplicable stage emits one stage:<D>:scope placeholder check with ok true and persona equal to STAGE_FALLBACK_PERSONA[D].",
|
|
65
66
|
"status": "pending",
|
|
66
67
|
"testPointer": "test/query/gates.test.js::gates (ADR-4126, AC-17402-7): notApplicable placeholder carries stage fallback persona and ok true"
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
"id": "TC-219-r13-deploy-adr-tree-wide",
|
|
71
|
+
"acId": "AC-17402-8",
|
|
72
|
+
"description": "A D2 scope narrowed so no REQ, PRD, TAD or resolving brief statement is in scope but no Deploy ADR exists tree-wide still fails skeleton:deployAdr; stage state is failing (not notApplicable) via the ADR-4138 shared helper.",
|
|
73
|
+
"status": "pending",
|
|
74
|
+
"testPointer": "test/query/gates.test.js::gates (R13, AC-17402-8): skeleton:deployAdr runs tree-wide under narrowed D2 scope"
|
|
67
75
|
}
|
|
68
76
|
],
|
|
69
77
|
"status": "draft"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"createdAt": "2026-10-01T14:30:00Z",
|
|
3
|
-
"updatedAt": "2026-10-
|
|
3
|
+
"updatedAt": "2026-10-05T18:00:00Z",
|
|
4
4
|
"purpose": "Cover US-17403: the skeleton:reqFields split into reqIntent + reqShape, the decisions:allAnswered split into wellFormed + allAnswered, and the new D3 shapes:draftSettled check for interface descriptions carrying the [draft] marker (ADR-4126).",
|
|
5
5
|
"testLevel": "unit",
|
|
6
6
|
"acIds": [
|
|
@@ -11,7 +11,9 @@
|
|
|
11
11
|
"AC-17403-5",
|
|
12
12
|
"AC-17403-6",
|
|
13
13
|
"AC-17403-7",
|
|
14
|
-
"AC-17403-8"
|
|
14
|
+
"AC-17403-8",
|
|
15
|
+
"AC-17403-9",
|
|
16
|
+
"AC-17403-10"
|
|
15
17
|
],
|
|
16
18
|
"id": "TS-220",
|
|
17
19
|
"usId": "US-17403",
|
|
@@ -72,6 +74,20 @@
|
|
|
72
74
|
"description": "No check named skeleton:reqFields is emitted; the stage envelope shape (stage, gate, state, checks) is unchanged.",
|
|
73
75
|
"status": "pending",
|
|
74
76
|
"testPointer": "test/query/gates.test.js::gates (ADR-4126, AC-17403-8): no check named skeleton:reqFields is emitted"
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
"id": "TC-220-r2-draft-tree-wide-under-narrowed-scope",
|
|
80
|
+
"acId": "AC-17403-9",
|
|
81
|
+
"description": "A D3 scope that excludes every TAC and shaped REQ still reports a [draft] marker on a TAC OUTSIDE the narrowed scope through shapes:draftSettled (stage state failing, not notApplicable) via the ADR-4138 shared tree-wide-before-scope helper; the same test asserted against pre-R2 gates.js (origin/main d8adedff^) returns notApplicable instead.",
|
|
82
|
+
"status": "pending",
|
|
83
|
+
"testPointer": "test/query/gates.test.js::gates (R2, AC-17403-9): draftSettled runs tree-wide under narrowed D3 scope"
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
"id": "TC-220-r13-failing-envelope-reason-drops",
|
|
87
|
+
"acId": "AC-17403-10",
|
|
88
|
+
"description": "The ADR-4138 helper returns a failing envelope with no reason field; the readiness CLI prints 'D3 (define.shapes): failing' without a '(no TAC ... in scope)' trailer when a tree-wide check fails under a scope-empty stage.",
|
|
89
|
+
"status": "pending",
|
|
90
|
+
"testPointer": "test/query/gates.test.js::gates (PR 292 follow-up, AC-17403-10): failing envelope carries no notApplicable reason text"
|
|
75
91
|
}
|
|
76
92
|
],
|
|
77
93
|
"status": "draft"
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"createdAt": "2026-10-01T18:00:00Z",
|
|
3
|
-
"updatedAt": "2026-10-
|
|
4
|
-
"purpose": "Cover US-18001 (Readiness as tab 1 and the PRD rename) 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.",
|
|
3
|
+
"updatedAt": "2026-10-06T12:00:00Z",
|
|
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": [
|
|
7
7
|
"AC-18001-1",
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
"AC-18001-5",
|
|
12
12
|
"AC-18001-6",
|
|
13
13
|
"AC-18001-7",
|
|
14
|
+
"AC-18001-8",
|
|
14
15
|
"AC-18101-1",
|
|
15
16
|
"AC-18101-2",
|
|
16
17
|
"AC-18101-3"
|
|
@@ -88,6 +89,27 @@
|
|
|
88
89
|
"description": "No existing Product Map or Requirements test expectation changes; only the Readiness-specific additions land.",
|
|
89
90
|
"status": "pending",
|
|
90
91
|
"testPointer": "test/view/readiness-tab.test.js::readiness tab: AC-18101-3 existing Product Map and Requirements tests retain their expectations"
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
"id": "TC-223-swap-preserves-readiness",
|
|
95
|
+
"acId": "AC-18001-8",
|
|
96
|
+
"description": "resyncTabsAfterSwap keeps tab-readiness as the sole visible panel when Readiness is aria-selected and the swap left tab-overview visible (the Phase 3.6 server default). Pins issue 297: before the fix, the hard-coded TABS list in live-client.js omitted 'readiness', indexOf returned -1, selected fell back to overview, and both tab-readiness and tab-overview went visible.",
|
|
97
|
+
"status": "passing",
|
|
98
|
+
"testPointer": "test/view/live-client.test.js::AC-18001-8 resyncTabsAfterSwap keeps Readiness visible on the embed-no-hash default (issue 297)"
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
"id": "TC-223-swap-ssot-every-tab",
|
|
102
|
+
"acId": "AC-18001-8",
|
|
103
|
+
"description": "resyncTabsAfterSwap honours every nav.tabs [role=tab][data-tab] the server rendered as the SSOT for the tab list. Iterating the six main tabs with each as aria-selected and the swap-default visible panel set to tab-overview, exactly the aria-selected tab's panel is visible after resync. Guards against future drift: a seventh tab added to the renderer survives a swap without an edit on live-client.",
|
|
104
|
+
"status": "passing",
|
|
105
|
+
"testPointer": "test/view/live-client.test.js::AC-18001-8 resyncTabsAfterSwap preserves every tab the DOM renders (SSOT invariant)"
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
"id": "TC-223-swap-product-map-regression",
|
|
109
|
+
"acId": "AC-18001-8",
|
|
110
|
+
"description": "resyncTabsAfterSwap preserves product-map as the sole visible panel through a swap. Guards the one tab that the pre-issue-297 TABS list did include, so the SSOT rewrite does not regress the behaviour it previously had right.",
|
|
111
|
+
"status": "passing",
|
|
112
|
+
"testPointer": "test/view/live-client.test.js::AC-18001-8 resyncTabsAfterSwap preserves Product Map through a swap (regression guard)"
|
|
91
113
|
}
|
|
92
114
|
],
|
|
93
115
|
"status": "draft"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"createdAt": "2026-10-03T00:00:00Z",
|
|
3
|
-
"updatedAt": "2026-10-
|
|
3
|
+
"updatedAt": "2026-10-05T12:30:00Z",
|
|
4
4
|
"purpose": "Cover US-205 (engineer jumps to any document or AC by id): id-first ranking (exact / prefix / contains), word-match title above snippet, single-char ids-only, hash pick lands and expands the entity, mount URL round-trip, embed/theme preservation, empty-state on fetch failure, no outbound postMessage / storage / cookies. Points at the 22 new unit tests under test/view/id-lookup.test.js.",
|
|
5
5
|
"testLevel": "unit",
|
|
6
6
|
"acIds": [
|
|
@@ -11,7 +11,8 @@
|
|
|
11
11
|
"AC-205-5",
|
|
12
12
|
"AC-205-6",
|
|
13
13
|
"AC-205-7",
|
|
14
|
-
"AC-205-8"
|
|
14
|
+
"AC-205-8",
|
|
15
|
+
"AC-205-9"
|
|
15
16
|
],
|
|
16
17
|
"id": "TS-225",
|
|
17
18
|
"usId": "US-205",
|
|
@@ -72,6 +73,13 @@
|
|
|
72
73
|
"description": "wireLookup never calls window.postMessage, never writes to localStorage / sessionStorage / document.cookie, and makes no outbound fetch other than `./index.json`; asserted by a source-level scan of page-init.js (no postMessage, no storage, no cookie writes in wireLookup).",
|
|
73
74
|
"status": "pending",
|
|
74
75
|
"testPointer": "test/view/id-lookup.test.js::page-init.js does not add outbound postMessage, localStorage, sessionStorage or cookies in the lookup wiring (AC-205-8)"
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
"id": "TC-225-search-button-contrast",
|
|
79
|
+
"acId": "AC-205-9",
|
|
80
|
+
"description": "The WCAG 2.1 AA contrast audit (test/view/contrast-aa.test.js) requires a `.rcf-search-btn` pair for each of hover, focus-visible and active (state rules merged over the base rule) in both the light and dark token sets and asserts >= 4.5:1 for the button text and >= 3:1 for the focus ring against the surface it sits on. A missing state pair fails the test (PR 291 landing review F3).",
|
|
81
|
+
"status": "pending",
|
|
82
|
+
"testPointer": "test/view/contrast-aa.test.js::.rcf-search-btn passes WCAG 2.1 AA in both themes across every state (AC-205-9)"
|
|
75
83
|
}
|
|
76
84
|
],
|
|
77
85
|
"status": "draft"
|