@kungfu-tech/buildchain 4.0.2-alpha.9 → 4.0.3-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 (281) hide show
  1. package/AGENTS.md +14 -5
  2. package/CONTRIBUTING.md +58 -0
  3. package/README.md +3 -3
  4. package/actions/promote-buildchain-ref/README.md +1 -1
  5. package/actions/release-candidate-promote/README.md +31 -0
  6. package/architecture/agent-change-map.md +190 -126
  7. package/architecture/{v4-architecture-constitution.md → architecture-constitution.md} +33 -30
  8. package/architecture/{v3-core-mechanism-inventory.md → baseline-core-mechanism-inventory.md} +1 -1
  9. package/architecture/{v4-bootstrap-authority.json → bootstrap-authority.json} +3 -3
  10. package/architecture/{v3-v4-capability-closure.md → capability-parity-closure.md} +3 -3
  11. package/architecture/{v3-v4-live-capability-inventory.json → capability-parity-live-capability-inventory.json} +4 -4
  12. package/architecture/{v4-capability-state-machine-manifest.json → capability-state-machine-manifest.json} +2 -2
  13. package/architecture/{v4-capability-state-machine-manifest.schema.json → capability-state-machine-manifest.schema.json} +2 -2
  14. package/architecture/ci-lane-change-budget.json +384 -0
  15. package/architecture/{v4-cross-platform-adopter-qualification.json → cross-platform-adopter-qualification.json} +4 -4
  16. package/architecture/{v4-delivery-authority-parity.json → delivery-authority-parity.json} +17 -17
  17. package/architecture/{v4-delivery-warrant-shadow-bootstrap-plan.json → delivery-warrant-shadow-bootstrap-plan.json} +4 -4
  18. package/architecture/{v4-delivery-warrant-shadow-bootstrap-plan.md → delivery-warrant-shadow-bootstrap-plan.md} +7 -7
  19. package/architecture/{v4-floating-consumer-policy.json → floating-consumer-policy.json} +2 -2
  20. package/architecture/{v4-floating-consumer-policy.md → floating-consumer-policy.md} +1 -1
  21. package/architecture/implementation-naming.json +1273 -0
  22. package/architecture/internal-capabilities.json +201 -154
  23. package/architecture/maintainability-debt.json +205 -146
  24. package/architecture/maintainability-policy.json +37 -33
  25. package/architecture/{v4-next-development-parity.json → next-development-parity.json} +12 -12
  26. package/architecture/{v4-partial-mutation-recovery-qualification.json → partial-mutation-recovery-qualification.json} +8 -5
  27. package/architecture/{v4-platform-stage-checkpoints.json → platform-stage-checkpoints.json} +3 -3
  28. package/architecture/{v4-provider-operation-journal-contract.json → provider-operation-journal-contract.json} +10 -7
  29. package/architecture/publication-facade-patches.json +64 -0
  30. package/architecture/{v4-publication-rehearsal-parity.json → publication-rehearsal-parity.json} +4 -4
  31. package/architecture/{v4-release-activation-shadow-domain.json → release-activation-shadow-domain.json} +9 -6
  32. package/architecture/release-tail-contract-inventory.json +6 -6
  33. package/architecture/{v4-release-topology.json → release-topology.json} +163 -72
  34. package/architecture/{v4-release-train-parity.json → release-train-parity.json} +2 -2
  35. package/architecture/{v4-runtime-ref-resume-authority.json → runtime-ref-resume-authority.json} +1 -1
  36. package/architecture/{v4-runtime-semantic-closure.json → runtime-semantic-closure.json} +2 -2
  37. package/architecture/{v4-rust-libnode-bridge-evaluation.json → rust-libnode-bridge-evaluation.json} +3 -3
  38. package/architecture/{v4-rust-libnode-bridge-spike.md → rust-libnode-bridge-spike.md} +6 -6
  39. package/architecture/rust-wasm-production-authority.json +58 -0
  40. package/architecture/{v4-stable-publication-fence.json → stable-publication-fence.json} +7 -4
  41. package/architecture/{v4-stage-capsule-contract.json → stage-capsule-contract.json} +1 -1
  42. package/architecture/{v4-stage-capsule-qualification.json → stage-capsule-qualification.json} +8 -8
  43. package/architecture/{v4-stage-capsule-resume-planner.json → stage-capsule-resume-planner.json} +2 -2
  44. package/architecture/{v4-stage-capsule-store-contract.json → stage-capsule-store-contract.json} +4 -4
  45. package/architecture/{v4-tail-reseal-parity.json → tail-reseal-parity.json} +35 -33
  46. package/architecture/universal-workflow-bootstrap.json +176 -0
  47. package/architecture/universal-workflow-fault-campaign.json +72 -0
  48. package/architecture/universal-workflow-train-admission.json +40 -0
  49. package/architecture/workflow-taxonomy.json +1462 -0
  50. package/bin/buildchain.mjs +10 -10
  51. package/bin/internal/adopter-delivery-cli.mjs +9 -9
  52. package/contracts/buildchain-v2-residuals-v1.json +57 -48
  53. package/contracts/dev-delivery-authority-v2.schema.json +16 -2
  54. package/contracts/fixtures/v4-tail-reseal-v1/valid.json +1 -1
  55. package/contracts/v4-canonical-contracts-v1.schema.json +1 -0
  56. package/crates/{buildchain-v4-bridge → buildchain-host-bridge}/Cargo.lock +1 -1
  57. package/crates/{buildchain-v4-bridge → buildchain-host-bridge}/Cargo.toml +1 -1
  58. package/crates/{buildchain-v4-bridge → buildchain-host-bridge}/src/main.rs +3 -3
  59. package/dist/site/buildchain-contract.json +98 -53
  60. package/dist/site/buildchain-site.json +351 -102
  61. package/dist/site/capability-registry.json +7 -7
  62. package/dist/site/controller-registry.json +50 -13
  63. package/dist/site/kfd-claims.json +2773 -1052
  64. package/dist/site/kfd-upstream-aggregate.json +1 -1
  65. package/dist/site/manual-registry.json +14 -14
  66. package/dist/site/node-api-registry.json +13176 -10733
  67. package/dist/site/page-registry.json +332 -83
  68. package/dist/site/public-surface-audit.json +3227 -1222
  69. package/dist/site/publication-authority-registry.json +1135 -363
  70. package/dist/site/publication-registry.json +4 -4
  71. package/dist/site/release-provenance.json +18 -9
  72. package/dist/site/schemas/dev-delivery-authority-v2.schema.json +16 -2
  73. package/dist/site/site-manifest.json +18 -18
  74. package/dist/site/workflow-registry.json +5367 -1931
  75. package/docs/MAP.md +5 -3
  76. package/docs/auditable-demo.md +1 -1
  77. package/docs/cli.md +21 -8
  78. package/docs/dev-delivery-warrant.md +1 -1
  79. package/docs/engineering-housekeeper.md +3 -3
  80. package/docs/kfd-support.md +26 -2
  81. package/docs/next-development-transition.md +26 -3
  82. package/docs/node-api-reference.md +618 -358
  83. package/docs/oci-publication.md +173 -0
  84. package/docs/publication-authority.md +2 -2
  85. package/docs/publish-transaction.md +36 -3
  86. package/docs/release-candidate.md +3 -3
  87. package/docs/release-flow.md +67 -19
  88. package/docs/release-governance.md +8 -8
  89. package/docs/release-passport.md +27 -2
  90. package/docs/reusable-build-surface.md +17 -1
  91. package/docs/v4-adopter-delivery.md +4 -4
  92. package/docs/v4-canonical-contracts.md +7 -7
  93. package/docs/v4-delivery-warrant-read-candidate.md +3 -3
  94. package/docs/v4-delivery-warrant-semantic-diff.md +3 -3
  95. package/docs/v4-production-release.md +77 -8
  96. package/docs/v4-publication-rehearsal.md +3 -3
  97. package/docs/v4-runtime-ref-resume-authority.md +2 -2
  98. package/docs/v4-rust-wasm-production-authority.md +58 -0
  99. package/docs/v4-stage-capsule.md +9 -9
  100. package/docs/v4-tail-reseal.md +2 -2
  101. package/docs/workflow-catalog.md +155 -0
  102. package/docs/workflow-path-migration.md +109 -0
  103. package/package.json +39 -24
  104. package/packages/compatibility/adopter-delivery.js +16 -0
  105. package/packages/compatibility/cross-platform-adopter-qualification.js +12 -0
  106. package/packages/compatibility/floating-consumer-policy.js +14 -0
  107. package/packages/compatibility/publication-qualification.js +11 -0
  108. package/packages/compatibility/publication-rehearsal.js +18 -0
  109. package/packages/compatibility/runtime-ref-resume-authority.js +13 -0
  110. package/packages/compatibility/tail-reseal-receipt.js +7 -0
  111. package/packages/compatibility/tail-reseal.js +11 -0
  112. package/packages/core/{v4-adopter-delivery-parity.js → adopter-delivery-parity.js} +12 -12
  113. package/packages/core/{v4-adopter-delivery.js → adopter-delivery.js} +24 -24
  114. package/packages/core/artifact-verification-envelope.js +5 -5
  115. package/packages/core/buildchain-contract.js +6 -6
  116. package/packages/core/buildchain-domain.wasm +0 -0
  117. package/packages/core/buildchain-kfd-claims.js +2 -2
  118. package/packages/core/buildchain-publication-authority.js +43 -26
  119. package/packages/core/{v4-canonical-contracts.js → canonical-contracts.js} +39 -103
  120. package/packages/core/ci-lane-change-budget.js +14 -1
  121. package/packages/core/controller-evidence.js +4 -1
  122. package/packages/core/{v4-cross-platform-adopter-qualification.js → cross-platform-adopter-qualification.js} +19 -19
  123. package/packages/core/{v4-delivery-warrant-fixture-runner.js → delivery-warrant-fixture-runner.js} +36 -32
  124. package/packages/core/{v4-delivery-warrant-read-candidate.js → delivery-warrant-read-candidate.js} +40 -40
  125. package/packages/core/{v4-delivery-warrant-semantic-diff-gate.js → delivery-warrant-semantic-diff-gate.js} +58 -59
  126. package/packages/core/{v4-delivery-warrant-shadow-adapter.js → delivery-warrant-shadow-adapter.js} +15 -15
  127. package/packages/core/dev-delivery-candidate-identity.js +40 -6
  128. package/packages/core/dev-delivery-execution-transfer.js +6 -6
  129. package/packages/core/dev-delivery-native-proof.js +12 -8
  130. package/packages/core/dev-delivery-warrant-legacy-recovery.js +1 -1
  131. package/packages/core/dev-delivery-warrant-native-compatibility.js +4 -4
  132. package/packages/core/dev-delivery-warrant-state.js +14 -15
  133. package/packages/core/dev-delivery-warrant.js +15 -5
  134. package/packages/core/domain-wasm-artifact.js +7 -0
  135. package/packages/core/domain-wasm.js +216 -0
  136. package/packages/core/{v4-floating-consumer-evidence.js → floating-consumer-evidence.js} +14 -14
  137. package/packages/core/{v4-floating-consumer-policy.js → floating-consumer-policy.js} +28 -30
  138. package/packages/core/{v4-floating-consumer-release-passport.js → floating-consumer-release-passport.js} +25 -25
  139. package/packages/core/github-governance-authority.js +4 -4
  140. package/packages/core/index.js +4 -8
  141. package/packages/core/kfd-adopter-manifest.js +46 -47
  142. package/packages/core/next-development-projection.js +26 -3
  143. package/packages/core/next-development-transition.js +5 -6
  144. package/packages/core/oci-compose-qualification.js +143 -0
  145. package/packages/core/oci-publication-bundle.js +281 -0
  146. package/packages/core/oci-publication-graph.js +206 -0
  147. package/packages/core/paper-agent-entry.js +30 -4
  148. package/packages/core/paper-fleet.js +1 -1
  149. package/packages/core/paper-runtime-channels.js +348 -0
  150. package/packages/core/paper-scaffold-content.js +10 -0
  151. package/packages/core/paper.js +37 -71
  152. package/packages/core/partial-mutation-recovery-qualification.js +18 -0
  153. package/packages/core/{v4-platform-stage-checkpoints.js → platform-stage-checkpoints.js} +37 -37
  154. package/packages/core/product-publication.js +59 -0
  155. package/packages/core/{v4-protected-publication-source.js → protected-publication-source.js} +22 -24
  156. package/packages/core/provider-operation-journal.js +62 -0
  157. package/packages/core/{v4-provider-readback-idempotency.js → provider-readback-idempotency.js} +40 -125
  158. package/packages/core/public-export-compatibility.js +33 -0
  159. package/packages/core/publication-development.js +72 -0
  160. package/packages/core/{v4-publication-qualification.js → publication-qualification.js} +17 -17
  161. package/packages/core/{v4-publication-rehearsal-capsule.js → publication-rehearsal-capsule.js} +23 -23
  162. package/packages/core/publication-rehearsal-projection.js +2 -2
  163. package/packages/core/{v4-publication-rehearsal-provider-bindings.js → publication-rehearsal-provider-bindings.js} +4 -4
  164. package/packages/core/publication-rehearsal-runtime.js +21 -21
  165. package/packages/core/{v4-publication-rehearsal.js → publication-rehearsal.js} +33 -33
  166. package/packages/core/publication-sealed-bundle.js +78 -13
  167. package/packages/core/release-activation-shadow.js +32 -0
  168. package/packages/core/release-candidate.js +6 -6
  169. package/packages/core/release-invocation.js +64 -0
  170. package/packages/core/release-line-dry-run.js +1 -1
  171. package/packages/core/release-passport-contract.js +5 -5
  172. package/packages/core/release-passport.js +41 -40
  173. package/packages/core/release-tail-product-capabilities.js +9 -0
  174. package/packages/core/release-tail-provider-plane.js +68 -1048
  175. package/packages/core/{v4-runtime-ref-resume-authority.js → runtime-ref-resume-authority.js} +36 -40
  176. package/packages/core/{v4-runtime-selector-persistence.js → runtime-selector-persistence.js} +7 -7
  177. package/packages/core/stable-publication-fence.js +28 -0
  178. package/packages/core/{v4-stage-capsule-local-store.js → stage-capsule-local-store.js} +56 -54
  179. package/packages/core/{v4-stage-capsule-qualification-campaign.js → stage-capsule-qualification-campaign.js} +37 -38
  180. package/packages/core/{v4-stage-capsule-qualification.js → stage-capsule-qualification.js} +28 -29
  181. package/packages/core/{v4-stage-capsule-resume-planner.js → stage-capsule-resume-planner.js} +29 -29
  182. package/packages/core/{v4-stage-capsule-store.js → stage-capsule-store.js} +59 -56
  183. package/packages/core/{v4-stage-capsule.js → stage-capsule.js} +45 -45
  184. package/packages/core/{v4-tail-reseal-contract.js → tail-reseal-contract.js} +6 -6
  185. package/packages/core/{v4-tail-reseal-github.js → tail-reseal-github.js} +12 -12
  186. package/packages/core/{v4-tail-reseal-receipt.js → tail-reseal-receipt.js} +22 -22
  187. package/packages/core/{v4-tail-reseal.js → tail-reseal.js} +29 -29
  188. package/packages/core/universal-workflow-bootstrap.js +586 -0
  189. package/scripts/{v4-architecture.mjs → architecture.mjs} +6 -6
  190. package/scripts/binary-publication-evidence.mjs +135 -0
  191. package/scripts/{v4-bridge-bootstrap.mjs → bridge-bootstrap.mjs} +14 -18
  192. package/scripts/{v4-bridge-evidence.mjs → bridge-evidence.mjs} +8 -8
  193. package/scripts/build-contract-core.mjs +1 -14
  194. package/scripts/build-domain-wasm.mjs +177 -0
  195. package/scripts/{v3-v4-capability-catalog.mjs → capability-parity-catalog.mjs} +19 -19
  196. package/scripts/check-action-bundles.mjs +12 -2
  197. package/scripts/{check-v3-v4-capability-inventory.mjs → check-capability-parity-inventory.mjs} +42 -42
  198. package/scripts/check-ci-lane-change-budget.mjs +4 -1
  199. package/scripts/check-core-mechanism-inventory.mjs +8 -4
  200. package/scripts/{check-v4-floating-consumer-policy-contract.mjs → check-floating-consumer-policy-contract.mjs} +10 -10
  201. package/scripts/check-implementation-naming.mjs +135 -0
  202. package/scripts/check-inventory.mjs +39 -47
  203. package/scripts/check-maintainability.mjs +25 -115
  204. package/scripts/{check-v4-public-dogfood-contract.mjs → check-public-dogfood-contract.mjs} +37 -24
  205. package/scripts/{check-v4-release-topology.mjs → check-release-topology.mjs} +131 -52
  206. package/scripts/{check-v4-runtime-semantic-closure.mjs → check-runtime-semantic-closure.mjs} +23 -17
  207. package/scripts/check-universal-workflow-bootstrap.mjs +266 -0
  208. package/scripts/check-workflow-taxonomy.mjs +6 -0
  209. package/scripts/{v4-consumer-policy.mjs → consumer-policy.mjs} +15 -15
  210. package/scripts/copy-domain-wasm.mjs +14 -0
  211. package/scripts/{v4-cross-platform-adopter-qualification.mjs → cross-platform-adopter-qualification.mjs} +9 -9
  212. package/scripts/{v4-declarative-promotion-admission.mjs → declarative-promotion-admission.mjs} +4 -4
  213. package/scripts/dev-delivery-authority-command-adapters.mjs +1 -1
  214. package/scripts/dev-delivery-authority.mjs +8 -8
  215. package/scripts/dev-delivery-source-proof-reuse.mjs +2 -1
  216. package/scripts/dev-delivery-warrant-options.mjs +15 -10
  217. package/scripts/dev-delivery-warrant-store.mjs +98 -13
  218. package/scripts/dev-delivery-warrant-transition.mjs +109 -0
  219. package/scripts/dev-delivery-warrant.mjs +80 -103
  220. package/scripts/dev-pr-auto-merge.mjs +15 -15
  221. package/scripts/dev-pr-delivery-warrant.mjs +1 -1
  222. package/scripts/generate-channel-build-workflow.mjs +7 -2
  223. package/scripts/generate-channel-promotion-workflow.mjs +19 -34
  224. package/scripts/generate-release-candidate-passport.mjs +23 -23
  225. package/scripts/generate-site-bundle.mjs +28 -28
  226. package/scripts/generate-universal-workflow-facades.mjs +498 -0
  227. package/scripts/generate-workflow-taxonomy.mjs +25 -0
  228. package/scripts/github-output.mjs +31 -0
  229. package/scripts/{v4-host-adapter.mjs → host-adapter.mjs} +1 -1
  230. package/scripts/implementation-references.mjs +25 -0
  231. package/scripts/init-repo.mjs +1 -1
  232. package/scripts/maintainability-metrics.mjs +16 -5
  233. package/scripts/maintainability-public-surface.mjs +115 -0
  234. package/scripts/next-development-review.mjs +313 -0
  235. package/scripts/oci-compose-preview.mjs +261 -0
  236. package/scripts/paper-work-fleet-cli.mjs +2 -0
  237. package/scripts/{v4-platform-stage-checkpoint-rehearsal.mjs → platform-stage-checkpoint-rehearsal.mjs} +17 -17
  238. package/scripts/{v4-product-publication-intent.mjs → product-publication-intent.mjs} +28 -13
  239. package/scripts/publication-candidate-kind.mjs +93 -0
  240. package/scripts/publication-candidate-sealer.mjs +16 -1
  241. package/scripts/{v4-publication-rehearsal-fixture.mjs → publication-rehearsal-fixture.mjs} +5 -5
  242. package/scripts/publication-settlement.mjs +211 -0
  243. package/scripts/release-asset-client.mjs +91 -0
  244. package/scripts/{v4-release-candidate-adapter.mjs → release-candidate-adapter.mjs} +4 -4
  245. package/scripts/release-candidate-resolver.mjs +24 -35
  246. package/scripts/release-tail.mjs +5 -5
  247. package/scripts/resume-from-candidate-run.mjs +35 -42
  248. package/scripts/site-capability-metadata.mjs +9 -0
  249. package/scripts/source-verification-evidence.mjs +344 -0
  250. package/scripts/stable-candidate-qualification.mjs +1 -1
  251. package/scripts/{v4-stage-capsule-qualification.mjs → stage-capsule-qualification.mjs} +62 -62
  252. package/scripts/{v4-stage-capsule-resume-rehearsal.mjs → stage-capsule-resume-rehearsal.mjs} +6 -6
  253. package/scripts/{v4-tail-reseal-macos-rehearsal.mjs → tail-reseal-macos-rehearsal.mjs} +9 -9
  254. package/scripts/{v4-tail-reseal.mjs → tail-reseal.mjs} +19 -19
  255. package/scripts/universal-facade-maintainability.mjs +91 -0
  256. package/scripts/universal-workflow-backflow.mjs +212 -0
  257. package/scripts/universal-workflow-engine.mjs +620 -0
  258. package/scripts/universal-workflow-self-dogfood.mjs +205 -0
  259. package/scripts/verify-version-state-delta.mjs +175 -0
  260. package/scripts/{v4-warrant-shadow-plan.mjs → warrant-shadow-plan.mjs} +6 -6
  261. package/scripts/workflow-taxonomy.mjs +507 -0
  262. package/templates/native-dev-delivery.yml +4 -7
  263. package/templates/universal-buildchain-bootstrap-recovery.yml +282 -0
  264. package/templates/universal-buildchain-bootstrap.yml +28 -0
  265. package/actions/v4-release-candidate-promote/README.md +0 -3
  266. package/packages/core/v4-partial-mutation-recovery-qualification.js +0 -395
  267. package/packages/core/v4-product-publication.js +0 -387
  268. package/packages/core/v4-provider-operation-journal.js +0 -531
  269. package/packages/core/v4-release-activation-shadow.js +0 -519
  270. package/packages/core/v4-release-invocation.js +0 -425
  271. package/packages/core/v4-stable-publication-fence.js +0 -357
  272. /package/architecture/{v4-adopter-delivery-parity.json → adopter-delivery-parity.json} +0 -0
  273. /package/architecture/{v3-core-mechanism-inventory.json → baseline-core-mechanism-inventory.json} +0 -0
  274. /package/architecture/{v4-canonical-contract-fixtures.json → canonical-contract-fixtures.json} +0 -0
  275. /package/architecture/{v4-compatibility-facts-parity.json → compatibility-facts-parity.json} +0 -0
  276. /package/architecture/{v4-delivery-warrant-shadow-bootstrap-plan.schema.json → delivery-warrant-shadow-bootstrap-plan.schema.json} +0 -0
  277. /package/architecture/{v4-delivery-warrant-shadow-fixtures.json → delivery-warrant-shadow-fixtures.json} +0 -0
  278. /package/architecture/{v4-delivery-warrant-shadow-fixtures.schema.json → delivery-warrant-shadow-fixtures.schema.json} +0 -0
  279. /package/architecture/{v4-exception-ledger.json → exception-ledger.json} +0 -0
  280. /package/architecture/{v4-exception-ledger.schema.json → exception-ledger.schema.json} +0 -0
  281. /package/architecture/{v4-release-invocation-fixtures.json → release-invocation-fixtures.json} +0 -0
