@kungfu-tech/buildchain 4.0.2-alpha.8 → 4.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (157) hide show
  1. package/AGENTS.md +10 -1
  2. package/CONTRIBUTING.md +24 -0
  3. package/README.md +2 -2
  4. package/actions/promote-buildchain-ref/README.md +1 -1
  5. package/actions/v4-release-candidate-promote/README.md +28 -0
  6. package/architecture/agent-change-map.md +64 -7
  7. package/architecture/ci-lane-change-budget.json +366 -0
  8. package/architecture/internal-capabilities.json +53 -8
  9. package/architecture/maintainability-debt.json +147 -93
  10. package/architecture/maintainability-policy.json +32 -28
  11. package/architecture/release-tail-contract-inventory.json +6 -6
  12. package/architecture/v4-architecture-constitution.md +23 -20
  13. package/architecture/v4-cross-platform-adopter-qualification.json +1 -1
  14. package/architecture/v4-delivery-authority-parity.json +2 -2
  15. package/architecture/v4-delivery-warrant-shadow-bootstrap-plan.json +1 -1
  16. package/architecture/v4-floating-consumer-policy.json +2 -2
  17. package/architecture/v4-next-development-parity.json +5 -5
  18. package/architecture/v4-partial-mutation-recovery-qualification.json +4 -1
  19. package/architecture/v4-platform-stage-checkpoints.json +1 -1
  20. package/architecture/v4-provider-operation-journal-contract.json +5 -2
  21. package/architecture/v4-publication-facade-patches.json +64 -0
  22. package/architecture/v4-release-activation-shadow-domain.json +5 -2
  23. package/architecture/v4-release-topology.json +74 -39
  24. package/architecture/v4-rust-wasm-production-authority.json +58 -0
  25. package/architecture/v4-stable-publication-fence.json +5 -2
  26. package/architecture/v4-stage-capsule-qualification.json +2 -2
  27. package/architecture/v4-tail-reseal-parity.json +8 -6
  28. package/architecture/v4-universal-workflow-bootstrap.json +171 -0
  29. package/architecture/v4-universal-workflow-fault-campaign.json +72 -0
  30. package/architecture/v4-universal-workflow-train-admission.json +40 -0
  31. package/architecture/workflow-taxonomy.json +1451 -0
  32. package/bin/buildchain.mjs +7 -7
  33. package/contracts/buildchain-v2-residuals-v1.json +57 -48
  34. package/contracts/dev-delivery-authority-v2.schema.json +16 -2
  35. package/contracts/fixtures/v4-tail-reseal-v1/valid.json +1 -1
  36. package/contracts/v4-canonical-contracts-v1.schema.json +1 -0
  37. package/dist/site/buildchain-contract.json +93 -48
  38. package/dist/site/buildchain-site.json +222 -69
  39. package/dist/site/capability-registry.json +4 -4
  40. package/dist/site/controller-registry.json +50 -13
  41. package/dist/site/kfd-claims.json +2585 -1000
  42. package/dist/site/kfd-upstream-aggregate.json +1 -1
  43. package/dist/site/manual-registry.json +13 -13
  44. package/dist/site/node-api-registry.json +120 -115
  45. package/dist/site/page-registry.json +204 -51
  46. package/dist/site/public-surface-audit.json +3205 -1219
  47. package/dist/site/publication-authority-registry.json +1124 -362
  48. package/dist/site/publication-registry.json +4 -4
  49. package/dist/site/schemas/dev-delivery-authority-v2.schema.json +16 -2
  50. package/dist/site/site-manifest.json +17 -17
  51. package/dist/site/workflow-registry.json +5061 -1659
  52. package/docs/MAP.md +1 -0
  53. package/docs/auditable-demo.md +1 -1
  54. package/docs/cli.md +21 -8
  55. package/docs/dev-delivery-warrant.md +1 -1
  56. package/docs/engineering-housekeeper.md +3 -3
  57. package/docs/kfd-support.md +26 -2
  58. package/docs/next-development-transition.md +2 -2
  59. package/docs/node-api-reference.md +190 -190
  60. package/docs/publication-authority.md +2 -2
  61. package/docs/release-candidate.md +3 -3
  62. package/docs/release-flow.md +67 -19
  63. package/docs/release-governance.md +8 -8
  64. package/docs/release-passport.md +27 -2
  65. package/docs/reusable-build-surface.md +16 -0
  66. package/docs/v4-adopter-delivery.md +2 -2
  67. package/docs/v4-production-release.md +71 -8
  68. package/docs/v4-rust-wasm-production-authority.md +58 -0
  69. package/docs/v4-stage-capsule.md +2 -2
  70. package/docs/v4-tail-reseal.md +1 -1
  71. package/docs/workflow-catalog.md +154 -0
  72. package/docs/workflow-path-migration.md +109 -0
  73. package/package.json +10 -6
  74. package/packages/core/artifact-verification-envelope.js +5 -5
  75. package/packages/core/buildchain-contract.js +1 -1
  76. package/packages/core/buildchain-kfd-claims.js +2 -2
  77. package/packages/core/buildchain-publication-authority.js +42 -26
  78. package/packages/core/buildchain-v4-domain.wasm +0 -0
  79. package/packages/core/ci-lane-change-budget.js +14 -1
  80. package/packages/core/controller-evidence.js +4 -1
  81. package/packages/core/dev-delivery-candidate-identity.js +40 -6
  82. package/packages/core/dev-delivery-warrant-state.js +3 -4
  83. package/packages/core/dev-delivery-warrant.js +12 -2
  84. package/packages/core/github-governance-authority.js +4 -4
  85. package/packages/core/kfd-adopter-manifest.js +46 -47
  86. package/packages/core/next-development-projection.js +2 -2
  87. package/packages/core/paper-agent-entry.js +30 -4
  88. package/packages/core/paper-fleet.js +1 -1
  89. package/packages/core/paper-runtime-channels.js +348 -0
  90. package/packages/core/paper-scaffold-content.js +10 -0
  91. package/packages/core/paper.js +37 -71
  92. package/packages/core/release-line-dry-run.js +1 -1
  93. package/packages/core/release-passport-contract.js +5 -5
  94. package/packages/core/release-passport.js +5 -4
  95. package/packages/core/release-tail-provider-plane.js +68 -1048
  96. package/packages/core/v4-canonical-contracts.js +10 -75
  97. package/packages/core/v4-domain-wasm-artifact.js +7 -0
  98. package/packages/core/v4-domain-wasm.js +216 -0
  99. package/packages/core/v4-floating-consumer-evidence.js +1 -1
  100. package/packages/core/v4-floating-consumer-policy.js +1 -1
  101. package/packages/core/v4-partial-mutation-recovery-qualification.js +9 -386
  102. package/packages/core/v4-product-publication.js +19 -349
  103. package/packages/core/v4-protected-publication-source.js +19 -21
  104. package/packages/core/v4-provider-operation-journal.js +18 -487
  105. package/packages/core/v4-provider-readback-idempotency.js +12 -97
  106. package/packages/core/v4-release-activation-shadow.js +13 -500
  107. package/packages/core/v4-release-invocation.js +28 -389
  108. package/packages/core/v4-stable-publication-fence.js +13 -342
  109. package/packages/core/v4-universal-workflow-bootstrap.js +586 -0
  110. package/scripts/binary-publication-evidence.mjs +135 -0
  111. package/scripts/build-contract-core.mjs +1 -14
  112. package/scripts/build-v4-domain-wasm.mjs +189 -0
  113. package/scripts/check-action-bundles.mjs +12 -2
  114. package/scripts/check-ci-lane-change-budget.mjs +4 -1
  115. package/scripts/check-core-mechanism-inventory.mjs +4 -3
  116. package/scripts/check-inventory.mjs +35 -44
  117. package/scripts/check-maintainability.mjs +16 -113
  118. package/scripts/check-v4-floating-consumer-policy-contract.mjs +2 -2
  119. package/scripts/check-v4-public-dogfood-contract.mjs +22 -9
  120. package/scripts/check-v4-release-topology.mjs +90 -33
  121. package/scripts/check-v4-runtime-semantic-closure.mjs +4 -1
  122. package/scripts/check-v4-universal-workflow-bootstrap.mjs +266 -0
  123. package/scripts/check-workflow-taxonomy.mjs +6 -0
  124. package/scripts/copy-v4-domain-wasm.mjs +14 -0
  125. package/scripts/dev-delivery-authority-command-adapters.mjs +1 -1
  126. package/scripts/dev-delivery-authority.mjs +8 -8
  127. package/scripts/dev-delivery-source-proof-reuse.mjs +2 -1
  128. package/scripts/dev-delivery-warrant-options.mjs +14 -9
  129. package/scripts/dev-delivery-warrant-store.mjs +73 -7
  130. package/scripts/dev-delivery-warrant-transition.mjs +109 -0
  131. package/scripts/dev-delivery-warrant.mjs +76 -99
  132. package/scripts/dev-pr-auto-merge.mjs +15 -15
  133. package/scripts/generate-channel-build-workflow.mjs +7 -2
  134. package/scripts/generate-channel-promotion-workflow.mjs +7 -5
  135. package/scripts/generate-site-bundle.mjs +11 -11
  136. package/scripts/generate-v4-universal-workflow-facades.mjs +458 -0
  137. package/scripts/generate-workflow-taxonomy.mjs +25 -0
  138. package/scripts/github-output.mjs +31 -0
  139. package/scripts/maintainability-metrics.mjs +16 -5
  140. package/scripts/maintainability-public-surface.mjs +115 -0
  141. package/scripts/next-development-review.mjs +307 -0
  142. package/scripts/paper-work-fleet-cli.mjs +2 -0
  143. package/scripts/release-asset-client.mjs +91 -0
  144. package/scripts/release-candidate-resolver.mjs +9 -9
  145. package/scripts/source-verification-evidence.mjs +344 -0
  146. package/scripts/stable-candidate-qualification.mjs +1 -1
  147. package/scripts/universal-facade-maintainability.mjs +82 -0
  148. package/scripts/v4-product-publication-intent.mjs +13 -6
  149. package/scripts/v4-publication-settlement.mjs +211 -0
  150. package/scripts/v4-universal-workflow-backflow.mjs +212 -0
  151. package/scripts/v4-universal-workflow-engine.mjs +618 -0
  152. package/scripts/v4-universal-workflow-self-dogfood.mjs +205 -0
  153. package/scripts/verify-version-state-delta.mjs +173 -0
  154. package/scripts/workflow-taxonomy.mjs +507 -0
  155. package/templates/native-dev-delivery.yml +4 -7
  156. package/templates/universal-buildchain-bootstrap-recovery.yml +282 -0
  157. package/templates/universal-buildchain-bootstrap.yml +28 -0
