@kungfu-tech/buildchain 4.0.0 → 4.0.1-alpha.10

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 (228) hide show
  1. package/AGENTS.md +13 -5
  2. package/actions/promote-buildchain-ref/README.md +11 -6
  3. package/actions/release-tail/README.md +8 -0
  4. package/architecture/ci-lane-change-budget.json +187 -0
  5. package/architecture/decisions/0002-next-development-transition.md +101 -0
  6. package/architecture/decisions/0003-two-phase-delivery-warrant.md +152 -0
  7. package/architecture/internal-capabilities.json +219 -7
  8. package/architecture/maintainability-policy.json +246 -29
  9. package/architecture/release-tail-contract-inventory.json +5 -2
  10. package/architecture/v3-core-mechanism-inventory.json +91 -0
  11. package/architecture/v4-adopter-delivery-parity.json +32 -5
  12. package/architecture/v4-capability-state-machine-manifest.json +73 -0
  13. package/architecture/v4-compatibility-facts-parity.json +77 -0
  14. package/architecture/v4-delivery-authority-parity.json +250 -0
  15. package/architecture/v4-delivery-warrant-shadow-fixtures.json +41 -9
  16. package/architecture/v4-floating-consumer-policy.json +81 -0
  17. package/architecture/v4-floating-consumer-policy.md +32 -0
  18. package/architecture/v4-next-development-parity.json +192 -0
  19. package/architecture/v4-publication-rehearsal-parity.json +84 -0
  20. package/architecture/v4-release-train-parity.json +1 -0
  21. package/architecture/v4-runtime-ref-resume-authority.json +64 -0
  22. package/architecture/v4-stage-capsule-qualification.json +2 -2
  23. package/architecture/v4-tail-reseal-parity.json +150 -0
  24. package/bin/buildchain.mjs +32 -3
  25. package/bin/internal/adopter-delivery-cli.mjs +70 -0
  26. package/bin/internal/command-registry.mjs +3 -0
  27. package/bin/internal/compatibility-facts-cli.mjs +101 -0
  28. package/bin/internal/trust-release-release-handlers.mjs +5 -0
  29. package/contracts/dev-delivery-authority-v2.schema.json +662 -0
  30. package/contracts/fixtures/next-development-transition-v1/anchored-manual-waiting.json +47 -0
  31. package/contracts/fixtures/next-development-transition-v1/semver-auto-planned.json +47 -0
  32. package/contracts/fixtures/next-development-transition-v1/version-model-cases.json +40 -0
  33. package/contracts/fixtures/v4-adopter-delivery-v1/archive-template.json +19 -0
  34. package/contracts/fixtures/v4-adopter-delivery-v1/bootstrap-positive.json +93 -0
  35. package/contracts/fixtures/v4-adopter-delivery-v1/gate-positive.json +29 -0
  36. package/contracts/fixtures/v4-adopter-delivery-v1/gate-unknown-selector.json +26 -0
  37. package/contracts/fixtures/v4-adopter-delivery-v1/offline-vectors.json +50 -0
  38. package/contracts/fixtures/v4-compatibility-facts-v1/shared.json +1129 -0
  39. package/contracts/fixtures/v4-floating-consumer-policy-v1/cases.json +59 -0
  40. package/contracts/fixtures/v4-publication-rehearsal-v1/candidate/artifacts/product.bin +1 -0
  41. package/contracts/fixtures/v4-publication-rehearsal-v1/candidate/config/buildchain.toml +5 -0
  42. package/contracts/fixtures/v4-publication-rehearsal-v1/candidate/documents/release-activation.json +1 -0
  43. package/contracts/fixtures/v4-publication-rehearsal-v1/candidate/documents/signed-channel.json +1 -0
  44. package/contracts/fixtures/v4-publication-rehearsal-v1/candidate/evidence/qualification.json +1 -0
  45. package/contracts/fixtures/v4-publication-rehearsal-v1/candidate/manifests/candidate.json +5 -0
  46. package/contracts/fixtures/v4-publication-rehearsal-v1/candidate/manifests/release-passport.json +1 -0
  47. package/contracts/fixtures/v4-publication-rehearsal-v1/capsule.json +707 -0
  48. package/contracts/fixtures/v4-publication-rehearsal-v1/offline-vectors.json +27 -0
  49. package/contracts/fixtures/v4-runtime-ref-resume-authority-v1/scenario.json +15 -0
  50. package/contracts/fixtures/v4-tail-reseal-v1/valid.json +229 -0
  51. package/contracts/next-development-request-v1.schema.json +66 -0
  52. package/contracts/next-development-transition-v1.schema.json +292 -0
  53. package/contracts/v4-adopter-delivery-v1.schema.json +81 -0
  54. package/contracts/v4-compatibility-facts-v1.schema.json +230 -0
  55. package/contracts/v4-floating-consumer-policy-receipt-v1.schema.json +107 -0
  56. package/contracts/v4-publication-rehearsal-capsule-v1.schema.json +233 -0
  57. package/contracts/v4-runtime-ref-resume-authority-v1.schema.json +235 -0
  58. package/contracts/v4-tail-reseal-v1.schema.json +276 -0
  59. package/dist/site/agent-index.json +5 -0
  60. package/dist/site/artifact-schemas.json +10 -0
  61. package/dist/site/buildchain-contract.json +1562 -44
  62. package/dist/site/buildchain-site.json +684 -42
  63. package/dist/site/capability-registry.json +17 -14
  64. package/dist/site/cli-registry.json +205 -3
  65. package/dist/site/controller-registry.json +62 -6
  66. package/dist/site/kfd-claims.json +551 -22
  67. package/dist/site/kfd-upstream-aggregate.json +1 -1
  68. package/dist/site/manual-registry.json +55 -9
  69. package/dist/site/node-api-registry.json +15247 -8690
  70. package/dist/site/page-registry.json +647 -29
  71. package/dist/site/public-surface-audit.json +876 -55
  72. package/dist/site/publication-authority-registry.json +44 -8
  73. package/dist/site/publication-registry.json +4 -4
  74. package/dist/site/release-provenance.json +26 -0
  75. package/dist/site/schemas/dev-delivery-authority-v2.schema.json +662 -0
  76. package/dist/site/schemas/release-tail-capabilities-v1.schema.json +199 -0
  77. package/dist/site/schemas/v4-adopter-delivery-v1.schema.json +81 -0
  78. package/dist/site/schemas/v4-compatibility-facts-v1.schema.json +230 -0
  79. package/dist/site/schemas/v4-publication-rehearsal-capsule-v1.schema.json +233 -0
  80. package/dist/site/site-manifest.json +37 -13
  81. package/dist/site/workflow-registry.json +200 -22
  82. package/docs/MAP.md +10 -2
  83. package/docs/cli-reference.md +404 -13
  84. package/docs/cli.md +8 -0
  85. package/docs/dev-alpha-candidate-patrol.md +8 -0
  86. package/docs/dev-delivery-qualification-landing-adr.md +251 -0
  87. package/docs/dev-delivery-warrant.md +361 -30
  88. package/docs/lifecycle-protocol.md +41 -0
  89. package/docs/next-development-transition.md +118 -0
  90. package/docs/node-api-reference.md +748 -322
  91. package/docs/release-tail-provider-plane.md +30 -0
  92. package/docs/reusable-build-surface.md +41 -0
  93. package/docs/runtime-train-validation.md +10 -0
  94. package/docs/v4-adopter-delivery.md +133 -0
  95. package/docs/v4-compatibility-facts.md +91 -0
  96. package/docs/v4-publication-rehearsal.md +130 -0
  97. package/docs/v4-runtime-ref-resume-authority.md +69 -0
  98. package/docs/v4-tail-reseal.md +73 -0
  99. package/docs/versioning.md +4 -2
  100. package/package.json +36 -6
  101. package/packages/core/adopter-delivery-passport.js +259 -0
  102. package/packages/core/adopter-delivery-vectors.js +158 -0
  103. package/packages/core/adopter-delivery-vectors.json +77 -0
  104. package/packages/core/artifact-signing.js +61 -0
  105. package/packages/core/buildchain-agent-manuals.js +3 -0
  106. package/packages/core/buildchain-compatibility-authority.js +336 -0
  107. package/packages/core/buildchain-compatibility-fact.js +394 -0
  108. package/packages/core/buildchain-compatibility-facts.json +217 -0
  109. package/packages/core/buildchain-compatibility-proof.js +566 -0
  110. package/packages/core/buildchain-config.js +150 -1
  111. package/packages/core/buildchain-contract.js +96 -143
  112. package/packages/core/buildchain-delivery-bootstrap.js +240 -0
  113. package/packages/core/buildchain-delivery-infrastructure.js +164 -0
  114. package/packages/core/buildchain-delivery-self-dogfood.js +395 -0
  115. package/packages/core/buildchain-publication-authority.js +1 -0
  116. package/packages/core/channel-candidate.js +8 -0
  117. package/packages/core/channel-promotion-baseline.js +55 -0
  118. package/packages/core/ci-lane-change-budget.js +247 -0
  119. package/packages/core/dev-alpha-candidate-selection.js +10 -2
  120. package/packages/core/dev-delivery-authority-candidate.js +270 -0
  121. package/packages/core/dev-delivery-authority-evidence.js +146 -0
  122. package/packages/core/dev-delivery-authority-landing.js +461 -0
  123. package/packages/core/dev-delivery-authority-observation.js +48 -0
  124. package/packages/core/dev-delivery-authority-qualification.js +591 -0
  125. package/packages/core/dev-delivery-authority-settlement.js +213 -0
  126. package/packages/core/dev-delivery-authority-state.js +583 -0
  127. package/packages/core/dev-delivery-candidate-identity.js +13 -0
  128. package/packages/core/dev-delivery-contract-surface.js +76 -0
  129. package/packages/core/dev-delivery-execution-failure.js +133 -0
  130. package/packages/core/dev-delivery-execution-transfer.js +592 -0
  131. package/packages/core/dev-delivery-landing-admission-core.js +119 -0
  132. package/packages/core/dev-delivery-landing-readback.js +598 -0
  133. package/packages/core/dev-delivery-landing-terminal-evidence.js +271 -0
  134. package/packages/core/dev-delivery-landing-testing-port.js +6 -0
  135. package/packages/core/dev-delivery-native-execution.js +110 -0
  136. package/packages/core/dev-delivery-native-proof.js +562 -0
  137. package/packages/core/dev-delivery-process-boundary.js +563 -0
  138. package/packages/core/dev-delivery-proof.js +37 -3
  139. package/packages/core/dev-delivery-provider-attempt.js +127 -0
  140. package/packages/core/dev-delivery-provider-heartbeat.js +382 -0
  141. package/packages/core/dev-delivery-warrant-cancellation.js +1 -0
  142. package/packages/core/dev-delivery-warrant-qualification.js +145 -0
  143. package/packages/core/dev-delivery-warrant-settlement.js +237 -36
  144. package/packages/core/dev-delivery-warrant-state.js +587 -0
  145. package/packages/core/dev-delivery-warrant.js +328 -370
  146. package/packages/core/github-governance-authority.js +1 -0
  147. package/packages/core/index.js +7 -0
  148. package/packages/core/kungfu-temporal-fact.js +557 -0
  149. package/packages/core/legacy-kfd-adopter-driver.js +167 -0
  150. package/packages/core/next-development-candidate-reservation.js +186 -0
  151. package/packages/core/next-development-controller.js +728 -0
  152. package/packages/core/next-development-projection.js +287 -0
  153. package/packages/core/next-development-transition.js +738 -0
  154. package/packages/core/paper-agent-entry.js +11 -5
  155. package/packages/core/paper.js +16 -5
  156. package/packages/core/publication-authority.js +5 -5
  157. package/packages/core/published-delivery-authority.js +266 -0
  158. package/packages/core/release-candidate-recovery.js +66 -11
  159. package/packages/core/release-candidate.js +79 -19
  160. package/packages/core/release-passport.js +271 -38
  161. package/packages/core/v4-adopter-delivery-parity.js +3 -3
  162. package/packages/core/v4-adopter-delivery.js +359 -0
  163. package/packages/core/v4-canonical-contracts.js +5 -0
  164. package/packages/core/v4-delivery-warrant-read-candidate.js +10 -3
  165. package/packages/core/v4-floating-consumer-evidence.js +338 -0
  166. package/packages/core/v4-floating-consumer-policy.js +569 -0
  167. package/packages/core/v4-floating-consumer-release-passport.js +153 -0
  168. package/packages/core/v4-publication-rehearsal-capsule.js +468 -0
  169. package/packages/core/v4-publication-rehearsal-provider-bindings.js +212 -0
  170. package/packages/core/v4-publication-rehearsal.js +481 -0
  171. package/packages/core/v4-runtime-ref-resume-authority.js +625 -0
  172. package/packages/core/v4-runtime-selector-persistence.js +228 -0
  173. package/packages/core/v4-tail-reseal-contract.js +26 -0
  174. package/packages/core/v4-tail-reseal-github.js +178 -0
  175. package/packages/core/v4-tail-reseal-receipt.js +225 -0
  176. package/packages/core/v4-tail-reseal.js +594 -0
  177. package/packages/core/workflow-yaml-contract.js +72 -2
  178. package/scripts/audit-publication-control-plane.mjs +31 -31
  179. package/scripts/buildchain-cli-help.mjs +41 -2
  180. package/scripts/check-ci-lane-change-budget.mjs +100 -0
  181. package/scripts/check-inventory.mjs +14 -3
  182. package/scripts/check-v4-floating-consumer-policy-contract.mjs +217 -0
  183. package/scripts/check-v4-public-dogfood-contract.mjs +6 -11
  184. package/scripts/dev-alpha-candidate-patrol.mjs +22 -1
  185. package/scripts/dev-delivery-authority-command-adapters.mjs +206 -0
  186. package/scripts/dev-delivery-authority-provider.mjs +28 -0
  187. package/scripts/dev-delivery-authority.mjs +490 -0
  188. package/scripts/dev-delivery-native-run.mjs +177 -0
  189. package/scripts/dev-delivery-process-boundary.mjs +260 -0
  190. package/scripts/dev-delivery-proof.mjs +67 -2
  191. package/scripts/dev-delivery-provider-heartbeat.mjs +215 -0
  192. package/scripts/dev-delivery-source-proof-replay.mjs +153 -0
  193. package/scripts/dev-delivery-source-proof-reuse.mjs +547 -0
  194. package/scripts/dev-delivery-two-phase-resume.mjs +345 -0
  195. package/scripts/dev-delivery-two-phase.mjs +573 -0
  196. package/scripts/dev-delivery-warrant-options.mjs +266 -0
  197. package/scripts/dev-delivery-warrant-store.mjs +231 -0
  198. package/scripts/dev-delivery-warrant.mjs +232 -194
  199. package/scripts/dev-pr-auto-merge.mjs +37 -48
  200. package/scripts/dev-pr-delivery-warrant.mjs +216 -2
  201. package/scripts/dev-pr-prequeue-guard.mjs +399 -0
  202. package/scripts/dev-qualification-patrol.mjs +9 -9
  203. package/scripts/dispatch-artifact-signing-authority.mjs +1 -1
  204. package/scripts/ensure-github-release.mjs +3 -3
  205. package/scripts/generate-channel-build-workflow.mjs +3 -0
  206. package/scripts/generate-channel-promotion-workflow.mjs +114 -14
  207. package/scripts/generate-next-development-guidance.mjs +49 -0
  208. package/scripts/generate-release-candidate-passport.mjs +192 -32
  209. package/scripts/generate-site-bundle.mjs +69 -4
  210. package/scripts/init-repo.mjs +26 -4
  211. package/scripts/inspect-artifact-signing-requests.mjs +6 -0
  212. package/scripts/next-development-self-dogfood-harness.mjs +460 -0
  213. package/scripts/next-development-self-dogfood.mjs +597 -0
  214. package/scripts/next-development-transition.mjs +47 -0
  215. package/scripts/npm-publish-transaction.mjs +103 -91
  216. package/scripts/promotion-channel-router.mjs +4 -4
  217. package/scripts/release-candidate-anchor-provenance.mjs +99 -0
  218. package/scripts/release-tail.mjs +51 -3
  219. package/scripts/release-train-self-dogfood.mjs +94 -92
  220. package/scripts/resume-from-candidate-run.mjs +565 -41
  221. package/scripts/seal-artifact-signing-requests.mjs +6 -0
  222. package/scripts/site-capability-metadata.mjs +43 -0
  223. package/scripts/stable-candidate-qualification.mjs +9 -10
  224. package/scripts/v4-consumer-policy.mjs +231 -0
  225. package/scripts/v4-publication-rehearsal-fixture.mjs +144 -0
  226. package/scripts/v4-tail-reseal-macos-rehearsal.mjs +134 -0
  227. package/scripts/v4-tail-reseal.mjs +416 -0
  228. package/templates/native-dev-delivery.yml +143 -0
