@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
@@ -97,14 +97,6 @@ export function decideChannelCandidate(input) {
97
97
  const sourceSha = sha(input.sourceSha, "sourceSha");
98
98
  const targetSha = sha(input.targetSha, "targetSha");
99
99
  const selection = normalizeChannelCandidateSelection(input.selection);
100
- if (
101
- selection?.versionReservation &&
102
- selection.versionReservation.candidateSha !== sourceSha
103
- ) {
104
- throw new Error(
105
- "selection version reservation must bind the selected source SHA",
106
- );
107
- }
108
100
  const now = required(input.now || new Date().toISOString(), "now");
109
101
  const maxAgeSeconds = Number(input.maxAgeSeconds ?? 7 * 24 * 60 * 60);
110
102
  if (!Number.isSafeInteger(maxAgeSeconds) || maxAgeSeconds <= 0) {
@@ -1,10 +1,5 @@
1
1
  // SPDX-License-Identifier: Apache-2.0
2
2
 
3
- import {
4
- nextDevelopmentPatrolContext,
5
- normalizeNextDevelopmentVersionReservation,
6
- } from "./next-development-candidate-reservation.js";
7
-
8
3
  const SHA = /^[0-9a-f]{40}$/;
9
4
 
10
5
  function text(value = "") {
@@ -64,18 +59,6 @@ export function normalizeChannelCandidateSelection(input) {
64
59
  ),
65
60
  }
66
61
  : {}),
67
- ...(input.versionReservation
68
- ? {
69
- versionReservation: normalizeNextDevelopmentVersionReservation(
70
- input.versionReservation,
71
- {
72
- reservationSha: input.versionReservation.reservationSha,
73
- candidateSha: input.versionReservation.candidateSha,
74
- targetVersion: input.versionReservation.targetVersion,
75
- },
76
- ),
77
- }
78
- : {}),
79
62
  };
80
63
  }
81
64
 