@@ -10,16 +10,17 @@ import {
10
10
  heartbeatDevDeliveryWarrant,
11
11
  observeDevDeliveryQueue,
12
12
  qualifyDevDeliveryWarrant,
13
- recoverExpiredDevDeliveryWarrant,
14
13
  reconcileDevDeliveryTerminalEvidence,
15
14
  selectDevDeliveryWarrant,
16
15
  settleDevDeliveryTerminalEvent,
17
16
  submitDevDeliveryCandidate,
18
17
  } from "../packages/core/dev-delivery-warrant.js";
19
18
  import { recoverLegacyTerminalDevDeliveryQueue } from "../packages/core/dev-delivery-warrant-legacy-recovery.js";
19
+ import { reuseExactActiveDevDeliverySourceProof } from "../packages/core/dev-delivery-candidate-identity.js";
20
20
  import { runV4DeliveryWarrantReadCandidate } from "../packages/core/v4-delivery-warrant-read-candidate.js";
21
21
 
22
22
  import { GitHubDevDeliveryStore } from "./dev-delivery-warrant-store.mjs";
23
+ import { persistDevDeliveryTransition } from "./dev-delivery-warrant-transition.mjs";
23
24
  import { devDeliveryCliOptions } from "./dev-delivery-warrant-options.mjs";
