@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,601 @@
1
+ #!/usr/bin/env node
2
+
3
+ import fs from "node:fs";
4
+ import path from "node:path";
5
+ import { pathToFileURL } from "node:url";
6
+
7
+ import {
8
+ cancelQueuedDevDeliveryCandidate,
9
+ closeDevDeliveryWarrant,
10
+ createDevDeliveryQueue,
11
+ devDeliveryContentRoot,
12
+ heartbeatDevDeliveryWarrant,
13
+ recoverExpiredDevDeliveryWarrant,
14
+ selectDevDeliveryWarrant,
15
+ settleDevDeliveryTerminalEvent,
16
+ submitDevDeliveryCandidate,
17
+ } from "../packages/core/dev-delivery-warrant.js";
18
+
19
+ const PLAN_PATH = "architecture/v4-delivery-warrant-shadow-bootstrap-plan.json";
20
+ const PLAN_SCHEMA_PATH =
21
+ "architecture/v4-delivery-warrant-shadow-bootstrap-plan.schema.json";
22
+ const FIXTURES_PATH = "architecture/v4-delivery-warrant-shadow-fixtures.json";
23
+ const FIXTURES_SCHEMA_PATH =
24
+ "architecture/v4-delivery-warrant-shadow-fixtures.schema.json";
25
+ const MANIFEST_PATH = "architecture/v4-capability-state-machine-manifest.json";
26
+ const BOOTSTRAP_PATH = "architecture/v4-bootstrap-authority.json";
27
+ const ROOT_PATTERN = /^sha256:[0-9a-f]{64}$/u;
28
+ const REQUIRED_PRIMITIVES = [
29
+ "canonical-json",
30
+ "content-root",
31
+ "expected-old",
32
+ "explicit-clock",
33
+ "decide-fold",
34
+ "effects",
35
+ "observations",
36
+ "typed-retry",
37
+ "receipts",
38
+ ];
39
+ const REQUIRED_STAGES = [
40
+ "legacy-authoritative-shadow",
41
+ "legacy-authoritative-v4-read",
42
+ "v4-authoritative-write",
43
+ "legacy-removal",
44
+ ];
45
+
46
+ function readJson(root, relativePath) {
47
+ return JSON.parse(fs.readFileSync(path.join(root, relativePath), "utf8"));
48
+ }
49
+ function required(condition, message, issues) {
50
+ if (!condition) issues.push(message);
51
+ }
52
+ function nonEmpty(value) {
53
+ return typeof value === "string" && value.trim() !== "";
54
+ }
55
+ function exactSet(left, right) {
56
+ return (
57
+ left.length === right.length &&
58
+ [...left].sort().every((entry, index) => entry === [...right].sort()[index])
59
+ );
60
+ }
61
+ function validateSchemaDocument(schema, relativePath, issues) {
62
+ required(
63
+ schema?.$schema === "https://json-schema.org/draft/2020-12/schema",
64
+ `${relativePath} must use JSON Schema draft 2020-12`,
65
+ issues,
66
+ );
67
+ required(nonEmpty(schema?.$id), `${relativePath} must declare $id`, issues);
68
+ required(
69
+ schema?.type === "object" && schema?.additionalProperties === false,
70
+ `${relativePath} must be a closed object schema`,
71
+ issues,
72
+ );
73
+ }
74
+
75
+ function dependencyCycles(nodes) {
76
+ const graph = new Map(nodes.map((node) => [node.id, node.dependsOn]));
77
+ const active = new Set();
78
+ const done = new Set();
79
+ const cycles = [];
80
+ function visit(id, stack = []) {
81
+ if (active.has(id)) {
82
+ cycles.push([...stack.slice(stack.indexOf(id)), id]);
83
+ return;
84
+ }
85
+ if (done.has(id)) return;
86
+ active.add(id);
87
+ for (const dependency of graph.get(id) || [])
88
+ visit(dependency, [...stack, id]);
89
+ active.delete(id);
90
+ done.add(id);
91
+ }
92
+ for (const id of graph.keys()) visit(id);
93
+ return cycles;
94
+ }
95
+
96
+ function validatePlan({ plan, manifest, bootstrap }) {
97
+ const issues = [];
98
+ required(plan?.schemaVersion === 1, "plan schemaVersion must be 1", issues);
99
+ required(
100
+ plan?.contract ===
101
+ "kungfu-buildchain-v4-delivery-warrant-shadow-bootstrap-plan",
102
+ "plan contract is invalid",
103
+ issues,
104
+ );
105
+ required(
106
+ plan?.releaseLine === "dev/v4/v4.0",
107
+ "plan releaseLine must be dev/v4/v4.0",
108
+ issues,
109
+ );
110
+ const machine = manifest.stateMachines.find(
111
+ (entry) => entry.id === "dev-delivery-warrant",
112
+ );
113
+ required(
114
+ Boolean(machine),
115
+ "v4 manifest is missing dev-delivery-warrant",
116
+ issues,
117
+ );
118
+ if (machine) {
119
+ required(
120
+ exactSet(plan.legacyAuthority.states, machine.states),
121
+ "plan states must exactly cover the v3 inventory manifest",
122
+ issues,
123
+ );
124
+ required(
125
+ exactSet(plan.legacyAuthority.events, machine.events),
126
+ "plan events must exactly cover the v3 inventory manifest",
127
+ issues,
128
+ );
129
+ required(
130
+ plan.legacyAuthority.writer === "typescript-v3",
131
+ "plan must retain the qualified v3 comparison writer",
132
+ issues,
133
+ );
134
+ required(
135
+ machine.writer.runtime === "typescript-v4" &&
136
+ machine.migrationPhase === "legacy-retired",
137
+ "manifest must close the v4 writer cutover",
138
+ issues,
139
+ );
140
+ }
141
+ const coveredStates = new Set(
142
+ (plan.transitionMatrix || []).flatMap((entry) => entry.from),
143
+ );
144
+ const coveredEvents = new Set(
145
+ (plan.transitionMatrix || []).map((entry) => entry.event),
146
+ );
147
+ for (const state of plan.legacyAuthority.states || []) {
148
+ required(
149
+ coveredStates.has(state),
150
+ `transition matrix omits state ${state}`,
151
+ issues,
152
+ );
153
+ }
154
+ for (const event of plan.legacyAuthority.events || []) {
155
+ required(
156
+ coveredEvents.has(event),
157
+ `transition matrix omits event ${event}`,
158
+ issues,
159
+ );
160
+ }
161
+ required(
162
+ plan.canonicalContract.clock.mode === "explicit-input-only",
163
+ "v4 clock must be explicit-input-only",
164
+ issues,
165
+ );
166
+ required(
167
+ plan.canonicalContract.json.objectKeys === "ascii-code-point-order",
168
+ "canonical JSON key order must be frozen",
169
+ issues,
170
+ );
171
+ required(
172
+ exactSet(
173
+ (plan.primitives || []).map((entry) => entry.id),
174
+ REQUIRED_PRIMITIVES,
175
+ ),
176
+ "plan must declare the complete reusable primitive set",
177
+ issues,
178
+ );
179
+ required(
180
+ plan.boundaries.rustDomain.providerSdkImports === "forbidden",
181
+ "Rust domain must forbid provider SDK imports",
182
+ issues,
183
+ );
184
+ required(
185
+ plan.authority.permanentDualAuthority === false,
186
+ "permanent dual authority must be forbidden",
187
+ issues,
188
+ );
189
+ required(
190
+ plan.authority.candidateSelfQualification === false,
191
+ "candidate self-qualification must be forbidden",
192
+ issues,
193
+ );
194
+ required(
195
+ plan.authority.bootstrap.sourceCommit ===
196
+ bootstrap.releaseLine.sourceCommit &&
197
+ plan.authority.bootstrap.bootstrapCommit ===
198
+ bootstrap.releaseLine.bootstrapCommit,
199
+ "plan bootstrap coordinates must match v4 bootstrap authority",
200
+ issues,
201
+ );
202
+ required(
203
+ exactSet(
204
+ (plan.rollout || []).map((entry) => entry.id),
205
+ REQUIRED_STAGES,
206
+ ),
207
+ "rollout stages must cover shadow, read, write, and legacy removal",
208
+ issues,
209
+ );
210
+ for (const stage of plan.rollout || []) {
211
+ for (const field of [
212
+ "authority",
213
+ "entry",
214
+ "exit",
215
+ "rollback",
216
+ "evidence",
217
+ "stopConditions",
218
+ ]) {
219
+ const value = stage[field];
220
+ required(
221
+ nonEmpty(value) || (Array.isArray(value) && value.length > 0),
222
+ `rollout ${stage.id}.${field} must be non-empty`,
223
+ issues,
224
+ );
225
+ }
226
+ }
227
+ for (const disagreement of plan.legacyDisagreements || []) {
228
+ required(
229
+ ["preserve-in-compatibility", "change-in-v4", "block-cutover"].includes(
230
+ disagreement.disposition,
231
+ ),
232
+ `disagreement ${disagreement.id} has no explicit disposition`,
233
+ issues,
234
+ );
235
+ }
236
+ required(
237
+ (plan.legacyDisagreements || []).length >= 5,
238
+ "legacy disagreements must be explicit and source-grounded",
239
+ issues,
240
+ );
241
+ const nodes = plan.wave1?.nodes || [];
242
+ const nodeIds = new Set(nodes.map((entry) => entry.id));
243
+ for (const node of nodes) {
244
+ for (const dependency of node.dependsOn || []) {
245
+ required(
246
+ nodeIds.has(dependency),
247
+ `Wave 1 node ${node.id} depends on unknown node ${dependency}`,
248
+ issues,
249
+ );
250
+ }
251
+ }
252
+ for (const cycle of dependencyCycles(nodes))
253
+ issues.push(`Wave 1 dependency cycle: ${cycle.join(" -> ")}`);
254
+ // prettier-ignore
255
+ required(JSON.stringify([plan.wave0Reconciliation?.children?.length, plan.wave0Reconciliation?.productionAuthority]) === '[4,"typescript-v3"]', "Wave 0 reconciliation must retain v3 authority", issues);
256
+ // prettier-ignore
257
+ required(JSON.stringify([plan.wave1?.entryGate, plan.wave1?.readCandidateEntryGate]) === '["wave0-reconciliation-proved","all-shadow-zero-diff-gates-pass"]', "Wave 1 entry gates must remain distinct", issues);
258
+ if (issues.length > 0) {
259
+ throw new Error(
260
+ `v4 Warrant plan validation failed:\n- ${issues.join("\n- ")}`,
261
+ );
262
+ }
263
+ return {
264
+ schemaVersion: 1,
265
+ contract: "kungfu-buildchain-v4-delivery-warrant-plan-validation",
266
+ ok: true,
267
+ states: plan.legacyAuthority.states.length,
268
+ events: plan.legacyAuthority.events.length,
269
+ transitionRows: plan.transitionMatrix.length,
270
+ primitives: plan.primitives.length,
271
+ disagreements: plan.legacyDisagreements.length,
272
+ rolloutStages: plan.rollout.length,
273
+ wave1Nodes: nodes.length,
274
+ permanentDualAuthority: false,
275
+ candidateSelfQualification: false,
276
+ };
277
+ }
278
+
279
+ const ROOTS = Object.fromEntries(
280
+ [
281
+ "assignment",
282
+ "initiative",
283
+ "patch",
284
+ "proof",
285
+ "plan",
286
+ "closure",
287
+ "dependency",
288
+ "toolchain",
289
+ "evidence",
290
+ ].map((name, index) => [
291
+ name,
292
+ `sha256:${(index + 1).toString(16).repeat(64)}`,
293
+ ]),
294
+ );
295
+
296
+ function fixtureCandidate(number, overrides = {}) {
297
+ const digit = (number % 9) + 1;
298
+ return {
299
+ pullRequestNumber: number,
300
+ sourceHead: digit.toString(16).repeat(40),
301
+ assignmentRoot: ROOTS.assignment,
302
+ initiativeRoot: ROOTS.initiative,
303
+ sourceIdentityRoot: `sha256:${digit.toString(16).repeat(64)}`,
304
+ sourcePatchRoot: ROOTS.patch,
305
+ sourceProofRoot: ROOTS.proof,
306
+ planRoot: ROOTS.plan,
307
+ closureRoot: ROOTS.closure,
308
+ dependencyRoot: ROOTS.dependency,
309
+ toolchainRoot: ROOTS.toolchain,
310
+ deliveryClass: "native-proof-required",
311
+ priority: "ordinary",
312
+ ...overrides,
313
+ };
314
+ }
315
+
316
+ function classifyError(error) {
317
+ const message = error instanceof Error ? error.message : String(error);
318
+ if (/stale fencing token/u.test(message)) return "stale-fencing-token";
319
+ if (/lease expired/u.test(message)) return "lease-expired";
320
+ if (/stateRoot drift/u.test(message)) return "state-root-drift";
321
+ return "unclassified-error";
322
+ }
323
+ function projection(step, before, queue, result = {}) {
324
+ return {
325
+ id: step.id,
326
+ operation: step.operation,
327
+ action:
328
+ result.receipt?.action || result.receipt?.reason || result.action || null,
329
+ errorCode: result.errorCode || null,
330
+ expectedOldStateRoot:
331
+ result.receipt?.expectedOldStateRoot || before.stateRoot,
332
+ nextStateRoot: queue.stateRoot,
333
+ receiptRoot: result.receiptRoot || null,
334
+ generation: queue.generation,
335
+ fencingCounter: queue.fencingCounter,
336
+ activePullRequest: queue.activeWarrant?.pullRequestNumber || null,
337
+ candidateStates: queue.candidates.map((candidate) => ({
338
+ pullRequestNumber: candidate.pullRequestNumber,
339
+ status: candidate.status,
340
+ attempts: candidate.attempts,
341
+ recoveries: candidate.recoveries,
342
+ })),
343
+ };
344
+ }
345
+
346
+ function runTrace(trace) {
347
+ const initial = trace.create;
348
+ let queue = createDevDeliveryQueue({
349
+ repository: initial.repository,
350
+ protectedBase: initial.protectedBase,
351
+ policy: initial.policy,
352
+ now: initial.now,
353
+ });
354
+ const warrants = new Map();
355
+ const settlements = new Map();
356
+ const roots = new Map([["initial", queue.stateRoot]]);
357
+ const projections = [];
358
+ for (const step of trace.steps) {
359
+ const before = queue;
360
+ let result;
361
+ try {
362
+ if (step.operation === "submit") {
363
+ result = submitDevDeliveryCandidate(
364
+ queue,
365
+ fixtureCandidate(step.pullRequestNumber, step.overrides),
366
+ { now: step.now },
367
+ );
368
+ queue = result.queue;
369
+ } else if (step.operation === "select") {
370
+ result = selectDevDeliveryWarrant(queue, {
371
+ now: step.now,
372
+ leaseSeconds: step.leaseSeconds,
373
+ });
374
+ queue = result.queue;
375
+ if (step.saveWarrant) warrants.set(step.saveWarrant, result.warrant);
376
+ } else if (step.operation === "heartbeat") {
377
+ result = heartbeatDevDeliveryWarrant(
378
+ queue,
379
+ warrants.get(step.useWarrant),
380
+ { now: step.now, leaseSeconds: step.leaseSeconds },
381
+ );
382
+ queue = result.queue;
383
+ } else if (step.operation === "recover-expired") {
384
+ result = recoverExpiredDevDeliveryWarrant(queue, { now: step.now });
385
+ queue = result.queue;
386
+ } else if (step.operation === "close") {
387
+ result = closeDevDeliveryWarrant(queue, warrants.get(step.useWarrant), {
388
+ outcome: step.outcome,
389
+ evidenceRoot: ROOTS.evidence,
390
+ reason: step.reason,
391
+ now: step.now,
392
+ });
393
+ queue = result.queue;
394
+ } else if (step.operation === "settle-not-applicable") {
395
+ result = settleDevDeliveryTerminalEvent(
396
+ queue,
397
+ {
398
+ pullRequestNumber: step.pullRequestNumber,
399
+ sourceHead: step.sourceHead,
400
+ outcome: step.outcome,
401
+ reason: step.reason,
402
+ },
403
+ { now: step.now },
404
+ );
405
+ queue = result.queue;
406
+ } else if (step.operation === "settle-active") {
407
+ const warrant = warrants.get(step.useWarrant);
408
+ const input = {
409
+ pullRequestNumber: warrant.pullRequestNumber,
410
+ sourceHead: warrant.sourceHead,
411
+ fencingToken: warrant.fencingToken,
412
+ leaseGeneration: warrant.generation,
413
+ outcome: step.outcome,
414
+ evidenceRoot: ROOTS.evidence,
415
+ reason: step.reason,
416
+ };
417
+ result = settleDevDeliveryTerminalEvent(queue, input, {
418
+ now: step.now,
419
+ });
420
+ queue = result.queue;
421
+ settlements.set(step.saveSettlement, input);
422
+ } else if (step.operation === "settle-duplicate") {
423
+ result = settleDevDeliveryTerminalEvent(
424
+ queue,
425
+ settlements.get(step.useSettlement),
426
+ { now: step.now },
427
+ );
428
+ queue = result.queue;
429
+ } else if (step.operation === "cancel-queued") {
430
+ const candidate = queue.candidates.find(
431
+ (entry) => entry.pullRequestNumber === step.pullRequestNumber,
432
+ );
433
+ const input = {
434
+ candidateId: candidate.candidateId,
435
+ pullRequestNumber: candidate.pullRequestNumber,
436
+ expectedSourceHead: candidate.sourceHead,
437
+ observedSourceHead: step.observedSourceHead || candidate.sourceHead,
438
+ eventAction: "closed",
439
+ outcome: "cancelled",
440
+ evidenceRoot: ROOTS.evidence,
441
+ reason: step.reason,
442
+ };
443
+ result = cancelQueuedDevDeliveryCandidate(queue, input, {
444
+ now: step.now,
445
+ });
446
+ queue = result.queue;
447
+ } else if (step.operation === "expected-old") {
448
+ const expected = roots.get(step.expectedRoot);
449
+ result =
450
+ expected === queue.stateRoot
451
+ ? { action: "cas-accepted" }
452
+ : { action: "cas-rejected", errorCode: "stale-expected-old" };
453
+ } else if (step.operation === "response-loss-readback") {
454
+ result = {
455
+ action:
456
+ roots.get(step.committedRoot) === queue.stateRoot
457
+ ? "committed-readback"
458
+ : "indeterminate-stop",
459
+ };
460
+ } else if (step.operation === "provider-conflict") {
461
+ result = {
462
+ action: "provider-conflict-stop",
463
+ errorCode: "provider-conflict",
464
+ };
465
+ } else {
466
+ throw new Error(`unsupported fixture operation: ${step.operation}`);
467
+ }
468
+ if (step.expectError) {
469
+ throw new Error(`fixture step ${step.id} expected ${step.expectError}`);
470
+ }
471
+ } catch (error) {
472
+ const errorCode = classifyError(error);
473
+ if (!step.expectError || step.expectError !== errorCode) throw error;
474
+ result = { errorCode };
475
+ queue = before;
476
+ }
477
+ roots.set(step.id, queue.stateRoot);
478
+ projections.push(projection(step, before, queue, result));
479
+ }
480
+ return {
481
+ id: trace.id,
482
+ projectionRoot: devDeliveryContentRoot(projections),
483
+ projections,
484
+ };
485
+ }
486
+
487
+ function validateFixtures(fixtures, { verifyRoots = true } = {}) {
488
+ const issues = [];
489
+ required(
490
+ fixtures?.schemaVersion === 1,
491
+ "fixtures schemaVersion must be 1",
492
+ issues,
493
+ );
494
+ required(
495
+ fixtures?.contract ===
496
+ "kungfu-buildchain-v4-delivery-warrant-shadow-fixtures",
497
+ "fixtures contract is invalid",
498
+ issues,
499
+ );
500
+ required(
501
+ fixtures?.canonicalization === "buildchain-canonical-json/v1",
502
+ "fixtures must bind canonicalization v1",
503
+ issues,
504
+ );
505
+ required(
506
+ fixtures?.clock === "explicit-input-only",
507
+ "fixtures must forbid ambient time",
508
+ issues,
509
+ );
510
+ const results = (fixtures.traces || []).map(runTrace);
511
+ for (const [index, result] of results.entries()) {
512
+ const expected = fixtures.traces[index].expectedLegacyProjectionRoot;
513
+ required(
514
+ ROOT_PATTERN.test(expected),
515
+ `${result.id} expected root is invalid`,
516
+ issues,
517
+ );
518
+ if (verifyRoots) {
519
+ required(
520
+ result.projectionRoot === expected,
521
+ `${result.id} projection drift: ${result.projectionRoot} != ${expected}`,
522
+ issues,
523
+ );
524
+ }
525
+ }
526
+ if (issues.length > 0) {
527
+ throw new Error(
528
+ `v4 Warrant fixture validation failed:\n- ${issues.join("\n- ")}`,
529
+ );
530
+ }
531
+ return results;
532
+ }
533
+
534
+ function loadWarrantPlan(
535
+ root = process.cwd(),
536
+ { verifyFixtureRoots = true } = {},
537
+ ) {
538
+ const planSchema = readJson(root, PLAN_SCHEMA_PATH);
539
+ const fixturesSchema = readJson(root, FIXTURES_SCHEMA_PATH);
540
+ const schemaIssues = [];
541
+ validateSchemaDocument(planSchema, PLAN_SCHEMA_PATH, schemaIssues);
542
+ validateSchemaDocument(fixturesSchema, FIXTURES_SCHEMA_PATH, schemaIssues);
543
+ if (schemaIssues.length > 0) {
544
+ throw new Error(
545
+ `v4 Warrant schema validation failed:\n- ${schemaIssues.join("\n- ")}`,
546
+ );
547
+ }
548
+ const plan = readJson(root, PLAN_PATH);
549
+ const fixtures = readJson(root, FIXTURES_PATH);
550
+ const report = validatePlan({
551
+ plan,
552
+ manifest: readJson(root, MANIFEST_PATH),
553
+ bootstrap: readJson(root, BOOTSTRAP_PATH),
554
+ });
555
+ const fixtureResults = validateFixtures(fixtures, {
556
+ verifyRoots: verifyFixtureRoots,
557
+ });
558
+ return { plan, fixtures, report, fixtureResults };
559
+ }
560
+
561
+ function runCli(args = []) {
562
+ const [command = "validate"] = args;
563
+ const root = process.cwd();
564
+ if (command === "roots") {
565
+ const { fixtureResults } = loadWarrantPlan(root, {
566
+ verifyFixtureRoots: false,
567
+ });
568
+ process.stdout.write(
569
+ `${JSON.stringify(
570
+ fixtureResults.map(({ id, projectionRoot }) => ({
571
+ id,
572
+ projectionRoot,
573
+ })),
574
+ null,
575
+ 2,
576
+ )}\n`,
577
+ );
578
+ return;
579
+ }
580
+ if (command !== "validate")
581
+ throw new Error(`unsupported command: ${command}`);
582
+ const { report, fixtureResults } = loadWarrantPlan(root);
583
+ process.stdout.write(
584
+ `${JSON.stringify({ ...report, fixtureTraces: fixtureResults.length }, null, 2)}\n`,
585
+ );
586
+ }
587
+ if (
588
+ process.argv[1] &&
589
+ import.meta.url === pathToFileURL(path.resolve(process.argv[1])).href
590
+ ) {
591
+ try {
592
+ runCli(process.argv.slice(2));
593
+ } catch (error) {
594
+ console.error(
595
+ `buildchain v4 Warrant plan: ${error instanceof Error ? error.message : String(error)}`,
596
+ );
597
+ process.exitCode = 1;
598
+ }
599
+ }
600
+
601
+ export { loadWarrantPlan, runTrace, validateFixtures, validatePlan };
@@ -1,14 +1,14 @@
1
1
  #!/usr/bin/env node
