@kungfu-tech/buildchain 4.1.3-alpha.9 → 4.1.4-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 (205) hide show
  1. package/AGENTS.md +11 -13
  2. package/CONTRIBUTING.md +32 -9
  3. package/README.md +56 -140
  4. package/actions/release/promotion/ref/README.md +1 -1
  5. package/architecture/action-taxonomy.json +1 -1
  6. package/architecture/agent-change-map.md +32 -45
  7. package/architecture/build-orchestration.json +1 -1
  8. package/architecture/capability-state-machine-manifest.json +5 -5
  9. package/architecture/ci-lane-change-budget.json +92 -92
  10. package/architecture/code-layout.json +2 -12
  11. package/architecture/core-mechanisms.json +38 -39
  12. package/architecture/cross-platform-adopter-qualification.json +1 -1
  13. package/architecture/dev-delivery-orchestration.json +2 -2
  14. package/architecture/floating-consumer-policy.json +3 -3
  15. package/architecture/internal-capabilities.json +27 -28
  16. package/architecture/maintainability-debt.json +60 -94
  17. package/architecture/maintainability-policy.json +7 -13
  18. package/architecture/minimal-consumer-migration.json +43 -5014
  19. package/architecture/platform-stage-checkpoints.json +1 -1
  20. package/architecture/release-tail-contract.json +2 -2
  21. package/architecture/release-topology.json +33 -25
  22. package/architecture/stage-capsule-qualification.json +1 -1
  23. package/architecture/universal-workflow-bootstrap.json +60 -60
  24. package/architecture/universal-workflow-capability-policy.json +3 -3
  25. package/architecture/universal-workflow-fault-campaign.json +7 -7
  26. package/architecture/workflow-taxonomy.json +59 -60
  27. package/contracts/fixtures/v4-tail-reseal-v1/valid.json +1 -1
  28. package/dist/site/buildchain-contract.json +138 -66
  29. package/dist/site/buildchain-site.json +257 -331
  30. package/dist/site/capability-registry.json +4 -4
  31. package/dist/site/cli-registry.json +6 -142
  32. package/dist/site/controller-registry.json +19 -19
  33. package/dist/site/kfd-claims.json +481 -529
  34. package/dist/site/kfd-upstream-aggregate.json +1 -1
  35. package/dist/site/manual-registry.json +22 -22
  36. package/dist/site/node-api-registry.json +82 -339
  37. package/dist/site/page-registry.json +229 -304
  38. package/dist/site/public-surface-audit.json +544 -754
  39. package/dist/site/publication-authority-registry.json +316 -316
  40. package/dist/site/publication-registry.json +1 -1
  41. package/dist/site/site-manifest.json +23 -23
  42. package/dist/site/workflow-registry.json +1071 -1027
  43. package/docs/MAP.md +28 -20
  44. package/docs/auditable-demo.md +17 -49
  45. package/docs/bootstrap-recovery.md +46 -37
  46. package/docs/cli-reference.md +2 -46
  47. package/docs/cli.md +97 -186
  48. package/docs/code-organization.md +7 -5
  49. package/docs/dev-alpha-candidate-patrol.md +19 -42
  50. package/docs/dev-delivery-orchestration.md +15 -11
  51. package/docs/dev-delivery-qualification-landing-adr.md +10 -9
  52. package/docs/dev-delivery-warrant.md +17 -16
  53. package/docs/dev-qualification-patrol.md +25 -20
  54. package/docs/getting-started.md +80 -139
  55. package/docs/github-artifact-attestation.md +31 -81
  56. package/docs/install.md +66 -30
  57. package/docs/lifecycle-protocol.md +19 -57
  58. package/docs/migration-inventory.md +17 -45
  59. package/docs/next-development-transition.md +13 -13
  60. package/docs/node-api-reference.md +122 -138
  61. package/docs/oci-publication.md +13 -10
  62. package/docs/publication-artifacts.md +128 -486
  63. package/docs/publication-authority.md +15 -45
  64. package/docs/publish-transaction.md +13 -11
  65. package/docs/release-candidate.md +126 -355
  66. package/docs/release-discussions.md +36 -67
  67. package/docs/release-flow.md +80 -339
  68. package/docs/release-governance.md +114 -962
  69. package/docs/release-promotion-request.md +45 -43
  70. package/docs/release-propagation.md +13 -27
  71. package/docs/release-tail-provider-plane.md +38 -65
  72. package/docs/reusable-build-surface.md +78 -196
  73. package/docs/runtime-train-validation.md +8 -6
  74. package/docs/stable-candidate-patrol.md +13 -66
  75. package/docs/v4-adopter-delivery.md +15 -15
  76. package/docs/v4-declarative-release-tail-migration.md +19 -17
  77. package/docs/v4-production-release.md +11 -6
  78. package/docs/v4-publication-rehearsal.md +12 -27
  79. package/docs/v4-stage-capsule.md +14 -20
  80. package/docs/v4-tail-reseal.md +34 -20
  81. package/docs/web-surface-deployments.md +26 -264
  82. package/docs/workflow-catalog.md +31 -31
  83. package/docs/workflow-path-migration.md +10 -4
  84. package/package.json +5 -4
  85. package/packages/core/adoption/buildchain-kfd-claims.js +7 -7
  86. package/packages/core/adoption/cli/output.mjs +1 -9
  87. package/packages/core/adoption/cli/product-gate.mjs +1 -15
  88. package/packages/core/adoption/cli/project.mjs +9 -10
  89. package/packages/core/adoption/cli/standards.mjs +1 -14
  90. package/packages/core/adoption/cli/support.mjs +0 -2
  91. package/packages/core/adoption/cli/surface-register.mjs +0 -2
  92. package/packages/core/adoption/commands/init-repo.mjs +77 -485
  93. package/packages/core/adoption/consumer-init.js +279 -0
  94. package/packages/core/adoption/qualification/admission.js +1 -1
  95. package/packages/core/build/cli/cache.mjs +0 -2
  96. package/packages/core/build/cli/facts.mjs +0 -3
  97. package/packages/core/build/cli/homebrew.mjs +0 -4
  98. package/packages/core/build/cli/lifecycle.mjs +0 -3
  99. package/packages/core/build/github-artifact-attestation.js +2 -2
  100. package/packages/core/build/platform-stage-checkpoints.js +1 -1
  101. package/packages/core/build/signing/dispatch.js +1 -1
  102. package/packages/core/consumer/buildchain-config.js +9 -0
  103. package/packages/core/consumer/contract/inspection.js +351 -9
  104. package/packages/core/consumer/contract/javascript-syntax.js +439 -0
  105. package/packages/core/consumer/contract/javascript-values.js +61 -0
  106. package/packages/core/consumer/contract/javascript.js +555 -0
  107. package/packages/core/consumer/contract/local-validation.js +84 -0
  108. package/packages/core/contracts/buildchain-contract.js +39 -8
  109. package/packages/core/contracts/cli/introspection.mjs +1 -9
  110. package/packages/core/contracts/public-surface-cli.js +0 -1
  111. package/packages/core/dev-delivery/dev-delivery-contract-surface.js +2 -2
  112. package/packages/core/governance/buildchain-publication-authority.js +24 -24
  113. package/packages/core/governance/cli/doctor.mjs +58 -42
  114. package/packages/core/governance/commands/architecture.mjs +6 -1
  115. package/packages/core/governance/commands/audit-publication-control-plane.mjs +1 -1
  116. package/packages/core/governance/commands/workflow-friction-report.mjs +1 -1
  117. package/packages/core/governance/github-governance-authority.js +2 -2
  118. package/packages/core/governance/publication/collection.js +1 -1
  119. package/packages/core/index.js +1 -3
  120. package/packages/core/observability/cli/candidate.mjs +0 -2
  121. package/packages/core/observability/cli/context.mjs +0 -5
  122. package/packages/core/observability/cli/diagnostics.mjs +0 -7
  123. package/packages/core/observability/cli/events.mjs +2 -10
  124. package/packages/core/paper/commands/paper-work-fleet-cli.mjs +1 -1
  125. package/packages/core/paper/commands/paper.mjs +33 -422
  126. package/packages/core/paper/consumer-status.js +72 -0
  127. package/packages/core/paper/operations/identity.js +0 -3
  128. package/packages/core/paper/operations/migration.js +460 -0
  129. package/packages/core/paper/operations/preflight-checks.js +8 -68
  130. package/packages/core/paper/operations/scaffold.js +16 -326
  131. package/packages/core/paper/operations/status.js +27 -53
  132. package/packages/core/paper/paper-agent-entry.js +36 -147
  133. package/packages/core/paper/paper-fleet.js +24 -39
  134. package/packages/core/paper/paper-repository.js +16 -0
  135. package/packages/core/paper/paper-runtime-channels.js +1 -1
  136. package/packages/core/paper/paper-scaffold-content.js +153 -162
  137. package/packages/core/paper/paper-work.js +3 -10
  138. package/packages/core/paper/paper.js +43 -5
  139. package/packages/core/providers/github/artifact-attestation.js +1 -1
  140. package/packages/core/providers/github/pipeline-context-artifacts.js +172 -0
  141. package/packages/core/providers/github/pipeline-release-evidence.js +17 -98
  142. package/packages/core/providers/github/pipeline-stable-baseline.js +86 -0
  143. package/packages/core/providers/github/pipeline-stable-source.js +22 -4
  144. package/packages/core/providers/github/release-evidence-assets.js +97 -0
  145. package/packages/core/publication/authority/control-plane.js +2 -2
  146. package/packages/core/publication/authority/seal.js +1 -1
  147. package/packages/core/publication/cli/dispatch.mjs +1 -12
  148. package/packages/core/publication/pipeline/actions.js +16 -9
  149. package/packages/core/publication/pipeline/apply.js +17 -9
  150. package/packages/core/publication/pipeline/context.js +29 -0
  151. package/packages/core/publication/pipeline/journal.js +13 -1
  152. package/packages/core/publication/pipeline/prepare.js +15 -6
  153. package/packages/core/publication/pipeline/recovery-import.js +1 -1
  154. package/packages/core/publication/pipeline/recovery-materials.js +63 -1
  155. package/packages/core/publication/pipeline/recovery-prepare.js +21 -9
  156. package/packages/core/publication/pipeline/stable-entry.js +12 -3
  157. package/packages/core/publication/pipeline/stable-products.js +21 -19
  158. package/packages/core/publication/pipeline/version-actions.js +15 -6
  159. package/packages/core/publication/publication-rehearsal-projection.js +0 -9
  160. package/packages/core/release/cli/dispatch.mjs +1 -4
  161. package/packages/core/release/cli/inspection-handlers.mjs +1 -33
  162. package/packages/core/release/cli/release-handlers.mjs +2 -19
  163. package/packages/core/release/cli/verification-handlers.mjs +4 -25
  164. package/packages/core/release/next-development-projection.js +13 -13
  165. package/packages/core/release/passport/locations.js +13 -8
  166. package/packages/core/release/release-passport.js +70 -5
  167. package/packages/core/web/cli/badges.mjs +0 -4
  168. package/packages/core/web/publication-admission.js +1 -1
  169. package/packages/core/web/publication-capability.js +1 -1
  170. package/packages/core/web/readme-badges.js +1 -1
  171. package/packages/core/workflow/cli/main.mjs +1 -4
  172. package/packages/core/workflow/cli/process.mjs +1 -1
  173. package/packages/core/workflow/commands/buildchain-cli-help.mjs +2 -8
  174. package/packages/core/workflow/engine/conformance.js +1 -1
  175. package/packages/core/workflow/pipeline/build.js +21 -1
  176. package/packages/core/workflow/pipeline/delivery-observation.js +6 -2
  177. package/packages/core/workflow/workflow-taxonomy.mjs +61 -17
  178. package/scripts/check-code-layout.mjs +2 -0
  179. package/scripts/check-core-mechanism-inventory.mjs +29 -13
  180. package/scripts/check-floating-consumer-policy-contract.mjs +3 -3
  181. package/scripts/check-inventory.mjs +27 -27
  182. package/scripts/check-maintainability.mjs +28 -5
  183. package/scripts/check-public-dogfood-contract.mjs +3 -3
  184. package/scripts/check-release-topology.mjs +1 -1
  185. package/scripts/check-self-consumer-contract.mjs +7 -7
  186. package/scripts/check-universal-workflow-bootstrap.mjs +1 -1
  187. package/scripts/generate-channel-promotion-workflow.mjs +1 -1
  188. package/scripts/generate-minimal-consumer-contract.mjs +21 -1
  189. package/scripts/generate-site-bundle.mjs +2 -1
  190. package/scripts/generate-tail-reseal-fixture.mjs +3 -3
  191. package/scripts/inventory/promotion.mjs +1 -1
  192. package/scripts/next-development-self-dogfood-harness.mjs +1 -1
  193. package/scripts/next-development-self-dogfood.mjs +4 -4
  194. package/scripts/site-capability-metadata.mjs +2 -6
  195. package/scripts/source-metric-lineage.mjs +62 -7
  196. package/scripts/verify-golden-path.mjs +31 -35
  197. package/templates/native-dev-delivery.yml +1 -1
  198. package/templates/universal-buildchain-bootstrap.yml +1 -1
  199. package/packages/core/paper/operations/bootstrap.js +0 -75
  200. package/packages/core/paper/operations/plans.js +0 -213
  201. package/packages/core/paper/operations/provisioning.js +0 -113
  202. package/packages/core/paper/operations/scaffold-config.js +0 -77
  203. package/packages/core/paper/operations/scaffold-workflows.js +0 -116
  204. package/packages/core/paper/operations/workspace.js +0 -60
  205. package/packages/core/paper/paper-npm-bootstrap.js +0 -492