24
25
  export { GitHubDevDeliveryStore, devDeliveryCliOptions };
25
26
 
@@ -199,54 +200,60 @@ function transitionFor(command, queue, options) {
199
200
  "native command contract root does not match native-command",
200
201
  );
201
202
  }
203
+ const input = {
204
+ pullRequestNumber: positiveInteger(
205
+ options.pullRequestNumber,
206
+ "pullRequestNumber",
207
+ ),
208
+ sourceHead: exactSha(options.sourceHead, "sourceHead"),
209
+ ...(options.sourceRoot ? { sourceRoot: options.sourceRoot } : {}),
210
+ ...(options.assignmentRoot
211
+ ? { assignmentRoot: options.assignmentRoot }
212
+ : {}),
213
+ ...(options.initiativeRoot
214
+ ? { initiativeRoot: options.initiativeRoot }
215
+ : {}),
216
+ sourceIdentityRoot: exactRoot(
217
+ options.sourceIdentityRoot,
218
+ "sourceIdentityRoot",
219
+ ),
220
+ sourcePatchRoot: exactRoot(options.sourcePatchRoot, "sourcePatchRoot"),
221
+ sourceProofRoot: exactRoot(options.sourceProofRoot, "sourceProofRoot"),
222
+ planRoot: exactRoot(options.planRoot, "planRoot"),
223
+ closureRoot: exactRoot(options.closureRoot, "closureRoot"),
224
+ dependencyRoot: exactRoot(options.dependencyRoot, "dependencyRoot"),
225
+ toolchainRoot: exactRoot(options.toolchainRoot, "toolchainRoot"),
226
+ ...(options.environmentRoot
227
+ ? {
228
+ environmentRoot: exactRoot(
229
+ options.environmentRoot,
230
+ "environmentRoot",
231
+ ),
232
+ }
233
+ : {}),
234
+ ...(nativeCommandContract ? { nativeCommandContract } : {}),
235
+ affectedPaths: jsonList(options.affectedPaths, "affected paths"),
236
+ shardEvidenceRoots: jsonList(
237
+ options.shardEvidenceRoots,
238
+ "shard evidence roots",
239
+ ),
240
+ sourceWorkflowRunId: options.sourceWorkflowRunId
241
+ ? positiveInteger(options.sourceWorkflowRunId, "sourceWorkflowRunId")
242
+ : 0,
243
+ deliveryClass: options.deliveryClass,
244
+ priority: options.priority || "ordinary",
245
+ ...(options.releaseBlockerPriority
246
+ ? {
247
+ releaseBlockerPriority: jsonObject(
248
+ options.releaseBlockerPriority,
249
+ "release blocker priority",
250
+ ),
251
+ }
252
+ : {}),
253
+ };
202
254
  return submitDevDeliveryCandidate(
203
255
  queue,
204
- {
205
- pullRequestNumber: positiveInteger(
206
- options.pullRequestNumber,
207
- "pullRequestNumber",
208
- ),
209
- sourceHead: exactSha(options.sourceHead, "sourceHead"),
210
- assignmentRoot: exactRoot(options.assignmentRoot, "assignmentRoot"),
211
- initiativeRoot: exactRoot(options.initiativeRoot, "initiativeRoot"),
212
- sourceIdentityRoot: exactRoot(
213
- options.sourceIdentityRoot,
214
- "sourceIdentityRoot",
215
- ),
216
- sourcePatchRoot: exactRoot(options.sourcePatchRoot, "sourcePatchRoot"),
217
- sourceProofRoot: exactRoot(options.sourceProofRoot, "sourceProofRoot"),
218
- planRoot: exactRoot(options.planRoot, "planRoot"),
219
- closureRoot: exactRoot(options.closureRoot, "closureRoot"),
220
- dependencyRoot: exactRoot(options.dependencyRoot, "dependencyRoot"),
221
- toolchainRoot: exactRoot(options.toolchainRoot, "toolchainRoot"),
222
- ...(options.environmentRoot
223
- ? {
224
- environmentRoot: exactRoot(
225
- options.environmentRoot,
226
- "environmentRoot",
227
- ),
228
- }
229
- : {}),
230
- ...(nativeCommandContract ? { nativeCommandContract } : {}),
231
- affectedPaths: jsonList(options.affectedPaths, "affected paths"),
232
- shardEvidenceRoots: jsonList(
233
- options.shardEvidenceRoots,
234
- "shard evidence roots",
235
- ),
236
- sourceWorkflowRunId: options.sourceWorkflowRunId
237
- ? positiveInteger(options.sourceWorkflowRunId, "sourceWorkflowRunId")
238
- : 0,
239
- deliveryClass: options.deliveryClass,
240
- priority: options.priority || "ordinary",
241
- ...(options.releaseBlockerPriority
242
- ? {
243
- releaseBlockerPriority: jsonObject(
244
- options.releaseBlockerPriority,
245
- "release blocker priority",
246
- ),
247
- }
248
- : {}),
249
- },
256
+ reuseExactActiveDevDeliverySourceProof(queue.activeWarrant, input),
250
257
  { now: options.now },
251
258
  );
