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

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 (69) hide show
  1. package/AGENTS.md +13 -5
  2. package/actions/promote-buildchain-ref/README.md +11 -6
  3. package/architecture/internal-capabilities.json +11 -2
  4. package/architecture/maintainability-policy.json +149 -17
  5. package/architecture/v4-floating-consumer-policy.json +75 -0
  6. package/architecture/v4-floating-consumer-policy.md +32 -0
  7. package/architecture/v4-runtime-ref-resume-authority.json +64 -0
  8. package/architecture/v4-stage-capsule-qualification.json +2 -2
  9. package/bin/internal/trust-release-release-handlers.mjs +5 -0
  10. package/contracts/fixtures/v4-floating-consumer-policy-v1/cases.json +53 -0
  11. package/contracts/fixtures/v4-runtime-ref-resume-authority-v1/scenario.json +15 -0
  12. package/contracts/v4-floating-consumer-policy-receipt-v1.schema.json +105 -0
  13. package/contracts/v4-runtime-ref-resume-authority-v1.schema.json +235 -0
  14. package/dist/site/buildchain-contract.json +101 -31
  15. package/dist/site/buildchain-site.json +73 -27
  16. package/dist/site/capability-registry.json +3 -3
  17. package/dist/site/controller-registry.json +62 -6
  18. package/dist/site/kfd-claims.json +68 -13
  19. package/dist/site/kfd-upstream-aggregate.json +1 -1
  20. package/dist/site/manual-registry.json +6 -6
  21. package/dist/site/node-api-registry.json +799 -127
  22. package/dist/site/page-registry.json +63 -17
  23. package/dist/site/public-surface-audit.json +49 -17
  24. package/dist/site/publication-registry.json +4 -4
  25. package/dist/site/release-provenance.json +2 -0
  26. package/dist/site/site-manifest.json +10 -10
  27. package/dist/site/workflow-registry.json +46 -18
  28. package/docs/MAP.md +2 -0
  29. package/docs/dev-delivery-warrant.md +19 -1
  30. package/docs/lifecycle-protocol.md +41 -0
  31. package/docs/node-api-reference.md +207 -134
  32. package/docs/reusable-build-surface.md +41 -0
  33. package/docs/runtime-train-validation.md +10 -0
  34. package/docs/v4-runtime-ref-resume-authority.md +69 -0
  35. package/docs/versioning.md +1 -0
  36. package/package.json +6 -4
  37. package/packages/core/artifact-signing.js +61 -0
  38. package/packages/core/buildchain-config.js +66 -1
  39. package/packages/core/dev-delivery-proof.js +37 -3
  40. package/packages/core/dev-delivery-warrant.js +3 -3
  41. package/packages/core/index.js +2 -0
  42. package/packages/core/publication-authority.js +5 -5
  43. package/packages/core/release-candidate.js +79 -19
  44. package/packages/core/release-passport.js +239 -33
  45. package/packages/core/v4-floating-consumer-evidence.js +324 -0
  46. package/packages/core/v4-floating-consumer-policy.js +446 -0
  47. package/packages/core/v4-floating-consumer-release-passport.js +126 -0
  48. package/packages/core/v4-runtime-ref-resume-authority.js +625 -0
  49. package/packages/core/v4-runtime-selector-persistence.js +228 -0
  50. package/packages/core/workflow-yaml-contract.js +48 -0
  51. package/scripts/audit-publication-control-plane.mjs +31 -31
  52. package/scripts/check-inventory.mjs +1 -1
  53. package/scripts/check-v4-floating-consumer-policy-contract.mjs +198 -0
  54. package/scripts/check-v4-public-dogfood-contract.mjs +6 -11
  55. package/scripts/dev-delivery-source-proof-reuse.mjs +631 -0
  56. package/scripts/dev-pr-auto-merge.mjs +37 -48
  57. package/scripts/dev-pr-delivery-warrant.mjs +205 -2
  58. package/scripts/dev-pr-prequeue-guard.mjs +399 -0
  59. package/scripts/ensure-github-release.mjs +3 -3
  60. package/scripts/generate-channel-build-workflow.mjs +3 -0
  61. package/scripts/generate-channel-promotion-workflow.mjs +112 -12
  62. package/scripts/generate-release-candidate-passport.mjs +41 -33
  63. package/scripts/init-repo.mjs +5 -1
  64. package/scripts/inspect-artifact-signing-requests.mjs +6 -0
  65. package/scripts/npm-publish-transaction.mjs +101 -89
  66. package/scripts/resume-from-candidate-run.mjs +11 -14
  67. package/scripts/seal-artifact-signing-requests.mjs +6 -0
  68. package/scripts/site-capability-metadata.mjs +2 -0
  69. package/scripts/v4-consumer-policy.mjs +231 -0