@@ -134,7 +117,6 @@ export async function resolvePatrolSourceInputs({
134
117
  let comparison = headComparison;
135
118
  let workflowEvidence = [];
136
119
  let skippedNewerCommitCount = 0;
137
- let versionReservation;
138
120
  let qualificationError;
139
121
  if (
140
122
  headComparison.status === "ahead" &&
@@ -148,8 +130,6 @@ export async function resolvePatrolSourceInputs({
148
130
  ),
149
131
  ]);
150
132
  try {
151
- const { preparations, ignoredSourceShas } =
152
- nextDevelopmentPatrolContext(sourceHistory);
153
133
  const selected = selectQualifiedSource({
154
134
  sourceHistory,
155
135
  workflowRunsByPath: new Map(
@@ -161,39 +141,8 @@ export async function resolvePatrolSourceInputs({
161
141
  requiredWorkflowPaths,
162
142
  now: options.now,
163
143
  maxAgeSeconds: options.maxAgeSeconds,
164
- ignoredSourceShas,
165
144
  });
166
145
  ({ sourceSha, skippedNewerCommitCount, workflowEvidence } = selected);
167
- const selectedIndex = sourceHistory.findIndex((entry) =>
168
- (typeof entry === "string" ? entry : entry?.sha) === sourceSha,
169
- );
170
- const reservation = preparations.find(
171
- ({ index }) => index > selectedIndex,
172
- )?.preparation;
173
- if (reservation) {
174
- if (typeof client.readNextDevelopmentVersionReservation !== "function") {
175
- throw new Error(
176
- "candidate follows next-development preparation but reservation readback is unavailable",
177
- );
178
- }
179
- versionReservation = normalizeNextDevelopmentVersionReservation(
180
- await client.readNextDevelopmentVersionReservation({
181
- reservationSha: reservation.sha,
182
- candidateSha: sourceSha,
183
- targetVersion: reservation.targetVersion,
184
- }),
185
- {
186
- reservationSha: reservation.sha,
187
- candidateSha: sourceSha,
188
- targetVersion: reservation.targetVersion,
189
- },
190
- );
191
- if (versionReservation.status !== "current") {
192
- throw new Error(
193
- `next-development version reservation is ${versionReservation.status} for candidate ${sourceSha}`,
194
- );
195
- }
196
- }
197
146
  if (sourceSha !== observedSourceHeadSha)
198
147
  comparison = await client.compare(boundarySha, sourceSha);
199
148
  } catch (error) {
@@ -209,7 +158,6 @@ export async function resolvePatrolSourceInputs({
209
158
  comparison,
210
159
  workflowEvidence,
211
160
  skippedNewerCommitCount,
212
- versionReservation,
213
161
  qualificationError,
214
162
  };
215
163
  }
@@ -34,14 +34,13 @@ const CONTROLLER_SPECS = [
34
34
  "resolve-runtime",
35
35
  "resolve-source",
36
36
  "anchored-release-preflight",
37
- "pre-build-contracts",
38
37
  "build",
39
38
  "signing-finalization",
40
39
  "credential-island",
41
40
  "verify",
42
41
  "aggregate",
43
42
  ],
44
- optionalStages: ["anchored-release-preflight", "pre-build-contracts", "credential-island"],
43
+ optionalStages: ["anchored-release-preflight", "credential-island"],
45
44
  evidence: [
46
45
  "platform-manifests",
47
46
  "build-summary",
@@ -53,8 +52,8 @@ const CONTROLLER_SPECS = [
53
52
  workflowId: "build",
54
53
  version: 1,
55
54
  capabilities: ["channel-selection", "runtime-selection", "build-delegation"],
56
- stages: ["resolve-channel", "alpha", "stable", "aggregate"],
57
- optionalStages: ["alpha", "stable"],
55
+ stages: ["resolve-channel", "override", "alpha", "stable", "aggregate"],
56
+ optionalStages: ["override", "alpha", "stable"],
58
57
  evidence: ["nested-controller-receipt", "controller-receipt"],
59
58
  },
60
59
  {
@@ -82,9 +82,7 @@ export function selectLatestQualifiedSource({
82
82
  requiredWorkflowPaths,
83
83
  now,
84
84
  maxAgeSeconds,
85
- ignoredSourceShas = [],
86
85
  }) {
87
- const ignored = new Set(ignoredSourceShas);
88
86
  const latestByPath = new Map(
89
87
  requiredWorkflowPaths.map((workflow) => [
90
88
  workflow,
@@ -92,11 +90,7 @@ export function selectLatestQualifiedSource({
92
90
  ]),
93
91
  );
94
92
  for (let index = 0; index < sourceHistory.length; index += 1) {
95
- const sourceSha =
96
- typeof sourceHistory[index] === "string"
97
- ? sourceHistory[index]
98
- : sourceHistory[index]?.sha;
99
- if (ignored.has(sourceSha)) continue;
93
+ const sourceSha = sourceHistory[index];
100
94
  const rows = requiredWorkflowPaths.map((workflow) =>
101
95
  latestByPath.get(workflow).get(sourceSha),
102
96
  );
@@ -121,9 +115,7 @@ export function selectLatestQualifiedSource({
121
115
  };
122
116
  }
123
117
  }
124
- const staleSuccessfulPair = sourceHistory.some((entry) => {
125
- const sourceSha = typeof entry === "string" ? entry : entry?.sha;
126
- if (ignored.has(sourceSha)) return false;
118
+ const staleSuccessfulPair = sourceHistory.some((sourceSha) => {
127
119
  const rows = requiredWorkflowPaths.map((workflow) =>
128
120
  latestByPath.get(workflow).get(sourceSha),
129
121
  );
@@ -6,7 +6,6 @@ const TERMINAL_STATES = new Set(["merged", "terminal-failure", "dequeued", "canc
6
6
  const QUEUED_CANCELLATION_EVENTS = new Map([
7
7
  ["closed", "cancelled"],
8
8
  ["cancelled", "cancelled"],
9
- ["synchronize", "cancelled"],
10
9
  ["dequeued", "dequeued"],
11
10
  ]);
12
11
 
@@ -33,11 +33,7 @@ export function createDevDeliveryTerminalSettler({ normalizeQueue, closeWarrant,
33
33
  };
34
34
  if (!terminalStates.has(identity.outcome)) throw new Error(`outcome must be one of ${[...terminalStates].join(", ")}`);
35
35
  const samePullRequest = queue.candidates.filter((entry) => entry.pullRequestNumber === identity.pullRequestNumber);
36
- const matchingHead = samePullRequest.filter((entry) => entry.sourceHead === identity.sourceHead);
37
- const activeCandidate = queue.activeWarrant
38
- ? matchingHead.find((entry) => entry.candidateId === queue.activeWarrant.candidateId)
39
- : null;
40
- const candidate = activeCandidate || matchingHead.at(-1) || null;
36
+ const candidate = samePullRequest.find((entry) => entry.sourceHead === identity.sourceHead) || null;
41
37
  if (!candidate && samePullRequest.length > 0) throw new Error("terminal event sourceHead does not match the recorded candidate");
42
38
 
43
39
  if (candidate && terminalStates.has(candidate.status)) {
@@ -2,12 +2,10 @@ import { devDeliveryClone as clone, devDeliveryContentRoot, devDeliveryExactRoot
2
2
  import { chainedDevDeliveryAttemptInput, createDevDeliveryCandidateIdentity, validateDevDeliveryCandidateChain } from "./dev-delivery-candidate-identity.js";
3
3
  import { DEV_DELIVERY_CANCELLATION_RECEIPT_SCHEMA, createCancelQueuedDevDeliveryCandidate } from "./dev-delivery-warrant-cancellation.js";
4
4
  import { DEV_DELIVERY_SETTLEMENT_RECEIPT_SCHEMA, createDevDeliveryTerminalSettler } from "./dev-delivery-warrant-settlement.js";
5
- import { createDevDeliveryWarrantQualifier } from "./dev-delivery-native-proof.js";
6
5
  import { compareReleaseBlockerPriority, normalizeReleaseBlockerPriorityClaim } from "./release-blocker-priority.js";
7
6
  export { devDeliveryContentRoot } from "./dev-delivery-common.js";
8
7
  export { RELEASE_BLOCKER_PRIORITY_CLAIM_SCHEMA, createReleaseBlockerPriorityClaim } from "./release-blocker-priority.js";
9
8
  export { SOURCE_QUALIFICATION_PROOF_SCHEMA, PROJECT_CUT_REPLAY_PROOF_SCHEMA, INTEGRATION_DELIVERY_PROOF_SCHEMA, classifyDevDeliveryDelta, createIntegrationDeliveryProof, createProjectCutReplayPlan, createProjectCutReplayProof, createSourceQualificationProof, verifyIntegrationDeliveryProof, verifyProjectCutReplayProof, verifySourceQualificationProof } from "./dev-delivery-proof.js";
10
- export { DEV_DELIVERY_QUALIFICATION_RECEIPT_SCHEMA, NATIVE_QUALIFICATION_PROOF_SCHEMA, NATIVE_PROOF_REUSE_DECISION_SCHEMA, createNativeProofReuseDecision, createNativeQualificationProof, verifyNativeProofReuseDecision, verifyNativeQualificationProof } from "./dev-delivery-native-proof.js";
11
9
  export { DEV_DELIVERY_CANCELLATION_RECEIPT_SCHEMA };
12
10
  export const DEV_DELIVERY_QUEUE_CONTRACT = "kungfu-buildchain-dev-delivery-warrant-queue";
13
11
  export const DEV_DELIVERY_WARRANT_SCHEMA = "kungfu.buildchain.dev-delivery-warrant/v1";
@@ -61,7 +59,7 @@ function normalizeCandidate(input, expected) {
61
59
  throw new Error(`candidateId mismatch for PR #${identity.pullRequestNumber}`);
62
60
  }
63
61
  const status = text(input.status || "queued");
64
- if (!["queued", "selected", "provisional", "proving", "qualified", "waiting", "blocked", ...TERMINAL_STATES].includes(status)) {
62
+ if (!["queued", "selected", "proving", "waiting", "blocked", ...TERMINAL_STATES].includes(status)) {
65
63
  throw new Error(`unsupported candidate status ${status || "<empty>"}`);
66
64
  }
67
65
  const candidate = {
@@ -73,7 +71,6 @@ function normalizeCandidate(input, expected) {
73
71
  closureRoot: exactRoot(input.closureRoot, "closureRoot"),
74
72
  dependencyRoot: exactRoot(input.dependencyRoot, "dependencyRoot"),
75
73
  toolchainRoot: exactRoot(input.toolchainRoot, "toolchainRoot"),
76
- ...(Object.hasOwn(input, "sourceWorkflowRunId") ? { sourceWorkflowRunId: nonNegativeInteger(input.sourceWorkflowRunId, "candidate sourceWorkflowRunId", 0) } : {}),
77
74
  priority: priority(input.priority),
78
75
  enqueuedAt: timestamp(input.enqueuedAt, "candidate enqueuedAt"),
79
76
  updatedAt: timestamp(input.updatedAt || input.enqueuedAt, "candidate updatedAt"),
@@ -82,10 +79,6 @@ function normalizeCandidate(input, expected) {
82
79
  status,
83
80
  terminal: input.terminal || null,
84
81
  };
85
- if (Object.hasOwn(input, "affectedPaths")) {
86
- if (!Array.isArray(input.affectedPaths)) throw new Error("candidate affectedPaths must be an array");
87
- candidate.affectedPaths = [...new Set(input.affectedPaths.map(text).filter(Boolean))].sort();
88
- }
89
82
  if (Object.hasOwn(input, "releaseBlockerPriority")) candidate.releaseBlockerPriority = normalizeReleaseBlockerPriorityClaim(input.releaseBlockerPriority, candidate, expected);
90
83
  return candidate;
91
84
  }
@@ -146,20 +139,12 @@ export function normalizeDevDeliveryQueue(input, expected = {}) {
146
139
  warrant.generation = positiveInteger(warrant.generation, "Warrant generation");
147
140
  warrant.issuedAt = timestamp(warrant.issuedAt, "Warrant issuedAt");
148
141
  warrant.expiresAt = timestamp(warrant.expiresAt, "Warrant expiresAt");
149
- const warrantPhase = text(warrant.phase || "qualified");
150
- if (!["provisional", "qualified"].includes(warrantPhase)) throw new Error("active Warrant phase is unsupported");
151
- if (Object.hasOwn(warrant, "phase")) warrant.phase = warrantPhase;
152
- if (warrantPhase === "qualified") {
153
- if (warrant.nativeProofRoot) warrant.nativeProofRoot = exactRoot(warrant.nativeProofRoot, "Warrant nativeProofRoot");
154
- if (warrant.nativeProofReuseRoot) warrant.nativeProofReuseRoot = exactRoot(warrant.nativeProofReuseRoot, "Warrant nativeProofReuseRoot");
155
- if (warrant.qualifiedAt) warrant.qualifiedAt = timestamp(warrant.qualifiedAt, "Warrant qualifiedAt");
156
- }
157
- const activeCandidates = queue.candidates.filter((candidate) => ["selected", "provisional", "proving", "qualified", "waiting", "blocked"].includes(candidate.status));
142
+ const activeCandidates = queue.candidates.filter((candidate) => ["selected", "proving", "waiting", "blocked"].includes(candidate.status));
158
143
  if (activeCandidates.length !== 1 || activeCandidates[0].candidateId !== warrant.candidateId) {
159
144
  throw new Error("exactly one active candidate must match the active Warrant");
160
145
  }
161
146
  if (warrant.releaseBlockerPriority?.claimRoot !== activeCandidates[0].releaseBlockerPriority?.claimRoot) throw new Error("active Warrant release-blocker priority drift");
162
- } else if (queue.candidates.some((candidate) => ["selected", "provisional", "proving", "qualified", "waiting", "blocked"].includes(candidate.status))) {
147
+ } else if (queue.candidates.some((candidate) => ["selected", "proving", "waiting", "blocked"].includes(candidate.status))) {
163
148
  throw new Error("active candidate exists without an active Warrant");
164
149
  }
165
150
  const rooted = withQueueRoot(queue);
@@ -198,7 +183,6 @@ function submissionReceipt({ before, after, candidate, action, now }) {
198
183
  closureRoot: candidate.closureRoot,
199
184
  dependencyRoot: candidate.dependencyRoot,
200
185
  toolchainRoot: candidate.toolchainRoot,
201
- ...(Object.hasOwn(candidate, "affectedPaths") ? { affectedPaths: candidate.affectedPaths } : {}),
202
186
  sourceWorkflowRunId: candidate.sourceWorkflowRunId,
203
187
  ...(Object.hasOwn(candidate, "releaseBlockerPriority") ? { releaseBlockerPriority: candidate.releaseBlockerPriority } : {}),
204
188
  deliveryClass: candidate.deliveryClass,
@@ -240,24 +224,17 @@ export function submitDevDeliveryCandidate(queueInput, input, { now = new Date()
240
224
  throw new Error(`candidate ${attemptedCandidate.candidateId} is terminal and cannot be resubmitted`);
241
225
  }
242
226
  const exactProofFields = ["sourcePatchRoot", "sourceProofRoot", "planRoot", "closureRoot", "dependencyRoot", "toolchainRoot"];
243
- const exactProofMatches = exactProofFields.every((field) => existing[field] === attemptedCandidate[field]) && JSON.stringify(existing.affectedPaths || []) === JSON.stringify(attemptedCandidate.affectedPaths || []) && existing.releaseBlockerPriority?.claimRoot === attemptedCandidate.releaseBlockerPriority?.claimRoot;
227
+ const exactProofMatches = exactProofFields.every((field) => existing[field] === attemptedCandidate[field]) && existing.releaseBlockerPriority?.claimRoot === attemptedCandidate.releaseBlockerPriority?.claimRoot;
244
228
  if (existing.sourceHead === attemptedCandidate.sourceHead && exactProofMatches) {
245
229
  action = "duplicate-noop";
246
230
  selected = existing;
247
231
  } else {
248
232
  if (before.activeWarrant?.candidateId === existing.candidateId) {
249
- if (existing.sourceHead !== attemptedCandidate.sourceHead) {
250
- throw new Error("selected candidate sourceHead cannot change before terminal Warrant closeout");
251
- }
252
- action = "active-warrant-retained-noop";
253
- selected = existing;
254
- return { candidate: selected, action };
233
+ throw new Error("selected candidate sourceHead cannot change before terminal Warrant closeout");
255
234
  }
256
235
  const headChanged = existing.sourceHead !== attemptedCandidate.sourceHead;
257
236
  existing.sourceHead = attemptedCandidate.sourceHead;
258
237
  for (const field of exactProofFields) existing[field] = attemptedCandidate[field];
259
- if (Object.hasOwn(attemptedCandidate, "affectedPaths")) existing.affectedPaths = attemptedCandidate.affectedPaths;
260
- else delete existing.affectedPaths;
261
238
  if (Object.hasOwn(attemptedCandidate, "releaseBlockerPriority")) existing.releaseBlockerPriority = attemptedCandidate.releaseBlockerPriority;
262
239
  else delete existing.releaseBlockerPriority;
263
240
  existing.updatedAt = currentTime;
@@ -342,7 +319,7 @@ export function selectDevDeliveryWarrant(queueInput, { now = new Date().toISOStr
342
319
  candidateId: queue.activeWarrant.candidateId,
343
320
  fencingToken: queue.activeWarrant.fencingToken,
344
321
  leaseGeneration: queue.activeWarrant.generation,
345
- expectedOldStateRoot: recoveryReceipt?.expectedOldStateRoot || queue.stateRoot,
322
+ expectedOldStateRoot: queue.stateRoot,
346
323
  nextStateRoot: queue.stateRoot,
347
324
  nextAction: "Continue the active delivery attempt; later candidates remain visibly queued.",
348
325
  };
@@ -396,17 +373,15 @@ export function selectDevDeliveryWarrant(queueInput, { now = new Date().toISOStr
396
373
  closureRoot: candidate.closureRoot,
397
374
  dependencyRoot: candidate.dependencyRoot,
398
375
  toolchainRoot: candidate.toolchainRoot,
399
- ...(Object.hasOwn(candidate, "affectedPaths") ? { affectedPaths: candidate.affectedPaths } : {}),
400
376
  sourceWorkflowRunId: candidate.sourceWorkflowRunId,
401
377
  ...(Object.hasOwn(candidate, "releaseBlockerPriority") ? { releaseBlockerPriority: candidate.releaseBlockerPriority } : {}),
402
378
  deliveryClass: candidate.deliveryClass,
403
379
  generation: next.fencingCounter,
404
- phase: "provisional",
405
380
  expectedOldStateRoot: before.stateRoot,
406
381
  issuedAt,
407
382
  expiresAt: new Date(Date.parse(issuedAt) + effectiveLeaseSeconds * 1000).toISOString(),
408
383
  fencingToken: "",
409
- nextAction: "Run or reuse the exact semantic native proof, then atomically qualify this fenced Warrant.",
384
+ nextAction: "Replay on the exact current dev base, prove required checks, then enqueue the unchanged PR head.",
410
385
  };
411
386
  warrant.fencingToken = warrantToken(warrant);
412
387
  next.activeWarrant = warrant;
@@ -443,7 +418,7 @@ export function selectDevDeliveryWarrant(queueInput, { now = new Date().toISOStr
443
418
  effectivePriority: selected.priority.score,
444
419
  fencingToken: transaction.result.warrant.fencingToken,
445
420
  leaseGeneration: transaction.result.warrant.generation,
446
- expectedOldStateRoot: recoveryReceipt?.expectedOldStateRoot || transaction.expectedOldStateRoot,
421
+ expectedOldStateRoot: transaction.expectedOldStateRoot,
447
422
  nextStateRoot: transaction.after.stateRoot,
448
423
  nextAction: transaction.result.warrant.nextAction,
449
424
  };
@@ -456,12 +431,12 @@ export function selectDevDeliveryWarrant(queueInput, { now = new Date().toISOStr
456
431
  };
457
432
  }
458
433
 
459
- function assertWarrantMutation(queue, warrant, now, { allowExpired = false } = {}) {
434
+ function assertWarrantMutation(queue, warrant, now) {
460
435
  if (!queue.activeWarrant) throw new Error("no active Delivery Warrant");
461
436
  if (text(warrant?.fencingToken) !== queue.activeWarrant.fencingToken) throw new Error("stale fencing token");
462
437
  if (Number(warrant?.generation) !== queue.activeWarrant.generation) throw new Error("stale lease generation");
463
438
  if (text(warrant?.candidateId) !== queue.activeWarrant.candidateId) throw new Error("Warrant candidate mismatch");
464
- if (!allowExpired && Date.parse(queue.activeWarrant.expiresAt) <= Date.parse(now)) throw new Error("Delivery Warrant lease expired");
439
+ if (Date.parse(queue.activeWarrant.expiresAt) <= Date.parse(now)) throw new Error("Delivery Warrant lease expired");
465
440
  }
466
441
 
467
442
  export function heartbeatDevDeliveryWarrant(queueInput, warrant, { now = new Date().toISOString(), leaseSeconds } = {}) {
@@ -473,7 +448,7 @@ export function heartbeatDevDeliveryWarrant(queueInput, warrant, { now = new Dat
473
448
  const effectiveLeaseSeconds = positiveInteger(leaseSeconds, "leaseSeconds", queue.policy.leaseSeconds);
474
449
  queue.activeWarrant.expiresAt = new Date(Date.parse(currentTime) + effectiveLeaseSeconds * 1000).toISOString();
475
450
  const candidate = queue.candidates.find((entry) => entry.candidateId === queue.activeWarrant.candidateId);
476
- candidate.status = queue.activeWarrant.phase === "qualified" ? "qualified" : "proving";
451
+ candidate.status = "proving";
477
452
  candidate.updatedAt = currentTime;
478
453
  return { candidate, warrant: queue.activeWarrant };
479
454
  },
@@ -497,8 +472,6 @@ export function heartbeatDevDeliveryWarrant(queueInput, warrant, { now = new Dat
497
472
  };
498
473
  }
499
474
 
500
- const qualifyDevDeliveryWarrantTransition = createDevDeliveryWarrantQualifier({ transition, assertWarrantMutation });
501
- export function qualifyDevDeliveryWarrant(queueInput, warrant, options) { return qualifyDevDeliveryWarrantTransition(queueInput, warrant, options); }
502
475
  export function recoverExpiredDevDeliveryWarrant(queueInput, { now = new Date().toISOString() } = {}) {
503
476
  const currentTime = timestamp(now, "now");
504
477
  const before = normalizeDevDeliveryQueue(queueInput);
@@ -558,7 +531,7 @@ export function closeDevDeliveryWarrant(queueInput, warrant, { outcome, evidence
558
531
  const transaction = transition(
559
532
  queueInput,
560
533
  (queue, before) => {
561
- assertWarrantMutation(before, warrant, currentTime, { allowExpired: true });
534
+ assertWarrantMutation(before, warrant, currentTime);
562
535
  const active = clone(queue.activeWarrant);
563
536
  const candidate = queue.candidates.find((entry) => entry.candidateId === active.candidateId);
564
537
  candidate.status = normalizedOutcome;
@@ -625,19 +598,6 @@ export function observeDevDeliveryQueue(queueInput, { now = new Date().toISOStri
625
598
  queueAgeSeconds: entry.priority.ageSeconds,
626
599
  attempts: entry.candidate.attempts,
627
600
  recoveries: entry.candidate.recoveries,
628
- assignmentRoot: entry.candidate.assignmentRoot,
629
- initiativeRoot: entry.candidate.initiativeRoot,
630
- sourceIdentityRoot: entry.candidate.sourceIdentityRoot,
631
- sourcePatchRoot: entry.candidate.sourcePatchRoot,
632
- sourceProofRoot: entry.candidate.sourceProofRoot,
633
- planRoot: entry.candidate.planRoot,
634
- closureRoot: entry.candidate.closureRoot,
635
- dependencyRoot: entry.candidate.dependencyRoot,
636
- toolchainRoot: entry.candidate.toolchainRoot,
637
- sourceWorkflowRunId: entry.candidate.sourceWorkflowRunId || 0,
638
- affectedPaths: entry.candidate.affectedPaths || [],
639
- deliveryClass: entry.candidate.deliveryClass,
640
- priority: entry.candidate.priority,
641
601
  nextAction: index === 0 && !queue.activeWarrant ? "eligible-for-selection" : "wait-for-active-warrant",
642
602
  })),
643
603
  observedAt: currentTime,
@@ -84,14 +84,10 @@ function fileStats(cwd, entries = []) {
84
84
  });
85
85
  }
86
86
 
87
- const TOOL_VERSION_PROBE_CWD = path.parse(process.execPath).root;
88
-
89
- function commandVersion(command, args = ["--version"]) {
87
+ function commandVersion(command, args = ["--version"], cwd = process.cwd()) {
90
88
  try {
91
89
  return execFileSync(command, args, {
92
- // Package managers may walk every parent even for --version. Keep this
93
- // bounded instead of scanning an arbitrary consumer or shared temp root.
94
- cwd: TOOL_VERSION_PROBE_CWD,
90
+ cwd,
95
91
  encoding: "utf8",
96
92
  stdio: ["ignore", "pipe", "ignore"],
97
93
  timeout: 5000,
@@ -497,8 +493,7 @@ export function collectRunnerDiagnostics() {
497
493
  }
498
494
 
499
495
  export function collectToolDiagnostics({ cwd = process.cwd(), tools = ["node", "pnpm", "npm", "git", "cmake", "ninja", "ccache", "sccache"] } = {}) {
500
- void cwd;
501
- return Object.fromEntries(tools.map((tool) => [tool, { version: commandVersion(tool) }]));
496
+ return Object.fromEntries(tools.map((tool) => [tool, { version: commandVersion(tool, ["--version"], cwd) }]));
502
497
  }
503
498
 
504
499
  function parseJsonDiagnostics(value = "") {
@@ -54,9 +54,11 @@ const PUBLIC_REPOSITORY_TARGETS = Object.freeze({
54
54
  target("publish-gate/major", [check("check")], true),
55
55
  ],
56
56
  buildchain: [
57
- target("dev/v3/v3.0", [check("check")], false),
57
+ ...["v3/v3.0", "v4/v4.0"].map((line) => target(`dev/${line}`, [check("check")], false)),
58
58
  target("alpha/v3/v3.0", [check("check"), check("verify")], false),
59
59
  target("release/v3/v3.0", [check("check")], true),
60
+ target("alpha/v4/v4.0", [check("check"), check("verify")], false),
61
+ target("release/v4/v4.0", [check("check"), check("verify")], true),
60
62
  target("authority/v3/v3.0/artifact-signing", [check("check"), check("verify")], true),
61
63
  target("publish-gate/major", [check("check")], true),
62
64
  ],
@@ -0,0 +1,167 @@
1
+ import kfdCategoryCatalog from "@kungfu-tech/kfd/adopter-conformance/category-profiles.json" with { type: "json" };
2
+ import kfdPackageJson from "@kungfu-tech/kfd/package.json" with { type: "json" };
3
+ import { resolveAdopterCategoryProfiles } from "@kungfu-tech/kfd/adopter-conformance/category-profile-resolver";
4
+ import { verifyAdopterCategoryInstanceManifest } from "@kungfu-tech/kfd/adopter-conformance/category-instance-verifier";
5
+ import { verifyAdopterManifestFromPackage } from "@kungfu-tech/kfd/adopter-conformance/toolchain";
6
+
7
+ import {
8
+ ADOPTER_PROTOCOL_DRIVER_INTERFACE,
9
+ adopterDeliveryGateDigest,
10
+ defineAdopterProtocolDriver,
11
+ } from "./adopter-delivery-gate.js";
12
+
13
+ export const KFD_ADOPTER_CATEGORY_PROTOCOL_ID =
14
+ "kfd.adopter-category/instance-manifest";
15
+ export const KFD_ADOPTER_CATEGORY_PROTOCOL_VERSION = "1.0.0";
16
+ export const KFD_ADOPTER_CATEGORY_DRIVER_REPORT_CONTRACT =
17
+ "kungfu-buildchain-kfd-adopter-category-driver-report";
18
+
19
+ function freezeJson(value) {
20
+ if (value && typeof value === "object" && !Object.isFrozen(value)) {
21
+ Object.freeze(value);
22
+ for (const child of Object.values(value)) freezeJson(child);
23
+ }
24
+ return value;
25
+ }
26
+
27
+ const publishedCatalog = freezeJson(structuredClone(kfdCategoryCatalog));
28
+
29
+ function catalogCopy() {
30
+ return structuredClone(publishedCatalog);
31
+ }
32
+
33
+ function sameJson(left, right) {
34
+ try {
35
+ return adopterDeliveryGateDigest(left) === adopterDeliveryGateDigest(right);
36
+ } catch {
37
+ return false;
38
+ }
39
+ }
40
+
41
+ function issue(code, path, message) {
42
+ return { code, path, message };
43
+ }
44
+
45
+ export function resolvePublishedKfdAdopterCategoryProfiles(selection) {
46
+ return resolveAdopterCategoryProfiles(
47
+ structuredClone(selection),
48
+ catalogCopy(),
49
+ );
50
+ }
51
+
52
+ export function verifyPublishedKfdAdopterCategoryInstance(
53
+ instanceManifest,
54
+ { adopterManifest, verifiedAt, maxAgeSeconds } = {},
55
+ ) {
56
+ const adopterReport = verifyAdopterManifestFromPackage(adopterManifest, {
57
+ packageArtifactRoot: instanceManifest?.kfdCut?.packageRoot,
58
+ verifiedAt,
59
+ maxAgeSeconds,
60
+ });
61
+ return verifyAdopterCategoryInstanceManifest(instanceManifest, {
62
+ catalog: catalogCopy(),
63
+ adopterManifest,
64
+ adopterReport,
65
+ verifiedAt,
66
+ maxAgeSeconds,
67
+ });
68
+ }
69
+
70
+ function deliveryBindingIssues(request, adopterManifest) {
71
+ const instance = request.declaration;
72
+ const issues = [];
73
+ if (
74
+ request.project.instanceId !== instance?.instanceId ||
75
+ request.project.adopterId !== instance?.project?.adopterId
76
+ ) {
77
+ issues.push(
78
+ issue(
79
+ "delivery-kfd-instance-binding-mismatch",
80
+ "/project",
81
+ "Delivery project identity must match the KFD category instance.",
82
+ ),
83
+ );
84
+ }
85
+ if (!sameJson(request.artifact, instance?.project?.artifact)) {
86
+ issues.push(
87
+ issue(
88
+ "delivery-kfd-instance-binding-mismatch",
89
+ "/artifact",
90
+ "Delivery artifact must match the KFD category instance artifact.",
91
+ ),
92
+ );
93
+ }
94
+ if (
95
+ adopterManifest?.kfdCut?.package?.name !== kfdPackageJson.name ||
96
+ adopterManifest?.kfdCut?.package?.version !== kfdPackageJson.version ||
97
+ instance?.kfdCut?.packageVersion !== kfdPackageJson.version
98
+ ) {
99
+ issues.push(
100
+ issue(
101
+ "delivery-kfd-package-cut-mismatch",
102
+ "/declaration/kfdCut",
103
+ "KFD declarations must bind the exact installed published package version.",
104
+ ),
105
+ );
106
+ }
107
+ return issues;
108
+ }
109
+
110
+ function driverReport(categoryReport, adapterIssues) {
111
+ const valid = categoryReport?.valid === true && adapterIssues.length === 0;
112
+ const report = {
113
+ schemaVersion: 1,
114
+ contract: KFD_ADOPTER_CATEGORY_DRIVER_REPORT_CONTRACT,
115
+ valid,
116
+ conforming: valid,
117
+ qualifying: false,
118
+ selfCertified: false,
119
+ independentlyCertified: false,
120
+ kfdPackage: {
121
+ name: kfdPackageJson.name,
122
+ version: kfdPackageJson.version,
123
+ },
124
+ categoryReport,
125
+ adapterIssues,
126
+ nonClaims: [
127
+ "Category conformance does not grant runtime permission or release authorization.",
128
+ "Buildchain carries the published KFD decision and does not certify or reinterpret it.",
129
+ ],
130
+ };
131
+ return {
132
+ valid,
133
+ report,
134
+ reportRoot: adopterDeliveryGateDigest(report),
135
+ issues: [...(categoryReport?.issues ?? []), ...adapterIssues],
136
+ };
137
+ }
138
+
139
+ export function createKfdAdopterCategoryProtocolDriver() {
140
+ return defineAdopterProtocolDriver({
141
+ interface: ADOPTER_PROTOCOL_DRIVER_INTERFACE,
142
+ id: KFD_ADOPTER_CATEGORY_PROTOCOL_ID,
143
+ version: KFD_ADOPTER_CATEGORY_PROTOCOL_VERSION,
144
+ verify({ request, context }) {
145
+ const adapterIssues = deliveryBindingIssues(
146
+ request,
147
+ context?.adopterManifest,
148
+ );
149
+ let categoryReport = null;
150
+ try {
151
+ categoryReport = verifyPublishedKfdAdopterCategoryInstance(
152
+ request.declaration,
153
+ context,
154
+ );
155
+ } catch {
156
+ adapterIssues.push(
157
+ issue(
158
+ "delivery-kfd-verification-context-invalid",
159
+ "/protocol",
160
+ "Published KFD verification could not reproduce from the supplied exact context.",
161
+ ),
162
+ );
163
+ }
164
+ return driverReport(categoryReport, adapterIssues);
165
+ },
166
+ });
167
+ }