@kungfu-tech/buildchain 3.0.9-alpha.8 → 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 (255) 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 -6
  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 -3
  65. package/dist/site/artifact-schemas.json +0 -6
  66. package/dist/site/buildchain-contract.json +103 -397
  67. package/dist/site/buildchain-site.json +302 -270
  68. package/dist/site/capability-registry.json +9 -11
  69. package/dist/site/cli-registry.json +8 -30
  70. package/dist/site/controller-registry.json +48 -8
  71. package/dist/site/kfd-claims.json +129 -142
  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 +1882 -4118
  75. package/dist/site/page-registry.json +278 -230
  76. package/dist/site/public-surface-audit.json +87 -185
  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 -7
  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 +80 -35
  83. package/docs/MAP.md +8 -4
  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 -92
  87. package/docs/cli.md +14 -14
  88. package/docs/dev-alpha-candidate-patrol.md +3 -11
  89. package/docs/dev-delivery-warrant.md +28 -100
  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 -523
  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 -3
  111. package/package.json +19 -17
  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-config.js +4 -69
  119. package/packages/core/buildchain-contract.js +232 -46
  120. package/packages/core/buildchain-kfd-claims.js +1 -1
  121. package/packages/core/channel-candidate.js +0 -8
  122. package/packages/core/channel-promotion-baseline.js +0 -52
  123. package/packages/core/controller-evidence.js +3 -4
  124. package/packages/core/dev-alpha-candidate-selection.js +2 -10
  125. package/packages/core/dev-delivery-warrant-cancellation.js +0 -1
  126. package/packages/core/dev-delivery-warrant-settlement.js +1 -5
  127. package/packages/core/dev-delivery-warrant.js +12 -52
  128. package/packages/core/diagnostics.js +3 -8
  129. package/packages/core/github-governance-authority.js +3 -1
  130. package/packages/core/kfd-adopter-category-driver.js +167 -0
  131. package/packages/core/kfd-adopter-manifest.js +47 -46
  132. package/packages/core/kfd-gate.js +15 -45
  133. package/packages/core/paper-agent-entry.js +7 -16
  134. package/packages/core/paper-fleet.js +2 -2
  135. package/packages/core/paper-repository.js +2 -3
  136. package/packages/core/paper-scaffold-content.js +2 -23
  137. package/packages/core/paper.js +11 -43
  138. package/packages/core/publication-reproducibility.js +4 -4
  139. package/packages/core/release-line-bootstrap.js +21 -8
  140. package/packages/core/release-passport-contract.js +5 -5
  141. package/packages/core/release-passport.js +20 -131
  142. package/packages/core/self-dogfood-version.js +48 -35
  143. package/packages/core/spawn-command.js +232 -8
  144. package/packages/core/v4-adopter-delivery-parity.js +219 -0
  145. package/packages/core/v4-canonical-contracts.js +284 -0
  146. package/packages/core/v4-delivery-warrant-fixture-runner.js +371 -0
  147. package/packages/core/v4-delivery-warrant-read-candidate.js +279 -0
  148. package/packages/core/v4-delivery-warrant-semantic-diff-gate.js +352 -0
  149. package/packages/core/v4-delivery-warrant-shadow-adapter.js +447 -0
  150. package/packages/core/v4-partial-mutation-recovery-qualification.js +395 -0
  151. package/packages/core/v4-platform-stage-checkpoints.js +471 -0
  152. package/packages/core/v4-provider-operation-journal.js +531 -0
  153. package/packages/core/v4-provider-readback-idempotency.js +394 -0
  154. package/packages/core/v4-release-activation-shadow.js +519 -0
  155. package/packages/core/v4-stable-publication-fence.js +357 -0
  156. package/packages/core/v4-stage-capsule-local-store.js +426 -0
  157. package/packages/core/v4-stage-capsule-qualification-campaign.js +512 -0
  158. package/packages/core/v4-stage-capsule-qualification.js +456 -0
  159. package/packages/core/v4-stage-capsule-resume-planner.js +397 -0
  160. package/packages/core/v4-stage-capsule-store.js +401 -0
  161. package/packages/core/v4-stage-capsule.js +319 -0
  162. package/scripts/assemble-self-publication-admission.mjs +1 -1
  163. package/scripts/audit-publication-control-plane.mjs +5 -5
  164. package/scripts/auditable-demo-bundle-verification.mjs +3 -2
  165. package/scripts/auditable-demo-platform.mjs +2 -2
  166. package/scripts/auditable-demo-renditions.mjs +1 -1
  167. package/scripts/auditable-demo.mjs +2 -2
  168. package/scripts/aws-macos-jit-controller-core.mjs +13 -346
  169. package/scripts/aws-macos-jit-controller-runtime.mjs +2 -210
  170. package/scripts/aws-macos-jit-controller.mjs +37 -275
  171. package/scripts/aws-macos-jit-core.mjs +3 -41
  172. package/scripts/aws-macos-jit.mjs +0 -12
  173. package/scripts/aws-windows-jit-campaign.mjs +2 -2
  174. package/scripts/aws-windows-jit-controller-core.mjs +1 -1
  175. package/scripts/aws-windows-jit-controller.mjs +3 -3
  176. package/scripts/build-contract-core.mjs +3 -8
  177. package/scripts/build-standalone-binary.mjs +3 -14
  178. package/scripts/buildchain-channel-router.mjs +4 -0
  179. package/scripts/buildchain-cli-help.mjs +7 -13
  180. package/scripts/buildchain-contract-lock.mjs +0 -6
  181. package/scripts/check-action-bundles.mjs +3 -4
  182. package/scripts/check-internal-architecture.mjs +7 -6
  183. package/scripts/check-inventory.mjs +30 -25
  184. package/scripts/check-v4-public-dogfood-contract.mjs +270 -0
  185. package/scripts/create-release-bundle.mjs +8 -4
  186. package/scripts/dev-alpha-candidate-patrol.mjs +1 -22
  187. package/scripts/dev-delivery-proof.mjs +2 -54
  188. package/scripts/dev-delivery-warrant.mjs +59 -77
  189. package/scripts/dev-pr-auto-merge.mjs +4 -30
  190. package/scripts/dev-pr-delivery-warrant.mjs +0 -55
  191. package/scripts/dispatch-artifact-signing-authority.mjs +7 -4
  192. package/scripts/generate-buildchain-kfd-witnesses.mjs +94 -88
  193. package/scripts/generate-channel-build-workflow.mjs +54 -24
  194. package/scripts/generate-channel-promotion-workflow.mjs +15 -6
  195. package/scripts/generate-site-bundle.mjs +5 -21
  196. package/scripts/git-fetch-process-tree.mjs +34 -1
  197. package/scripts/init-repo.mjs +64 -159
  198. package/scripts/inspect-artifact-signing-requests.mjs +0 -6
  199. package/scripts/locked-source-checkout.mjs +3 -4
  200. package/scripts/maintainability-metrics.mjs +8 -2
  201. package/scripts/npm-publish-dry-run.mjs +2 -2
  202. package/scripts/npm-publish-transaction.mjs +2 -2
  203. package/scripts/publication-commit-evidence.mjs +23 -69
  204. package/scripts/release-candidate-resolver.mjs +11 -17
  205. package/scripts/release-tail.mjs +3 -49
  206. package/scripts/resume-from-candidate-run.mjs +9 -123
  207. package/scripts/run-lifecycle-core.mjs +12 -13
  208. package/scripts/seal-artifact-signing-requests.mjs +17 -21
  209. package/scripts/site-capability-metadata.mjs +2 -7
  210. package/scripts/stable-candidate-qualification.mjs +10 -10
  211. package/scripts/v4-architecture.mjs +12 -2
  212. package/scripts/v4-bridge-bootstrap.mjs +141 -0
  213. package/scripts/v4-bridge-evidence.mjs +141 -0
  214. package/scripts/v4-host-adapter.mjs +182 -0
  215. package/scripts/v4-platform-stage-checkpoint-rehearsal.mjs +207 -0
  216. package/scripts/v4-stage-capsule-qualification.mjs +528 -0
  217. package/scripts/v4-stage-capsule-resume-rehearsal.mjs +57 -0
  218. package/scripts/v4-warrant-shadow-plan.mjs +601 -0
  219. package/scripts/verify-golden-path.mjs +5 -5
  220. package/scripts/web-surface-cloudfront-rewrite.mjs +15 -15
  221. package/scripts/web-surface-core.mjs +2 -8
  222. package/scripts/workflow-call-contract.mjs +5 -184
  223. package/contracts/fixtures/kfd-adopter-release-v1/kfd-4-perspective.json +0 -16
  224. package/contracts/fixtures/kfd-adopter-release-v1/kfd-4-replay.json +0 -57
  225. package/contracts/fixtures/next-development-transition-v1/anchored-manual-waiting.json +0 -47
  226. package/contracts/fixtures/next-development-transition-v1/semver-auto-planned.json +0 -47
  227. package/contracts/fixtures/next-development-transition-v1/version-model-cases.json +0 -40
  228. package/contracts/next-development-request-v1.schema.json +0 -66
  229. package/contracts/next-development-transition-v1.schema.json +0 -292
  230. package/contracts/publication-rehearsal-capsule-v1.schema.json +0 -173
  231. package/dist/site/schemas/publication-rehearsal-capsule-v1.schema.json +0 -269
  232. package/dist/site/schemas/release-tail-capabilities-v1.schema.json +0 -353
  233. package/dist/site/schemas/release-tail-provider-bindings-v1.schema.json +0 -94
  234. package/docs/next-development-transition.md +0 -119
  235. package/docs/publication-rehearsal.md +0 -94
  236. package/packages/core/buildchain-compatibility-proof.js +0 -631
  237. package/packages/core/dev-delivery-native-proof.js +0 -333
  238. package/packages/core/dev-delivery-warrant-shadow.js +0 -502
  239. package/packages/core/next-development-candidate-reservation.js +0 -186
  240. package/packages/core/next-development-controller.js +0 -726
  241. package/packages/core/next-development-projection.js +0 -288
  242. package/packages/core/next-development-transition.js +0 -738
  243. package/packages/core/publication-rehearsal-projection.js +0 -173
  244. package/packages/core/publication-rehearsal-runtime.js +0 -921
  245. package/scripts/aws-macos-jit-instance-rehydrate.mjs +0 -260
  246. package/scripts/aws-macos-jit-source-rebind.mjs +0 -724
  247. package/scripts/dev-delivery-native-run.mjs +0 -187
  248. package/scripts/dev-delivery-two-phase.mjs +0 -598
  249. package/scripts/generate-next-development-guidance.mjs +0 -49
  250. package/scripts/materialize-self-release-candidate-version.mjs +0 -137
  251. package/scripts/next-development-self-dogfood-harness.mjs +0 -409
  252. package/scripts/next-development-self-dogfood.mjs +0 -532
  253. package/scripts/next-development-transition.mjs +0 -47
  254. package/scripts/release-candidate-tail-reseal.mjs +0 -426
  255. package/templates/native-dev-delivery.yml +0 -82
