@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
@@ -1,631 +0,0 @@
1
- import {
2
- devDeliveryClone as clone,
3
- devDeliveryContentRoot as contentRoot,
4
- devDeliveryExactRoot as exactRoot,
5
- devDeliveryExactSha as exactSha,
6
- devDeliveryProtectedBase as protectedBase,
7
- devDeliveryRepository as repository,
8
- devDeliveryText as text,
9
- } from "./dev-delivery-common.js";
10
- import { evaluateBuildchainChannelBinding } from "./buildchain-channel-identity.js";
11
-
12
- export const BUILDCHAIN_COMPATIBILITY_PROOF_SCHEMA = "kungfu.buildchain.compatibility-proof/v1";
13
- export const BUILDCHAIN_COMPATIBILITY_PROOF_REGISTRY_SCHEMA = "kungfu.buildchain.compatibility-proof-registry/v1";
14
- export const BUILDCHAIN_COMPATIBILITY_VERIFICATION_RECEIPT_SCHEMA = "kungfu.buildchain.compatibility-verification-receipt/v1";
15
-
16
- const BUILDCHAIN_CONTRACT = "kungfu-buildchain-runtime-contract-world";
17
- const COMPATIBILITY_PREDICATE = "compatible-breaking-digest";
18
- const COMPATIBILITY_OPERATION = "accept-contract-lock";
19
- const COMPATIBILITY_DIRECTION = "source-to-target";
20
- const CURRENT_PROOF_CUT = {
21
- kind: "protected-git-cut",
22
- repository: "kungfu-systems/buildchain",
23
- protectedBase: "dev/v3/v3.0",
24
- commit: "ff0f9006be1c8f63be40e67789e0cfd28fd69d46",
25
- };
26
- const CURRENT_AUTHORITY = {
27
- kind: "protected-base-contract-authority",
28
- repository: "kungfu-systems/buildchain",
29
- protectedBase: "dev/v3/v3.0",
30
- };
31
-
32
- const HISTORICAL_ACCEPTANCES = [
33
- {
34
- proofId: "release-candidate-promote-acd401-to-e60642",
35
- surfaceId: "release-candidate-promote",
36
- surfaceKind: "workflow",
37
- sourceBreakingDigest: "sha256:acd401cfc46450115a3763fd4b679d85f185e8757ebd52510d6262e1533df4cf",
38
- targetBreakingDigest: "sha256:e60642aa298933d2c103284794921a6c340a50aa91ee528b06e58892a2a006bf",
39
- evidence: {
40
- kind: "protected-pull-request-contract-acceptance",
41
- pullRequest: "https://github.com/kungfu-systems/buildchain/pull/2342",
42
- protectedBase: "dev/v3/v3.0",
43
- sourceCommit: "8870db287a9ee5fb95eebbbe907b1649d84d5b7f",
44
- mergeCommit: "30b605adea1ed33dcf0bbb4cc7b666b64a6ccd18",
45
- contractDigest: "sha256:9c07dbdb9aa8390569cd07ace044af45e6751b91ffe8fcc0cb69a77388b0f72b",
46
- compatibilityDigest: "sha256:80cfdf1786019217c439810f1a80d2866bf8f7ef35a6fa569e1a687fb2bf4cbe",
47
- },
48
- },
49
- {
50
- proofId: "advanced-release-candidate-promote-aa30f2-to-9db8dd",
51
- surfaceId: "advanced-release-candidate-promote",
52
- surfaceKind: "workflow",
53
- sourceBreakingDigest: "sha256:aa30f22e3af0a89841310bdbdc900844dd95a66974db173fa140a71bbd7e82c0",
54
- targetBreakingDigest: "sha256:9db8dd07152855d03ff30f9c571438593c689d3e8139fa45431d000f548242f5",
55
- evidence: {
56
- kind: "protected-pull-request-contract-acceptance",
57
- pullRequest: "https://github.com/kungfu-systems/buildchain/pull/2342",
58
- protectedBase: "dev/v3/v3.0",
59
- sourceCommit: "8870db287a9ee5fb95eebbbe907b1649d84d5b7f",
60
- mergeCommit: "30b605adea1ed33dcf0bbb4cc7b666b64a6ccd18",
61
- contractDigest: "sha256:9c07dbdb9aa8390569cd07ace044af45e6751b91ffe8fcc0cb69a77388b0f72b",
62
- compatibilityDigest: "sha256:80cfdf1786019217c439810f1a80d2866bf8f7ef35a6fa569e1a687fb2bf4cbe",
63
- },
64
- },
65
- {
66
- proofId: "promote-buildchain-ref-action-a59f09-to-6147c0",
67
- surfaceId: "promote-buildchain-ref-action",
68
- surfaceKind: "action",
69
- sourceBreakingDigest: "sha256:a59f0910e6df842e7699139472e5dd69ac2fdd7f7213bf2cb346d1d622556874",
70
- targetBreakingDigest: "sha256:6147c0a8d5c36bfaa6021871574e1fc28192a3f1b8cfdae4d24ef3059ac1ebda",
71
- evidence: {
72
- kind: "protected-pull-request-contract-acceptance",
73
- pullRequest: "https://github.com/kungfu-systems/buildchain/pull/1556",
74
- protectedBase: "dev/v2/v2.14",
75
- sourceCommit: "f8e2c5d28ef34d711892589331b7e018095a96d7",
76
- mergeCommit: "6e0c29be1489f686a9a3792b46bfaa4466828393",
77
- contractDigest: "sha256:f6dbf5147d9ad3b8c49ba6630cd52b8c7853ead7c921d7e1210a393aebf97d1f",
78
- compatibilityDigest: "sha256:cdf588422ec6b460bd6f631400efa6e361a045e052c8967d6c50fadd7aa4dd90",
79
- },
80
- },
81
- {
82
- proofId: "build-lifecycle-e264a7-to-6b8d38",
83
- surfaceId: "controller:build-lifecycle",
84
- surfaceKind: "controller",
85
- sourceBreakingDigest: "sha256:e264a79f9f399038c2fcfd21e4168c68c2e1485ee5c651c02242a02b622ac2be",
86
- targetBreakingDigest: "sha256:6b8d38e92b2c67b5bc83fae0a3fd95bfa47582fbc176e6cdeebe7630a57534cb",
87
- evidence: {
88
- kind: "protected-pull-request-contract-acceptance",
89
- pullRequest: "https://github.com/kungfu-systems/buildchain/pull/2058",
90
- protectedBase: "dev/v3/v3.0",
91
- sourceCommit: "c9a86bd1ac17b4fae54b0410498830edad80d831",
92
- mergeCommit: "3991801a7a7d6fe5e31b9a670dfde7ea59e61253",
93
- contractDigest: "sha256:da72850bbd3088f0e9eb20c17382557e0dfb7e68bf4469d352ed870ee8a334e8",
94
- compatibilityDigest: "sha256:32a651504c57829085dc8863f0e41dee98eb60708ff6dec958c9c7e4b1010102",
95
- },
96
- },
97
- {
98
- proofId: "build-lifecycle-307459-to-6b8d38",
99
- surfaceId: "controller:build-lifecycle",
100
- surfaceKind: "controller",
101
- sourceBreakingDigest: "sha256:30745921541e9b0f70475bb2178c2559f6aef248f6680670ccd44d8c5a69a6b1",
102
- targetBreakingDigest: "sha256:6b8d38e92b2c67b5bc83fae0a3fd95bfa47582fbc176e6cdeebe7630a57534cb",
103
- evidence: {
104
- kind: "protected-pull-request-contract-acceptance",
105
- pullRequest: "https://github.com/kungfu-systems/buildchain/pull/2058",
106
- protectedBase: "dev/v3/v3.0",
107
- sourceCommit: "c9a86bd1ac17b4fae54b0410498830edad80d831",
108
- mergeCommit: "3991801a7a7d6fe5e31b9a670dfde7ea59e61253",
109
- contractDigest: "sha256:da72850bbd3088f0e9eb20c17382557e0dfb7e68bf4469d352ed870ee8a334e8",
110
- compatibilityDigest: "sha256:32a651504c57829085dc8863f0e41dee98eb60708ff6dec958c9c7e4b1010102",
111
- },
112
- },
113
- {
114
- proofId: "build-channel-router-d40dd0-to-30549a",
115
- surfaceId: "controller:build-channel-router",
116
- surfaceKind: "controller",
117
- sourceBreakingDigest: "sha256:d40dd05d7e07473d4b2dc1b62fbb0ed6f06449b4d3a7c44a2e8014313e3c0273",
118
- targetBreakingDigest: "sha256:30549aa26cd1e1dd81f10fe3529d3c6e3f8438a6efa0100c47ebae4d2f3d71df",
119
- evidence: {
120
- kind: "protected-pull-request-contract-acceptance",
121
- pullRequest: "https://github.com/kungfu-systems/buildchain/pull/2549",
122
- protectedBase: "dev/v3/v3.0",
123
- sourceCommit: "0d87b772265066f5e6157e1ba6a2ba1021fb5225",
124
- mergeCommit: "34fad9d3a94c450d75c0d06fd6ed00470c992ff7",
125
- contractDigest: "sha256:2584ba36ab54cd5e9bab9e34dfc08d87a55dc57de1be7641492bf7ceb1366350",
126
- compatibilityDigest: "sha256:80f65cc191b1f771475184edf8a1bf9c10dd69bb58060aa09313d0e1e57f508a",
127
- },
128
- cut: {
129
- kind: "protected-git-cut",
130
- repository: "kungfu-systems/buildchain",
131
- protectedBase: "dev/v3/v3.0",
132
- commit: "34fad9d3a94c450d75c0d06fd6ed00470c992ff7",
133
- },
134
- },
135
- ];
136
-
137
- function exactText(value, label) {
138
- const normalized = text(value);
139
- if (!normalized) throw new Error(`${label} must not be empty`);
140
- return normalized;
141
- }
142
-
143
- function majorLines(values) {
144
- const normalized = [...new Set((values || []).map((value) => exactText(value, "majorLine")))].sort();
145
- if (normalized.length === 0 || normalized.some((value) => !/^v\d+$/.test(value))) {
146
- throw new Error("scope.majorLines must contain version-major identifiers");
147
- }
148
- return normalized;
149
- }
150
-
151
- function normalizeEvidence(value = {}) {
152
- return {
153
- kind: exactText(value.kind, "evidence.kind"),
154
- pullRequest: exactText(value.pullRequest, "evidence.pullRequest"),
155
- protectedBase: protectedBase(value.protectedBase),
156
- sourceCommit: exactSha(value.sourceCommit, "evidence.sourceCommit"),
157
- mergeCommit: exactSha(value.mergeCommit, "evidence.mergeCommit"),
158
- contractDigest: exactRoot(value.contractDigest, "evidence.contractDigest"),
159
- compatibilityDigest: exactRoot(value.compatibilityDigest, "evidence.compatibilityDigest"),
160
- };
161
- }
162
-
163
- function normalizeAuthority(value = {}) {
164
- return {
165
- kind: exactText(value.kind, "authority.kind"),
166
- repository: repository(value.repository),
167
- protectedBase: protectedBase(value.protectedBase),
168
- };
169
- }
170
-
171
- function normalizeCut(value = {}) {
172
- return {
173
- kind: exactText(value.kind, "cut.kind"),
174
- repository: repository(value.repository),
175
- protectedBase: protectedBase(value.protectedBase),
176
- commit: exactSha(value.commit, "cut.commit"),
177
- };
178
- }
179
-
180
- export function createBuildchainCompatibilityProof(input = {}) {
181
- const surfaceId = exactText(input.surfaceId, "surfaceId");
182
- const surfaceKind = exactText(input.surfaceKind, "surfaceKind");
183
- const sourceBreakingDigest = exactRoot(input.sourceBreakingDigest, "sourceBreakingDigest");
184
- const targetBreakingDigest = exactRoot(input.targetBreakingDigest, "targetBreakingDigest");
185
- if (sourceBreakingDigest === targetBreakingDigest) {
186
- throw new Error("compatibility proof source and target must differ");
187
- }
188
- const scope = {
189
- contract: BUILDCHAIN_CONTRACT,
190
- surfaceId,
191
- surfaceKind,
192
- majorLines: majorLines(input.scope?.majorLines || ["v2", "v3"]),
193
- operation: COMPATIBILITY_OPERATION,
194
- };
195
- const evidence = normalizeEvidence(input.evidence);
196
- const authority = normalizeAuthority(input.authority || CURRENT_AUTHORITY);
197
- const cut = normalizeCut(input.cut || CURRENT_PROOF_CUT);
198
- const body = {
199
- schema: BUILDCHAIN_COMPATIBILITY_PROOF_SCHEMA,
200
- proofId: exactText(input.proofId, "proofId"),
201
- predicate: COMPATIBILITY_PREDICATE,
202
- direction: COMPATIBILITY_DIRECTION,
203
- operation: COMPATIBILITY_OPERATION,
204
- source: {
205
- contract: BUILDCHAIN_CONTRACT,
206
- surfaceId,
207
- surfaceKind,
208
- breakingDigest: sourceBreakingDigest,
209
- },
210
- target: {
211
- contract: BUILDCHAIN_CONTRACT,
212
- surfaceId,
213
- surfaceKind,
214
- breakingDigest: targetBreakingDigest,
215
- },
216
- scope,
217
- scopeRoot: contentRoot(scope),
218
- evidence,
219
- evidenceRoot: contentRoot(evidence),
220
- authority,
221
- authorityRoot: contentRoot(authority),
222
- cut,
223
- cutRoot: contentRoot(cut),
224
- };
225
- return { ...body, proofRoot: contentRoot(body) };
226
- }
227
-
228
- export function verifyBuildchainCompatibilityProof(proofInput, expected = {}) {
229
- try {
230
- const proof = clone(proofInput || {});
231
- if (proof.schema !== BUILDCHAIN_COMPATIBILITY_PROOF_SCHEMA) return { ok: false, reason: "unsupported-schema" };
232
- const normalized = createBuildchainCompatibilityProof({
233
- ...proof,
234
- proofId: proof.proofId,
235
- surfaceId: proof.source?.surfaceId,
236
- surfaceKind: proof.source?.surfaceKind,
237
- sourceBreakingDigest: proof.source?.breakingDigest,
238
- targetBreakingDigest: proof.target?.breakingDigest,
239
- scope: proof.scope,
240
- });
241
- if (normalized.proofRoot !== proof.proofRoot) return { ok: false, reason: "proof-root-drift" };
242
- if (JSON.stringify(normalized) !== JSON.stringify(proof)) return { ok: false, reason: "non-canonical-proof" };
243
- for (const [field, value] of Object.entries(expected)) {
244
- if (value !== undefined && normalized[field] !== value) return { ok: false, reason: `${field}-mismatch` };
245
- }
246
- return { ok: true, reason: "exact-compatibility-proof", proofRoot: normalized.proofRoot, proof: normalized };
247
- } catch (error) {
248
- return { ok: false, reason: "invalid-proof", error: error.message };
249
- }
250
- }
251
-
252
- export function createHistoricalBuildchainCompatibilityProofs() {
253
- return HISTORICAL_ACCEPTANCES.map((entry) => createBuildchainCompatibilityProof(entry)).sort((left, right) => left.proofRoot.localeCompare(right.proofRoot));
254
- }
255
-
256
- function projectionForSurface({ proofs, surface, majorLine }) {
257
- const matching = proofs.filter((proof) => (
258
- proof.target.surfaceId === surface.id
259
- && proof.target.surfaceKind === surface.kind
260
- && proof.target.breakingDigest === surface.breakingDigest
261
- && proof.scope.majorLines.includes(majorLine)
262
- && proof.operation === COMPATIBILITY_OPERATION
263
- ));
264
- const bySource = new Map();
265
- for (const proof of matching) {
266
- const sourceDigest = proof.source.breakingDigest;
267
- if (bySource.has(sourceDigest)) throw new Error(`ambiguous compatibility proof for ${surface.id} ${sourceDigest}`);
268
- bySource.set(sourceDigest, proof);
269
- }
270
- return [...bySource.values()]
271
- .sort((left, right) => left.source.breakingDigest.localeCompare(right.source.breakingDigest))
272
- .map((proof) => ({ breakingDigest: proof.source.breakingDigest, proofRoot: proof.proofRoot }));
273
- }
274
-
275
- export function createBuildchainCompatibilityProofRegistry({ proofs = createHistoricalBuildchainCompatibilityProofs(), surfaces = [], majorLine = "" } = {}) {
276
- const verifiedProofs = proofs.map((proof) => {
277
- const verification = verifyBuildchainCompatibilityProof(proof);
278
- if (!verification.ok) throw new Error(`invalid compatibility proof: ${verification.reason}${verification.error ? `: ${verification.error}` : ""}`);
279
- return verification.proof;
280
- }).sort((left, right) => left.proofRoot.localeCompare(right.proofRoot));
281
- const projections = Object.fromEntries(
282
- [...surfaces]
283
- .sort((left, right) => left.id.localeCompare(right.id))
284
- .map((surface) => [surface.id, projectionForSurface({ proofs: verifiedProofs, surface, majorLine })])
285
- .filter(([, entries]) => entries.length > 0),
286
- );
287
- const identity = {
288
- schema: BUILDCHAIN_COMPATIBILITY_PROOF_REGISTRY_SCHEMA,
289
- proofRoots: verifiedProofs.map((proof) => proof.proofRoot),
290
- };
291
- return {
292
- ...identity,
293
- proofs: verifiedProofs,
294
- projections,
295
- registryRoot: contentRoot(identity),
296
- };
297
- }
298
-
299
- export function assertBuildchainCompatibilityProjection(contractWorld) {
300
- if (!Array.isArray(contractWorld?.compatibilityProofs)) return { ok: true, reason: "legacy-world-without-proofs" };
301
- const registry = createBuildchainCompatibilityProofRegistry({
302
- proofs: contractWorld.compatibilityProofs,
303
- surfaces: contractWorld.surfaces || [],
304
- majorLine: contractWorld.majorLine,
305
- });
306
- if (contractWorld.compatibilityProofRegistryRoot !== registry.registryRoot) {
307
- throw new Error("compatibility proof registry root mismatch");
308
- }
309
- for (const surface of contractWorld.surfaces || []) {
310
- const expected = registry.projections[surface.id] || [];
311
- const expectedDigests = expected.map((entry) => entry.breakingDigest);
312
- const expectedRoots = expected.map((entry) => entry.proofRoot);
313
- const actualDigests = surface.compatibleBreakingDigests || [];
314
- const actualRoots = surface.compatibilityProofRoots || [];
315
- if (JSON.stringify(actualDigests) !== JSON.stringify(expectedDigests)) {
316
- throw new Error(`compatibleBreakingDigests projection mismatch for ${surface.id}`);
317
- }
318
- if (JSON.stringify(actualRoots) !== JSON.stringify(expectedRoots)) {
319
- throw new Error(`compatibilityProofRoots projection mismatch for ${surface.id}`);
320
- }
321
- }
322
- return { ok: true, reason: "exact-proof-backed-projection", registryRoot: registry.registryRoot };
323
- }
324
-
325
- export function resolveBuildchainCompatibilityProof({ registry, surface, sourceBreakingDigest, majorLine } = {}) {
326
- const candidates = (registry?.proofs || []).filter((proof) => (
327
- proof.source.surfaceId === surface.id
328
- && proof.source.surfaceKind === surface.kind
329
- && proof.source.breakingDigest === sourceBreakingDigest
330
- && proof.target.breakingDigest === surface.breakingDigest
331
- && proof.scope.majorLines.includes(majorLine)
332
- && proof.operation === COMPATIBILITY_OPERATION
333
- ));
334
- if (candidates.length === 0) return { ok: false, reason: "compatibility-proof-missing" };
335
- if (candidates.length > 1) return { ok: false, reason: "ambiguous-compatibility-proof" };
336
- const verification = verifyBuildchainCompatibilityProof(candidates[0]);
337
- if (!verification.ok) return verification;
338
- const projection = registry.projections?.[surface.id] || [];
339
- if (!projection.some((entry) => entry.breakingDigest === sourceBreakingDigest && entry.proofRoot === verification.proofRoot)) {
340
- return { ok: false, reason: "compatibility-proof-projection-missing" };
341
- }
342
- return { ok: true, reason: "proof-backed-compatible-relation", proof: verification.proof, proofRoot: verification.proofRoot };
343
- }
344
-
345
- export function createBuildchainCompatibilityVerificationReceipt(input = {}) {
346
- const decisions = clone(input.decisions || []);
347
- const usedProofRoots = [...new Set(decisions.map((decision) => decision.proofRoot).filter(Boolean).map((root) => exactRoot(root, "decision.proofRoot")))].sort();
348
- const body = {
349
- schema: BUILDCHAIN_COMPATIBILITY_VERIFICATION_RECEIPT_SCHEMA,
350
- operation: COMPATIBILITY_OPERATION,
351
- direction: COMPATIBILITY_DIRECTION,
352
- status: exactText(input.status, "status"),
353
- compatible: input.compatible === true,
354
- policy: exactText(input.policy, "policy"),
355
- scope: clone(input.scope || {}),
356
- acceptedContractDigest: text(input.acceptedContractDigest),
357
- acceptedCompatibilityDigest: text(input.acceptedCompatibilityDigest),
358
- acceptedProofRegistryRoot: text(input.acceptedProofRegistryRoot),
359
- currentContractDigest: text(input.currentContractDigest),
360
- currentCompatibilityDigest: text(input.currentCompatibilityDigest),
361
- currentProofRegistryRoot: text(input.currentProofRegistryRoot),
362
- decisions,
363
- usedProofRoots,
364
- reasonCodes: [...new Set((input.reasonCodes || []).map((reason) => exactText(reason, "reasonCode")))].sort(),
365
- };
366
- return { ...body, receiptRoot: contentRoot(body) };
367
- }
368
-
369
- export function verifyBuildchainCompatibilityVerificationReceipt(receiptInput) {
370
- try {
371
- const receipt = clone(receiptInput || {});
372
- if (receipt.schema !== BUILDCHAIN_COMPATIBILITY_VERIFICATION_RECEIPT_SCHEMA) return { ok: false, reason: "unsupported-schema" };
373
- const normalized = createBuildchainCompatibilityVerificationReceipt(receipt);
374
- if (normalized.receiptRoot !== receipt.receiptRoot) return { ok: false, reason: "receipt-root-drift" };
375
- if (JSON.stringify(normalized) !== JSON.stringify(receipt)) return { ok: false, reason: "non-canonical-receipt" };
376
- return { ok: true, reason: "exact-compatibility-verification-receipt", receiptRoot: receipt.receiptRoot };
377
- } catch (error) {
378
- return { ok: false, reason: "invalid-receipt", error: error.message };
379
- }
380
- }
381
-
382
- export function contractSummary(contractWorld, runtimeRef = "", runtimeSha = "") {
383
- return {
384
- ref: runtimeRef,
385
- resolvedSha: runtimeSha,
386
- contract: contractWorld.contract,
387
- contractDigest: contractWorld.contractDigest,
388
- compatibilityDigest: contractWorld.compatibilityDigest,
389
- compatibilityProofRegistryRoot: contractWorld.compatibilityProofRegistryRoot,
390
- majorLine: contractWorld.majorLine,
391
- surfaceCount: Array.isArray(contractWorld.surfaces) ? contractWorld.surfaces.length : 0,
392
- };
393
- }
394
-
395
- function evaluationReceipt({ status, compatible, policy, accepted, current, decisions = [], reasons = [] }) {
396
- return createBuildchainCompatibilityVerificationReceipt({
397
- status,
398
- compatible,
399
- policy,
400
- scope: { contract: current.contract, majorLine: current.majorLine },
401
- acceptedContractDigest: accepted.contractDigest,
402
- acceptedCompatibilityDigest: accepted.compatibilityDigest,
403
- acceptedProofRegistryRoot: accepted.compatibilityProofRegistryRoot,
404
- currentContractDigest: current.contractDigest,
405
- currentCompatibilityDigest: current.compatibilityDigest,
406
- currentProofRegistryRoot: current.compatibilityProofRegistryRoot,
407
- decisions,
408
- reasonCodes: reasons,
409
- });
410
- }
411
-
412
- function contractPolicyReasons(accepted, current, policy) {
413
- const reasons = [];
414
- if (accepted.contract !== current.contract) reasons.push(`contract changed from ${accepted.contract || "(unknown)"} to ${current.contract}`);
415
- if (accepted.majorLine && accepted.majorLine !== current.majorLine) reasons.push(`major line changed from ${accepted.majorLine} to ${current.majorLine}`);
416
- if (policy === "exact" && accepted.contractDigest !== current.contractDigest) reasons.push("exact policy requires the contract digest to remain unchanged");
417
- if (!["major-compatible", "allow-additive", "exact"].includes(policy)) reasons.push(`unsupported compatibility policy: ${policy}`);
418
- return reasons;
419
- }
420
-
421
- function evaluateSurfaceRelation({ oldSurface, nextSurface, proofRegistry, majorLine }) {
422
- if (!nextSurface) {
423
- return {
424
- reason: `surface removed: ${oldSurface.id}`,
425
- decision: { surfaceId: oldSurface.id, status: "surface-removed", sourceBreakingDigest: oldSurface.breakingDigest, targetBreakingDigest: "", reason: "surface-removed" },
426
- };
427
- }
428
- if (nextSurface.breakingDigest === oldSurface.breakingDigest) return {};
429
- const resolution = resolveBuildchainCompatibilityProof({
430
- registry: proofRegistry,
431
- surface: nextSurface,
432
- sourceBreakingDigest: oldSurface.breakingDigest,
433
- majorLine,
434
- });
435
- if (!resolution.ok) {
436
- return {
437
- reason: `surface breaking digest changed without a valid compatibility proof: ${oldSurface.id} (${resolution.reason})`,
438
- decision: { surfaceId: oldSurface.id, status: "rejected", sourceBreakingDigest: oldSurface.breakingDigest, targetBreakingDigest: nextSurface.breakingDigest, reason: resolution.reason },
439
- };
440
- }
441
- const proof = resolution.proof;
442
- return {
443
- decision: {
444
- surfaceId: oldSurface.id,
445
- status: "accepted",
446
- sourceBreakingDigest: oldSurface.breakingDigest,
447
- targetBreakingDigest: nextSurface.breakingDigest,
448
- proofRoot: proof.proofRoot,
449
- direction: proof.direction,
450
- operation: proof.operation,
451
- scope: proof.scope,
452
- scopeRoot: proof.scopeRoot,
453
- evidence: proof.evidence,
454
- evidenceRoot: proof.evidenceRoot,
455
- authority: proof.authority,
456
- authorityRoot: proof.authorityRoot,
457
- cut: proof.cut,
458
- cutRoot: proof.cutRoot,
459
- },
460
- };
461
- }
462
-
463
- function evaluateChannelBinding({ lock, workflowShellRef, runtimeRef, expectedChannel, expectedMajor, allowOpaqueRuntime }) {
464
- if (!workflowShellRef && !expectedChannel && !expectedMajor) return null;
465
- return evaluateBuildchainChannelBinding({
466
- workflowShellRef,
467
- runtimeRef,
468
- lockRef: lock?.buildchain?.ref || "",
469
- lockMajorLine: lock?.buildchain?.majorLine || "",
470
- expectedChannel,
471
- expectedMajor,
472
- allowOpaqueRuntime,
473
- });
474
- }
475
-
476
- export function evaluateBuildchainContractLock({
477
- lock,
478
- current,
479
- runtimeRef = "",
480
- runtimeSha = "",
481
- runtimeClass = "",
482
- compatibilityPolicy = "",
483
- workflowShellRef = "",
484
- expectedChannel = "",
485
- expectedMajor = "",
486
- allowOpaqueRuntime = false,
487
- } = {}) {
488
- if (!current || current.contract !== BUILDCHAIN_CONTRACT) {
489
- throw new Error("current must be a Buildchain runtime contract world");
490
- }
491
- assertBuildchainCompatibilityProjection(current);
492
- const binding = evaluateChannelBinding({
493
- lock, workflowShellRef, runtimeRef, expectedChannel, expectedMajor, allowOpaqueRuntime,
494
- });
495
- if (binding?.ok === false) {
496
- return {
497
- ok: false,
498
- status: binding.status,
499
- drift: false,
500
- compatible: false,
501
- issueRecommended: false,
502
- reasons: binding.reasons,
503
- channelBinding: binding,
504
- };
505
- }
506
- if (!new Set(["stable", "alpha"]).has(runtimeClass)) {
507
- return {
508
- ok: true,
509
- status: "non-floating-runtime",
510
- drift: false,
511
- compatible: true,
512
- issueRecommended: false,
513
- reason: `runtime class ${runtimeClass || "unknown"} is not a stable floating ref`,
514
- };
515
- }
516
- if (!lock) {
517
- return {
518
- ok: true,
519
- status: "missing-lock",
520
- drift: false,
521
- compatible: true,
522
- issueRecommended: false,
523
- reason: "consumer repository has no Buildchain contract lock",
524
- };
525
- }
526
- const accepted = lock.buildchain || {};
527
- const policy = compatibilityPolicy || accepted.compatibilityPolicy || "major-compatible";
528
- const shaDrift = !!accepted.resolvedSha && !!runtimeSha && accepted.resolvedSha !== runtimeSha;
529
- const contractDrift = !!accepted.contractDigest && accepted.contractDigest !== current.contractDigest;
530
- if (!shaDrift && !contractDrift) {
531
- const verificationReceipt = evaluationReceipt({ status: "unchanged", compatible: true, policy, accepted, current });
532
- return {
533
- ok: true,
534
- status: "unchanged",
535
- drift: false,
536
- compatible: true,
537
- issueRecommended: false,
538
- policy,
539
- accepted,
540
- current: contractSummary(current, runtimeRef, runtimeSha),
541
- compatibilityDecisions: [],
542
- usedProofRoots: [],
543
- verificationReceipt,
544
- receiptRoot: verificationReceipt.receiptRoot,
545
- };
546
- }
547
- const reasons = contractPolicyReasons(accepted, current, policy);
548
- const compatibilityDecisions = [];
549
- const currentSurfaces = new Map(current.surfaces.map((entry) => [entry.id, entry]));
550
- const proofRegistry = createBuildchainCompatibilityProofRegistry({
551
- proofs: current.compatibilityProofs,
552
- surfaces: current.surfaces,
553
- majorLine: current.majorLine,
554
- });
555
- for (const oldSurface of accepted.surfaces || []) {
556
- const result = evaluateSurfaceRelation({
557
- oldSurface,
558
- nextSurface: currentSurfaces.get(oldSurface.id),
559
- proofRegistry,
560
- majorLine: current.majorLine,
561
- });
562
- if (result.reason) reasons.push(result.reason);
563
- if (result.decision) compatibilityDecisions.push(result.decision);
564
- }
565
- const compatible = reasons.length === 0;
566
- const status = compatible ? "compatible-drift" : "breaking-drift";
567
- const verificationReceipt = evaluationReceipt({ status, compatible, policy, accepted, current, decisions: compatibilityDecisions, reasons });
568
- return {
569
- ok: compatible,
570
- status,
571
- drift: shaDrift || contractDrift,
572
- shaDrift,
573
- contractDrift,
574
- compatible,
575
- issueRecommended: true,
576
- policy,
577
- reasons,
578
- accepted,
579
- current: contractSummary(current, runtimeRef, runtimeSha),
580
- compatibilityDecisions,
581
- usedProofRoots: verificationReceipt.usedProofRoots,
582
- verificationReceipt,
583
- receiptRoot: verificationReceipt.receiptRoot,
584
- };
585
- }
586
-
587
- function shown(value, fallback = "(unknown)") {
588
- return value ? value : fallback;
589
- }
590
-
591
- function renderCompatibilityDecision(decision) {
592
- const lines = [
593
- `- Surface \`${decision.surfaceId}\`: ${decision.status}`,
594
- ` - Relation: \`${shown(decision.sourceBreakingDigest, "(missing)")}\` -> \`${shown(decision.targetBreakingDigest, "(missing)")}\``,
595
- ` - Reason: \`${shown(decision.reason, "proof-backed-compatible-relation")}\``,
596
- ];
597
- if (!decision.proofRoot) return lines.join("\n");
598
- lines.push(
599
- ` - Proof root: \`${decision.proofRoot}\``,
600
- ` - Direction / operation: \`${decision.direction}\` / \`${decision.operation}\``,
601
- ` - Scope root: \`${decision.scopeRoot}\``,
602
- ` - Evidence: ${shown(decision.evidence && decision.evidence.pullRequest)} (\`${decision.evidenceRoot}\`)`,
603
- ` - Authority: \`${shown(decision.authority && decision.authority.repository)}@${shown(decision.authority && decision.authority.protectedBase)}\` (\`${decision.authorityRoot}\`)`,
604
- ` - Cut: \`${shown(decision.cut && decision.cut.commit)}\` (\`${decision.cutRoot}\`)`,
605
- );
606
- return lines.join("\n");
607
- }
608
-
609
- function renderCompatibilityDecisions(decisions) {
610
- if (decisions.length === 0) return "- No breaking-digest relation required proof resolution.";
611
- return decisions.map(renderCompatibilityDecision).join("\n");
612
- }
613
-
614
- export function renderBuildchainContractDriftIssueBody({ repository = "", workflow = "", runUrl = "", lockPath = "", evaluation } = {}) {
615
- const accepted = evaluation.accepted || {};
616
- const current = evaluation.current || {};
617
- const decisions = evaluation.compatibilityDecisions || [];
618
- const renderedDecisions = renderCompatibilityDecisions(decisions);
619
- return [
620
- "# Buildchain contract drift", "", "## Summary", "",
621
- `Buildchain detected ${evaluation.compatible ? "compatible" : "breaking"} contract drift for a floating runtime ref before expensive Buildchain work continued.`,
622
- "", "## Consumer", "", `- Repository: ${shown(repository)}`, `- Workflow: ${shown(workflow)}`, `- Run: ${shown(runUrl)}`, `- Lock path: ${shown(lockPath)}`,
623
- "", "## Accepted Buildchain contract", "", `- Ref: ${shown(accepted.ref)}`, `- SHA: ${shown(accepted.resolvedSha)}`, `- Contract digest: ${shown(accepted.contractDigest)}`, `- Compatibility digest: ${shown(accepted.compatibilityDigest)}`, `- Compatibility proof registry: ${shown(accepted.compatibilityProofRegistryRoot, "(legacy lock without proof registry)")}`, `- Policy: ${shown(evaluation.policy || accepted.compatibilityPolicy)}`,
624
- "", "## Current Buildchain contract", "", `- Ref: ${shown(current.ref)}`, `- SHA: ${shown(current.resolvedSha)}`, `- Contract digest: ${shown(current.contractDigest)}`, `- Compatibility digest: ${shown(current.compatibilityDigest)}`, `- Compatibility proof registry: ${shown(current.compatibilityProofRegistryRoot)}`, `- Major line: ${shown(current.majorLine)}`,
625
- "", "## Compatibility", "", `- Status: ${shown(evaluation.status)}`, `- Compatible: ${evaluation.compatible ? "yes" : "no"}`, evaluation.reasons && evaluation.reasons.length ? evaluation.reasons.map((reason) => `- ${reason}`).join("\n") : "- No breaking drift detected.",
626
- "", "## Proof-backed decisions", "", renderedDecisions, `- Verification receipt: \`${shown(evaluation.receiptRoot, "(not produced)")}\``,
627
- "", "## Suggested next action", "", evaluation.compatible
628
- ? "Review the Buildchain release notes, then update the consumer contract lock to the current SHA and contract digest."
629
- : "Failing before heavy build is intentional. Review the Buildchain contract change, update the consumer workflow/configuration, or pin the previous Buildchain SHA.",
630
- ].join("\n");
631
- }