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
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"createdAt": "2026-09-08T03:20:33.239Z",
|
|
3
|
-
"updatedAt": "2026-09-
|
|
3
|
+
"updatedAt": "2026-09-22T13:47:34.538Z",
|
|
4
4
|
"description": "The edge-cloudflare-tunnel v1.0.0 blueprint contributes a cloudflared connector whose runtime shape switches on the applied capability set: when the containerHost capability is applied (T-2 platform-docker-compose-host on top of T-1 deploy-hetzner-server), the connector ships as a compose service alongside the applying project's other services on the same web-net network; when the host runs bare (only T-1 applied), the connector ships as a systemd unit per the cloudflared as-a-service local-configuration-file docs. Either shape emits cloudflaredReady on boot with connector id, region and version metadata (metadata only; no token or tunnel credentials in the payload). Chain: HQ round-7 T-3 reserved-block per HQ chain-block ruling 2026-09-07 (REQ-130..139 / TS-160..169 / FBS-150..159 / CN-470..499). Round-7 T-3 track of hetzner-round-7-spec-2026-09-07 section 5.3.",
|
|
5
5
|
"reqId": "REQ-130",
|
|
6
6
|
"prdId": "PRD-001",
|
|
@@ -28,5 +28,9 @@
|
|
|
28
28
|
"match": "credential"
|
|
29
29
|
}
|
|
30
30
|
]
|
|
31
|
-
}
|
|
31
|
+
},
|
|
32
|
+
"tags": [
|
|
33
|
+
"capability:edge-security",
|
|
34
|
+
"capability:platform-integrations"
|
|
35
|
+
]
|
|
32
36
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"createdAt": "2026-09-08T03:20:33.475Z",
|
|
3
|
-
"updatedAt": "2026-09-
|
|
3
|
+
"updatedAt": "2026-09-22T13:47:34.538Z",
|
|
4
4
|
"description": "The applying project ships one tunnel manifest per named tunnel at cloudflare/tunnels/<name>.yaml. The schema requires: a tunnel id (uuid-shaped string), a credentials-file reference into security-secrets-management (secretRef, never a literal path or JSON body inline), and an ingress rules array mapping public hostname to internal service URL with a mandatory catch-all rule returning http_status 404. The manifest is the single source of truth for what the connector serves; cloudflared refuses to boot if it fails the shipped JSON-schema validation. Chain: HQ round-7 T-3 reserved-block per HQ chain-block ruling 2026-09-07. Round-7 T-3 track of hetzner-round-7-spec-2026-09-07 section 5.3.",
|
|
5
5
|
"reqId": "REQ-131",
|
|
6
6
|
"prdId": "PRD-001",
|
|
@@ -50,5 +50,9 @@
|
|
|
50
50
|
"match": "schema"
|
|
51
51
|
}
|
|
52
52
|
]
|
|
53
|
-
}
|
|
53
|
+
},
|
|
54
|
+
"tags": [
|
|
55
|
+
"capability:edge-security",
|
|
56
|
+
"capability:platform-integrations"
|
|
57
|
+
]
|
|
54
58
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"createdAt": "2026-09-08T03:20:33.710Z",
|
|
3
|
-
"updatedAt": "2026-09-
|
|
3
|
+
"updatedAt": "2026-09-22T13:47:34.538Z",
|
|
4
4
|
"description": "The applying project MUST NOT open a public port on the host firewall for the origin path when only edge-cloudflare-tunnel provides ingress. T-1 deploy-hetzner-server's firewall shape allows port 22 unconditionally and ports 80/443 only when a reverse proxy is applied on the host. A project that applies only T-1 plus T-3 (no reverse proxy) declares zero 80/443 firewall rules; the tunnel manifest schema check refuses the apply if an ingress rule tries to bind a port on the host directly (the ingress URL must reference an internal address, never the public interface). Chain: HQ round-7 T-3 reserved-block per HQ chain-block ruling 2026-09-07. Round-7 T-3 track of hetzner-round-7-spec-2026-09-07 section 5.3.",
|
|
5
5
|
"reqId": "REQ-132",
|
|
6
6
|
"prdId": "PRD-001",
|
|
@@ -23,5 +23,9 @@
|
|
|
23
23
|
"match": "schema"
|
|
24
24
|
}
|
|
25
25
|
]
|
|
26
|
-
}
|
|
26
|
+
},
|
|
27
|
+
"tags": [
|
|
28
|
+
"capability:edge-security",
|
|
29
|
+
"capability:platform-integrations"
|
|
30
|
+
]
|
|
27
31
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"createdAt": "2026-09-08T03:20:33.944Z",
|
|
3
|
-
"updatedAt": "2026-09-
|
|
3
|
+
"updatedAt": "2026-09-22T13:47:34.538Z",
|
|
4
4
|
"description": "The blueprint reads the applying project's sidecar rcf/blueprints/edge-cloudflare-tunnel.applied.json at apply time and inspects appliedCapabilities. When zeroTrustGate is present (i.e. edge-cloudflare-access v1.0.0 has been applied on the same project), every ingress rule under the tunnel manifest attaches an originRequest.access block naming the Access AUD; cloudflared then refuses at the edge any request that arrives without a valid Access JWT for that AUD. When zeroTrustGate is absent, the block is omitted and the tunnel serves in public-hostname mode (open ingress on the public hostname). The aud-presence-check probe asserts the shape flips correctly on both fixture variants; the shape MUST NOT silently degrade to open ingress on a project that intended the gated shape. Chain: HQ round-7 T-3 reserved-block per HQ chain-block ruling 2026-09-07. Round-7 T-3 track of hetzner-round-7-spec-2026-09-07 section 5.3.",
|
|
5
5
|
"reqId": "REQ-133",
|
|
6
6
|
"prdId": "PRD-001",
|
|
@@ -16,5 +16,9 @@
|
|
|
16
16
|
],
|
|
17
17
|
"reason": "keyword-scan",
|
|
18
18
|
"classifiedAt": "2026-09-08T03:20:33.989Z"
|
|
19
|
-
}
|
|
19
|
+
},
|
|
20
|
+
"tags": [
|
|
21
|
+
"capability:edge-security",
|
|
22
|
+
"capability:platform-integrations"
|
|
23
|
+
]
|
|
20
24
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"createdAt": "2026-09-08T03:20:34.180Z",
|
|
3
|
-
"updatedAt": "2026-09-
|
|
3
|
+
"updatedAt": "2026-09-22T13:47:34.538Z",
|
|
4
4
|
"description": "The tunnel credentials file the cloudflared connector reads at boot MUST land on the host at mode 0o400 (owner read only), MUST be referenced from the tunnel manifest as a secretRef (never as a literal path to a committed file), MUST NOT be committed to the applying project's git tree (a grep across the working tree for the credentials-file body's uuid-shaped tunnel id and its account-tag literal refuses if either appears in a tracked file), and MUST NOT appear in any cloudflaredReady, tunnelConnectorUp or ingressRuleReloaded event body. A leaked credentials file gives an attacker lateral movement across every hostname the tunnel serves; the discipline is defensive against silent loss. Chain: HQ round-7 T-3 reserved-block per HQ chain-block ruling 2026-09-07. Round-7 T-3 track of hetzner-round-7-spec-2026-09-07 section 5.3.",
|
|
5
5
|
"reqId": "REQ-134",
|
|
6
6
|
"prdId": "PRD-001",
|
|
@@ -38,5 +38,9 @@
|
|
|
38
38
|
"match": "credential"
|
|
39
39
|
}
|
|
40
40
|
]
|
|
41
|
-
}
|
|
41
|
+
},
|
|
42
|
+
"tags": [
|
|
43
|
+
"capability:edge-security",
|
|
44
|
+
"capability:platform-integrations"
|
|
45
|
+
]
|
|
42
46
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"createdAt": "2026-09-08T09:02:25.166Z",
|
|
3
|
-
"updatedAt": "2026-09-
|
|
3
|
+
"updatedAt": "2026-09-22T13:47:34.538Z",
|
|
4
4
|
"description": "The object-storage-s3 blueprint gains a Hetzner Object Storage provider value under its shipped v1.0.0 S3-API facade contract. The delta adds an endpoint-shape helper hetzner-endpoint.mjs composing the vendor-documented pattern <bucket>.<location>.your-objectstorage.com from an elicited bucket and location (fsn1 fal, hel1 hel, nbg1 nur per the Hetzner storage overview); a new probe hetzner-object-storage-round-trip.mjs drives put/get/delete against the composed endpoint with accountBound true gated on CI_HAS_HETZNER_OBJECT_STORAGE (records accountBoundSkipped when unset per spec section 3.5); one blueprint-owned REQ (object-storage-s3-REQ-101) and one blueprint-owned US (object-storage-s3-US-28110) anchor the AC AC-28110-1; one blueprint TAC (TAC-2904-object-storage-s3-hetzner-endpoint-helper) formalises the helper contract; one blueprint ADR (ADR-2905-object-storage-s3-hetzner-object-storage-provider, scope local) documents the Hetzner provider value alongside R2, AWS, MinIO with standardsTraceClause Hetzner Object Storage S3 compatibility documented endpoint shape. The existing MinIO local emulator round-trip and R2 real-account smoke stay byte-identical; blueprint bumps 1.0.0 to 1.1.0; rcf-lite package version does NOT bump (spec 8). Chain: HQ round-7 follow-up per HQ chain-block ruling 2026-09-08 (adapter block REQ-140..144, TS-170..174, FBS-160..164, CN-500..509). Section 5.4 of hetzner-round-7-spec-2026-09-07.",
|
|
5
5
|
"reqId": "REQ-140",
|
|
6
6
|
"prdId": "PRD-001",
|
|
@@ -145,5 +145,8 @@
|
|
|
145
145
|
"match": "endpoint"
|
|
146
146
|
}
|
|
147
147
|
]
|
|
148
|
-
}
|
|
148
|
+
},
|
|
149
|
+
"tags": [
|
|
150
|
+
"capability:applications-shelf"
|
|
151
|
+
]
|
|
149
152
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"createdAt": "2026-09-08T10:50:11.871Z",
|
|
3
|
-
"updatedAt": "2026-09-
|
|
3
|
+
"updatedAt": "2026-09-22T13:47:34.538Z",
|
|
4
4
|
"description": "H-1 patch train against deploy-hetzner-server 1.0.0 shipped in rcf-lite 0.25.0 (real-account gate d-2026-09-08-010 report). Nine defects; every real-account probe throws before writing the scratch id file so destroy cannot tear the server down. This REQ adds the standing requirement that mocked probes for deploy-hetzner-server consume the same rendered cloud-init user-data the real path consumes (renderer writes the file; mock and real path both read it) and that the rendered user-data carries a real ssh public-key line for the deploy user plus NOPASSWD sudo for that user; that provision.mjs projects snake_case hcloud fields; that destroy.mjs and sweep-orphans.mjs never pass --output json to a delete verb (accepts arrays or objects); that snapshot-verb.mjs shells hcloud server create-image --type snapshot; that ssh baseline checks poll ssh readiness before firing and shell NOPASSWD sudo; and that the manifest ssh-key name is overridable via RCF_LITE_CI_SSH_KEY_NAME. Domain functional. Chain: HQ hardening block H-1 per HQ chain-block ruling 2026-09-08 (REQ-145..149 / TS-175..179 / FBS-165..169 / CN-510..519). Blueprint version 1.0.0 to 1.0.1; every existing contribution id byte-identical.",
|
|
5
5
|
"reqId": "REQ-145",
|
|
6
6
|
"prdId": "PRD-001",
|
|
@@ -49,5 +49,8 @@
|
|
|
49
49
|
"match": "delete"
|
|
50
50
|
}
|
|
51
51
|
]
|
|
52
|
-
}
|
|
52
|
+
},
|
|
53
|
+
"tags": [
|
|
54
|
+
"capability:deploy"
|
|
55
|
+
]
|
|
53
56
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"createdAt": "2026-09-08T12:16:28.007Z",
|
|
3
|
-
"updatedAt": "2026-09-
|
|
3
|
+
"updatedAt": "2026-09-21T17:00:00.000Z",
|
|
4
4
|
"description": "The rcf-lite platform-cloudflare-kv blueprint ships eight approved user stories (US-31101..US-31108) with nine ACs (AC-31101-1, AC-31102-1, AC-31103-1, AC-31103-2, AC-31104-1, AC-31105-1, AC-31106-1, AC-31107-1, AC-31108-1). Its five contributed probes and the README still anchor the defunct AC-5001..AC-5401 id band that never became chain rows on this repo. This train re-anchors every probe result and the README chain-slice pointers to the shipped AC-31xxx band per Dave ruling 4 (2026-09-08 relay 582c2bca): do NOT resurrect the AC-5xxx stories, move the probes to the shipped band. Every one of the nine shipped kv ACs must appear as an anchor (primary or additional result) on at least one probe with a runtime observable; the two ACs no shipped probe currently covers (AC-31102-1 sole-reader grep, AC-31107-1 whitelist-only lifecycle event scan) are added as additional results on facade-round-trip and event-secrecy per the dispatch addendum. Anatomy-test assertions move with the re-anchor per dispatch addendum ruling 1. No capability change; 0.25.x patch scope; runtime surface unchanged.",
|
|
5
5
|
"category": "functional",
|
|
6
6
|
"domain": "functional",
|
|
@@ -16,5 +16,9 @@
|
|
|
16
16
|
],
|
|
17
17
|
"reason": "keyword-scan",
|
|
18
18
|
"classifiedAt": "2026-09-08T12:16:28.156Z"
|
|
19
|
-
}
|
|
19
|
+
},
|
|
20
|
+
"tags": [
|
|
21
|
+
"capability:verify",
|
|
22
|
+
"capability:platform-integrations"
|
|
23
|
+
]
|
|
20
24
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"createdAt": "2026-09-08T12:16:28.590Z",
|
|
3
|
-
"updatedAt": "2026-09-
|
|
3
|
+
"updatedAt": "2026-09-21T17:00:00.000Z",
|
|
4
4
|
"description": "The rcf-lite platform-cloudflare-durable-objects blueprint ships thirteen ACs (AC-33101-1..AC-33113-1); eight probes anchor AC-33101, 33102, 33103, 33104, 33105, 33107, 33112, 33113, leaving AC-33106-1, AC-33108-1, AC-33109-1, AC-33110-1, AC-33111-1 unbound. real-account-storage-smoke.mjs currently returns pass on credential readiness alone. This train replaces the credential-readiness pass-stub with a real storage round-trip driver: when CI_HAS_CLOUDFLARE_ACCOUNT is set with CF_ACCOUNT_ID, CF_DO_NAMESPACE_ID (or the binding config the driver needs) and CF_API_TOKEN, the probe drives an HTTP round trip against a deployed Worker route that opens the DO facade, writes a fixture key, reads it back, asserts the returned bytes equal the written value. Local proof against miniflare or wrangler dev via the existing wrangler-seam. Env-absent branch keeps the section 3.5 pass-with-skip shape; a pass must never again be reachable from credential presence alone. The five unbound ACs are bound as additional-result anchors on the existing wrangler-seam, storage-round-trip and concurrent-increment probes (or a new probe body inside existing capability if none carries the observable honestly).",
|
|
5
5
|
"category": "functional",
|
|
6
6
|
"domain": "functional",
|
|
@@ -81,5 +81,9 @@
|
|
|
81
81
|
"match": "storage"
|
|
82
82
|
}
|
|
83
83
|
]
|
|
84
|
-
}
|
|
84
|
+
},
|
|
85
|
+
"tags": [
|
|
86
|
+
"capability:verify",
|
|
87
|
+
"capability:platform-integrations"
|
|
88
|
+
]
|
|
85
89
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"createdAt": "2026-09-08T12:16:29.086Z",
|
|
3
|
-
"updatedAt": "2026-09-
|
|
3
|
+
"updatedAt": "2026-09-21T17:00:00.000Z",
|
|
4
4
|
"description": "The rcf-lite messaging-queue-cloudflare blueprint's real-account-concurrency-smoke.mjs returns verdict pass with accountBoundSkipped true on the account-set branch (the wrangler dev --remote path is unsupported for Queues, so a real-account run must ride a deployed Worker that binds the queue). This train replaces that pass-stub with a real concurrency driver: the account-set branch publishes 500 messages through the producer facade wired to a live Queues binding on a deployed Worker (queue name and binding parameterised via env; HQ supplies values at gate time, canonical queue rcf-lite-ci-queue-smoke) and asserts concurrent processing up to the documented push-invocation cap. Local proof against miniflare or wrangler dev (local queue simulation). The env-absent branch keeps pass-with-skip. The documented Cloudflare Queues limits URL is re-verified 200 at merge time and logged in the PR provenance.",
|
|
5
5
|
"category": "functional",
|
|
6
6
|
"domain": "functional",
|
|
@@ -16,5 +16,9 @@
|
|
|
16
16
|
],
|
|
17
17
|
"reason": "keyword-scan",
|
|
18
18
|
"classifiedAt": "2026-09-08T12:16:29.218Z"
|
|
19
|
-
}
|
|
19
|
+
},
|
|
20
|
+
"tags": [
|
|
21
|
+
"capability:verify",
|
|
22
|
+
"capability:platform-integrations"
|
|
23
|
+
]
|
|
20
24
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"createdAt": "2026-09-08T12:16:29.584Z",
|
|
3
|
-
"updatedAt": "2026-09-
|
|
3
|
+
"updatedAt": "2026-09-21T17:00:00.000Z",
|
|
4
4
|
"description": "The rcf-lite edge-cloudflare-tunnel blueprint's two real-account probes return warn when the env vars ARE set (account-bound path present but not exercised) and manifest-schema-validate warns on a missing credentials placeholder. This train replaces both warn-on-env stubs with real drivers and converts the placeholder to a fail. real-account-connector-healthy: with both CI_HAS_CLOUDFLARE_ACCOUNT and CI_HAS_HETZNER_ACCOUNT set, provision the throwaway server through the T-1 hetzner fixture surface, run cloudflared tunnel info <name> through a cloudflared control shim, assert healthy connector count, capture the tunnelConnectorUp event. Consume the hetzner fixture as-is; its defects are H-1 scope at HQ; if the fixture path fails locally the driver fails with a pointer naming the fixture step, never warn. real-account-tunnel-hostname-routes: undici fetch driver for the public-hostname sub-case activated on CI_HAS_CLOUDFLARE_ACCOUNT; two-identity JWT driver for the access-gated sub-case activated only when CI_HAS_CLOUDFLARE_ACCESS is ALSO set (HQ note: Access is not enabled on the HQ account, so the AUD sub-case stays pass-with-skip until HQ enables Access). Env-absent branch keeps pass-with-skip; a pass must never again be reachable from account-flag presence alone. manifest-schema-validate.mjs missing-credentials-placeholder becomes FAIL with a fixture-setup pointer.",
|
|
5
5
|
"category": "functional",
|
|
6
6
|
"domain": "functional",
|
|
@@ -55,5 +55,9 @@
|
|
|
55
55
|
"match": "credential"
|
|
56
56
|
}
|
|
57
57
|
]
|
|
58
|
-
}
|
|
58
|
+
},
|
|
59
|
+
"tags": [
|
|
60
|
+
"capability:verify",
|
|
61
|
+
"capability:platform-integrations"
|
|
62
|
+
]
|
|
59
63
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"createdAt": "2026-09-08T12:16:30.083Z",
|
|
3
|
-
"updatedAt": "2026-09-
|
|
3
|
+
"updatedAt": "2026-09-21T17:00:00.000Z",
|
|
4
4
|
"description": "The four Cloudflare-platform blueprints (platform-cloudflare-kv, platform-cloudflare-durable-objects, messaging-queue-cloudflare, edge-cloudflare-tunnel) carry mutation-purity, envelope-hygiene and marker-wording defects surfaced by stage-2 semantic and stage-1 mechanical passes: SIMULATE_ env reads in probe bodies (cache-aside-hit-then-miss, event-secrecy, sole-reader-scan, storage-round-trip, websocket-hub-broadcast); a committed fail envelope at .rcf/reports/blueprints/platform-cloudflare-kv/event-secrecy.json; comments labelling local doubles as fake state / fake WebSocket pair / fake clock in ways the stage-1 marker sweep flagged. This train moves every probe-body SIMULATE_ branch into a fixture-side shim under packages/rcf-lite/test/fixtures/cf-platform/ or .../cf-edge/ (new shim files carry the h2-cf-platform-probe-integrity slug prefix, short form h2-cf acceptable), deletes the committed fail envelope and commits a shipped-code pass envelope in its place, regenerates the other kv envelopes so committed envelopes reflect the re-anchored shipped-code runs, and reworks probe comments to name the local test doubles honestly (or records adjudicated-acceptable with reason in the PR body). No capability change; 0.25.x patch scope.",
|
|
5
5
|
"category": "functional",
|
|
6
6
|
"domain": "functional",
|
|
@@ -40,5 +40,8 @@
|
|
|
40
40
|
"match": "delete"
|
|
41
41
|
}
|
|
42
42
|
]
|
|
43
|
-
}
|
|
43
|
+
},
|
|
44
|
+
"tags": [
|
|
45
|
+
"capability:verify"
|
|
46
|
+
]
|
|
44
47
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"createdAt": "2026-09-16T22:20:45Z",
|
|
3
|
-
"updatedAt": "2026-09-
|
|
3
|
+
"updatedAt": "2026-09-21T17:00:00.000Z",
|
|
4
4
|
"description": "Referee-guarantees docs page (how-it-works/what-the-referee-guarantees) promises that `rcf define validate` proves every reference in every document resolves, so a walked tree that passes has nothing pointing at nothing. The 0.27.0 walker checks the parent-id fields and the FBS / TS / EVAL / CN cross-links, but two ADR-schema-declared reference fields, supersededBy and relatedAdrs, are declared in the ADR schema without being walked: a bad target passes validate. This train closes the gap by walking both fields inside collectBrokenReferences, keeping the existing brokenReference error kind, and reporting the exact ADR file + field on failure. Chain: referee-guarantees docs claims C-7 and C-38 (audit at reviews/2026-09-15-docs-claims-audit/how-it-works__what-the-referee-guarantees.json). No schema change (the schema already declares both fields); rcf-lite behaviour widens, and any project whose ADRs have stale supersession pointers surfaces the defect the next time validate runs.",
|
|
5
5
|
"category": "functional",
|
|
6
6
|
"domain": "functional",
|
|
@@ -9,5 +9,8 @@
|
|
|
9
9
|
"prdId": "PRD-001",
|
|
10
10
|
"title": "Referee guarantee: `rcf define validate` walks every schema-declared reference field on ADR (supersededBy, relatedAdrs) so the docs-page 'nothing points at nothing' claim holds",
|
|
11
11
|
"version": "0.1.0",
|
|
12
|
-
"status": "draft"
|
|
12
|
+
"status": "draft",
|
|
13
|
+
"tags": [
|
|
14
|
+
"capability:verify"
|
|
15
|
+
]
|
|
13
16
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"createdAt": "2026-09-16T22:28:54Z",
|
|
3
|
-
"updatedAt": "2026-09-
|
|
3
|
+
"updatedAt": "2026-09-21T17:00:00.000Z",
|
|
4
4
|
"description": "Referee-guarantees docs page states without qualification that a requirement counts as covered only when every acceptance criterion beneath it has a resolving Test Case, and that a stub or stale pointer fails the coverage gate exactly as a missing test does when the displayed command (`rcf audit coverage`) is run. The 0.27.0 shipped default is shallow-any, so the plain command does not enforce that; strict is per-AC-strict but is opt-in via `--strict`. This train flips the shipped default: strict is the default, `--mode shallow-any` is the explicit opt-out for author-time exploration (prints gaps, exits 0), and the legacy `--strict` flag stays as a no-op alias so existing CI, blueprints and dogfood scripts stay green. `--mode shallow-any --strict` is a usage refusal (exit 2) so a scripted invocation cannot silently disagree with itself. CHANGELOG carries a migration note under [Unreleased]. Repo's own CI dogfood invocation is updated to the shipped default. Closes referee-guarantees docs claims C-11 and C-14 (audit at reviews/2026-09-15-docs-claims-audit/how-it-works__what-the-referee-guarantees.json).",
|
|
5
5
|
"category": "functional",
|
|
6
6
|
"domain": "functional",
|
|
@@ -9,5 +9,8 @@
|
|
|
9
9
|
"prdId": "PRD-001",
|
|
10
10
|
"title": "Referee guarantee: `rcf audit coverage` is strict-by-default; `--mode shallow-any` is the explicit opt-out; `--strict` remains a no-op alias",
|
|
11
11
|
"version": "0.1.0",
|
|
12
|
-
"status": "draft"
|
|
12
|
+
"status": "draft",
|
|
13
|
+
"tags": [
|
|
14
|
+
"capability:verify"
|
|
15
|
+
]
|
|
13
16
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"createdAt": "2026-09-16T22:38:04Z",
|
|
3
|
-
"updatedAt": "2026-09-
|
|
3
|
+
"updatedAt": "2026-09-21T17:00:00.000Z",
|
|
4
4
|
"description": "Referee-guarantees docs page promises that `rcf build finalise` is the only path that writes verified, that a chain that says verified traces to an actual post-merge runtime check, and that the finalise gate refuses on the three per-AC verdicts the aggregator already emits: UI-BASELINE-UNMET (docs claim C-28; also covers a block-severity probe-pack failure, C-36), BROWSER-VERIFICATION-MISSING (C-29) and SCOPE-MISMATCH (C-30). The 0.27.0 finalise CLI only branched on MOCK-ONLY-DECLARED / BLOCKED-BY-DECLARATION and EVAL-MISSING / EVAL-BELOW-THRESHOLD; the three new verdicts were derived on the report but did not gate finalise. The manual override path (`rcf define update FBS.executionStatus=verified`) was accepted by the writer, defeating the C-22 promise. This train wires the three per-AC refusals in finalise (no ack path: the refusals are honest; fix the AC or its scope), gates the manual override behind `--acknowledge-verified-override` on `rcf define update` (per the escalation clause: existing WSD projects may still need the escape valve; the writer's default is now the documented behaviour), and adds a git default-branch precondition to finalise with `--allow-pre-merge` as the deliberate pre-merge dry-run opt-out. Closes referee-guarantees docs claims C-22 / C-26 / C-28 / C-29 / C-30 / C-36 (audit at reviews/2026-09-15-docs-claims-audit/how-it-works__what-the-referee-guarantees.json). C-33 (shipWithoutEval manifest field) remains open: the write path already exists (skips schema validation), but the rcf-schemas 0.6.2 manifest schema does not yet declare the field; the exact delta needed lands in the ship-without-eval.js comment and in the report for this dispatch. C-38 (per-check applicable:false in browserVerificationProbePackCheck) is also blocked on the rcf-schemas bump; source comments already flag it.",
|
|
5
5
|
"category": "functional",
|
|
6
6
|
"domain": "functional",
|
|
@@ -9,5 +9,8 @@
|
|
|
9
9
|
"prdId": "PRD-001",
|
|
10
10
|
"title": "Referee guarantee: `rcf build finalise` refuses UI-BASELINE-UNMET / BROWSER-VERIFICATION-MISSING / SCOPE-MISMATCH; verified traces to a post-merge run; manual override is gated",
|
|
11
11
|
"version": "0.1.0",
|
|
12
|
-
"status": "draft"
|
|
12
|
+
"status": "draft",
|
|
13
|
+
"tags": [
|
|
14
|
+
"capability:verify"
|
|
15
|
+
]
|
|
13
16
|
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"createdAt": "2026-09-21T16:52:32.174Z",
|
|
3
|
+
"updatedAt": "2026-09-21T17:00:00.000Z",
|
|
4
|
+
"description": "The RCF review surface offers a Product Map tab in addition to Overview, Requirements, Architecture and Build sequence. The tab lets a product reader group requirements by shape, status, component (TAC), trace coverage or capability. Every grouping drills group -> requirement (with a status pill) -> its user stories -> acceptance criteria. Groupings and the status filter are hash-addressable so a URL of the form #tab=product-map&group=capability&status=approved is deep-linkable and shareable.",
|
|
5
|
+
"reqId": "REQ-170",
|
|
6
|
+
"prdId": "PRD-001",
|
|
7
|
+
"title": "Product Map tab on the review surface",
|
|
8
|
+
"category": "functional",
|
|
9
|
+
"domain": "reviewSurface",
|
|
10
|
+
"priority": "must",
|
|
11
|
+
"version": "0.1.0",
|
|
12
|
+
"status": "draft",
|
|
13
|
+
"shapeClassification": {
|
|
14
|
+
"shapes": [
|
|
15
|
+
"webUi"
|
|
16
|
+
],
|
|
17
|
+
"reason": "keyword-scan",
|
|
18
|
+
"classifiedAt": "2026-09-21T16:52:32.226Z",
|
|
19
|
+
"signals": [
|
|
20
|
+
{
|
|
21
|
+
"source": "description",
|
|
22
|
+
"shape": "webUi",
|
|
23
|
+
"match": "component"
|
|
24
|
+
}
|
|
25
|
+
]
|
|
26
|
+
},
|
|
27
|
+
"rationale": "The Requirements tab is a flat REQ list ordered by id. A product reader (operator or reviewer) does not think in that shape - they think in surfaces, capabilities, states, and what has and has not been built yet. The Product Map tab re-buckets the same in-memory tree by the axes the data actually populates (shape 65%, status 100%) and by two derived axes (component-first via TAC, and trace coverage), plus a convention-driven capability grouping. No schema change; all work is a re-bucketing of the tree-model the view already builds.",
|
|
28
|
+
"tags": [
|
|
29
|
+
"capability:review-surface",
|
|
30
|
+
"product-map",
|
|
31
|
+
"view"
|
|
32
|
+
]
|
|
33
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"createdAt": "2026-09-21T16:52:37.436Z",
|
|
3
|
+
"updatedAt": "2026-09-21T17:00:00.000Z",
|
|
4
|
+
"description": "Requirements carry one or more capability slugs on their existing free-form tags array using the convention capability:<kebab-slug>. A capability taxonomy for the rcf-lite product itself is documented in the rcf-lite docs, alongside the rule for adding a new capability. This is a convention that rides on the shipped schema; no schema change. The Product Map by-capability grouping is the consumer that proves the convention works on real data.",
|
|
5
|
+
"reqId": "REQ-171",
|
|
6
|
+
"prdId": "PRD-001",
|
|
7
|
+
"title": "Capability tag convention on requirements",
|
|
8
|
+
"category": "functional",
|
|
9
|
+
"domain": "requirementsAuthoring",
|
|
10
|
+
"priority": "must",
|
|
11
|
+
"version": "0.1.0",
|
|
12
|
+
"status": "draft",
|
|
13
|
+
"shapeClassification": {
|
|
14
|
+
"shapes": [
|
|
15
|
+
"webUi",
|
|
16
|
+
"persistence"
|
|
17
|
+
],
|
|
18
|
+
"reason": "keyword-scan",
|
|
19
|
+
"classifiedAt": "2026-09-21T16:52:37.488Z",
|
|
20
|
+
"signals": [
|
|
21
|
+
{
|
|
22
|
+
"source": "description",
|
|
23
|
+
"shape": "webUi",
|
|
24
|
+
"match": "form"
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"source": "description",
|
|
28
|
+
"shape": "persistence",
|
|
29
|
+
"match": "schema"
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"source": "description",
|
|
33
|
+
"shape": "persistence",
|
|
34
|
+
"match": "schema"
|
|
35
|
+
}
|
|
36
|
+
]
|
|
37
|
+
},
|
|
38
|
+
"rationale": "Analysis d-019 established that the shipped schema has no capability or feature level between PRD and REQ. The trial answers whether a lightweight convention on the existing tags array carries a usable product taxonomy without a schema change. If the tags and the by-capability view earn their keep, the capability level is promoted to a proper schema field later; if not, nothing was spent.",
|
|
39
|
+
"tags": [
|
|
40
|
+
"capability:requirements-authoring",
|
|
41
|
+
"capability:review-surface",
|
|
42
|
+
"capability-tags-trial"
|
|
43
|
+
]
|
|
44
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"createdAt": "2026-09-24T12:00:00Z",
|
|
3
|
+
"updatedAt": "2026-09-24T12:00:00Z",
|
|
4
|
+
"reqId": "REQ-172",
|
|
5
|
+
"prdId": "PRD-001",
|
|
6
|
+
"title": "DEFINE delta detection and freeze record foundation",
|
|
7
|
+
"description": "rcf-lite gains three pure primitives and one durable record. hashDocument returns a sha256:<hex> hash over the canonical JSON of a parsed document (keys sorted recursively, no whitespace). computeTreeHash hashes the sorted (id, docHash) pairs. computeDelta(tree, freeze, ledgers) returns the whole change model of the proposal (2026-09-22 v3) section 2.2: frozen, frozenAt, treeHash, currentTreeHash, changed, added, removed, briefSince, unchanged. docHashes cover every standalone document the walker exposes on tree.byId (PRD, TAD, BS, REQ, US, TAC, ADR, FBS, TS, CN, EVAL) plus one ledger:<name> entry per sidecar the caller passes in. Before the first freeze the delta is the whole tree (frozen false, everything in added). The freeze record itself sits at rcf/define/freeze.json (owned by rcf-lite, outside the shared rcf-schemas package until 0.7) with a small local schema and a reader/writer module: reading a missing file returns null, a malformed file raises a clear error. No rcf define freeze verb yet; the writer the verb will call is exposed for slice 3.",
|
|
8
|
+
"category": "functional",
|
|
9
|
+
"domain": "defineDetection",
|
|
10
|
+
"priority": "must",
|
|
11
|
+
"version": "0.1.0",
|
|
12
|
+
"status": "draft",
|
|
13
|
+
"shapeClassification": {
|
|
14
|
+
"shapes": ["persistence"],
|
|
15
|
+
"reason": "keyword-scan",
|
|
16
|
+
"classifiedAt": "2026-09-24T12:00:00Z",
|
|
17
|
+
"signals": [
|
|
18
|
+
{ "source": "description", "shape": "persistence", "match": "record" }
|
|
19
|
+
]
|
|
20
|
+
},
|
|
21
|
+
"rationale": "Barry's backstory dogfood found DEFINE generated too fast with no gates. Baz ruled 2026-09-22 that the fix is detection over configured change records: the freeze remembers what the tree looked like; anything that differs is the change. The delta.js primitives are what every later slice (gates, readiness, freeze verb, bundle read, viewer tab) consumes, so their return shape is a contract worth pinning early. Canonical-JSON hashing (over raw bytes) is the difference between a real change and a hand reformat; document granularity (over criterion granularity) keeps the model cheap while git supplies the criterion-level diff.",
|
|
22
|
+
"tags": [
|
|
23
|
+
"capability:define-detection"
|
|
24
|
+
]
|
|
25
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"createdAt": "2026-09-24T12:00:00Z",
|
|
3
|
+
"updatedAt": "2026-09-24T12:00:00Z",
|
|
4
|
+
"reqId": "REQ-173",
|
|
5
|
+
"prdId": "PRD-001",
|
|
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.",
|
|
8
|
+
"category": "functional",
|
|
9
|
+
"domain": "defineLedgers",
|
|
10
|
+
"priority": "must",
|
|
11
|
+
"version": "0.1.0",
|
|
12
|
+
"status": "draft",
|
|
13
|
+
"shapeClassification": {
|
|
14
|
+
"shapes": ["persistence"],
|
|
15
|
+
"reason": "keyword-scan",
|
|
16
|
+
"classifiedAt": "2026-09-24T12:00:00Z",
|
|
17
|
+
"signals": [
|
|
18
|
+
{ "source": "description", "shape": "persistence", "match": "record" }
|
|
19
|
+
]
|
|
20
|
+
},
|
|
21
|
+
"rationale": "The proposal (2026-09-22 v3, section 8.2) makes ledgers the seam every later DEFINE stage draws from: D1 reads the brief ledger, D5 the concern ledger, D6 the probe ledger, D7 the decisions ledger, and D2's greenfield resolution walks the brief statements. Building the sidecars and the CLI now, before any gate reads them, keeps slice 2 free of write-side surprises. Baz's ruling of 2026-09-22 (decision 5) fixed the ownership: sidecars in rcf-lite until schemas 0.7 promotes them to manifest records. Precedent: .rcf/preflight-secrets.local.json is an rcf-lite-owned file outside the shared schema; rcf/define/ follows the same shape.",
|
|
22
|
+
"tags": [
|
|
23
|
+
"capability:define-ledgers"
|
|
24
|
+
]
|
|
25
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"createdAt": "2026-09-24T14:30:00Z",
|
|
3
|
+
"updatedAt": "2026-09-24T14:30:00Z",
|
|
4
|
+
"reqId": "REQ-174",
|
|
5
|
+
"prdId": "PRD-001",
|
|
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.",
|
|
8
|
+
"category": "functional",
|
|
9
|
+
"domain": "defineDetection",
|
|
10
|
+
"priority": "must",
|
|
11
|
+
"version": "0.1.0",
|
|
12
|
+
"status": "draft",
|
|
13
|
+
"shapeClassification": {
|
|
14
|
+
"shapes": ["persistence"],
|
|
15
|
+
"reason": "keyword-scan",
|
|
16
|
+
"classifiedAt": "2026-09-24T14:30:00Z",
|
|
17
|
+
"signals": [
|
|
18
|
+
{ "source": "description", "shape": "persistence", "match": "record" }
|
|
19
|
+
]
|
|
20
|
+
},
|
|
21
|
+
"rationale": "Baz ruled on 2026-09-22 (proposal section 9, decision 2) that gates block where the data exists and warn-with-ack for D3, D5 and D6 until 0.31 (Baz ruled 2026-09-24 that 0.31 renumbers to 0.30, so this train ships D3/D5/D6 as warn-with-ack in 0.29.0). One check function per stage is the seam every later consumer reads: the readiness view (REQ-175) composes them, the freeze verb (slice 3) refuses on any failing stage, the viewer's Readiness tab (slice 5) prints the same checks[]. Building the check functions now, with cheap data-backed checks only, keeps 0.29.0 shippable while leaving named seams for 0.30's template parser, entity join, catalogue walk, probe runner and consistency scans.",
|
|
22
|
+
"tags": [
|
|
23
|
+
"capability:define-detection"
|
|
24
|
+
]
|
|
25
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"createdAt": "2026-09-24T14:30:00Z",
|
|
3
|
+
"updatedAt": "2026-09-24T14:30:00Z",
|
|
4
|
+
"reqId": "REQ-175",
|
|
5
|
+
"prdId": "PRD-001",
|
|
6
|
+
"title": "computeReadiness and the rcf define readiness CLI verb",
|
|
7
|
+
"description": "rcf-lite gains src/query/readiness.js with computeReadiness(tree, { freeze, ledgers, profile, testPointers }) returning the exact section 2.4 shape { tree, delta, stages, nextAction, coverage, decisions, freezeable }. computeReadiness composes computeDelta (slice 1), calls computeImpact once per id in changed union added (the union is the fan-out; impacted names every id, impactedFbs names the re-execute subset), runs the gates D1..D8 over scope = changed union added union impacted ids, calls computeCoverage tree-wide plus per REQ ancestor of the delta (using the testPointers map the CLI produces exactly as src/cli/coverage.js builds it), lists open decisions (in the #241 numbered format from the decisions ledger), derives a nextAction { stage, check, ids, command } from the first failing gate, and reports freezeable when every stage state is passed, acknowledged or notApplicable. rcf-lite also gains src/cli/readiness.js implementing rcf define readiness [--json] [--check <stage>|all] (stage accepts D1..D8 or the gate short name: brief, skeleton, shapes, stories, crosscut, consistency, decisions, freeze). Text output: tree line, next action, stage chips, delta list, failing items. --check exits 0 green, 4 red (matching coverage refusal exit); warn-with-ack stages failing but unacknowledged exit 0 with a visible warning. The producer is wrapped with runWithAdmissibilityGate as the ruleset toolScope requires. loadAllLedgers (src/define/ledgers.js) is corrected so a project that never authored a ledger does not get ledger:<name> hashes in the docHashes map (slice-1 P3 resolution: code and JSDoc agree that absent ledger files contribute no docHash).",
|
|
8
|
+
"category": "functional",
|
|
9
|
+
"domain": "defineDetection",
|
|
10
|
+
"priority": "must",
|
|
11
|
+
"version": "0.1.0",
|
|
12
|
+
"status": "draft",
|
|
13
|
+
"shapeClassification": {
|
|
14
|
+
"shapes": ["persistence"],
|
|
15
|
+
"reason": "keyword-scan",
|
|
16
|
+
"classifiedAt": "2026-09-24T14:30:00Z",
|
|
17
|
+
"signals": [
|
|
18
|
+
{ "source": "description", "shape": "persistence", "match": "record" }
|
|
19
|
+
]
|
|
20
|
+
},
|
|
21
|
+
"rationale": "Baz ruled on 2026-09-22 (proposal section 2.4, section 6, section 9 decision 4) that Readiness is one object rendered by two consumers (the CLI and the viewer tab) so the two cannot disagree. The Product Map precedent (PR #238) established the shape: one pure compute, one JSON envelope, two renderers. computeReadiness is the object; rcf define readiness is the CLI twin the viewer tab (REQ-180, slice 5) will render unchanged. Slice 3 (rcf define freeze) reads freezeable and the per-stage state and refuses on any failing stage; slice 4's bundle --next reads the same object; slice 6's guidance points at the CLI as the one 'am I ready to build' surface. Fixing the slice-1 P3 in the same slice as the reader that consumes it keeps the ledger docHash contract single-sourced before it stabilises across the fleet.",
|
|
22
|
+
"tags": [
|
|
23
|
+
"capability:define-detection"
|
|
24
|
+
]
|
|
25
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"createdAt": "2026-09-24T12:00:00Z",
|
|
3
|
+
"updatedAt": "2026-09-24T12:00:00Z",
|
|
4
|
+
"tacId": "TAC-4120-define-delta-and-freeze",
|
|
5
|
+
"prdId": "PRD-001",
|
|
6
|
+
"tadId": "TAD-001",
|
|
7
|
+
"version": "0.1.0",
|
|
8
|
+
"status": "draft",
|
|
9
|
+
"name": "define delta compute and freeze record",
|
|
10
|
+
"purpose": "The detection-model primitives (hashDocument, computeTreeHash, computeDelta) live in a new pure module src/query/delta.js, exported from src/query/index.js alongside computeTrace, computeImpact and computeCoverage. The freeze record I/O sits in a new module src/define/freeze-record.js with a small local schema (until schemas 0.7 promotes it to manifest.freeze per ADR-4121). Both modules are pure per call: no filesystem I/O beyond the freeze reader / writer, no state, no time. Canonical JSON is defined on the parsed body, not the raw bytes: keys sorted recursively, no whitespace, JSON.stringify escaping. A whitespace-only reformat of a document produces the same hash; two objects that parse to the same value produce the same hash. Delta granularity is the standalone document: every id in tree.byId (PRD, TAD, BS, REQ, US, TAC, ADR, FBS, TS, CN, EVAL) contributes one docHash; inline AC / TC ride inside the parent's hash; the criterion-level diff is git's job (proposal section 2.2). Ledger docHashes are added under a ledger:<name> id per sidecar the caller passes in.",
|
|
11
|
+
"responsibilities": [
|
|
12
|
+
"src/query/delta.js: canonicaliseJson, hashDocument, computeTreeHash and computeDelta pure functions; JSDoc on computeDelta names the exact return shape AC-17201-1 pins.",
|
|
13
|
+
"src/query/index.js: re-export canonicaliseJson, hashDocument, computeTreeHash and computeDelta so every consumer imports through one seam.",
|
|
14
|
+
"src/define/freeze-record.js: FREEZE_RECORD_REL_PATH (rcf/define/freeze.json), FreezeRecordError, validateFreezeRecord, loadFreezeRecord (returns null on ENOENT, throws FreezeRecordError on parse or schema failure), saveFreezeRecord (validates then writes pretty JSON with trailing newline; creates rcf/define/ on demand).",
|
|
15
|
+
"Every hash is a 'sha256:<64-hex>' string; the record's docHashes values and treeHash are validated against that shape and rejected with a named field otherwise.",
|
|
16
|
+
"Extension fields (counts, litmus, versions, note, override, gates) survive a save / load round trip; the writer refuses to persist an invalid record so a bad in-memory value never lands on disk."
|
|
17
|
+
],
|
|
18
|
+
"internalStructure": "canonicaliseJson recurses over parsed values: object keys sorted lexicographically, arrays kept in source order, JSON.stringify handles string / number / boolean escaping (non-finite numbers coerce to 'null' as JSON does), undefined is omitted from objects and arrays (matches JSON.stringify semantics). computeTreeHash normalises the input (Map or plain object) into sorted (id, docHash) pairs, canonically encodes the pair array, and hashes the resulting string; the tree hash is thereby order-independent by construction. computeDelta walks tree.byId once, hashes each doc, adds one ledger:<name> entry per non-nullish ledger the caller passes, then either returns the whole-tree 'added' shape (freeze absent) or classifies every id against freeze.docHashes; briefSince walks the brief ledger's statements[] and reports ids above freeze.briefStatements.",
|
|
19
|
+
"interfaces": [],
|
|
20
|
+
"notes": "Slice-2 hook: the readiness module will call computeDelta once per render, pass the result through computeImpact per changed id, and hand the union of changed + added + fan-out to every gate check. Slice 3 (the freeze verb) is the only caller of saveFreezeRecord in the shipped path; this slice ships the writer so the verb can be built without a second refactor."
|
|
21
|
+
}
|