@@ -0,0 +1,471 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+
4
+ import {
5
+ V4ContractFault,
6
+ v4CanonicalBytes,
7
+ validateV4Clock,
8
+ validateV4Root,
9
+ } from "./v4-canonical-contracts.js";
10
+ import {
11
+ V4_STAGE_CAPSULE_CONTRACT,
12
+ V4_STAGE_CAPSULE_IDENTITY_CONTRACT,
13
+ v4StageCapsuleIdentityRoot,
14
+ v4StageCapsuleRoot,
15
+ validateV4StageCapsule,
16
+ } from "./v4-stage-capsule.js";
17
+ import {
18
+ V4_STAGE_CAPSULE_OUTPUT_MANIFEST_CONTRACT,
19
+ v4StageCapsuleBlobRoot,
20
+ v4StageCapsuleOutputManifestRoot,
21
+ } from "./v4-stage-capsule-store.js";
22
+
23
+ export const V4_PLATFORM_STAGE_CHECKPOINT_CONTRACT =
24
+ "buildchain-v4-platform-stage-checkpoint/v1";
25
+ export const V4_PLATFORM_STAGE_RESTORE_CONTRACT =
26
+ "buildchain-v4-platform-stage-restore/v1";
27
+
28
+ const TOKEN = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/u;
29
+ const ZERO_ROOT = `sha256:${"0".repeat(64)}`;
30
+
31
+ function fault(code, location, message) {
32
+ throw new V4ContractFault(code, location, message);
33
+ }
34
+
35
+ function object(value, location) {
36
+ if (!value || typeof value !== "object" || Array.isArray(value))
37
+ fault("invalid-stage-checkpoint-shape", location, "object required");
38
+ return value;
39
+ }
40
+
41
+ function exactKeys(value, expected, location) {
42
+ object(value, location);
43
+ const actual = Object.keys(value).sort();
44
+ const canonical = [...expected].sort();
45
+ if (
46
+ actual.length !== canonical.length ||
47
+ actual.some((key, index) => key !== canonical[index])
48
+ )
49
+ fault(
50
+ "undeclared-stage-checkpoint-field",
51
+ location,
52
+ `${location} keys do not match the declaration`,
53
+ );
54
+ }
55
+
56
+ function tokens(values, location) {
57
+ if (!Array.isArray(values))
58
+ fault("invalid-stage-checkpoint-shape", location, "array required");
59
+ let prior = null;
60
+ for (const [index, value] of values.entries()) {
61
+ if (typeof value !== "string" || !TOKEN.test(value))
62
+ fault(
63
+ "invalid-stage-checkpoint-token",
64
+ `${location}/${index}`,
65
+ "token required",
66
+ );
67
+ if (prior !== null && value <= prior)
68
+ fault(
69
+ "unordered-stage-checkpoint-declaration",
70
+ `${location}/${index}`,
71
+ "tokens must be unique and byte-sorted",
72
+ );
73
+ prior = value;
74
+ }
75
+ return values;
76
+ }
77
+
78
+ function rootOf(value) {
79
+ return v4StageCapsuleBlobRoot(v4CanonicalBytes(value));
80
+ }
81
+
82
+ function declaredMap(value, names, location, { roots = false } = {}) {
83
+ exactKeys(value, names, location);
84
+ return names.map((name) => {
85
+ const entry = value[name];
86
+ if (roots) validateV4Root(entry, `${location}/${name}`);
87
+ else if (typeof entry !== "string")
88
+ fault(
89
+ "invalid-stage-checkpoint-value",
90
+ `${location}/${name}`,
91
+ "string required",
92
+ );
93
+ return { name, root: roots ? entry : rootOf(entry) };
94
+ });
95
+ }
96
+
97
+ function safeRelative(relativePath, location) {
98
+ if (
99
+ typeof relativePath !== "string" ||
100
+ relativePath.length === 0 ||
101
+ path.isAbsolute(relativePath) ||
102
+ relativePath.includes("\\") ||
103
+ relativePath
104
+ .split("/")
105
+ .some((part) => part === "" || part === "." || part === "..")
106
+ )
107
+ fault(
108
+ "unsafe-stage-checkpoint-path",
109
+ location,
110
+ "declared output path must be a portable relative path",
111
+ );
112
+ return relativePath;
113
+ }
114
+
115
+ export function validateV4PlatformStageCheckpointDeclaration(value) {
116
+ exactKeys(
117
+ value,
118
+ [
119
+ "schemaVersion",
120
+ "contract",
121
+ "capsuleAuthority",
122
+ "storeAuthority",
123
+ "mode",
124
+ "platforms",
125
+ "stages",
126
+ "projections",
127
+ "authority",
128
+ ],
129
+ "$/declaration",
130
+ );
131
+ if (
132
+ value.schemaVersion !== 1 ||
133
+ value.contract !== "kungfu-buildchain-v4-platform-stage-checkpoints" ||
134
+ value.mode !== "shadow-only"
135
+ )
136
+ fault(
137
+ "unsupported-stage-checkpoint-declaration",
138
+ "$/declaration",
139
+ "unsupported checkpoint declaration",
140
+ );
141
+ if (!Array.isArray(value.platforms) || value.platforms.length !== 3)
142
+ fault(
143
+ "invalid-stage-checkpoint-platforms",
144
+ "$/declaration/platforms",
145
+ "three platforms required",
146
+ );
147
+ const platformIds = [];
148
+ for (const [index, platform] of value.platforms.entries()) {
149
+ exactKeys(
150
+ platform,
151
+ ["id", "os", "arch", "runner"],
152
+ `$/declaration/platforms/${index}`,
153
+ );
154
+ for (const key of ["id", "os", "arch"])
155
+ if (typeof platform[key] !== "string" || !TOKEN.test(platform[key]))
156
+ fault(
157
+ "invalid-stage-checkpoint-token",
158
+ `$/declaration/platforms/${index}/${key}`,
159
+ "token required",
160
+ );
161
+ if (typeof platform.runner !== "string" || platform.runner.length === 0)
162
+ fault(
163
+ "invalid-stage-checkpoint-value",
164
+ `$/declaration/platforms/${index}/runner`,
165
+ "runner required",
166
+ );
167
+ platformIds.push(platform.id);
168
+ }
169
+ tokens([...platformIds].sort(), "$/declaration/platformIds");
170
+ if (!Array.isArray(value.stages) || value.stages.length === 0)
171
+ fault(
172
+ "invalid-stage-checkpoint-stages",
173
+ "$/declaration/stages",
174
+ "stages required",
175
+ );
176
+ const stageIds = [];
177
+ for (const [index, stage] of value.stages.entries()) {
178
+ const location = `$/declaration/stages/${index}`;
179
+ exactKeys(
180
+ stage,
181
+ [
182
+ "id",
183
+ "inputs",
184
+ "outputs",
185
+ "environment",
186
+ "toolchains",
187
+ "providerEffects",
188
+ ],
189
+ location,
190
+ );
191
+ if (
192
+ typeof stage.id !== "string" ||
193
+ !TOKEN.test(stage.id) ||
194
+ stage.providerEffects !== false
195
+ )
196
+ fault(
197
+ "invalid-stage-checkpoint-stage",
198
+ location,
199
+ "stage id and effect boundary are invalid",
200
+ );
201
+ tokens(stage.inputs, `${location}/inputs`);
202
+ tokens(stage.environment, `${location}/environment`);
203
+ tokens(stage.toolchains, `${location}/toolchains`);
204
+ if (!Array.isArray(stage.outputs) || stage.outputs.length === 0)
205
+ fault(
206
+ "invalid-stage-checkpoint-outputs",
207
+ `${location}/outputs`,
208
+ "outputs required",
209
+ );
210
+ const outputNames = [];
211
+ for (const [outputIndex, output] of stage.outputs.entries()) {
212
+ exactKeys(output, ["name", "path"], `${location}/outputs/${outputIndex}`);
213
+ if (typeof output.name !== "string" || !TOKEN.test(output.name))
214
+ fault(
215
+ "invalid-stage-checkpoint-token",
216
+ `${location}/outputs/${outputIndex}/name`,
217
+ "token required",
218
+ );
219
+ safeRelative(output.path, `${location}/outputs/${outputIndex}/path`);
220
+ outputNames.push(output.name);
221
+ }
222
+ tokens([...outputNames].sort(), `${location}/outputNames`);
223
+ stageIds.push(stage.id);
224
+ }
225
+ tokens([...stageIds].sort(), "$/declaration/stageIds");
226
+ exactKeys(
227
+ value.projections,
228
+ ["protectedWorkflow", "generatedTemplate", "agentGuidance", "manual"],
229
+ "$/declaration/projections",
230
+ );
231
+ exactKeys(
232
+ value.authority,
233
+ [
234
+ "productionStageSkipping",
235
+ "providerEffects",
236
+ "credentials",
237
+ "ambientEnvironment",
238
+ "ambientClock",
239
+ "v3BehaviorChange",
240
+ ],
241
+ "$/declaration/authority",
242
+ );
243
+ if (Object.values(value.authority).some((entry) => entry !== false))
244
+ fault(
245
+ "invalid-stage-checkpoint-authority",
246
+ "$/declaration/authority",
247
+ "shadow declaration cannot grant authority",
248
+ );
249
+ return value;
250
+ }
251
+
252
+ function select(declaration, platformId, stageId) {
253
+ validateV4PlatformStageCheckpointDeclaration(declaration);
254
+ const platform = declaration.platforms.find(
255
+ (entry) => entry.id === platformId,
256
+ );
257
+ const stage = declaration.stages.find((entry) => entry.id === stageId);
258
+ if (!platform || !stage)
259
+ fault(
260
+ "undeclared-stage-checkpoint",
261
+ "$/request",
262
+ "platform and stage must be declared",
263
+ );
264
+ return { platform, stage };
265
+ }
266
+
267
+ function outputManifest(stage, outputs) {
268
+ exactKeys(
269
+ outputs,
270
+ stage.outputs.map((entry) => entry.name),
271
+ "$/request/outputs",
272
+ );
273
+ const entries = stage.outputs
274
+ .map(({ name }) => {
275
+ const bytes = Buffer.from(outputs[name]);
276
+ return { name, root: v4StageCapsuleBlobRoot(bytes), size: bytes.length };
277
+ })
278
+ .sort((left, right) => left.name.localeCompare(right.name, "en"));
279
+ const draft = {
280
+ schema: V4_STAGE_CAPSULE_OUTPUT_MANIFEST_CONTRACT,
281
+ entries,
282
+ manifestRoot: ZERO_ROOT,
283
+ };
284
+ return { ...draft, manifestRoot: v4StageCapsuleOutputManifestRoot(draft) };
285
+ }
286
+
287
+ export function emitV4PlatformStageCheckpoint(request) {
288
+ const { platform, stage } = select(
289
+ request.declaration,
290
+ request.platformId,
291
+ request.stageId,
292
+ );
293
+ validateV4Clock(request.recordedAt, "$/request/recordedAt");
294
+ if (request.stageOutcome !== "success")
295
+ return Object.freeze({ emitted: false, reason: "stage-not-successful" });
296
+ if (!Number.isSafeInteger(request.overheadMs) || request.overheadMs < 0)
297
+ fault(
298
+ "invalid-stage-checkpoint-overhead",
299
+ "$/request/overheadMs",
300
+ "non-negative integer required",
301
+ );
302
+ const inputs = declaredMap(request.inputs, stage.inputs, "$/request/inputs", {
303
+ roots: true,
304
+ });
305
+ const environmentRoots = declaredMap(
306
+ request.environment,
307
+ stage.environment,
308
+ "$/request/environment",
309
+ );
310
+ const toolchainRoots = declaredMap(
311
+ request.toolchains,
312
+ stage.toolchains,
313
+ "$/request/toolchains",
314
+ { roots: true },
315
+ );
316
+ const manifest = outputManifest(stage, request.outputs);
317
+ const productionOutputRoots = declaredMap(
318
+ request.productionOutputRoots,
319
+ stage.outputs.map((entry) => entry.name),
320
+ "$/request/productionOutputRoots",
321
+ { roots: true },
322
+ );
323
+ const manifestRoots = manifest.entries.map(({ name, root }) => ({
324
+ name,
325
+ root,
326
+ }));
327
+ const productionLifecycleRoot = rootOf(request.productionLifecycleResult);
328
+ const shadowLifecycleRoot = rootOf(request.shadowLifecycleResult);
329
+ if (
330
+ rootOf(productionOutputRoots) !== rootOf(manifestRoots) ||
331
+ productionLifecycleRoot !== shadowLifecycleRoot
332
+ )
333
+ fault(
334
+ "stage-checkpoint-production-drift",
335
+ "$/request",
336
+ "shadow checkpoint inputs differ from production bytes or lifecycle result",
337
+ );
338
+ const shadowComparison = {
339
+ productionOutputRoots,
340
+ shadowOutputRoots: manifestRoots,
341
+ productionLifecycleRoot,
342
+ shadowLifecycleRoot,
343
+ };
344
+ const identity = {
345
+ schema: V4_STAGE_CAPSULE_IDENTITY_CONTRACT,
346
+ sourceRoot: request.inputs["source-tree"],
347
+ platform: platform.id,
348
+ platformRoot: rootOf(platform),
349
+ stage: stage.id,
350
+ toolchainRoots,
351
+ runtimeRoot: rootOf(request.runtime),
352
+ policyRoot: rootOf(stage),
353
+ declaredInputs: inputs,
354
+ transformationRoot: rootOf(request.transformation),
355
+ outputManifestRoot: manifest.manifestRoot,
356
+ qualificationRoot: rootOf(request.qualification),
357
+ observationRoots: [
358
+ { name: "declared-environment", root: rootOf(environmentRoots) },
359
+ { name: "shadow-comparison", root: rootOf(shadowComparison) },
360
+ ],
361
+ };
362
+ const capsule = {
363
+ schema: V4_STAGE_CAPSULE_CONTRACT,
364
+ writerAuthority: "typescript-v3",
365
+ rustAuthority: "validation-only",
366
+ identity,
367
+ identityRoot: v4StageCapsuleIdentityRoot(identity),
368
+ retentionPromise: request.retentionPromise,
369
+ capsuleRoot: ZERO_ROOT,
370
+ };
371
+ capsule.capsuleRoot = v4StageCapsuleRoot(capsule);
372
+ validateV4StageCapsule(capsule);
373
+ const blobs = manifest.entries.map((entry) => ({
374
+ name: entry.name,
375
+ bytes: Buffer.from(request.outputs[entry.name]),
376
+ }));
377
+ const receipt = request.store.put({
378
+ capsule,
379
+ manifest,
380
+ blobs,
381
+ recordedAt: request.recordedAt,
382
+ });
383
+ const body = {
384
+ schema: V4_PLATFORM_STAGE_CHECKPOINT_CONTRACT,
385
+ mode: "shadow-only",
386
+ platform: platform.id,
387
+ stage: stage.id,
388
+ capsuleRoot: capsule.capsuleRoot,
389
+ manifestRoot: manifest.manifestRoot,
390
+ storeReceiptRoot: receipt.receiptRoot,
391
+ productionBytesChanged: false,
392
+ lifecycleResultChanged: false,
393
+ overheadMs: request.overheadMs,
394
+ };
395
+ return {
396
+ emitted: true,
397
+ capsule,
398
+ manifest,
399
+ receipt,
400
+ report: { ...body, reportRoot: rootOf(body) },
401
+ };
402
+ }
403
+
404
+ function ensureEmptyDirectory(targetDirectory) {
405
+ const target = path.resolve(targetDirectory);
406
+ if (fs.existsSync(target) && fs.readdirSync(target).length !== 0)
407
+ fault(
408
+ "stage-checkpoint-restore-target-not-empty",
409
+ "$/targetDirectory",
410
+ "clean restore directory required",
411
+ );
412
+ fs.mkdirSync(target, { recursive: true });
413
+ return target;
414
+ }
415
+
416
+ export function restoreV4PlatformStageCheckpoint(request) {
417
+ const { stage } = select(
418
+ request.declaration,
419
+ request.expectedPlatform,
420
+ request.expectedStage,
421
+ );
422
+ validateV4Clock(request.recordedAt, "$/request/recordedAt");
423
+ const restored = request.store.restore({
424
+ capsuleRoot: request.capsuleRoot,
425
+ recordedAt: request.recordedAt,
426
+ });
427
+ if (
428
+ restored.capsule.identity.platform !== request.expectedPlatform ||
429
+ restored.capsule.identity.stage !== request.expectedStage
430
+ )
431
+ fault(
432
+ "stage-checkpoint-identity-mismatch",
433
+ "$/request",
434
+ "restored platform or stage differs",
435
+ );
436
+ const target = ensureEmptyDirectory(request.targetDirectory);
437
+ const byName = new Map(restored.blobs.map((entry) => [entry.name, entry]));
438
+ for (const output of stage.outputs) {
439
+ const blob = byName.get(output.name);
440
+ if (!blob)
441
+ fault(
442
+ "stage-capsule-partial",
443
+ `$/restore/${output.name}`,
444
+ "declared output missing",
445
+ );
446
+ const destination = path.join(
447
+ target,
448
+ safeRelative(output.path, `$/restore/${output.name}`),
449
+ );
450
+ fs.mkdirSync(path.dirname(destination), { recursive: true });
451
+ fs.writeFileSync(destination, blob.bytes, { flag: "wx" });
452
+ if (v4StageCapsuleBlobRoot(fs.readFileSync(destination)) !== blob.root)
453
+ fault(
454
+ "stage-capsule-root-mismatch",
455
+ `$/restore/${output.name}`,
456
+ "restored bytes differ",
457
+ );
458
+ }
459
+ const body = {
460
+ schema: V4_PLATFORM_STAGE_RESTORE_CONTRACT,
461
+ platform: request.expectedPlatform,
462
+ stage: request.expectedStage,
463
+ capsuleRoot: request.capsuleRoot,
464
+ manifestRoot: restored.manifest.manifestRoot,
465
+ storeReceiptRoot: restored.receipt.receiptRoot,
466
+ restoredOutputCount: stage.outputs.length,
467
+ exactRootVerified: true,
468
+ providerCredentialsUsed: false,
469
+ };
470
+ return { restored, report: { ...body, reportRoot: rootOf(body) } };
471
+ }