@kungfu-tech/buildchain 4.0.8 → 4.0.9-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 (51) hide show
  1. package/AGENTS.md +12 -19
  2. package/CONTRIBUTING.md +6 -9
  3. package/README.md +11 -1
  4. package/architecture/agent-change-map.md +11 -4
  5. package/architecture/build-environments.json +71 -0
  6. package/architecture/build-orchestration.json +18 -0
  7. package/architecture/ci-lane-change-budget.json +34 -2
  8. package/architecture/internal-capabilities.json +17 -4
  9. package/architecture/maintainability-debt.json +34 -123
  10. package/architecture/maintainability-policy.json +19 -210
  11. package/architecture/release-topology.json +6 -5
  12. package/architecture/universal-workflow-bootstrap.json +5 -4
  13. package/architecture/universal-workflow-train-admission.json +2 -2
  14. package/bin/buildchain.mjs +1 -1
  15. package/contracts/fixtures/v4-tail-reseal-v1/valid.json +1 -1
  16. package/dist/site/buildchain-contract.json +41 -1131
  17. package/dist/site/buildchain-site.json +39 -144
  18. package/dist/site/capability-registry.json +1 -1
  19. package/dist/site/cli-registry.json +1 -1
  20. package/dist/site/controller-registry.json +30 -868
  21. package/dist/site/kfd-claims.json +132 -394
  22. package/dist/site/kfd-upstream-aggregate.json +1 -1
  23. package/dist/site/manual-registry.json +6 -6
  24. package/dist/site/node-api-registry.json +34 -34
  25. package/dist/site/page-registry.json +30 -135
  26. package/dist/site/public-surface-audit.json +81 -401
  27. package/dist/site/publication-registry.json +2 -2
  28. package/dist/site/site-manifest.json +8 -8
  29. package/dist/site/workflow-registry.json +135 -391
  30. package/docs/MAP.md +5 -4
  31. package/docs/cli-reference.md +1 -1
  32. package/docs/getting-started.md +8 -7
  33. package/docs/node-api-reference.md +79 -79
  34. package/docs/reusable-build-surface.md +159 -1430
  35. package/docs/runtime-train-validation.md +45 -172
  36. package/package.json +1 -1
  37. package/packages/core/build-configuration.js +117 -0
  38. package/packages/core/buildchain-config.js +2 -0
  39. package/packages/core/buildchain-contract.js +14 -44
  40. package/packages/core/controller-evidence.js +2 -9
  41. package/scripts/buildchain-cli-help.mjs +1 -1
  42. package/scripts/check-floating-consumer-policy-contract.mjs +4 -7
  43. package/scripts/check-inventory.mjs +81 -54
  44. package/scripts/check-universal-workflow-bootstrap.mjs +12 -2
  45. package/scripts/generate-channel-build-workflow.mjs +50 -410
  46. package/scripts/generate-site-bundle.mjs +2 -1
  47. package/scripts/generate-universal-workflow-facades.mjs +1 -0
  48. package/scripts/init-repo.mjs +25 -26
  49. package/scripts/resolve-build-configuration.mjs +105 -0
  50. package/scripts/universal-workflow-self-dogfood.mjs +8 -1
  51. package/scripts/verify-golden-path.mjs +3 -3
@@ -1,13 +1,12 @@
1
1
  import fs from "node:fs";
2
2
  import path from "node:path";
3
+ import { execFileSync } from "node:child_process";
3
4
  import {
4
5
  assertPublicSurfaceReverseAudit,
5
6
  collectPublicSurfaceReverseAudit,
6
7
  } from "../packages/core/public-surface-audit.js";
7
- import { evaluateBuildchainContractLock } from "../packages/core/buildchain-contract.js";
8
+ import { createBuildchainContractLock, evaluateBuildchainContractLock, finalizeBuildchainContractWorld } from "../packages/core/buildchain-contract.js";
8
9
  import {
9
- canAdmitSelfDogfoodLockEvaluation,
10
- contractForSelfDogfoodEvaluation,
11
10
  hasQualifiedSelfDogfoodBootstrapAuthority,
12
11
  resolveSelfDogfoodMajor,
13
12
  } from "../packages/core/self-dogfood-version.js";