@@ -116,10 +116,10 @@ export function checkFloatingConsumerPolicyContract() {
116
116
  assertOrdered("actions/publication/candidate/plan/action.yml", [
117
117
  "Admit source checkout", "Enforce v4 floating consumer policy", "Resolve controller identities",
118
118
  ]);
119
- const publication = YAML.parse(read(".github/workflows/public-build-publication.yml"));
119
+ const publication = YAML.parse(read(".github/workflows/.build-publication.yml"));
120
120
  if (!Object.values(publication.jobs).some((job) => job.steps?.some((step) => step.uses?.endsWith("/actions/publication/candidate/plan"))))
121
121
  fail("publication does not invoke its consumer policy node");
122
- const stageCanary = read(".github/workflows/public-build-stage-capsule-canary.yml");
122
+ const stageCanary = read(".github/workflows/.build-stage-capsule-canary.yml");
123
123
  if (
124
124
  !stageCanary.includes("consumer-admission:") ||
125
125
  !jobDependsOn(stageCanary, "qualify", "consumer-admission")
@@ -128,7 +128,7 @@ export function checkFloatingConsumerPolicyContract() {
128
128
  "Stage Capsule qualification is not transitively gated by consumer admission",
129
129
  );
130
130
  }
131
- const promotion = read(".github/workflows/public-release-promote.yml");
131
+ const promotion = read(".github/workflows/.release-candidate-promote.yml");
132
132
  if (
133
133
  !promotion.includes("consumer-admission:") ||
134
134
  !jobDependsOn(promotion, "invoke", "consumer-admission")
@@ -146,23 +146,23 @@ const requiredPaths = [
146
146
  ".buildchain/alpha-contract-lock.json",
147
147
  ".buildchain/release-impact.json",
148
148
  ".github/actionlint.yaml",
149
- ".github/workflows/public-ops-release-governance.yml",
150
- ".github/workflows/public-ops-dev-auto-merge.yml",
151
- ".github/workflows/public-ops-patrol.yml",
152
- ".github/workflows/public-ops-patrol-daily.yml",
153
- ".github/workflows/public-ops-patrol-weekly.yml",
154
- ".github/workflows/public-ops-patrol-monthly.yml",
155
- ".github/workflows/public-ops-observed-evidence.yml",
156
- ".github/workflows/public-release-promote.yml",
149
+ ".github/workflows/.ops-release-governance.yml",
150
+ ".github/workflows/.ops-dev-auto-merge.yml",
151
+ ".github/workflows/.ops-patrol.yml",
152
+ ".github/workflows/.ops-patrol-daily.yml",
153
+ ".github/workflows/.ops-patrol-weekly.yml",
154
+ ".github/workflows/.ops-patrol-monthly.yml",
155
+ ".github/workflows/.ops-observed-evidence.yml",
156
+ ".github/workflows/.release-candidate-promote.yml",
157
157
  ".github/workflows/.release-promote.yml",
158
- ".github/workflows/public-release-propagation.yml",
159
- ".github/workflows/public-release-paper.yml",
158
+ ".github/workflows/.release-propagation.yml",
159
+ ".github/workflows/.release-paper.yml",
160
160
  ".github/workflows/.release-binary-assets.yml",
161
161
  ".github/workflows/.build.yml",
162
162
  ".github/workflows/.build-gate-profile.yml",
163
163
  ".github/workflows/.build-demo-adapter.yml",
164
- ".github/workflows/public-build-demo.yml",
165
- ".github/workflows/build.yml",
164
+ ".github/workflows/.build-demo.yml",
165
+ ".github/workflows/.build-candidate.yml",
166
166
  "fixtures/libnode-shaped/buildchain.toml",
167
167
  "fixtures/libnode-shaped/.github/workflows/build.yml",
168
168
  "fixtures/libnode-shaped/package.json",
@@ -281,7 +281,7 @@ for (const requiredSnippet of [
281
281
  }
282
282
  }
283
283
  const channelBuildWorkflow = fs.readFileSync(
284
- path.join(root, ".github/workflows/build.yml"),
284
+ path.join(root, ".github/workflows/.build-candidate.yml"),
285
285
  "utf8",
286
286
  );
287
287
  const advancedPromotionWorkflow = fs.readFileSync(
@@ -289,7 +289,7 @@ const advancedPromotionWorkflow = fs.readFileSync(
289
289
  "utf8",
290
290
  );
291
291
  const channelPromotionWorkflow = fs.readFileSync(
292
- path.join(root, ".github/workflows/public-release-promote.yml"),
292
+ path.join(root, ".github/workflows/.release-candidate-promote.yml"),
293
293
  "utf8",
294
294
  );
295
295
  assertPromotionInventory(root);
@@ -306,7 +306,7 @@ const actionlintConfig = fs.readFileSync(
306
306
  "utf8",
307
307
  );
308
308
  for (const requiredSnippet of [
309
- ".github/workflows/build.yml:",
309
+ ".github/workflows/.build-candidate.yml:",
310
310
  ".github/workflows/.build.yml:",
311
311
  ".github/workflows/.build-gate-profile.yml:",
312
312
  'property "workflow_ref" is not defined in object type',
@@ -859,25 +859,25 @@ for (const requiredSnippet of [
859
859
  }
860
860
  const reusableBuildSurfaceDoc = fs.readFileSync(path.join(root, "docs/reusable-build-surface.md"), "utf8");
861
861
  for (const requiredSnippet of [
862
- "config-path",
863
- "buildchain.toml",
864
- ".buildchain/contract-lock.json",
865
- ".buildchain/alpha-contract-lock.json",
866
- "architecture/build-environments.json",
867
- "build.contract",
868
- "cache roots",
869
- "exact consumer source",
870
- "run-build-stage",
871
- "transfer-build-artifact",
862
+ ".buildchain/buildchain.toml",
863
+ "schema = 2",
864
+ "[[products]]",
865
+ "public-ops-pipeline.yml@v4",
866
+ "public-ops-recover.yml@v4",
867
+ "Without a lock",
868
+ "exact Git commit, tree and TOML blob",
869
+ "without provider credentials",
870
+ "original attempt",
871
+ "Consumers do not call",
872
872
  ]) {
873
873
  if (!reusableBuildSurfaceDoc.includes(requiredSnippet)) {
874
- throw new Error(`reusable build surface doc missing contract lock snippet: ${requiredSnippet}`);
874
+ throw new Error(`consumer build surface doc missing schema-2 contract snippet: ${requiredSnippet}`);
875
875
  }
876
876
  }
877
877
  for (const [docName, docSource] of Object.entries({ "docs/cli.md": cliDoc, "docs/install.md": installDoc })) {
878
878
  for (const requiredSnippet of [
879
879
  "minimumReleaseAgeExclude",
880
- "@kungfu-tech/buildchain@4.0.0",
880
+ "@kungfu-tech/buildchain@4.1.3",
881
881
  "package/version-specific",
882
882
  ]) {
883
883
  if (!docSource.includes(requiredSnippet)) {
@@ -1,7 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import fs from "node:fs";
4
- import { projectRenamedMetrics } from "./source-metric-lineage.mjs";
4
+ import {
5
+ projectRenamedMetrics,
6
+ projectWorkflowMetrics,
7
+ } from "./source-metric-lineage.mjs";
8
+ import {
9
+ workflowPath,
10
+ TAXONOMY_PATH,
11
+ } from "../packages/core/workflow/workflow-taxonomy.mjs";
5
12
  import path from "node:path";
6
13
  import { execFileSync } from "node:child_process";
7
14
  import { pathToFileURL } from "node:url";
@@ -417,10 +424,25 @@ function checkMaintainability({ root = process.cwd() } = {}) {
417
424
  if (file.endsWith(".rs")) baselineFiles[file] = metrics;
418
425
  }
419
426
  const baselineTests = testMetricsAtRevision(root, extendedCoverageRevision);
420
- const baselineWorkflows = workflowMetricsAtRevision(
421
- root,
422
- extendedCoverageRevision,
423
- );
427
+ const taxonomyCoordinates = (policy) =>
428
+ policy.entries.map((entry) => ({
429
+ id: entry.id,
430
+ path: workflowPath(entry),
431
+ }));
432
+ const workflowLineage = projectWorkflowMetrics({
433
+ before: taxonomyCoordinates(
434
+ JSON.parse(
435
+ gitOutput(root, [
436
+ "show",
437
+ `${extendedCoverageRevision}:${TAXONOMY_PATH}`,
438
+ ]),
439
+ ),
440
+ ),
441
+ after: taxonomyCoordinates(readJson(root, TAXONOMY_PATH)),
442
+ metrics: workflowMetricsAtRevision(root, extendedCoverageRevision),
443
+ currentPaths: new Set(Object.keys(current.workflows)),
444
+ });
445
+ const baselineWorkflows = workflowLineage.metrics;
424
446
  const issues = evaluateExceptionGovernance({ policy });
425
447
  issues.push(...evaluateExceptionBudget({ policy }));
426
448
  const hotspots = collectHotspots(root, current, 20, debt.hotspots || []);
@@ -469,6 +491,7 @@ function checkMaintainability({ root = process.cwd() } = {}) {
469
491
  trackedFiles: current.repository.trackedFiles,
470
492
  sourceFiles: current.repository.handMaintainedSourceFiles,
471
493
  measurementRenames: lineage.renames,
494
+ workflowMeasurementRenames: workflowLineage.renames,
472
495
  publicSurface: current.publicSurface,
473
496
  hotspots: current.hotspots,
474
497
  governedDebtSurfaces: Object.values(debt.surfaces).reduce(
@@ -11,7 +11,7 @@ const DEFAULT_ROOT = path.resolve(
11
11
  "..",
12
12
  );
13
13
  const CALLER_PATH = ".github/workflows/self-build-public-consumer-dogfood.yml";
14
- const REUSABLE_PATH = ".github/workflows/public-build-stage-capsule-canary.yml";
14
+ const REUSABLE_PATH = ".github/workflows/.build-stage-capsule-canary.yml";
15
15
  export const PUBLIC_DOGFOOD_ENTRY_REF = "v4";
16
16
  const PRIVATE_CONSUMER = ["buildchain", "self", "dogfood"].join("-");
17
17
  const PRIVATE_SHADOW = ["kungfu", "shadow"].join("-");
@@ -201,7 +201,7 @@ function assertWorkflowInventory(root) {
201
201
  fail(`${relative} invokes the private qualification script directly`);
202
202
  if (
203
203
  relative !== CALLER_PATH &&
204
- text.includes(".github/workflows/public-build-stage-capsule-canary.yml@")
204
+ text.includes(".github/workflows/.build-stage-capsule-canary.yml@")
205
205
  )
206
206
  fail(`${relative} creates a second v4 dogfood caller`);
207
207
  if (relative !== REUSABLE_PATH && relative !== CALLER_PATH)
@@ -275,7 +275,7 @@ function assertArchitecture(root) {
275
275
  !dogfood ||
276
276
  dogfood.callerWorkflow !== CALLER_PATH ||
277
277
  dogfood.reusableWorkflow !==
278
- "kungfu-systems/buildchain/.github/workflows/public-build-stage-capsule-canary.yml" ||
278
+ "kungfu-systems/buildchain/.github/workflows/.build-stage-capsule-canary.yml" ||
279
279
  dogfood.runtimeBinding !== "entry-selected-runtime" ||
280
280
  dogfood.consumerSourceBinding !== "github.sha" ||
281
281
  JSON.stringify(dogfood.executableStages) !==
@@ -532,7 +532,7 @@ export function checkReleaseTopology() {
532
532
  assertPipelinePublicationTopology(ledger, discoverReleaseTopology, root);
533
533
  const preview = ledger.postPublicationScope;
534
534
  assert.deepEqual(preview.workflowPaths, [
535
- ".github/workflows/public-release-oci-compose-preview.yml",
535
+ ".github/workflows/.release-oci-compose-preview.yml",
536
536
  ]);
537
537
  const previewTopology = discoverReleaseTopology(
538
538
  preview.workflowPaths,
@@ -2,12 +2,11 @@ import fs from "node:fs";
2
2
  import path from "node:path";
3
3
  import { fileURLToPath } from "node:url";
4
4
  import { parse as yaml } from "yaml";
5
- import { compileConsumerPlan } from "../packages/core/consumer/contract/plan.js";
5
+ import * as consumerPlan from "../packages/core/consumer/contract/plan.js";
6
6
  import { consumerWorkflows } from "../packages/core/consumer/contract/entries.js";
7
7
  import { workflowPath } from "../packages/core/workflow/workflow-taxonomy.mjs";
8
8
 
9
- export const SELF_ENTRY_CHANNEL = "v4-alpha";
10
- export const SELF_CONFIG_PATH = ".buildchain/minimal-consumer.toml";
9
+ export const SELF_ENTRY_CHANNEL = "v4";
11
10
  const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
12
11
  const PLATFORMS = ["linux-x64", "macos-arm64", "windows-x64"];
13
12
 
@@ -19,10 +18,11 @@ export function checkSelfConsumerContract(root = ROOT) {
19
18
  const fail = (message) => {
20
19
  throw new Error(`self-consumer-contract: ${message}`);
21
20
  };
22
- const plan = compileConsumerPlan(read(SELF_CONFIG_PATH));
23
- if (read(SELF_CONFIG_PATH) !== read(".buildchain/buildchain.toml"))
24
- fail("transition config must match the canonical product plan");
25
- const callers = consumerWorkflows(SELF_ENTRY_CHANNEL, SELF_CONFIG_PATH);
21
+ const plan = consumerPlan.compileConsumerPlan(read(consumerPlan.CONFIG_PATH));
22
+ const retired = path.join(root, ".buildchain/minimal-consumer.toml");
23
+ if (fs.lstatSync(retired, { throwIfNoEntry: false }))
24
+ fail("retired transition config must not remain in the self consumer tree");
25
+ const callers = consumerWorkflows();
26
26
  for (const [file, bytes] of Object.entries(callers))
27
27
  if (read(file) !== bytes) fail(`${file}: generated caller drift`);
28
28
  const taxonomy = JSON.parse(read("architecture/workflow-taxonomy.json"));
@@ -41,7 +41,7 @@ assert.equal(executor.with["mutation-token"], "${{ inputs.secrets-buildchain-pro
41
41
  assert.equal(executor.with.token, "${{ github.token }}");
42
42
  assert.doesNotMatch(read(contract.bootstrap.publicWorkflow), /admission-policy-json:/u);
43
43
  const template = parse(contract.bootstrap.consumerTemplate);
44
- assert.equal(template.jobs.bootstrap.uses, "kungfu-systems/buildchain/.github/workflows/public-ops-bootstrap.yml@v4");
44
+ assert.equal(template.jobs.bootstrap.uses, "kungfu-systems/buildchain/.github/workflows/.ops-bootstrap.yml@v4");
45
45
  assert.equal(template.jobs.bootstrap.with["runtime-ref"], "${{ inputs.runtime-ref }}");
46
46
  assert.equal(contract.bootstrap.selfDogfoodActive, false);
47
47
  assert.equal(fs.existsSync(path.join(root, contract.bootstrap.selfDogfoodWorkflow)), false,
@@ -41,4 +41,4 @@ export function generateChannelPromotionWorkflow(source) {
41
41
  }, { lineWidth: 0, aliasDuplicateObjects: false });
42
42
  }
43
43
  if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url))
44
- writeWorkflowSource(root, ".github/workflows/public-release-promote.yml", generateChannelPromotionWorkflow(fs.readFileSync(path.join(root, ".github/workflows/.release-promote.yml"), "utf8")));
44
+ writeWorkflowSource(root, ".github/workflows/.release-candidate-promote.yml", generateChannelPromotionWorkflow(fs.readFileSync(path.join(root, ".github/workflows/.release-promote.yml"), "utf8")));
@@ -5,6 +5,7 @@ import { parse as yaml } from "yaml";
5
5
  import { format } from "prettier";
6
6
  import { standardConsumerExample } from "../packages/core/consumer/contract/examples.js";
7
7
  import { inspectConsumerContract } from "../packages/core/consumer/contract/inspection.js";
8
+ import { validateConsumerWiring } from "../packages/core/consumer/contract/local-validation.js";
8
9
  import { workflowPath } from "../packages/core/workflow/workflow-taxonomy.mjs";
9
10
 
10
11
  const root = process.cwd(),
@@ -13,6 +14,25 @@ const tracked = execFileSync("git", ["ls-files", "-z"], { encoding: "utf8" })
13
14
  .split("\0")
14
15
  .filter(Boolean);
15
16
 
17
+ if (check) {
18
+ const files = Object.create(null);
19
+ for (const file of tracked)
20
+ Object.defineProperty(files, file, {
21
+ enumerable: true,
22
+ get: () => fs.readFileSync(path.join(root, file), "utf8"),
23
+ });
24
+ const { channel } = validateConsumerWiring(root);
25
+ const inspection = inspectConsumerContract(files, { channel });
26
+ if (inspection.controlIssues.length)
27
+ throw new Error(inspection.controlIssues.join("\n"));
28
+ const unresolved = inspection.commandClosures.filter(
29
+ (closure) => !closure.commandEdgesResolved,
30
+ ).length;
31
+ console.log(
32
+ `Self control wiring verified; ${unresolved} product graphs remain unresolved and require read-only runtime execution.`,
33
+ );
34
+ }
35
+
16
36
  function output(file, value) {
17
37
  const target = path.join(root, file);
18
38
  if (check) {
@@ -143,7 +163,7 @@ output(
143
163
  await format(
144
164
  JSON.stringify({
145
165
  schema: "buildchain.consumer-migration/v1",
146
- stage: "self-cutover-in-progress; final-release-qualification-pending",
166
+ stage: "self-default-entry; final-release-qualification-pending",
147
167
  workflows: workflowInventory(),
148
168
  consumerSources: consumerSourceInventory(),
149
169
  }),
@@ -887,8 +887,9 @@ function buildSiteBundle() {
887
887
  ["self-hosted-runner-smoke", "compatibility-fixture"],
888
888
  ]);
889
889
  const engineeringHousekeeper = semanticId.startsWith("engineering-housekeeper");
890
+ if (classification?.role === "component") statusById.set(semanticId, "repository-internal");
890
891
  return {
891
- ...entry,
892
+ ...entry, apiRole: classification?.role === "public" ? "public" : "implementation",
892
893
  ...(classification ? { taxonomy: { id: classification.id, role: classification.role, category: classification.category, purpose: classification.purpose, status: classification.status, canonicalPath: workflowPath(classification), ...(classification.role === "self" && classification.migration ? { contractPath: classification.migration.previousPath } : {}), compatibilityAlias: entry.path !== workflowPath(classification) } } : {}),
893
894
  surface: surfaceById.get(semanticId) || (entry.path.includes("/.") ? "reusable-workflow" : "repository-workflow"),
894
895
  capabilityGroup: workflowCapabilityGroup({
@@ -19,8 +19,8 @@ export function tailResealFixturePolicyReceipt(fixture, policy) {
19
19
  try {
20
20
  fs.mkdirSync(path.join(root, ".github/workflows"), { recursive: true });
21
21
  fs.writeFileSync(
22
- path.join(root, ".github/workflows/build.yml"),
23
- "jobs:\n build:\n uses: kungfu-systems/buildchain/.github/workflows/public-build-stage-capsule-canary.yml@v4-alpha\n",
22
+ path.join(root, ".github/workflows/.build-candidate.yml"),
23
+ "jobs:\n build:\n uses: kungfu-systems/buildchain/.github/workflows/.build-stage-capsule-canary.yml@v4-alpha\n",
24
24
  );
25
25
  fs.mkdirSync(path.join(root, ".buildchain"), { recursive: true });
26
26
  for (const [file, ref, resolvedSha] of [
@@ -51,7 +51,7 @@ export function tailResealFixturePolicyReceipt(fixture, policy) {
51
51
  root,
52
52
  repository: fixture.repository,
53
53
  sourceSha: fixture.source.sha,
54
- invokedWorkflow: "public-build-stage-capsule-canary.yml",
54
+ invokedWorkflow: ".build-stage-capsule-canary.yml",
55
55
  expectedInvocationChannel: "alpha",
56
56
  resolvedRuntimeSha: fixture.runtime.sha,
57
57
  policy,
@@ -8,7 +8,7 @@ import { generateChannelPromotionWorkflow } from "../generate-channel-promotion-
8
8
 
9
9
  export function assertPromotionInventory(root) {
10
10
  const read = (file) => fs.readFileSync(path.join(root, file), "utf8");
11
- const publicPath = ".github/workflows/public-release-promote.yml";
11
+ const publicPath = ".github/workflows/.release-candidate-promote.yml";
12
12
  const api = YAML.parse(read(publicPath));
13
13
  assert.equal(
14
14
  read(publicPath),
@@ -164,7 +164,7 @@ export function validateSelfDogfoodRoute(route) {
164
164
  targetRepository !== "kungfu-systems/buildchain" ||
165
165
  route.runtimeRef !== "v4-alpha" ||
166
166
  route.publicWorkflow !==
167
- `${targetRepository}/.github/workflows/build.yml@v4-alpha` ||
167
+ `${targetRepository}/.github/workflows/.build-candidate.yml@v4-alpha` ||
168
168
  route.protectedDevBranch !== PROTECTED_DEV_BRANCH ||
169
169
  JSON.stringify(route.hostedReadbackPaths) !==
170
170
  JSON.stringify(HOSTED_READBACK_PATHS)
@@ -66,7 +66,7 @@ export function validateSelfDogfoodCheckpoint(checkpoint) {
66
66
  if (
67
67
  checkpoint.route.runtimeRef !== "v4-alpha" ||
68
68
  checkpoint.route.publicWorkflow !==
69
- `${targetRepository}/.github/workflows/build.yml@v4-alpha` ||
69
+ `${targetRepository}/.github/workflows/.build-candidate.yml@v4-alpha` ||
70
70
  targetRepository !== "kungfu-systems/buildchain"
71
71
  ) {
72
72
  throw new Error("checkpoint requires the public owner/repo v4-alpha route");
@@ -122,7 +122,7 @@ export async function createSelfDogfoodCheckpoint({
122
122
  const routeRepository = repository(targetRepository);
123
123
  const route = {
124
124
  repository: routeRepository,
125
- publicWorkflow: `${routeRepository}/.github/workflows/build.yml@v4-alpha`,
125
+ publicWorkflow: `${routeRepository}/.github/workflows/.build-candidate.yml@v4-alpha`,
126
126
  runtimeRef: required(runtimeRef, "runtimeRef"),
127
127
  runtimeSha: exactSha(runtimeSha, "runtimeSha"),
128
128
  contractRoot: exactRoot(contractRoot, "contractRoot"),
@@ -239,7 +239,7 @@ export function validateSelfDogfoodEvidence(evidence) {
239
239
  validateAdapterEvidence(evidence.adapter, semver, anchored);
240
240
  if (
241
241
  evidence.adoption?.coordinate !==
242
- "kungfu-systems/buildchain/.github/workflows/build.yml@v4" ||
242
+ "kungfu-systems/buildchain/.github/workflows/.build-candidate.yml@v4" ||
243
243
  evidence.adoption?.exactShaProductionPin !== false
244
244
  ) {
245
245
  throw new Error("Kungfu adoption must use the floating v4 coordinate");
@@ -367,7 +367,7 @@ export async function resumeSelfDogfoodCheckpoint(
367
367
  },
368
368
  },
369
369
  adoption: {
370
- coordinate: "kungfu-systems/buildchain/.github/workflows/build.yml@v4",
370
+ coordinate: "kungfu-systems/buildchain/.github/workflows/.build-candidate.yml@v4",
371
371
  runtimeRef: "v4",
372
372
  exactShaProductionPin: false,
373
373
  },
@@ -134,14 +134,10 @@ export function cliCommandMeta(id) {
134
134
  "npm-dry-run": { group: "release-passport-trust", purpose: "Verify npm publish shape before a release transaction." },
135
135
  paper: { group: "reusable-build", purpose: "Inspect the unified paper repository and publication command families." },
136
136
  "paper-agent": { group: "getting-started", purpose: "Verify the mandatory managed Paper agent entry contract on an existing work branch." },
137
- "paper-alpha": { group: "release-passport-trust", purpose: "Plan or open the protected dev-to-alpha paper publication PR without direct publication." },
138
- "paper-bootstrap-npm": { group: "release-passport-trust", purpose: "Dry-run or explicitly bootstrap the public npm package and bind GitHub Trusted Publishing." },
139
- "paper-build": { group: "reusable-build", purpose: "Plan or execute the existing two-clean-build reproducibility gate for a paper." },
140
- "paper-fleet-audit": { group: "governance-versioning", purpose: "Discover Paper repositories and emit one deterministic v3 dependency, control-surface, and governance audit." },
137
+ "paper-fleet-audit": { group: "governance-versioning", purpose: "Discover Paper repositories and audit current consumer configuration, dependencies, and governance." },
141
138
  "paper-fleet-update": { group: "governance-versioning", purpose: "Plan or write a bounded v3 migration across isolated Paper work branches." },
142
139
  "paper-migrate": { group: "getting-started", purpose: "Plan or write the bounded Buildchain-owned control-file migration for an existing paper repository." },
143
- "paper-preflight": { group: "reusable-build", purpose: "Report exact source, runtime, permission, npm trust, deterministic build, and release-state readiness." },
144
- "paper-resume": { group: "release-passport-trust", purpose: "Plan or dispatch recovery of the exact existing sealed paper release transaction." },
140
+ "paper-preflight": { group: "reusable-build", purpose: "Validate the schema-2 consumer configuration and inspect retained legacy evidence without inferring hosted publication." },
145
141
  "paper-scaffold": { group: "getting-started", purpose: "Plan or write an idempotent, no-overwrite, release-ready paper repository scaffold." },
146
142
  "paper-status": { group: "reusable-build", purpose: "Report explicit evidence for every paper lifecycle state without unsupported inference." },
147
143
  "paper-work-start": { group: "getting-started", purpose: "Create a safe Paper work branch from the exact canonical remote development SHA." },
@@ -1,17 +1,72 @@
1
- import { execFileSync } from 'node:child_process';
1
+ import { execFileSync } from "node:child_process";
2
2
 
3
3
  // Measurement identity follows Git's observed renames. This does not resolve a
4
4
  // runtime path or keep a removed entrypoint callable.
5
- export function projectRenamedMetrics({ root, revision, metrics, currentPaths }) {
6
- const records = execFileSync('git', ['diff', '--name-status', '-z', '--find-renames=50%', '--diff-filter=R', revision],
7
- { cwd: root, encoding: 'utf8', maxBuffer: 16 * 1024 * 1024 }).split('\0');
8
- const projected = { ...metrics }, renames = [];
5
+ export function projectRenamedMetrics({
6
+ root,
7
+ revision,
8
+ metrics,
9
+ currentPaths,
10
+ }) {
11
+ const records = execFileSync(
12
+ "git",
13
+ [
14
+ "diff",
15
+ "--name-status",
16
+ "-z",
17
+ "--find-renames=50%",
18
+ "--diff-filter=R",
19
+ revision,
20
+ ],
21
+ { cwd: root, encoding: "utf8", maxBuffer: 16 * 1024 * 1024 },
22
+ ).split("\0");
23
+ const projected = { ...metrics },
24
+ renames = [];
9
25
  for (let index = 0; index < records.length && records[index]; index += 3) {
10
26
  const [status, source, target] = records.slice(index, index + 3);
11
- if (!/^R\d+$/.test(status) || !source || !target) throw Error('Invalid Git metric lineage');
12
- if (!metrics[source] || metrics[target] || !currentPaths.has(target)) continue;
27
+ if (!/^R\d+$/.test(status) || !source || !target)
28
+ throw Error("Invalid Git metric lineage");
29
+ if (!metrics[source] || metrics[target] || !currentPaths.has(target))
30
+ continue;
13
31
  projected[target] = { ...metrics[source], file: target };
14
32
  renames.push({ source, target, similarity: Number(status.slice(1)) });
15
33
  }
16
34
  return { metrics: projected, renames };
17
35
  }
36
+
37
+ // Workflow taxonomy IDs survive role/path changes and are available at both
38
+ // exact cuts even in a shallow checkout. Preserve their original measured budget.
39
+ export function projectWorkflowMetrics({
40
+ metrics,
41
+ before,
42
+ after,
43
+ currentPaths,
44
+ }) {
45
+ for (const entries of [before, after])
46
+ for (const key of ["id", "path"])
47
+ if (
48
+ new Set(entries.map((entry) => entry[key])).size !== entries.length ||
49
+ entries.some((entry) => typeof entry[key] !== "string" || !entry[key])
50
+ )
51
+ throw Error(
52
+ "Workflow measurement identities must be unique and explicit",
53
+ );
54
+ const originals = new Map(before.map((entry) => [entry.id, entry.path]));
55
+ const projected = { ...metrics },
56
+ renames = [];
57
+ for (const { id, path: target } of after) {
58
+ const source = originals.get(id);
59
+ if (
60
+ !source ||
61
+ source === target ||
62
+ !metrics[source] ||
63
+ metrics[target] ||
64
+ !currentPaths.has(target) ||
65
+ currentPaths.has(source)
66
+ )
67
+ continue;
68
+ projected[target] = { ...metrics[source], file: target };
69
+ renames.push({ id, source, target });
70
+ }
71
+ return { metrics: projected, renames };
72
+ }
@@ -56,7 +56,12 @@ export function verifyGoldenPath() {
56
56
  name: "buildchain-golden-path-consumer",
57
57
  version: "0.1.0",
58
58
  private: true,
59
- scripts: { build: 'node -e ""', check: 'node -e ""' },
59
+ scripts: {
60
+ build:
61
+ "node -e \"require('fs').mkdirSync('dist',{recursive:true});require('fs').writeFileSync('dist/index.js','export const value = 1;')\"",
62
+ check:
63
+ "node -e \"require('assert').ok(require('fs').statSync('dist/index.js').size > 0)\"",
64
+ },
60
65
  },
61
66
  null,
62
67
  2,
@@ -88,34 +93,19 @@ export function verifyGoldenPath() {
88
93
  { cwd: consumer, json: true },
89
94
  );
90
95
  const workflow = fs.readFileSync(
91
- path.join(consumer, ".github", "workflows", "build.yml"),
96
+ path.join(consumer, ".github", "workflows", "buildchain.yml"),
92
97
  "utf8",
93
98
  );
94
- const releaseDryRun = run(
95
- buildchain,
96
- ["release", "--dry-run", "--target-ref", "alpha/v4/v4.0", "--json"],
97
- { cwd: consumer, json: true },
98
- );
99
- const passportPath = path.join(
100
- consumer,
101
- ".buildchain",
102
- "golden-path",
103
- "buildchain.release.json",
104
- );
105
- fs.mkdirSync(path.dirname(passportPath), { recursive: true });
106
- run(
107
- process.execPath,
108
- [
109
- "--input-type=module",
110
- "--eval",
111
- `import fs from "node:fs"; import { createReleasePassport } from "@kungfu-tech/buildchain"; const value=createReleasePassport({repository:"example/consumer",tag:"v0.1.0-alpha.0",sourceSha:"a".repeat(40),assets:[{name:"consumer.tgz",sha256:"b".repeat(64)}]}); fs.writeFileSync(${JSON.stringify(passportPath)}, JSON.stringify(value,null,2)+"\\n");`,
112
- ],
113
- { cwd: consumer },
114
- );
115
- const inspection = run(
116
- buildchain,
117
- ["inspect", "release", "--passport", passportPath, "--json"],
118
- { cwd: consumer, json: true },
99
+ run("git", ["init", "-q"], { cwd: consumer });
100
+ const doctor = run(buildchain, ["doctor", "--json"], {
101
+ cwd: consumer,
102
+ json: true,
103
+ });
104
+ run("npm", ["run", "build"], { cwd: consumer });
105
+ run("npm", ["run", "check"], { cwd: consumer });
106
+ const recovery = fs.readFileSync(
107
+ path.join(consumer, ".github/workflows/buildchain-recover.yml"),
108
+ "utf8",
119
109
  );
120
110
 
121
111
  assert(
@@ -133,7 +123,7 @@ export function verifyGoldenPath() {
133
123
  "Golden Path validation did not retain the required lifecycle stages",
134
124
  );
135
125
  assert(
136
- /uses:\s+kungfu-systems\/buildchain\/\.github\/workflows\/build\.yml@v4/.test(
126
+ /uses:\s+kungfu-systems\/buildchain\/\.github\/workflows\/public-ops-pipeline\.yml@v4/.test(
137
127
  workflow,
138
128
  ),
139
129
  "Golden Path workflow is not a thin v4 reusable-workflow caller",
@@ -142,13 +132,18 @@ export function verifyGoldenPath() {
142
132
  !/\n\s+(?:inputs|with|steps):/.test(workflow),
143
133
  "Golden Path ordinary caller must have zero inputs and delegate its steps",
144
134
  );
135
+ assert(doctor.ok, "Golden Path doctor rejected the initialized consumer");
136
+ assert(
137
+ validation.config.schema === 2 && validation.products[0].type === "npm",
138
+ "Golden Path did not validate the schema-2 product",
139
+ );
145
140
  assert(
146
- releaseDryRun && typeof releaseDryRun === "object",
147
- "Golden Path release dry-run did not return JSON",
141
+ /public-ops-recover\.yml@v4/.test(recovery),
142
+ "Golden Path recovery entry is not the shared caller",
148
143
  );
149
144
  assert(
150
- inspection && typeof inspection === "object",
151
- "Golden Path Release Passport inspection did not return JSON",
145
+ Object.keys(validation.consumer || {}).length > 0,
146
+ "Golden Path validation did not inspect caller wiring",
152
147
  );
153
148
  return {
154
149
  contract: "kungfu-buildchain-golden-path-verification/v1",
@@ -156,9 +151,10 @@ export function verifyGoldenPath() {
156
151
  version,
157
152
  projectType: initialized.type,
158
153
  validationPath: validation.config?.path,
159
- reusableWorkflow: ".github/workflows/build.yml",
160
- releaseDryRun: true,
161
- releasePassportInspection: true,
154
+ reusableWorkflows: validation.consumer.workflows,
155
+ productBuildAndVerification: true,
156
+ doctor: doctor.ok,
157
+ providerEffects: false,
162
158
  };
163
159
  } finally {
164
160
  fs.rmSync(temporary, { recursive: true, force: true });
@@ -93,7 +93,7 @@ permissions:
93
93
  statuses: write
94
94
  jobs:
95
95
  deliver:
96
- uses: kungfu-systems/buildchain/.github/workflows/public-ops-dev-auto-merge.yml@v4-alpha
96
+ uses: kungfu-systems/buildchain/.github/workflows/.ops-dev-auto-merge.yml@v4-alpha
97
97
  with:
98
98
  runtime-ref: ${{ inputs.runtime-ref || '' }}
99
99
  target-branch: ${{ github.event.client_payload.candidate.targetBranch || inputs.target-branch }}
@@ -30,7 +30,7 @@ permissions:
30
30
 
31
31
  jobs:
32
32
  bootstrap:
33
- uses: kungfu-systems/buildchain/.github/workflows/public-ops-bootstrap.yml@v4
33
+ uses: kungfu-systems/buildchain/.github/workflows/.ops-bootstrap.yml@v4
34
34
  with:
35
35
  request-json: ${{ inputs.request-json }}
36
36
  runtime-ref: ${{ inputs.runtime-ref }}