@@ -0,0 +1,498 @@
1
+ #!/usr/bin/env node
2
+ import { rewriteImplementationReferences } from "./implementation-references.mjs";
3
+ import fs from "node:fs";
4
+ import crypto from "node:crypto";
5
+ import {
6
+ currentWorkflowPath,
7
+ writeWorkflowSource,
8
+ rewriteRepositoryWorkflowPaths,
9
+ } from "./workflow-taxonomy.mjs";
10
+ import path from "node:path";
11
+ import { execFileSync } from "node:child_process";
12
+ import { fileURLToPath } from "node:url";
13
+ const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
14
+ const contractPath = path.join(
15
+ root,
16
+ "architecture/universal-workflow-bootstrap.json",
17
+ );
18
+ const contract = JSON.parse(fs.readFileSync(contractPath, "utf8"));
19
+ const laneBudgetPath = path.join(
20
+ root,
21
+ "architecture/ci-lane-change-budget.json",
22
+ );
23
+ const recoveryTemplatePath = path.join(
24
+ root,
25
+ contract.bootstrap.consumerRecoveryTemplate,
26
+ );
27
+ const recoveryWorkflowPath = path.join(
28
+ root,
29
+ contract.bootstrap.consumerRecoveryWorkflow,
30
+ );
31
+ const universalInput = ` universal-request-json:
32
+ description: "Versioned exact-candidate request envelope; empty preserves the compatibility path"
33
+ default: ""
34
+ required: false
35
+ type: string
36
+ `;
37
+ const bootstrapJob = ` universal-bootstrap:
38
+ name: Universal exact-candidate execution
39
+ if: \${{ inputs.universal-request-json != '' }}
40
+ uses: ./.github/workflows/bootstrap.yml
41
+ with:
42
+ request-json: \${{ inputs.universal-request-json }}
43
+
44
+ `;
45
+
46
+ function fail(message) {
47
+ throw new Error(message);
48
+ }
49
+
50
+ function activeFacadePaths() {
51
+ const retired = new Set(contract.retiredWorkflowSurfaces || []);
52
+ return contract.inventoryWorkflows.filter(
53
+ (relative) =>
54
+ relative !== contract.bootstrap.publicWorkflow &&
55
+ relative !== contract.bootstrap.consumerRecoveryWorkflow &&
56
+ !retired.has(relative),
57
+ );
58
+ }
59
+
60
+ function sourceRevision() {
61
+ const revision = contract.migration.facadeSourceRevision;
62
+ if (!/^[0-9a-f]{40}$/u.test(revision || ""))
63
+ fail("migration.facadeSourceRevision must be an exact commit");
64
+ return revision;
65
+ }
66
+
67
+ function materializeSourceRevision() {
68
+ const revision = sourceRevision();
69
+ try {
70
+ execFileSync("git", ["cat-file", "-e", `${revision}^{commit}`], {
71
+ cwd: root,
72
+ stdio: "ignore",
73
+ });
74
+ return;
75
+ } catch {}
76
+ try {
77
+ execFileSync(
78
+ "git",
79
+ ["fetch", "--no-tags", "--depth=1", "origin", revision],
80
+ { cwd: root, stdio: "pipe" },
81
+ );
82
+ execFileSync("git", ["cat-file", "-e", `${revision}^{commit}`], {
83
+ cwd: root,
84
+ stdio: "ignore",
85
+ });
86
+ } catch (error) {
87
+ const detail = String(error?.stderr || error?.message || error).trim();
88
+ fail(
89
+ `facade source revision ${revision} is unavailable and could not be hydrated from origin${detail ? `: ${detail}` : ""}`,
90
+ );
91
+ }
92
+ }
93
+
94
+ function frozenFacadeSource(relative) {
95
+ return execFileSync("git", ["show", `${sourceRevision()}:${relative}`], {
96
+ cwd: root,
97
+ encoding: "utf8",
98
+ });
99
+ }
100
+
101
+ const mutableFacades = new Set([
102
+ ...(contract.migration.channelGeneratedFacades || []),
103
+ ".github/workflows/dev-pr-auto-merge.yml",
104
+ ...(contract.migration.postMigrationWorkflows || []),
105
+ ]);
106
+
107
+ function isMutableFacade(relative) {
108
+ return mutableFacades.has(relative);
109
+ }
110
+
111
+ function addUniversalInput(source, relative) {
112
+ if (source.includes(" universal-request-json:\n")) return source;
113
+ const workflowCall = source.match(/^(\s*)workflow_call:\s*$/mu);
114
+ if (!workflowCall) fail(`${relative} has no workflow_call mapping`);
115
+ const callIndent = workflowCall[1];
116
+ const inputHeader = `${callIndent} inputs:\n`;
117
+ const callEnd = workflowCall.index + workflowCall[0].length;
118
+ if (source.slice(callEnd + 1).startsWith(inputHeader)) {
119
+ const insertion = callEnd + 1 + inputHeader.length;
120
+ return `${source.slice(0, insertion)}${universalInput}${source.slice(insertion)}`;
121
+ }
122
+ return `${source.slice(0, callEnd + 1)}\n${inputHeader}${universalInput}${source.slice(callEnd + 1)}`;
123
+ }
124
+
125
+ function conditionExpression(source, relative, jobId) {
126
+ const child = source.match(/^(\s+)[A-Za-z0-9_-]+:/mu);
127
+ const indent = child?.[1] || " ";
128
+ const match = source.match(new RegExp(`^${indent}if:\\s*(.*)$`, "mu"));
129
+ if (!match)
130
+ return `${indent}if: \${{ inputs.universal-request-json == '' }}\n`;
131
+ const suffix = match[1].trim();
132
+ if (suffix === ">-" || suffix === "|") {
133
+ const start = match.index + match[0].length + 1;
134
+ const tail = source.slice(start);
135
+ const endMatch = tail.match(/^ [A-Za-z0-9_-]+:/mu);
136
+ const end = endMatch ? start + endMatch.index : source.length;
137
+ const raw = source.slice(start, end).trim();
138
+ const inner = raw
139
+ .replace(/^\$\{\{\s*/u, "")
140
+ .replace(/\s*\}\}$/u, "")
141
+ .split("\n")
142
+ .map((line) => line.trim())
143
+ .filter(Boolean)
144
+ .join("\n ");
145
+ if (!inner) fail(`${relative}#${jobId} has an empty multiline if`);
146
+ return {
147
+ start: match.index,
148
+ end,
149
+ value: `${indent}if: >-\n${indent} \${{\n${indent} inputs.universal-request-json == '' &&\n${indent} (\n${indent} ${inner}\n${indent} )\n${indent} }}\n`,
150
+ };
151
+ }
152
+ const inner = suffix.startsWith("${{")
153
+ ? suffix.replace(/^\$\{\{\s*/u, "").replace(/\s*\}\}$/u, "")
154
+ : suffix;
155
+ return {
156
+ start: match.index,
157
+ end:
158
+ match.index +
159
+ match[0].length +
160
+ (source[match.index + match[0].length] === "\n" ? 1 : 0),
161
+ value: `${indent}if: \${{ inputs.universal-request-json == '' && (${inner}) }}\n`,
162
+ };
163
+ }
164
+
165
+ function guardCompatibilityJobs(source, relative) {
166
+ const jobs = source.match(/^jobs:\s*$/mu);
167
+ if (!jobs) fail(`${relative} has no jobs mapping`);
168
+ const bodyStart = jobs.index + jobs[0].length + 1;
169
+ const body = source.slice(bodyStart);
170
+ const headers = [...body.matchAll(/^ ([A-Za-z0-9_-]+):\s*$/gmu)];
171
+ if (headers.length === 0) fail(`${relative} has no jobs`);
172
+ let rewritten = body;
173
+ for (let index = headers.length - 1; index >= 0; index -= 1) {
174
+ const header = headers[index];
175
+ if (header[1] === "universal-bootstrap") continue;
176
+ const start = header.index + header[0].length + 1;
177
+ const end = headers[index + 1]?.index ?? body.length;
178
+ const job = body.slice(start, end);
179
+ if (job.includes("inputs.universal-request-json == ''")) continue;
180
+ const condition = conditionExpression(job, relative, header[1]);
181
+ if (typeof condition === "string") {
182
+ rewritten = `${rewritten.slice(0, start)}${condition}${rewritten.slice(start)}`;
183
+ } else {
184
+ rewritten = `${rewritten.slice(0, start + condition.start)}${condition.value}${rewritten.slice(start + condition.end)}`;
185
+ }
186
+ }
187
+ const withGuards = `${source.slice(0, bodyStart)}${rewritten}`;
188
+ return withGuards.includes(" universal-bootstrap:\n")
189
+ ? withGuards
190
+ : `${withGuards.slice(0, bodyStart)}${bootstrapJob}${withGuards.slice(bodyStart)}`;
191
+ }
192
+
193
+ function addRuntimeBootstrapDependencies(source, relative) {
194
+ if (
195
+ relative !== ".github/workflows/.build.yml" ||
196
+ source.includes(".buildchain/workflow-shell/scripts/github-output.mjs\n")
197
+ )
198
+ return source;
199
+ const anchor =
200
+ " .buildchain/workflow-shell/scripts/build-contract-core.mjs\n";
201
+ return source.replace(
202
+ anchor,
203
+ `${anchor} .buildchain/workflow-shell/scripts/github-output.mjs\n`,
204
+ );
205
+ }
206
+
207
+ function applyPublicationFacadePatches(source, relative) {
208
+ const document = JSON.parse(
209
+ fs.readFileSync(
210
+ path.join(root, "architecture/publication-facade-patches.json"),
211
+ "utf8",
212
+ ),
213
+ );
214
+ const patch = document.facades.find((entry) => entry.workflow === relative);
215
+ if (!patch) return source;
216
+ const digest = (value) =>
217
+ crypto.createHash("sha256").update(value).digest("hex");
218
+ if (digest(source) === patch.afterSha256) return source;
219
+ if (digest(source) !== patch.beforeSha256)
220
+ fail(`${relative}: publication facade source drift`);
221
+ for (const { before, after } of patch.replacements) {
222
+ if (source.split(before).length !== 2)
223
+ fail(`${relative}: ambiguous publication patch`);
224
+ source = source.replace(before, () => after);
225
+ }
226
+ if (digest(source) !== patch.afterSha256)
227
+ fail(`${relative}: publication facade result drift`);
228
+ return source;
229
+ }
230
+
231
+ function inheritPublicationProviderAuthority(source, relative) {
232
+ if (relative !== ".github/workflows/.release-candidate-promote.yml")
233
+ return source;
234
+ return source
235
+ .replace(
236
+ "permissions:\n contents: read\n",
237
+ "# Provider authority is inherited from the explicit caller envelope.\n",
238
+ )
239
+ .replace(
240
+ " permissions:\n actions: read\n checks: write\n contents: write\n id-token: write\n pull-requests: write\n",
241
+ " # Provider authority is inherited from the explicit caller envelope.\n",
242
+ );
243
+ }
244
+
245
+ export function migrateUniversalWorkflowFacade(source, relative) {
246
+ return rewriteImplementationReferences(rewriteRepositoryWorkflowPaths(
247
+ root,
248
+ inheritPublicationProviderAuthority(
249
+ applyPublicationFacadePatches(
250
+ guardCompatibilityJobs(
251
+ addUniversalInput(
252
+ addRuntimeBootstrapDependencies(source, relative),
253
+ relative,
254
+ ),
255
+ relative,
256
+ ),
257
+ relative,
258
+ ),
259
+ relative,
260
+ ),
261
+ ));
262
+ }
263
+
264
+ function verify(source, relative) {
265
+ for (const snippet of [
266
+ " universal-request-json:\n",
267
+ " universal-bootstrap:\n",
268
+ "uses: ./.github/workflows/bootstrap.yml",
269
+ ]) {
270
+ if (!source.includes(snippet))
271
+ fail(`${relative} is missing ${snippet.trim()}`);
272
+ }
273
+ const jobs = source.slice(source.search(/^jobs:\s*$/mu));
274
+ const headers = [...jobs.matchAll(/^ ([A-Za-z0-9_-]+):\s*$/gmu)];
275
+ for (let index = 0; index < headers.length; index += 1) {
276
+ const header = headers[index];
277
+ if (header[1] === "universal-bootstrap") continue;
278
+ const end = headers[index + 1]?.index ?? jobs.length;
279
+ const block = jobs.slice(header.index, end);
280
+ if (!block.includes("inputs.universal-request-json == ''"))
281
+ fail(`${relative}#${header[1]} can overlap universal execution`);
282
+ }
283
+ if (!isMutableFacade(relative)) {
284
+ const expected = migrateUniversalWorkflowFacade(
285
+ frozenFacadeSource(relative),
286
+ relative,
287
+ );
288
+ if (source !== expected)
289
+ fail(
290
+ `${relative} differs from the exact generated facade rooted at ${sourceRevision()}`,
291
+ );
292
+ }
293
+ }
294
+
295
+ function laneBudget({ laneId, authorityClass, triggerClass, minutes, metric }) {
296
+ return {
297
+ laneId,
298
+ authorityClass,
299
+ triggerClass,
300
+ concurrencyPolicy: { mode: "none", cancelInProgress: false },
301
+ expectedRunnerMinutes: minutes,
302
+ cancellationBehavior: "finish-started",
303
+ sloImpact: {
304
+ mergeCritical: false,
305
+ metric,
306
+ expectedContributionSeconds: 0,
307
+ rationale:
308
+ "The opt-in universal path preserves the default compatibility lane and executes only an exact admitted runtime.",
309
+ },
310
+ };
311
+ }
312
+
313
+ function updateLaneBudgets() {
314
+ const policy = JSON.parse(fs.readFileSync(laneBudgetPath, "utf8"));
315
+ const mixed = new Set([
316
+ ".github/workflows/release-governance-reconcile.yml",
317
+ ".github/workflows/v4-adopter-delivery.yml",
318
+ ]);
319
+ const facadeLanes = activeFacadePaths().map(
320
+ (relative) => `${relative}#universal-bootstrap`,
321
+ );
322
+ policy.declarationFamilies = [
323
+ {
324
+ ...laneBudget({
325
+ laneId: "",
326
+ authorityClass: "governed-delegation",
327
+ triggerClass: "reusable",
328
+ minutes: 60,
329
+ metric: "opt-in exact-candidate execution latency",
330
+ }),
331
+ laneIds: facadeLanes.filter(
332
+ (laneId) => !mixed.has(laneId.split("#", 1)[0]),
333
+ ),
334
+ },
335
+ {
336
+ ...laneBudget({
337
+ laneId: "",
338
+ authorityClass: "governed-delegation",
339
+ triggerClass: "mixed",
340
+ minutes: 60,
341
+ metric: "mixed-trigger exact-candidate execution latency",
342
+ }),
343
+ laneIds: facadeLanes.filter((laneId) =>
344
+ mixed.has(laneId.split("#", 1)[0]),
345
+ ),
346
+ },
347
+ ].map(({ laneId: _laneId, ...family }) => family);
348
+ const universalLaneIds = new Set([
349
+ ".github/workflows/bootstrap.yml#admit",
350
+ ".github/workflows/bootstrap.yml#execute",
351
+ ".github/workflows/bootstrap.yml#settle",
352
+ ".github/workflows/universal-bootstrap-recovery.yml#recovery-admit",
353
+ ".github/workflows/universal-bootstrap-recovery.yml#recovery-execute",
354
+ ".github/workflows/universal-bootstrap-recovery.yml#recovery-settle",
355
+ ".github/workflows/universal-bootstrap-dogfood.yml#public-bootstrap",
356
+ ".github/workflows/universal-bootstrap-dogfood.yml#prepare",
357
+ ".github/workflows/universal-bootstrap-dogfood.yml#primary-conformance",
358
+ ".github/workflows/universal-bootstrap-dogfood.yml#recovery-conformance",
359
+ ".github/workflows/universal-bootstrap-dogfood.yml#primary-alpha",
360
+ ".github/workflows/universal-bootstrap-dogfood.yml#recovery-alpha",
361
+ ".github/workflows/universal-bootstrap-dogfood.yml#primary-stable",
362
+ ".github/workflows/universal-bootstrap-dogfood.yml#recovery-stable",
363
+ ".github/workflows/universal-bootstrap-dogfood.yml#reconcile",
364
+ ]);
365
+ policy.declarations = policy.declarations.filter(
366
+ ({ laneId }) => !universalLaneIds.has(laneId),
367
+ );
368
+ policy.declarations.push(
369
+ laneBudget({
370
+ laneId: ".github/workflows/bootstrap.yml#admit",
371
+ authorityClass: "evidence",
372
+ triggerClass: "reusable",
373
+ minutes: 10,
374
+ metric: "exact-candidate admission latency",
375
+ }),
376
+ laneBudget({
377
+ laneId: ".github/workflows/bootstrap.yml#execute",
378
+ authorityClass: "governed-delegation",
379
+ triggerClass: "reusable",
380
+ minutes: 60,
381
+ metric: "exact-candidate execution latency",
382
+ }),
383
+ laneBudget({
384
+ laneId: ".github/workflows/bootstrap.yml#settle",
385
+ authorityClass: "evidence",
386
+ triggerClass: "reusable",
387
+ minutes: 10,
388
+ metric: "universal terminal settlement latency",
389
+ }),
390
+ laneBudget({
391
+ laneId:
392
+ ".github/workflows/universal-bootstrap-recovery.yml#recovery-admit",
393
+ authorityClass: "evidence",
394
+ triggerClass: "reusable",
395
+ minutes: 10,
396
+ metric: "consumer-owned exact-candidate admission latency",
397
+ }),
398
+ laneBudget({
399
+ laneId:
400
+ ".github/workflows/universal-bootstrap-recovery.yml#recovery-execute",
401
+ authorityClass: "governed-delegation",
402
+ triggerClass: "reusable",
403
+ minutes: 60,
404
+ metric: "consumer-owned exact-candidate execution latency",
405
+ }),
406
+ laneBudget({
407
+ laneId:
408
+ ".github/workflows/universal-bootstrap-recovery.yml#recovery-settle",
409
+ authorityClass: "evidence",
410
+ triggerClass: "reusable",
411
+ minutes: 10,
412
+ metric: "consumer-owned terminal settlement latency",
413
+ }),
414
+ laneBudget({
415
+ laneId: ".github/workflows/universal-bootstrap-dogfood.yml#prepare",
416
+ authorityClass: "evidence",
417
+ triggerClass: "mixed",
418
+ minutes: 10,
419
+ metric: "Train-first self-dogfood admission latency",
420
+ }),
421
+ ...[
422
+ "primary-conformance",
423
+ "recovery-conformance",
424
+ "primary-alpha",
425
+ "recovery-alpha",
426
+ "primary-stable",
427
+ "recovery-stable",
428
+ ].map((job) =>
429
+ laneBudget({
430
+ laneId: `.github/workflows/universal-bootstrap-dogfood.yml#${job}`,
431
+ authorityClass: "governed-delegation",
432
+ triggerClass: "mixed",
433
+ minutes: 60,
434
+ metric: "Train-first exact-candidate self-dogfood latency",
435
+ }),
436
+ ),
437
+ laneBudget({
438
+ laneId: ".github/workflows/universal-bootstrap-dogfood.yml#reconcile",
439
+ authorityClass: "evidence",
440
+ triggerClass: "mixed",
441
+ minutes: 10,
442
+ metric: "primary and recovery equivalence latency",
443
+ }),
444
+ );
445
+ fs.writeFileSync(laneBudgetPath, `${JSON.stringify(policy, null, 2)}\n`);
446
+ }
447
+
448
+ function main() {
449
+ const check = process.argv.includes("--check");
450
+ const fresh = process.argv.includes("--fresh");
451
+ materializeSourceRevision();
452
+ if (check) {
453
+ if (
454
+ fs.readFileSync(recoveryWorkflowPath, "utf8") !==
455
+ fs.readFileSync(recoveryTemplatePath, "utf8")
456
+ )
457
+ fail(
458
+ "consumer recovery workflow differs from its pre-positioned template",
459
+ );
460
+ } else {
461
+ writeWorkflowSource(
462
+ root,
463
+ path.relative(root, recoveryWorkflowPath),
464
+ fs.readFileSync(recoveryTemplatePath, "utf8"),
465
+ );
466
+ }
467
+ for (const relative of activeFacadePaths()) {
468
+ const current = currentWorkflowPath(root, relative);
469
+ const target = path.join(root, current);
470
+ const source = fresh
471
+ ? frozenFacadeSource(relative)
472
+ : fs.readFileSync(target, "utf8");
473
+ if (check) verify(source, relative);
474
+ else
475
+ writeWorkflowSource(
476
+ root,
477
+ current,
478
+ migrateUniversalWorkflowFacade(source, relative),
479
+ );
480
+ }
481
+ if (!check) {
482
+ contract.bootstrapGovernedWorkflows = [
483
+ contract.bootstrap.publicWorkflow,
484
+ ...activeFacadePaths(),
485
+ ].sort();
486
+ contract.migration.compatibilityFacades = "generated-dual-path";
487
+ fs.writeFileSync(contractPath, `${JSON.stringify(contract, null, 2)}\n`);
488
+ updateLaneBudgets();
489
+ process.stdout.write(
490
+ `${JSON.stringify({ migrated: activeFacadePaths().length })}\n`,
491
+ );
492
+ }
493
+ }
494
+
495
+ const isMain =
496
+ process.argv[1] &&
497
+ path.resolve(process.argv[1]) === fileURLToPath(import.meta.url);
498
+ if (isMain) main();
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env node
2
+ import fs from "node:fs";
3
+ import path from "node:path";
4
+ import {
5
+ readWorkflowTaxonomy,
6
+ renderWorkflowCatalog,
7
+ TAXONOMY_DOC,
8
+ workflowPath,
9
+ writeWorkflowSource,
10
+ } from "./workflow-taxonomy.mjs";
11
+
12
+ const root = process.cwd();
13
+ const policy = readWorkflowTaxonomy(root);
14
+ if (!policy) throw new Error("workflow taxonomy is missing");
15
+ for (const entry of policy.entries) {
16
+ writeWorkflowSource(
17
+ root,
18
+ workflowPath(entry),
19
+ fs.readFileSync(path.join(root, workflowPath(entry)), "utf8"),
20
+ );
21
+ }
22
+ fs.writeFileSync(path.join(root, TAXONOMY_DOC), renderWorkflowCatalog(policy));
23
+ process.stdout.write(
24
+ `Generated ${policy.entries.length} canonical workflow declarations and their exact compatibility projections.\n`,
25
+ );
@@ -0,0 +1,31 @@
1
+ import crypto from "node:crypto";
2
+ import fs from "node:fs";
3
+
4
+ function githubOutputRecord(key, value) {
5
+ const normalized = String(value ?? "");
6
+ if (!/[\r\n]/u.test(normalized)) return `${key}=${normalized}\n`;
7
+ const valueLines = normalized.split(/\r\n|\r|\n/u);
8
+ let delimiter = `BUILDCHAIN_OUTPUT_${crypto
9
+ .createHash("sha256")
10
+ .update(`${key}\0${normalized}`)
11
+ .digest("hex")}`;
12
+ while (valueLines.includes(delimiter)) delimiter += "_";
13
+ const separator = normalized.endsWith("\n") ? "" : "\n";
14
+ return `${key}<<${delimiter}\n${normalized}${separator}${delimiter}\n`;
15
+ }
16
+
17
+ export function writeGitHubOutputs(outputs) {
18
+ const outputPath = process.env.GITHUB_OUTPUT;
19
+ if (!outputPath) {
20
+ for (const [key, value] of Object.entries(outputs)) {
21
+ console.log(`${key}=${value}`);
22
+ }
23
+ return;
24
+ }
25
+ fs.appendFileSync(
26
+ outputPath,
27
+ Object.entries(outputs)
28
+ .map(([key, value]) => githubOutputRecord(key, value))
29
+ .join(""),
30
+ );
31
+ }
@@ -3,7 +3,7 @@
3
3
  import fs from "node:fs";
