@kungfu-tech/buildchain 3.0.9-alpha.9 → 4.0.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (262) hide show
  1. package/AGENTS.md +39 -0
  2. package/README.md +17 -13
  3. package/actions/promote-buildchain-ref/README.md +0 -10
  4. package/actions/release-tail/README.md +6 -10
  5. package/architecture/internal-capabilities.json +502 -0
  6. package/architecture/maintainability-baseline.json +59 -0
  7. package/architecture/maintainability-policy.json +1384 -0
  8. package/architecture/release-tail-contract-inventory.json +587 -0
  9. package/architecture/v3-core-mechanism-inventory.json +1043 -0
  10. package/architecture/v3-core-mechanism-inventory.md +67 -0
  11. package/architecture/v4-adopter-delivery-parity.json +47 -0
  12. package/architecture/v4-architecture-constitution.md +210 -0
  13. package/architecture/v4-bootstrap-authority.json +56 -0
  14. package/architecture/v4-canonical-contract-fixtures.json +105 -0
  15. package/architecture/v4-capability-state-machine-manifest.json +480 -0
  16. package/architecture/v4-capability-state-machine-manifest.schema.json +202 -0
  17. package/architecture/v4-delivery-warrant-shadow-bootstrap-plan.json +830 -0
  18. package/architecture/v4-delivery-warrant-shadow-bootstrap-plan.md +223 -0
  19. package/architecture/v4-delivery-warrant-shadow-bootstrap-plan.schema.json +318 -0
  20. package/architecture/v4-delivery-warrant-shadow-fixtures.json +227 -0
  21. package/architecture/v4-delivery-warrant-shadow-fixtures.schema.json +67 -0
  22. package/architecture/v4-exception-ledger.json +5 -0
  23. package/architecture/v4-exception-ledger.schema.json +56 -0
  24. package/architecture/v4-partial-mutation-recovery-qualification.json +65 -0
  25. package/architecture/v4-platform-stage-checkpoints.json +97 -0
  26. package/architecture/v4-provider-operation-journal-contract.json +113 -0
  27. package/architecture/v4-release-activation-shadow-domain.json +61 -0
  28. package/architecture/v4-release-train-parity.json +68 -0
  29. package/architecture/v4-rust-libnode-bridge-evaluation.json +107 -0
  30. package/architecture/v4-rust-libnode-bridge-spike.md +85 -0
  31. package/architecture/v4-stable-publication-fence.json +66 -0
  32. package/architecture/v4-stage-capsule-contract.json +90 -0
  33. package/architecture/v4-stage-capsule-qualification.json +99 -0
  34. package/architecture/v4-stage-capsule-resume-planner.json +52 -0
  35. package/architecture/v4-stage-capsule-store-contract.json +72 -0
  36. package/bin/buildchain.mjs +15 -10
  37. package/contracts/auditable-demo-scenario-v1.schema.json +1 -1
  38. package/contracts/buildchain-v2-residuals-v1.json +2 -2
  39. package/contracts/fixtures/v4-delivery-warrant-trace-v1/golden.json +158 -0
  40. package/contracts/fixtures/v4-delivery-warrant-trace-v1/property.json +380 -0
  41. package/contracts/fixtures/v4-delivery-warrant-trace-v1/replay.json +163 -0
  42. package/contracts/fixtures/v4-partial-mutation-recovery-v1/shared.json +155 -0
  43. package/contracts/fixtures/v4-provider-operation-journal-v1/shared.json +457 -0
  44. package/contracts/fixtures/v4-provider-readback-idempotency-v1/shared.json +682 -0
  45. package/contracts/fixtures/v4-release-activation-shadow-v1/shared.json +53 -0
  46. package/contracts/fixtures/v4-stable-publication-fence-v1/shared.json +56 -0
  47. package/contracts/fixtures/v4-stage-capsule-resume-v1/late-platform-failure.json +176 -0
  48. package/contracts/fixtures/v4-stage-capsule-store-v1/shared.json +132 -0
  49. package/contracts/fixtures/v4-stage-capsule-v1/shared.json +111 -0
  50. package/contracts/v4-canonical-contracts-v1.schema.json +182 -0
  51. package/contracts/v4-delivery-warrant-semantic-diff-report-v1.schema.json +284 -0
  52. package/contracts/v4-delivery-warrant-trace-v1.schema.json +215 -0
  53. package/contracts/v4-host-contract-v1.schema.json +135 -0
  54. package/contracts/v4-partial-mutation-recovery-v1.schema.json +168 -0
  55. package/contracts/v4-provider-operation-journal-v1.schema.json +381 -0
  56. package/contracts/v4-release-activation-shadow-v1.schema.json +186 -0
  57. package/contracts/v4-stable-publication-fence-v1.schema.json +125 -0
  58. package/contracts/v4-stage-capsule-resume-v1.schema.json +225 -0
  59. package/contracts/v4-stage-capsule-store-v1.schema.json +154 -0
  60. package/contracts/v4-stage-capsule-v1.schema.json +178 -0
  61. package/crates/buildchain-v4-bridge/Cargo.lock +213 -0
  62. package/crates/buildchain-v4-bridge/Cargo.toml +12 -0
  63. package/crates/buildchain-v4-bridge/src/main.rs +495 -0
  64. package/dist/site/agent-index.json +0 -4
  65. package/dist/site/artifact-schemas.json +0 -8
  66. package/dist/site/buildchain-contract.json +103 -397
  67. package/dist/site/buildchain-site.json +302 -386
  68. package/dist/site/capability-registry.json +9 -11
  69. package/dist/site/cli-registry.json +8 -53
  70. package/dist/site/controller-registry.json +48 -8
  71. package/dist/site/kfd-claims.json +129 -167
  72. package/dist/site/kfd-upstream-aggregate.json +9 -9
  73. package/dist/site/manual-registry.json +18 -49
  74. package/dist/site/node-api-registry.json +4345 -7345
  75. package/dist/site/page-registry.json +278 -346
  76. package/dist/site/public-surface-audit.json +85 -404
  77. package/dist/site/publication-authority-registry.json +11 -1
  78. package/dist/site/publication-registry.json +4 -4
  79. package/dist/site/release-provenance.json +3 -9
  80. package/dist/site/schemas/kfd-support-projection-v1.schema.json +106 -0
  81. package/dist/site/site-manifest.json +22 -38
  82. package/dist/site/workflow-registry.json +78 -35
  83. package/docs/MAP.md +8 -5
  84. package/docs/auditable-demo.md +2 -2
  85. package/docs/aws-us-elastic-runner-burst-plane.md +7 -59
  86. package/docs/cli-reference.md +15 -213
  87. package/docs/cli.md +14 -14
  88. package/docs/dev-alpha-candidate-patrol.md +3 -11
  89. package/docs/dev-delivery-warrant.md +29 -194
  90. package/docs/engineering-housekeeper.md +12 -4
  91. package/docs/getting-started.md +1 -1
  92. package/docs/install.md +5 -5
  93. package/docs/kfd-support.md +2 -7
  94. package/docs/lifecycle-protocol.md +2 -4
  95. package/docs/node-api-reference.md +414 -554
  96. package/docs/release-flow.md +31 -31
  97. package/docs/release-governance.md +16 -28
  98. package/docs/release-passport.md +2 -15
  99. package/docs/release-tail-contract.md +13 -6
  100. package/docs/release-tail-provider-plane.md +13 -19
  101. package/docs/release-train.md +4 -4
  102. package/docs/reusable-build-surface.md +14 -27
  103. package/docs/site-bundle-contract.md +1 -5
  104. package/docs/stable-candidate-patrol.md +7 -7
  105. package/docs/v4-canonical-contracts.md +92 -0
  106. package/docs/v4-delivery-warrant-read-candidate.md +73 -0
  107. package/docs/v4-delivery-warrant-semantic-diff.md +75 -0
  108. package/docs/v4-production-release.md +63 -0
  109. package/docs/v4-stage-capsule.md +193 -0
  110. package/docs/versioning.md +3 -5
  111. package/package.json +19 -19
  112. package/packages/core/adopter-delivery-gate.js +576 -0
  113. package/packages/core/adopter-delivery-json.js +66 -0
  114. package/packages/core/artifact-signing.js +0 -61
  115. package/packages/core/artifact-verification-envelope.js +5 -5
  116. package/packages/core/build-facts.js +12 -4
  117. package/packages/core/buildchain-agent-manuals.js +0 -2
  118. package/packages/core/buildchain-channel-identity.js +3 -2
  119. package/packages/core/buildchain-config.js +4 -69
  120. package/packages/core/buildchain-contract.js +232 -46
  121. package/packages/core/buildchain-kfd-claims.js +1 -1
  122. package/packages/core/channel-candidate.js +0 -8
  123. package/packages/core/channel-promotion-baseline.js +0 -52
  124. package/packages/core/controller-evidence.js +3 -4
  125. package/packages/core/dev-alpha-candidate-selection.js +2 -10
  126. package/packages/core/dev-delivery-warrant-cancellation.js +0 -1
  127. package/packages/core/dev-delivery-warrant-settlement.js +20 -67
  128. package/packages/core/dev-delivery-warrant.js +50 -138
  129. package/packages/core/diagnostics.js +3 -8
  130. package/packages/core/github-governance-authority.js +3 -1
  131. package/packages/core/kfd-adopter-category-driver.js +167 -0
  132. package/packages/core/kfd-adopter-manifest.js +47 -46
  133. package/packages/core/kfd-gate.js +15 -45
  134. package/packages/core/paper-agent-entry.js +7 -16
  135. package/packages/core/paper-fleet.js +2 -2
  136. package/packages/core/paper-repository.js +2 -3
  137. package/packages/core/paper-scaffold-content.js +2 -23
  138. package/packages/core/paper.js +11 -43
  139. package/packages/core/publication-reproducibility.js +4 -4
  140. package/packages/core/release-line-bootstrap.js +21 -8
  141. package/packages/core/release-passport-contract.js +5 -5
  142. package/packages/core/release-passport.js +20 -131
  143. package/packages/core/self-dogfood-version.js +48 -35
  144. package/packages/core/spawn-command.js +232 -8
  145. package/packages/core/v4-adopter-delivery-parity.js +219 -0
  146. package/packages/core/v4-canonical-contracts.js +284 -0
  147. package/packages/core/v4-delivery-warrant-fixture-runner.js +371 -0
  148. package/packages/core/v4-delivery-warrant-read-candidate.js +279 -0
  149. package/packages/core/v4-delivery-warrant-semantic-diff-gate.js +352 -0
  150. package/packages/core/v4-delivery-warrant-shadow-adapter.js +447 -0
  151. package/packages/core/v4-partial-mutation-recovery-qualification.js +395 -0
  152. package/packages/core/v4-platform-stage-checkpoints.js +471 -0
  153. package/packages/core/v4-provider-operation-journal.js +531 -0
  154. package/packages/core/v4-provider-readback-idempotency.js +394 -0
  155. package/packages/core/v4-release-activation-shadow.js +519 -0
  156. package/packages/core/v4-stable-publication-fence.js +357 -0
  157. package/packages/core/v4-stage-capsule-local-store.js +426 -0
  158. package/packages/core/v4-stage-capsule-qualification-campaign.js +512 -0
  159. package/packages/core/v4-stage-capsule-qualification.js +456 -0
  160. package/packages/core/v4-stage-capsule-resume-planner.js +397 -0
  161. package/packages/core/v4-stage-capsule-store.js +401 -0
  162. package/packages/core/v4-stage-capsule.js +319 -0
  163. package/scripts/assemble-self-publication-admission.mjs +1 -1
  164. package/scripts/audit-publication-control-plane.mjs +5 -5
  165. package/scripts/auditable-demo-bundle-verification.mjs +3 -2
  166. package/scripts/auditable-demo-platform.mjs +2 -2
  167. package/scripts/auditable-demo-renditions.mjs +1 -1
  168. package/scripts/auditable-demo.mjs +2 -2
  169. package/scripts/aws-macos-jit-controller-core.mjs +13 -346
  170. package/scripts/aws-macos-jit-controller-runtime.mjs +2 -210
  171. package/scripts/aws-macos-jit-controller.mjs +37 -275
  172. package/scripts/aws-macos-jit-core.mjs +3 -41
  173. package/scripts/aws-macos-jit.mjs +0 -12
  174. package/scripts/aws-windows-jit-campaign.mjs +2 -2
  175. package/scripts/aws-windows-jit-controller-core.mjs +1 -1
  176. package/scripts/aws-windows-jit-controller.mjs +3 -3
  177. package/scripts/build-contract-core.mjs +3 -8
  178. package/scripts/build-standalone-binary.mjs +3 -14
  179. package/scripts/buildchain-channel-router.mjs +4 -0
  180. package/scripts/buildchain-cli-help.mjs +7 -16
  181. package/scripts/buildchain-contract-lock.mjs +0 -6
  182. package/scripts/check-action-bundles.mjs +3 -4
  183. package/scripts/check-internal-architecture.mjs +7 -6
  184. package/scripts/check-inventory.mjs +30 -25
  185. package/scripts/check-v4-public-dogfood-contract.mjs +270 -0
  186. package/scripts/create-release-bundle.mjs +8 -4
  187. package/scripts/dev-alpha-candidate-patrol.mjs +1 -22
  188. package/scripts/dev-delivery-proof.mjs +2 -64
  189. package/scripts/dev-delivery-warrant.mjs +61 -86
  190. package/scripts/dev-pr-auto-merge.mjs +4 -30
  191. package/scripts/dev-pr-delivery-warrant.mjs +0 -55
  192. package/scripts/dispatch-artifact-signing-authority.mjs +7 -4
  193. package/scripts/generate-buildchain-kfd-witnesses.mjs +94 -88
  194. package/scripts/generate-channel-build-workflow.mjs +54 -24
  195. package/scripts/generate-channel-promotion-workflow.mjs +15 -6
  196. package/scripts/generate-site-bundle.mjs +8 -27
  197. package/scripts/git-fetch-process-tree.mjs +34 -1
  198. package/scripts/init-repo.mjs +64 -159
  199. package/scripts/inspect-artifact-signing-requests.mjs +0 -6
  200. package/scripts/locked-source-checkout.mjs +3 -4
  201. package/scripts/maintainability-metrics.mjs +8 -2
  202. package/scripts/npm-publish-dry-run.mjs +2 -2
  203. package/scripts/npm-publish-transaction.mjs +2 -2
  204. package/scripts/publication-commit-evidence.mjs +23 -69
  205. package/scripts/release-candidate-resolver.mjs +11 -17
  206. package/scripts/release-tail.mjs +3 -49
  207. package/scripts/resume-from-candidate-run.mjs +9 -123
  208. package/scripts/run-lifecycle-core.mjs +12 -13
  209. package/scripts/seal-artifact-signing-requests.mjs +17 -21
  210. package/scripts/site-capability-metadata.mjs +3 -20
  211. package/scripts/stable-candidate-qualification.mjs +10 -10
  212. package/scripts/v4-architecture.mjs +12 -2
  213. package/scripts/v4-bridge-bootstrap.mjs +141 -0
  214. package/scripts/v4-bridge-evidence.mjs +141 -0
  215. package/scripts/v4-host-adapter.mjs +182 -0
  216. package/scripts/v4-platform-stage-checkpoint-rehearsal.mjs +207 -0
  217. package/scripts/v4-stage-capsule-qualification.mjs +528 -0
  218. package/scripts/v4-stage-capsule-resume-rehearsal.mjs +57 -0
  219. package/scripts/v4-warrant-shadow-plan.mjs +601 -0
  220. package/scripts/verify-golden-path.mjs +5 -5
  221. package/scripts/web-surface-cloudfront-rewrite.mjs +15 -15
  222. package/scripts/web-surface-core.mjs +2 -8
  223. package/scripts/workflow-call-contract.mjs +5 -184
  224. package/contracts/dev-delivery-authority-v2.schema.json +0 -253
  225. package/contracts/fixtures/kfd-adopter-release-v1/kfd-4-perspective.json +0 -16
  226. package/contracts/fixtures/kfd-adopter-release-v1/kfd-4-replay.json +0 -57
  227. package/contracts/fixtures/next-development-transition-v1/anchored-manual-waiting.json +0 -47
  228. package/contracts/fixtures/next-development-transition-v1/semver-auto-planned.json +0 -47
  229. package/contracts/fixtures/next-development-transition-v1/version-model-cases.json +0 -40
  230. package/contracts/next-development-request-v1.schema.json +0 -66
  231. package/contracts/next-development-transition-v1.schema.json +0 -292
  232. package/contracts/publication-rehearsal-capsule-v1.schema.json +0 -173
  233. package/dist/site/schemas/dev-delivery-authority-v2.schema.json +0 -442
  234. package/dist/site/schemas/publication-rehearsal-capsule-v1.schema.json +0 -269
  235. package/dist/site/schemas/release-tail-capabilities-v1.schema.json +0 -353
  236. package/dist/site/schemas/release-tail-provider-bindings-v1.schema.json +0 -94
  237. package/docs/dev-delivery-qualification-landing-adr.md +0 -137
  238. package/docs/next-development-transition.md +0 -119
  239. package/docs/publication-rehearsal.md +0 -94
  240. package/packages/core/buildchain-compatibility-proof.js +0 -631
  241. package/packages/core/dev-delivery-authority.js +0 -996
  242. package/packages/core/dev-delivery-native-proof.js +0 -418
  243. package/packages/core/dev-delivery-warrant-shadow.js +0 -502
  244. package/packages/core/next-development-candidate-reservation.js +0 -186
  245. package/packages/core/next-development-controller.js +0 -726
  246. package/packages/core/next-development-projection.js +0 -288
  247. package/packages/core/next-development-transition.js +0 -738
  248. package/packages/core/publication-rehearsal-projection.js +0 -173
  249. package/packages/core/publication-rehearsal-runtime.js +0 -921
  250. package/scripts/aws-macos-jit-instance-rehydrate.mjs +0 -260
  251. package/scripts/aws-macos-jit-source-rebind.mjs +0 -724
  252. package/scripts/dev-delivery-authority.mjs +0 -368
  253. package/scripts/dev-delivery-native-run.mjs +0 -235
  254. package/scripts/dev-delivery-two-phase-resume.mjs +0 -90
  255. package/scripts/dev-delivery-two-phase.mjs +0 -577
  256. package/scripts/generate-next-development-guidance.mjs +0 -49
  257. package/scripts/materialize-self-release-candidate-version.mjs +0 -137
  258. package/scripts/next-development-self-dogfood-harness.mjs +0 -409
  259. package/scripts/next-development-self-dogfood.mjs +0 -532
  260. package/scripts/next-development-transition.mjs +0 -47
  261. package/scripts/release-candidate-tail-reseal.mjs +0 -426
  262. package/templates/native-dev-delivery.yml +0 -86