2
- import { spawnSync } from "node:child_process";
3
2
  import fs from "node:fs";
4
3
  import os from "node:os";
5
4
  import path from "node:path";
6
5
  import { fileURLToPath } from "node:url";
6
+ import { spawnSyncCommand } from "../packages/core/spawn-command.js";
7
7
 
8
8
  const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
9
9
 
10
10
  function run(command, args, { cwd, json = false } = {}) {
11
- const result = spawnSync(command, args, {
11
+ const result = spawnSyncCommand(command, args, {
12
12
  cwd,
13
13
  encoding: "utf8",
14
14
  env: {
@@ -89,7 +89,7 @@ export function verifyGoldenPath() {
89
89
  );
90
90
  const releaseDryRun = run(
91
91
  buildchain,
92
- ["release", "--dry-run", "--target-ref", "alpha/v3/v3.0", "--json"],
92
+ ["release", "--dry-run", "--target-ref", "alpha/v4/v4.0", "--json"],
93
93
  { cwd: consumer, json: true },
94
94
  );
95
95
  const passportPath = path.join(
@@ -129,10 +129,10 @@ export function verifyGoldenPath() {
129
129
  "Golden Path validation did not retain the required lifecycle stages",
130
130
  );
131
131
  assert(
132
- /uses:\s+kungfu-systems\/buildchain\/.github\/workflows\/.build.yml@v3/.test(
132
+ /uses:\s+kungfu-systems\/buildchain\/.github\/workflows\/.build.yml@v4/.test(
133
133
  workflow,
134
134
  ),
135
- "Golden Path workflow is not a thin v3 reusable-workflow caller",
135
+ "Golden Path workflow is not a thin v4 reusable-workflow caller",
136
136
  );
137
137
  assert(
138
138
  /buildchain-ref:/.test(workflow),