@kungfu-tech/buildchain 4.0.1-alpha.2 → 4.0.1-alpha.21

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 (203) hide show
  1. package/actions/release-tail/README.md +8 -0
  2. package/architecture/ci-lane-change-budget.json +187 -0
  3. package/architecture/decisions/0002-next-development-transition.md +101 -0
  4. package/architecture/decisions/0003-two-phase-delivery-warrant.md +152 -0
  5. package/architecture/internal-capabilities.json +211 -8
  6. package/architecture/maintainability-policy.json +113 -28
  7. package/architecture/release-tail-contract-inventory.json +5 -2
  8. package/architecture/v3-core-mechanism-inventory.json +91 -0
  9. package/architecture/v4-adopter-delivery-parity.json +32 -5
  10. package/architecture/v4-capability-state-machine-manifest.json +73 -0
  11. package/architecture/v4-compatibility-facts-parity.json +77 -0
  12. package/architecture/v4-delivery-authority-parity.json +250 -0
  13. package/architecture/v4-delivery-warrant-shadow-fixtures.json +41 -9
  14. package/architecture/v4-floating-consumer-policy.json +6 -0
  15. package/architecture/v4-next-development-parity.json +192 -0
  16. package/architecture/v4-publication-rehearsal-parity.json +84 -0
  17. package/architecture/v4-release-train-parity.json +1 -0
  18. package/architecture/v4-tail-reseal-parity.json +150 -0
  19. package/bin/buildchain.mjs +32 -3
  20. package/bin/internal/adopter-delivery-cli.mjs +70 -0
  21. package/bin/internal/command-registry.mjs +3 -0
  22. package/bin/internal/compatibility-facts-cli.mjs +101 -0
  23. package/contracts/dev-delivery-authority-v2.schema.json +662 -0
  24. package/contracts/fixtures/next-development-transition-v1/anchored-manual-waiting.json +47 -0
  25. package/contracts/fixtures/next-development-transition-v1/semver-auto-planned.json +47 -0
  26. package/contracts/fixtures/next-development-transition-v1/version-model-cases.json +40 -0
  27. package/contracts/fixtures/v4-adopter-delivery-v1/archive-template.json +19 -0
  28. package/contracts/fixtures/v4-adopter-delivery-v1/bootstrap-positive.json +93 -0
  29. package/contracts/fixtures/v4-adopter-delivery-v1/gate-positive.json +29 -0
  30. package/contracts/fixtures/v4-adopter-delivery-v1/gate-unknown-selector.json +26 -0
  31. package/contracts/fixtures/v4-adopter-delivery-v1/offline-vectors.json +50 -0
  32. package/contracts/fixtures/v4-compatibility-facts-v1/shared.json +1129 -0
  33. package/contracts/fixtures/v4-floating-consumer-policy-v1/cases.json +7 -1
  34. package/contracts/fixtures/v4-publication-rehearsal-v1/candidate/artifacts/product.bin +1 -0
  35. package/contracts/fixtures/v4-publication-rehearsal-v1/candidate/config/buildchain.toml +5 -0
  36. package/contracts/fixtures/v4-publication-rehearsal-v1/candidate/documents/release-activation.json +1 -0
  37. package/contracts/fixtures/v4-publication-rehearsal-v1/candidate/documents/signed-channel.json +1 -0
  38. package/contracts/fixtures/v4-publication-rehearsal-v1/candidate/evidence/qualification.json +1 -0
  39. package/contracts/fixtures/v4-publication-rehearsal-v1/candidate/manifests/candidate.json +5 -0
  40. package/contracts/fixtures/v4-publication-rehearsal-v1/candidate/manifests/release-passport.json +1 -0
  41. package/contracts/fixtures/v4-publication-rehearsal-v1/capsule.json +707 -0
  42. package/contracts/fixtures/v4-publication-rehearsal-v1/offline-vectors.json +27 -0
  43. package/contracts/fixtures/v4-tail-reseal-v1/valid.json +229 -0
  44. package/contracts/next-development-request-v1.schema.json +66 -0
  45. package/contracts/next-development-transition-v1.schema.json +292 -0
  46. package/contracts/v4-adopter-delivery-v1.schema.json +81 -0
  47. package/contracts/v4-compatibility-facts-v1.schema.json +230 -0
  48. package/contracts/v4-floating-consumer-policy-receipt-v1.schema.json +4 -2
  49. package/contracts/v4-publication-rehearsal-capsule-v1.schema.json +233 -0
  50. package/contracts/v4-tail-reseal-v1.schema.json +276 -0
  51. package/dist/site/agent-index.json +5 -0
  52. package/dist/site/artifact-schemas.json +10 -0
  53. package/dist/site/buildchain-contract.json +1475 -27
  54. package/dist/site/buildchain-site.json +627 -31
  55. package/dist/site/capability-registry.json +17 -14
  56. package/dist/site/cli-registry.json +205 -3
  57. package/dist/site/kfd-claims.json +490 -16
  58. package/dist/site/kfd-upstream-aggregate.json +1 -1
  59. package/dist/site/manual-registry.json +52 -6
  60. package/dist/site/node-api-registry.json +14736 -8851
  61. package/dist/site/page-registry.json +593 -21
  62. package/dist/site/public-surface-audit.json +837 -48
  63. package/dist/site/publication-authority-registry.json +44 -8
  64. package/dist/site/publication-registry.json +4 -4
  65. package/dist/site/release-provenance.json +24 -0
  66. package/dist/site/schemas/dev-delivery-authority-v2.schema.json +662 -0
  67. package/dist/site/schemas/release-tail-capabilities-v1.schema.json +199 -0
  68. package/dist/site/schemas/v4-adopter-delivery-v1.schema.json +81 -0
  69. package/dist/site/schemas/v4-compatibility-facts-v1.schema.json +230 -0
  70. package/dist/site/schemas/v4-publication-rehearsal-capsule-v1.schema.json +233 -0
  71. package/dist/site/site-manifest.json +34 -10
  72. package/dist/site/workflow-registry.json +160 -10
  73. package/docs/MAP.md +8 -2
  74. package/docs/cli-reference.md +404 -13
  75. package/docs/cli.md +8 -0
  76. package/docs/dev-alpha-candidate-patrol.md +8 -0
  77. package/docs/dev-delivery-qualification-landing-adr.md +251 -0
  78. package/docs/dev-delivery-warrant.md +351 -38
  79. package/docs/next-development-transition.md +118 -0
  80. package/docs/node-api-reference.md +646 -293
  81. package/docs/release-tail-provider-plane.md +30 -0
  82. package/docs/v4-adopter-delivery.md +133 -0
  83. package/docs/v4-compatibility-facts.md +91 -0
  84. package/docs/v4-publication-rehearsal.md +130 -0
  85. package/docs/v4-tail-reseal.md +73 -0
  86. package/docs/versioning.md +4 -3
  87. package/package.json +34 -6
  88. package/packages/core/adopter-delivery-passport.js +259 -0
  89. package/packages/core/adopter-delivery-vectors.js +158 -0
  90. package/packages/core/adopter-delivery-vectors.json +77 -0
  91. package/packages/core/buildchain-agent-manuals.js +3 -0
  92. package/packages/core/buildchain-compatibility-authority.js +336 -0
  93. package/packages/core/buildchain-compatibility-fact.js +394 -0
  94. package/packages/core/buildchain-compatibility-facts.json +217 -0
  95. package/packages/core/buildchain-compatibility-proof.js +566 -0
  96. package/packages/core/buildchain-config.js +84 -0
  97. package/packages/core/buildchain-contract.js +96 -143
  98. package/packages/core/buildchain-delivery-bootstrap.js +240 -0
  99. package/packages/core/buildchain-delivery-infrastructure.js +164 -0
  100. package/packages/core/buildchain-delivery-self-dogfood.js +395 -0
  101. package/packages/core/buildchain-publication-authority.js +1 -0
  102. package/packages/core/channel-candidate.js +8 -0
  103. package/packages/core/channel-promotion-baseline.js +55 -0
  104. package/packages/core/ci-lane-change-budget.js +247 -0
  105. package/packages/core/dev-alpha-candidate-selection.js +10 -2
  106. package/packages/core/dev-delivery-authority-candidate.js +270 -0
  107. package/packages/core/dev-delivery-authority-evidence.js +146 -0
  108. package/packages/core/dev-delivery-authority-landing.js +461 -0
  109. package/packages/core/dev-delivery-authority-observation.js +48 -0
  110. package/packages/core/dev-delivery-authority-qualification.js +591 -0
  111. package/packages/core/dev-delivery-authority-settlement.js +213 -0
  112. package/packages/core/dev-delivery-authority-state.js +583 -0
  113. package/packages/core/dev-delivery-candidate-identity.js +13 -0
  114. package/packages/core/dev-delivery-contract-surface.js +76 -0
  115. package/packages/core/dev-delivery-execution-failure.js +133 -0
  116. package/packages/core/dev-delivery-execution-transfer.js +592 -0
  117. package/packages/core/dev-delivery-landing-admission-core.js +119 -0
  118. package/packages/core/dev-delivery-landing-readback.js +598 -0
  119. package/packages/core/dev-delivery-landing-terminal-evidence.js +271 -0
  120. package/packages/core/dev-delivery-landing-testing-port.js +6 -0
  121. package/packages/core/dev-delivery-native-execution.js +110 -0
  122. package/packages/core/dev-delivery-native-proof.js +562 -0
  123. package/packages/core/dev-delivery-process-boundary.js +563 -0
  124. package/packages/core/dev-delivery-provider-attempt.js +127 -0
  125. package/packages/core/dev-delivery-provider-heartbeat.js +382 -0
  126. package/packages/core/dev-delivery-warrant-cancellation.js +1 -0
  127. package/packages/core/dev-delivery-warrant-qualification.js +145 -0
  128. package/packages/core/dev-delivery-warrant-settlement.js +237 -36
  129. package/packages/core/dev-delivery-warrant-state.js +587 -0
  130. package/packages/core/dev-delivery-warrant.js +328 -370
  131. package/packages/core/github-governance-authority.js +1 -0
  132. package/packages/core/index.js +5 -0
  133. package/packages/core/kungfu-temporal-fact.js +557 -0
  134. package/packages/core/legacy-kfd-adopter-driver.js +167 -0
  135. package/packages/core/next-development-candidate-reservation.js +186 -0
  136. package/packages/core/next-development-controller.js +728 -0
  137. package/packages/core/next-development-projection.js +287 -0
  138. package/packages/core/next-development-transition.js +738 -0
  139. package/packages/core/paper-agent-entry.js +11 -5
  140. package/packages/core/paper.js +16 -5
  141. package/packages/core/published-delivery-authority.js +266 -0
  142. package/packages/core/release-candidate-recovery.js +70 -15
  143. package/packages/core/release-candidate.js +2 -2
  144. package/packages/core/release-passport.js +36 -9
  145. package/packages/core/v4-adopter-delivery-parity.js +3 -3
  146. package/packages/core/v4-adopter-delivery.js +359 -0
  147. package/packages/core/v4-canonical-contracts.js +5 -0
  148. package/packages/core/v4-delivery-warrant-read-candidate.js +10 -3
  149. package/packages/core/v4-floating-consumer-evidence.js +18 -4
  150. package/packages/core/v4-floating-consumer-policy.js +143 -20
  151. package/packages/core/v4-floating-consumer-release-passport.js +32 -5
  152. package/packages/core/v4-publication-rehearsal-capsule.js +468 -0
  153. package/packages/core/v4-publication-rehearsal-provider-bindings.js +212 -0
  154. package/packages/core/v4-publication-rehearsal.js +481 -0
  155. package/packages/core/v4-tail-reseal-contract.js +26 -0
  156. package/packages/core/v4-tail-reseal-github.js +178 -0
  157. package/packages/core/v4-tail-reseal-receipt.js +225 -0
  158. package/packages/core/v4-tail-reseal.js +594 -0
  159. package/packages/core/workflow-yaml-contract.js +24 -2
  160. package/scripts/buildchain-cli-help.mjs +41 -2
  161. package/scripts/check-ci-lane-change-budget.mjs +100 -0
  162. package/scripts/check-inventory.mjs +14 -3
  163. package/scripts/check-v4-floating-consumer-policy-contract.mjs +23 -4
  164. package/scripts/dev-alpha-candidate-patrol.mjs +22 -1
  165. package/scripts/dev-delivery-authority-command-adapters.mjs +206 -0
  166. package/scripts/dev-delivery-authority-provider.mjs +28 -0
  167. package/scripts/dev-delivery-authority.mjs +490 -0
  168. package/scripts/dev-delivery-native-run.mjs +177 -0
  169. package/scripts/dev-delivery-process-boundary.mjs +260 -0
  170. package/scripts/dev-delivery-proof.mjs +67 -2
  171. package/scripts/dev-delivery-provider-heartbeat.mjs +215 -0
  172. package/scripts/dev-delivery-source-proof-replay.mjs +153 -0
  173. package/scripts/dev-delivery-source-proof-reuse.mjs +13 -97
  174. package/scripts/dev-delivery-two-phase-resume.mjs +345 -0
  175. package/scripts/dev-delivery-two-phase.mjs +573 -0
  176. package/scripts/dev-delivery-warrant-options.mjs +266 -0
  177. package/scripts/dev-delivery-warrant-store.mjs +231 -0
  178. package/scripts/dev-delivery-warrant.mjs +232 -194
  179. package/scripts/dev-pr-auto-merge.mjs +1 -1
  180. package/scripts/dev-pr-delivery-warrant.mjs +11 -0
  181. package/scripts/dev-qualification-patrol.mjs +9 -9
  182. package/scripts/dispatch-artifact-signing-authority.mjs +1 -1
  183. package/scripts/generate-channel-promotion-workflow.mjs +2 -2
  184. package/scripts/generate-next-development-guidance.mjs +49 -0
  185. package/scripts/generate-release-candidate-passport.mjs +152 -0
  186. package/scripts/generate-site-bundle.mjs +69 -4
  187. package/scripts/init-repo.mjs +22 -4
  188. package/scripts/next-development-self-dogfood-harness.mjs +460 -0
  189. package/scripts/next-development-self-dogfood.mjs +597 -0
  190. package/scripts/next-development-transition.mjs +47 -0
  191. package/scripts/npm-publish-transaction.mjs +2 -2
  192. package/scripts/promotion-channel-router.mjs +4 -4
  193. package/scripts/release-candidate-anchor-provenance.mjs +99 -0
  194. package/scripts/release-tail.mjs +51 -3
  195. package/scripts/release-train-self-dogfood.mjs +94 -92
  196. package/scripts/resume-from-candidate-run.mjs +557 -30
  197. package/scripts/site-capability-metadata.mjs +41 -0
  198. package/scripts/stable-candidate-qualification.mjs +9 -10
  199. package/scripts/v4-consumer-policy.mjs +5 -5
  200. package/scripts/v4-publication-rehearsal-fixture.mjs +144 -0
  201. package/scripts/v4-tail-reseal-macos-rehearsal.mjs +134 -0
  202. package/scripts/v4-tail-reseal.mjs +416 -0
  203. package/templates/native-dev-delivery.yml +143 -0