@@ -0,0 +1,279 @@
1
+ import crypto from "node:crypto";
2
+
3
+ import {
4
+ normalizeDevDeliveryQueue,
5
+ observeDevDeliveryQueue,
6
+ } from "./dev-delivery-warrant.js";
7
+ import {
8
+ v4CanonicalBytes,
9
+ v4ContentRoot,
10
+ validateV4Clock,
11
+ validateV4Root,
12
+ } from "./v4-canonical-contracts.js";
13
+ import { invokeV4RustShadowHost } from "./v4-delivery-warrant-shadow-adapter.js";
14
+ import { V4_DELIVERY_WARRANT_SEMANTIC_DIFF_REPORT_CONTRACT } from "./v4-delivery-warrant-semantic-diff-gate.js";
15
+
16
+ export const V4_DELIVERY_WARRANT_READ_PROJECTION_CONTRACT =
17
+ "buildchain-v4-delivery-warrant-read-projection/v1";
18
+ export const V4_DELIVERY_WARRANT_READ_RESULT_CONTRACT =
19
+ "buildchain-v4-delivery-warrant-read-result/v1";
20
+ export const V4_DELIVERY_WARRANT_READ_EVIDENCE_CONTRACT =
21
+ "buildchain-v4-delivery-warrant-read-evidence/v1";
22
+
23
+ const HOST_REQUEST_CONTRACT = "kungfu-buildchain-v4-host-request";
24
+ const HOST_RESPONSE_CONTRACT = "kungfu-buildchain-v4-host-response";
25
+ const STATE_CONTRACT = "buildchain-v4-delivery-warrant-state/v1";
26
+ const REQUIRED_CAPABILITIES = Object.freeze([
27
+ "canonical-input-v1",
28
+ "delivery-warrant-state-projection-v1",
29
+ "diagnostics-v1",
30
+ "effects-disabled-v1",
31
+ "structured-result-v1",
32
+ ]);
33
+ const REVISION = /^[0-9a-f]{40,64}$/u;
34
+ const MAX_TIMEOUT_MS = 30_000;
35
+
36
+ export class V4DeliveryWarrantReadFault extends Error {
37
+ constructor(code, message) {
38
+ super(message);
39
+ this.name = "V4DeliveryWarrantReadFault";
40
+ this.code = code;
41
+ }
42
+ }
43
+
44
+ function fail(code, message) {
45
+ throw new V4DeliveryWarrantReadFault(code, message);
46
+ }
47
+
48
+ function validateSources(actual, expected) {
49
+ for (const key of [
50
+ "typescriptRevision",
51
+ "rustRevision",
52
+ "validatorVersion",
53
+ ]) {
54
+ if (typeof expected?.[key] !== "string" || actual?.[key] !== expected[key])
55
+ fail("qualification-source-drift", `qualification ${key} drifted`);
56
+ }
57
+ if (
58
+ !REVISION.test(expected.typescriptRevision) ||
59
+ !REVISION.test(expected.rustRevision)
60
+ )
61
+ fail("qualification-source-drift", "qualification revisions are invalid");
62
+ }
63
+
64
+ export function validateV4DeliveryWarrantReadQualification(
65
+ report,
66
+ { expectedRoot, expectedSources, observedAt },
67
+ ) {
68
+ validateV4Root(expectedRoot, "$/expectedQualificationRoot");
69
+ validateV4Clock(observedAt, "$/observedAt");
70
+ const body = structuredClone(report || {});
71
+ const reportedRoot = body.reportRoot;
72
+ delete body.reportRoot;
73
+ if (
74
+ reportedRoot !== expectedRoot ||
75
+ v4ContentRoot("semantic-diff", body) !== expectedRoot
76
+ )
77
+ fail("qualification-root-drift", "semantic-diff report root drifted");
78
+ if (
79
+ report.schema !== V4_DELIVERY_WARRANT_SEMANTIC_DIFF_REPORT_CONTRACT ||
80
+ report.authority !== "typescript-v3" ||
81
+ report.rustAuthority !== "none" ||
82
+ report.rustEffects !== "disabled" ||
83
+ report.verdict?.status !== "qualified" ||
84
+ report.verdict?.zeroUnexplainedDifferences !== true ||
85
+ report.verdict?.nextEligibleStage !== "legacy-authoritative-v4-read" ||
86
+ report.verdict?.v4WriteAuthorized !== false ||
87
+ report.retention?.status !== "retained" ||
88
+ report.blockers?.length !== 0 ||
89
+ report.coverage?.missing?.length !== 0
90
+ )
91
+ fail(
92
+ "qualification-not-eligible",
93
+ "semantic-diff report does not authorize a read-only candidate",
94
+ );
95
+ validateV4Clock(report.retainUntil, "$/qualification/retainUntil");
96
+ if (Date.parse(report.retainUntil) <= Date.parse(observedAt))
97
+ fail("qualification-expired", "semantic-diff retention window expired");
98
+ validateSources(report.sources, expectedSources);
99
+ return report;
100
+ }
101
+
102
+ export function projectV3QueueToV4ReadState(queueInput) {
103
+ const queue = normalizeDevDeliveryQueue(queueInput);
104
+ return {
105
+ schema: STATE_CONTRACT,
106
+ generation: queue.generation,
107
+ fencingCounter: queue.fencingCounter,
108
+ activeWarrant: queue.activeWarrant
109
+ ? {
110
+ candidateId: queue.activeWarrant.candidateId,
111
+ fencingToken: queue.activeWarrant.fencingToken,
112
+ generation: queue.activeWarrant.generation,
113
+ issuedAt: queue.activeWarrant.issuedAt,
114
+ expiresAt: queue.activeWarrant.expiresAt,
115
+ }
116
+ : null,
117
+ candidates: queue.candidates.map((candidate) => ({
118
+ candidateId: candidate.candidateId,
119
+ pullRequestNumber: candidate.pullRequestNumber,
120
+ status: candidate.status,
121
+ enqueuedAt: candidate.enqueuedAt,
122
+ updatedAt: candidate.updatedAt,
123
+ attempts: candidate.attempts,
124
+ recoveries: candidate.recoveries,
125
+ ...(candidate.terminal
126
+ ? {
127
+ terminal: {
128
+ outcome: candidate.terminal.outcome,
129
+ evidenceRoot: candidate.terminal.evidenceRoot,
130
+ closedAt: candidate.terminal.closedAt,
131
+ },
132
+ }
133
+ : {}),
134
+ })),
135
+ };
136
+ }
137
+
138
+ export function createV4DeliveryWarrantReadRequest(
139
+ state,
140
+ { requestId = crypto.randomUUID(), timeoutMs = 5_000 } = {},
141
+ ) {
142
+ if (
143
+ !Number.isInteger(timeoutMs) ||
144
+ timeoutMs < 1 ||
145
+ timeoutMs > MAX_TIMEOUT_MS
146
+ )
147
+ throw new RangeError(`timeoutMs must be between 1 and ${MAX_TIMEOUT_MS}`);
148
+ return {
149
+ schemaVersion: 1,
150
+ contract: HOST_REQUEST_CONTRACT,
151
+ protocolVersion: "1.0",
152
+ requestId,
153
+ command: { id: "delivery-warrant.state-project", arguments: [] },
154
+ input: {
155
+ encoding: "base64",
156
+ bytes: v4CanonicalBytes(state).toString("base64"),
157
+ },
158
+ requiredCapabilities: [...REQUIRED_CAPABILITIES],
159
+ timeoutMs,
160
+ };
161
+ }
162
+
163
+ function validateProjection(response, request, expectedState) {
164
+ if (
165
+ response?.schemaVersion !== 1 ||
166
+ response?.contract !== HOST_RESPONSE_CONTRACT ||
167
+ response?.protocolVersion !== "1.0" ||
168
+ response?.requestId !== request.requestId ||
169
+ response?.command?.id !== request.command.id
170
+ )
171
+ fail("host-response-invalid", "Rust read projection response is invalid");
172
+ const capabilities = response.host?.capabilities || [];
173
+ if (
174
+ response.status === "unsupported" ||
175
+ REQUIRED_CAPABILITIES.some((entry) => !capabilities.includes(entry))
176
+ )
177
+ fail(
178
+ "unsupported-capability",
179
+ "Rust host lacks the read-only projection capability",
180
+ );
181
+ if (response.status !== "ok")
182
+ fail("rust-projection-failed", "Rust read projection failed closed");
183
+ const projection = response.structuredResult;
184
+ if (
185
+ projection?.schema !== V4_DELIVERY_WARRANT_READ_PROJECTION_CONTRACT ||
186
+ !projection.stateRoot
187
+ )
188
+ fail("host-response-invalid", "Rust read projection shape is invalid");
189
+ validateV4Root(projection.stateRoot, "$/projection/stateRoot");
190
+ if (
191
+ !v4CanonicalBytes(projection.state).equals(
192
+ v4CanonicalBytes(expectedState),
193
+ ) ||
194
+ projection.stateRoot !== v4ContentRoot("queue-state", expectedState)
195
+ )
196
+ fail("projection-drift", "Rust read projection disagrees with v3 state");
197
+ return projection;
198
+ }
199
+
200
+ export async function runV4DeliveryWarrantReadCandidate(
201
+ queueInput,
202
+ {
203
+ qualification,
204
+ expectedQualificationRoot,
205
+ expectedSources,
206
+ observedAt = new Date().toISOString(),
207
+ requestId,
208
+ timeoutMs = 5_000,
209
+ signal,
210
+ invokeRust = invokeV4RustShadowHost,
211
+ host = {},
212
+ retain,
213
+ } = {},
214
+ ) {
215
+ validateV4DeliveryWarrantReadQualification(qualification, {
216
+ expectedRoot: expectedQualificationRoot,
217
+ expectedSources,
218
+ observedAt,
219
+ });
220
+ if (typeof retain !== "function")
221
+ fail("retention-required", "v4 read evidence retention is required");
222
+ const queue = normalizeDevDeliveryQueue(queueInput);
223
+ const state = projectV3QueueToV4ReadState(queue);
224
+ const request = createV4DeliveryWarrantReadRequest(state, {
225
+ requestId,
226
+ timeoutMs,
227
+ });
228
+ let response;
229
+ try {
230
+ response = await invokeRust(request, { ...host, signal });
231
+ } catch (error) {
232
+ fail(
233
+ error?.code || "rust-projection-failed",
234
+ error?.message || "Rust read projection failed",
235
+ );
236
+ }
237
+ const projection = validateProjection(response, request, state);
238
+ const observation = observeDevDeliveryQueue(queue, { now: observedAt });
239
+ const evidence = {
240
+ schema: V4_DELIVERY_WARRANT_READ_EVIDENCE_CONTRACT,
241
+ authority: "typescript-v3",
242
+ writerAuthority: "typescript-v3",
243
+ rustAuthority: "read-only",
244
+ rustEffects: "disabled",
245
+ rollbackMode: "v3",
246
+ observedAt,
247
+ qualificationRoot: expectedQualificationRoot,
248
+ legacyStateRoot: queue.stateRoot,
249
+ v4StateRoot: projection.stateRoot,
250
+ observationRoot: v4ContentRoot("observation", observation),
251
+ parity: "matched",
252
+ };
253
+ const evidenceRoot = v4ContentRoot("observation", evidence);
254
+ let retentionReceipt;
255
+ try {
256
+ retentionReceipt = await retain(
257
+ structuredClone({ ...evidence, evidenceRoot }),
258
+ );
259
+ validateV4Root(retentionReceipt?.receiptRoot, "$/retention/receiptRoot");
260
+ } catch {
261
+ fail("retention-failed", "v4 read evidence retention failed");
262
+ }
263
+ return {
264
+ schema: V4_DELIVERY_WARRANT_READ_RESULT_CONTRACT,
265
+ mode: "v4-read",
266
+ authority: "typescript-v3",
267
+ writerAuthority: "typescript-v3",
268
+ rustAuthority: "read-only",
269
+ rustEffects: "disabled",
270
+ rollbackMode: "v3",
271
+ observation,
272
+ projection,
273
+ evidence: {
274
+ ...evidence,
275
+ evidenceRoot,
276
+ retentionReceiptRoot: retentionReceipt.receiptRoot,
277
+ },
278
+ };
279
+ }
@@ -0,0 +1,352 @@
1
+ import crypto from "node:crypto";
2
+
3
+ import {
4
+ v4ContentRoot,
5
+ validateV4Clock,
6
+ validateV4Root,
7
+ } from "./v4-canonical-contracts.js";
8
+ import {
9
+ V4_DELIVERY_WARRANT_PROJECTION_CONTRACT,
10
+ V4_DELIVERY_WARRANT_RUNNER_CONTRACT,
11
+ V4_DELIVERY_WARRANT_TRACE_CONTRACT,
12
+ } from "./v4-delivery-warrant-fixture-runner.js";
13
+ import {
14
+ V4_DELIVERY_WARRANT_SHADOW_OBSERVATION_CONTRACT,
15
+ runV4DeliveryWarrantShadow,
16
+ } from "./v4-delivery-warrant-shadow-adapter.js";
17
+
18
+ export const V4_DELIVERY_WARRANT_SEMANTIC_DIFF_REPORT_CONTRACT =
19
+ "buildchain-v4-delivery-warrant-semantic-diff-report/v1";
20
+ export const V4_DELIVERY_WARRANT_SEMANTIC_DIFF_VALIDATOR_VERSION =
21
+ "semantic-diff-gate-v1";
22
+ export const V4_DELIVERY_WARRANT_SEMANTIC_DIFF_REQUIRED_COVERAGE =
23
+ Object.freeze([
24
+ "cancellation",
25
+ "cas",
26
+ "conflict",
27
+ "duplicate",
28
+ "golden",
29
+ "lease-fence",
30
+ "property",
31
+ "replay",
32
+ "response-loss",
33
+ ]);
34
+
35
+ const REVISION = /^[0-9a-f]{40,64}$/u;
36
+ const TOKEN = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/u;
37
+ const stop = (code) => ({ code, retry: "stop" });
38
+ const valueRoot = (value) =>
39
+ value === undefined ? null : v4ContentRoot("semantic-diff", { value });
40
+
41
+ function difference(path, kind, legacy, rust) {
42
+ const summary = {
43
+ path,
44
+ kind,
45
+ legacyRoot: valueRoot(legacy),
46
+ rustRoot: valueRoot(rust),
47
+ };
48
+ return {
49
+ ...summary,
50
+ differenceRoot: v4ContentRoot("semantic-diff", summary),
51
+ };
52
+ }
53
+
54
+ export function compareV4DeliveryWarrantSemantics(legacy, rust, path = "$") {
55
+ if (Object.is(legacy, rust)) return [];
56
+ if (legacy === undefined)
57
+ return [difference(path, "missing-legacy", legacy, rust)];
58
+ if (rust === undefined)
59
+ return [difference(path, "missing-rust", legacy, rust)];
60
+ if (
61
+ legacy === null ||
62
+ rust === null ||
63
+ typeof legacy !== "object" ||
64
+ typeof rust !== "object" ||
65
+ Array.isArray(legacy) !== Array.isArray(rust)
66
+ )
67
+ return [difference(path, "value-mismatch", legacy, rust)];
68
+ const keys = Array.isArray(legacy)
69
+ ? Array.from({ length: Math.max(legacy.length, rust.length) }, (_, i) => i)
70
+ : [...new Set([...Object.keys(legacy), ...Object.keys(rust)])].sort();
71
+ return keys.flatMap((key) =>
72
+ compareV4DeliveryWarrantSemantics(legacy[key], rust[key], `${path}/${key}`),
73
+ );
74
+ }
75
+
76
+ export function v4DeliveryWarrantDispositionRoot(value) {
77
+ return v4ContentRoot("semantic-diff", {
78
+ differenceRoot: value.differenceRoot,
79
+ disposition: value.disposition,
80
+ reasonCode: value.reasonCode,
81
+ reviewRoot: value.reviewRoot,
82
+ });
83
+ }
84
+
85
+ function dispositions(values = []) {
86
+ return new Map(
87
+ values.map((value) => {
88
+ validateV4Root(value.differenceRoot);
89
+ validateV4Root(value.reviewRoot);
90
+ validateV4Root(value.dispositionRoot);
91
+ if (
92
+ value.disposition !== "reviewed-exclusion" ||
93
+ !TOKEN.test(value.reasonCode) ||
94
+ value.dispositionRoot !== v4DeliveryWarrantDispositionRoot(value)
95
+ )
96
+ throw new TypeError(
97
+ "semantic difference disposition is not review-rooted",
98
+ );
99
+ return [value.differenceRoot, value];
100
+ }),
101
+ );
102
+ }
103
+
104
+ function bytes(value) {
105
+ if (typeof value === "string") return Buffer.from(value);
106
+ if (Buffer.isBuffer(value) || value instanceof Uint8Array)
107
+ return Buffer.from(value);
108
+ throw new TypeError("semantic diff input must be retained bytes");
109
+ }
110
+
111
+ function classify(entries, index) {
112
+ return entries.map((entry) => {
113
+ const reviewed = index.get(entry.differenceRoot);
114
+ return reviewed
115
+ ? {
116
+ ...entry,
117
+ classification: "reviewed-exclusion",
118
+ dispositionRoot: reviewed.dispositionRoot,
119
+ reasonCode: reviewed.reasonCode,
120
+ reviewRoot: reviewed.reviewRoot,
121
+ }
122
+ : { ...entry, classification: "unexplained" };
123
+ });
124
+ }
125
+
126
+ async function projectCase(definition, options, dispositionIndex) {
127
+ if (!TOKEN.test(definition.id) || !Array.isArray(definition.coverage))
128
+ throw new TypeError(
129
+ "semantic diff case identity and coverage are required",
130
+ );
131
+ const input = bytes(definition.bytes);
132
+ const inputRoot = `sha256:${crypto.createHash("sha256").update(input).digest("hex")}`;
133
+ const result = await options.runShadow(input, {
134
+ enabled: true,
135
+ requestId: `semantic-diff-${definition.id}`,
136
+ recordedAt: options.recordedAt,
137
+ timeoutMs: 30_000,
138
+ retention: definition.retention || { kind: "fixture" },
139
+ retain: options.retainObservation,
140
+ sources: options.sources,
141
+ });
142
+ const observation = result.shadow?.observation;
143
+ const blockers = [];
144
+ if (result.shadow?.status !== "observed" || !observation)
145
+ blockers.push(stop("missing-observation"));
146
+ if (
147
+ observation &&
148
+ (observation.schema !== V4_DELIVERY_WARRANT_SHADOW_OBSERVATION_CONTRACT ||
149
+ observation.authority !== "typescript-v3" ||
150
+ observation.rustAuthority !== "none" ||
151
+ observation.rustEffects !== "disabled")
152
+ )
153
+ blockers.push(stop("authority-mismatch"));
154
+ if (
155
+ observation &&
156
+ (observation.input?.root !== inputRoot ||
157
+ result.shadow?.inputRoot !== inputRoot)
158
+ )
159
+ blockers.push(stop("input-binding-mismatch"));
160
+ if (observation && observation.retention?.publicSafe !== true)
161
+ blockers.push(stop("input-not-public-safe"));
162
+ if (result.shadow?.retention?.status !== "retained")
163
+ blockers.push(stop("retention-failed"));
164
+ if (
165
+ observation &&
166
+ Object.keys(options.sources).some(
167
+ (key) => observation.sources?.[key] !== options.sources[key],
168
+ )
169
+ )
170
+ blockers.push(stop("source-binding-mismatch"));
171
+ const rust = observation?.rust?.projection;
172
+ const differences = classify(
173
+ rust
174
+ ? compareV4DeliveryWarrantSemantics(result.authoritativeResult, rust)
175
+ : [],
176
+ dispositionIndex,
177
+ );
178
+ if (differences.some((entry) => entry.classification === "unexplained"))
179
+ blockers.push(stop("unexplained-difference"));
180
+ const evidence = {
181
+ id: definition.id,
182
+ coverage: [...new Set(definition.coverage)].sort(),
183
+ inputRoot,
184
+ observationRoot: observation
185
+ ? v4ContentRoot("semantic-diff", observation)
186
+ : null,
187
+ legacyProjectionRoot: result.authoritativeResult?.projectionRoot || null,
188
+ rustProjectionRoot: rust?.projectionRoot || null,
189
+ differences,
190
+ differenceRoot: v4ContentRoot("semantic-diff", differences),
191
+ blockers,
192
+ };
193
+ return {
194
+ report: {
195
+ ...evidence,
196
+ evidenceRoot: v4ContentRoot("semantic-diff", evidence),
197
+ status: blockers.length ? "blocked" : "zero-unexplained-diff",
198
+ },
199
+ legacy: result.authoritativeResult,
200
+ rust,
201
+ };
202
+ }
203
+
204
+ function inject(value, probe) {
205
+ const clone = structuredClone(value);
206
+ const parts = probe.path.slice(2).split("/");
207
+ const leaf = parts.pop();
208
+ const parent = parts.reduce((node, part) => node?.[part], clone);
209
+ if (!parent || !(leaf in parent))
210
+ throw new TypeError("fault probe path is absent");
211
+ if (probe.operation === "remove") delete parent[leaf];
212
+ else if (probe.operation === "replace") parent[leaf] = probe.value;
213
+ else throw new TypeError("fault probe operation is invalid");
214
+ return clone;
215
+ }
216
+
217
+ function probeReceipts(probes, runtime) {
218
+ if (!Array.isArray(probes) || probes.length < 1 || probes.length > 32)
219
+ throw new RangeError("fault probes must contain 1-32 entries");
220
+ return probes.map((probe) => {
221
+ const target = runtime.get(probe.caseId);
222
+ const differences = target?.rust
223
+ ? compareV4DeliveryWarrantSemantics(
224
+ target.legacy,
225
+ inject(target.rust, probe),
226
+ )
227
+ : [];
228
+ const receipt = {
229
+ id: probe.id,
230
+ caseId: probe.caseId,
231
+ operation: probe.operation,
232
+ path: probe.path,
233
+ detected: differences.length > 0,
234
+ differenceRoots: differences.map((entry) => entry.differenceRoot).sort(),
235
+ };
236
+ return { ...receipt, receiptRoot: v4ContentRoot("semantic-diff", receipt) };
237
+ });
238
+ }
239
+
240
+ export async function runV4DeliveryWarrantSemanticDiffGate(
241
+ cases,
242
+ options = {},
243
+ ) {
244
+ validateV4Clock(options.recordedAt);
245
+ if (!Array.isArray(cases) || cases.length < 1 || cases.length > 64)
246
+ throw new RangeError("semantic diff cases must contain 1-64 entries");
247
+ if (
248
+ !REVISION.test(options.sources?.typescriptRevision) ||
249
+ !REVISION.test(options.sources?.rustRevision) ||
250
+ !TOKEN.test(options.sources?.validatorVersion)
251
+ )
252
+ throw new TypeError("semantic diff source binding is invalid");
253
+ for (const key of ["traceSchemaRoot", "reportSchemaRoot", "runnerRoot"])
254
+ validateV4Root(options.contracts?.[key]);
255
+ const index = dispositions(options.dispositions);
256
+ const projected = [];
257
+ for (const entry of cases)
258
+ projected.push(
259
+ await projectCase(
260
+ entry,
261
+ {
262
+ ...options,
263
+ runShadow: options.runShadow || runV4DeliveryWarrantShadow,
264
+ },
265
+ index,
266
+ ),
267
+ );
268
+ const runtime = new Map(projected.map((entry, i) => [cases[i].id, entry]));
269
+ const receipts = probeReceipts(options.faultProbes, runtime);
270
+ const coverage = new Set(cases.flatMap((entry) => entry.coverage));
271
+ const missing = V4_DELIVERY_WARRANT_SEMANTIC_DIFF_REQUIRED_COVERAGE.filter(
272
+ (entry) => !coverage.has(entry),
273
+ );
274
+ const blockers = projected.flatMap((entry) => entry.report.blockers);
275
+ if (missing.length) blockers.push(stop("coverage-incomplete"));
276
+ if (receipts.some((entry) => !entry.detected))
277
+ blockers.push(stop("fault-injection-undetected"));
278
+ const body = {
279
+ schema: V4_DELIVERY_WARRANT_SEMANTIC_DIFF_REPORT_CONTRACT,
280
+ authority: "typescript-v3",
281
+ rustAuthority: "none",
282
+ rustEffects: "disabled",
283
+ recordedAt: options.recordedAt,
284
+ retainUntil: new Date(
285
+ Date.parse(options.recordedAt) + 90 * 86400_000,
286
+ ).toISOString(),
287
+ sources: options.sources,
288
+ contracts: {
289
+ trace: V4_DELIVERY_WARRANT_TRACE_CONTRACT,
290
+ projection: V4_DELIVERY_WARRANT_PROJECTION_CONTRACT,
291
+ observation: V4_DELIVERY_WARRANT_SHADOW_OBSERVATION_CONTRACT,
292
+ runner: V4_DELIVERY_WARRANT_RUNNER_CONTRACT,
293
+ ...options.contracts,
294
+ },
295
+ coverage: {
296
+ required: [...V4_DELIVERY_WARRANT_SEMANTIC_DIFF_REQUIRED_COVERAGE],
297
+ observed: [...coverage].sort(),
298
+ missing,
299
+ },
300
+ cases: projected.map((entry) => entry.report),
301
+ faultInjection: { bounded: true, maximumProbes: 32, receipts },
302
+ stopPolicy: {
303
+ retryBudget: 0,
304
+ conditions: [
305
+ "authority-mismatch",
306
+ "coverage-incomplete",
307
+ "fault-injection-undetected",
308
+ "input-binding-mismatch",
309
+ "input-not-public-safe",
310
+ "missing-observation",
311
+ "retention-failed",
312
+ "source-binding-mismatch",
313
+ "unexplained-difference",
314
+ ],
315
+ },
316
+ };
317
+ let retention = {
318
+ status: "failed",
319
+ evidenceRoot: v4ContentRoot("semantic-diff", body),
320
+ receiptRoot: null,
321
+ };
322
+ try {
323
+ const receipt = await options.retain?.(structuredClone(body));
324
+ validateV4Root(receipt?.receiptRoot);
325
+ retention = {
326
+ ...retention,
327
+ status: "retained",
328
+ receiptRoot: receipt.receiptRoot,
329
+ };
330
+ } catch {
331
+ blockers.push(stop("retention-failed"));
332
+ }
333
+ const unique = [
334
+ ...new Map(blockers.map((entry) => [entry.code, entry])).values(),
335
+ ].sort((a, b) => (a.code < b.code ? -1 : 1));
336
+ const report = {
337
+ ...body,
338
+ retention,
339
+ blockers: unique,
340
+ verdict: {
341
+ status: unique.length ? "blocked" : "qualified",
342
+ zeroUnexplainedDifferences: !projected.some((entry) =>
343
+ entry.report.differences.some(
344
+ (diff) => diff.classification === "unexplained",
345
+ ),
346
+ ),
347
+ nextEligibleStage: unique.length ? null : "legacy-authoritative-v4-read",
348
+ v4WriteAuthorized: false,
349
+ },
350
+ };
351
+ return { ...report, reportRoot: v4ContentRoot("semantic-diff", report) };
352
+ }