@@ -3,8 +3,8 @@ import crypto from "node:crypto";
3
3
  import { spawnSync } from "node:child_process";
4
4
  import fs from "node:fs";
5
5
  import path from "node:path";
6
- import { verifyProjectCutReplayProof } from "../packages/core/dev-delivery-warrant.js";
7
- import { admitExistingQueueEntry, createDevPrAdmissionReceipt, readDeliveryWarrantResult, runSourceQualification, runTargetedQueueAdmission } from "./dev-pr-delivery-warrant.mjs";
6
+ import { admitExistingQueueEntry, createDevPrAdmissionReceipt, qualifyAtomicQueueAdmission, readDeliveryWarrantResult, runSourceQualification, runTargetedQueueAdmission, setActiveLeaseStatus, verifyCurrentDeliveryWarrant } from "./dev-pr-delivery-warrant.mjs";
7
+ import { projectCutQualification } from "./dev-pr-prequeue-guard.mjs";
8
8
  const DEFAULT_BLOCK_LABELS = ["blocked", "do-not-merge", "work-in-progress"];
9
9
  const DEFAULT_ALLOWED_HEAD_PREFIXES = ["feature/", "fix/", "chore/", "docs/", "ci/", "refactor/"];
10
10
  const DEFAULT_REQUIRED_CHECKS = ["check"];
@@ -70,6 +70,7 @@ function normalizeOptions(options = {}) {
70
70
  allowedHeadPrefixes: splitList(options.allowedHeadPrefixes, DEFAULT_ALLOWED_HEAD_PREFIXES),
71
71
  requiredChecks: splitList(options.requiredChecks, DEFAULT_REQUIRED_CHECKS),
72
72
  queueAdmissionContext: String(options.queueAdmissionContext || "").trim(),
73
+ activeLeaseContext: String(options.activeLeaseContext || "").trim(),
73
74
  requireApproval: boolOption(options.requireApproval, true),
74
75
  sameRepositoryOnly: boolOption(options.sameRepositoryOnly, true),
75
76
  maxMerges: intOption(options.maxMerges, 1),
@@ -85,8 +86,10 @@ function normalizeOptions(options = {}) {
85
86
  warrantMode: choiceOption(options.warrantMode, VALID_WARRANT_MODES, "off", "delivery Warrant mode"),
86
87
  warrantResultPath: String(options.warrantResultPath || "").trim(),
87
88
  projectCutProofPath: String(options.projectCutProofPath || "").trim(),
89
+ sourceProofPath: String(options.sourceProofPath || ".buildchain/dev-delivery/source-proof.json").trim(),
88
90
  sourcePatchRoot: String(options.sourcePatchRoot || "").trim().toLowerCase(),
89
91
  qualificationOnly: boolOption(options.qualificationOnly, false),
92
+ verifiedDeliveryWarrant: options.verifiedDeliveryWarrant || null,
90
93
  };
91
94
  }
92
95
 
@@ -191,26 +194,8 @@ function mergeableAccepted(pr, landingMode = "direct", projectCutQualified = fal
191
194
  return state ? ["clean", "has_hooks", "unstable", "unknown", ...(landingMode === "queue" && pr.mergeable === true ? ["blocked", ...(projectCutQualified ? ["behind"] : [])] : [])].includes(state) : pr.mergeable === true;
192
195
  }
193
196
 