252
259
  }
@@ -461,51 +468,16 @@ export async function runDevDeliveryCommand(optionsInput = {}, clientInput) {
461
468
  }
462
469
  if (options.command === "observe") return observeQueue(loaded, options);
463
470
  const initialLoaded = loaded;
464
- let changed = transitionFor(options.command, loaded.queue, options);
465
- let mutates = changed.queue.stateRoot !== loaded.queue.stateRoot;
466
- let write = null;
467
- if (options.execute && mutates) {
468
- if (changed.receipt.expectedOldStateRoot !== loaded.queue.stateRoot) {
469
- throw new Error(
470
- "transition receipt expected-old root does not match the loaded authority",
471
- );
472
- }
473
- try {
474
- write = await store.write({
475
- stateRef: options.stateRef,
476
- queue: changed.queue,
477
- expectedCommitSha: loaded.commitSha,
478
- expectedStateRoot: loaded.queue.stateRoot,
479
- receiptRoot: changed.receiptRoot,
480
- });
481
- } catch (error) {
482
- if (options.command !== "settle" || options.expectedOldStateRoot)
483
- throw error;
484
- const latest = await store.read({
485
- stateRef: options.stateRef,
486
- protectedBase: options.branch,
487
- now: options.now,
488
- });
489
- const reconciled = transitionFor(options.command, latest.queue, options);
490
- const reconciledMutates =
491
- reconciled.queue.stateRoot !== latest.queue.stateRoot;
492
- if (
493
- reconciledMutates ||
494
- reconciled.receipt.action !== "duplicate-terminal-event-noop"
495
- )
496
- throw error;
497
- loaded = latest;
498
- changed = reconciled;
499
- mutates = false;
500
- concurrencyRecovery = {
501
- schema: "kungfu.buildchain.dev-delivery-concurrency-recovery/v1",
502
- action: "terminal-settlement-race-noop",
503
- initialCommitSha: initialLoaded.commitSha,
504
- observedCommitSha: latest.commitSha,
505
- observedStateRoot: latest.queue.stateRoot,
506
- };
507
- }
508
- }
471
+ const persisted = await persistDevDeliveryTransition({
472
+ store,
473
+ options,
474
+ loaded,
475
+ initialLoaded,
476
+ changed: transitionFor(options.command, loaded.queue, options),
477
+ transitionFor,
478
+ });
479
+ loaded = persisted.loaded;
480
+ concurrencyRecovery = persisted.concurrencyRecovery || concurrencyRecovery;
509
481
  return {
510
482
  schema: "kungfu.buildchain.dev-delivery-command-result/v1",
511
483
  ok: true,
@@ -514,16 +486,21 @@ export async function runDevDeliveryCommand(optionsInput = {}, clientInput) {
514
486
  stateRef: options.stateRef,
515
487
  before: { commitSha: loaded.commitSha, stateRoot: loaded.queue.stateRoot },
516
488
  after: {
517
- commitSha: write?.commitSha || loaded.commitSha,
518
- stateRoot: changed.queue.stateRoot,
489
+ commitSha: persisted.write?.commitSha || loaded.commitSha,
490
+ stateRoot: persisted.changed.queue.stateRoot,
519
491
  },
520
492
  mutationAuthorized: options.execute,
521
- mutationApplied: Boolean(write),
493
+ mutationApplied: Boolean(persisted.write),
522
494
  concurrencyRecovery,
523
- receipt: changed.receipt,
524
- receiptRoot: changed.receiptRoot,
525
- warrant: changed.warrant || changed.queue.activeWarrant || null,
526
- observation: observeDevDeliveryQueue(changed.queue, { now: options.now }),
495
+ receipt: persisted.changed.receipt,
496
+ receiptRoot: persisted.changed.receiptRoot,
497
+ warrant:
498
+ persisted.changed.warrant ||
499
+ persisted.changed.queue.activeWarrant ||
500
+ null,
501
+ observation: observeDevDeliveryQueue(persisted.changed.queue, {
502
+ now: options.now,
503
+ }),
527
504
  };
528
505
  }
