@kungfu-tech/buildchain 4.1.3-alpha.0 → 4.1.3-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 (278) hide show
  1. package/AGENTS.md +41 -75
  2. package/CONTRIBUTING.md +19 -26
  3. package/architecture/action-taxonomy.json +24 -0
  4. package/architecture/agent-change-map.md +272 -12
  5. package/architecture/capability-state-machine-manifest.json +1 -4
  6. package/architecture/ci-lane-change-budget.json +190 -807
  7. package/architecture/core-mechanisms.json +3 -6
  8. package/architecture/decisions/0005-minimal-consumer-contract.md +122 -0
  9. package/architecture/decisions/0006-business-attempt-journal.md +89 -0
  10. package/architecture/decisions/0007-hosted-pipeline-controller.md +106 -0
  11. package/architecture/decisions/0008-pipeline-product-publication.md +120 -0
  12. package/architecture/decisions/0009-pipeline-version-preparation.md +186 -0
  13. package/architecture/internal-capabilities.json +371 -9
  14. package/architecture/maintainability-debt.json +50 -34
  15. package/architecture/maintainability-policy.json +8 -8
  16. package/architecture/minimal-consumer-migration.json +5670 -0
  17. package/architecture/platform-stage-checkpoints.json +31 -7
  18. package/architecture/product-upstreams.json +20 -0
  19. package/architecture/release-topology.json +331 -74
  20. package/architecture/stage-capsule-qualification.json +3 -1
  21. package/architecture/universal-workflow-bootstrap.json +15 -1
  22. package/architecture/universal-workflow-capability-policy.json +9 -9
  23. package/architecture/universal-workflow-fault-campaign.json +3 -1
  24. package/architecture/workflow-taxonomy.json +77 -328
  25. package/contracts/release-discussion-v1.schema.json +3 -0
  26. package/dist/readers/business-attempt.cjs +809 -0
  27. package/dist/readers/release-discussion.cjs +4 -0
  28. package/dist/site/buildchain-contract.json +16 -68
  29. package/dist/site/buildchain-site.json +47 -27
  30. package/dist/site/capability-registry.json +4 -4
  31. package/dist/site/controller-registry.json +1 -47
  32. package/dist/site/kfd-claims.json +499 -494
  33. package/dist/site/kfd-upstream-aggregate.json +1 -1
  34. package/dist/site/manual-registry.json +3 -3
  35. package/dist/site/node-api-registry.json +56 -56
  36. package/dist/site/page-registry.json +40 -20
  37. package/dist/site/public-surface-audit.json +286 -349
  38. package/dist/site/publication-authority-registry.json +203 -523
  39. package/dist/site/publication-registry.json +4 -4
  40. package/dist/site/site-manifest.json +7 -7
  41. package/dist/site/workflow-registry.json +590 -940
  42. package/docs/code-organization.md +9 -6
  43. package/docs/node-api-reference.md +103 -103
  44. package/docs/release-discussions.md +44 -5
  45. package/docs/release-governance.md +10 -12
  46. package/docs/runtime-entry.md +73 -5
  47. package/docs/runtime-train-validation.md +39 -11
  48. package/docs/stable-candidate-patrol.md +6 -5
  49. package/docs/workflow-catalog.md +9 -32
  50. package/package.json +4 -3
  51. package/packages/core/adoption/buildchain-kfd-claims.js +7 -7
  52. package/packages/core/build/standalone/build.js +7 -1
  53. package/packages/core/consumer/buildchain-config.js +2 -21
  54. package/packages/core/consumer/contract/entries.js +85 -0
  55. package/packages/core/consumer/contract/examples.js +96 -0
  56. package/packages/core/consumer/contract/identity.js +65 -0
  57. package/packages/core/consumer/contract/inspection.js +45 -0
  58. package/packages/core/consumer/contract/plan.js +149 -0
  59. package/packages/core/consumer/contract/products.js +119 -0
  60. package/packages/core/consumer/contract/reader.js +47 -0
  61. package/packages/core/consumer/contract/shape.js +46 -0
  62. package/packages/core/dev-delivery/candidate/admission.js +9 -5
  63. package/packages/core/dev-delivery/candidate/reservation.js +11 -0
  64. package/packages/core/dev-delivery/candidate/source-paths.js +12 -4
  65. package/packages/core/dev-delivery/commands/project-cut-merge-queue-admission.mjs +47 -20
  66. package/packages/core/dev-delivery/dev-delivery-provider-heartbeat.js +18 -15
  67. package/packages/core/dev-delivery/native/actions.js +9 -1
  68. package/packages/core/dev-delivery/native/heartbeat-action.js +16 -0
  69. package/packages/core/dev-delivery/native/heartbeat.js +6 -4
  70. package/packages/core/dev-delivery/native/process-entry.js +19 -0
  71. package/packages/core/dev-delivery/queue/landing-action.js +53 -0
  72. package/packages/core/dev-delivery/warrant/failure-settlement.js +8 -6
  73. package/packages/core/dev-delivery/warrant/service.js +7 -0
  74. package/packages/core/governance/buildchain-publication-authority.js +8 -23
  75. package/packages/core/governance/github-governance-authority.js +1 -0
  76. package/packages/core/observability/controller-evidence.js +0 -8
  77. package/packages/core/paper/operations/bootstrap.js +2 -0
  78. package/packages/core/paper/paper-npm-bootstrap.js +2 -2
  79. package/packages/core/providers/github/attempt-index.js +60 -0
  80. package/packages/core/providers/github/attempt-journal.js +154 -0
  81. package/packages/core/providers/github/discussions/materials.js +35 -11
  82. package/packages/core/providers/github/discussions/transport.js +16 -5
  83. package/packages/core/providers/github/pipeline-checkout.js +49 -0
  84. package/packages/core/providers/github/pipeline-entry-runs.js +210 -0
  85. package/packages/core/providers/github/pipeline-events.js +131 -0
  86. package/packages/core/providers/github/pipeline-integration.js +95 -0
  87. package/packages/core/providers/github/pipeline-policy.js +240 -0
  88. package/packages/core/providers/github/pipeline-product-payload.js +50 -0
  89. package/packages/core/providers/github/pipeline-product-release.js +198 -0
  90. package/packages/core/providers/github/pipeline-publication-artifacts.js +153 -0
  91. package/packages/core/providers/github/pipeline-release-evidence.js +30 -0
  92. package/packages/core/providers/github/pipeline-run-entry.js +86 -0
  93. package/packages/core/providers/github/pipeline-runs.js +132 -0
  94. package/packages/core/providers/github/pipeline-source.js +195 -0
  95. package/packages/core/providers/github/pipeline-stable-baseline.js +86 -0
  96. package/packages/core/providers/github/pipeline-stable-source.js +372 -0
  97. package/packages/core/providers/github/pipeline-version-artifacts.js +91 -0
  98. package/packages/core/providers/github/pipeline-version-readback.js +117 -0
  99. package/packages/core/providers/github/pipeline-version.js +199 -0
  100. package/packages/core/providers/github/pipeline-worker.js +108 -0
  101. package/packages/core/providers/github/release-evidence-assets.js +97 -0
  102. package/packages/core/publication/candidate/registry-hydration.js +2 -2
  103. package/packages/core/publication/npm/pack-preview.js +2 -2
  104. package/packages/core/publication/npm/pack-result.js +31 -0
  105. package/packages/core/publication/npm/package.js +3 -6
  106. package/packages/core/publication/npm/pipeline-channel.js +36 -0
  107. package/packages/core/publication/npm/pipeline-provider.js +137 -0
  108. package/packages/core/publication/npm/registry.js +12 -9
  109. package/packages/core/publication/pipeline/actions.js +116 -0
  110. package/packages/core/publication/pipeline/apply.js +189 -0
  111. package/packages/core/publication/pipeline/build-segments.js +107 -0
  112. package/packages/core/publication/pipeline/capsules.js +92 -0
  113. package/packages/core/publication/pipeline/context.js +39 -0
  114. package/packages/core/publication/pipeline/development-anchor.js +91 -0
  115. package/packages/core/publication/pipeline/development-current.js +63 -0
  116. package/packages/core/publication/pipeline/development-pr.js +112 -0
  117. package/packages/core/publication/pipeline/development-proof.js +76 -0
  118. package/packages/core/publication/pipeline/development-transition.js +112 -0
  119. package/packages/core/publication/pipeline/distribution.js +130 -0
  120. package/packages/core/publication/pipeline/documents.js +192 -0
  121. package/packages/core/publication/pipeline/effects.js +192 -0
  122. package/packages/core/publication/pipeline/files.js +66 -0
  123. package/packages/core/publication/pipeline/imported-materials.js +32 -0
  124. package/packages/core/publication/pipeline/journal.js +122 -0
  125. package/packages/core/publication/pipeline/next-development.js +117 -0
  126. package/packages/core/publication/pipeline/pack.js +180 -0
  127. package/packages/core/publication/pipeline/package-policy.js +22 -0
  128. package/packages/core/publication/pipeline/plan.js +136 -0
  129. package/packages/core/publication/pipeline/prepare.js +139 -0
  130. package/packages/core/publication/pipeline/qualification.js +175 -0
  131. package/packages/core/publication/pipeline/qualify.js +104 -0
  132. package/packages/core/publication/pipeline/recovery-admission.js +122 -0
  133. package/packages/core/publication/pipeline/recovery-build-download.js +80 -0
  134. package/packages/core/publication/pipeline/recovery-build-plan.js +122 -0
  135. package/packages/core/publication/pipeline/recovery-build-readback.js +68 -0
  136. package/packages/core/publication/pipeline/recovery-capsules.js +54 -0
  137. package/packages/core/publication/pipeline/recovery-import.js +80 -0
  138. package/packages/core/publication/pipeline/recovery-inspection.js +218 -0
  139. package/packages/core/publication/pipeline/recovery-materials.js +104 -0
  140. package/packages/core/publication/pipeline/recovery-plan.js +46 -0
  141. package/packages/core/publication/pipeline/recovery-prepare.js +73 -0
  142. package/packages/core/publication/pipeline/recovery-qualification.js +128 -0
  143. package/packages/core/publication/pipeline/recovery-readback.js +56 -0
  144. package/packages/core/publication/pipeline/recovery-signing.js +58 -0
  145. package/packages/core/publication/pipeline/sealed-products.js +79 -0
  146. package/packages/core/publication/pipeline/settle.js +42 -0
  147. package/packages/core/publication/pipeline/signing.js +140 -0
  148. package/packages/core/publication/pipeline/source-plan.js +83 -0
  149. package/packages/core/publication/pipeline/stable-entry.js +219 -0
  150. package/packages/core/publication/pipeline/stable-products.js +317 -0
  151. package/packages/core/publication/pipeline/stable-wait.js +170 -0
  152. package/packages/core/publication/pipeline/stable.js +82 -0
  153. package/packages/core/publication/pipeline/version-actions.js +93 -0
  154. package/packages/core/publication/pipeline/version-build.js +130 -0
  155. package/packages/core/publication/pipeline/version-context.js +143 -0
  156. package/packages/core/publication/pipeline/version-material.js +36 -0
  157. package/packages/core/publication/pipeline/version-preparation.js +69 -0
  158. package/packages/core/publication/pipeline/version-regeneration.js +162 -0
  159. package/packages/core/publication/pipeline/version-source-guard.js +69 -0
  160. package/packages/core/publication/pipeline/version.js +81 -0
  161. package/packages/core/publication/pipeline/worker.js +72 -0
  162. package/packages/core/publication/publication-reproducibility.js +2 -2
  163. package/packages/core/release/discussion/binary.js +11 -0
  164. package/packages/core/release/discussion/checkpoints.js +45 -4
  165. package/packages/core/release/discussion/envelope.js +1 -0
  166. package/packages/core/release/discussion/evidence.js +51 -0
  167. package/packages/core/release/discussion/presentation.js +92 -0
  168. package/packages/core/release/discussion/publication.js +3 -1
  169. package/packages/core/release/discussion/qualification.js +1 -0
  170. package/packages/core/release/discussion/reader.js +9 -0
  171. package/packages/core/release/discussion/session.js +2 -0
  172. package/packages/core/release/discussion/store.js +28 -31
  173. package/packages/core/release/discussion/threads.js +83 -0
  174. package/packages/core/release/next-development-transition.js +15 -15
  175. package/packages/core/release/promote-candidate/product-provider-adapters.js +4 -3
  176. package/packages/core/release/promote-ref/internal/npm-existing-evidence.js +2 -1
  177. package/packages/core/release/promote-ref/internal/publish-command.js +16 -5
  178. package/packages/core/release/stable-release-gate.js +11 -0
  179. package/packages/core/runtime/buildchain-domain.wasm +0 -0
  180. package/packages/core/runtime/domain-wasm-artifact.js +2 -2
  181. package/packages/core/runtime/entry/actions.js +27 -25
  182. package/packages/core/runtime/entry/attempt.js +25 -0
  183. package/packages/core/runtime/entry/selection.js +14 -0
  184. package/packages/core/runtime/entry/source.js +62 -0
  185. package/packages/core/workflow/attempt/identity.js +170 -0
  186. package/packages/core/workflow/attempt/journal.js +89 -0
  187. package/packages/core/workflow/attempt/materials.js +72 -0
  188. package/packages/core/workflow/attempt/reader-entry.js +12 -0
  189. package/packages/core/workflow/attempt/reader.js +149 -0
  190. package/packages/core/workflow/attempt/records.js +153 -0
  191. package/packages/core/workflow/attempt/store.js +75 -0
  192. package/packages/core/workflow/commands/pipeline-build.mjs +23 -0
  193. package/packages/core/workflow/pipeline/action-output.js +11 -0
  194. package/packages/core/workflow/pipeline/actions.js +52 -0
  195. package/packages/core/workflow/pipeline/build-control.js +140 -0
  196. package/packages/core/workflow/pipeline/build-evidence.js +210 -0
  197. package/packages/core/workflow/pipeline/build-qualification.js +145 -0
  198. package/packages/core/workflow/pipeline/build-result.js +78 -0
  199. package/packages/core/workflow/pipeline/build.js +142 -0
  200. package/packages/core/workflow/pipeline/cancellation.js +169 -0
  201. package/packages/core/workflow/pipeline/channel-control.js +157 -0
  202. package/packages/core/workflow/pipeline/channel-source.js +53 -0
  203. package/packages/core/workflow/pipeline/controller.js +141 -0
  204. package/packages/core/workflow/pipeline/delivery-control.js +249 -0
  205. package/packages/core/workflow/pipeline/delivery-observation.js +124 -0
  206. package/packages/core/workflow/pipeline/delivery-request.js +198 -0
  207. package/packages/core/workflow/pipeline/events.js +84 -0
  208. package/packages/core/workflow/pipeline/fence.js +42 -0
  209. package/packages/core/workflow/pipeline/group-control.js +59 -0
  210. package/packages/core/workflow/pipeline/guard-build.js +74 -0
  211. package/packages/core/workflow/pipeline/guard.js +158 -0
  212. package/packages/core/workflow/pipeline/host.js +144 -0
  213. package/packages/core/workflow/pipeline/integration-status.js +113 -0
  214. package/packages/core/workflow/pipeline/materials.js +58 -0
  215. package/packages/core/workflow/pipeline/notifications.js +36 -0
  216. package/packages/core/workflow/pipeline/parent-notification.js +27 -0
  217. package/packages/core/workflow/pipeline/platforms.js +21 -0
  218. package/packages/core/workflow/pipeline/progress.js +108 -0
  219. package/packages/core/workflow/pipeline/projection.js +20 -0
  220. package/packages/core/workflow/pipeline/reconcile.js +194 -0
  221. package/packages/core/workflow/pipeline/record-action.js +27 -0
  222. package/packages/core/workflow/pipeline/recorder-status.js +69 -0
  223. package/packages/core/workflow/pipeline/recovery-action.js +30 -0
  224. package/packages/core/workflow/pipeline/recovery-admission.js +122 -0
  225. package/packages/core/workflow/pipeline/recovery-build-control.js +95 -0
  226. package/packages/core/workflow/pipeline/recovery-build-evidence.js +71 -0
  227. package/packages/core/workflow/pipeline/recovery-build.js +121 -0
  228. package/packages/core/workflow/pipeline/recovery-controller.js +91 -0
  229. package/packages/core/workflow/pipeline/recovery-integration.js +79 -0
  230. package/packages/core/workflow/pipeline/recovery-merge-proof.js +90 -0
  231. package/packages/core/workflow/pipeline/recovery-ownership-settlement.js +150 -0
  232. package/packages/core/workflow/pipeline/recovery-ownership.js +91 -0
  233. package/packages/core/workflow/pipeline/recovery-plan.js +126 -0
  234. package/packages/core/workflow/pipeline/recovery-runtime.js +68 -0
  235. package/packages/core/workflow/pipeline/recovery-session.js +129 -0
  236. package/packages/core/workflow/pipeline/recovery-transition.js +135 -0
  237. package/packages/core/workflow/pipeline/recovery-unrecorded-build.js +74 -0
  238. package/packages/core/workflow/pipeline/runtime-source.js +111 -0
  239. package/packages/core/workflow/pipeline/selection.js +111 -0
  240. package/packages/core/workflow/pipeline/session.js +72 -0
  241. package/packages/core/workflow/pipeline/settlement.js +137 -0
  242. package/packages/core/workflow/pipeline/wake.js +38 -0
  243. package/packages/core/workflow/pipeline/web-status.js +108 -0
  244. package/packages/core/workflow/workflow-taxonomy.mjs +67 -47
  245. package/scripts/build-release-discussion-reader.mjs +11 -7
  246. package/scripts/check-inventory.mjs +7 -70
  247. package/scripts/check-pipeline-publication-topology.mjs +50 -0
  248. package/scripts/check-public-dogfood-contract.mjs +38 -51
  249. package/scripts/check-release-topology.mjs +15 -8
  250. package/scripts/check-self-consumer-contract.mjs +133 -0
  251. package/scripts/check-universal-workflow-bootstrap.mjs +4 -6
  252. package/scripts/generate-minimal-consumer-contract.mjs +155 -0
  253. package/scripts/generate-site-bundle.mjs +1 -1
  254. package/scripts/inventory/binary.mjs +9 -19
  255. package/scripts/inventory/promotion.mjs +2 -13
  256. package/scripts/prepare-product-toolchain.mjs +10 -0
  257. package/scripts/verify-golden-path.mjs +5 -1
  258. package/scripts/verify-product-platform.mjs +65 -0
  259. package/scripts/verify-standalone-product.mjs +42 -0
  260. package/templates/minimal-consumer/binary/.buildchain/buildchain.toml +45 -0
  261. package/templates/minimal-consumer/binary/.github/workflows/buildchain-recover.yml +30 -0
  262. package/templates/minimal-consumer/binary/.github/workflows/buildchain.yml +28 -0
  263. package/templates/minimal-consumer/binary/package.json +6 -0
  264. package/templates/minimal-consumer/binary/src/build.mjs +5 -0
  265. package/templates/minimal-consumer/binary/src/hello.c +2 -0
  266. package/templates/minimal-consumer/binary/src/verify.mjs +3 -0
  267. package/templates/minimal-consumer/npm/.buildchain/buildchain.toml +46 -0
  268. package/templates/minimal-consumer/npm/.github/workflows/buildchain-recover.yml +30 -0
  269. package/templates/minimal-consumer/npm/.github/workflows/buildchain.yml +28 -0
  270. package/templates/minimal-consumer/npm/package.json +6 -0
  271. package/templates/minimal-consumer/npm/src/build.mjs +5 -0
  272. package/templates/minimal-consumer/npm/src/verify.mjs +3 -0
  273. package/templates/minimal-consumer/paper/.buildchain/buildchain.toml +45 -0
  274. package/templates/minimal-consumer/paper/.github/workflows/buildchain-recover.yml +30 -0
  275. package/templates/minimal-consumer/paper/.github/workflows/buildchain.yml +28 -0
  276. package/templates/minimal-consumer/paper/package.json +6 -0
  277. package/templates/minimal-consumer/paper/src/build.mjs +12 -0
  278. package/templates/minimal-consumer/paper/src/verify.mjs +3 -0