@@ -203,9 +202,6 @@ const selfDogfoodWorkflow = fs.readFileSync(
203
202
  const selfDogfoodAlphaLock = JSON.parse(
204
203
  fs.readFileSync(path.join(root, ".buildchain/alpha-contract-lock.json"), "utf8"),
205
204
  );
206
- const currentBuildchainContract = JSON.parse(
207
- fs.readFileSync(path.join(root, "dist/site/buildchain-contract.json"), "utf8"),
208
- );
209
205
  const selfDogfoodBootstrapAuthority = JSON.parse(
210
206
  fs.readFileSync(path.join(root, "architecture/bootstrap-authority.json"), "utf8"),
211
207
  );
@@ -227,23 +223,58 @@ if (!/^[0-9a-f]{40}$/.test(selfDogfoodAlphaLock.buildchain?.resolvedSha || ""))
227
223
  if (selfDogfoodAlphaLock.buildchain?.compatibilityPolicy !== "major-compatible") {
228
224
  throw new Error("Buildchain self-dogfood alpha lock must enforce major-compatible policy");
229
225
  }
230
- const selfDogfoodAlphaEvaluation = evaluateBuildchainContractLock({
231
- lock: selfDogfoodAlphaLock,
232
- current: contractForSelfDogfoodEvaluation({
233
- currentContract: currentBuildchainContract,
234
- majorResolution: selfDogfoodMajorResolution,
235
- }),
236
- runtimeRef: `v${selfDogfoodMajor}-alpha`,
237
- runtimeSha: "current-development-contract",
238
- runtimeClass: "alpha", workflowShellRef: `v${selfDogfoodMajor}-alpha`,
239
- });
240
- if (
241
- !canAdmitSelfDogfoodLockEvaluation({
242
- evaluation: selfDogfoodAlphaEvaluation,
243
- majorResolution: selfDogfoodMajorResolution,
244
- })
245
- ) {
246
- throw new Error("Buildchain self-dogfood alpha lock requires review after a breaking contract change");
226
+ // Consumer locks describe accepted published runtimes, not this unpublished producer.
227
+ // Validate their immutable source worlds here; hosted admission checks floating drift.
228
+ for (const channel of ["alpha-contract-lock.json", "contract-lock.json"]) {
229
+ const lock = JSON.parse(
230
+ fs.readFileSync(path.join(root, ".buildchain", channel), "utf8"),
231
+ );
232
+ const sha = lock.buildchain?.resolvedSha;
233
+ if (!/^[0-9a-f]{40}$/u.test(sha || ""))
234
+ throw new Error(`${channel}: invalid accepted SHA`);
235
+ let world;
236
+ try {
237
+ world = JSON.parse(
238
+ execFileSync(
239
+ "git",
240
+ ["show", `${sha}:dist/site/buildchain-contract.json`],
241
+ { cwd: root, encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] },
242
+ ),
243
+ );
244
+ } catch {
245
+ const response = await fetch(
246
+ `https://raw.githubusercontent.com/kungfu-systems/buildchain/${sha}/dist/site/buildchain-contract.json`,
247
+ { signal: AbortSignal.timeout(30000) },
248
+ );
249
+ if (!response.ok)
250
+ throw new Error(
251
+ `${channel}: accepted source contract unavailable (${response.status})`,
252
+ );
253
+ world = await response.json();
254
+ }
255
+ const verified = finalizeBuildchainContractWorld(world);
256
+ for (const field of ["contractDigest", "compatibilityDigest"]) {
257
+ if (
258
+ world[field] !== verified[field] ||
259
+ lock.buildchain[field] !== world[field]
260
+ )
261
+ throw new Error(`${channel}: accepted ${field} mismatch`);
262
+ }
263
+ const accepted = createBuildchainContractLock({ contractWorld: verified }).buildchain;
264
+ if (JSON.stringify(lock.buildchain.surfaces) !== JSON.stringify(accepted.surfaces) || lock.buildchain.majorLine !== verified.majorLine || lock.buildchain.compatibilityPolicy !== "major-compatible") throw new Error(`${channel}: accepted surface set or policy mismatch`);
265
+ const ref = channel.startsWith("alpha")
266
+ ? `v${selfDogfoodMajor}-alpha`
267
+ : `v${selfDogfoodMajor}`;
268
+ const evaluation = evaluateBuildchainContractLock({
269
+ lock,
270
+ current: verified,
271
+ runtimeRef: ref,
272
+ runtimeSha: sha,
273
+ runtimeClass: channel.startsWith("alpha") ? "alpha" : "stable",
274
+ workflowShellRef: ref,
275
+ });
276
+ if (!evaluation.ok || lock.buildchain.ref !== ref)
277
+ throw new Error(`${channel}: invalid accepted runtime contract`);
247
278
  }
248
279
  for (const requiredSnippet of [
249
280
  `/.github/workflows/build.yml@v${selfDogfoodMajor}-alpha`,
@@ -262,8 +293,8 @@ const reusableBuildWorkflow = fs.readFileSync(
262
293
  );
263
294
  for (const requiredSnippet of [
264
295
  "BUILDCHAIN_WORKFLOW_REF: ${{ job.workflow_ref }}",
265
- "process.env.BUILDCHAIN_WORKFLOW_REF || process.env.GITHUB_WORKFLOW_REF",
266
- 'replace(/^refs\\/(?:heads|tags)\\//, "")',
296
+ "BUILDCHAIN_WORKFLOW_SHA: ${{ job.workflow_sha }}",
297
+ "Resolve rooted build plan from TOML",
267
298
  ]) {
268
299
  if (!reusableBuildWorkflow.includes(requiredSnippet)) {
269
300
  throw new Error(`reusable build workflow missing called-workflow identity: ${requiredSnippet}`);
@@ -343,23 +374,13 @@ const promotionOverrideAuthorization = fs.readFileSync(
343
374
  if (!promotionOverrideAuthorization.includes("promotion runtime override is only allowed for trusted workflow_dispatch runs")) {
344
375
  throw new Error("promotion runtime override authorization must remain fail closed");
345
376
  }
346
- for (const requiredSnippet of [
347
- "buildchain-channel:",
348
- "uses: ./.github/workflows/.build.yml",
349
- "needs.resolve-channel.outputs.runtime-override != 'true' && needs.resolve-channel.outputs.channel == 'alpha'",
350
- "needs.resolve-channel.outputs.runtime-override != 'true' && needs.resolve-channel.outputs.channel == 'stable'",
351
- "needs.resolve-channel.outputs.buildchain-ref",
352
- "needs.resolve-channel.outputs.contract-lock-path",
353
- ]) {
354
- if (!channelBuildWorkflow.includes(requiredSnippet)) {
355
- throw new Error(`channel build workflow missing routing contract: ${requiredSnippet}`);
356
- }
357
- }
358
- if ((channelBuildWorkflow.match(/uses: \.\/\.github\/workflows\/\.build\.yml/g) || []).length !== 3) {
359
- throw new Error("channel build workflow must bind override, alpha, and stable to the exact caller workflow shell");
377
+ for (const workflow of [channelBuildWorkflow, reusableBuildWorkflow]) {
378
+ const block = workflow.split(" inputs:\n")[1].split(" secrets:\n")[0];
379
+ const names = [...block.matchAll(/^ ([a-z0-9-]+):$/gm)].map((match) => match[1]);
380
+ if (JSON.stringify(names) !== '["config-path"]') throw new Error("ordinary build inputs must contain only config-path");
360
381
  }
361
- if (channelBuildWorkflow.includes("uses: kungfu-systems/buildchain/.github/workflows/.build.yml@")) {
362
- throw new Error("channel build workflow must not statically fetch another channel shell before its ref exists");
382
+ if ((channelBuildWorkflow.match(/uses: \.\/\.github\/workflows\/\.build\.yml/g) || []).length !== 1) {
383
+ throw new Error("public build facade must invoke its exact backbone once");
363
384
  }
364
385
  for (const requiredSnippet of [
365
386
  "group: buildchain-release-promotion-${{ github.repository }}",
@@ -780,8 +801,9 @@ const registeredActionIds = (workflowRegistry.actions || []).map((entry) => entr
780
801
  const readmeActionIndex = fs.readFileSync(path.join(root, "README.md"), "utf8");
781
802
  const mapActionIndex = fs.readFileSync(path.join(root, "docs/MAP.md"), "utf8");
782
803
  const retrospectiveActionIndex = fs.readFileSync(path.join(root, ".github/retrospectives/2026-07-10-buildchain-consolidation.md"), "utf8");
783
- if (registeredActionIds.length !== 8) {
784
- throw new Error(`workflow-registry.json must expose the eight current action entries, got ${registeredActionIds.length}`);
804
+ const buildOwners = JSON.parse(fs.readFileSync(path.join(root, "architecture/build-orchestration.json"), "utf8")).owners;
805
+ if (registeredActionIds.length !== 8 + Object.keys(buildOwners).length) {
806
+ throw new Error(`workflow-registry.json must expose the eight public actions and owned build composites, got ${registeredActionIds.length}`);
785
807
  }
786
808
  for (const actionId of registeredActionIds) {
787
809
  if (!readmeActionIndex.includes(`actions/${actionId}`) || !mapActionIndex.includes(`actions/${actionId}`)) {
@@ -925,16 +947,16 @@ for (const requiredSnippet of [
925
947
  }
926
948
  const reusableBuildSurfaceDoc = fs.readFileSync(path.join(root, "docs/reusable-build-surface.md"), "utf8");
927
949
  for (const requiredSnippet of [
928
- "Floating Ref Contract Lock",
929
- "dist/site/buildchain-contract.json",
930
- "buildchain-contract-drift-issue-mode",
931
- "compatible drift",
932
- "Locked Source Checkout Cache",
933
- "checkout-cache-mode",
934
- "BUILDCHAIN_CHECKOUT_CACHE_MIRROR_URL_TEMPLATE",
935
- "sourceCheckout",
936
- "Shifu Cache Profile Passthrough",
937
- "opaque reference and digest",
950
+ "config-path",
951
+ "buildchain.toml",
952
+ ".buildchain/contract-lock.json",
953
+ ".buildchain/alpha-contract-lock.json",
954
+ "architecture/build-environments.json",
955
+ "build.contract",
956
+ "cache roots",
957
+ "exact consumer source",
958
+ "build-lifecycle-stage",
959
+ "build-artifact-transfer",
938
960
  ]) {
939
961
  if (!reusableBuildSurfaceDoc.includes(requiredSnippet)) {
940
962
  throw new Error(`reusable build surface doc missing contract lock snippet: ${requiredSnippet}`);
@@ -1319,7 +1341,12 @@ if (!Array.isArray(inventory.migratedActions) || inventory.migratedActions.lengt
1319
1341
  throw new Error("migratedActions must be empty; buildchain v2 only ships native actions");
1320
1342
  }
1321
1343
  const shippedActions = internalActions;
1322
- const shippedActionNames = shippedActions.map((action) => action.path.replace(/^actions\//, "")).sort();
1344
+ if (inventory.compositeActionOwnership !== "architecture/build-orchestration.json#owners") throw new Error("composite action ownership must use the build orchestration contract");
1345
+ const compositeNames = Object.keys(buildOwners).map((file) => {
1346
+ if (!/^actions\/[^/]+\/action\.yml$/.test(file) || !/using:\s*composite/.test(fs.readFileSync(path.join(root, file), "utf8"))) throw new Error(`invalid owned composite action: ${file}`);
1347
+ return path.posix.basename(path.posix.dirname(file));
1348
+ });
1349
+ const shippedActionNames = [...shippedActions.map((action) => action.path.replace(/^actions\//, "")), ...compositeNames].sort();
1323
1350
 
1324
1351
  if (JSON.stringify(actualActions) !== JSON.stringify(shippedActionNames)) {
1325
1352
  throw new Error(
@@ -75,13 +75,23 @@ for (const relative of contract.retiredWorkflowSurfaces) {
75
75
  const activeWorkflows = contract.inventoryWorkflows.filter(
76
76
  (relative) =>
77
77
  !contract.retiredWorkflowSurfaces.includes(relative) &&
78
+ !contract.configurationGovernedWorkflows.includes(relative) &&
78
79
  relative !== contract.bootstrap.consumerRecoveryWorkflow,
79
80
  );
80
81
  assert.deepEqual(
81
82
  contract.bootstrapGovernedWorkflows,
82
83
  activeWorkflows,
83
- "every active public reusable workflow must be Bootstrap-governed",
84
- );
84
+ "every active reusable workflow must have its declared configuration or Bootstrap authority",
85
+ );
86
+ assert.deepEqual(contract.configurationGovernedWorkflows, [
87
+ ".github/workflows/.build.yml", ".github/workflows/build.yml",
88
+ ]);
89
+ for (const relative of contract.configurationGovernedWorkflows) {
90
+ const source = fs.readFileSync(path.join(root, relative), "utf8");
91
+ const inputBlock = source.split(" inputs:\n")[1].split(" secrets:\n")[0];
92
+ assert.deepEqual([...inputBlock.matchAll(/^ ([a-z0-9-]+):$/gmu)].map((match) => match[1]), ["config-path"]);
93
+ assert.doesNotMatch(source, /universal-request-json/u);
94
+ }
85
95
  for (const relative of contract.bootstrapGovernedWorkflows) {
86
96
  assert.ok(
87
97
  contract.inventoryWorkflows.includes(relative),