529
506
 
@@ -723,7 +723,6 @@ function renderAdmissionComment(receipt, receiptRoot) {
723
723
  "GitHub auto-merge state is observed evidence only; it is not Buildchain admission authority.",
724
724
  ].join("\n");
725
725
  }
726
-
727
726
  async function publishAdmissionDiagnostic(client, options, receipt, receiptRoot) {
728
727
  const marker = `<!-- ${AGENT_ADMISSION_MARKER} pr=${receipt.pullRequestNumber} head=${receipt.expectedHeadSha} -->`;
729
728
  const body = renderAdmissionComment(receipt, receiptRoot);
@@ -743,7 +742,6 @@ async function publishAdmissionDiagnostic(client, options, receipt, receiptRoot)
743
742
  }
744
743
  return { commentId: comment?.id || null, commentUrl: comment?.html_url || "", statusPublished: Boolean(status) };
745
744
  }
746
-
747
745
  function createAdmissionReceipt({ options, pr = {}, state, reason, readiness, decision = {}, queue = null, warrant = null }) {
748
746
  return createDevPrAdmissionReceipt({ options, pr, state, reason, readiness, decision, queue, warrant, labels: labelsOf(pr), nextAction: nextAdmissionAction });
749
747
  }
@@ -751,16 +749,21 @@ function createAdmissionReceipt({ options, pr = {}, state, reason, readiness, de
751
749
  function targetedFailure({ options, pr, state, reason, readiness, decision, queue }) {
752
750
  const receipt = createAdmissionReceipt({ options, pr, state, reason, readiness, decision, queue });
753
751
  return {
754
- schema: AGENT_ADMISSION_RESULT_SCHEMA,
755
- ok: false,
756
- mode: options.dryRun ? "plan" : "execute",
757
- outcome: "targeted-admission-failed",
758
- receipt,
759
- receiptRoot: contentRoot(receipt),
760
- diagnostic: null,
752
+ schema: AGENT_ADMISSION_RESULT_SCHEMA, ok: false, mode: options.dryRun ? "plan" : "execute",
753
+ outcome: "targeted-admission-failed", receipt, receiptRoot: contentRoot(receipt), diagnostic: null,
761
754
  };
762
755
  }
763
-
756
+ async function readTargetPullRequest(client, number, options) {
757
+ let { pollMergeableAttempts: attempts, pollMergeableDelayMs: delayMs } = options;
758
+ for (; attempts > 1; attempts -= 1) {
759
+ try {
760
+ return await client.getPullRequest(number, { attempts, delayMs });
761
+ } catch {
762
+ await delay(delayMs);
763
+ }
764
+ }
765
+ return client.getPullRequest(number, { attempts, delayMs });
766
+ }
764
767
  export async function runDevPrAdmission(optionsInput = {}, clientInput) {
765
768
  const options = normalizeOptions(optionsInput);
766
769
  if (!options.targetBranch) throw new Error("target branch is required");
@@ -776,12 +779,9 @@ export async function runDevPrAdmission(optionsInput = {}, clientInput) {
776
779
 
777
780
  let pr;
778
781
  try {
779
- pr = await client.getPullRequest(options.targetPullRequestNumber, {
780
- attempts: options.pollMergeableAttempts,
781
- delayMs: options.pollMergeableDelayMs,
782
- });
782
+ pr = await readTargetPullRequest(client, options.targetPullRequestNumber, options);
783
783
  } catch (error) {
784
- return targetedFailure({ options, pr: {}, state: "missing", reason: "pull-request-not-found" });
784
+ return targetedFailure({ options, pr: {}, state: "blocked", reason: "pull-request-read-failed" });
785
785
  }
786
786
 
787
787
  const readinessFence = createPreReadinessQueueFence({ client, options, sleep: delay });
@@ -1,8 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import fs from "node:fs";
4
+ import { writeWorkflowSource } from "./workflow-taxonomy.mjs";
4
5
  import path from "node:path";
5
6
  import { fileURLToPath } from "node:url";
7
+ import { migrateV4UniversalWorkflowFacade } from "./generate-v4-universal-workflow-facades.mjs";
6
8
 
7
9
  const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
8
10
  const sourcePath = path.join(root, ".github/workflows/.build.yml");
@@ -403,7 +405,10 @@ export function generateChannelBuildWorkflow(source) {
403
405
  ].join("\n"),
404
406
  )
405
407
  .replace("\n alpha:\n", `\n${routerControllerPlanJob()}\n\n alpha:\n`);
406
- return `${generated.trimEnd()}\n\n${routerControllerReceiptJob()}\n\n${routerAggregateJob()}\n`;
408
+ return migrateV4UniversalWorkflowFacade(
409
+ `${generated.trimEnd()}\n\n${routerControllerReceiptJob()}\n\n${routerAggregateJob()}\n`,
410
+ ".github/workflows/build.yml",
411
+ );
407
412
  }
408
413
 
409
414
  function main() {
@@ -417,7 +422,7 @@ function main() {
417
422
  }
418
423
  return;
419
424
  }
420
- fs.writeFileSync(targetPath, generated);
425
+ writeWorkflowSource(root, path.relative(root, targetPath), generated);
421
426
  }
422
427
 
423
428
  const isMain = process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url);
