rcf-lite 0.28.2 → 0.28.4
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 +211 -0
- package/bin/rcf.js +4 -0
- package/fixtures/canary-manifest.json +9 -9
- package/package.json +1 -1
- package/rcf/adrs/adr-4120-canonical-json-hashing.json +30 -0
- package/rcf/adrs/adr-4121-define-sidecars.json +30 -0
- package/rcf/adrs/adr-4122-define-gates-blocking-and-optout.json +30 -0
- package/rcf/adrs/adr-4123-readiness-single-object.json +30 -0
- package/rcf/code-nodes/cn-700.json +23 -0
- package/rcf/code-nodes/cn-701.json +14 -0
- package/rcf/code-nodes/cn-702.json +14 -0
- package/rcf/code-nodes/cn-703.json +16 -0
- package/rcf/code-nodes/cn-720.json +15 -0
- package/rcf/code-nodes/cn-721.json +15 -0
- package/rcf/code-nodes/cn-722.json +15 -0
- package/rcf/code-nodes/cn-723.json +18 -0
- package/rcf/code-nodes/cn-724.json +14 -0
- package/rcf/code-nodes/cn-725.json +21 -0
- package/rcf/code-nodes/cn-726.json +17 -0
- package/rcf/code-nodes/cn-727.json +14 -0
- package/rcf/code-nodes/cn-728.json +21 -0
- package/rcf/code-nodes/cn-729.json +18 -0
- package/rcf/code-nodes/cn-730.json +14 -0
- package/rcf/fbs/fbs-190.json +37 -0
- package/rcf/fbs/fbs-191.json +34 -0
- package/rcf/fbs/fbs-192.json +17 -0
- package/rcf/fbs/fbs-193.json +37 -0
- package/rcf/fbs/fbs-194.json +35 -0
- package/rcf/fbs/fbs-195.json +37 -0
- package/rcf/fbs/fbs-196.json +37 -0
- package/rcf/fbs/fbs-197.json +41 -0
- package/rcf/requirements/req-001.json +2 -1
- package/rcf/requirements/req-002.json +2 -1
- package/rcf/requirements/req-003.json +2 -1
- package/rcf/requirements/req-004.json +2 -1
- package/rcf/requirements/req-005.json +2 -1
- package/rcf/requirements/req-006.json +2 -1
- package/rcf/requirements/req-007.json +2 -1
- package/rcf/requirements/req-008.json +2 -1
- package/rcf/requirements/req-009.json +2 -1
- package/rcf/requirements/req-010.json +5 -2
- package/rcf/requirements/req-011.json +2 -1
- package/rcf/requirements/req-012.json +2 -1
- package/rcf/requirements/req-013.json +2 -1
- package/rcf/requirements/req-014.json +2 -1
- package/rcf/requirements/req-015.json +2 -1
- package/rcf/requirements/req-016.json +5 -2
- package/rcf/requirements/req-017.json +6 -2
- package/rcf/requirements/req-018.json +5 -2
- package/rcf/requirements/req-019.json +5 -2
- package/rcf/requirements/req-020.json +5 -2
- package/rcf/requirements/req-021.json +5 -2
- package/rcf/requirements/req-022.json +5 -2
- package/rcf/requirements/req-023.json +6 -4
- package/rcf/requirements/req-024.json +5 -2
- package/rcf/requirements/req-025.json +5 -2
- package/rcf/requirements/req-026.json +5 -2
- package/rcf/requirements/req-027.json +5 -2
- package/rcf/requirements/req-028.json +5 -2
- package/rcf/requirements/req-029.json +5 -2
- package/rcf/requirements/req-030.json +5 -2
- package/rcf/requirements/req-040.json +5 -2
- package/rcf/requirements/req-041.json +5 -2
- package/rcf/requirements/req-042.json +5 -2
- package/rcf/requirements/req-043.json +5 -2
- package/rcf/requirements/req-050.json +5 -2
- package/rcf/requirements/req-051.json +5 -2
- package/rcf/requirements/req-052.json +5 -2
- package/rcf/requirements/req-053.json +5 -2
- package/rcf/requirements/req-054.json +5 -2
- package/rcf/requirements/req-060.json +5 -2
- package/rcf/requirements/req-061.json +5 -2
- package/rcf/requirements/req-062.json +5 -2
- package/rcf/requirements/req-063.json +5 -2
- package/rcf/requirements/req-070.json +5 -2
- package/rcf/requirements/req-071.json +5 -2
- package/rcf/requirements/req-072.json +5 -2
- package/rcf/requirements/req-073.json +5 -2
- package/rcf/requirements/req-074.json +5 -2
- package/rcf/requirements/req-075.json +5 -2
- package/rcf/requirements/req-076.json +5 -2
- package/rcf/requirements/req-077.json +5 -2
- package/rcf/requirements/req-080.json +5 -2
- package/rcf/requirements/req-081.json +5 -2
- package/rcf/requirements/req-082.json +5 -2
- package/rcf/requirements/req-083.json +5 -2
- package/rcf/requirements/req-084.json +5 -2
- package/rcf/requirements/req-085.json +5 -2
- package/rcf/requirements/req-086.json +5 -2
- package/rcf/requirements/req-090.json +5 -2
- package/rcf/requirements/req-091.json +5 -2
- package/rcf/requirements/req-092.json +5 -2
- package/rcf/requirements/req-093.json +5 -2
- package/rcf/requirements/req-094.json +5 -2
- package/rcf/requirements/req-100.json +5 -2
- package/rcf/requirements/req-101.json +5 -2
- package/rcf/requirements/req-102.json +5 -2
- package/rcf/requirements/req-103.json +5 -2
- package/rcf/requirements/req-104.json +5 -2
- package/rcf/requirements/req-110.json +5 -2
- package/rcf/requirements/req-111.json +5 -2
- package/rcf/requirements/req-112.json +5 -2
- package/rcf/requirements/req-113.json +5 -2
- package/rcf/requirements/req-114.json +5 -2
- package/rcf/requirements/req-115.json +5 -2
- package/rcf/requirements/req-120.json +5 -2
- package/rcf/requirements/req-121.json +5 -2
- package/rcf/requirements/req-122.json +5 -2
- package/rcf/requirements/req-123.json +5 -2
- package/rcf/requirements/req-124.json +5 -2
- package/rcf/requirements/req-125.json +5 -2
- package/rcf/requirements/req-130.json +6 -2
- package/rcf/requirements/req-131.json +6 -2
- package/rcf/requirements/req-132.json +6 -2
- package/rcf/requirements/req-133.json +6 -2
- package/rcf/requirements/req-134.json +6 -2
- package/rcf/requirements/req-140.json +5 -2
- package/rcf/requirements/req-145.json +5 -2
- package/rcf/requirements/req-150.json +6 -2
- package/rcf/requirements/req-151.json +6 -2
- package/rcf/requirements/req-152.json +6 -2
- package/rcf/requirements/req-153.json +6 -2
- package/rcf/requirements/req-154.json +5 -2
- package/rcf/requirements/req-155.json +4 -1
- package/rcf/requirements/req-156.json +4 -1
- package/rcf/requirements/req-157.json +4 -1
- package/rcf/requirements/req-158.json +4 -1
- package/rcf/requirements/req-159.json +4 -1
- package/rcf/requirements/req-160.json +4 -1
- package/rcf/requirements/req-161.json +4 -1
- package/rcf/requirements/req-162.json +4 -1
- package/rcf/requirements/req-163.json +5 -2
- package/rcf/requirements/req-164.json +5 -2
- package/rcf/requirements/req-165.json +5 -2
- package/rcf/requirements/req-170.json +33 -0
- package/rcf/requirements/req-171.json +44 -0
- package/rcf/requirements/req-172.json +25 -0
- package/rcf/requirements/req-173.json +25 -0
- package/rcf/requirements/req-174.json +25 -0
- package/rcf/requirements/req-175.json +25 -0
- package/rcf/tacs/tac-4120-define-delta-and-freeze.json +21 -0
- package/rcf/tacs/tac-4121-define-ledgers.json +23 -0
- package/rcf/tacs/tac-4122-define-gates.json +25 -0
- package/rcf/tacs/tac-4123-define-readiness.json +25 -0
- package/rcf/test-suites/ts-204.json +30 -0
- package/rcf/test-suites/ts-205.json +22 -0
- package/rcf/test-suites/ts-206.json +22 -0
- package/rcf/test-suites/ts-207.json +22 -0
- package/rcf/test-suites/ts-208.json +22 -0
- package/rcf/test-suites/ts-209.json +22 -0
- package/rcf/test-suites/ts-210.json +22 -0
- package/rcf/test-suites/ts-211.json +22 -0
- package/rcf/test-suites/ts-212.json +22 -0
- package/rcf/test-suites/ts-213.json +50 -0
- package/rcf/test-suites/ts-214.json +74 -0
- package/rcf/test-suites/ts-215.json +67 -0
- package/rcf/test-suites/ts-216.json +78 -0
- package/rcf/test-suites/ts-217.json +62 -0
- package/rcf/user-stories/us-15601.json +4 -4
- package/rcf/user-stories/us-17001.json +27 -0
- package/rcf/user-stories/us-17002.json +22 -0
- package/rcf/user-stories/us-17003.json +22 -0
- package/rcf/user-stories/us-17004.json +22 -0
- package/rcf/user-stories/us-17005.json +22 -0
- package/rcf/user-stories/us-17006.json +21 -0
- package/rcf/user-stories/us-17007.json +21 -0
- package/rcf/user-stories/us-17008.json +22 -0
- package/rcf/user-stories/us-17101.json +22 -0
- package/rcf/user-stories/us-17102.json +22 -0
- package/rcf/user-stories/us-17201.json +38 -0
- package/rcf/user-stories/us-17301.json +38 -0
- package/rcf/user-stories/us-17401.json +58 -0
- package/rcf/user-stories/us-17501.json +48 -0
- package/releases/releases.yaml +21 -1
- package/src/cli/feedback.js +126 -10
- package/src/cli/help.js +11 -0
- package/src/cli/ledger.js +399 -0
- package/src/cli/readiness.js +280 -0
- package/src/core/store/writer.js +86 -6
- package/src/define/freeze-record.js +232 -0
- package/src/define/ledgers.js +513 -0
- package/src/feedback/redact.js +105 -19
- package/src/query/delta.js +276 -0
- package/src/query/gates.js +832 -0
- package/src/query/index.js +36 -0
- package/src/query/readiness.js +333 -0
- package/src/server/index.js +37 -0
- package/src/server/routes.js +65 -3
- package/src/view/doc-renderers/helpers.js +2 -2
- package/src/view/doc-renderers/req.js +10 -2
- package/src/view/doc-renderers/user-story.js +10 -5
- package/src/view/html-page.js +347 -28
- package/src/view/index.js +14 -1
- package/src/view/live-client.js +22 -2
- package/src/view/product-map.js +751 -0
- package/src/view/style.css +378 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"createdAt": "2026-09-24T12:00:00Z",
|
|
3
|
+
"updatedAt": "2026-09-24T12:00:00Z",
|
|
4
|
+
"tacId": "TAC-4121-define-ledgers",
|
|
5
|
+
"prdId": "PRD-001",
|
|
6
|
+
"tadId": "TAD-001",
|
|
7
|
+
"version": "0.1.0",
|
|
8
|
+
"status": "draft",
|
|
9
|
+
"name": "define ledgers module and rcf define ledger CLI",
|
|
10
|
+
"purpose": "The four sidecar ledgers land under rcf/define/ as one JSON file each, with one numbered sequence per ledger for the life of the project. The pure module src/define/ledgers.js exposes LEDGER_NAMES (the four allowed values), BRIEF_KINDS, LedgerError, emptyLedger, ledgerRelPath, ledgerPath, loadLedger, saveLedger, validateLedger, addEntry, resolveEntry, nextIdFor, parseBriefFromFile and loadAllLedgers (returns a LedgerBundle for computeDelta). The CLI verb src/cli/ledger.js wraps the module with parseArgs, wires under bin/rcf.js's define group as GROUPS.define.ledger, and prints usage text also mounted in src/cli/help.js's HELP_MAP.define.ledger so `rcf help define ledger` and `rcf define ledger --help` render the same block by construction.",
|
|
11
|
+
"responsibilities": [
|
|
12
|
+
"src/define/ledgers.js: LEDGER_NAMES = ['brief','decisions','concerns','probes']; per-ledger config maps a name to its filename (brief-ledger.json, decisions-ledger.json, concern-ledger.json, probe-ledger.json) and its body array key (statements | decisions | concerns | probes).",
|
|
13
|
+
"loadLedger returns emptyLedger(name) on ENOENT; a malformed file raises LedgerError with a code ('parseFailure' | 'schemaFailure' | 'ioFailure' | 'usage') and a named field.",
|
|
14
|
+
"addEntry mints the next id (highest current + 1), stamps addedAt and defaults status open, validates the resulting body before returning it, refuses unknown BRIEF_KINDS at validation.",
|
|
15
|
+
"resolveEntry flips status to resolved, stamps resolvedAt, throws LedgerError code 'usage' when the id is unknown, is idempotent-ish (resolving twice refreshes resolvedAt).",
|
|
16
|
+
"parseBriefFromFile splits by non-empty lines, strips leading '- ', '* ' or '<n>. ' bullets, defaults kind to 'capability', and threads --source through to every draft.",
|
|
17
|
+
"src/cli/ledger.js: `rcf define ledger <name> <verb>` argv parsing; verbs add / resolve / list; ledger-specific flags for each; renderDecisionsList formats the #241 numbered layout; list --json emits { ledger, <arrayKey>: [...] }.",
|
|
18
|
+
"bin/rcf.js: register GROUPS.define.ledger; src/cli/help.js: import LEDGER_HELP and wire into HELP_MAP.define.ledger + DEFINE_HELP + top-level DEFINE listing so per-verb help stays single-sourced."
|
|
19
|
+
],
|
|
20
|
+
"internalStructure": "The walker never reads under rcf/define/: subdirFor in src/core/store/loader.js returns null for anything that is not a known child kind (requirements, user-stories, tacs, adrs, fbs, test-suites, code-nodes, evals), so a ledger file sitting under rcf/define/ is never enumerated for schema validation. The walker-invisibility invariant is proved by a dedicated test that seeds the four ledger files plus a bug-bait req-shaped file under rcf/define/ and asserts zero walker error paths starting with rcf/define/ and no matching id in tree.byId. Validation is JSON-schema-shaped inline (no ajv, no @stravica-ai/rcf-schemas dependency) because the sidecars ride outside the shared schema until schemas 0.7 (ADR-4121).",
|
|
21
|
+
"interfaces": [],
|
|
22
|
+
"notes": "The intake-scan-against-frozen-statements hook on brief add --from is a named seam this slice leaves for a later one: 'rcf discover intake' is the intended caller in slice 2's D1 gate check, and this slice ensures the CLI has one place to inject that seam without a second refactor. `list --json` is a keep-alive for slice 5's viewer, which will render the same object over http."
|
|
23
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"createdAt": "2026-09-24T14:30:00Z",
|
|
3
|
+
"updatedAt": "2026-09-24T15:48:40Z",
|
|
4
|
+
"tacId": "TAC-4122-define-gates",
|
|
5
|
+
"prdId": "PRD-001",
|
|
6
|
+
"tadId": "TAD-001",
|
|
7
|
+
"version": "0.1.0",
|
|
8
|
+
"status": "draft",
|
|
9
|
+
"name": "define stage gates D1..D8",
|
|
10
|
+
"purpose": "src/query/gates.js lands as a new pure module beside delta.js. Every stage has one exported check function that takes (tree, context) and returns the { stage, gate, state, checks[] } shape section 2.4 pins. computeReadiness (TAC-4123) is the composer; every gate function is otherwise consumable in isolation for tests and for future viewers that render one stage. No I/O, no state, no time: the caller supplies ledgers, profile, freeze, delta, validate errors, probe count and coverage rollups.",
|
|
11
|
+
"responsibilities": [
|
|
12
|
+
"src/query/gates.js: STAGE_ORDER = ['D1','D2','D3','D4','D5','D6','D7','D8']; STAGE_GATES map (D1 -> 'define.brief' etc.); INTERFACE_KINDS closed set matching proposal section 5.2; STAGE_SHORT_NAMES map (D1 -> 'brief' etc.).",
|
|
13
|
+
"checkD1Brief: intake acknowledged (brief-ledger has at least one statement since the freeze high-water mark), every statement kinded from BRIEF_KINDS, every openQuestion statement resolved or promoted to a decisions-ledger entry, profile.md carries surface (viewer | runningApp | prDiff) and register (productOwner | engineer | unstated) markers.",
|
|
14
|
+
"checkD2Skeleton: every 'capability' and 'constraint' statement in scope resolves to a REQ (via a REQ id in the statement's resolvedBy field OR by name-match against a REQ title, cheap check); every REQ in scope has non-TODO description, shapeClassification and domain; TAD dataStores and coreEntities non-empty when any persistence REQ exists; exactly one deploy or deferral ADR tree-wide (title prefix 'Deploy target:' or 'Deploy deferral:').",
|
|
15
|
+
"checkD3Shapes: every TAC in scope has at least one interface; every interface's kind is in INTERFACE_KINDS. Template markers, entity join, ownerRef resolution and path resolution are seams (0.30).",
|
|
16
|
+
"checkD4Stories: every REQ in scope has at least one US (fbsByAcId inversion via reqByUs is enough); every US in scope has a testable AC (ac.testable !== false and description non-empty), a failure AC or a project-scoped or req-scoped opt-out with baselineKey 'defineD4:failure', a must-not AC or an opt-out with baselineKey 'defineD4:mustNot', tacIds non-empty and every id resolving to a walker-known TAC, and no AC description containing the scaffold TODO placeholder pattern (case-sensitive uppercase 'TODO:' with a colon -- the literal shape src/core/store/init.js writes; incidental prose mentioning 'todo' does NOT trip the gate, and the validate CLI's broader whole-word notice stays separate).",
|
|
17
|
+
"checkD5Crosscut: TAD.securityArchitecture non-empty when tree carries any REQ with shape 'auth' or 'httpApi'; TAD.operationalConcerns non-empty when any AC description carries the '[deployed]' marker; every concern-ledger entry on a REQ in scope has disposition applied or waived (no status 'open').",
|
|
18
|
+
"checkD6Consistency: caller-supplied validateErrors is empty (tree-wide); caller-supplied probeOpenCount is zero.",
|
|
19
|
+
"checkD7Decisions: no decisions-ledger entry with status 'open'.",
|
|
20
|
+
"checkD8Freeze: prior stages passed | acknowledged at the current tree hash; every AC id owned by exactly one FBS (walker.fbsByAcId length 1); computeQueue.nextActionable is not null (queue head actionable) and the head's title is not 'TODO' or empty; validateErrors empty."
|
|
21
|
+
],
|
|
22
|
+
"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.",
|
|
23
|
+
"interfaces": [],
|
|
24
|
+
"notes": "Slice-3 hook (rcf define freeze): reads state to refuse on any 'failing'; --ack <gate> --reason <text> writes freeze.gates[<gate>] = { state: 'acknowledged', at: { hash: <currentTreeHash>, reason: <text>, by: <id> } } and re-runs computeReadiness to check freezeable. Slice-5 hook (viewer): reads the same object end-to-end."
|
|
25
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"createdAt": "2026-09-24T14:30:00Z",
|
|
3
|
+
"updatedAt": "2026-09-24T15:48:40Z",
|
|
4
|
+
"tacId": "TAC-4123-define-readiness",
|
|
5
|
+
"prdId": "PRD-001",
|
|
6
|
+
"tadId": "TAD-001",
|
|
7
|
+
"version": "0.1.0",
|
|
8
|
+
"status": "draft",
|
|
9
|
+
"name": "computeReadiness compute and rcf define readiness CLI",
|
|
10
|
+
"purpose": "src/query/readiness.js and src/cli/readiness.js land as a matched pair. The pure module composes computeDelta, computeImpact, the eight gate check functions from TAC-4122, computeCoverage, and the decisions ledger into the single-object contract section 2.4 pins; the CLI is its twin. Text output for readable status; --json for machine consumers and the viewer slice; --check <stage>|all for targeted inspection with the same 0-green / 4-red exit shape rcf audit coverage uses.",
|
|
11
|
+
"responsibilities": [
|
|
12
|
+
"src/query/readiness.js: computeReadiness(tree, { freeze, ledgers, profile, testPointers }) returns { tree, delta, stages, nextAction, coverage, decisions, freezeable } exactly as section 2.4 specifies; internal computeScope collects changed + added + impacted ids into a Set; internal composeStages calls each check function in D1..D8 order; internal computeNextAction picks the first failing stage and check; internal deriveTreeSummary shortens the tree hash to eight characters for the tree line.",
|
|
13
|
+
"src/query/readiness.js: computeImpact is called once per id in changed union added; impacted is the deduplicated union of every impact node id excluding the pivots; impactedFbs is the subset with kind 'fbs' AND actionNeeded === 're-execute'.",
|
|
14
|
+
"src/query/readiness.js: computeCoverage is called once tree-wide (strict per-AC, testPointers threaded through) for coverage.tree; coverage.delta is one CoverageResult per unique REQ ancestor of the delta ids (via tree.parentByChild walk to the reqId, or the doc's own reqId field).",
|
|
15
|
+
"src/query/readiness.js: freezeable is true when every stage state in ['passed', 'acknowledged', 'notApplicable'] and false otherwise; nextAction is null when freezeable is true.",
|
|
16
|
+
"src/cli/readiness.js: parseArgs on --json, --check, --help; findProjectRoot; walkTree; loadFreezeRecord; loadAllLedgers; resolveTestPointers; runWithAdmissibilityGate wraps a producer that invokes computeReadiness; on refuse the CLI prints an informational '[warn] readiness: chain admissibility refused (informational; the readiness compute still ran).' on stderr and STILL runs the compute so the diagnostic reports which stage blocks (readiness is a diagnostic, not a gate that hides its answer); the top-level exit stays 0 in that case and --check <stage> follows its normal per-stage exit rule; on ok the CLI renders text (default) or JSON.",
|
|
17
|
+
"src/cli/readiness.js: text output = tree line, next-action line, chip line (D1..D8 with state color words), stage-by-stage failing items (checks with failing ids); --check exits 4 for a blocking stage that is failing, 0 with a stderr [warn] for a warn-with-ack stage that is failing but not acknowledged, 0 otherwise.",
|
|
18
|
+
"src/define/ledgers.js (P3 resolution): loadAllLedgers checks each ledger file's existence with statPath and omits missing files from the returned bundle; loadLedger keeps returning an empty ledger on ENOENT so single-ledger callers retain the ergonomic default.",
|
|
19
|
+
"bin/rcf.js: register GROUPS.define.readiness -> readinessMain; src/cli/help.js: import READINESS_HELP and wire into HELP_MAP.define.readiness + DEFINE_HELP + top-level DEFINE listing.",
|
|
20
|
+
"src/query/index.js: export computeReadiness (plus its subhelpers where useful for tests) so downstream consumers (slice 3 freeze, slice 5 viewer) import through the same seam every other query verb does."
|
|
21
|
+
],
|
|
22
|
+
"internalStructure": "readiness.js is a linear composer: 1) compute delta and its docHashes; 2) fan-out impacted / impactedFbs; 3) build stage context (freeze, delta, scope, ledgers, profile, validateErrors, probeOpenCount, coverageTree); 4) call the eight check functions; 5) fold freezeable and nextAction. The CLI parses flags, loads the tree once, loads the four ledgers and the freeze record once, computes the readiness, then routes to the text or JSON emitter. --check maps its argument to the STAGE_SHORT_NAMES map (brief -> D1 ... freeze -> D8) or accepts D1..D8 directly. The runWithAdmissibilityGate wrap sits inside main so refusals ride the same exit path as coverage's admissibility refusals.",
|
|
23
|
+
"interfaces": [],
|
|
24
|
+
"notes": "Slice-3 hook (rcf define freeze) reads freezeable and stages[].state; --ack <gate> writes into freeze.gates[<gate>] and re-computes readiness. Slice-5 hook (viewer) fetches the same JSON object over the existing tab wire and renders the pill vocabulary + findings-list + diff components. Performance seam: computeImpact per id on a whole-tree delta (before freeze) may be quadratic on very large trees; the compute stays fast on the dogfood chain (~700 documents, sub-second) but the CLI notes the wall time in text mode so an operator can spot regression."
|
|
25
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "TS-204",
|
|
3
|
+
"usId": "US-17001",
|
|
4
|
+
"title": "Product Map shape grouping",
|
|
5
|
+
"purpose": "Cover the shape-grouping renderer and its drill-down for AC-17001-1 and AC-17001-2.",
|
|
6
|
+
"testLevel": "integration",
|
|
7
|
+
"acIds": [
|
|
8
|
+
"AC-17001-1",
|
|
9
|
+
"AC-17001-2"
|
|
10
|
+
],
|
|
11
|
+
"testCases": [
|
|
12
|
+
{
|
|
13
|
+
"id": "TC-204-shape-buckets-present",
|
|
14
|
+
"acId": "AC-17001-1",
|
|
15
|
+
"description": "Rendering the tree emits a product-map tab with shape buckets covering every classified shape plus Unclassified and Business rules.",
|
|
16
|
+
"status": "passing",
|
|
17
|
+
"testPointer": "test/view/product-map.test.js::product-map shape grouping renders one bucket per shape plus Unclassified and Business rules"
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"id": "TC-204-shape-drill-req-us-ac",
|
|
21
|
+
"acId": "AC-17001-2",
|
|
22
|
+
"description": "The shape grouping drills bucket -> REQ (status pill) -> US -> AC using the shared detailsWrap helper; every id inside the Product Map tab is bucket-scoped so the same REQ can appear under multiple buckets without duplicating ids.",
|
|
23
|
+
"status": "passing",
|
|
24
|
+
"testPointer": "test/view/product-map.test.js::product-map shape grouping drills bucket to REQ to US to AC with status pill, ids scoped to the bucket (P2-1)"
|
|
25
|
+
}
|
|
26
|
+
],
|
|
27
|
+
"status": "approved",
|
|
28
|
+
"createdAt": "2026-09-21T17:00:00.000Z",
|
|
29
|
+
"updatedAt": "2026-09-21T18:02:10.540Z"
|
|
30
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "TS-205",
|
|
3
|
+
"usId": "US-17002",
|
|
4
|
+
"title": "Product Map status filter",
|
|
5
|
+
"purpose": "Cover AC-17002-1: status filter control and empty-bucket collapse.",
|
|
6
|
+
"testLevel": "integration",
|
|
7
|
+
"acIds": [
|
|
8
|
+
"AC-17002-1"
|
|
9
|
+
],
|
|
10
|
+
"testCases": [
|
|
11
|
+
{
|
|
12
|
+
"id": "TC-205-status-filter-control",
|
|
13
|
+
"acId": "AC-17002-1",
|
|
14
|
+
"description": "The tab renders a status filter with six options; server-rendered outer pm-req counts per status match a model-side prediction across every grouping (the same DOM the client-side applyPmStatusFilter reads).",
|
|
15
|
+
"status": "passing",
|
|
16
|
+
"testPointer": "test/view/product-map.test.js::product-map status filter markup + server-rendered per-bucket status counts match the model (P2-3 real assertion)"
|
|
17
|
+
}
|
|
18
|
+
],
|
|
19
|
+
"status": "approved",
|
|
20
|
+
"createdAt": "2026-09-21T17:00:00.000Z",
|
|
21
|
+
"updatedAt": "2026-09-21T18:02:10.757Z"
|
|
22
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "TS-206",
|
|
3
|
+
"usId": "US-17003",
|
|
4
|
+
"title": "Product Map component grouping",
|
|
5
|
+
"purpose": "Cover AC-17003-1: TAD-rooted TAC hierarchy with Unmapped bucket.",
|
|
6
|
+
"testLevel": "integration",
|
|
7
|
+
"acIds": [
|
|
8
|
+
"AC-17003-1"
|
|
9
|
+
],
|
|
10
|
+
"testCases": [
|
|
11
|
+
{
|
|
12
|
+
"id": "TC-206-component-tad-root",
|
|
13
|
+
"acId": "AC-17003-1",
|
|
14
|
+
"description": "Component grouping shows TAD -> TAC (with dependencies) -> US -> REQ -> AC, with an Unmapped bucket for REQs no component reaches.",
|
|
15
|
+
"status": "passing",
|
|
16
|
+
"testPointer": "test/view/product-map.test.js::product-map component grouping roots at TAD and lists TAC to US to REQ to AC with an Unmapped bucket"
|
|
17
|
+
}
|
|
18
|
+
],
|
|
19
|
+
"status": "approved",
|
|
20
|
+
"createdAt": "2026-09-21T17:00:00.000Z",
|
|
21
|
+
"updatedAt": "2026-09-21T17:00:00.000Z"
|
|
22
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "TS-207",
|
|
3
|
+
"usId": "US-17004",
|
|
4
|
+
"title": "Product Map trace coverage",
|
|
5
|
+
"purpose": "Cover AC-17004-1: each REQ bucketed by trace completeness with a plain-text \"what is missing\" line.",
|
|
6
|
+
"testLevel": "integration",
|
|
7
|
+
"acIds": [
|
|
8
|
+
"AC-17004-1"
|
|
9
|
+
],
|
|
10
|
+
"testCases": [
|
|
11
|
+
{
|
|
12
|
+
"id": "TC-207-trace-coverage-buckets",
|
|
13
|
+
"acId": "AC-17004-1",
|
|
14
|
+
"description": "Trace coverage grouping buckets each REQ into the FIRST bucket whose rule it meets (missing-stories, missing-ac-scope, missing-component, missing-tests, complete); a synthetic fixture asserts the classification per REQ id, including the P1-4 dangling-TAC case landing in missing-component.",
|
|
15
|
+
"status": "passing",
|
|
16
|
+
"testPointer": "test/view/product-map.test.js::product-map trace coverage places each REQ in the FIRST bucket whose condition it meets, on a synthetic fixture (P2-3)"
|
|
17
|
+
}
|
|
18
|
+
],
|
|
19
|
+
"status": "approved",
|
|
20
|
+
"createdAt": "2026-09-21T17:00:00.000Z",
|
|
21
|
+
"updatedAt": "2026-09-21T18:02:10.973Z"
|
|
22
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "TS-208",
|
|
3
|
+
"usId": "US-17005",
|
|
4
|
+
"title": "Product Map capability grouping",
|
|
5
|
+
"purpose": "Cover AC-17005-1: capability:<slug> tag consumption and Unclassified bucket.",
|
|
6
|
+
"testLevel": "integration",
|
|
7
|
+
"acIds": [
|
|
8
|
+
"AC-17005-1"
|
|
9
|
+
],
|
|
10
|
+
"testCases": [
|
|
11
|
+
{
|
|
12
|
+
"id": "TC-208-capability-buckets",
|
|
13
|
+
"acId": "AC-17005-1",
|
|
14
|
+
"description": "Capability grouping enumerates one bucket per distinct capability:<slug> tag; multi-tag REQs appear in each bucket; untagged REQs go to Unclassified.",
|
|
15
|
+
"status": "passing",
|
|
16
|
+
"testPointer": "test/view/product-map.test.js::product-map capability grouping enumerates one bucket per capability slug with Unclassified for untagged REQs"
|
|
17
|
+
}
|
|
18
|
+
],
|
|
19
|
+
"status": "approved",
|
|
20
|
+
"createdAt": "2026-09-21T17:00:00.000Z",
|
|
21
|
+
"updatedAt": "2026-09-21T17:00:00.000Z"
|
|
22
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "TS-209",
|
|
3
|
+
"usId": "US-17101",
|
|
4
|
+
"title": "Dogfood REQs carry capability tags",
|
|
5
|
+
"purpose": "Cover AC-17101-1: every REQ file carries at least one capability:<slug> tag drawn from the documented taxonomy.",
|
|
6
|
+
"testLevel": "integration",
|
|
7
|
+
"acIds": [
|
|
8
|
+
"AC-17101-1"
|
|
9
|
+
],
|
|
10
|
+
"testCases": [
|
|
11
|
+
{
|
|
12
|
+
"id": "TC-209-every-req-has-capability-tag",
|
|
13
|
+
"acId": "AC-17101-1",
|
|
14
|
+
"description": "Every requirement file under packages/rcf-lite/rcf/requirements/ carries at least one capability:<slug> tag, and each slug is listed in docs/capability-tags.md.",
|
|
15
|
+
"status": "passing",
|
|
16
|
+
"testPointer": "test/view/capability-tags.test.js::every dogfood REQ carries at least one capability tag mapped to a documented slug"
|
|
17
|
+
}
|
|
18
|
+
],
|
|
19
|
+
"status": "approved",
|
|
20
|
+
"createdAt": "2026-09-21T17:00:00.000Z",
|
|
21
|
+
"updatedAt": "2026-09-21T17:00:00.000Z"
|
|
22
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "TS-210",
|
|
3
|
+
"usId": "US-17102",
|
|
4
|
+
"title": "Capability taxonomy documented",
|
|
5
|
+
"purpose": "Cover AC-17102-1: docs/capability-tags.md exists and is linked from docs/README.md.",
|
|
6
|
+
"testLevel": "integration",
|
|
7
|
+
"acIds": [
|
|
8
|
+
"AC-17102-1"
|
|
9
|
+
],
|
|
10
|
+
"testCases": [
|
|
11
|
+
{
|
|
12
|
+
"id": "TC-210-taxonomy-doc-present",
|
|
13
|
+
"acId": "AC-17102-1",
|
|
14
|
+
"description": "docs/capability-tags.md exists, lists every taxonomy slug with a one-line meaning, states the \"add a capability\" rule, and is linked from docs/README.md.",
|
|
15
|
+
"status": "passing",
|
|
16
|
+
"testPointer": "test/view/capability-tags.test.js::docs carry the capability taxonomy and link to it from the docs README"
|
|
17
|
+
}
|
|
18
|
+
],
|
|
19
|
+
"status": "approved",
|
|
20
|
+
"createdAt": "2026-09-21T17:00:00.000Z",
|
|
21
|
+
"updatedAt": "2026-09-21T17:00:00.000Z"
|
|
22
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"createdAt": "2026-09-21T18:46:16.398Z",
|
|
3
|
+
"updatedAt": "2026-09-21T18:46:16.604Z",
|
|
4
|
+
"purpose": "Cover the collapsed-by-default buckets, jump-nav rail, per-status mini counts, expand/collapse-all and open-bucket hash restore for AC-17006-1.",
|
|
5
|
+
"testLevel": "integration",
|
|
6
|
+
"acIds": [
|
|
7
|
+
"AC-17006-1"
|
|
8
|
+
],
|
|
9
|
+
"id": "TS-211",
|
|
10
|
+
"usId": "US-17006",
|
|
11
|
+
"title": "Product Map interaction model",
|
|
12
|
+
"testCases": [
|
|
13
|
+
{
|
|
14
|
+
"id": "TC-211-interaction-model-buckets",
|
|
15
|
+
"acId": "AC-17006-1",
|
|
16
|
+
"description": "Every bucket renders as a collapsed <details class=pm-bucket> with a per-status mini row and a jump-nav chip row per grouping.",
|
|
17
|
+
"status": "pending",
|
|
18
|
+
"testPointer": "test/view/product-map.test.js::product-map buckets are <details class=\"pm-bucket\"> collapsed by default with a per-status mini row (AC-17006-1)"
|
|
19
|
+
}
|
|
20
|
+
],
|
|
21
|
+
"status": "draft"
|
|
22
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"createdAt": "2026-09-21T18:46:16.821Z",
|
|
3
|
+
"updatedAt": "2026-09-21T18:46:17.106Z",
|
|
4
|
+
"purpose": "Cover the initial-render skeletons and raw-JSON suppression the lazy render depends on for AC-17007-1.",
|
|
5
|
+
"testLevel": "integration",
|
|
6
|
+
"acIds": [
|
|
7
|
+
"AC-17007-1"
|
|
8
|
+
],
|
|
9
|
+
"id": "TS-212",
|
|
10
|
+
"usId": "US-17007",
|
|
11
|
+
"title": "Product Map lazy first-load payload",
|
|
12
|
+
"testCases": [
|
|
13
|
+
{
|
|
14
|
+
"id": "TC-212-lazy-skeletons",
|
|
15
|
+
"acId": "AC-17007-1",
|
|
16
|
+
"description": "Initial contentHtml emits data-pm-lazy=true skeletons for every grouping and never inlines a raw-JSON disclosure inside a pm-req card.",
|
|
17
|
+
"status": "pending",
|
|
18
|
+
"testPointer": "test/view/product-map.test.js::product-map lazy render: initial contentHtml emits skeletons for every grouping (AC-17007-1)"
|
|
19
|
+
}
|
|
20
|
+
],
|
|
21
|
+
"status": "draft"
|
|
22
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"createdAt": "2026-09-22T11:59:39Z",
|
|
3
|
+
"updatedAt": "2026-09-22T15:00:00Z",
|
|
4
|
+
"purpose": "Cover the blueprint badge on every REQ row and the by-blueprint grouping (bucket per applied blueprint plus Application bucket, capability second level, hash round-trip, /product-map/blueprint partial endpoint) for AC-17008-1.",
|
|
5
|
+
"testLevel": "integration",
|
|
6
|
+
"acIds": [
|
|
7
|
+
"AC-17008-1"
|
|
8
|
+
],
|
|
9
|
+
"id": "TS-213",
|
|
10
|
+
"usId": "US-17008",
|
|
11
|
+
"title": "Product Map by-blueprint grouping and blueprint badge",
|
|
12
|
+
"testCases": [
|
|
13
|
+
{
|
|
14
|
+
"id": "TC-213-badge",
|
|
15
|
+
"acId": "AC-17008-1",
|
|
16
|
+
"description": "In the shape grouping rendered over a fixture project that applies one blueprint contributing two REQs, both contributed REQ rows carry a pm-blueprint-badge in their summary while the non-blueprint (Application) REQ rows do not.",
|
|
17
|
+
"status": "pending",
|
|
18
|
+
"testPointer": "test/view/product-map.test.js::product-map: blueprint badge on every contributed REQ row across groupings (AC-17008-1)"
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"id": "TC-213-buckets",
|
|
22
|
+
"acId": "AC-17008-1",
|
|
23
|
+
"description": "The by-blueprint grouping over a fixture with one applied blueprint (2 contributed REQs) and 2 non-blueprint REQs renders exactly two buckets: a blueprint bucket with count 2 and an Application bucket with count 2.",
|
|
24
|
+
"status": "pending",
|
|
25
|
+
"testPointer": "test/view/product-map.test.js::product-map: by-blueprint grouping yields one bucket per applied blueprint plus an Application bucket (AC-17008-1)"
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"id": "TC-213-capability-second-level",
|
|
29
|
+
"acId": "AC-17008-1",
|
|
30
|
+
"description": "Inside each by-blueprint bucket the second level is capability (existing capability:<slug> tags), then requirement rows, then the usual drill-down.",
|
|
31
|
+
"status": "pending",
|
|
32
|
+
"testPointer": "test/view/product-map.test.js::product-map: by-blueprint bucket second level is capability then REQ (AC-17008-1)"
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"id": "TC-213-hash-and-lazy-endpoint",
|
|
36
|
+
"acId": "AC-17008-1",
|
|
37
|
+
"description": "The inline script's PM_GROUPS constant lists 'blueprint', the lazy fetch endpoint /product-map/blueprint is exposed on the pre-rendered pmPartials, and renderProductMapGrouping(model, 'blueprint') returns a non-empty string.",
|
|
38
|
+
"status": "pending",
|
|
39
|
+
"testPointer": "test/view/product-map.test.js::product-map: by-blueprint grouping wired into PM_GROUPS, pmPartials and renderProductMapGrouping (AC-17008-1)"
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"id": "TC-213-empty-blueprints",
|
|
43
|
+
"acId": "AC-17008-1",
|
|
44
|
+
"description": "A project with no applied blueprints (manifest.blueprints empty) renders the by-blueprint grouping with a single Application bucket and no error banner.",
|
|
45
|
+
"status": "pending",
|
|
46
|
+
"testPointer": "test/view/product-map.test.js::product-map: by-blueprint grouping on a project with no applied blueprints renders a single Application bucket (AC-17008-1)"
|
|
47
|
+
}
|
|
48
|
+
],
|
|
49
|
+
"status": "draft"
|
|
50
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
{
|
|
2
|
+
"createdAt": "2026-09-24T12:00:00Z",
|
|
3
|
+
"updatedAt": "2026-09-24T12:00:00Z",
|
|
4
|
+
"purpose": "Cover the delta-detection primitives (hashDocument, computeTreeHash, computeDelta) and the freeze record I/O (load, save, validate) against AC-17201-1..4 on US-17201.",
|
|
5
|
+
"testLevel": "unit",
|
|
6
|
+
"acIds": [
|
|
7
|
+
"AC-17201-1",
|
|
8
|
+
"AC-17201-2",
|
|
9
|
+
"AC-17201-3",
|
|
10
|
+
"AC-17201-4"
|
|
11
|
+
],
|
|
12
|
+
"id": "TS-214",
|
|
13
|
+
"usId": "US-17201",
|
|
14
|
+
"title": "Delta detection and freeze record primitives",
|
|
15
|
+
"testCases": [
|
|
16
|
+
{
|
|
17
|
+
"id": "TC-214-delta-shape",
|
|
18
|
+
"acId": "AC-17201-1",
|
|
19
|
+
"description": "computeDelta returns the shape proposal section 2.2 pins: frozen / frozenAt / treeHash / currentTreeHash / changed / added / removed / briefSince / unchanged, and classifies changed / added / removed correctly against a divergent freeze record.",
|
|
20
|
+
"status": "pending",
|
|
21
|
+
"testPointer": "test/query/delta.test.js::delta: changed / added / removed classify against the freeze record"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"id": "TC-214-unchanged",
|
|
25
|
+
"acId": "AC-17201-1",
|
|
26
|
+
"description": "A tree that matches the freeze record produces empty changed / added / removed lists and unchanged equal to the docHashes count.",
|
|
27
|
+
"status": "pending",
|
|
28
|
+
"testPointer": "test/query/delta.test.js::delta: an unchanged tree against a matching freeze reports empty changed/added/removed"
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"id": "TC-214-canonical",
|
|
32
|
+
"acId": "AC-17201-2",
|
|
33
|
+
"description": "hashDocument is invariant under a whitespace-only reformat: two documents that parse to the same object hash identically and produce zero changed entries in the delta.",
|
|
34
|
+
"status": "pending",
|
|
35
|
+
"testPointer": "test/query/delta.test.js::delta: a whitespace-only reformat of a document produces zero changed ids"
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"id": "TC-214-hash-shape",
|
|
39
|
+
"acId": "AC-17201-2",
|
|
40
|
+
"description": "hashDocument returns a sha256:<64-hex> string over the canonical JSON form of the parsed document.",
|
|
41
|
+
"status": "pending",
|
|
42
|
+
"testPointer": "test/query/delta.test.js::delta: hashDocument returns a sha256:<64-hex> string over the canonical form"
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"id": "TC-214-freeze-missing",
|
|
46
|
+
"acId": "AC-17201-3",
|
|
47
|
+
"description": "loadFreezeRecord returns null when rcf/define/freeze.json is absent; a malformed body raises FreezeRecordError with the parseFailure code.",
|
|
48
|
+
"status": "pending",
|
|
49
|
+
"testPointer": "test/define/freeze-record.test.js::freeze-record: a malformed JSON body raises FreezeRecordError with parseFailure code"
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"id": "TC-214-freeze-schema",
|
|
53
|
+
"acId": "AC-17201-3",
|
|
54
|
+
"description": "A body with a non-sha256 docHashes value is refused with a FreezeRecordError naming the failing docHashes.<id> field.",
|
|
55
|
+
"status": "pending",
|
|
56
|
+
"testPointer": "test/define/freeze-record.test.js::freeze-record: docHashes with a non-sha256 value is refused"
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
"id": "TC-214-roundtrip",
|
|
60
|
+
"acId": "AC-17201-4",
|
|
61
|
+
"description": "saveFreezeRecord followed by loadFreezeRecord round-trips every field including unknown extension fields (counts, litmus, versions, note).",
|
|
62
|
+
"status": "pending",
|
|
63
|
+
"testPointer": "test/define/freeze-record.test.js::freeze-record: unknown top-level fields survive a save/load round trip"
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
"id": "TC-214-refuse-invalid-write",
|
|
67
|
+
"acId": "AC-17201-4",
|
|
68
|
+
"description": "saveFreezeRecord refuses an invalid record and writes nothing to disk.",
|
|
69
|
+
"status": "pending",
|
|
70
|
+
"testPointer": "test/define/freeze-record.test.js::freeze-record: saveFreezeRecord refuses to write an invalid record"
|
|
71
|
+
}
|
|
72
|
+
],
|
|
73
|
+
"status": "draft"
|
|
74
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
{
|
|
2
|
+
"createdAt": "2026-09-24T12:00:00Z",
|
|
3
|
+
"updatedAt": "2026-09-24T12:00:00Z",
|
|
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/ against AC-17301-1..4 on US-17301.",
|
|
5
|
+
"testLevel": "integration",
|
|
6
|
+
"acIds": [
|
|
7
|
+
"AC-17301-1",
|
|
8
|
+
"AC-17301-2",
|
|
9
|
+
"AC-17301-3",
|
|
10
|
+
"AC-17301-4"
|
|
11
|
+
],
|
|
12
|
+
"id": "TS-215",
|
|
13
|
+
"usId": "US-17301",
|
|
14
|
+
"title": "Sidecar ledgers, rcf define ledger and walker invisibility",
|
|
15
|
+
"testCases": [
|
|
16
|
+
{
|
|
17
|
+
"id": "TC-215-brief-add-text",
|
|
18
|
+
"acId": "AC-17301-1",
|
|
19
|
+
"description": "rcf define ledger brief add --text mints id 1 with status open, kind capability by default, and writes rcf/define/brief-ledger.json.",
|
|
20
|
+
"status": "pending",
|
|
21
|
+
"testPointer": "test/cli/ledger.test.js::ledger CLI: brief add --text appends a numbered statement"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"id": "TC-215-brief-refuse-mixed",
|
|
25
|
+
"acId": "AC-17301-1",
|
|
26
|
+
"description": "rcf define ledger brief add refuses conflicting --text and --from with a usage-class error (exit 2).",
|
|
27
|
+
"status": "pending",
|
|
28
|
+
"testPointer": "test/cli/ledger.test.js::ledger CLI: brief add refuses conflicting --text and --from with a usage error"
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"id": "TC-215-decisions-list-241",
|
|
32
|
+
"acId": "AC-17301-2",
|
|
33
|
+
"description": "rcf define ledger decisions list prints the numbered #241 format: question, options as 'letter) text', default and blocks labelled on their own lines.",
|
|
34
|
+
"status": "pending",
|
|
35
|
+
"testPointer": "test/cli/ledger.test.js::ledger CLI: decisions list prints the numbered #241 format"
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"id": "TC-215-list-json",
|
|
39
|
+
"acId": "AC-17301-2",
|
|
40
|
+
"description": "rcf define ledger <name> list --json emits { ledger, <arrayKey>: [...] } with the same body loadLedger returns.",
|
|
41
|
+
"status": "pending",
|
|
42
|
+
"testPointer": "test/cli/ledger.test.js::ledger CLI: list --json emits the machine-readable envelope"
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"id": "TC-215-brief-from-file",
|
|
46
|
+
"acId": "AC-17301-3",
|
|
47
|
+
"description": "rcf define ledger brief add --from <file> splits by non-empty lines, mints sequential ids and writes every statement with the resolved kind.",
|
|
48
|
+
"status": "pending",
|
|
49
|
+
"testPointer": "test/cli/ledger.test.js::ledger CLI: brief add --from <file> splits by non-empty line"
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"id": "TC-215-parse-brief-bullets",
|
|
53
|
+
"acId": "AC-17301-3",
|
|
54
|
+
"description": "parseBriefFromFile strips leading '- ', '* ' and '<n>. ' bullets so drafts match the raw statement text.",
|
|
55
|
+
"status": "pending",
|
|
56
|
+
"testPointer": "test/define/ledgers.test.js::ledgers: parseBriefFromFile splits by non-empty lines and strips bullets"
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
"id": "TC-215-walker-invisible",
|
|
60
|
+
"acId": "AC-17301-4",
|
|
61
|
+
"description": "walkTree run over a project seeded with rcf/define/freeze.json, the four ledger files and a bug-bait req-999.json under rcf/define/ never surfaces any rcf/define/ path in errors or byId.",
|
|
62
|
+
"status": "pending",
|
|
63
|
+
"testPointer": "test/store/walker-invisible-define.test.js::walkTree never surfaces rcf/define/ files as documents in byId"
|
|
64
|
+
}
|
|
65
|
+
],
|
|
66
|
+
"status": "draft"
|
|
67
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
{
|
|
2
|
+
"createdAt": "2026-09-24T14:30:00Z",
|
|
3
|
+
"updatedAt": "2026-09-24T14:30:00Z",
|
|
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
|
+
"testLevel": "unit",
|
|
6
|
+
"acIds": [
|
|
7
|
+
"AC-17401-1",
|
|
8
|
+
"AC-17401-2",
|
|
9
|
+
"AC-17401-3",
|
|
10
|
+
"AC-17401-4",
|
|
11
|
+
"AC-17401-5",
|
|
12
|
+
"AC-17401-6",
|
|
13
|
+
"AC-17401-7",
|
|
14
|
+
"AC-17401-8"
|
|
15
|
+
],
|
|
16
|
+
"id": "TS-216",
|
|
17
|
+
"usId": "US-17401",
|
|
18
|
+
"title": "Stage gates D1..D8 check functions",
|
|
19
|
+
"testCases": [
|
|
20
|
+
{
|
|
21
|
+
"id": "TC-216-shape",
|
|
22
|
+
"acId": "AC-17401-1",
|
|
23
|
+
"description": "Every check function returns { stage, gate, state, checks[] } and every entry in checks[] is { name, ok, over: 'delta'|'tree', pass, total, failing }; failing is empty when ok is true.",
|
|
24
|
+
"status": "pending",
|
|
25
|
+
"testPointer": "test/query/gates.test.js::gates: every check function returns the section 2.4 shape"
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"id": "TC-216-blocking-vs-warn",
|
|
29
|
+
"acId": "AC-17401-2",
|
|
30
|
+
"description": "Blocking stages fold to failing on any check.ok false; warn-with-ack stages (D3, D5, D6) also fold to failing on any check.ok false unless freeze.gates[<gate>].state === 'acknowledged' AND at.hash === currentTreeHash.",
|
|
31
|
+
"status": "pending",
|
|
32
|
+
"testPointer": "test/query/gates.test.js::gates: warn-with-ack fold honours freeze.gates acknowledgement at the current hash"
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"id": "TC-216-not-applicable",
|
|
36
|
+
"acId": "AC-17401-3",
|
|
37
|
+
"description": "notApplicable is decided per stage per section 3.2: D2 with no statement of a resolving kind and no REQ/PRD/TAD in scope; D3 with no TAC and no shaped REQ in scope; D5 with no REQ in scope; D7 with no open decisions and profile.skipReviewFor 'singleDocument' and one-document delta.",
|
|
38
|
+
"status": "pending",
|
|
39
|
+
"testPointer": "test/query/gates.test.js::gates: notApplicable decision per stage"
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"id": "TC-216-d4-floors",
|
|
43
|
+
"acId": "AC-17401-4",
|
|
44
|
+
"description": "checkD4Stories enforces every REQ has US, every US has testable AC + failure AC (parsed by [failure] prefix or opt-out with baselineKey 'defineD4:failure') + must-not AC (or opt-out with 'defineD4:mustNot'), tacIds non-empty and resolving, no TODO placeholder in AC.description.",
|
|
45
|
+
"status": "pending",
|
|
46
|
+
"testPointer": "test/query/gates.test.js::gates: D4 floors and per-class opt-outs"
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"id": "TC-216-d3-shapes",
|
|
50
|
+
"acId": "AC-17401-5",
|
|
51
|
+
"description": "checkD3Shapes runs only the cheap data-backed checks: every TAC in scope has at least one interface, and every interface kind is in the closed vocabulary. Unknown kinds show up in failing[].",
|
|
52
|
+
"status": "pending",
|
|
53
|
+
"testPointer": "test/query/gates.test.js::gates: D3 interface presence and kind vocabulary"
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"id": "TC-216-d5-crosscut",
|
|
57
|
+
"acId": "AC-17401-6",
|
|
58
|
+
"description": "checkD5Crosscut checks TAD.securityArchitecture presence when any REQ has shape 'auth' or 'httpApi'; TAD.operationalConcerns when any AC has '[deployed]' marker; no dangling 'open' concerns on in-scope REQs.",
|
|
59
|
+
"status": "pending",
|
|
60
|
+
"testPointer": "test/query/gates.test.js::gates: D5 crosscut cheap checks"
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"id": "TC-216-d6-consistency",
|
|
64
|
+
"acId": "AC-17401-7",
|
|
65
|
+
"description": "checkD6Consistency asserts validateErrors is empty tree-wide and probeOpenCount is zero; the richer scans are named seams (0.30).",
|
|
66
|
+
"status": "pending",
|
|
67
|
+
"testPointer": "test/query/gates.test.js::gates: D6 consistency validate + probe count"
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
"id": "TC-216-d8-freeze",
|
|
71
|
+
"acId": "AC-17401-8",
|
|
72
|
+
"description": "checkD8Freeze asserts prior stages passed/acknowledged, every AC owned by exactly one FBS, computeQueue nextActionable not null, validateErrors empty.",
|
|
73
|
+
"status": "pending",
|
|
74
|
+
"testPointer": "test/query/gates.test.js::gates: D8 tree-wide freeze checks"
|
|
75
|
+
}
|
|
76
|
+
],
|
|
77
|
+
"status": "draft"
|
|
78
|
+
}
|