@@ -0,0 +1,562 @@
1
+ import {
2
+ devDeliveryClone as clone,
3
+ devDeliveryContentRoot,
4
+ devDeliveryExactRoot as exactRoot,
5
+ devDeliveryExactSha as exactSha,
6
+ devDeliveryProtectedBase as protectedBase,
7
+ devDeliveryRepository as repository,
8
+ devDeliveryText as text,
9
+ devDeliveryTimestamp as timestamp,
10
+ } from "./dev-delivery-common.js";
11
+ import {
12
+ NATIVE_EXECUTION_BINDING_SCHEMA,
13
+ NATIVE_EXECUTION_RECEIPT_SCHEMA,
14
+ NATIVE_COMMAND_CONTRACT_SCHEMA,
15
+ createNativeCommandContract,
16
+ createNativeExecutionBinding,
17
+ createNativeExecutionReceipt,
18
+ normalizeNativeCommandContract,
19
+ verifyNativeExecutionReceipt,
20
+ } from "./dev-delivery-native-execution.js";
21
+ export {
22
+ NATIVE_EXECUTION_BINDING_SCHEMA,
23
+ NATIVE_EXECUTION_RECEIPT_SCHEMA,
24
+ NATIVE_COMMAND_CONTRACT_SCHEMA,
25
+ createNativeCommandContract,
26
+ createNativeExecutionBinding,
27
+ createNativeExecutionReceipt,
28
+ normalizeNativeCommandContract,
29
+ verifyNativeExecutionReceipt,
30
+ };
31
+ export const NATIVE_QUALIFICATION_PROOF_SCHEMA =
32
+ "kungfu.buildchain.native-qualification-proof/v4";
33
+ const LEGACY_NATIVE_QUALIFICATION_PROOF_V3_SCHEMA =
34
+ "kungfu.buildchain.native-qualification-proof/v3";
35
+ const LEGACY_NATIVE_QUALIFICATION_PROOF_V2_SCHEMA =
36
+ "kungfu.buildchain.native-qualification-proof/v2";
37
+ const LEGACY_NATIVE_QUALIFICATION_PROOF_SCHEMA =
38
+ "kungfu.buildchain.native-qualification-proof/v1";
39
+ export const NATIVE_PROOF_REUSE_DECISION_SCHEMA =
40
+ "kungfu.buildchain.native-proof-reuse-decision/v1";
41
+ export const DEV_DELIVERY_QUALIFICATION_RECEIPT_SCHEMA =
42
+ "kungfu.buildchain.dev-delivery-qualification-receipt/v1";
43
+ export const NATIVE_PROOF_BASE_DELTA_SCHEMA =
44
+ "kungfu.buildchain.native-proof-base-delta/v1";
45
+ const NATIVE_QUALIFICATION_ROOT_SEMANTICS = "semantic-native-identity-v1";
46
+
47
+ function normalizeQualifiedWarrant(warrant, candidate, allowLegacyV3Readback) {
48
+ const qualifiedV3Readback =
49
+ allowLegacyV3Readback &&
50
+ !warrant.nativeCommandContract &&
51
+ !candidate.nativeCommandContract &&
52
+ !warrant.nativeExecutionReceiptRoot &&
53
+ !warrant.qualificationReceiptRoot;
54
+ warrant.nativeProofRoot = exactRoot(
55
+ warrant.nativeProofRoot,
56
+ "Warrant nativeProofRoot",
57
+ );
58
+ warrant.nativeProofReuseRoot = exactRoot(
59
+ warrant.nativeProofReuseRoot,
60
+ "Warrant nativeProofReuseRoot",
61
+ );
62
+ if (!qualifiedV3Readback) {
63
+ warrant.nativeExecutionReceiptRoot = exactRoot(
64
+ warrant.nativeExecutionReceiptRoot,
65
+ "Warrant nativeExecutionReceiptRoot",
66
+ );
67
+ warrant.qualificationReceiptRoot = exactRoot(
68
+ warrant.qualificationReceiptRoot,
69
+ "Warrant qualificationReceiptRoot",
70
+ );
71
+ }
72
+ warrant.qualifiedAt = timestamp(warrant.qualifiedAt, "Warrant qualifiedAt");
73
+ }
74
+
75
+ export function validateActiveDevDeliveryWarrant(
76
+ queue,
77
+ { allowLegacyV3Readback = false } = {},
78
+ ) {
79
+ const warrant = queue.activeWarrant;
80
+ if (warrant.schema !== "kungfu.buildchain.dev-delivery-warrant/v1")
81
+ throw new Error("active Warrant schema is unsupported");
82
+ warrant.candidateId = exactRoot(warrant.candidateId, "Warrant candidateId");
83
+ warrant.fencingToken = exactRoot(
84
+ warrant.fencingToken,
85
+ "Warrant fencingToken",
86
+ );
87
+ warrant.expectedOldStateRoot = exactRoot(
88
+ warrant.expectedOldStateRoot,
89
+ "Warrant expectedOldStateRoot",
90
+ );
91
+ if (
92
+ !Number.isInteger(Number(warrant.generation)) ||
93
+ Number(warrant.generation) < 1
94
+ )
95
+ throw new Error("Warrant generation must be a positive integer");
96
+ warrant.generation = Number(warrant.generation);
97
+ warrant.issuedAt = timestamp(warrant.issuedAt, "Warrant issuedAt");
98
+ warrant.expiresAt = timestamp(warrant.expiresAt, "Warrant expiresAt");
99
+ const historicalPhaseLess = !Object.hasOwn(warrant, "phase");
100
+ const phase = historicalPhaseLess ? "legacy-active" : warrant.phase;
101
+ if (!["legacy-active", "provisional", "qualified"].includes(phase))
102
+ throw new Error("active Warrant phase is unsupported");
103
+ const active = queue.candidates.filter((candidate) =>
104
+ ["selected", "proving", "waiting", "blocked", "qualified"].includes(
105
+ candidate.status,
106
+ ),
107
+ );
108
+ if (active.length !== 1 || active[0].candidateId !== warrant.candidateId)
109
+ throw new Error(
110
+ "exactly one active candidate must match the active Warrant",
111
+ );
112
+ if (warrant.phase === "qualified") {
113
+ normalizeQualifiedWarrant(warrant, active[0], allowLegacyV3Readback);
114
+ } else if (
115
+ warrant.phase === "provisional" &&
116
+ (warrant.nativeProofRoot ||
117
+ warrant.nativeProofReuseRoot ||
118
+ warrant.nativeExecutionReceiptRoot ||
119
+ warrant.qualificationReceiptRoot ||
120
+ warrant.qualifiedAt)
121
+ ) {
122
+ throw new Error(
123
+ "provisional Warrant cannot carry qualified native evidence",
124
+ );
125
+ }
126
+ if (
127
+ historicalPhaseLess &&
128
+ (active[0].environmentRoot ||
129
+ warrant.nativeProofRoot ||
130
+ warrant.nativeProofReuseRoot ||
131
+ warrant.qualifiedAt)
132
+ ) {
133
+ throw new Error(
134
+ "phase-less active Warrant must use the historical non-native contract",
135
+ );
136
+ }
137
+ if (phase === "provisional" && active[0].status === "qualified")
138
+ throw new Error("provisional Warrant cannot bind a qualified candidate");
139
+ if (warrant.phase === "qualified" && active[0].status !== "qualified")
140
+ throw new Error("qualified Warrant must bind a qualified candidate");
141
+ if (
142
+ warrant.releaseBlockerPriority?.claimRoot !==
143
+ active[0].releaseBlockerPriority?.claimRoot
144
+ )
145
+ throw new Error("active Warrant release-blocker priority drift");
146
+ if (
147
+ warrant.nativeCommandContract?.commandRoot !==
148
+ active[0].nativeCommandContract?.commandRoot
149
+ )
150
+ throw new Error("active Warrant native command contract drift");
151
+ if (
152
+ JSON.stringify(warrant.shardEvidenceRoots || []) !==
153
+ JSON.stringify(active[0].shardEvidenceRoots || [])
154
+ )
155
+ throw new Error("active Warrant shard evidence roots drift");
156
+ }
157
+ export function createDevDeliveryWarrantToken(input) {
158
+ return devDeliveryContentRoot({
159
+ schema: "kungfu.buildchain.dev-delivery-warrant/v1",
160
+ repository: input.repository,
161
+ protectedBase: input.protectedBase,
162
+ candidateId: input.candidateId,
163
+ phase: input.phase,
164
+ generation: input.generation,
165
+ expectedOldStateRoot: input.expectedOldStateRoot,
166
+ issuedAt: input.issuedAt,
167
+ });
168
+ }
169
+ function exactRoots(values, label) {
170
+ if (!Array.isArray(values) || values.length === 0) {
171
+ throw new Error(`${label} must contain at least one content root`);
172
+ }
173
+ return [...new Set(values.map((value) => exactRoot(value, label)))].sort();
174
+ }
175
+ function normalizedPaths(values) {
176
+ if (!Array.isArray(values)) throw new Error("paths must be a JSON array");
177
+ return [
178
+ ...new Set(
179
+ values
180
+ .map(text)
181
+ .map((entry) => entry.replace(/^\.\//u, "").replace(/\/+$/u, ""))
182
+ .filter(Boolean),
183
+ ),
184
+ ].sort();
185
+ }
186
+ function normalizedRenames(values) {
187
+ if (!Array.isArray(values)) throw new Error("renames must be a JSON array");
188
+ return values
189
+ .map((entry) => ({
190
+ from: normalizedPaths([entry?.from])[0] || "",
191
+ to: normalizedPaths([entry?.to])[0] || "",
192
+ }))
193
+ .filter((entry) => entry.from && entry.to)
194
+ .sort(
195
+ (left, right) =>
196
+ left.from.localeCompare(right.from) || left.to.localeCompare(right.to),
197
+ );
198
+ }
199
+ export function createNativeProofBaseDelta(input = {}) {
200
+ const body = {
201
+ schema: NATIVE_PROOF_BASE_DELTA_SCHEMA,
202
+ repository: repository(input.repository),
203
+ protectedBase: protectedBase(input.protectedBase),
204
+ qualifiedBase: exactSha(input.qualifiedBase, "qualifiedBase"),
205
+ currentBase: exactSha(input.currentBase, "currentBase"),
206
+ graphKnown: input.graphKnown === true,
207
+ attributionComplete: input.attributionComplete === true,
208
+ changedPaths: normalizedPaths(input.changedPaths || []),
209
+ renames: normalizedRenames(input.renames || []),
210
+ };
211
+ return { ...body, deltaRoot: devDeliveryContentRoot(body) };
212
+ }
213
+ function proofIdentity(body) {
214
+ const identity = clone(body);
215
+ delete identity.qualifiedAt;
216
+ delete identity.observationRoot;
217
+ return identity;
218
+ }
219
+ function proofObservation(body) {
220
+ return { qualifiedAt: body.qualifiedAt };
221
+ }
222
+ function rooted(body) {
223
+ return { ...body, decisionRoot: devDeliveryContentRoot(body) };
224
+ }
225
+ export function createNativeQualificationProof(input = {}) {
226
+ const sourceHead = exactSha(input.sourceHead, "sourceHead");
227
+ const qualifiedBase = exactSha(input.qualifiedBase, "qualifiedBase");
228
+ const toolchainRoot = exactRoot(input.toolchainRoot, "toolchainRoot");
229
+ const environmentRoot = exactRoot(input.environmentRoot, "environmentRoot");
230
+ const nativeCommandRoot = exactRoot(
231
+ input.nativeCommandRoot,
232
+ "nativeCommandRoot",
233
+ );
234
+ const executionReceipt = verifyNativeExecutionReceipt(
235
+ input.nativeExecutionReceipt,
236
+ {
237
+ repository: repository(input.repository),
238
+ protectedBase: protectedBase(input.protectedBase),
239
+ sourceHead,
240
+ qualifiedBase,
241
+ nativeCommandRoot,
242
+ toolchainRoot,
243
+ environmentRoot,
244
+ },
245
+ );
246
+ if (!executionReceipt.ok) {
247
+ throw new Error(
248
+ `native execution receipt rejected: ${executionReceipt.reason}`,
249
+ );
250
+ }
251
+ const body = {
252
+ schema: NATIVE_QUALIFICATION_PROOF_SCHEMA,
253
+ rootSemantics: NATIVE_QUALIFICATION_ROOT_SEMANTICS,
254
+ repository: repository(input.repository),
255
+ protectedBase: protectedBase(input.protectedBase),
256
+ sourceIdentityRoot: exactRoot(
257
+ input.sourceIdentityRoot,
258
+ "sourceIdentityRoot",
259
+ ),
260
+ sourcePatchRoot: exactRoot(input.sourcePatchRoot, "sourcePatchRoot"),
261
+ planRoot: exactRoot(input.planRoot, "planRoot"),
262
+ closureRoot: exactRoot(input.closureRoot, "closureRoot"),
263
+ dependencyRoot: exactRoot(input.dependencyRoot, "dependencyRoot"),
264
+ toolchainRoot,
265
+ environmentRoot,
266
+ sourceHead,
267
+ qualifiedBase,
268
+ nativeCommandRoot,
269
+ nativeExecutionBindingRoot: executionReceipt.executionBindingRoot,
270
+ nativeExecutionReceiptRoot: executionReceipt.receiptRoot,
271
+ nativeExecutionReceipt: executionReceipt.receipt,
272
+ affectedPaths: normalizedPaths(input.affectedPaths || []),
273
+ shardEvidenceRoots: exactRoots(
274
+ [...(input.shardEvidenceRoots || []), executionReceipt.receiptRoot],
275
+ "shardEvidenceRoots",
276
+ ),
277
+ qualifiedAt: timestamp(input.qualifiedAt, "qualifiedAt"),
278
+ };
279
+ body.observationRoot = devDeliveryContentRoot(proofObservation(body));
280
+ return {
281
+ ...body,
282
+ proofRoot: devDeliveryContentRoot(proofIdentity(body)),
283
+ };
284
+ }
285
+ export function verifyNativeQualificationProof(proofInput, expected = {}) {
286
+ try {
287
+ const proof = clone(proofInput || {});
288
+ if (
289
+ ![
290
+ NATIVE_QUALIFICATION_PROOF_SCHEMA,
291
+ LEGACY_NATIVE_QUALIFICATION_PROOF_V3_SCHEMA,
292
+ LEGACY_NATIVE_QUALIFICATION_PROOF_V2_SCHEMA,
293
+ LEGACY_NATIVE_QUALIFICATION_PROOF_SCHEMA,
294
+ ].includes(proof.schema)
295
+ ) {
296
+ return { ok: false, reason: "unsupported-schema" };
297
+ }
298
+ const proofRoot = proof.proofRoot;
299
+ delete proof.proofRoot;
300
+ if (proof.rootSemantics !== NATIVE_QUALIFICATION_ROOT_SEMANTICS) {
301
+ return { ok: false, reason: "unsupported-root-semantics" };
302
+ }
303
+ if (devDeliveryContentRoot(proofIdentity(proof)) !== proofRoot) {
304
+ return { ok: false, reason: "proof-root-drift" };
305
+ }
306
+ if (
307
+ devDeliveryContentRoot(proofObservation(proof)) !== proof.observationRoot
308
+ ) {
309
+ return { ok: false, reason: "observation-root-drift" };
310
+ }
311
+ for (const [field, value] of Object.entries(expected)) {
312
+ if (value !== undefined && proof[field] !== value) {
313
+ return { ok: false, reason: `${field}-mismatch` };
314
+ }
315
+ }
316
+ if (proof.schema === NATIVE_QUALIFICATION_PROOF_SCHEMA) {
317
+ repository(proof.repository);
318
+ protectedBase(proof.protectedBase);
319
+ exactSha(proof.sourceHead, "sourceHead");
320
+ exactSha(proof.qualifiedBase, "qualifiedBase");
321
+ for (const field of [
322
+ "sourceIdentityRoot",
323
+ "sourcePatchRoot",
324
+ "planRoot",
325
+ "closureRoot",
326
+ "dependencyRoot",
327
+ "toolchainRoot",
328
+ "environmentRoot",
329
+ "nativeCommandRoot",
330
+ "nativeExecutionBindingRoot",
331
+ "nativeExecutionReceiptRoot",
332
+ ]) {
333
+ exactRoot(proof[field], field);
334
+ }
335
+ const expectedBindingRoot = devDeliveryContentRoot(
336
+ createNativeExecutionBinding(proof),
337
+ );
338
+ if (proof.nativeExecutionBindingRoot !== expectedBindingRoot) {
339
+ return { ok: false, reason: "native-execution-binding-root-drift" };
340
+ }
341
+ const shardEvidenceRoots = exactRoots(
342
+ proof.shardEvidenceRoots,
343
+ "shardEvidenceRoots",
344
+ );
345
+ if (!shardEvidenceRoots.includes(proof.nativeExecutionReceiptRoot)) {
346
+ return { ok: false, reason: "native-execution-receipt-unbound" };
347
+ }
348
+ if (!proof.nativeExecutionReceipt) {
349
+ return {
350
+ ok: false,
351
+ reason: "native-execution-receipt-bytes-missing",
352
+ };
353
+ }
354
+ const executionReceipt = verifyNativeExecutionReceipt(
355
+ proof.nativeExecutionReceipt,
356
+ {
357
+ repository: proof.repository,
358
+ protectedBase: proof.protectedBase,
359
+ sourceHead: proof.sourceHead,
360
+ qualifiedBase: proof.qualifiedBase,
361
+ nativeCommandRoot: proof.nativeCommandRoot,
362
+ toolchainRoot: proof.toolchainRoot,
363
+ environmentRoot: proof.environmentRoot,
364
+ },
365
+ );
366
+ if (!executionReceipt.ok) {
367
+ return {
368
+ ok: false,
369
+ reason: `native-execution-${executionReceipt.reason}`,
370
+ };
371
+ }
372
+ if (
373
+ executionReceipt.receiptRoot !== proof.nativeExecutionReceiptRoot ||
374
+ executionReceipt.executionBindingRoot !==
375
+ proof.nativeExecutionBindingRoot
376
+ ) {
377
+ return { ok: false, reason: "native-execution-receipt-root-drift" };
378
+ }
379
+ if (
380
+ Date.parse(proof.qualifiedAt) <
381
+ Date.parse(executionReceipt.receipt.completedAt)
382
+ ) {
383
+ return {
384
+ ok: false,
385
+ reason: "native-execution-qualified-before-completion",
386
+ };
387
+ }
388
+ normalizedPaths(proof.affectedPaths || []);
389
+ timestamp(proof.qualifiedAt, "qualifiedAt");
390
+ } else {
391
+ repository(proof.repository);
392
+ protectedBase(proof.protectedBase);
393
+ exactSha(proof.qualifiedBase, "qualifiedBase");
394
+ for (const field of [
395
+ "sourceIdentityRoot",
396
+ "sourcePatchRoot",
397
+ "planRoot",
398
+ "closureRoot",
399
+ "dependencyRoot",
400
+ "toolchainRoot",
401
+ ]) {
402
+ exactRoot(proof[field], field);
403
+ }
404
+ normalizedPaths(proof.affectedPaths || []);
405
+ exactRoots(proof.shardEvidenceRoots, "shardEvidenceRoots");
406
+ timestamp(proof.qualifiedAt, "qualifiedAt");
407
+ }
408
+ return { ok: true, reason: "exact-native-proof", proofRoot };
409
+ } catch (error) {
410
+ return { ok: false, reason: "invalid-proof", error: error.message };
411
+ }
412
+ }
413
+ function pathsOverlap(changedPath, affectedPath) {
414
+ if (affectedPath === "*" || affectedPath === "**") return true;
415
+ return (
416
+ changedPath === affectedPath ||
417
+ changedPath.startsWith(`${affectedPath}/`) ||
418
+ affectedPath.startsWith(`${changedPath}/`)
419
+ );
420
+ }
421
+ function nativeReuseBody(proof, current) {
422
+ const verification = verifyNativeQualificationProof(proof);
423
+ const currentBase = current.currentBase
424
+ ? exactSha(current.currentBase, "currentBase")
425
+ : null;
426
+ const changedPaths = normalizedPaths(current.changedPaths || []);
427
+ const base = {
428
+ schema: NATIVE_PROOF_REUSE_DECISION_SCHEMA,
429
+ proofRoot: verification.ok ? proof.proofRoot : null,
430
+ repository: verification.ok ? proof.repository : null,
431
+ protectedBase: verification.ok ? proof.protectedBase : null,
432
+ qualifiedBase: verification.ok ? proof.qualifiedBase : null,
433
+ currentBase,
434
+ graphKnown: current.graphKnown === true,
435
+ attributionComplete: current.attributionComplete === true,
436
+ changedPaths,
437
+ renames: normalizedRenames(current.renames || []),
438
+ baseDeltaRoot: null,
439
+ overlappingPaths: [],
440
+ reusable: false,
441
+ action: "rerun-full-native-qualification",
442
+ reason: verification.reason,
443
+ requiredValidation: "full-native",
444
+ };
445
+ if (!verification.ok) return base;
446
+ if (proof.schema !== NATIVE_QUALIFICATION_PROOF_SCHEMA) {
447
+ return {
448
+ ...base,
449
+ reason: "native-execution-evidence-unbound",
450
+ };
451
+ }
452
+ const semanticFields = [
453
+ "sourceHead",
454
+ "sourceIdentityRoot",
455
+ "sourcePatchRoot",
456
+ "planRoot",
457
+ "closureRoot",
458
+ "dependencyRoot",
459
+ "toolchainRoot",
460
+ "environmentRoot",
461
+ "nativeCommandRoot",
462
+ ];
463
+ for (const field of semanticFields) {
464
+ if (!current[field] || current[field] !== proof[field]) {
465
+ return {
466
+ ...base,
467
+ reason: `${field}-changed-or-unknown`,
468
+ };
469
+ }
470
+ }
471
+ if (!currentBase) {
472
+ return { ...base, reason: "current-base-unknown" };
473
+ }
474
+ const delta = createNativeProofBaseDelta({
475
+ repository: proof.repository,
476
+ protectedBase: proof.protectedBase,
477
+ qualifiedBase: proof.qualifiedBase,
478
+ currentBase,
479
+ graphKnown: current.graphKnown,
480
+ attributionComplete: current.attributionComplete,
481
+ changedPaths,
482
+ renames: current.renames || [],
483
+ });
484
+ base.baseDeltaRoot = delta.deltaRoot;
485
+ base.renames = delta.renames;
486
+ if (currentBase === proof.qualifiedBase) {
487
+ return {
488
+ ...base,
489
+ reusable: true,
490
+ action: "accept-fresh-native-proof",
491
+ reason: "exact-qualified-base",
492
+ requiredValidation: "exact-merge-group",
493
+ };
494
+ }
495
+ if (
496
+ current.graphKnown !== true ||
497
+ current.attributionComplete !== true ||
498
+ !Array.isArray(current.changedPaths) ||
499
+ !Array.isArray(current.renames)
500
+ ) {
501
+ return { ...base, reason: "base-delta-attribution-unknown" };
502
+ }
503
+ if (proof.affectedPaths.length === 0) {
504
+ return { ...base, reason: "affected-closure-paths-unknown" };
505
+ }
506
+ const attributedPaths = [
507
+ ...changedPaths,
508
+ ...base.renames.flatMap((rename) => [rename.from, rename.to]),
509
+ ];
510
+ const overlap = [...new Set(attributedPaths)].filter((changedPath) =>
511
+ proof.affectedPaths.some((affectedPath) =>
512
+ pathsOverlap(changedPath, affectedPath),
513
+ ),
514
+ );
515
+ if (overlap.length > 0) {
516
+ return {
517
+ ...base,
518
+ action: "rerun-affected-native-shards",
519
+ reason: "base-delta-overlaps-affected-closure",
520
+ requiredValidation: "incremental-or-full-native",
521
+ overlappingPaths: overlap,
522
+ };
523
+ }
524
+ return {
525
+ ...base,
526
+ reusable: true,
527
+ action: "reuse-native-proof",
528
+ reason: "semantic-source-stable-and-base-delta-disjoint",
529
+ requiredValidation: "exact-merge-group",
530
+ };
531
+ }
532
+ export function createNativeProofReuseDecision({ proof, current = {} } = {}) {
533
+ return rooted(nativeReuseBody(proof, current));
534
+ }
535
+ export function verifyNativeProofReuseDecision(
536
+ decisionInput,
537
+ { proof, current = {} } = {},
538
+ ) {
539
+ try {
540
+ const decision = clone(decisionInput || {});
541
+ if (decision.schema !== NATIVE_PROOF_REUSE_DECISION_SCHEMA) {
542
+ return { ok: false, reason: "unsupported-schema" };
543
+ }
544
+ const decisionRoot = decision.decisionRoot;
545
+ delete decision.decisionRoot;
546
+ if (devDeliveryContentRoot(decision) !== decisionRoot) {
547
+ return { ok: false, reason: "decision-root-drift" };
548
+ }
549
+ const recomputed = nativeReuseBody(proof, current);
550
+ if (JSON.stringify(decision) !== JSON.stringify(recomputed)) {
551
+ return { ok: false, reason: "decision-input-drift" };
552
+ }
553
+ return {
554
+ ok: decision.reusable === true,
555
+ reason: decision.reason,
556
+ decisionRoot,
557
+ action: decision.action,
558
+ };
559
+ } catch (error) {
560
+ return { ok: false, reason: "invalid-decision", error: error.message };
561
+ }
562
+ }