@@ -1,8 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import fs from "node:fs";
4
+ import { writeWorkflowSource } from "./workflow-taxonomy.mjs";
4
5
  import path from "node:path";
5
6
  import { fileURLToPath } from "node:url";
7
+ import { migrateV4UniversalWorkflowFacade } from "./generate-v4-universal-workflow-facades.mjs";
6
8
 
7
9
  const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
8
10
  const sourcePath = path.join(root, ".github/workflows/.release-candidate-promote.yml");
@@ -214,9 +216,9 @@ function consumerAdmissionJob() {
214
216
  id: policy
215
217
  env:
216
218
  BUILDCHAIN_CONSUMER_ROOT: .buildchain/consumer
217
- BUILDCHAIN_INVOCATION_SOURCE_PATH: \${{ inputs.publication-publisher-workflow-path == '.github/workflows/buildchain-ref-promotion-recovery.yml' && '.github/workflows/release-candidate-promote.yml' || inputs.publication-publisher-workflow-path }}
219
+ BUILDCHAIN_INVOCATION_SOURCE_PATH: \${{ inputs.publication-publisher-workflow-path == '.github/workflows/self-ops-promotion-recovery.yml' && '.github/workflows/release-candidate-promote.yml' || inputs.publication-publisher-workflow-path }}
218
220
  BUILDCHAIN_EXPECTED_INVOCATION_CHANNEL: \${{ needs.resolve-promotion.outputs.channel }}
219
- BUILDCHAIN_INVOKED_WORKFLOW: \${{ inputs.publication-publisher-workflow-path == '.github/workflows/buildchain-ref-promotion-recovery.yml' && '.github/workflows/.release-candidate-promote.yml' || '.github/workflows/release-candidate-promote.yml' }}
221
+ BUILDCHAIN_INVOKED_WORKFLOW: \${{ inputs.publication-publisher-workflow-path == '.github/workflows/self-ops-promotion-recovery.yml' && '.github/workflows/.release-candidate-promote.yml' || '.github/workflows/release-candidate-promote.yml' }}
220
222
  BUILDCHAIN_WORKFLOW_SHA: \${{ needs.resolve-promotion.outputs.router-sha }}
221
223
  BUILDCHAIN_RUNTIME_SHA: \${{ needs.resolve-promotion.outputs.router-sha }}
222
224
  BUILDCHAIN_STABLE_CONTRACT_LOCK_PATH: \${{ inputs.buildchain-stable-contract-lock-path }}
@@ -302,7 +304,7 @@ export function generateChannelPromotionWorkflow(source, { major = 2, shellRouti
302
304
  if (!inputNames.includes(required)) throw new Error(`advanced promotion workflow missing input: ${required}`);
303
305
  }
304
306
  const invokeForwarded = routedInputs(inputNames, alphaRoute, major);
305
- return `# Generated by scripts/generate-channel-promotion-workflow.mjs. Do not edit directly.
307
+ return migrateV4UniversalWorkflowFacade(`# Generated by scripts/generate-channel-promotion-workflow.mjs. Do not edit directly.
306
308
  name: Release Candidate Promote
307
309
 
308
310
  on:
@@ -513,7 +515,7 @@ ${consumerAdmissionJob()}
513
515
  with:
514
516
  ${invokeForwarded}
515
517
  secrets: inherit
516
- `;
518
+ `, ".github/workflows/release-candidate-promote.yml");
517
519
  }