194
- async function projectCutQualification(pr, options, client) {
195
- if (!options.projectCutProofPath) return { ok: false, reason: "project-cut-proof-required" };
196
- let proof;
197
- try {
198
- proof = JSON.parse(fs.readFileSync(options.projectCutProofPath, "utf8"));
199
- } catch {
200
- return { ok: false, reason: "project-cut-proof-invalid" };
201
- }
202
- const currentBase = await client.getBranchSha(options.targetBranch).catch(() => "");
203
- const verification = verifyProjectCutReplayProof(proof, {
204
- repository: options.repository.fullName,
205
- protectedBase: options.targetBranch,
206
- pullRequestNumber: Number(pr.number),
207
- sourceHead: String(pr.head?.sha || "").toLowerCase(),
208
- ...(options.sourcePatchRoot ? { sourcePatchRoot: options.sourcePatchRoot } : {}),
209
- currentBase,
210
- });
211
- return verification.ok
212
- ? { ok: true, reason: verification.reason, proofRoot: verification.proofRoot, currentBase }
213
- : { ok: false, reason: `project-cut-${verification.reason}`, currentBase };
197
+ function rejectBaseMoveBeforeAtomicReplay(options, initialBaseSha, observedBaseSha) {
198
+ return observedBaseSha !== initialBaseSha && options.warrantMode !== "required";
214
199
  }
215
200
  async function setQueueAdmissionStatus(client, repository, sha, context, state) {
216
201
  if (!context) return null;
@@ -253,6 +238,7 @@ export async function evaluatePullRequest(pr, options, client) {
253
238
  ? await projectCutQualification(detailed, options, client)
254
239
  : null;
255
240
  if (projectCut && !projectCut.ok) return skip(projectCut.reason, { projectCut });
241
+ if (options.landingMode === "queue" && detailed.mergeable === false) return skip("pre-enqueue-merge-conflict", { mergeable: false, mergeableState });
256
242
  if (!mergeableAccepted(detailed, options.landingMode, projectCut?.ok === true)) {
257
243
  return skip("not-mergeable", {
258
244
  mergeable: detailed.mergeable,
@@ -493,11 +479,9 @@ export class GitHubClient {
493
479
  );
494
480
  return data;
495
481
  }
496
-
497
482
  async listIssueComments(number) {
498
483
  return this.paginate(`/repos/${this.repository.owner}/${this.repository.repo}/issues/${number}/comments?per_page=100`);
499
484
  }
500
-
501
485
  async createIssueComment(number, body) {
502
486
  const { data } = await this.request(
503
487
  "POST",
@@ -506,7 +490,6 @@ export class GitHubClient {
506
490
  );
507
491
  return data;
508
492
  }
509
-
510
493
  async updateIssueComment(commentId, body) {
511
494
  const { data } = await this.request(
512
495
  "PATCH",
@@ -515,7 +498,6 @@ export class GitHubClient {
515
498
  );
516
499
  return data;
517
500
  }
518
-
519
501
  async setCommitStatus(sha, { state, context, description, targetUrl = "" }) {
520
502
  const { data } = await this.request(
521
503
  "POST",
@@ -525,12 +507,20 @@ export class GitHubClient {
525
507
  return data;
526
508
  }
527
509
  }
528
-
510
+ function ghEnvironment() {
511
+ const environment = { ...process.env };
512
+ delete environment.GITHUB_TOKEN;
513
+ delete environment.GH_TOKEN;
514
+ return environment;
515
+ }
516
+ function ghAuthToken() {
517
+ const result = spawnSync("gh", ["auth", "token"], { encoding: "utf8", env: ghEnvironment() });
518
+ if (result.error) throw result.error;
519
+ if (result.status !== 0 || !result.stdout.trim()) throw new Error((result.stderr || "gh auth token failed").trim());
520
+ return result.stdout.trim();
521
+ }
529
522
  function ghJson(args, { input } = {}) {
530
- const ghEnvironment = { ...process.env };
531
- delete ghEnvironment.GITHUB_TOKEN;
532
- delete ghEnvironment.GH_TOKEN;
533
- const result = spawnSync("gh", args, { encoding: "utf8", input, env: ghEnvironment });
523
+ const result = spawnSync("gh", args, { encoding: "utf8", input, env: ghEnvironment() });
534
524
  if (result.error) throw result.error;
535
525
  if (result.status !== 0) {
536
526
  const error = new Error((result.stderr || result.stdout || "gh command failed").trim());
@@ -539,12 +529,10 @@ function ghJson(args, { input } = {}) {
539
529
  }
540
530
  return result.stdout.trim() ? JSON.parse(result.stdout) : null;
541
531
  }
542
-
543
532
  export class GhCliClient extends GitHubClient {
544
- constructor({ repository } = {}) {
545
- super({ token: "gh-cli", repository, fetchImpl: async () => { throw new Error("unexpected fetch"); } });
533
+ constructor({ repository, token = "", fetchImpl = globalThis.fetch } = {}) {
534
+ super({ token: token || ghAuthToken(), repository, fetchImpl });
546
535
  }
547
-
548
536
  async request(method, requestPath, { body } = {}) {
549
537
  const endpoint = requestPath.replace(/^https:\/\/api\.github\.com/, "");
550
538
  const args = ["api", "--method", method, endpoint];
@@ -554,11 +542,9 @@ export class GhCliClient extends GitHubClient {
554
542
  response: { headers: { get: () => "" } },
555
543
  };
556
544
  }
557
-
558
545
  async paginate(requestPath) {
559
546
  return ghJson(["api", "--paginate", requestPath, "--slurp"]).flatMap((page) => page);
560
547
  }
561
-
562
548
  async getMergeQueueState(branch) {
563
549
  const query = `query($owner:String!,$repo:String!,$branch:String!){repository(owner:$owner,name:$repo){mergeQueue(branch:$branch){id entries(first:100){nodes{id position state baseCommit{oid} headCommit{oid} pullRequest{number headRefOid}}}}}}`;
564
550
  const data = ghJson([
@@ -852,7 +838,7 @@ export async function runDevPrAdmission(optionsInput = {}, clientInput) {
852
838
  const initialQueue = await client.getMergeQueueState(options.targetBranch);
853
839
  let warrant = null;
854
840
  try {
855
- warrant = readDeliveryWarrantResult(options, pr);
841
+ warrant = readDeliveryWarrantResult(options, pr); await verifyCurrentDeliveryWarrant(client, options, pr, warrant);
856
842
  } catch (error) {
857
843
  return reject("blocked", error.code || "invalid-delivery-warrant");
858
844
  }
@@ -890,9 +876,9 @@ function finalizePatrolResult(result) {
890
876
 
891
877
  async function reconcileEnqueueError({ client, options, pr, expectedHeadSha, entry, result, error }) {
892
878
  const queueReadback = await client.getMergeQueueState(options.targetBranch).catch(() => null);
893
- const exactEntry = queueReadback?.entries?.find((candidate) =>
894
- candidate.pullRequestNumber === pr.number && candidate.pullRequestHeadSha === expectedHeadSha);
879
+ const exactEntry = queueReadback?.entries?.find((candidate) => candidate.pullRequestNumber === pr.number && candidate.pullRequestHeadSha === expectedHeadSha);
895
880
  if (exactEntry) {
881
+ entry.activeLeaseStatus = await setActiveLeaseStatus(client, options.repository, expectedHeadSha, options.activeLeaseContext, "pending");
896
882
  entry.action = "enqueued";
897
883
  entry.reason = "already-enqueued-exact-head";
898
884
  entry.queueEntry = exactEntry;
@@ -902,9 +888,11 @@ async function reconcileEnqueueError({ client, options, pr, expectedHeadSha, ent
902
888
  return;
903
889
  }
904
890
  entry.queueAdmissionStatus = await setQueueAdmissionStatus(client, options.repository, expectedHeadSha, options.queueAdmissionContext, "failure");
891
+ entry.activeLeaseStatus = await setActiveLeaseStatus(client, options.repository, expectedHeadSha, options.activeLeaseContext, "failure");
905
892
  entry.action = "skip";
906
- entry.reason = "enqueue-rejected";
893
+ entry.reason = error.preEnqueue ? (error.code || "pre-enqueue-qualification-failed") : "enqueue-rejected";
907
894
  entry.enqueueError = {
895
+ phase: error.preEnqueue ? "pre-enqueue" : "enqueue",
908
896
  status: error.status || null,
909
897
  message: error.message || "GitHub rejected merge queue admission",
910
898
  };
@@ -1027,7 +1015,7 @@ export async function runDevPrAutoMerge(optionsInput = {}, clientInput) {
1027
1015
  admissionDecision = "blocked";
1028
1016
  admissionReason = "blocked-by-predecessor";
1029
1017
  predecessor = queuePredecessor(observedQueueState);
1030
- } else if (observedBaseSha !== initialBaseSha) {
1018
+ } else if (rejectBaseMoveBeforeAtomicReplay(options, initialBaseSha, observedBaseSha)) {
1031
1019
  admissionDecision = "rejected";
1032
1020
  admissionReason = "base-sha-drift";
1033
1021
  } else if (observedHeadSha !== expectedHeadSha) {
@@ -1067,13 +1055,12 @@ export async function runDevPrAutoMerge(optionsInput = {}, clientInput) {
1067
1055
  result.skipped.push(entry);
1068
1056
  } else {
1069
1057
  try {
1070
- entry.queueAdmissionStatus = await setQueueAdmissionStatus(client, options.repository, expectedHeadSha, options.queueAdmissionContext, "success");
1071
- const queueEntry = await client.enqueuePullRequest({
1072
- pullRequestId: decision.pullRequestId,
1073
- expectedHeadOid: expectedHeadSha,
1074
- });
1058
+ const atomicAdmission = await qualifyAtomicQueueAdmission({ client, options, pullRequest: pr, expectedBaseSha: initialBaseSha, expectedHeadSha, projectCut: decision.projectCut, sleep: delay, mergeableAccepted, root: contentRoot,
1059
+ setActiveLeaseStatus: (state) => setActiveLeaseStatus(client, options.repository, expectedHeadSha, options.activeLeaseContext, state), setQueueAdmissionStatus: (state) => setQueueAdmissionStatus(client, options.repository, expectedHeadSha, options.queueAdmissionContext, state) });
1060
+ Object.assign(entry, atomicAdmission.entryFields);
1061
+ const queueEntry = atomicAdmission.exactEntry || await client.enqueuePullRequest({ pullRequestId: decision.pullRequestId, expectedHeadOid: expectedHeadSha });
1075
1062
  entry.action = "enqueued";
1076
- entry.reason = "enqueued-with-expected-head";
1063
+ entry.reason = atomicAdmission.exactEntry ? "already-enqueued-exact-head" : "enqueued-with-expected-head";
1077
1064
  entry.queueEntry = queueEntry;
1078
1065
  entry.admissionReceipt.reason = entry.reason;
1079
1066
  result.actions.push(entry);
@@ -1155,10 +1142,12 @@ export function cliOptions(args = [], environment = process.env) {
1155
1142
  allowedHeadPrefixes: cliValue(args, "allowed-head-prefixes", environment.BUILDCHAIN_DEV_PR_ALLOWED_HEAD_PREFIXES),
1156
1143
  requiredChecks: cliValue(args, "required-checks", environment.BUILDCHAIN_DEV_PR_REQUIRED_CHECKS),
1157
1144
  queueAdmissionContext: cliValue(args, "queue-admission-context", environment.BUILDCHAIN_DEV_PR_QUEUE_ADMISSION_CONTEXT),
1145
+ activeLeaseContext: cliValue(args, "active-lease-context", environment.BUILDCHAIN_DEV_PR_ACTIVE_LEASE_CONTEXT),
1158
1146
  diagnosticContext: cliValue(args, "diagnostic-context", environment.BUILDCHAIN_DEV_PR_DIAGNOSTIC_CONTEXT),
1159
1147
  warrantMode: cliValue(args, "warrant-mode", environment.BUILDCHAIN_DEV_PR_WARRANT_MODE),
1160
1148
  warrantResultPath: cliValue(args, "warrant-result", environment.BUILDCHAIN_DEV_PR_WARRANT_RESULT_PATH),
1161
1149
  projectCutProofPath: cliValue(args, "project-cut-proof", environment.BUILDCHAIN_DEV_PR_PROJECT_CUT_PROOF_PATH),
1150
+ sourceProofPath: cliValue(args, "source-proof", environment.BUILDCHAIN_DEV_PR_SOURCE_PROOF_PATH),
1162
1151
  sourcePatchRoot: cliValue(args, "source-patch-root", environment.BUILDCHAIN_DEV_PR_SOURCE_PATCH_ROOT),
1163
1152
  qualificationOnly: cliFlag(args, "qualification-only"),
1164
1153
  requireApproval: environment.BUILDCHAIN_DEV_PR_REQUIRE_APPROVAL,
@@ -1,4 +1,6 @@
1
1
  import fs from "node:fs";
2
+ import { defaultDevDeliveryStateRef, GitHubDevDeliveryStore } from "./dev-delivery-warrant.mjs";
3
+ import { qualifyPreEnqueueReadback } from "./dev-pr-prequeue-guard.mjs";
2
4
 
3
5
  const ROOT_PATTERN = /^sha256:[0-9a-f]{64}$/;
4
6
  const SHA_PATTERN = /^[0-9a-f]{40}$/;
@@ -113,9 +115,203 @@ export function readDeliveryWarrantResult(options, pullRequest) {
113
115
  generation: warrant.generation,
114
116
  issuedAt: warrant.issuedAt,
115
117
  expiresAt: warrant.expiresAt,
118
+ repository: warrant.repository,
119
+ protectedBase: warrant.protectedBase,
120
+ pullRequestNumber: warrant.pullRequestNumber,
121
+ sourceHead: warrant.sourceHead,
122
+ sourceProofRoot: warrant.sourceProofRoot,
116
123
  };
117
124
  }
118
125
 
126
+ export async function readCurrentDeliveryQueueState(client, repository, targetBranch) {
127
+ if (typeof client.getDevDeliveryQueueState === "function") {
128
+ return client.getDevDeliveryQueueState(targetBranch);
129
+ }
130
+ const store = new GitHubDevDeliveryStore({
131
+ repository: `${repository.owner}/${repository.repo}`,
132
+ token: client.token,
133
+ apiUrl: client.apiUrl,
134
+ fetchImpl: client.fetch,
135
+ });
136
+ const { queue } = await store.read({
137
+ stateRef: defaultDevDeliveryStateRef(targetBranch),
138
+ protectedBase: targetBranch,
139
+ });
140
+ return queue;
141
+ }
142
+
143
+ export async function verifyCurrentDeliveryWarrant(client, options, pullRequest, warrant) {
144
+ if (!warrant) return null;
145
+ let queue;
146
+ try {
147
+ queue = await readCurrentDeliveryQueueState(
148
+ client,
149
+ options.repository,
150
+ options.targetBranch,
151
+ );
152
+ } catch {
153
+ mismatch("delivery-warrant-current-readback-failed");
154
+ }
155
+ const active = queue?.activeWarrant;
156
+ const candidate = queue?.candidates?.find(
157
+ (entry) => entry.candidateId === active?.candidateId,
158
+ );
159
+ requireMatch(active?.candidateId === warrant.candidateId, "delivery-warrant-no-longer-active");
160
+ requireMatch(active?.fencingToken === warrant.fencingToken, "delivery-warrant-current-fencing-mismatch");
161
+ requireMatch(Number(active?.generation) === Number(warrant.generation), "delivery-warrant-current-generation-mismatch");
162
+ requireMatch(Number(active?.pullRequestNumber) === Number(pullRequest.number), "delivery-warrant-current-pr-mismatch");
163
+ requireMatch(String(active?.sourceHead || "").toLowerCase() === options.expectedHeadSha, "delivery-warrant-current-head-mismatch");
164
+ requireMatch(active?.sourceProofRoot === warrant.sourceProofRoot, "delivery-warrant-current-source-proof-mismatch");
165
+ requireMatch(Number.isFinite(Date.parse(active?.expiresAt)) && Date.parse(active.expiresAt) > Date.now(), "delivery-warrant-current-expired");
166
+ requireMatch(["selected", "proving", "waiting", "blocked", "qualified"].includes(candidate?.status), "delivery-warrant-current-candidate-not-selected");
167
+ requireMatch(candidate?.sourceHead === active.sourceHead, "delivery-warrant-current-candidate-head-mismatch");
168
+ return { activeWarrant: active, activeCandidate: candidate };
169
+ }
170
+
171
+ function latestStatusForContext(statuses, context) {
172
+ return (statuses || []).find(
173
+ (status) => String(status.context || "") === context,
174
+ ) || null;
175
+ }
176
+
177
+ function preEnqueueMismatch(code, details = {}) {
178
+ const error = new Error(code);
179
+ error.code = code;
180
+ Object.assign(error, details);
181
+ throw error;
182
+ }
183
+
184
+ export async function setActiveLeaseStatus(client, repository, sha, context, state) {
185
+ if (!context) return null;
186
+ await client.request("POST", `/repos/${repository.owner}/${repository.repo}/statuses/${sha}`, {
187
+ body: {
188
+ state,
189
+ context,
190
+ description: state === "pending"
191
+ ? "Buildchain reactivated this exact lease for merge-group qualification"
192
+ : "Buildchain released this exact lease after queue admission failed",
193
+ },
194
+ });
195
+ return { context, state, sha };
196
+ }
197
+
198
+ async function readBackAdmissionStatuses(client, options, expectedHeadSha, sleep) {
199
+ let last = { queueAdmission: null, activeLease: null };
200
+ const attempts = Math.max(1, options.pollMergeableAttempts);
201
+ for (let attempt = 1; attempt <= attempts; attempt += 1) {
202
+ const checks = await client.listCommitChecks(expectedHeadSha);
203
+ last = {
204
+ queueAdmission: latestStatusForContext(
205
+ checks?.statuses,
206
+ options.queueAdmissionContext,
207
+ ),
208
+ activeLease: latestStatusForContext(
209
+ checks?.statuses,
210
+ options.activeLeaseContext,
211
+ ),
212
+ };
213
+ if (
214
+ (!options.queueAdmissionContext || last.queueAdmission?.state === "success") &&
215
+ (!options.activeLeaseContext || last.activeLease?.state === "pending")
216
+ ) {
217
+ return { ...last, attempts: attempt };
218
+ }
219
+ if (attempt < attempts) await sleep(options.pollMergeableDelayMs);
220
+ }
221
+ preEnqueueMismatch("queue-admission-lease-readback-mismatch", { readback: last });
222
+ }
223
+
224
+ export async function qualifyAtomicQueueAdmission({
225
+ client,
226
+ options,
227
+ pullRequest,
228
+ expectedBaseSha,
229
+ expectedHeadSha,
230
+ projectCut,
231
+ setActiveLeaseStatus,
232
+ setQueueAdmissionStatus,
233
+ sleep,
234
+ mergeableAccepted,
235
+ root,
236
+ }) {
237
+ try {
238
+ if (options.warrantMode === "required") {
239
+ if (!options.verifiedDeliveryWarrant) {
240
+ preEnqueueMismatch("delivery-warrant-pre-enqueue-readback-missing");
241
+ }
242
+ if (!options.queueAdmissionContext) {
243
+ preEnqueueMismatch("queue-admission-context-required");
244
+ }
245
+ if (!options.activeLeaseContext) {
246
+ preEnqueueMismatch("active-lease-context-required");
247
+ }
248
+ }
249
+ const activeLeaseStatus = await setActiveLeaseStatus("pending");
250
+ const queueAdmissionStatus = await setQueueAdmissionStatus("success");
251
+ const statusReadback = await readBackAdmissionStatuses(
252
+ client,
253
+ options,
254
+ expectedHeadSha,
255
+ sleep,
256
+ );
257
+ const { observedBaseSha, observedQueueState, currentWarrant, preEnqueueProjectCut } = await qualifyPreEnqueueReadback({
258
+ client, options, pullRequest, expectedBaseSha, expectedHeadSha, projectCut, mergeableAccepted, root, verifyCurrentWarrant: verifyCurrentDeliveryWarrant,
259
+ });
260
+ const exactEntry = observedQueueState.entries.find(
261
+ (candidate) => candidate.pullRequestNumber === pullRequest.number &&
262
+ candidate.pullRequestHeadSha === expectedHeadSha,
263
+ );
264
+ const predecessor = observedQueueState.entries.find(
265
+ (candidate) => candidate !== exactEntry,
266
+ ) || null;
267
+ if (predecessor) {
268
+ preEnqueueMismatch("queue-predecessor-after-lease-readback", { predecessor });
269
+ }
270
+ const transaction = {
271
+ schema: "kungfu.buildchain.dev-queue-admission-transaction/v1",
272
+ repository: options.repository.fullName,
273
+ protectedBase: options.targetBranch,
274
+ pullRequestNumber: pullRequest.number,
275
+ sourceHead: expectedHeadSha,
276
+ frozenBase: expectedBaseSha,
277
+ admittedBase: observedBaseSha,
278
+ queueAdmission: {
279
+ context: options.queueAdmissionContext,
280
+ state: statusReadback.queueAdmission?.state || "",
281
+ },
282
+ activeLease: {
283
+ context: options.activeLeaseContext,
284
+ state: statusReadback.activeLease?.state || "",
285
+ },
286
+ warrant: options.verifiedDeliveryWarrant,
287
+ currentWarrant: currentWarrant ? {
288
+ candidateId: currentWarrant.activeWarrant.candidateId,
289
+ fencingToken: currentWarrant.activeWarrant.fencingToken,
290
+ generation: currentWarrant.activeWarrant.generation,
291
+ sourceHead: currentWarrant.activeWarrant.sourceHead,
292
+ expiresAt: currentWarrant.activeWarrant.expiresAt,
293
+ } : null,
294
+ projectCutProofRoot: projectCut?.proofRoot || "",
295
+ preEnqueueProjectCut: preEnqueueProjectCut?.receipt || null,
296
+ preEnqueueProjectCutRoot: preEnqueueProjectCut?.receiptRoot || "",
297
+ decision: exactEntry ? "already-enqueued" : "qualified",
298
+ };
299
+ return {
300
+ exactEntry,
301
+ entryFields: {
302
+ activeLeaseStatus,
303
+ queueAdmissionStatus,
304
+ atomicAdmissionReceipt: transaction,
305
+ atomicAdmissionReceiptRoot: root(transaction),
306
+ atomicAdmissionReadbackAttempts: statusReadback.attempts,
307
+ },
308
+ };
309
+ } catch (error) {
310
+ error.preEnqueue = true;
311
+ throw error;
312
+ }
313
+ }
314
+
119
315
  export async function runSourceQualification({ options, pullRequest, readiness, client, evaluate, admissionState, createReceipt, root, publishDiagnostic, reject }) {
120
316
  const decision = await evaluate(pullRequest, { ...options, landingMode: options.landingMode, dryRun: true }, client);
121
317
  if (decision.observedHeadSha && String(decision.observedHeadSha).toLowerCase() !== options.expectedHeadSha) {
@@ -147,13 +343,14 @@ export async function runSourceQualification({ options, pullRequest, readiness,
147
343
 
148
344
  export async function admitExistingQueueEntry({ options, pullRequest, readiness, client, entry, warrant, createReceipt, root, publishDiagnostic }) {
149
345
  if (!entry) return null;
346
+ const activeLeaseStatus = options.dryRun ? null : await setActiveLeaseStatus(client, options.repository, options.expectedHeadSha, options.activeLeaseContext, "pending");
150
347
  const receipt = createReceipt({
151
348
  options,
152
349
  pr: pullRequest,
153
350
  state: "queued",
154
351
  reason: "already-enqueued-exact-head",
155
352
  readiness,
156
- queue: { enabled: true, entry },
353
+ queue: { enabled: true, entry, activeLeaseStatus },
157
354
  warrant,
158
355
  });
159
356
  const result = {
@@ -172,7 +369,11 @@ export async function admitExistingQueueEntry({ options, pullRequest, readiness,
172
369
  export async function runTargetedQueueAdmission({ options, pullRequest, readiness, client, warrant, runController, admissionState, createReceipt, root, publishDiagnostic }) {
173
370
  const targetedClient = Object.create(client);
174
371
  targetedClient.listPullRequests = async () => [pullRequest];
175
- const controller = await runController({ ...options, targetPullRequestNumber: 0 }, targetedClient);
372
+ const controller = await runController({
373
+ ...options,
374
+ targetPullRequestNumber: 0,
375
+ verifiedDeliveryWarrant: warrant,
376
+ }, targetedClient);
176
377
  controller.runKind = "targeted-admission-evaluation";
177
378
  controller.outcome = controller.actions.length === 0 ? "target-not-admitted" : "target-action-selected";
178
379
  controller.qualification = false;
@@ -190,6 +391,8 @@ export async function runTargetedQueueAdmission({ options, pullRequest, readines
190
391
  enabled: controller.mergeQueue?.enabled === true,
191
392
  predecessor: entry.admissionReceipt?.predecessor || null,
192
393
  entry: entry.queueEntry || null,
394
+ admissionTransaction: entry.atomicAdmissionReceipt || null,
395
+ admissionTransactionRoot: entry.atomicAdmissionReceiptRoot || "",
193
396
  },
194
397
  warrant,
195
398
  });