@kungfu-tech/buildchain 2.14.3-alpha.10 → 2.14.3-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.
@@ -4,7 +4,7 @@
4
4
  "product": {
5
5
  "name": "Buildchain",
6
6
  "package": "@kungfu-tech/buildchain",
7
- "version": "2.14.3-alpha.10",
7
+ "version": "2.14.3-alpha.2",
8
8
  "repository": "https://github.com/kungfu-systems/buildchain"
9
9
  },
10
10
  "majorLine": "v2",
@@ -50,7 +50,7 @@
50
50
  "retryable GitHub fallback fetches use a bounded attempt budget before exact source SHA and tree verification"
51
51
  ],
52
52
  "breakingDigest": "sha256:a6a35370d6b0d0f46e1b2712dcc01961fe53c2febde95409a27a485c10a36650",
53
- "auditDigest": "sha256:18d0ab6f916258871d45e92fa28597f590efbac0a0610f9bf7585472a5126307"
53
+ "auditDigest": "sha256:46fa80913e6174f34b96c323ed913410b9fea0f3632a0ce9c7d4f3e0b23b7072"
54
54
  },
55
55
  {
56
56
  "contractVersion": 1,
@@ -168,7 +168,7 @@
168
168
  "GitHub Release passport and evidence publication is delegated to promote-buildchain-ref after the semver release transaction completes"
169
169
  ],
170
170
  "breakingDigest": "sha256:1f476fb9a4854b362c4b24cef89a3c7675d7d63baf3bc828d7b8ae7d2787cead",
171
- "auditDigest": "sha256:4a0f29c9c33ef97609ca0e2244f79a36307de2c3bbb42f1515b358d2f4a2caa2"
171
+ "auditDigest": "sha256:b083a71f80052c013468d48473ec0f8f919161e38a3607feebe99edcd3b32460"
172
172
  },
173
173
  {
174
174
  "contractVersion": 1,
@@ -320,7 +320,7 @@
320
320
  "semver GitHub Releases are created or updated only after transaction completion, with prerelease/latest metadata derived from the public release tag"
321
321
  ],
322
322
  "breakingDigest": "sha256:a59f0910e6df842e7699139472e5dd69ac2fdd7f7213bf2cb346d1d622556874",
323
- "auditDigest": "sha256:5b365ef8afa4c5d88e73d22415929f4123da0ea3b33374f465a1c8f22aaf2785"
323
+ "auditDigest": "sha256:df58156fe2ae06cc080c2e1a7e70458ab9177365ac7da1a66abe026386ddd548"
324
324
  },
325
325
  {
326
326
  "contractVersion": 1,
@@ -600,7 +600,7 @@
600
600
  "agents can discover supported Node APIs without importing internal file paths"
601
601
  ],
602
602
  "breakingDigest": "sha256:48f925608d3e2131d90936b07dc2a30341204cae3e6e785c0f77d61ad755c945",
603
- "auditDigest": "sha256:7d74190fd37b62acc862e5a50fa01f2888605b60404f600548a3bb32c0d8b93f"
603
+ "auditDigest": "sha256:21b2e8fa81fbeab636fbd6e65ee3f39c05ab5a521b5dc24b95ccbfd06c334cb8"
604
604
  },
605
605
  {
606
606
  "contractVersion": 1,
@@ -1057,7 +1057,7 @@
1057
1057
  "missing receipts are non-qualifying and must not be represented as a successful controller run"
1058
1058
  ],
1059
1059
  "breakingDigest": "sha256:e264a79f9f399038c2fcfd21e4168c68c2e1485ee5c651c02242a02b622ac2be",
1060
- "auditDigest": "sha256:18d0ab6f916258871d45e92fa28597f590efbac0a0610f9bf7585472a5126307"
1060
+ "auditDigest": "sha256:46fa80913e6174f34b96c323ed913410b9fea0f3632a0ce9c7d4f3e0b23b7072"
1061
1061
  },
1062
1062
  {
1063
1063
  "contractVersion": 1,
@@ -2830,5 +2830,5 @@
2830
2830
  }
2831
2831
  ],