518
520
 
519
521
  function main() {
@@ -531,7 +533,7 @@ function main() {
531
533
  }
532
534
  return;
533
535
  }
534
- fs.writeFileSync(targetPath, generated);
536
+ writeWorkflowSource(root, path.relative(root, targetPath), generated);
535
537
  }
536
538
 
537
539
  const isMain = process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url);
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env node
2
+ import { readWorkflowTaxonomy, workflowPath } from "./workflow-taxonomy.mjs";
2
3
  import fs from "node:fs";
3
4
  import path from "node:path";
4
5
  import crypto from "node:crypto";
@@ -755,9 +756,7 @@ function buildSiteBundle() {
755
756
  timestampFieldsParticipateInArtifactDigest: true,
756
757
  artifactDigestScope: "npm package dist/site JSON files",
757
758
  });
758
-
759
759
  const cliRegistry = createCliRegistry(packageJson);
760
-
761
760
  const manualRegistry = {
762
761
  schemaVersion: 1,
763
762
  contract: "kungfu-buildchain-agent-manual-registry",
@@ -805,7 +804,6 @@ function buildSiteBundle() {
805
804
  ],
806
805
  guidance: "Agent consumers should use this registry to find packaged Buildchain manuals before inferring behavior from workflow snippets or release notes.",
807
806
  };