@@ -0,0 +1,155 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { execFileSync } from "node:child_process";
4
+ import { parse as yaml } from "yaml";
5
+ import { format } from "prettier";
6
+ import { standardConsumerExample } from "../packages/core/consumer/contract/examples.js";
7
+ import { inspectConsumerContract } from "../packages/core/consumer/contract/inspection.js";
8
+ import { workflowPath } from "../packages/core/workflow/workflow-taxonomy.mjs";
9
+
10
+ const root = process.cwd(),
11
+ check = process.argv.includes("--check");
12
+ const tracked = execFileSync("git", ["ls-files", "-z"], { encoding: "utf8" })
13
+ .split("\0")
14
+ .filter(Boolean);
15
+
16
+ function output(file, value) {
17
+ const target = path.join(root, file);
18
+ if (check) {
19
+ if (!fs.existsSync(target) || fs.readFileSync(target, "utf8") !== value)
20
+ throw new Error(`${file}: generated contract drift`);
21
+ } else {
22
+ fs.mkdirSync(path.dirname(target), { recursive: true });
23
+ fs.writeFileSync(target, value);
24
+ }
25
+ }
26
+
27
+ function destination(name) {
28
+ if (name === "config-path") return "normal-entry.config-path";
29
+ if (name === "runtime-ref") return "recovery-entry.runtime-ref";
30
+ if (/token|secret|private-key|app-id/u.test(name))
31
+ return "setup.provider-authority";
32
+ if (/run|resume|recover|transaction|discussion|attempt/u.test(name))
33
+ return "attempt.material-index";
34
+ if (/root|proof|nonce|warrant|fence|generation|candidate/u.test(name))
35
+ return "attempt.internal-authority";
36
+ return "internal.plan-derived-input";
37
+ }
38
+
39
+ function workflowInventory() {
40
+ const taxonomy = JSON.parse(
41
+ fs.readFileSync("architecture/workflow-taxonomy.json", "utf8"),
42
+ );
43
+ return taxonomy.entries
44
+ .filter((entry) => ["public", "self"].includes(entry.role))
45
+ .map((entry) => {
46
+ const file = workflowPath(entry),
47
+ document = yaml(fs.readFileSync(file, "utf8"));
48
+ return {
49
+ path: file,
50
+ role: entry.role,
51
+ events: Object.keys(document.on || {}).sort(),
52
+ secrets: Object.keys(document.on?.workflow_call?.secrets || {}).sort(),
53
+ outputs: Object.keys(document.on?.workflow_call?.outputs || {}).sort(),
54
+ destination:
55
+ entry.role === "self"
56
+ ? "self-dogfood.two-callers-or-internal-component"
57
+ : "internal-component.behind-pipeline-or-recovery",
58
+ interfaces: ["workflow_call", "workflow_dispatch"].flatMap((trigger) =>
59
+ Object.entries(document.on?.[trigger]?.inputs || {}).map(
60
+ ([name, definition]) => ({
61
+ trigger,
62
+ name,
63
+ definition,
64
+ destination: destination(name),
65
+ }),
66
+ ),
67
+ ),
68
+ calls: Object.entries(document.jobs || {})
69
+ .filter(([, job]) => job.uses)
70
+ .map(([id, job]) => ({
71
+ id,
72
+ uses: job.uses,
73
+ inputs: Object.keys(job.with || {}).sort(),
74
+ destination: "internal.workflow-composition",
75
+ })),
76
+ };
77
+ })
78
+ .sort((a, b) => a.path.localeCompare(b.path));
79
+ }
80
+
81
+ function consumerSourceInventory() {
82
+ return tracked
83
+ .filter(
84
+ (file) =>
85
+ (/^(?:templates|fixtures|\.buildchain)\//u.test(file) ||
86
+ file === "package.json") &&
87
+ /\.(?:ya?ml|toml|json|[cm]?js|sh|py|ps1)$/u.test(file) &&
88
+ !file.startsWith("templates/minimal-consumer/"),
89
+ )
90
+ .map((file) => {
91
+ const bytes = fs.readFileSync(file, "utf8");
92
+ const kind = /\.ya?ml$/u.test(file)
93
+ ? "caller"
94
+ : /\.toml$/u.test(file)
95
+ ? "config"
96
+ : "consumer-source";
97
+ return {
98
+ path: file,
99
+ kind,
100
+ destination:
101
+ kind === "caller"
102
+ ? "replace-with-shared-pair"
103
+ : kind === "config"
104
+ ? "closed-toml-plan"
105
+ : "retain-product-source; move-orchestration-into-runtime",
106
+ commandReferences: [
107
+ ...new Set(
108
+ bytes.match(
109
+ /(?:packages\/core|scripts)\/[A-Za-z0-9_./-]+\.(?:[cm]?js|sh|py|ps1)/gu,
110
+ ) || [],
111
+ ),
112
+ ].sort(),
113
+ };
114
+ });
115
+ }
116
+
117
+ for (const type of ["npm", "binary", "paper"]) {
118
+ const files = standardConsumerExample(type);
119
+ if (check) {
120
+ const directory = `templates/minimal-consumer/${type}`;
121
+ for (const entry of fs.readdirSync(directory, {
122
+ recursive: true,
123
+ withFileTypes: true,
124
+ })) {
125
+ if (entry.isDirectory()) continue;
126
+ const file = path
127
+ .relative(directory, path.join(entry.parentPath, entry.name))
128
+ .split(path.sep)
129
+ .join("/");
130
+ if (!entry.isFile() || !Object.hasOwn(files, file))
131
+ throw new Error(
132
+ `${directory}/${file}: undeclared generated consumer file`,
133
+ );
134
+ }
135
+ }
136
+ const inspection = inspectConsumerContract(files);
137
+ if (!inspection.ok) throw new Error(inspection.issues.join("\n"));
138
+ for (const [file, bytes] of Object.entries(files))
139
+ output(`templates/minimal-consumer/${type}/${file}`, bytes);
140
+ }
141
+ output(
142
+ "architecture/minimal-consumer-migration.json",
143
+ await format(
144
+ JSON.stringify({
145
+ schema: "buildchain.consumer-migration/v1",
146
+ stage: "self-cutover-in-progress; final-release-qualification-pending",
147
+ workflows: workflowInventory(),
148
+ consumerSources: consumerSourceInventory(),
149
+ }),
150
+ { parser: "json" },
151
+ ),
152
+ );
153
+ console.log(
154
+ "Minimal consumer contract: three shared-caller examples and complete migration inventory verified.",
155
+ );
@@ -1343,7 +1343,7 @@ function buildSiteBundle() {
1343
1343
  "badge-endpoint-registry.json": badgeEndpointRegistry,
1344
1344
  "publication-registry.json": publicationRegistry,
1345
1345
  "buildchain-contract.json": createBuildchainContractWorld({ root, controllerRegistry }),
1346
- "kfd-upstream-aggregate.json": collectKfdUpstreamFacts({ cwd: root, includeOwn: false }),
1346
+ "kfd-upstream-aggregate.json": collectKfdUpstreamFacts({ cwd: root, components: readJson("architecture/product-upstreams.json"), includeOwn: false }),
1347
1347
  "kfd-claims.json": createBuildchainKfdClaimRegistry({ root }),
1348
1348
  "product-mechanism.json": productMechanism,
1349
1349
  "release-provenance.json": releaseProvenance,
@@ -1,26 +1,16 @@
1
1
  import assert from "node:assert/strict";
2
+ import { checkSelfConsumerContract } from "../check-self-consumer-contract.mjs";
2
3
  import { inspectWorkflowJob, readWorkflow } from "../workflow-action-graph.mjs";
3
4
 
4
5
  export function assertBinaryInventory(root) {
5
- const file = ".github/workflows/self-build-binary-distribution.yml";
6
- const workflow = readWorkflow(file, root);
7
- assert.equal(workflow.name, "Binary Distribution");
8
- assert.deepEqual(Object.keys(workflow.jobs).filter(id => id !== "execution-runtime"), ["preflight", "binary", "passport", "dispatch-publication"]);
9
- const graphs = Object.keys(workflow.jobs).filter(id => id !== "execution-runtime").map(id => inspectWorkflowJob(file, id, root));
10
- for (const graph of graphs) {
11
- assert.equal(graph.job.permissions.contents, "read");
12
- assert.notEqual(graph.job.permissions["id-token"], "write");
13
- assert.ok(!JSON.stringify(graph.job["runs-on"]).includes("self-hosted"));
14
- for (const step of graph.steps) assert.ok(!/gh release (?:upload|create)/u.test(step.run || ""));
15
- assert.ok(graph.actions.has(`actions/build/binary/${["preflight", "build", "passport", "dispatch-publication"][graphs.indexOf(graph)]}`));
16
- }
17
- const binary = graphs[1];
18
- assert.deepEqual(binary.job.strategy.matrix.include.map(entry => entry.os).sort(), ["macos-latest", "ubuntu-24.04", "windows-2022"]);
19
- const passport = graphs[2];
20
- const executable = passport.modules.get("packages/core/build/binary/distribution.js");
21
- for (const command of ["verifyBuildchainLogEvents", "verifyReleasePassport", "verifyArtifactPassport", "createReleaseEvidenceBundle", "buildchain-log-events", "buildchain-log-summary"])
22
- assert.ok(executable.includes(command), `Binary evidence is missing ${command}`);
23
- assert.ok(passport.actions.has("actions/build/binary/qualify"));
6
+ const { plan } = checkSelfConsumerContract(root);
7
+ assert.deepEqual(plan.products.filter(product => product.type === "binary")
8
+ .flatMap(product => product.platforms).sort(), ["linux-x64", "macos-arm64", "windows-x64"]);
9
+ const build = inspectWorkflowJob(".github/workflows/.release-pipeline-products.yml", "build", root);
10
+ assert.equal(build.job.permissions.contents, "read");
11
+ assert.notEqual(build.job.permissions["id-token"], "write");
12
+ assert.ok(!JSON.stringify(build.job["runs-on"]).includes("self-hosted"));
13
+ for (const step of build.steps) assert.ok(!/gh release (?:upload|create)/u.test(step.run || ""));
24
14
  const publish = inspectWorkflowJob(".github/workflows/.release-binary-assets.yml", "publish", root);
25
15
  assert.equal(publish.workflow.jobs["publication-authority"].uses, "./.github/workflows/.release-authority.yml");
26
16
  assert.ok(publish.job.needs.includes("publication-authority"));
@@ -1,4 +1,5 @@
1
1
  import assert from "node:assert/strict";
2
+ import { checkSelfConsumerContract } from "../check-self-consumer-contract.mjs";
2
3
  import fs from "node:fs";
3
4
  import path from "node:path";
4
5
  import YAML from "yaml";
@@ -35,19 +36,7 @@ export function assertPromotionInventory(root) {
35
36
  "publish-command",
36
37
  ])
37
38
  assert.ok(!request.properties[key]);
38
- for (const file of [
39
- "self-release-promote",
40
- "self-release-tail-dogfood",
41
- "self-ops-promotion-recovery",
42
- ]) {
43
- const caller = YAML.parse(read(`.github/workflows/${file}.yml`));
44
- const calls = Object.values(caller.jobs).filter(
45
- (job) => job.uses === `kungfu-systems/buildchain/${publicPath}@v4`,
46
- );
47
- assert.equal(calls.length, 1, file);
48
- assert.ok(calls[0].with["request-json"]);
49
- assert.ok(Object.keys(calls[0].with).every(key => ["request-json", "runtime-ref", "contract-lock", "runtime-selection"].includes(key)));
50
- }
39
+ checkSelfConsumerContract(root);
51
40
  const component = ".github/workflows/.release-promote.yml";
52
41
  const expected = {
53
42
  qualify: "promotion/qualify",
@@ -0,0 +1,10 @@
1
+ import fs from "node:fs";
2
+ import os from "node:os";
3
+ import path from "node:path";
4
+
5
+ // Product prerequisites cross command phases through the runner file protocol.
6
+ // An explicit cache works with the credential-isolated Windows environment too.
7
+ fs.appendFileSync(
8
+ process.env.GITHUB_ENV,
9
+ `GOTOOLCHAIN=go1.25.14+auto\nGOCACHE=${path.join(os.tmpdir(), "buildchain-go-cache")}\nGOPATH=${path.join(os.tmpdir(), "buildchain-go")}\n`,
10
+ );
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import fs from "node:fs";
3
+ import { readNpmPackResult } from "../packages/core/publication/npm/pack-result.js";
3
4
  import os from "node:os";
4
5
  import path from "node:path";
5
6
  import { fileURLToPath } from "node:url";
@@ -44,7 +45,10 @@ export function verifyGoldenPath() {
44
45
  ["pack", "--json", "--pack-destination", packDir],
45
46
  { cwd: root, json: true },
46
47
  );
47
- const tarball = path.join(packDir, packed[0].filename);
48
+ const tarball = path.join(
49
+ packDir,
50
+ readNpmPackResult(JSON.stringify(packed)).filename,
51
+ );
48
52
  fs.writeFileSync(
49
53
  path.join(consumer, "package.json"),
50
54
  `${JSON.stringify(
@@ -0,0 +1,65 @@
1
+ import path from "node:path";
2
+ import { execFileSync } from "node:child_process";
3
+ import { verifyStageCapsuleCheckpoints } from "../packages/core/build/stage-capsule/rehearsal/verify.js";
4
+
5
+ const platform = {
6
+ linux: "linux-x64",
7
+ darwin: "macos-arm64",
8
+ win32: "windows-x64",
9
+ }[process.platform];
10
+ if (!platform)
11
+ throw new Error(
12
+ `Unsupported product verification platform: ${process.platform}`,
13
+ );
14
+ const goVersion = execFileSync("go", ["version"], { encoding: "utf8" }).trim();
15
+ const goMatch = /^go version go1\.(\d+)\./u.exec(goVersion);
16
+ if (!goMatch || Number(goMatch[1]) < 25)
17
+ throw new Error(
18
+ `Product verification requires Go 1.25 or newer in major 1: ${goVersion}`,
19
+ );
20
+ const workspace = process.cwd();
21
+ const result = verifyStageCapsuleCheckpoints({
22
+ runtimeRoot: workspace,
23
+ workspace,
24
+ platform,
25
+ environment: process.env,
26
+ });
27
+ if (platform === "linux-x64") {
28
+ // Same immutable image and backbone tests as the retired container CI lane.
29
+ // Supply the selected Node as the hosted container runner did; no credentials.
30
+ const image =
31
+ "ghcr.io/kungfu-systems/build-images/kungfu-verify@sha256:11f0ba64267ce88174a4f73a9bf833ff4e9c59cd16ec3d08a6432a06c2be6fb1";
32
+ execFileSync(
33
+ "docker",
34
+ [
35
+ "run",
36
+ "--rm",
37
+ "--network=none",
38
+ "--cap-drop=ALL",
39
+ "--security-opt=no-new-privileges",
40
+ "--mount",
41
+ `type=bind,source=${path.resolve(workspace)},target=/source,readonly`,
42
+ "--mount",
43
+ `type=bind,source=${process.execPath},target=/toolchain/node,readonly`,
44
+ "--env",
45
+ "PATH=/toolchain:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
46
+ "--workdir",
47
+ "/source",
48
+ image,
49
+ "node",
50
+ "--test",
51
+ "tests/build-orchestration.test.mjs",
52
+ "tests/build-artifact-pipeline.test.mjs",
53
+ "tests/dev-delivery-minimal-request.test.mjs",
54
+ ],
55
+ { stdio: "inherit" },
56
+ );
57
+ }
58
+ console.log(
59
+ JSON.stringify({
60
+ platform,
61
+ checkpoint: result.checkpoint,
62
+ resume: result.resume,
63
+ tail: result.tail,
64
+ }),
65
+ );
@@ -0,0 +1,42 @@
1
+ import assert from "node:assert/strict";
2
+ import fs from "node:fs";
3
+ import path from "node:path";
4
+ import { execFileSync } from "node:child_process";
5
+ import { createHash } from "node:crypto";
6
+ import {
7
+ platformTriple,
8
+ packageVersion,
9
+ sourceSha,
10
+ } from "../packages/core/build/standalone/identity.js";
11
+
12
+ const cwd = process.cwd();
13
+ const manifest = JSON.parse(
14
+ fs.readFileSync(
15
+ path.join(cwd, "dist/binary", `buildchain-${platformTriple()}.json`),
16
+ "utf8",
17
+ ),
18
+ );
19
+ const version = packageVersion(cwd);
20
+ assert.equal(manifest.version, version);
21
+ assert.equal(manifest.sourceSha, sourceSha(cwd));
22
+ assert.equal(manifest.platform, platformTriple());
23
+ const binary = path.join(
24
+ cwd,
25
+ "dist/binary",
26
+ process.platform === "win32" ? "buildchain.exe" : "buildchain",
27
+ );
28
+ assert.equal(
29
+ createHash("sha256").update(fs.readFileSync(binary)).digest("hex"),
30
+ manifest.sha256,
31
+ );
32
+ assert.equal(
33
+ execFileSync(binary, ["--version"], { encoding: "utf8" }).trim(),
34
+ version,
35
+ );
36
+ assert.match(
37
+ execFileSync(binary, ["help"], { encoding: "utf8" }),
38
+ /^Usage:\s+buildchain --help/mu,
39
+ );
40
+ process.stdout.write(
41
+ `Verified standalone product ${platformTriple()} at ${version}\n`,
42
+ );
@@ -0,0 +1,45 @@
1
+ schema = 2
2
+
3
+ [[products]]
4
+ id = "main"
5
+ type = "binary"
6
+ platforms = ["linux-x64"]
7
+ build = ["node src/build.mjs"]
8
+ verify = ["node src/verify.mjs"]
9
+
10
+ [[products.artifacts]]
11
+ id = "main"
12
+ path = "dist/hello.tar.gz"
13
+ kind = "archive"
14
+
15
+ [[products.targets]]
16
+ provider = "github-release"
17
+ artifacts = ["main"]
18
+
19
+ [version]
20
+ strategy = "semver"
21
+
22
+ [[version.files]]
23
+ path = "package.json"
24
+ format = "json"
25
+ key = "version"
26
+
27
+ [[channels]]
28
+ from = "feature/*"
29
+ to = "dev/v1/v1.0"
30
+ operation = "develop"
31
+
32
+ [[channels]]
33
+ from = "dev/v1/v1.0"
34
+ to = "alpha/v1/v1.0"
35
+ operation = "alpha"
36
+
37
+ [[channels]]
38
+ from = "alpha/v1/v1.0"
39
+ to = "release/v1/v1.0"
40
+ operation = "stable"
41
+
42
+ [review]
43
+ minimum_approvals = 1
44
+ code_owners = true
45
+ merge_queue = true
@@ -0,0 +1,30 @@
1
+ name: Buildchain recovery
2
+ on:
3
+ workflow_dispatch:
4
+ inputs:
5
+ attempt:
6
+ description: Exact Buildchain attempt to recover
7
+ required: true
8
+ type: string
9
+ runtime-ref:
10
+ description: Optional repaired runtime
11
+ required: false
12
+ type: string
13
+ permissions:
14
+ contents: read
15
+ jobs:
16
+ buildchain:
17
+ uses: kungfu-systems/buildchain/.github/workflows/public-ops-recover.yml@v4
18
+ with:
19
+ attempt: ${{ inputs.attempt }}
20
+ runtime-ref: ${{ inputs.runtime-ref }}
21
+ secrets: inherit
22
+ permissions:
23
+ actions: write
24
+ attestations: write
25
+ checks: write
26
+ contents: write
27
+ discussions: write
28
+ id-token: write
29
+ pull-requests: write
30
+ statuses: write
@@ -0,0 +1,28 @@
1
+ name: Buildchain pipeline
2
+ on:
3
+ pull_request:
4
+ types: [opened, reopened, synchronize, ready_for_review, converted_to_draft, closed, labeled, unlabeled, edited, enqueued, dequeued]
5
+ pull_request_review:
6
+ types: [submitted, dismissed]
7
+ pull_request_target:
8
+ types: [closed]
9
+ merge_group:
10
+ types: [checks_requested]
11
+ push:
12
+ repository_dispatch:
13
+ types: [buildchain-attempt-wake]
14
+ permissions:
15
+ contents: read
16
+ jobs:
17
+ buildchain:
18
+ uses: kungfu-systems/buildchain/.github/workflows/public-ops-pipeline.yml@v4
19
+ secrets: inherit
20
+ permissions:
21
+ actions: write
22
+ attestations: write
23
+ checks: write
24
+ contents: write
25
+ discussions: write
26
+ id-token: write
27
+ pull-requests: write
28
+ statuses: write
@@ -0,0 +1,6 @@
1
+ {
2
+ "name": "minimal-binary",
3
+ "private": true,
4
+ "version": "1.0.0-alpha.1",
5
+ "type": "module"
6
+ }
@@ -0,0 +1,5 @@
1
+ import fs from "node:fs";
2
+ fs.mkdirSync("dist", { recursive: true });
3
+ import { execFileSync } from "node:child_process";
4
+ execFileSync("cc", ["src/hello.c", "-o", "dist/hello"], { stdio: "inherit" });
5
+ execFileSync("tar", ["-czf", "dist/hello.tar.gz", "-C", "dist", "hello"], { stdio: "inherit" });
@@ -0,0 +1,2 @@
1
+ #include <stdio.h>
2
+ int main(void) { puts("hello"); return 0; }
@@ -0,0 +1,3 @@
1
+ import assert from "node:assert/strict";
2
+ import fs from "node:fs";
3
+ assert.ok(fs.statSync("dist/hello.tar.gz").size > 0);
@@ -0,0 +1,46 @@
1
+ schema = 2
2
+
3
+ [[products]]
4
+ id = "main"
5
+ type = "npm"
6
+ platforms = ["linux-x64"]
7
+ build = ["node src/build.mjs"]
8
+ verify = ["node src/verify.mjs"]
9
+
10
+ [[products.artifacts]]
11
+ id = "main"
12
+ path = "dist/package"
13
+ kind = "npm-package"
14
+
15
+ [[products.targets]]
16
+ provider = "npm"
17
+ artifacts = ["main"]
18
+ access = "public"
19
+
20
+ [version]
21
+ strategy = "semver"
22
+
23
+ [[version.files]]
24
+ path = "package.json"
25
+ format = "json"
26
+ key = "version"
27
+
28
+ [[channels]]
29
+ from = "feature/*"
30
+ to = "dev/v1/v1.0"
31
+ operation = "develop"
32
+
33
+ [[channels]]
34
+ from = "dev/v1/v1.0"
35
+ to = "alpha/v1/v1.0"
36
+ operation = "alpha"
37
+
38
+ [[channels]]
39
+ from = "alpha/v1/v1.0"
40
+ to = "release/v1/v1.0"
41
+ operation = "stable"
42
+
43
+ [review]
44
+ minimum_approvals = 1
45
+ code_owners = true
46
+ merge_queue = true
@@ -0,0 +1,30 @@
1
+ name: Buildchain recovery
2
+ on:
3
+ workflow_dispatch:
4
+ inputs:
5
+ attempt:
6
+ description: Exact Buildchain attempt to recover
7
+ required: true
8
+ type: string
9
+ runtime-ref:
10
+ description: Optional repaired runtime
11
+ required: false
12
+ type: string
13
+ permissions:
14
+ contents: read
15
+ jobs:
16
+ buildchain:
17
+ uses: kungfu-systems/buildchain/.github/workflows/public-ops-recover.yml@v4
18
+ with:
19
+ attempt: ${{ inputs.attempt }}
20
+ runtime-ref: ${{ inputs.runtime-ref }}
21
+ secrets: inherit
22
+ permissions:
23
+ actions: write
24
+ attestations: write
25
+ checks: write
26
+ contents: write
27
+ discussions: write
28
+ id-token: write
29
+ pull-requests: write
30
+ statuses: write
@@ -0,0 +1,28 @@
1
+ name: Buildchain pipeline
2
+ on:
3
+ pull_request:
4
+ types: [opened, reopened, synchronize, ready_for_review, converted_to_draft, closed, labeled, unlabeled, edited, enqueued, dequeued]
5
+ pull_request_review:
6
+ types: [submitted, dismissed]
7
+ pull_request_target:
8
+ types: [closed]
9
+ merge_group:
10
+ types: [checks_requested]
11
+ push:
12
+ repository_dispatch:
13
+ types: [buildchain-attempt-wake]
14
+ permissions:
15
+ contents: read
16
+ jobs:
17
+ buildchain:
18
+ uses: kungfu-systems/buildchain/.github/workflows/public-ops-pipeline.yml@v4
19
+ secrets: inherit
20
+ permissions:
21
+ actions: write
22
+ attestations: write
23
+ checks: write
24
+ contents: write
25
+ discussions: write
26
+ id-token: write
27
+ pull-requests: write
28
+ statuses: write
@@ -0,0 +1,6 @@
1
+ {
2
+ "name": "minimal-npm",
3
+ "private": true,
4
+ "version": "1.0.0-alpha.1",
5
+ "type": "module"
6
+ }
@@ -0,0 +1,5 @@
1
+ import fs from "node:fs";
2
+ fs.mkdirSync("dist", { recursive: true });
3
+ fs.mkdirSync("dist/package", { recursive: true });
4
+ fs.writeFileSync("dist/package/index.js", 'export const hello = "hello";\n');
5
+ fs.writeFileSync("dist/package/package.json", JSON.stringify({ name: "@example/minimal", version: JSON.parse(fs.readFileSync("package.json")).version, type: "module", exports: "./index.js" }));
@@ -0,0 +1,3 @@
1
+ import assert from "node:assert/strict";
2
+ import fs from "node:fs";
3
+ assert.ok(fs.statSync("dist/package").isDirectory());
@@ -0,0 +1,45 @@
1
+ schema = 2
2
+
3
+ [[products]]
4
+ id = "main"
5
+ type = "paper"
6
+ platforms = ["linux-x64"]
7
+ build = ["node src/build.mjs"]
8
+ verify = ["node src/verify.mjs"]
9
+
10
+ [[products.artifacts]]
11
+ id = "main"
12
+ path = "dist/paper.pdf"
13
+ kind = "pdf"
14
+
15
+ [[products.targets]]
16
+ provider = "github-release"
17
+ artifacts = ["main"]
18
+
19
+ [version]
20
+ strategy = "semver"
21
+
22
+ [[version.files]]
23
+ path = "package.json"
24
+ format = "json"
25
+ key = "version"
26
+
27
+ [[channels]]
28
+ from = "feature/*"
29
+ to = "dev/v1/v1.0"
30
+ operation = "develop"
31
+
32
+ [[channels]]
33
+ from = "dev/v1/v1.0"
34
+ to = "alpha/v1/v1.0"
35
+ operation = "alpha"
36
+
37
+ [[channels]]
38
+ from = "alpha/v1/v1.0"
39
+ to = "release/v1/v1.0"
40
+ operation = "stable"
41
+
42
+ [review]
43
+ minimum_approvals = 1
44
+ code_owners = true
45
+ merge_queue = true