4
4
  import path from "node:path";
5
5
  import { pathToFileURL } from "node:url";
6
- import { architectureList, architectureShow } from "./v4-architecture.mjs";
6
+ import { architectureList, architectureShow } from "./architecture.mjs";
7
7
 
8
8
  const MAX_REQUEST_BYTES = 8 * 1024 * 1024;
9
9
  const SUPPORTED_CAPABILITIES = Object.freeze([
@@ -0,0 +1,25 @@
1
+ import fs from "node:fs";
2
+
3
+ const policy = JSON.parse(
4
+ fs.readFileSync(
5
+ new URL("../architecture/implementation-naming.json", import.meta.url),
6
+ "utf8",
7
+ ),
8
+ );
9
+
10
+ // Project frozen workflow sources through the explicit implementation relocation.
11
+ // Historical source commits and published wire identities stay unchanged.
12
+ export function rewriteImplementationReferences(source) {
13
+ for (const [before, after] of Object.entries({
14
+ ...policy.pathMigrations,
15
+ ...Object.fromEntries(
16
+ Object.entries(policy.ephemeralPathMigrations).filter(([before]) =>
17
+ before.startsWith(".buildchain/"),
18
+ ),
19
+ ),
20
+ }).sort(([a], [b]) => b.length - a.length))
21
+ source = source.replaceAll(before, after);
22
+ for (const [before, after] of Object.entries(policy.symbolMigrations))
23
+ source = source.replace(new RegExp(`\\b${before}\\b`, "gu"), after);
24
+ return source;
25
+ }
@@ -366,7 +366,7 @@ jobs:
366
366
  }
367
367
 
368
368
  function workflowYaml({ type, runnerPreset, artifactName }) {
369
- return `${nextDevelopmentWorkflowHeader()}# Buildchain v4 lifecycle checkpoints are governed by architecture/v4-platform-stage-checkpoints.json.
369
+ return `${nextDevelopmentWorkflowHeader()}# Buildchain v4 lifecycle checkpoints are governed by architecture/platform-stage-checkpoints.json.
370
370
  # Do not add undeclared runner-only inputs, outputs, environment, or provider effects.
371
371
  # Commit both .buildchain/contract-lock.json and .buildchain/alpha-contract-lock.json.
372
372
  # Persist only @v4 or @v4-alpha; pass temporary train/SHA runtimes through workflow_dispatch.
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env node
2
+ import { projectWorkflowIdentities } from "./workflow-taxonomy.mjs";
2
3
 
3
4
  import fs from "node:fs";
4
5
  import path from "node:path";
@@ -280,10 +281,17 @@ function collectMaintainabilityMetrics({
280
281
  analyzeJavaScript(file, readTrackedFile(root, file, revision)),
281
282
  ]),
282
283
  );
284
+ const physicalWorkflows = workflowFiles.map((file) => ({
285
+ path: file,
286
+ text: readTrackedFile(root, file, revision),
287
+ }));
288
+ const logicalWorkflows = revision
289
+ ? physicalWorkflows
290
+ : projectWorkflowIdentities(root, physicalWorkflows);
283
291
  const workflowMetrics = Object.fromEntries(
284
- workflowFiles.map((file) => [
285
- file,
286
- analyzeWorkflow(file, readTrackedFile(root, file, revision)),
292
+ logicalWorkflows.map((entry) => [
293
+ entry.path,
294
+ analyzeWorkflow(entry.path, entry.text),
287
295
  ]),
288
296
  );
289
297
  const sumLines = (entries) =>
@@ -316,8 +324,11 @@ function collectMaintainabilityMetrics({
316
324
  ),
317
325
  testFiles: testFiles.length,
318
326
  testLines: sumLines(testFiles),
319
- workflowFiles: workflowFiles.length,
320
- workflowLines: sumLines(workflowFiles),
327
+ workflowFiles: logicalWorkflows.length,
328
+ workflowLines: logicalWorkflows.reduce(
329
+ (total, entry) => total + lineCount(entry.text),
330
+ 0,
331
+ ),
321
332
  documentationFiles: documentationFiles.length,
322
333
  documentationLines: sumLines(documentationFiles),
323
334
  generatedFiles: generatedFiles.length,