@kungfu-tech/buildchain 3.0.9-alpha.9 → 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 (262) 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 -10
  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 -4
  65. package/dist/site/artifact-schemas.json +0 -8
  66. package/dist/site/buildchain-contract.json +103 -397
  67. package/dist/site/buildchain-site.json +302 -386
  68. package/dist/site/capability-registry.json +9 -11
  69. package/dist/site/cli-registry.json +8 -53
  70. package/dist/site/controller-registry.json +48 -8
  71. package/dist/site/kfd-claims.json +129 -167
  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 +4345 -7345
  75. package/dist/site/page-registry.json +278 -346
  76. package/dist/site/public-surface-audit.json +85 -404
  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 -9
  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 +78 -35
  83. package/docs/MAP.md +8 -5
  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 -213
  87. package/docs/cli.md +14 -14
  88. package/docs/dev-alpha-candidate-patrol.md +3 -11
  89. package/docs/dev-delivery-warrant.md +29 -194
  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 -554
  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 -5
  111. package/package.json +19 -19
  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-channel-identity.js +3 -2
  119. package/packages/core/buildchain-config.js +4 -69
  120. package/packages/core/buildchain-contract.js +232 -46
  121. package/packages/core/buildchain-kfd-claims.js +1 -1
  122. package/packages/core/channel-candidate.js +0 -8
  123. package/packages/core/channel-promotion-baseline.js +0 -52
  124. package/packages/core/controller-evidence.js +3 -4
  125. package/packages/core/dev-alpha-candidate-selection.js +2 -10
  126. package/packages/core/dev-delivery-warrant-cancellation.js +0 -1
  127. package/packages/core/dev-delivery-warrant-settlement.js +20 -67
  128. package/packages/core/dev-delivery-warrant.js +50 -138
  129. package/packages/core/diagnostics.js +3 -8
  130. package/packages/core/github-governance-authority.js +3 -1
  131. package/packages/core/kfd-adopter-category-driver.js +167 -0
  132. package/packages/core/kfd-adopter-manifest.js +47 -46
  133. package/packages/core/kfd-gate.js +15 -45
  134. package/packages/core/paper-agent-entry.js +7 -16
  135. package/packages/core/paper-fleet.js +2 -2
  136. package/packages/core/paper-repository.js +2 -3
  137. package/packages/core/paper-scaffold-content.js +2 -23
  138. package/packages/core/paper.js +11 -43
  139. package/packages/core/publication-reproducibility.js +4 -4
  140. package/packages/core/release-line-bootstrap.js +21 -8
  141. package/packages/core/release-passport-contract.js +5 -5
  142. package/packages/core/release-passport.js +20 -131
  143. package/packages/core/self-dogfood-version.js +48 -35
  144. package/packages/core/spawn-command.js +232 -8
  145. package/packages/core/v4-adopter-delivery-parity.js +219 -0
  146. package/packages/core/v4-canonical-contracts.js +284 -0
  147. package/packages/core/v4-delivery-warrant-fixture-runner.js +371 -0
  148. package/packages/core/v4-delivery-warrant-read-candidate.js +279 -0
  149. package/packages/core/v4-delivery-warrant-semantic-diff-gate.js +352 -0
  150. package/packages/core/v4-delivery-warrant-shadow-adapter.js +447 -0
  151. package/packages/core/v4-partial-mutation-recovery-qualification.js +395 -0
  152. package/packages/core/v4-platform-stage-checkpoints.js +471 -0
  153. package/packages/core/v4-provider-operation-journal.js +531 -0
  154. package/packages/core/v4-provider-readback-idempotency.js +394 -0
  155. package/packages/core/v4-release-activation-shadow.js +519 -0
  156. package/packages/core/v4-stable-publication-fence.js +357 -0
  157. package/packages/core/v4-stage-capsule-local-store.js +426 -0
  158. package/packages/core/v4-stage-capsule-qualification-campaign.js +512 -0
  159. package/packages/core/v4-stage-capsule-qualification.js +456 -0
  160. package/packages/core/v4-stage-capsule-resume-planner.js +397 -0
  161. package/packages/core/v4-stage-capsule-store.js +401 -0
  162. package/packages/core/v4-stage-capsule.js +319 -0
  163. package/scripts/assemble-self-publication-admission.mjs +1 -1
  164. package/scripts/audit-publication-control-plane.mjs +5 -5
  165. package/scripts/auditable-demo-bundle-verification.mjs +3 -2
  166. package/scripts/auditable-demo-platform.mjs +2 -2
  167. package/scripts/auditable-demo-renditions.mjs +1 -1
  168. package/scripts/auditable-demo.mjs +2 -2
  169. package/scripts/aws-macos-jit-controller-core.mjs +13 -346
  170. package/scripts/aws-macos-jit-controller-runtime.mjs +2 -210
  171. package/scripts/aws-macos-jit-controller.mjs +37 -275
  172. package/scripts/aws-macos-jit-core.mjs +3 -41
  173. package/scripts/aws-macos-jit.mjs +0 -12
  174. package/scripts/aws-windows-jit-campaign.mjs +2 -2
  175. package/scripts/aws-windows-jit-controller-core.mjs +1 -1
  176. package/scripts/aws-windows-jit-controller.mjs +3 -3
  177. package/scripts/build-contract-core.mjs +3 -8
  178. package/scripts/build-standalone-binary.mjs +3 -14
  179. package/scripts/buildchain-channel-router.mjs +4 -0
  180. package/scripts/buildchain-cli-help.mjs +7 -16
  181. package/scripts/buildchain-contract-lock.mjs +0 -6
  182. package/scripts/check-action-bundles.mjs +3 -4
  183. package/scripts/check-internal-architecture.mjs +7 -6
  184. package/scripts/check-inventory.mjs +30 -25
  185. package/scripts/check-v4-public-dogfood-contract.mjs +270 -0
  186. package/scripts/create-release-bundle.mjs +8 -4
  187. package/scripts/dev-alpha-candidate-patrol.mjs +1 -22
  188. package/scripts/dev-delivery-proof.mjs +2 -64
  189. package/scripts/dev-delivery-warrant.mjs +61 -86
  190. package/scripts/dev-pr-auto-merge.mjs +4 -30
  191. package/scripts/dev-pr-delivery-warrant.mjs +0 -55
  192. package/scripts/dispatch-artifact-signing-authority.mjs +7 -4
  193. package/scripts/generate-buildchain-kfd-witnesses.mjs +94 -88
  194. package/scripts/generate-channel-build-workflow.mjs +54 -24
  195. package/scripts/generate-channel-promotion-workflow.mjs +15 -6
  196. package/scripts/generate-site-bundle.mjs +8 -27
  197. package/scripts/git-fetch-process-tree.mjs +34 -1
  198. package/scripts/init-repo.mjs +64 -159
  199. package/scripts/inspect-artifact-signing-requests.mjs +0 -6
  200. package/scripts/locked-source-checkout.mjs +3 -4
  201. package/scripts/maintainability-metrics.mjs +8 -2
  202. package/scripts/npm-publish-dry-run.mjs +2 -2
  203. package/scripts/npm-publish-transaction.mjs +2 -2
  204. package/scripts/publication-commit-evidence.mjs +23 -69
  205. package/scripts/release-candidate-resolver.mjs +11 -17
  206. package/scripts/release-tail.mjs +3 -49
  207. package/scripts/resume-from-candidate-run.mjs +9 -123
  208. package/scripts/run-lifecycle-core.mjs +12 -13
  209. package/scripts/seal-artifact-signing-requests.mjs +17 -21
  210. package/scripts/site-capability-metadata.mjs +3 -20
  211. package/scripts/stable-candidate-qualification.mjs +10 -10
  212. package/scripts/v4-architecture.mjs +12 -2
  213. package/scripts/v4-bridge-bootstrap.mjs +141 -0
  214. package/scripts/v4-bridge-evidence.mjs +141 -0
  215. package/scripts/v4-host-adapter.mjs +182 -0
  216. package/scripts/v4-platform-stage-checkpoint-rehearsal.mjs +207 -0
  217. package/scripts/v4-stage-capsule-qualification.mjs +528 -0
  218. package/scripts/v4-stage-capsule-resume-rehearsal.mjs +57 -0
  219. package/scripts/v4-warrant-shadow-plan.mjs +601 -0
  220. package/scripts/verify-golden-path.mjs +5 -5
  221. package/scripts/web-surface-cloudfront-rewrite.mjs +15 -15
  222. package/scripts/web-surface-core.mjs +2 -8
  223. package/scripts/workflow-call-contract.mjs +5 -184
  224. package/contracts/dev-delivery-authority-v2.schema.json +0 -253
  225. package/contracts/fixtures/kfd-adopter-release-v1/kfd-4-perspective.json +0 -16
  226. package/contracts/fixtures/kfd-adopter-release-v1/kfd-4-replay.json +0 -57
  227. package/contracts/fixtures/next-development-transition-v1/anchored-manual-waiting.json +0 -47
  228. package/contracts/fixtures/next-development-transition-v1/semver-auto-planned.json +0 -47
  229. package/contracts/fixtures/next-development-transition-v1/version-model-cases.json +0 -40
  230. package/contracts/next-development-request-v1.schema.json +0 -66
  231. package/contracts/next-development-transition-v1.schema.json +0 -292
  232. package/contracts/publication-rehearsal-capsule-v1.schema.json +0 -173
  233. package/dist/site/schemas/dev-delivery-authority-v2.schema.json +0 -442
  234. package/dist/site/schemas/publication-rehearsal-capsule-v1.schema.json +0 -269
  235. package/dist/site/schemas/release-tail-capabilities-v1.schema.json +0 -353
  236. package/dist/site/schemas/release-tail-provider-bindings-v1.schema.json +0 -94
  237. package/docs/dev-delivery-qualification-landing-adr.md +0 -137
  238. package/docs/next-development-transition.md +0 -119
  239. package/docs/publication-rehearsal.md +0 -94
  240. package/packages/core/buildchain-compatibility-proof.js +0 -631
  241. package/packages/core/dev-delivery-authority.js +0 -996
  242. package/packages/core/dev-delivery-native-proof.js +0 -418
  243. package/packages/core/dev-delivery-warrant-shadow.js +0 -502
  244. package/packages/core/next-development-candidate-reservation.js +0 -186
  245. package/packages/core/next-development-controller.js +0 -726
  246. package/packages/core/next-development-projection.js +0 -288
  247. package/packages/core/next-development-transition.js +0 -738
  248. package/packages/core/publication-rehearsal-projection.js +0 -173
  249. package/packages/core/publication-rehearsal-runtime.js +0 -921
  250. package/scripts/aws-macos-jit-instance-rehydrate.mjs +0 -260
  251. package/scripts/aws-macos-jit-source-rebind.mjs +0 -724
  252. package/scripts/dev-delivery-authority.mjs +0 -368
  253. package/scripts/dev-delivery-native-run.mjs +0 -235
  254. package/scripts/dev-delivery-two-phase-resume.mjs +0 -90
  255. package/scripts/dev-delivery-two-phase.mjs +0 -577
  256. package/scripts/generate-next-development-guidance.mjs +0 -49
  257. package/scripts/materialize-self-release-candidate-version.mjs +0 -137
  258. package/scripts/next-development-self-dogfood-harness.mjs +0 -409
  259. package/scripts/next-development-self-dogfood.mjs +0 -532
  260. package/scripts/next-development-transition.mjs +0 -47
  261. package/scripts/release-candidate-tail-reseal.mjs +0 -426
  262. package/templates/native-dev-delivery.yml +0 -86