2832
2832
  "compatibilityDigest": "sha256:edc3653e5cb34efd97065a6941db16140bbf375a565bbcf329d9d795bb07676f",
2833
- "contractDigest": "sha256:311379747d9beb4f3d8a1126b8c34122e92750690694ba5a04677ace3004bd21"
2833
+ "contractDigest": "sha256:5ee3923ae7dc5e6633b0ef0be62a4f28611946f5333bb28c9c8229e88c149599"
2834
2834
  }
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
3
  "contract": "kungfu-buildchain-site-bundle",
4
- "generatedAt": "2026-07-19T15:17:37.795Z",
5
- "publishedAt": "2026-07-19T15:17:37.795Z",
4
+ "generatedAt": "2026-07-19T01:05:14.449Z",
5
+ "publishedAt": "2026-07-19T01:05:14.449Z",
6
6
  "reproducible": true,
7
7
  "timestampPolicy": "ci-injected",
8
8
  "deterministicInputs": [
@@ -19,7 +19,7 @@
19
19
  "declared Buildchain surface manifest contract"
20
20
  ],
21
21
  "sourceDateEpoch": "0",
22
- "sourceRevision": "4c58fc3d46b34b6c7399cec95ab4dc4aff11bbe7",
22
+ "sourceRevision": "2a19346a43d0a6be49ca4d6e76fda6c7d3b63c9d",
23
23
  "timestampPolicyDetails": {
24
24
  "contract": "kungfu-buildchain-surface-timestamp-policy",
25
25
  "timestampFields": [
@@ -37,7 +37,7 @@
37
37
  },
38
38
  "package": {
39
39
  "name": "@kungfu-tech/buildchain",
40
- "version": "2.14.3-alpha.10",
40
+ "version": "2.14.3-alpha.2",
41
41
  "versionSource": "package.json#version"
42
42
  },
43
43
  "source": {
@@ -4,7 +4,7 @@
4
4
  "product": {
5
5
  "id": "kungfu-tech-buildchain",
6
6
  "name": "@kungfu-tech/buildchain",
7
- "version": "2.14.3-alpha.10",
7
+ "version": "2.14.3-alpha.2",
8
8
  "repository": "https://github.com/kungfu-systems/buildchain"
9
9
  },
10
10
  "source": {
@@ -281,7 +281,7 @@
281
281
  "specifier": "@kungfu-tech/buildchain/publication-control-plane-audit",
282
282
  "export": "./publication-control-plane-audit",
283
283
  "target": "./packages/core/publication-control-plane-audit.js",
284
- "digest": "sha256:3c082cdfea7bda55bd6d389dce140f1f359917c68ecf4e64eb6f2defa77cc03c",
284
+ "digest": "sha256:58baa05440b86259812f370aa9645ba26a4df8e986dd57598412b479589286dc",
285
285
  "summary": "Read-only publication control-plane snapshot evaluation APIs.",
286
286
  "capabilityGroup": "release-passport-trust",
287
287
  "audience": [
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
3
  "contract": "kungfu-buildchain-publication-release-registry",
4
- "generatedAt": "2026-07-19T15:17:37.795Z",
5
- "publishedAt": "2026-07-19T15:17:37.795Z",
4
+ "generatedAt": "2026-07-19T01:05:14.449Z",
5
+ "publishedAt": "2026-07-19T01:05:14.449Z",
6
6
  "reproducible": true,
7
7
  "timestampPolicy": "ci-injected",
8
8
  "deterministicInputs": [
@@ -19,7 +19,7 @@
19
19
  "declared Buildchain surface manifest contract"
20
20
  ],
21
21
  "sourceDateEpoch": "0",
22
- "sourceRevision": "4c58fc3d46b34b6c7399cec95ab4dc4aff11bbe7",
22
+ "sourceRevision": "2a19346a43d0a6be49ca4d6e76fda6c7d3b63c9d",
23
23
  "timestampPolicyDetails": {
24
24
  "contract": "kungfu-buildchain-surface-timestamp-policy",
25
25
  "timestampFields": [
@@ -32,7 +32,7 @@
32
32
  },
33
33
  "package": {
34
34
  "name": "@kungfu-tech/buildchain",
35
- "version": "2.14.3-alpha.10",
35
+ "version": "2.14.3-alpha.2",
36
36
  "versionSource": "package.json#version"
37
37
  },
38
38
  "sourceKind": "package-site-bundle",
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
3
  "contract": "kungfu-buildchain-site-manifest",
4
- "generatedAt": "2026-07-19T15:17:37.795Z",
5
- "publishedAt": "2026-07-19T15:17:37.795Z",
4
+ "generatedAt": "2026-07-19T01:05:14.449Z",
5
+ "publishedAt": "2026-07-19T01:05:14.449Z",
6
6
  "reproducible": true,
7
7
  "timestampPolicy": "ci-injected",
8
8
  "deterministicInputs": [
@@ -19,7 +19,7 @@
19
19
  "declared Buildchain surface manifest contract"
20
20
  ],
21
21
  "sourceDateEpoch": "0",
22
- "sourceRevision": "4c58fc3d46b34b6c7399cec95ab4dc4aff11bbe7",
22
+ "sourceRevision": "2a19346a43d0a6be49ca4d6e76fda6c7d3b63c9d",
23
23
  "timestampPolicyDetails": {
24
24
  "contract": "kungfu-buildchain-surface-timestamp-policy",
25
25
  "timestampFields": [
@@ -37,7 +37,7 @@
37
37
  },
38
38
  "package": {
39
39
  "name": "@kungfu-tech/buildchain",
40
- "version": "2.14.3-alpha.10",
40
+ "version": "2.14.3-alpha.2",
41
41
  "versionSource": "package.json#version"
42
42
  },
43
43
  "entrypoint": "buildchain-site.json",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kungfu-tech/buildchain",
3
- "version": "2.14.3-alpha.10",
3
+ "version": "2.14.3-alpha.2",
4
4
  "private": false,
5
5
  "description": "Buildchain Release Passport, release governance, CLI toolkit, and site facts.",
6
6
  "repository": "https://github.com/kungfu-systems/buildchain",
@@ -76,8 +76,6 @@ export function evaluatePublicationControlPlaneSnapshot({
76
76
  branchPolicy.requiredStatusCheck === requiredStatusCheck &&
77
77
  branchPolicy.requiredStatusChecks.includes(requiredStatusCheck) &&
78
78
  branchPolicy.requiredCheckPassed === true &&
79
- /^[0-9a-f]{40}$/i.test(String(branchPolicy.requiredCheckSha || "")) &&
80
- branchPolicy.requiredCheckSha === branchPolicy.pullRequestHeadSha &&
81
79
  branchPolicy.sourceSha === branchPolicy.headSha &&
82
80
  branchPolicy.mergedPullRequest === true &&
83
81
  branchPolicy.baseRef === branch &&
@@ -278,10 +278,7 @@ function main() {
278
278
  const independentApprovals = [...latestReviews.values()].filter((review) =>
279
279
  review.state === "APPROVED" && review.user?.login !== mergedPullRequest?.user?.login
280
280
  );
281
- const pullRequestHeadSha = String(mergedPullRequest?.head?.sha || "").toLowerCase();
282
- const checkRuns = /^[0-9a-f]{40}$/.test(pullRequestHeadSha)
283
- ? githubJson(`repos/${repository}/commits/${pullRequestHeadSha}/check-runs?per_page=100`, "merged pull-request head check runs")
284
- : { check_runs: [] };
281
+ const checkRuns = githubJson(`repos/${repository}/commits/${sourceSha}/check-runs?per_page=100`, "source check runs");
285
282
  const requiredStatusCheckPolicy = branchState.protection?.required_status_checks || {};
286
283
  const requiredStatusChecks = requiredStatusCheckPolicy.contexts || [];
287
284
  const requiredCheckSource = (requiredStatusCheckPolicy.checks || []).find((entry) => entry.context === requiredStatusCheck);
@@ -298,12 +295,10 @@ function main() {
298
295
  (!requiredCheckSource?.app_id || entry.app?.id === requiredCheckSource.app_id)
299
296
  ),
300
297
  requiredCheckAppId: requiredCheckSource?.app_id || 0,
301
- requiredCheckSha: pullRequestHeadSha,
302
298
  sourceSha,
303
299
  headSha: String(branchState.commit?.sha || "").toLowerCase(),
304
300
  mergedPullRequest: Boolean(mergedPullRequest),
305
301
  pullRequestNumber: mergedPullRequest?.number || 0,
306
- pullRequestHeadSha,
307
302
  baseRef: mergedPullRequest?.base?.ref || "",
308
303
  headRepository: mergedPullRequest?.head?.repo?.full_name || "",
309
304
  approvalCount: independentApprovals.length,
@@ -90,34 +90,29 @@ function publicOutputs(outputBlock) {
90
90
  return [...routed, ...forwarded].join("\n");
91
91
  }
92
92
 
93
- function forwardedInputs(inputNames, { includeInternal = true } = {}) {
94
- return inputNames
95
- .filter((name) => includeInternal || !internalInputs.has(name))
96
- .map((name) => {
97
- const routed = {
98
- "buildchain-ref": "runtime-ref",
99
- "buildchain-contract-lock-path": "contract-lock-path",
100
- channel: "publication-channel",
101
- "target-ref": "target-ref",
102
- "promotion-router-ref": "router-ref",
103
- "promotion-router-sha": "router-sha",
104
- "promotion-shell-ref": "shell-ref",
105
- "promotion-shell-sha": "shell-sha",
106
- "promotion-runtime-ref": "runtime-ref",
107
- "promotion-runtime-sha": "runtime-sha",
108
- "promotion-contract-lock-path": "contract-lock-path",
109
- "promotion-contract-lock-digest": "contract-lock-digest",
110
- "promotion-publication-channel": "publication-channel",
111
- "promotion-target-ref": "target-ref",
112
- "promotion-override-used": "override-used",
113
- }[name];
114
- if (name === "promotion-override-used") {
115
- return ` ${name}: \${{ needs.resolve-promotion.outputs.override-used == 'true' }}`;
116
- }
117
- return routed
118
- ? ` ${name}: \${{ needs.resolve-promotion.outputs.${routed} }}`
119
- : ` ${name}: \${{ inputs.${name} }}`;
120
- }).join("\n");
93
+ function forwardedInputs(inputNames) {
94
+ return inputNames.map((name) => {
95
+ const routed = {
96
+ "buildchain-ref": "runtime-ref",
97
+ "buildchain-contract-lock-path": "contract-lock-path",
98
+ channel: "publication-channel",
99
+ "target-ref": "target-ref",
100
+ "promotion-router-ref": "router-ref",
101
+ "promotion-router-sha": "router-sha",
102
+ "promotion-shell-ref": "shell-ref",
103
+ "promotion-shell-sha": "shell-sha",
104
+ "promotion-runtime-ref": "runtime-ref",
105
+ "promotion-runtime-sha": "runtime-sha",
106
+ "promotion-contract-lock-path": "contract-lock-path",
107
+ "promotion-contract-lock-digest": "contract-lock-digest",
108
+ "promotion-publication-channel": "publication-channel",
109
+ "promotion-target-ref": "target-ref",
110
+ "promotion-override-used": "override-used",
111
+ }[name];
112
+ return routed
113
+ ? ` ${name}: \${{ needs.resolve-promotion.outputs.${routed} }}`
114
+ : ` ${name}: \${{ inputs.${name} }}`;
115
+ }).join("\n");
121
116
  }
122
117
 
123
118
  function validateWorkflowRoute(name, route, expectedLogicalRef) {
@@ -131,9 +126,6 @@ function validateWorkflowRoute(name, route, expectedLogicalRef) {
131
126
  if (!/^(?:v[0-9]+(?:-alpha)?|[0-9a-f]{40})$/.test(route.callRef || "")) {
132
127
  throw new Error(`promotion shell ${name} callRef must be an official channel ref or exact SHA`);
133
128
  }
134
- if (typeof route.forwardInternalInputs !== "boolean") {
135
- throw new Error(`promotion shell ${name} forwardInternalInputs must be boolean`);
136
- }
137
129
  return { ...route };
138
130
  }
139
131
 
@@ -153,13 +145,11 @@ export function generateChannelPromotionWorkflow(source, { major = 2, shellRouti
153
145
  logicalRef: `v${major}-alpha`,
154
146
  callRef: `v${major}-alpha`,
155
147
  workflowPath: ".github/workflows/.release-candidate-promote.yml",
156
- forwardInternalInputs: true,
157
148
  },
158
149
  stable: {
159
150
  logicalRef: `v${major}`,
160
151
  callRef: `v${major}`,
161
152
  workflowPath: ".github/workflows/.release-candidate-promote.yml",
162
- forwardInternalInputs: true,
163
153
  },
164
154
  };
165
155
  const alphaRoute = validateWorkflowRoute("alpha", routes.alpha, `v${major}-alpha`);
@@ -171,12 +161,7 @@ export function generateChannelPromotionWorkflow(source, { major = 2, shellRouti
171
161
  for (const required of ["buildchain-ref", "buildchain-contract-lock-path", "channel", "target-ref", ...internalInputs]) {
172
162
  if (!inputNames.includes(required)) throw new Error(`advanced promotion workflow missing input: ${required}`);
173
163
  }
174
- const alphaForwarded = forwardedInputs(inputNames, {
175
- includeInternal: alphaRoute.forwardInternalInputs,
176
- });
177
- const stableForwarded = forwardedInputs(inputNames, {
178
- includeInternal: stableRoute.forwardInternalInputs,
179
- });
164
+ const forwarded = forwardedInputs(inputNames);
180
165
  return `# Generated by scripts/generate-channel-promotion-workflow.mjs. Do not edit directly.
181
166
  name: Release Candidate Promote
182
167
 
@@ -371,7 +356,7 @@ jobs:
371
356
  id-token: write
372
357
  issues: write
373
358
  with:
374
- ${alphaForwarded}
359
+ ${forwarded}
375
360
  secrets: inherit
376
361
 
377
362
  stable:
@@ -386,7 +371,7 @@ ${alphaForwarded}
386
371
  id-token: write
387
372
  issues: write
388
373
  with:
389
- ${stableForwarded}
374
+ ${forwarded}
390
375
  secrets: inherit
391
376
  `;
392
377
  }
@@ -23,10 +23,12 @@ function targetIntent(targetRef, requestedPublicationChannel = "") {
23
23
  if (requested && requested !== target.publicationChannel) {
24
24
  throw new Error(`promotion channel ${requested} does not match target ref ${ref} (${target.publicationChannel})`);
25
25
  }
26
+ const match = ref.match(target.pattern);
26
27
  return {
27
28
  targetRef: ref,
28
29
  publicationChannel: target.publicationChannel,
29
30
  shellChannel: target.shellChannel,
31
+ targetMajor: match?.[1] ? Number(match[1]) : undefined,
30
32
  };
31
33
  }
32
34
 
@@ -53,6 +55,11 @@ export function resolvePromotionChannel({
53
55
  `promotion target ${intent.targetRef} requires ${intent.shellChannel} shell/runtime, got ${selected.channel}`,
54
56
  );
55
57
  }
58
+ if (Number.isInteger(intent.targetMajor) && selected.major !== intent.targetMajor) {
59
+ throw new Error(
60
+ `promotion target ${intent.targetRef} requires Buildchain v${intent.targetMajor}, got v${selected.major}`,
61
+ );
62
+ }
56
63
  const shellRef = intent.shellChannel === "alpha" ? `v${selected.major}-alpha` : `v${selected.major}`;
57
64
  return {
58
65
  targetRef: intent.targetRef,
@@ -223,7 +223,7 @@ export async function runStableCandidatePatrol(optionsInput = {}, clientInput) {
223
223
  `Buildchain Stable Candidate Patrol human release-now for ${selection.candidate.version}`,
224
224
  );
225
225
  }
226
- await client.ensureBranch(refs.sourceRef, selection.candidate.sha, refs.targetRef);
226
+ await client.ensureBranch(refs.sourceRef, selection.candidate.sha);
227
227
  const pullRequest = await client.ensurePromotionPullRequest({
228
228
  head: refs.sourceRef,
229
229
  base: refs.targetRef,
@@ -371,64 +371,15 @@ export function createGitHubStableCandidateClient({ repository: repositoryInput,
371
371
  },
372
372
  });
373
373
  },
374
- async ensureBranch(ref, candidateSha, targetRef) {
374
+ async ensureBranch(ref, candidateSha) {
375
375
  const current = await api(`/repos/${owner}/${repo}/git/ref/heads/${encodeRef(ref)}`, { allow404: true });
376
- if (!targetRef) {
377
- if (!current) {
378
- return api(`/repos/${owner}/${repo}/git/refs`, { method: "POST", body: { ref: `refs/heads/${ref}`, sha: candidateSha } });
379
- }
380
- if (current.object.sha !== candidateSha) {
381
- throw new Error(`source-lock branch ${ref} already points to ${current.object.sha}, not ${candidateSha}`);
382
- }
383
- return current;
384
- }
385
-
386
- const candidateCommit = await api(`/repos/${owner}/${repo}/git/commits/${candidateSha}`);
387
- let sourceSha = current?.object?.sha || candidateSha;
388
- if (sourceSha !== candidateSha) {
389
- const sourceCommit = await api(`/repos/${owner}/${repo}/git/commits/${sourceSha}`);
390
- if (sourceCommit.tree?.sha !== candidateCommit.tree?.sha) {
391
- throw new Error(`source-lock branch ${ref} no longer preserves candidate ${candidateSha} tree`);
392
- }
393
- const candidateLineage = await api(`/repos/${owner}/${repo}/compare/${candidateSha}...${sourceSha}`);
394
- if (!["ahead", "identical"].includes(candidateLineage.status)) {
395
- throw new Error(`source-lock branch ${ref} no longer descends from candidate ${candidateSha}`);
396
- }
397
- }
398
-
399
- const target = await api(`/repos/${owner}/${repo}/git/ref/heads/${encodeRef(targetRef)}`);
400
- const targetSha = target.object?.sha || "";
401
- const targetLineage = await api(`/repos/${owner}/${repo}/compare/${targetSha}...${sourceSha}`);
402
- if (["ahead", "identical"].includes(targetLineage.status)) {
403
- if (current) return current;
376
+ if (!current) {
404
377
  return api(`/repos/${owner}/${repo}/git/refs`, { method: "POST", body: { ref: `refs/heads/${ref}`, sha: candidateSha } });
405
378
  }
406
-
407
- const identity = { name: "Buildchain Patrol", email: "buildchain-patrol@kungfu.link" };
408
- const reconciliation = await api(`/repos/${owner}/${repo}/git/commits`, {
409
- method: "POST",
410
- body: {
411
- message: [
412
- "chore(buildchain): reconcile stable source-lock ancestry",
413
- "",
414
- `Preserve the exact candidate tree from ${candidateSha} while admitting ${targetRef} at ${targetSha}.`,
415
- "",
416
- "Signed-off-by: Buildchain Patrol <buildchain-patrol@kungfu.link>",
417
- ].join("\n"),
418
- tree: candidateCommit.tree.sha,
419
- parents: [sourceSha, targetSha],
420
- author: identity,
421
- committer: identity,
422
- },
423
- });
424
- sourceSha = reconciliation.sha;
425
- if (!current) {
426
- return api(`/repos/${owner}/${repo}/git/refs`, { method: "POST", body: { ref: `refs/heads/${ref}`, sha: sourceSha } });
379
+ if (current.object.sha !== candidateSha) {
380
+ throw new Error(`source-lock branch ${ref} already points to ${current.object.sha}, not ${candidateSha}`);
427
381
  }
428
- return api(`/repos/${owner}/${repo}/git/refs/heads/${encodeRef(ref)}`, {
429
- method: "PATCH",
430
- body: { sha: sourceSha, force: false },
431
- });
382
+ return current;
432
383
  },
433
384
  async ensurePromotionPullRequest({ head, base, title, body }) {
434
385
  const open = await api(`/repos/${owner}/${repo}/pulls?state=open&head=${encodeURIComponent(`${owner}:${head}`)}&base=${encodeURIComponent(base)}&per_page=20`);