808
-
809
807
  const pageRegistry = {
810
808
  schemaVersion: 1,
811
809
  contract: "kungfu-buildchain-site-page-registry",
@@ -821,14 +819,15 @@ function buildSiteBundle() {
821
819
  capabilityGroups: CAPABILITY_GROUPS.map((group) => group.id),
822
820
  pages,
823
821
  };
824
-
825
822
  const nodeApiRegistry = createSiteNodeApiRegistry({ root, packageJson, nodeApiMeta, sha256File, publicSurfaceLifecycle });
826
-
823
+ const taxonomy = readWorkflowTaxonomy(root);
827
824
  const workflowRegistry = {
828
825
  schemaVersion: 1,
829
826
  contract: "kungfu-buildchain-workflow-registry",
830
827
  workflowSource: ".github/workflows reverse input enumeration",
831
828
  workflows: enumerateWorkflowInputs({ root }).map((entry) => {
829
+ const classification = taxonomy?.entries.find((item) => workflowPath(item) === entry.path || item.compatibility?.path === entry.path);
830
+ const semanticId = classification?.id || entry.id;
832
831
  const surfaceById = new Map([
833
832
  ["build", "channel-build-router"],
834
833
  [".build", "reusable-build"],
@@ -878,18 +877,19 @@ function buildSiteBundle() {
878
877
  ["engineering-housekeeper-monthly", "preview"],
879
878
  ["self-hosted-runner-smoke", "compatibility-fixture"],
880
879
  ]);
881
- const engineeringHousekeeper = entry.id.startsWith("engineering-housekeeper");
880
+ const engineeringHousekeeper = semanticId.startsWith("engineering-housekeeper");
882
881
  return {
883
882
  ...entry,
884
- surface: surfaceById.get(entry.id) || (entry.path.includes("/.") ? "reusable-workflow" : "repository-workflow"),
883
+ ...(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) } } : {}),
884
+ surface: surfaceById.get(semanticId) || (entry.path.includes("/.") ? "reusable-workflow" : "repository-workflow"),
885
885
  capabilityGroup: workflowCapabilityGroup({
886
- ...entry,
887
- status: statusById.get(entry.id) || "active",
886
+ ...entry, id: semanticId,
887
+ status: statusById.get(semanticId) || "active",
888
888
  }),
889
- status: statusById.get(entry.id) || "active",
889
+ status: statusById.get(semanticId) || "active",
890
890
  ...publicSurfaceLifecycle({
891
891
  owner: "buildchain-workflows",
892
- maturity: statusById.get(entry.id) || "active",
892
+ maturity: statusById.get(semanticId) || "active",
893
893
  introducedVersion: engineeringHousekeeper ? packageJson.version : undefined,
894
894
  nonDuplicationRationale: engineeringHousekeeper
895
895
  ? "One reusable policy and evidence boundary owns Engineering Housekeeper execution; scheduled callers contain cadence values only."