@@ -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, NATIVE_PROOF_BASE_DELTA_SCHEMA, createNativeProofBaseDelta, 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";
@@ -23,14 +21,7 @@ export const DEV_DELIVERY_PRIORITIES = Object.freeze({
23
21
 
24
22
  export const DEV_DELIVERY_CLASSES = Object.freeze(["non-native-fast", "native-proof-required", "cross-platform", "release"]);
25
23
 
26
- const TERMINAL_STATES = new Set(["merged", "terminal-failure", "dequeued", "cancelled", "superseded"]);
27
- const TERMINAL_CLASSES = Object.freeze({
28
- merged: "authoritative-completion",
29
- "terminal-failure": "authoritative-failure",
30
- cancelled: "authoritative-cancellation",
31
- superseded: "authoritative-supersession",
32
- dequeued: "transient-dequeue",
33
- });
24
+ const TERMINAL_STATES = new Set(["merged", "terminal-failure", "dequeued", "cancelled"]);
34
25
  function nonNegativeInteger(value, label, fallback = 0) {
35
26
  const parsed = Number(value ?? fallback);
36
27
  if (!Number.isInteger(parsed) || parsed < 0) throw new Error(`${label} must be a non-negative integer`);
@@ -68,7 +59,7 @@ function normalizeCandidate(input, expected) {
68
59
  throw new Error(`candidateId mismatch for PR #${identity.pullRequestNumber}`);
69
60
  }
70
61
  const status = text(input.status || "queued");
71
- if (!["queued", "selected", "provisional", "proving", "qualified", "waiting", "blocked", ...TERMINAL_STATES].includes(status)) {
62
+ if (!["queued", "selected", "proving", "waiting", "blocked", ...TERMINAL_STATES].includes(status)) {
72
63
  throw new Error(`unsupported candidate status ${status || "<empty>"}`);
73
64
  }
74
65
  const candidate = {
@@ -80,14 +71,6 @@ function normalizeCandidate(input, expected) {
80
71
  closureRoot: exactRoot(input.closureRoot, "closureRoot"),
81
72
  dependencyRoot: exactRoot(input.dependencyRoot, "dependencyRoot"),
82
73
  toolchainRoot: exactRoot(input.toolchainRoot, "toolchainRoot"),
83
- ...(input.environmentRoot
84
- ? { environmentRoot: exactRoot(input.environmentRoot, "environmentRoot") }
85
- : {}),
86
- ...(Object.hasOwn(input, "sourceWorkflowRunId")
87
- ? {
88
- sourceWorkflowRunId: nonNegativeInteger(input.sourceWorkflowRunId, "candidate sourceWorkflowRunId", 0),
89
- }
90
- : {}),
91
74
  priority: priority(input.priority),
92
75
  enqueuedAt: timestamp(input.enqueuedAt, "candidate enqueuedAt"),
93
76
  updatedAt: timestamp(input.updatedAt || input.enqueuedAt, "candidate updatedAt"),
@@ -96,10 +79,6 @@ function normalizeCandidate(input, expected) {
96
79
  status,
97
80
  terminal: input.terminal || null,
98
81
  };
99
- if (Object.hasOwn(input, "affectedPaths")) {
100
- if (!Array.isArray(input.affectedPaths)) throw new Error("candidate affectedPaths must be an array");
101
- candidate.affectedPaths = [...new Set(input.affectedPaths.map(text).filter(Boolean))].sort();
102
- }
103
82
  if (Object.hasOwn(input, "releaseBlockerPriority")) candidate.releaseBlockerPriority = normalizeReleaseBlockerPriorityClaim(input.releaseBlockerPriority, candidate, expected);
104
83
  return candidate;
105
84
  }
@@ -160,20 +139,12 @@ export function normalizeDevDeliveryQueue(input, expected = {}) {
160
139
  warrant.generation = positiveInteger(warrant.generation, "Warrant generation");
161
140
  warrant.issuedAt = timestamp(warrant.issuedAt, "Warrant issuedAt");
162
141
  warrant.expiresAt = timestamp(warrant.expiresAt, "Warrant expiresAt");
163
- const warrantPhase = text(warrant.phase || "qualified");
164
- if (!["provisional", "qualified"].includes(warrantPhase)) throw new Error("active Warrant phase is unsupported");
165
- if (Object.hasOwn(warrant, "phase")) warrant.phase = warrantPhase;
166
- if (warrantPhase === "qualified") {
167
- if (warrant.nativeProofRoot) warrant.nativeProofRoot = exactRoot(warrant.nativeProofRoot, "Warrant nativeProofRoot");
168
- if (warrant.nativeProofReuseRoot) warrant.nativeProofReuseRoot = exactRoot(warrant.nativeProofReuseRoot, "Warrant nativeProofReuseRoot");
169
- if (warrant.qualifiedAt) warrant.qualifiedAt = timestamp(warrant.qualifiedAt, "Warrant qualifiedAt");
170
- }
171
- 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));
172
143
  if (activeCandidates.length !== 1 || activeCandidates[0].candidateId !== warrant.candidateId) {
173
144
  throw new Error("exactly one active candidate must match the active Warrant");
174
145
  }
175
146
  if (warrant.releaseBlockerPriority?.claimRoot !== activeCandidates[0].releaseBlockerPriority?.claimRoot) throw new Error("active Warrant release-blocker priority drift");
176
- } 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))) {
177
148
  throw new Error("active candidate exists without an active Warrant");
178
149
  }
