@kungfu-tech/buildchain 3.0.9-alpha.1 → 3.0.9-alpha.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. package/bin/buildchain.mjs +9 -1
  2. package/contracts/dev-delivery-authority-v2.schema.json +253 -0
  3. package/contracts/fixtures/next-development-transition-v1/anchored-manual-waiting.json +47 -0
  4. package/contracts/fixtures/next-development-transition-v1/semver-auto-planned.json +47 -0
  5. package/contracts/fixtures/next-development-transition-v1/version-model-cases.json +40 -0
  6. package/contracts/next-development-request-v1.schema.json +66 -0
  7. package/contracts/next-development-transition-v1.schema.json +292 -0
  8. package/dist/site/agent-index.json +1 -0
  9. package/dist/site/artifact-schemas.json +2 -0
  10. package/dist/site/buildchain-contract.json +74 -14
  11. package/dist/site/buildchain-site.json +334 -36
  12. package/dist/site/capability-registry.json +7 -6
  13. package/dist/site/cli-registry.json +41 -2
  14. package/dist/site/kfd-claims.json +193 -9
  15. package/dist/site/kfd-upstream-aggregate.json +9 -9
  16. package/dist/site/manual-registry.json +23 -7
  17. package/dist/site/node-api-registry.json +7789 -4648
  18. package/dist/site/page-registry.json +315 -25
  19. package/dist/site/public-surface-audit.json +353 -8
  20. package/dist/site/publication-registry.json +4 -4
  21. package/dist/site/release-passport-check-manifest.json +1 -0
  22. package/dist/site/release-provenance.json +12 -0
  23. package/dist/site/schemas/dev-delivery-authority-v2.schema.json +442 -0
  24. package/dist/site/schemas/release-passport-v1.schema.json +3 -0
  25. package/dist/site/site-manifest.json +19 -11
  26. package/dist/site/workflow-registry.json +15 -7
  27. package/docs/MAP.md +5 -2
  28. package/docs/adopter-delivery-gate.md +106 -0
  29. package/docs/aws-us-elastic-runner-burst-plane.md +30 -3
  30. package/docs/cli-reference.md +200 -13
  31. package/docs/dev-alpha-candidate-patrol.md +8 -0
  32. package/docs/dev-delivery-qualification-landing-adr.md +137 -0
  33. package/docs/dev-delivery-warrant.md +149 -22
  34. package/docs/kfd-support.md +7 -2
  35. package/docs/next-development-transition.md +119 -0
  36. package/docs/node-api-reference.md +381 -204
  37. package/docs/release-governance.md +10 -7
  38. package/docs/release-passport.md +8 -2
  39. package/docs/versioning.md +4 -1
  40. package/package.json +21 -6
  41. package/packages/core/README.md +25 -0
  42. package/packages/core/adopter-delivery-gate.js +576 -0
  43. package/packages/core/adopter-delivery-json.js +66 -0
  44. package/packages/core/adopter-delivery-passport.js +259 -0
  45. package/packages/core/adopter-delivery-vectors.js +158 -0
  46. package/packages/core/adopter-delivery-vectors.json +77 -0
  47. package/packages/core/artifact-verification-envelope.js +5 -5
  48. package/packages/core/buildchain-agent-manuals.js +1 -0
  49. package/packages/core/buildchain-channel-identity.js +2 -3
  50. package/packages/core/buildchain-compatibility-proof.js +22 -0
  51. package/packages/core/buildchain-delivery-bootstrap.js +240 -0
  52. package/packages/core/buildchain-delivery-infrastructure.js +164 -0
  53. package/packages/core/channel-candidate.js +8 -0
  54. package/packages/core/channel-promotion-baseline.js +52 -0
  55. package/packages/core/dev-alpha-candidate-selection.js +10 -2
  56. package/packages/core/dev-delivery-authority.js +996 -0
  57. package/packages/core/dev-delivery-native-proof.js +418 -0
  58. package/packages/core/dev-delivery-warrant-settlement.js +67 -20
  59. package/packages/core/dev-delivery-warrant.js +128 -46
  60. package/packages/core/kfd-adopter-category-driver.js +167 -0
  61. package/packages/core/kfd-adopter-manifest.js +49 -50
  62. package/packages/core/legacy-kfd-adopter-driver.js +167 -0
  63. package/packages/core/next-development-candidate-reservation.js +186 -0
  64. package/packages/core/next-development-controller.js +726 -0
  65. package/packages/core/next-development-projection.js +288 -0
  66. package/packages/core/next-development-transition.js +738 -0
  67. package/packages/core/paper-agent-entry.js +7 -4
  68. package/packages/core/paper.js +14 -7
  69. package/packages/core/release-passport-contract.js +10 -6
  70. package/packages/core/release-passport.js +29 -12
  71. package/scripts/aws-macos-jit-controller-core.mjs +239 -4
  72. package/scripts/aws-macos-jit-controller.mjs +198 -2
  73. package/scripts/aws-macos-jit-instance-rehydrate.mjs +260 -0
  74. package/scripts/aws-macos-jit-source-rebind.mjs +235 -14
  75. package/scripts/aws-macos-jit.mjs +12 -0
  76. package/scripts/buildchain-cli-help.mjs +9 -2
  77. package/scripts/check-internal-architecture.mjs +1 -0
  78. package/scripts/check-inventory.mjs +12 -1
  79. package/scripts/dev-alpha-candidate-patrol.mjs +22 -1
  80. package/scripts/dev-delivery-authority.mjs +368 -0
  81. package/scripts/dev-delivery-native-run.mjs +235 -0
  82. package/scripts/dev-delivery-proof.mjs +64 -2
  83. package/scripts/dev-delivery-two-phase-resume.mjs +90 -0
  84. package/scripts/dev-delivery-two-phase.mjs +577 -0
  85. package/scripts/dev-delivery-warrant.mjs +47 -5
  86. package/scripts/dev-pr-delivery-warrant.mjs +19 -14
  87. package/scripts/generate-buildchain-kfd-witnesses.mjs +2 -2
  88. package/scripts/generate-channel-build-workflow.mjs +4 -0
  89. package/scripts/generate-next-development-guidance.mjs +49 -0
  90. package/scripts/generate-site-bundle.mjs +8 -3
  91. package/scripts/init-repo.mjs +135 -62
  92. package/scripts/next-development-self-dogfood-harness.mjs +409 -0
  93. package/scripts/next-development-self-dogfood.mjs +532 -0
  94. package/scripts/next-development-transition.mjs +47 -0
  95. package/scripts/release-candidate-tail-reseal.mjs +426 -0
  96. package/scripts/seal-artifact-signing-requests.mjs +7 -4
  97. package/scripts/site-capability-metadata.mjs +23 -1
  98. package/scripts/stable-candidate-qualification.mjs +7 -7
  99. package/scripts/workflow-call-contract.mjs +1 -1
  100. package/templates/native-dev-delivery.yml +86 -0