@@ -0,0 +1,566 @@
1
+ import {
2
+ devDeliveryClone as clone,
3
+ devDeliveryContentRoot as contentRoot,
4
+ devDeliveryExactRoot as exactRoot,
5
+ devDeliveryText as text,
6
+ } from "./dev-delivery-common.js";
7
+ import { evaluateBuildchainChannelBinding } from "./buildchain-channel-identity.js";
8
+ import {
9
+ assertBuildchainCompatibilityProjection,
10
+ createBuildchainCompatibilityProofRegistry,
11
+ resolveBuildchainCompatibilityProof,
12
+ } from "./buildchain-compatibility-authority.js";
13
+
14
+ export {
15
+ BUILDCHAIN_COMPATIBILITY_FACT_REGISTRY_SCHEMA,
16
+ BUILDCHAIN_COMPATIBILITY_RELEASE_EVIDENCE_SCHEMA,
17
+ BUILDCHAIN_COMPATIBILITY_FACT_SCHEMA,
18
+ BUILDCHAIN_COMPATIBILITY_PROOF_REGISTRY_SCHEMA,
19
+ BUILDCHAIN_COMPATIBILITY_PROOF_SCHEMA,
20
+ createBuildchainCompatibilityFact,
21
+ createBuildchainCompatibilityFactRegistry,
22
+ createBuildchainCompatibilityProof,
23
+ createHistoricalBuildchainCompatibilityFacts,
24
+ createHistoricalBuildchainCompatibilityProofs,
25
+ verifyBuildchainCompatibilityFact,
26
+ verifyBuildchainCompatibilityFactRegistry,
27
+ verifyBuildchainCompatibilityProof,
28
+ } from "./buildchain-compatibility-fact.js";
29
+ export {
30
+ assertBuildchainCompatibilityProjection,
31
+ createBuildchainCompatibilityPathQuery,
32
+ createBuildchainCompatibilityProofRegistry,
33
+ createBuildchainCompatibilityReleaseEvidence,
34
+ resolveBuildchainCompatibilityProof,
35
+ verifyBuildchainCompatibilityPath,
36
+ } from "./buildchain-compatibility-authority.js";
37
+
38
+ export const BUILDCHAIN_LEGACY_COMPATIBILITY_VERIFICATION_RECEIPT_SCHEMA =
39
+ "kungfu.buildchain.compatibility-verification-receipt/v1";
40
+ export const BUILDCHAIN_COMPATIBILITY_VERIFICATION_RECEIPT_SCHEMA =
41
+ "kungfu.buildchain.compatibility-verification-receipt/v2";
42
+
43
+ const BUILDCHAIN_CONTRACT = "kungfu-buildchain-runtime-contract-world";
44
+ const COMPATIBILITY_OPERATION = "accept-contract-lock";
45
+ const COMPATIBILITY_DIRECTION = "source-to-target";
46
+
47
+ function exactText(value, label) {
48
+ const normalized = text(value);
49
+ if (!normalized) throw new Error(`${label} must not be empty`);
50
+ return normalized;
51
+ }
52
+
53
+ export function createBuildchainCompatibilityVerificationReceipt(input = {}) {
54
+ const decisions = clone(input.decisions || []);
55
+ const usedProofRoots = [
56
+ ...new Set(
57
+ decisions
58
+ .map((decision) => decision.proofRoot)
59
+ .filter(Boolean)
60
+ .map((root) => exactRoot(root, "decision.proofRoot")),
61
+ ),
62
+ ].sort();
63
+ const usedFactRoots = [
64
+ ...new Set(
65
+ decisions
66
+ .map((decision) => decision.factRoot)
67
+ .filter(Boolean)
68
+ .map((root) => exactRoot(root, "decision.factRoot")),
69
+ ),
70
+ ].sort();
71
+ const pathReceiptRoots = [
72
+ ...new Set(
73
+ decisions
74
+ .map((decision) => decision.pathReceiptRoot)
75
+ .filter(Boolean)
76
+ .map((root) => exactRoot(root, "decision.pathReceiptRoot")),
77
+ ),
78
+ ].sort();
79
+ const body = {
80
+ schema: BUILDCHAIN_COMPATIBILITY_VERIFICATION_RECEIPT_SCHEMA,
81
+ operation: COMPATIBILITY_OPERATION,
82
+ direction: COMPATIBILITY_DIRECTION,
83
+ status: exactText(input.status, "status"),
84
+ compatible: input.compatible === true,
85
+ policy: exactText(input.policy, "policy"),
86
+ scope: clone(input.scope || {}),
87
+ acceptedContractDigest: text(input.acceptedContractDigest),
88
+ acceptedCompatibilityDigest: text(input.acceptedCompatibilityDigest),
89
+ acceptedFactRegistryRoot: text(input.acceptedFactRegistryRoot),
90
+ acceptedProofRegistryRoot: text(input.acceptedProofRegistryRoot),
91
+ currentContractDigest: text(input.currentContractDigest),
92
+ currentCompatibilityDigest: text(input.currentCompatibilityDigest),
93
+ currentFactRegistryRoot: exactRoot(
94
+ input.currentFactRegistryRoot,
95
+ "currentFactRegistryRoot",
96
+ ),
97
+ currentFactCutRoot: exactRoot(
98
+ input.currentFactCutRoot,
99
+ "currentFactCutRoot",
100
+ ),
101
+ currentProofRegistryRoot: text(input.currentProofRegistryRoot),
102
+ decisions,
103
+ usedProofRoots,
104
+ usedFactRoots,
105
+ pathReceiptRoots,
106
+ reasonCodes: [
107
+ ...new Set(
108
+ (input.reasonCodes || []).map((reason) =>
109
+ exactText(reason, "reasonCode"),
110
+ ),
111
+ ),
112
+ ].sort(),
113
+ };
114
+ return { ...body, receiptRoot: contentRoot(body) };
115
+ }
116
+
117
+ function createLegacyCompatibilityVerificationReceipt(input = {}) {
118
+ const decisions = clone(input.decisions || []);
119
+ const body = {
120
+ schema: BUILDCHAIN_LEGACY_COMPATIBILITY_VERIFICATION_RECEIPT_SCHEMA,
121
+ operation: COMPATIBILITY_OPERATION,
122
+ direction: COMPATIBILITY_DIRECTION,
123
+ status: exactText(input.status, "status"),
124
+ compatible: input.compatible === true,
125
+ policy: exactText(input.policy, "policy"),
126
+ scope: clone(input.scope || {}),
127
+ acceptedContractDigest: text(input.acceptedContractDigest),
128
+ acceptedCompatibilityDigest: text(input.acceptedCompatibilityDigest),
129
+ acceptedProofRegistryRoot: text(input.acceptedProofRegistryRoot),
130
+ currentContractDigest: text(input.currentContractDigest),
131
+ currentCompatibilityDigest: text(input.currentCompatibilityDigest),
132
+ currentProofRegistryRoot: text(input.currentProofRegistryRoot),
133
+ decisions,
134
+ usedProofRoots: [
135
+ ...new Set(
136
+ decisions
137
+ .map((decision) => decision.proofRoot)
138
+ .filter(Boolean)
139
+ .map((entry) => exactRoot(entry, "decision.proofRoot")),
140
+ ),
141
+ ].sort(),
142
+ reasonCodes: [
143
+ ...new Set(
144
+ (input.reasonCodes || []).map((reason) =>
145
+ exactText(reason, "reasonCode"),
146
+ ),
147
+ ),
148
+ ].sort(),
149
+ };
150
+ return { ...body, receiptRoot: contentRoot(body) };
151
+ }
152
+
153
+ export function verifyBuildchainCompatibilityVerificationReceipt(receiptInput) {
154
+ try {
155
+ const receipt = clone(receiptInput || {});
156
+ const normalized =
157
+ receipt.schema === BUILDCHAIN_COMPATIBILITY_VERIFICATION_RECEIPT_SCHEMA
158
+ ? createBuildchainCompatibilityVerificationReceipt(receipt)
159
+ : receipt.schema ===
160
+ BUILDCHAIN_LEGACY_COMPATIBILITY_VERIFICATION_RECEIPT_SCHEMA
161
+ ? createLegacyCompatibilityVerificationReceipt(receipt)
162
+ : null;
163
+ if (!normalized) return { ok: false, reason: "unsupported-schema" };
164
+ if (normalized.receiptRoot !== receipt.receiptRoot)
165
+ return { ok: false, reason: "receipt-root-drift" };
166
+ if (JSON.stringify(normalized) !== JSON.stringify(receipt))
167
+ return { ok: false, reason: "non-canonical-receipt" };
168
+ return {
169
+ ok: true,
170
+ reason: "exact-compatibility-verification-receipt",
171
+ receiptRoot: receipt.receiptRoot,
172
+ };
173
+ } catch (error) {
174
+ return { ok: false, reason: "invalid-receipt", error: error.message };
175
+ }
176
+ }
177
+
178
+ export function contractSummary(
179
+ contractWorld,
180
+ runtimeRef = "",
181
+ runtimeSha = "",
182
+ ) {
183
+ return {
184
+ ref: runtimeRef,
185
+ resolvedSha: runtimeSha,
186
+ contract: contractWorld.contract,
187
+ contractDigest: contractWorld.contractDigest,
188
+ compatibilityDigest: contractWorld.compatibilityDigest,
189
+ compatibilityFactRegistryRoot: contractWorld.compatibilityFactRegistryRoot,
190
+ compatibilityFactCutRoot: contractWorld.compatibilityFactCutRoot,
191
+ compatibilityProofRegistryRoot:
192
+ contractWorld.compatibilityProofRegistryRoot,
193
+ majorLine: contractWorld.majorLine,
194
+ surfaceCount: Array.isArray(contractWorld.surfaces)
195
+ ? contractWorld.surfaces.length
196
+ : 0,
197
+ };
198
+ }
199
+
200
+ function evaluationReceipt({
201
+ status,
202
+ compatible,
203
+ policy,
204
+ accepted,
205
+ current,
206
+ decisions = [],
207
+ reasons = [],
208
+ }) {
209
+ return createBuildchainCompatibilityVerificationReceipt({
210
+ status,
211
+ compatible,
212
+ policy,
213
+ scope: { contract: current.contract, majorLine: current.majorLine },
214
+ acceptedContractDigest: accepted.contractDigest,
215
+ acceptedCompatibilityDigest: accepted.compatibilityDigest,
216
+ acceptedFactRegistryRoot: accepted.compatibilityFactRegistryRoot,
217
+ acceptedProofRegistryRoot: accepted.compatibilityProofRegistryRoot,
218
+ currentContractDigest: current.contractDigest,
219
+ currentCompatibilityDigest: current.compatibilityDigest,
220
+ currentFactRegistryRoot: current.compatibilityFactRegistryRoot,
221
+ currentFactCutRoot: current.compatibilityFactCutRoot,
222
+ currentProofRegistryRoot: current.compatibilityProofRegistryRoot,
223
+ decisions,
224
+ reasonCodes: reasons,
225
+ });
226
+ }
227
+
228
+ function contractPolicyReasons(accepted, current, policy) {
229
+ const reasons = [];
230
+ if (accepted.contract !== current.contract)
231
+ reasons.push(
232
+ `contract changed from ${accepted.contract || "(unknown)"} to ${current.contract}`,
233
+ );
234
+ if (accepted.majorLine && accepted.majorLine !== current.majorLine)
235
+ reasons.push(
236
+ `major line changed from ${accepted.majorLine} to ${current.majorLine}`,
237
+ );
238
+ if (policy === "exact" && accepted.contractDigest !== current.contractDigest)
239
+ reasons.push(
240
+ "exact policy requires the contract digest to remain unchanged",
241
+ );
242
+ if (!["major-compatible", "allow-additive", "exact"].includes(policy))
243
+ reasons.push(`unsupported compatibility policy: ${policy}`);
244
+ return reasons;
245
+ }
246
+
247
+ function evaluateSurfaceRelation({
248
+ oldSurface,
249
+ nextSurface,
250
+ proofRegistry,
251
+ majorLine,
252
+ }) {
253
+ if (!nextSurface) {
254
+ return {
255
+ reason: `surface removed: ${oldSurface.id}`,
256
+ decision: {
257
+ surfaceId: oldSurface.id,
258
+ status: "surface-removed",
259
+ sourceBreakingDigest: oldSurface.breakingDigest,
260
+ targetBreakingDigest: "",
261
+ reason: "surface-removed",
262
+ },
263
+ };
264
+ }
265
+ if (nextSurface.breakingDigest === oldSurface.breakingDigest) return {};
266
+ const resolution = resolveBuildchainCompatibilityProof({
267
+ registry: proofRegistry,
268
+ surface: nextSurface,
269
+ sourceBreakingDigest: oldSurface.breakingDigest,
270
+ majorLine,
271
+ });
272
+ if (!resolution.ok) {
273
+ return {
274
+ reason: `surface breaking digest changed without a valid compatibility proof: ${oldSurface.id} (${resolution.reason})`,
275
+ decision: {
276
+ surfaceId: oldSurface.id,
277
+ status: "rejected",
278
+ sourceBreakingDigest: oldSurface.breakingDigest,
279
+ targetBreakingDigest: nextSurface.breakingDigest,
280
+ reason: resolution.reason,
281
+ },
282
+ };
283
+ }
284
+ const proof = resolution.proof;
285
+ return {
286
+ decision: {
287
+ surfaceId: oldSurface.id,
288
+ status: "accepted",
289
+ sourceBreakingDigest: oldSurface.breakingDigest,
290
+ targetBreakingDigest: nextSurface.breakingDigest,
291
+ proofRoot: proof.proofRoot,
292
+ factRoot: resolution.factRoot,
293
+ pathReceipt: resolution.pathReceipt,
294
+ pathReceiptRoot: resolution.pathReceiptRoot,
295
+ direction: proof.direction,
296
+ operation: proof.operation,
297
+ scope: proof.scope,
298
+ scopeRoot: proof.scopeRoot,
299
+ evidence: proof.evidence,
300
+ evidenceRoot: proof.evidenceRoot,
301
+ authority: proof.authority,
302
+ authorityRoot: proof.authorityRoot,
303
+ cut: proof.cut,
304
+ cutRoot: proof.cutRoot,
305
+ },
306
+ };
307
+ }
308
+
309
+ function evaluateChannelBinding({
310
+ lock,
311
+ workflowShellRef,
312
+ runtimeRef,
313
+ expectedChannel,
314
+ expectedMajor,
315
+ allowOpaqueRuntime,
316
+ }) {
317
+ if (!workflowShellRef && !expectedChannel && !expectedMajor) return null;
318
+ return evaluateBuildchainChannelBinding({
319
+ workflowShellRef,
320
+ runtimeRef,
321
+ lockRef: lock?.buildchain?.ref || "",
322
+ lockMajorLine: lock?.buildchain?.majorLine || "",
323
+ expectedChannel,
324
+ expectedMajor,
325
+ allowOpaqueRuntime,
326
+ });
327
+ }
328
+
329
+ export function evaluateBuildchainContractLock({
330
+ lock,
331
+ current,
332
+ runtimeRef = "",
333
+ runtimeSha = "",
334
+ runtimeClass = "",
335
+ compatibilityPolicy = "",
336
+ workflowShellRef = "",
337
+ expectedChannel = "",
338
+ expectedMajor = "",
339
+ allowOpaqueRuntime = false,
340
+ } = {}) {
341
+ if (!current || current.contract !== BUILDCHAIN_CONTRACT) {
342
+ throw new Error("current must be a Buildchain runtime contract world");
343
+ }
344
+ assertBuildchainCompatibilityProjection(current);
345
+ const binding = evaluateChannelBinding({
346
+ lock,
347
+ workflowShellRef,
348
+ runtimeRef,
349
+ expectedChannel,
350
+ expectedMajor,
351
+ allowOpaqueRuntime,
352
+ });
353
+ if (binding?.ok === false) {
354
+ return {
355
+ ok: false,
356
+ status: binding.status,
357
+ drift: false,
358
+ compatible: false,
359
+ issueRecommended: false,
360
+ reasons: binding.reasons,
361
+ channelBinding: binding,
362
+ };
363
+ }
364
+ if (!new Set(["stable", "alpha"]).has(runtimeClass)) {
365
+ return {
366
+ ok: true,
367
+ status: "non-floating-runtime",
368
+ drift: false,
369
+ compatible: true,
370
+ issueRecommended: false,
371
+ reason: `runtime class ${runtimeClass || "unknown"} is not a stable floating ref`,
372
+ };
373
+ }
374
+ if (!lock) {
375
+ return {
376
+ ok: true,
377
+ status: "missing-lock",
378
+ drift: false,
379
+ compatible: true,
380
+ issueRecommended: false,
381
+ reason: "consumer repository has no Buildchain contract lock",
382
+ };
383
+ }
384
+ const accepted = lock.buildchain || {};
385
+ const policy =
386
+ compatibilityPolicy || accepted.compatibilityPolicy || "major-compatible";
387
+ const shaDrift =
388
+ !!accepted.resolvedSha &&
389
+ !!runtimeSha &&
390
+ accepted.resolvedSha !== runtimeSha;
391
+ const contractDrift =
392
+ !!accepted.contractDigest &&
393
+ accepted.contractDigest !== current.contractDigest;
394
+ if (!shaDrift && !contractDrift) {
395
+ const verificationReceipt = evaluationReceipt({
396
+ status: "unchanged",
397
+ compatible: true,
398
+ policy,
399
+ accepted,
400
+ current,
401
+ });
402
+ return {
403
+ ok: true,
404
+ status: "unchanged",
405
+ drift: false,
406
+ compatible: true,
407
+ issueRecommended: false,
408
+ policy,
409
+ accepted,
410
+ current: contractSummary(current, runtimeRef, runtimeSha),
411
+ compatibilityDecisions: [],
412
+ usedProofRoots: [],
413
+ usedFactRoots: [],
414
+ pathReceiptRoots: [],
415
+ verificationReceipt,
416
+ receiptRoot: verificationReceipt.receiptRoot,
417
+ };
418
+ }
419
+ const reasons = contractPolicyReasons(accepted, current, policy);
420
+ const compatibilityDecisions = [];
421
+ const currentSurfaces = new Map(
422
+ current.surfaces.map((entry) => [entry.id, entry]),
423
+ );
424
+ const proofRegistry = createBuildchainCompatibilityProofRegistry({
425
+ proofs: current.compatibilityProofs,
426
+ surfaces: current.surfaces,
427
+ majorLine: current.majorLine,
428
+ });
429
+ for (const oldSurface of accepted.surfaces || []) {
430
+ const result = evaluateSurfaceRelation({
431
+ oldSurface,
432
+ nextSurface: currentSurfaces.get(oldSurface.id),
433
+ proofRegistry,
434
+ majorLine: current.majorLine,
435
+ });
436
+ if (result.reason) reasons.push(result.reason);
437
+ if (result.decision) compatibilityDecisions.push(result.decision);
438
+ }
439
+ const compatible = reasons.length === 0;
440
+ const status = compatible ? "compatible-drift" : "breaking-drift";
441
+ const verificationReceipt = evaluationReceipt({
442
+ status,
443
+ compatible,
444
+ policy,
445
+ accepted,
446
+ current,
447
+ decisions: compatibilityDecisions,
448
+ reasons,
449
+ });
450
+ return {
451
+ ok: compatible,
452
+ status,
453
+ drift: shaDrift || contractDrift,
454
+ shaDrift,
455
+ contractDrift,
456
+ compatible,
457
+ issueRecommended: true,
458
+ policy,
459
+ reasons,
460
+ accepted,
461
+ current: contractSummary(current, runtimeRef, runtimeSha),
462
+ compatibilityDecisions,
463
+ usedProofRoots: verificationReceipt.usedProofRoots,
464
+ usedFactRoots: verificationReceipt.usedFactRoots,
465
+ pathReceiptRoots: verificationReceipt.pathReceiptRoots,
466
+ verificationReceipt,
467
+ receiptRoot: verificationReceipt.receiptRoot,
468
+ };
469
+ }
470
+
471
+ function shown(value, fallback = "(unknown)") {
472
+ return value ? value : fallback;
473
+ }
474
+
475
+ function renderCompatibilityDecision(decision) {
476
+ const lines = [
477
+ `- Surface \`${decision.surfaceId}\`: ${decision.status}`,
478
+ ` - Relation: \`${shown(decision.sourceBreakingDigest, "(missing)")}\` -> \`${shown(decision.targetBreakingDigest, "(missing)")}\``,
479
+ ` - Reason: \`${shown(decision.reason, "proof-backed-compatible-relation")}\``,
480
+ ];
481
+ if (!decision.proofRoot) return lines.join("\n");
482
+ lines.push(
483
+ ` - Proof root: \`${decision.proofRoot}\``,
484
+ ` - Fact root: \`${decision.factRoot}\``,
485
+ ` - Temporal path receipt: \`${decision.pathReceiptRoot}\``,
486
+ ` - Direction / operation: \`${decision.direction}\` / \`${decision.operation}\``,
487
+ ` - Scope root: \`${decision.scopeRoot}\``,
488
+ ` - Evidence: ${shown(decision.evidence && decision.evidence.pullRequest)} (\`${decision.evidenceRoot}\`)`,
489
+ ` - Authority: \`${shown(decision.authority && decision.authority.repository)}@${shown(decision.authority && decision.authority.protectedBase)}\` (\`${decision.authorityRoot}\`)`,
490
+ ` - Cut: \`${shown(decision.cut && decision.cut.commit)}\` (\`${decision.cutRoot}\`)`,
491
+ );
492
+ return lines.join("\n");
493
+ }
494
+
495
+ function renderCompatibilityDecisions(decisions) {
496
+ if (decisions.length === 0)
497
+ return "- No breaking-digest relation required proof resolution.";
498
+ return decisions.map(renderCompatibilityDecision).join("\n");
499
+ }
500
+
501
+ export function renderBuildchainContractDriftIssueBody({
502
+ repository = "",
503
+ workflow = "",
504
+ runUrl = "",
505
+ lockPath = "",
506
+ evaluation,
507
+ } = {}) {
508
+ const accepted = evaluation.accepted || {};
509
+ const current = evaluation.current || {};
510
+ const decisions = evaluation.compatibilityDecisions || [];
511
+ const renderedDecisions = renderCompatibilityDecisions(decisions);
512
+ return [
513
+ "# Buildchain contract drift",
514
+ "",
515
+ "## Summary",
516
+ "",
517
+ `Buildchain detected ${evaluation.compatible ? "compatible" : "breaking"} contract drift for a floating runtime ref before expensive Buildchain work continued.`,
518
+ "",
519
+ "## Consumer",
520
+ "",
521
+ `- Repository: ${shown(repository)}`,
522
+ `- Workflow: ${shown(workflow)}`,
523
+ `- Run: ${shown(runUrl)}`,
524
+ `- Lock path: ${shown(lockPath)}`,
525
+ "",
526
+ "## Accepted Buildchain contract",
527
+ "",
528
+ `- Ref: ${shown(accepted.ref)}`,
529
+ `- SHA: ${shown(accepted.resolvedSha)}`,
530
+ `- Contract digest: ${shown(accepted.contractDigest)}`,
531
+ `- Compatibility digest: ${shown(accepted.compatibilityDigest)}`,
532
+ `- Compatibility Fact registry: ${shown(accepted.compatibilityFactRegistryRoot, "(legacy lock without Fact registry)")}`,
533
+ `- Compatibility proof registry: ${shown(accepted.compatibilityProofRegistryRoot, "(legacy lock without proof registry)")}`,
534
+ `- Policy: ${shown(evaluation.policy || accepted.compatibilityPolicy)}`,
535
+ "",
536
+ "## Current Buildchain contract",
537
+ "",
538
+ `- Ref: ${shown(current.ref)}`,
539
+ `- SHA: ${shown(current.resolvedSha)}`,
540
+ `- Contract digest: ${shown(current.contractDigest)}`,
541
+ `- Compatibility digest: ${shown(current.compatibilityDigest)}`,
542
+ `- Compatibility Fact registry: ${shown(current.compatibilityFactRegistryRoot)}`,
543
+ `- Compatibility Fact Cut: ${shown(current.compatibilityFactCutRoot)}`,
544
+ `- Compatibility proof registry: ${shown(current.compatibilityProofRegistryRoot)}`,
545
+ `- Major line: ${shown(current.majorLine)}`,
546
+ "",
547
+ "## Compatibility",
548
+ "",
549
+ `- Status: ${shown(evaluation.status)}`,
550
+ `- Compatible: ${evaluation.compatible ? "yes" : "no"}`,
551
+ evaluation.reasons && evaluation.reasons.length
552
+ ? evaluation.reasons.map((reason) => `- ${reason}`).join("\n")
553
+ : "- No breaking drift detected.",
554
+ "",
555
+ "## Proof-backed decisions",
556
+ "",
557
+ renderedDecisions,
558
+ `- Verification receipt: \`${shown(evaluation.receiptRoot, "(not produced)")}\``,
559
+ "",
560
+ "## Suggested next action",
561
+ "",
562
+ evaluation.compatible
563
+ ? "Review the Buildchain release notes, then update the consumer contract lock to the current SHA and contract digest."
564
+ : "Failing before heavy build is intentional. Review the Buildchain contract change, update the consumer workflow/configuration, or pin the previous Buildchain SHA.",
565
+ ].join("\n");
566
+ }