179
150
  const rooted = withQueueRoot(queue);
@@ -211,8 +182,7 @@ function submissionReceipt({ before, after, candidate, action, now }) {
211
182
  planRoot: candidate.planRoot,
212
183
  closureRoot: candidate.closureRoot,
213
184
  dependencyRoot: candidate.dependencyRoot,
214
- toolchainRoot: candidate.toolchainRoot, ...(candidate.environmentRoot ? { environmentRoot: candidate.environmentRoot } : {}),
215
- ...(Object.hasOwn(candidate, "affectedPaths") ? { affectedPaths: candidate.affectedPaths } : {}),
185
+ toolchainRoot: candidate.toolchainRoot,
216
186
  sourceWorkflowRunId: candidate.sourceWorkflowRunId,
217
187
  ...(Object.hasOwn(candidate, "releaseBlockerPriority") ? { releaseBlockerPriority: candidate.releaseBlockerPriority } : {}),
218
188
  deliveryClass: candidate.deliveryClass,
@@ -227,21 +197,6 @@ function submissionReceipt({ before, after, candidate, action, now }) {
227
197
  };
228
198
  }
229
199
 
230
- function reconcileSourceWorkflowRunId(existing, attempted, activeCandidateId, currentTime) {
231
- const current = existing.sourceWorkflowRunId || 0;
232
- const next = attempted.sourceWorkflowRunId || 0;
233
- if (existing.sourceHead !== attempted.sourceHead) {
234
- existing.sourceWorkflowRunId = next;
235
- return "head-change";
236
- }
237
- if (current > 0 && next > 0 && current !== next) throw new Error("candidate sourceWorkflowRunId cannot change for the same sourceHead");
238
- if (current !== 0 || next === 0) return "retained";
239
- if (activeCandidateId === existing.candidateId) return "active";
240
- existing.sourceWorkflowRunId = next;
241
- existing.updatedAt = currentTime;
242
- return "upgraded";
243
- }
244
-
245
200
  export function submitDevDeliveryCandidate(queueInput, input, { now = new Date().toISOString() } = {}) {
246
201
  const transaction = transition(
247
202
  queueInput,
@@ -257,13 +212,7 @@ export function submitDevDeliveryCandidate(queueInput, input, { now = new Date()
257
212
  },
258
213
  queue,
259
214
  );
260
- const chainedInput = chainedDevDeliveryAttemptInput({
261
- queue,
262
- candidate,
263
- input,
264
- currentTime,
265
- terminalStates: TERMINAL_STATES,
266
- });
215
+ const chainedInput = chainedDevDeliveryAttemptInput({ queue, candidate, input, currentTime, terminalStates: TERMINAL_STATES });
267
216
  const attemptedCandidate = chainedInput ? normalizeCandidate(chainedInput, queue) : candidate;
268
217
  const conflicting = queue.candidates.find((entry) => entry.pullRequestNumber === attemptedCandidate.pullRequestNumber && entry.candidateId !== attemptedCandidate.candidateId && !TERMINAL_STATES.has(entry.status));
269
218
  if (conflicting) throw new Error(`PR #${candidate.pullRequestNumber} already has a different active semantic source`);
@@ -274,27 +223,18 @@ export function submitDevDeliveryCandidate(queueInput, input, { now = new Date()
274
223
  if (TERMINAL_STATES.has(existing.status)) {
275
224
  throw new Error(`candidate ${attemptedCandidate.candidateId} is terminal and cannot be resubmitted`);
276
225
  }
277
- const exactProofFields = ["sourcePatchRoot", "sourceProofRoot", "planRoot", "closureRoot", "dependencyRoot", "toolchainRoot", "environmentRoot"];
278
- const exactProofMatches = exactProofFields.every((field) => existing[field] === attemptedCandidate[field]) && JSON.stringify(existing.affectedPaths || []) === JSON.stringify(attemptedCandidate.affectedPaths || []) && existing.releaseBlockerPriority?.claimRoot === attemptedCandidate.releaseBlockerPriority?.claimRoot;
279
- const bindingAction = reconcileSourceWorkflowRunId(existing, attemptedCandidate, before.activeWarrant?.candidateId, currentTime);
226
+ const exactProofFields = ["sourcePatchRoot", "sourceProofRoot", "planRoot", "closureRoot", "dependencyRoot", "toolchainRoot"];
227
+ const exactProofMatches = exactProofFields.every((field) => existing[field] === attemptedCandidate[field]) && existing.releaseBlockerPriority?.claimRoot === attemptedCandidate.releaseBlockerPriority?.claimRoot;
280
228
  if (existing.sourceHead === attemptedCandidate.sourceHead && exactProofMatches) {
281
- if (bindingAction === "active") return { candidate: existing, action: "active-warrant-retained-noop" };
282
- action = bindingAction === "upgraded" ? "source-workflow-run-upgrade-retained-age" : "duplicate-noop";
229
+ action = "duplicate-noop";
283
230
  selected = existing;
284
231
  } else {
285
232
  if (before.activeWarrant?.candidateId === existing.candidateId) {
286
- if (existing.sourceHead !== attemptedCandidate.sourceHead) {
287
- throw new Error("selected candidate sourceHead cannot change before terminal Warrant closeout");
288
- }
289
- action = "active-warrant-retained-noop";
290
- selected = existing;
291
- return { candidate: selected, action };
233
+ throw new Error("selected candidate sourceHead cannot change before terminal Warrant closeout");
292
234
  }
293
235
  const headChanged = existing.sourceHead !== attemptedCandidate.sourceHead;
294
236
  existing.sourceHead = attemptedCandidate.sourceHead;
295
237
  for (const field of exactProofFields) existing[field] = attemptedCandidate[field];
296
- if (Object.hasOwn(attemptedCandidate, "affectedPaths")) existing.affectedPaths = attemptedCandidate.affectedPaths;
297
- else delete existing.affectedPaths;
298
238
  if (Object.hasOwn(attemptedCandidate, "releaseBlockerPriority")) existing.releaseBlockerPriority = attemptedCandidate.releaseBlockerPriority;
299
239
  else delete existing.releaseBlockerPriority;
300
240
  existing.updatedAt = currentTime;
@@ -362,26 +302,26 @@ function warrantToken(input) {
362
302
 
363
303
  export function selectDevDeliveryWarrant(queueInput, { now = new Date().toISOString(), leaseSeconds } = {}) {
364
304
  const currentTime = timestamp(now, "now");
365
- const queue = normalizeDevDeliveryQueue(queueInput);
305
+ let queue = normalizeDevDeliveryQueue(queueInput);
366
306
  let recoveryReceipt = null;
367
307
  if (queue.activeWarrant && Date.parse(queue.activeWarrant.expiresAt) <= Date.parse(currentTime)) {
368
308
  const recovered = recoverExpiredDevDeliveryWarrant(queue, {
369
309
  now: currentTime,
370
310
  });
311
+ queue = recovered.queue;
371
312
  recoveryReceipt = recovered.receipt;
372
313
  }
373
314
  if (queue.activeWarrant) {
374
- const expired = Date.parse(queue.activeWarrant.expiresAt) <= Date.parse(currentTime);
375
315
  const receipt = {
376
316
  schema: DEV_DELIVERY_SELECTION_RECEIPT_SCHEMA,
377
- selected: !expired,
378
- reason: expired ? "expired-active-warrant-awaits-fenced-settlement" : "non-preemptive-active-warrant",
317
+ selected: true,
318
+ reason: "non-preemptive-active-warrant",
379
319
  candidateId: queue.activeWarrant.candidateId,
380
320
  fencingToken: queue.activeWarrant.fencingToken,
381
321
  leaseGeneration: queue.activeWarrant.generation,
382
- expectedOldStateRoot: recoveryReceipt?.expectedOldStateRoot || queue.stateRoot,
322
+ expectedOldStateRoot: queue.stateRoot,
383
323
  nextStateRoot: queue.stateRoot,
384
- nextAction: expired ? "Prove the stale native worker stopped, then close this exact fenced generation before selecting a successor." : "Continue the active delivery attempt; later candidates remain visibly queued.",
324
+ nextAction: "Continue the active delivery attempt; later candidates remain visibly queued.",
385
325
  };
386
326
  return {
387
327
  queue,
@@ -432,18 +372,16 @@ export function selectDevDeliveryWarrant(queueInput, { now = new Date().toISOStr
432
372
  planRoot: candidate.planRoot,
433
373
  closureRoot: candidate.closureRoot,
434
374
  dependencyRoot: candidate.dependencyRoot,
435
- toolchainRoot: candidate.toolchainRoot, ...(candidate.environmentRoot ? { environmentRoot: candidate.environmentRoot } : {}),
436
- ...(Object.hasOwn(candidate, "affectedPaths") ? { affectedPaths: candidate.affectedPaths } : {}),
375
+ toolchainRoot: candidate.toolchainRoot,
437
376
  sourceWorkflowRunId: candidate.sourceWorkflowRunId,
438
377
  ...(Object.hasOwn(candidate, "releaseBlockerPriority") ? { releaseBlockerPriority: candidate.releaseBlockerPriority } : {}),
439
378
  deliveryClass: candidate.deliveryClass,
440
379
  generation: next.fencingCounter,
441
- phase: "provisional",
442
380
  expectedOldStateRoot: before.stateRoot,
443
381
  issuedAt,
444
382
  expiresAt: new Date(Date.parse(issuedAt) + effectiveLeaseSeconds * 1000).toISOString(),
445
383
  fencingToken: "",
446
- 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.",
447
385
  };
448
386
  warrant.fencingToken = warrantToken(warrant);
449
387
  next.activeWarrant = warrant;
@@ -470,13 +408,9 @@ export function selectDevDeliveryWarrant(queueInput, { now = new Date().toISOStr
470
408
  planRoot: transaction.result.candidate.planRoot,
471
409
  closureRoot: transaction.result.candidate.closureRoot,
472
410
  dependencyRoot: transaction.result.candidate.dependencyRoot,
473
- toolchainRoot: transaction.result.candidate.toolchainRoot, ...(transaction.result.candidate.environmentRoot ? { environmentRoot: transaction.result.candidate.environmentRoot } : {}),
411
+ toolchainRoot: transaction.result.candidate.toolchainRoot,
474
412
  sourceWorkflowRunId: transaction.result.candidate.sourceWorkflowRunId,
475
- ...(Object.hasOwn(transaction.result.candidate, "releaseBlockerPriority")
476
- ? {
477
- releaseBlockerPriority: transaction.result.candidate.releaseBlockerPriority,
478
- }
479
- : {}),
413
+ ...(Object.hasOwn(transaction.result.candidate, "releaseBlockerPriority") ? { releaseBlockerPriority: transaction.result.candidate.releaseBlockerPriority } : {}),
480
414
  deliveryClass: transaction.result.candidate.deliveryClass,
481
415
  queueAgeSeconds: selected.priority.ageSeconds,
482
416
  basePriority: selected.priority.basePriority,
@@ -484,7 +418,7 @@ export function selectDevDeliveryWarrant(queueInput, { now = new Date().toISOStr
484
418
  effectivePriority: selected.priority.score,
485
419
  fencingToken: transaction.result.warrant.fencingToken,
486
420
  leaseGeneration: transaction.result.warrant.generation,
487
- expectedOldStateRoot: recoveryReceipt?.expectedOldStateRoot || transaction.expectedOldStateRoot,
421
+ expectedOldStateRoot: transaction.expectedOldStateRoot,
488
422
  nextStateRoot: transaction.after.stateRoot,
489
423
  nextAction: transaction.result.warrant.nextAction,
490
424
  };
@@ -497,12 +431,12 @@ export function selectDevDeliveryWarrant(queueInput, { now = new Date().toISOStr
497
431
  };
498
432
  }
499
433
 
500
- function assertWarrantMutation(queue, warrant, now, { allowExpired = false } = {}) {
434
+ function assertWarrantMutation(queue, warrant, now) {
501
435
  if (!queue.activeWarrant) throw new Error("no active Delivery Warrant");
502
436
  if (text(warrant?.fencingToken) !== queue.activeWarrant.fencingToken) throw new Error("stale fencing token");
503
437
  if (Number(warrant?.generation) !== queue.activeWarrant.generation) throw new Error("stale lease generation");
504
438
  if (text(warrant?.candidateId) !== queue.activeWarrant.candidateId) throw new Error("Warrant candidate mismatch");
505
- 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");
506
440
  }
507
441
 
508
442
  export function heartbeatDevDeliveryWarrant(queueInput, warrant, { now = new Date().toISOString(), leaseSeconds } = {}) {
@@ -514,7 +448,7 @@ export function heartbeatDevDeliveryWarrant(queueInput, warrant, { now = new Dat
514
448
  const effectiveLeaseSeconds = positiveInteger(leaseSeconds, "leaseSeconds", queue.policy.leaseSeconds);
515
449
  queue.activeWarrant.expiresAt = new Date(Date.parse(currentTime) + effectiveLeaseSeconds * 1000).toISOString();
516
450
  const candidate = queue.candidates.find((entry) => entry.candidateId === queue.activeWarrant.candidateId);
517
- candidate.status = queue.activeWarrant.phase === "qualified" ? "qualified" : "proving";
451
+ candidate.status = "proving";
518
452
  candidate.updatedAt = currentTime;
519
453
  return { candidate, warrant: queue.activeWarrant };
520
454
  },
@@ -538,13 +472,6 @@ export function heartbeatDevDeliveryWarrant(queueInput, warrant, { now = new Dat
538
472
  };
539
473
  }
540
474
 
541
- const qualifyDevDeliveryWarrantTransition = createDevDeliveryWarrantQualifier({
542
- transition,
543
- assertWarrantMutation,
544
- });
545
- export function qualifyDevDeliveryWarrant(queueInput, warrant, options) {
546
- return qualifyDevDeliveryWarrantTransition(queueInput, warrant, options);
547
- }
548
475
  export function recoverExpiredDevDeliveryWarrant(queueInput, { now = new Date().toISOString() } = {}) {
549
476
  const currentTime = timestamp(now, "now");
550
477
  const before = normalizeDevDeliveryQueue(queueInput);
@@ -563,21 +490,33 @@ export function recoverExpiredDevDeliveryWarrant(queueInput, { now = new Date().
563
490
  receiptRoot: devDeliveryContentRoot(receipt),
564
491
  };
565
492
  }
566
- const expired = before.activeWarrant;
567
- const candidate = before.candidates.find((entry) => entry.candidateId === expired.candidateId);
493
+ const transaction = transition(
494
+ before,
495
+ (queue) => {
496
+ const expired = clone(queue.activeWarrant);
497
+ const candidate = queue.candidates.find((entry) => entry.candidateId === expired.candidateId);
498
+ candidate.status = "queued";
499
+ candidate.recoveries += 1;
500
+ candidate.attempts += 1;
501
+ candidate.updatedAt = currentTime;
502
+ queue.activeWarrant = null;
503
+ return { candidate, expired };
504
+ },
505
+ currentTime,
506
+ );
568
507
  const receipt = {
569
508
  schema: DEV_DELIVERY_LEASE_RECEIPT_SCHEMA,
570
- action: "expired-lease-fenced-stop-required",
571
- candidateId: candidate.candidateId,
572
- rejectedFencingToken: expired.fencingToken,
573
- expiredLeaseGeneration: expired.generation,
574
- retainedEnqueuedAt: candidate.enqueuedAt,
575
- expectedOldStateRoot: before.stateRoot,
576
- nextStateRoot: before.stateRoot,
577
- nextAction: "Prove the stale native worker stopped, then close this exact fenced generation before selecting a successor.",
509
+ action: "recovered-expired-lease",
510
+ candidateId: transaction.result.candidate.candidateId,
511
+ rejectedFencingToken: transaction.result.expired.fencingToken,
512
+ expiredLeaseGeneration: transaction.result.expired.generation,
513
+ retainedEnqueuedAt: transaction.result.candidate.enqueuedAt,
514
+ expectedOldStateRoot: transaction.expectedOldStateRoot,
515
+ nextStateRoot: transaction.after.stateRoot,
516
+ nextAction: "Re-select through the queue to mint a new lease generation and fencing token.",
578
517
  };
579
518
  return {
580
- queue: before,
519
+ queue: transaction.after,
581
520
  receipt,
582
521
  receiptRoot: devDeliveryContentRoot(receipt),
583
522
  };
@@ -589,22 +528,16 @@ export function closeDevDeliveryWarrant(queueInput, warrant, { outcome, evidence
589
528
  if (!TERMINAL_STATES.has(normalizedOutcome)) {
590
529
  throw new Error(`outcome must be one of ${[...TERMINAL_STATES].join(", ")}`);
591
530
  }
592
- if (normalizedOutcome === "dequeued") {
593
- throw new Error("transient dequeue cannot close an active Delivery Warrant");
594
- }
595
531
  const transaction = transition(
596
532
  queueInput,
597
533
  (queue, before) => {
598
- assertWarrantMutation(before, warrant, currentTime, {
599
- allowExpired: true,
600
- });
534
+ assertWarrantMutation(before, warrant, currentTime);
601
535
  const active = clone(queue.activeWarrant);
602
536
  const candidate = queue.candidates.find((entry) => entry.candidateId === active.candidateId);
603
537
  candidate.status = normalizedOutcome;
604
538
  candidate.updatedAt = currentTime;
605
539
  candidate.terminal = {
606
540
  outcome: normalizedOutcome,
607
- terminalClass: TERMINAL_CLASSES[normalizedOutcome],
608
541
  reason: text(reason),
609
542
  evidenceRoot: exactRoot(evidenceRoot, "evidenceRoot"),
610
543
  closedAt: currentTime,
@@ -620,7 +553,6 @@ export function closeDevDeliveryWarrant(queueInput, warrant, { outcome, evidence
620
553
  schema: DEV_DELIVERY_LEASE_RECEIPT_SCHEMA,
621
554
  action: "terminal-closeout",
622
555
  outcome: normalizedOutcome,
623
- terminalClass: TERMINAL_CLASSES[normalizedOutcome],
624
556
  reason: text(reason),
625
557
  candidateId: transaction.result.candidate.candidateId,
626
558
  fencingToken: transaction.result.active.fencingToken,
@@ -638,15 +570,8 @@ export function closeDevDeliveryWarrant(queueInput, warrant, { outcome, evidence
638
570
  }
639
571
 
640
572
  const cancelQueuedDevDeliveryCandidateTransition = createCancelQueuedDevDeliveryCandidate(normalizeDevDeliveryQueue);
641
- export function cancelQueuedDevDeliveryCandidate(queueInput, input, options) {
642
- return cancelQueuedDevDeliveryCandidateTransition(queueInput, input, options);
643
- }
644
- export const settleDevDeliveryTerminalEvent = createDevDeliveryTerminalSettler({
645
- normalizeQueue: normalizeDevDeliveryQueue,
646
- closeWarrant: closeDevDeliveryWarrant,
647
- cancelQueued: cancelQueuedDevDeliveryCandidate,
648
- terminalStates: TERMINAL_STATES,
649
- });
573
+ export function cancelQueuedDevDeliveryCandidate(queueInput, input, options) { return cancelQueuedDevDeliveryCandidateTransition(queueInput, input, options); }
574
+ export const settleDevDeliveryTerminalEvent = createDevDeliveryTerminalSettler({ normalizeQueue: normalizeDevDeliveryQueue, closeWarrant: closeDevDeliveryWarrant, cancelQueued: cancelQueuedDevDeliveryCandidate, terminalStates: TERMINAL_STATES });
650
575
 
651
576
  export function observeDevDeliveryQueue(queueInput, { now = new Date().toISOString() } = {}) {
652
577
  const queue = normalizeDevDeliveryQueue(queueInput);
@@ -673,19 +598,6 @@ export function observeDevDeliveryQueue(queueInput, { now = new Date().toISOStri
673
598
  queueAgeSeconds: entry.priority.ageSeconds,
674
599
  attempts: entry.candidate.attempts,
675
600
  recoveries: entry.candidate.recoveries,
676
- assignmentRoot: entry.candidate.assignmentRoot,
677
- initiativeRoot: entry.candidate.initiativeRoot,
678
- sourceIdentityRoot: entry.candidate.sourceIdentityRoot,
679
- sourcePatchRoot: entry.candidate.sourcePatchRoot,
680
- sourceProofRoot: entry.candidate.sourceProofRoot,
681
- planRoot: entry.candidate.planRoot,
682
- closureRoot: entry.candidate.closureRoot,
683
- dependencyRoot: entry.candidate.dependencyRoot,
684
- toolchainRoot: entry.candidate.toolchainRoot, ...(entry.candidate.environmentRoot ? { environmentRoot: entry.candidate.environmentRoot } : {}),
685
- sourceWorkflowRunId: entry.candidate.sourceWorkflowRunId || 0,
686
- affectedPaths: entry.candidate.affectedPaths || [],
687
- deliveryClass: entry.candidate.deliveryClass,
688
- priority: entry.candidate.priority,
689
601
  nextAction: index === 0 && !queue.activeWarrant ? "eligible-for-selection" : "wait-for-active-warrant",
690
602
  })),
691
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
+ }