@@ -28,7 +28,169 @@ function priorOwnershipPlan(plan) {
28
28
  };
29
29
  }
30
30
 
31
- function campaignRunsWithNoWork(plan) {
31
+ function assertRunMatchesPolicy(policy, run, jobs, jobCount, artifactCount) {
32
+ if (policy === "unused") {
33
+ if (jobCount !== 0 || artifactCount !== 0) {
34
+ throw new Error(
35
+ `macOS campaign run ${run.id} already has jobs or artifacts`,
36
+ );
37
+ }
38
+ return;
39
+ }
40
+ if (policy === "preflight-failure") {
41
+ const jobList = jobs.jobs || [];
42
+ const failedJobs = jobList.filter((job) => job.conclusion === "failure");
43
+ const nonFailedJobs = jobList.filter((job) => job.conclusion !== "failure");
44
+ const hasJitLabel = jobList.some((job) =>
45
+ (job.labels || []).some((label) =>
46
+ String(label.name || label).startsWith(MACOS_JIT_RUNNER_LABEL_PREFIX),
47
+ ),
48
+ );
49
+ if (
50
+ run.status !== "completed" ||
51
+ run.conclusion !== "failure" ||
52
+ jobCount === 0 ||
53
+ artifactCount === 0 ||
54
+ jobList.some((job) => job.status !== "completed") ||
55
+ failedJobs.length !== 1 ||
56
+ !String(failedJobs[0].name || "").endsWith(" / Trust gate") ||
57
+ nonFailedJobs.some((job) => job.conclusion !== "skipped") ||
58
+ hasJitLabel
59
+ ) {
60
+ throw new Error(
61
+ `macOS campaign run ${run.id} is not an exact preflight Trust gate failure`,
62
+ );
63
+ }
64
+ return;
65
+ }
66
+ if (
67
+ run.status !== "completed" ||
68
+ run.conclusion !== "failure" ||
69
+ jobCount === 0 ||
70
+ artifactCount === 0 ||
71
+ (jobs.jobs || []).some((job) => job.status !== "completed")
72
+ ) {
73
+ throw new Error(
74
+ `macOS campaign run ${run.id} is not a terminal failed run with retained evidence`,
75
+ );
76
+ }
77
+ }
78
+
79
+ function assertExactStartupFailure(run, jobCount, artifactCount) {
80
+ if (
81
+ run.status !== "completed" ||
82
+ run.conclusion !== "startup_failure" ||
83
+ jobCount !== 0 ||
84
+ artifactCount !== 0
85
+ ) {
86
+ throw new Error(
87
+ `macOS campaign run ${run.id} is not an exact startup failure`,
88
+ );
89
+ }
90
+ }
91
+
92
+ function assertExactSuccessfulRun(run, jobs, jobCount, artifactCount) {
93
+ if (
94
+ run.status !== "completed" ||
95
+ run.conclusion !== "success" ||
96
+ jobCount === 0 ||
97
+ artifactCount === 0 ||
98
+ (jobs.jobs || []).some((job) => job.status !== "completed")
99
+ ) {
100
+ throw new Error(
101
+ `macOS campaign run ${run.id} is not a terminal successful run with retained evidence`,
102
+ );
103
+ }
104
+ }
105
+
106
+ function classifyCampaignRun(plan, run) {
107
+ const startupFailure = plan.github.startupFailureRuns.find(
108
+ ({ runId }) => runId === String(run.id),
109
+ );
110
+ const historicalTerminalFailure =
111
+ plan.github.historicalTerminalFailureRuns.find(
112
+ ({ runId }) => runId === String(run.id),
113
+ );
114
+ const historicalPreflightFailure =
115
+ plan.github.historicalPreflightFailureRuns.find(
116
+ ({ runId }) => runId === String(run.id),
117
+ );
118
+ const preflightFailure = plan.github.preflightFailureRunIds.includes(
119
+ String(run.id),
120
+ );
121
+ const successfulRun = plan.github.successfulRunIds.includes(String(run.id));
122
+ return {
123
+ startupFailure,
124
+ historicalTerminalFailure,
125
+ historicalPreflightFailure,
126
+ successfulRun,
127
+ expectedSourceSha:
128
+ startupFailure?.sourceSha ||
129
+ historicalTerminalFailure?.sourceSha ||
130
+ historicalPreflightFailure?.sourceSha ||
131
+ plan.previousSource.sha,
132
+ classification: startupFailure
133
+ ? "startup-failure"
134
+ : historicalTerminalFailure
135
+ ? "historical-terminal-failure"
136
+ : historicalPreflightFailure
137
+ ? "historical-preflight-failure"
138
+ : successfulRun
139
+ ? "successful-run"
140
+ : preflightFailure
141
+ ? "preflight-failure"
142
+ : plan.github.priorRunPolicy,
143
+ };
144
+ }
145
+
146
+ function exactReceiptInventory(receipts, classification, withSource = false) {
147
+ return receipts
148
+ .filter((receipt) => receipt.classification === classification)
149
+ .map((receipt) =>
150
+ withSource
151
+ ? { runId: receipt.runId, sourceSha: receipt.sourceSha }
152
+ : receipt.runId,
153
+ )
154
+ .sort(
155
+ (left, right) =>
156
+ Number(withSource ? left.runId : left) -
157
+ Number(withSource ? right.runId : right),
158
+ );
159
+ }
160
+
161
+ function assertExactReceiptInventories(plan, receipts) {
162
+ if (plan.github.priorRunPolicy === "unused") return;
163
+ const inventories = [
164
+ ["terminal-failure", plan.github.terminalFailureRunIds, false],
165
+ ["preflight-failure", plan.github.preflightFailureRunIds, false],
166
+ ["successful-run", plan.github.successfulRunIds, false],
167
+ ["startup-failure", plan.github.startupFailureRuns, true],
168
+ [
169
+ "historical-terminal-failure",
170
+ plan.github.historicalTerminalFailureRuns,
171
+ true,
172
+ ],
173
+ [
174
+ "historical-preflight-failure",
175
+ plan.github.historicalPreflightFailureRuns,
176
+ true,
177
+ ],
178
+ ];
179
+ for (const [classification, expected, withSource] of inventories) {
180
+ const observed = exactReceiptInventory(
181
+ receipts,
182
+ classification,
183
+ withSource,
184
+ );
185
+ if (JSON.stringify(observed) !== JSON.stringify(expected)) {
186
+ throw new Error(
187
+ `macOS campaign ${classification} inventory does not match the confirmed runs`,
188
+ );
189
+ }
190
+ }
191
+ }
192
+
193
+ function campaignRunReceipts(plan) {
32
194
  const branch = sourceRefName(plan.source.ref);
33
195
  const response = ghJson(
34
196
  [
@@ -46,7 +208,8 @@ function campaignRunsWithNoWork(plan) {
46
208
  }
47
209
  const receipts = [];
48
210
  for (const run of matching) {
49
- if (run.head_sha !== plan.previousSource.sha) {
211
+ const classification = classifyCampaignRun(plan, run);
212
+ if (run.head_sha !== classification.expectedSourceSha) {
50
213
  throw new Error(
51
214
  `macOS campaign run ${run.id} is bound to an unexpected source`,
52
215
  );
@@ -68,19 +231,41 @@ function campaignRunsWithNoWork(plan) {
68
231
  const artifactCount = Number(
69
232
  artifacts.total_count || (artifacts.artifacts || []).length || 0,
70
233
  );
71
- if (jobCount !== 0 || artifactCount !== 0) {
72
- throw new Error(
73
- `macOS campaign run ${run.id} already has jobs or artifacts`,
234
+ if (classification.startupFailure) {
235
+ assertExactStartupFailure(run, jobCount, artifactCount);
236
+ } else if (classification.successfulRun) {
237
+ assertExactSuccessfulRun(run, jobs, jobCount, artifactCount);
238
+ } else {
239
+ assertRunMatchesPolicy(
240
+ classification.historicalTerminalFailure
241
+ ? "terminal-failure"
242
+ : classification.historicalPreflightFailure
243
+ ? "preflight-failure"
244
+ : plan.github.priorRunPolicy,
245
+ run,
246
+ jobs,
247
+ jobCount,
248
+ artifactCount,
74
249
  );
75
250
  }
76
251
  receipts.push({
77
252
  runId: String(run.id),
253
+ sourceSha: String(run.head_sha || ""),
254
+ classification: classification.classification,
78
255
  status: String(run.status || "unknown"),
79
256
  conclusion: String(run.conclusion || ""),
80
257
  jobCount,
81
258
  artifactCount,
259
+ artifacts: (artifacts.artifacts || []).map((artifact) => ({
260
+ id: String(artifact.id),
261
+ name: String(artifact.name || ""),
262
+ sizeInBytes: Number(artifact.size_in_bytes || 0),
263
+ digest: String(artifact.digest || ""),
264
+ expired: artifact.expired === true,
265
+ })),
82
266
  });
83
267
  }
268
+ assertExactReceiptInventories(plan, receipts);
84
269
  return receipts;
85
270
  }
86
271
 
@@ -286,8 +471,22 @@ function assertZeroCampaignResidue(plan, profile) {
286
471
  if (matchingRunners.length !== 0) {
287
472
  throw new Error("macOS campaign already has a registered JIT runner");
288
473
  }
289
- const evidenceObjectCounts = {};
290
- for (const sourceSha of [plan.previousSource.sha, plan.source.sha]) {
474
+ const evidenceObjects = {};
475
+ const historicalTerminalSources =
476
+ plan.github.historicalTerminalFailureRuns.map(({ sourceSha }) => sourceSha);
477
+ const historicalPreflightSources =
478
+ plan.github.historicalPreflightFailureRuns.map(
479
+ ({ sourceSha }) => sourceSha,
480
+ );
481
+ const evidenceSources = [
482
+ ...new Set([
483
+ plan.previousSource.sha,
484
+ ...historicalTerminalSources,
485
+ ...historicalPreflightSources,
486
+ plan.source.sha,
487
+ ]),
488
+ ];
489
+ for (const sourceSha of evidenceSources) {
291
490
  const evidence = awsJson(
292
491
  plan,
293
492
  profile,
@@ -299,27 +498,44 @@ function assertZeroCampaignResidue(plan, profile) {
299
498
  "--prefix",
300
499
  `macos/${sourceSha}/`,
301
500
  "--max-keys",
302
- "1",
501
+ "1000",
303
502
  "--output",
304
503
  "json",
305
504
  ],
306
505
  `macOS campaign evidence inventory for ${sourceSha}`,
307
506
  );
507
+ if (evidence.IsTruncated === true) {
508
+ throw new Error(
509
+ `macOS campaign source ${sourceSha} evidence inventory is incomplete`,
510
+ );
511
+ }
512
+ const objects = (evidence.Contents || []).map((object) => ({
513
+ key: String(object.Key || ""),
514
+ size: Number(object.Size || 0),
515
+ etag: String(object.ETag || ""),
516
+ }));
308
517
  const count = Number(
309
518
  evidence.KeyCount || (evidence.Contents || []).length || 0,
310
519
  );
311
- if (count !== 0) {
520
+ const terminalEvidenceSource =
521
+ (sourceSha === plan.previousSource.sha &&
522
+ plan.github.priorRunPolicy === "terminal-failure") ||
523
+ historicalTerminalSources.includes(sourceSha);
524
+ if (
525
+ (!terminalEvidenceSource && count !== 0) ||
526
+ (terminalEvidenceSource && count === 0)
527
+ ) {
312
528
  throw new Error(
313
- `macOS campaign source ${sourceSha} already has bootstrap evidence`,
529
+ `macOS campaign source ${sourceSha} bootstrap evidence does not match the rebind policy`,
314
530
  );
315
531
  }
316
- evidenceObjectCounts[sourceSha] = count;
532
+ evidenceObjects[sourceSha] = objects;
317
533
  }
318
534
  return {
319
- priorRuns: campaignRunsWithNoWork(plan),
535
+ priorRuns: campaignRunReceipts(plan),
320
536
  jitParameterCount: parameters.length,
321
537
  runnerCount: matchingRunners.length,
322
- evidenceObjectCounts,
538
+ evidenceObjects,
323
539
  };
324
540
  }
325
541
 
@@ -480,7 +696,12 @@ export function executeMacosJitSourceRebind(plan, { profile = "" } = {}) {
480
696
  schemaVersion: 1,
481
697
  contract: AWS_MACOS_JIT_CONTROLLER_CONTRACT,
482
698
  kind: "campaign-source-rebind-result",
483
- status: "rebound-zero-allocation",
699
+ status:
700
+ plan.github.priorRunPolicy === "terminal-failure"
701
+ ? "rebound-after-terminal-failure-zero-allocation"
702
+ : plan.github.priorRunPolicy === "preflight-failure"
703
+ ? "rebound-after-preflight-failure-zero-allocation"
704
+ : "rebound-zero-allocation",
484
705
  repository: plan.repository,
485
706
  campaign: plan.campaign,
486
707
  previousSource: plan.previousSource,
@@ -25,6 +25,17 @@ function writeJson(file, value) {
25
25
  return resolved;
26
26
  }
27
27
 
28
+ export function writeMacosJitQualificationEnvironment(
29
+ githubEnv = process.env.GITHUB_ENV,
30
+ ) {
31
+ if (!githubEnv) return false;
32
+ fs.appendFileSync(
33
+ path.resolve(githubEnv),
34
+ "BUILDCHAIN_SIGNING_REQUESTS_ENABLED=false\n",
35
+ );
36
+ return true;
37
+ }
38
+
28
39
  export function main() {
29
40
  const mode = process.argv[2] || "plan";
30
41
  if (mode === "plan") {
@@ -64,6 +75,7 @@ export function main() {
64
75
  ".buildchain/aws-macos-jit.json",
65
76
  result,
66
77
  );
78
+ writeMacosJitQualificationEnvironment();
67
79
  process.stdout.write(`${output}\n`);
68
80
  return result;
69
81
  }
@@ -129,11 +129,18 @@ export const BUILDCHAIN_USAGE = `Usage:
129
129
  [--from-config | --workflow <required-workflow.yml>...] [--cwd <dir>]
130
130
  [--check-response-timeout-minutes <n>]
131
131
  [--max-entries-to-build <n>] [--apply]
132
- buildchain dev warrant <submit|select|heartbeat|recover|close|cancel-queued|observe>
132
+ buildchain dev warrant <submit|select|heartbeat|qualify|recover|close|cancel-queued|observe>
133
133
  --repository <owner/repo> --branch <dev/vN/vN.M>
134
134
  [--execute] [--output <file>] [--json]
135
- buildchain dev proof <source|verify-source|classify|replay|integration|verify-integration>
135
+ buildchain dev authority <migrate|submit|lease-qualification|heartbeat-qualification|complete-qualification|lease-landing|heartbeat-landing|recover|admit-merge-group|settle|observe>
136
+ --repository <owner/repo> --branch <dev/vN/vN.M>
137
+ [--execute] [--output <file>] [--json]
138
+ buildchain dev proof <source|verify-source|classify|native|verify-native|classify-native|verify-native-reuse|replay|integration|verify-integration>
136
139
  [--output <file>] [--json]
140
+ buildchain dev two-phase --repository <owner/repo> --branch <dev/vN/vN.M>
141
+ --pull-request <n> --expected-head <sha>
142
+ --warrant-result <file> [--native-proof <file>]
143
+ [--native-command <command>]
137
144
  buildchain log <info|warn|error> --event <name> [--phase <phase>]
138
145
  [--component <name>] [--source <name>] [--attribute key=value]...
139
146
  [--path <jsonl>] [--json]
@@ -131,6 +131,7 @@ function repositoryJavaScriptFiles(root) {
131
131
  .filter((file) => [".js", ".mjs", ".cjs"].includes(path.extname(file)))
132
132
  .filter((file) => !file.startsWith("tests/"))
133
133
  .filter((file) => !/(?:^|\/)tests?\//u.test(file))
134
+ .filter((file) => !file.startsWith(".buildchain/"))
134
135
  .filter((file) => !/^actions\/[^/]+\/dist\//u.test(file))
135
136
  .sort();
136
137
  }
@@ -53,6 +53,10 @@ const requiredPaths = [
53
53
  "packages/core/homebrew.js",
54
54
  "packages/core/artifact-verification-envelope.js",
55
55
  "packages/core/anchored-version-material.js",
56
+ "packages/core/next-development-transition.js",
57
+ "packages/core/next-development-controller.js",
58
+ "packages/core/next-development-candidate-reservation.js",
59
+ "packages/core/next-development-projection.js",
56
60
  "packages/core/build-facts.js",
57
61
  "packages/core/publication-package.js",
58
62
  "packages/core/publication-reproducibility.js",
@@ -75,6 +79,8 @@ const requiredPaths = [
75
79
  "docs/auditable-demo.md",
76
80
  "contracts/auditable-demo-scenario-v1.schema.json",
77
81
  "contracts/release-candidate-recovery-v1.schema.json",
82
+ "contracts/next-development-request-v1.schema.json",
83
+ "contracts/next-development-transition-v1.schema.json",
78
84
  "contracts/auditable-demo-media-profiles-v1.json",
79
85
  "contracts/evidence/auditable-demo-web-delivery-v1.json",
80
86
  "contracts/evidence/auditable-demo-responsive-web-delivery-v1.json",
@@ -86,10 +92,15 @@ const requiredPaths = [
86
92
  "contracts/fixtures/auditable-demo-responsive-web-delivery-v1/public-projection.json",
87
93
  "contracts/fixtures/auditable-demo-responsive-web-delivery-v1/scene.json",
88
94
  "docs/release-propagation.md",
95
+ "docs/next-development-transition.md",
89
96
  "docs/site-bundle-contract.md",
90
97
  "docs/toolkit-observability.md",
91
98
  "docs/versioning.md",
92
99
  "scripts/release-line-dry-run.mjs",
100
+ "scripts/next-development-transition.mjs",
101
+ "scripts/next-development-self-dogfood.mjs",
102
+ "scripts/next-development-self-dogfood-harness.mjs",
103
+ "scripts/generate-next-development-guidance.mjs",
93
104
  "scripts/reconcile-release-governance.mjs",
94
105
  "scripts/buildchain-channel-router.mjs",
95
106
  "scripts/generate-channel-build-workflow.mjs",
@@ -992,7 +1003,7 @@ for (const forbiddenSnippet of [
992
1003
  for (const requiredSnippet of [
993
1004
  "id-token: write",
994
1005
  "actions: write",
995
- "uses: kungfu-systems/buildchain/.github/workflows/release-candidate-promote.yml@769b221bad7a6b9104afad4c2628d9dca396ab0f\n",
1006
+ "uses: kungfu-systems/buildchain/.github/workflows/release-candidate-promote.yml@cc6c32845ab5779009aeb48cc34efe65e229fe30\n",
996
1007
  "github.event.workflow_run.event == 'push'",
997
1008
  "!startsWith(github.event.workflow_run.display_title, 'chore(release): prepare v')",
998
1009
  "!startsWith(github.event.workflow_run.display_title, 'chore(release): release v')",
@@ -20,6 +20,7 @@ import {
20
20
  candidateFromDecision,
21
21
  selectLatestQualifiedSource,
22
22
  } from "../packages/core/dev-alpha-candidate-selection.js";
23
+ import { readGitHubNextDevelopmentVersionReservation } from "../packages/core/next-development-candidate-reservation.js";
23
24
 
24
25
  export { reconcileActiveReleaseTrain, selectLatestQualifiedSource };
25
26
 
@@ -617,6 +618,7 @@ export async function runDevAlphaCandidatePatrol(
617
618
  comparison,
618
619
  workflowEvidence,
619
620
  skippedNewerCommitCount,
621
+ versionReservation,
620
622
  qualificationError,
621
623
  } = await resolvePatrolSourceInputs({
622
624
  client,
@@ -646,6 +648,7 @@ export async function runDevAlphaCandidatePatrol(
646
648
  observedSourceHeadSha,
647
649
  skippedNewerCommitCount,
648
650
  ...(targetBaseline ? { targetBaseline } : {}),
651
+ ...(versionReservation ? { versionReservation } : {}),
649
652
  },
650
653
  workflowEvidence,
651
654
  requiredWorkflowPaths,
@@ -992,6 +995,20 @@ export function createGitHubChannelCandidateClient({
992
995
  targetBranch,
993
996
  parseCandidate: managedCandidateFromPullRequest,
994
997
  }),
998
+ async readNextDevelopmentVersionReservation({
999
+ reservationSha,
1000
+ candidateSha,
1001
+ targetVersion,
1002
+ }) {
1003
+ return readGitHubNextDevelopmentVersionReservation({
1004
+ api,
1005
+ owner,
1006
+ repo,
1007
+ reservationSha,
1008
+ candidateSha,
1009
+ targetVersion,
1010
+ });
1011
+ },
995
1012
  async listCompletedWorkflowRuns(workflowPathValue, sourceBranch) {
996
1013
  const runs = [];
997
1014
  for (let page = 1; page <= 10; page += 1) {
@@ -1015,7 +1032,11 @@ export function createGitHubChannelCandidateClient({
1015
1032
  for (const commit of rows) {
1016
1033
  const commitSha = text(commit.sha);
1017
1034
  if (commitSha === targetSha) return commits;
1018
- commits.push(commitSha);
1035
+ commits.push({
1036
+ sha: commitSha,
1037
+ message: text(commit.commit?.message),
1038
+ parents: (commit.parents || []).map((parent) => text(parent.sha)),
1039
+ });
1019
1040
  }
1020
1041
  if (rows.length < 100) return commits;
1021
1042
  }