@kungfu-tech/buildchain 4.1.5-alpha.0 → 4.1.6-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.
- package/architecture/maintainability-policy.json +5 -5
- package/architecture/release-topology.json +3 -1
- package/dist/site/buildchain-contract.json +2 -2
- package/dist/site/buildchain-site.json +3 -3
- package/dist/site/kfd-claims.json +2 -2
- package/dist/site/kfd-upstream-aggregate.json +1 -1
- package/dist/site/page-registry.json +2 -2
- package/dist/site/public-surface-audit.json +2 -2
- package/dist/site/publication-registry.json +1 -1
- package/dist/site/site-manifest.json +1 -1
- package/dist/site/workflow-registry.json +1 -1
- package/docs/workflow-catalog.md +1 -1
- package/package.json +1 -1
- package/packages/core/consumer/compatibility-promotion-workflows.js +43 -0
- package/packages/core/consumer/compatibility-workflows.js +197 -0
- package/packages/core/workflow/workflow-taxonomy.mjs +45 -2
|
@@ -26,17 +26,17 @@
|
|
|
26
26
|
},
|
|
27
27
|
"repositoryBudgets": {
|
|
28
28
|
"baselineRevision": "9569f69c2cb609372b8a3d65ce5dec8fb7b34a84",
|
|
29
|
-
"maxHandMaintainedSourceFiles":
|
|
30
|
-
"maxHandMaintainedSourceLines":
|
|
29
|
+
"maxHandMaintainedSourceFiles": 1484,
|
|
30
|
+
"maxHandMaintainedSourceLines": 219417,
|
|
31
31
|
"maxWorkflowFiles": 44,
|
|
32
32
|
"maxWorkflowLines": 8029,
|
|
33
|
-
"latestTransition": "
|
|
34
|
-
"latestTransitionRationale": "Charge
|
|
33
|
+
"latestTransition": "Admit byte-verified historical workflow registries before consumers adopt retained entries.",
|
|
34
|
+
"latestTransitionRationale": "Charge two bounded registry/renderer modules and 275 measured source lines; retain all workflow, action, structural, debt and exception ceilings. Publish the reader before the historical entry inventory so the existing protected merge-group runtime can validate the upgrade.",
|
|
35
35
|
"rationale": "Bounded modules separate candidate, evidence, native proof and execution, canonical failure verification, closed-set execution transfer, process-boundary verification, Warrant state and qualification, authority state, qualification, Landing acquisition, verified-attempt admission, Landing settlement and fence validation, provider attempt and heartbeat readback, sealed terminal evidence, hosted heartbeat, resume, store, options, command-specific adapters, and CLI orchestration responsibilities. The protected delivery workflow gives candidate and seal jobs no provider write credential, recursively rejects transfer drift, scopes every transfer artifact to the exact provider run attempt, chains every durable heartbeat state and receipt root on a distinct hosted runner domain, and permits qualification or exact failure settlement only after the finalizer verifies live jobs and the latest durable authority state. Public Landing admission and heartbeat always perform non-injectable fresh exact-attempt provider readback, tolerate only a not-yet-materialized seal job while retaining exact native and duplicate-job rejection, and heartbeat-loss coordination never invokes GitHub's run-scoped cancellation API where a successor rerun could race. The hosted process boundary anchors trust in the kernel-resolved versioned Runner.Worker path while accepting an equivalent argv-zero spelling with the same basename; its public boundary marker is allowed only at the one exact non-secret value, so a forged value under the same credential-like name still fails closed. The credentialless transfer seal validates the rooted native reuse decision against the Warrant-bound source, closure, dependency, toolchain, environment and command inputs; qualifiedBase stays in the proof and decision where it is rooted and later independently rechecked, rather than being assumed on the Warrant schema. V2 mutation cannot initialize a second empty authority beside a legacy ref: migration reads and roots the canonical live v1 ref, rechecks it, applies the explicit configured v2 policy, and atomically replaces its bytes through one expected-old non-force update, so old v1 controllers fail closed while the prior commit remains immutable history. Candidate ancestry classifies the GitHub artifact runtime token as credential authority. Every Landing settlement, including an unexpired fence, requires product-owned terminal readback. Terminal cleanup reads the immutable historical attempt, derives workflow and hosted Landing job identity from live run data, reads the exact protected ref head and compares containment against that immutable SHA, and seals merged only when the admitted merge-group head is contained by that protected base; a later different-head merge settles the old attempt as dequeued. Terminal normalization preserves transfer, finalizer boundary, native and seal job, admitted provider attempt, protected-base head, containment result, and terminal readback coordinates. The public reusable workflow truthfully retains its single-flight v1 authority without advertising v2 migration, while bounded v2 remains a separate opt-in CLI, Node API, and schema contract; the tracked self-caller stays on public v4-alpha with matching stable and alpha locks, and transient train selection is dispatch-only. Next-development parity adds one versioned transition authority, one durable controller, one bounded reservation adapter, and pure public-contract recovery evidence while retaining the existing thin floating-channel callers byte-for-byte. The floating-consumer gate reuses the existing contract-world evaluator so SHA drift passes only under the selected lock's compatibility policy, breaking surface drift still fails closed, and external certification reconstructs the receipt from the observed workflow SHA rather than the lock's historical evidence SHA. Tail reseal adds no Stage Capsule effect or general rebuild authority: it verifies the exact retained four-platform bytes, admits one known macOS tail failure through live provider readback, fences signing and finalization to explicit credentials and Warrant identity, and requires standard candidate Passport plus provider and protected readback. Compatibility Facts parity isolates canonical encoding, temporal verification, lifecycle validation, fixture projection, public authority projection, and CLI adaptation into bounded modules; legacy digest and proof arrays are derived only from exact current Fact lineage. Publication Rehearsal adds no production release authority: the content-addressed capsule contract binds source, candidate, manifest, config, canonical data-only provider bindings, provider policy, observations and core version separately from filesystem, runtime and rehearsal-only provider authority; simulate, replay and explicitly authorized provider rehearsal all reuse the release-tail planner, while same-commit local dogfood resolves the new reusable contract and exact current runtime before external callers remain on floating v4-alpha. Cross-runtime candidate recovery preserves original runtime and provider roots and creates resume lineage only after exact public ref, tag, ancestry, npm version and integrity readback. Adopter Delivery restores the reviewed public v3 gate, drivers, Passport binding, N-1 bootstrap and exact archive loader through one public v4 surface while keeping provider and release authority explicit non-claims. Floating Alpha bootstrap uses only the existing exact resolver and protected Alpha private shell to move an otherwise stale floating shell, retains public v4 stable promotion, and removes itself after protected readback. CI lane change-budget enforcement adds a bounded parser, evaluator, guard, and tests without creating another merge authority. Minimal consumer contract adds exactly seven bounded contract modules, one generated-contract gate and six product build/test example sources; the source-file ceiling increases by fourteen for this reviewed feature slice. Existing per-file, function, complexity and debt limits are unchanged. The final readable template sources require exact source-line and total-automation ceilings of 203394 and 224451 respectively; this charges all generated example sources rather than hiding them from measurement. Qualified landing status projection adds 51 source lines and four internal action-contract lines within existing job permissions; per-file, function, complexity and exception budgets are unchanged. Delivery scheduling preserves its exact queued or running provider owner before Warrant acquisition, adding 31 measured source lines within the existing structural budgets.",
|
|
36
36
|
"governance": "legacy-debt-sunset-2026q4",
|
|
37
37
|
"maxActionDefinitions": 283,
|
|
38
38
|
"maxActionDefinitionLines": 12399,
|
|
39
|
-
"maxAutomationImplementationLines":
|
|
39
|
+
"maxAutomationImplementationLines": 238995
|
|
40
40
|
},
|
|
41
41
|
"sourceBudgets": {
|
|
42
42
|
"newFileLines": 600,
|
|
@@ -119,6 +119,8 @@
|
|
|
119
119
|
"packages/core/build/stage-capsule.js",
|
|
120
120
|
"packages/core/consumer/buildchain-channel-identity.js",
|
|
121
121
|
"packages/core/consumer/buildchain-config.js",
|
|
122
|
+
"packages/core/consumer/compatibility-promotion-workflows.js",
|
|
123
|
+
"packages/core/consumer/compatibility-workflows.js",
|
|
122
124
|
"packages/core/consumer/contract/entries.js",
|
|
123
125
|
"packages/core/consumer/contract/identity.js",
|
|
124
126
|
"packages/core/consumer/contract/inspection.js",
|
|
@@ -407,7 +409,7 @@
|
|
|
407
409
|
"packages/core/workflow/pipeline/web-status.js",
|
|
408
410
|
"packages/core/workflow/workflow-taxonomy.mjs"
|
|
409
411
|
],
|
|
410
|
-
"root": "sha256:
|
|
412
|
+
"root": "sha256:6d36d0b94d4b25f68e65afdea4ff8ca30eeaaf0c6ef16982473b1024d3443ac5"
|
|
411
413
|
},
|
|
412
414
|
"rustWasmAuthority": {
|
|
413
415
|
"loader": "packages/core/runtime/domain-wasm.js",
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"product": {
|
|
5
5
|
"name": "Buildchain",
|
|
6
6
|
"package": "@kungfu-tech/buildchain",
|
|
7
|
-
"version": "4.1.
|
|
7
|
+
"version": "4.1.6-alpha.0",
|
|
8
8
|
"repository": "https://github.com/kungfu-systems/buildchain"
|
|
9
9
|
},
|
|
10
10
|
"majorLine": "v4",
|
|
@@ -2428,5 +2428,5 @@
|
|
|
2428
2428
|
"compatibilityFactCutRoot": "sha256:58f33e498596505a26b6fc3c7ae5acef847ff699eee6c7e17a7b318a40bdf0d6",
|
|
2429
2429
|
"compatibilityProofRegistryRoot": "sha256:2f6477405c7891b754b33ad6515d55618bd320e7cdc59330d7cc645e17201e72",
|
|
2430
2430
|
"compatibilityDigest": "sha256:808c03915bf090ded3082642ffc5163e15bdd090b629344df9bfb65544041dd3",
|
|
2431
|
-
"contractDigest": "sha256:
|
|
2431
|
+
"contractDigest": "sha256:c17e0bce24c8501186084a6148d0c290491d93f59ae5e3ae9267d63484f83523"
|
|
2432
2432
|
}
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
},
|
|
38
38
|
"package": {
|
|
39
39
|
"name": "@kungfu-tech/buildchain",
|
|
40
|
-
"version": "4.1.
|
|
40
|
+
"version": "4.1.6-alpha.0",
|
|
41
41
|
"versionSource": "package.json#version"
|
|
42
42
|
},
|
|
43
43
|
"source": {
|
|
@@ -5473,7 +5473,7 @@
|
|
|
5473
5473
|
],
|
|
5474
5474
|
"maturity": "stable",
|
|
5475
5475
|
"sourcePath": "docs/workflow-catalog.md",
|
|
5476
|
-
"digest": "sha256:
|
|
5476
|
+
"digest": "sha256:99b20bc39eaf03df2970e04a6a0695e514a0ef263c18ad1e6e633da4b625713e",
|
|
5477
5477
|
"headings": [
|
|
5478
5478
|
{
|
|
5479
5479
|
"level": 1,
|
|
@@ -5496,7 +5496,7 @@
|
|
|
5496
5496
|
"anchor": "self"
|
|
5497
5497
|
}
|
|
5498
5498
|
],
|
|
5499
|
-
"markdown": "---\nstatus: active\nperiod: ongoing\ntheme: workflow-taxonomy\ndoc_type: technical-reference\nsource_level: local-files\nconfidence: high\nsensitivity: public\nevidence_grade: B\nreview_state: unreviewed\nlast_reviewed: 2026-09-09\nai_provenance:\n model_family: GPT-6\n product: Codex\n generated_at: 2026-09-09\n visible_context: Canonical Buildchain workflow ownership and source files\n invisible_context_boundary: No private credentials or unpublished consumer state inspected\n---\n\n# Workflow catalog\n\nGenerated from `architecture/workflow-taxonomy.json`. Every workflow has one canonical implementation
|
|
5499
|
+
"markdown": "---\nstatus: active\nperiod: ongoing\ntheme: workflow-taxonomy\ndoc_type: technical-reference\nsource_level: local-files\nconfidence: high\nsensitivity: public\nevidence_grade: B\nreview_state: unreviewed\nlast_reviewed: 2026-09-09\nai_provenance:\n model_family: GPT-6\n product: Codex\n generated_at: 2026-09-09\n visible_context: Canonical Buildchain workflow ownership and source files\n invisible_context_boundary: No private credentials or unpublished consumer state inspected\n---\n\n# Workflow catalog\n\nGenerated from `architecture/workflow-taxonomy.json`. Every workflow has one canonical implementation. Historical entry contracts declared in an optional `architecture/consumer-upgrade.json` registry must match their generated canonical implementations byte-for-byte, including job contexts, inputs, outputs, permissions and publisher identities.\n\nThe two public workflows own normal pipeline execution and exact-attempt recovery. Component workflows are internal runtime implementation, including once-only setup and the dispatch signing service; consumers do not wire these components. Self workflows are the generated consumer pair. Actions own execution steps; JS adapters and Rust/WASM own implementation.\n\nNames use `public-ops-pipeline.yml`, `public-ops-recover.yml`, internal `.<category>-<purpose>.yml`, and the generated self callers `buildchain.yml` and `buildchain-recover.yml`. Categories are `build`, `release`, and `ops`; the internal build engine retains `.build.yml`.\n\nRegister ownership before adding a workflow. `pnpm run check:workflows` validates source, calls, required CI integration and independent review ownership. `pnpm run generate:workflows` regenerates this catalog.\n\n## public\n\n| Workflow | Category | Invocation | Status | Purpose |\n| --- | --- | --- | --- | --- |\n| [public-ops-pipeline.yml](../.github/workflows/public-ops-pipeline.yml) | ops | reusable | active | Buildchain pipeline |\n| [public-ops-recover.yml](../.github/workflows/public-ops-recover.yml) | ops | reusable | active | Buildchain recovery |\n\n## component\n\n| Workflow | Category | Invocation | Status | Purpose |\n| --- | --- | --- | --- | --- |\n| [.build-adopter-qualification.yml](../.github/workflows/.build-adopter-qualification.yml) | build | reusable | active | V4 Adopter Delivery |\n| [.build-candidate.yml](../.github/workflows/.build-candidate.yml) | build | reusable | active | Buildchain Channel Build |\n| [.build-check.yml](../.github/workflows/.build-check.yml) | build | reusable | active | Buildchain Check |\n| [.build-demo-adapter.yml](../.github/workflows/.build-demo-adapter.yml) | build | reusable | active | Buildchain Auditable Demo |\n| [.build-demo.yml](../.github/workflows/.build-demo.yml) | build | reusable | active | Buildchain Declarative Binary Auditable Demo |\n| [.build-gate-profile.yml](../.github/workflows/.build-gate-profile.yml) | build | reusable | active | Buildchain Shifu Gate Profile |\n| [.build-publication.yml](../.github/workflows/.build-publication.yml) | build | reusable | active | Buildchain Publication Artifact |\n| [.build-stage-capsule-canary.yml](../.github/workflows/.build-stage-capsule-canary.yml) | build | reusable | active | V4 Stage Capsule Canary |\n| [.build.yml](../.github/workflows/.build.yml) | build | reusable | active | Buildchain Build |\n| [.ops-alpha-candidate-patrol.yml](../.github/workflows/.ops-alpha-candidate-patrol.yml) | ops | reusable | active | Buildchain Dev to Alpha Candidate Patrol |\n| [.ops-bootstrap.yml](../.github/workflows/.ops-bootstrap.yml) | ops | reusable | active | Buildchain Universal Bootstrap |\n| [.ops-dev-auto-merge.yml](../.github/workflows/.ops-dev-auto-merge.yml) | ops | reusable | active | Dev PR Auto Merge |\n| [.ops-dev-qualification-patrol.yml](../.github/workflows/.ops-dev-qualification-patrol.yml) | ops | reusable | active | Buildchain Dev Qualification Patrol |\n| [.ops-git-sync.yml](../.github/workflows/.ops-git-sync.yml) | ops | reusable | active | sync remote git |\n| [.ops-housekeeping.yml](../.github/workflows/.ops-housekeeping.yml) | ops | reusable | active | Engineering Housekeeper |\n| [.ops-observed-evidence.yml](../.github/workflows/.ops-observed-evidence.yml) | ops | reusable | active | Patrol Observed Evidence |\n| [.ops-patrol-daily.yml](../.github/workflows/.ops-patrol-daily.yml) | ops | reusable | active | Buildchain Patrol Daily |\n| [.ops-patrol-monthly.yml](../.github/workflows/.ops-patrol-monthly.yml) | ops | reusable | active | Buildchain Patrol Monthly |\n| [.ops-patrol-weekly.yml](../.github/workflows/.ops-patrol-weekly.yml) | ops | reusable | active | Buildchain Patrol Weekly |\n| [.ops-patrol.yml](../.github/workflows/.ops-patrol.yml) | ops | reusable | active | Buildchain Patrol |\n| [.ops-pipeline-delivery.yml](../.github/workflows/.ops-pipeline-delivery.yml) | ops | reusable | active | Internal pipeline delivery |\n| [.ops-pipeline-execute.yml](../.github/workflows/.ops-pipeline-execute.yml) | ops | reusable | active | Internal pipeline execution |\n| [.ops-release-governance.yml](../.github/workflows/.ops-release-governance.yml) | ops | reusable | active | Release Governance Reconcile |\n| [.ops-stable-candidate-patrol.yml](../.github/workflows/.ops-stable-candidate-patrol.yml) | ops | reusable | active | Buildchain Stable Candidate Patrol |\n| [.ops-tail-reseal.yml](../.github/workflows/.ops-tail-reseal.yml) | ops | reusable | active | V4 Retained Candidate Tail Reseal |\n| [.ops-warrant-cancel.yml](../.github/workflows/.ops-warrant-cancel.yml) | ops | reusable | active | Dev Delivery Warrant Queued Candidate Cancel |\n| [.ops-warrant-close.yml](../.github/workflows/.ops-warrant-close.yml) | ops | reusable | active | Dev Delivery Warrant Close |\n| [.release-artifact-attestation.yml](../.github/workflows/.release-artifact-attestation.yml) | release | reusable | active | Buildchain GitHub Artifact Attestation |\n| [.release-authority.yml](../.github/workflows/.release-authority.yml) | release | reusable | active | Buildchain Sealed Publication Authority |\n| [.release-binary-assets.yml](../.github/workflows/.release-binary-assets.yml) | release | reusable | active | Buildchain Binary Release Assets |\n| [.release-candidate-promote.yml](../.github/workflows/.release-candidate-promote.yml) | release | reusable | active | Release Candidate Promote |\n| [.release-oci-compose-preview.yml](../.github/workflows/.release-oci-compose-preview.yml) | release | reusable | active | Buildchain OCI Compose Preview |\n| [.release-paper.yml](../.github/workflows/.release-paper.yml) | release | reusable | active | Buildchain Paper Release |\n| [.release-pipeline-products.yml](../.github/workflows/.release-pipeline-products.yml) | release | reusable | active | Internal pipeline product publication |\n| [.release-pipeline-version.yml](../.github/workflows/.release-pipeline-version.yml) | release | reusable | active | Internal pipeline version preparation |\n| [.release-promote.yml](../.github/workflows/.release-promote.yml) | release | reusable | active | Release Candidate Promote Advanced |\n| [.release-propagation.yml](../.github/workflows/.release-propagation.yml) | release | reusable | active | Release Propagation |\n| [.release-signing-authority.yml](../.github/workflows/.release-signing-authority.yml) | release | dispatch-service | active | Buildchain Artifact Signing Authority |\n| [.release-tail.yml](../.github/workflows/.release-tail.yml) | release | reusable | active | Declarative Release Tail |\n| [.release-web.yml](../.github/workflows/.release-web.yml) | release | reusable | active | Buildchain Web Surface |\n\n## self\n\n| Workflow | Category | Invocation | Status | Purpose |\n| --- | --- | --- | --- | --- |\n| [buildchain-recover.yml](../.github/workflows/buildchain-recover.yml) | ops | repository | active | Buildchain recovery |\n| [buildchain.yml](../.github/workflows/buildchain.yml) | ops | repository | active | Buildchain pipeline |"
|
|
5500
5500
|
},
|
|
5501
5501
|
{
|
|
5502
5502
|
"id": "manual:workflow-path-migration",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"contract": "kungfu-buildchain-public-surface-reverse-audit",
|
|
22
22
|
"path": "dist/site/public-surface-audit.json",
|
|
23
23
|
"status": "passed",
|
|
24
|
-
"sha256": "
|
|
24
|
+
"sha256": "cb1df6c1767d031c630f00f8fe76e545ebf9b41d9c48fe6cbb2e230c48397ebd",
|
|
25
25
|
"summary": {
|
|
26
26
|
"cliCommandCount": 113,
|
|
27
27
|
"workflowCount": 44,
|
|
@@ -246,7 +246,7 @@
|
|
|
246
246
|
"contract": "kungfu-buildchain-public-surface-reverse-audit",
|
|
247
247
|
"path": "dist/site/public-surface-audit.json",
|
|
248
248
|
"status": "passed",
|
|
249
|
-
"sha256": "
|
|
249
|
+
"sha256": "cb1df6c1767d031c630f00f8fe76e545ebf9b41d9c48fe6cbb2e230c48397ebd",
|
|
250
250
|
"summary": {
|
|
251
251
|
"cliCommandCount": 113,
|
|
252
252
|
"workflowCount": 44,
|
|
@@ -5407,7 +5407,7 @@
|
|
|
5407
5407
|
],
|
|
5408
5408
|
"maturity": "stable",
|
|
5409
5409
|
"sourcePath": "docs/workflow-catalog.md",
|
|
5410
|
-
"digest": "sha256:
|
|
5410
|
+
"digest": "sha256:99b20bc39eaf03df2970e04a6a0695e514a0ef263c18ad1e6e633da4b625713e",
|
|
5411
5411
|
"headings": [
|
|
5412
5412
|
{
|
|
5413
5413
|
"level": 1,
|
|
@@ -5430,7 +5430,7 @@
|
|
|
5430
5430
|
"anchor": "self"
|
|
5431
5431
|
}
|
|
5432
5432
|
],
|
|
5433
|
-
"markdown": "---\nstatus: active\nperiod: ongoing\ntheme: workflow-taxonomy\ndoc_type: technical-reference\nsource_level: local-files\nconfidence: high\nsensitivity: public\nevidence_grade: B\nreview_state: unreviewed\nlast_reviewed: 2026-09-09\nai_provenance:\n model_family: GPT-6\n product: Codex\n generated_at: 2026-09-09\n visible_context: Canonical Buildchain workflow ownership and source files\n invisible_context_boundary: No private credentials or unpublished consumer state inspected\n---\n\n# Workflow catalog\n\nGenerated from `architecture/workflow-taxonomy.json`. Every workflow has one canonical implementation
|
|
5433
|
+
"markdown": "---\nstatus: active\nperiod: ongoing\ntheme: workflow-taxonomy\ndoc_type: technical-reference\nsource_level: local-files\nconfidence: high\nsensitivity: public\nevidence_grade: B\nreview_state: unreviewed\nlast_reviewed: 2026-09-09\nai_provenance:\n model_family: GPT-6\n product: Codex\n generated_at: 2026-09-09\n visible_context: Canonical Buildchain workflow ownership and source files\n invisible_context_boundary: No private credentials or unpublished consumer state inspected\n---\n\n# Workflow catalog\n\nGenerated from `architecture/workflow-taxonomy.json`. Every workflow has one canonical implementation. Historical entry contracts declared in an optional `architecture/consumer-upgrade.json` registry must match their generated canonical implementations byte-for-byte, including job contexts, inputs, outputs, permissions and publisher identities.\n\nThe two public workflows own normal pipeline execution and exact-attempt recovery. Component workflows are internal runtime implementation, including once-only setup and the dispatch signing service; consumers do not wire these components. Self workflows are the generated consumer pair. Actions own execution steps; JS adapters and Rust/WASM own implementation.\n\nNames use `public-ops-pipeline.yml`, `public-ops-recover.yml`, internal `.<category>-<purpose>.yml`, and the generated self callers `buildchain.yml` and `buildchain-recover.yml`. Categories are `build`, `release`, and `ops`; the internal build engine retains `.build.yml`.\n\nRegister ownership before adding a workflow. `pnpm run check:workflows` validates source, calls, required CI integration and independent review ownership. `pnpm run generate:workflows` regenerates this catalog.\n\n## public\n\n| Workflow | Category | Invocation | Status | Purpose |\n| --- | --- | --- | --- | --- |\n| [public-ops-pipeline.yml](../.github/workflows/public-ops-pipeline.yml) | ops | reusable | active | Buildchain pipeline |\n| [public-ops-recover.yml](../.github/workflows/public-ops-recover.yml) | ops | reusable | active | Buildchain recovery |\n\n## component\n\n| Workflow | Category | Invocation | Status | Purpose |\n| --- | --- | --- | --- | --- |\n| [.build-adopter-qualification.yml](../.github/workflows/.build-adopter-qualification.yml) | build | reusable | active | V4 Adopter Delivery |\n| [.build-candidate.yml](../.github/workflows/.build-candidate.yml) | build | reusable | active | Buildchain Channel Build |\n| [.build-check.yml](../.github/workflows/.build-check.yml) | build | reusable | active | Buildchain Check |\n| [.build-demo-adapter.yml](../.github/workflows/.build-demo-adapter.yml) | build | reusable | active | Buildchain Auditable Demo |\n| [.build-demo.yml](../.github/workflows/.build-demo.yml) | build | reusable | active | Buildchain Declarative Binary Auditable Demo |\n| [.build-gate-profile.yml](../.github/workflows/.build-gate-profile.yml) | build | reusable | active | Buildchain Shifu Gate Profile |\n| [.build-publication.yml](../.github/workflows/.build-publication.yml) | build | reusable | active | Buildchain Publication Artifact |\n| [.build-stage-capsule-canary.yml](../.github/workflows/.build-stage-capsule-canary.yml) | build | reusable | active | V4 Stage Capsule Canary |\n| [.build.yml](../.github/workflows/.build.yml) | build | reusable | active | Buildchain Build |\n| [.ops-alpha-candidate-patrol.yml](../.github/workflows/.ops-alpha-candidate-patrol.yml) | ops | reusable | active | Buildchain Dev to Alpha Candidate Patrol |\n| [.ops-bootstrap.yml](../.github/workflows/.ops-bootstrap.yml) | ops | reusable | active | Buildchain Universal Bootstrap |\n| [.ops-dev-auto-merge.yml](../.github/workflows/.ops-dev-auto-merge.yml) | ops | reusable | active | Dev PR Auto Merge |\n| [.ops-dev-qualification-patrol.yml](../.github/workflows/.ops-dev-qualification-patrol.yml) | ops | reusable | active | Buildchain Dev Qualification Patrol |\n| [.ops-git-sync.yml](../.github/workflows/.ops-git-sync.yml) | ops | reusable | active | sync remote git |\n| [.ops-housekeeping.yml](../.github/workflows/.ops-housekeeping.yml) | ops | reusable | active | Engineering Housekeeper |\n| [.ops-observed-evidence.yml](../.github/workflows/.ops-observed-evidence.yml) | ops | reusable | active | Patrol Observed Evidence |\n| [.ops-patrol-daily.yml](../.github/workflows/.ops-patrol-daily.yml) | ops | reusable | active | Buildchain Patrol Daily |\n| [.ops-patrol-monthly.yml](../.github/workflows/.ops-patrol-monthly.yml) | ops | reusable | active | Buildchain Patrol Monthly |\n| [.ops-patrol-weekly.yml](../.github/workflows/.ops-patrol-weekly.yml) | ops | reusable | active | Buildchain Patrol Weekly |\n| [.ops-patrol.yml](../.github/workflows/.ops-patrol.yml) | ops | reusable | active | Buildchain Patrol |\n| [.ops-pipeline-delivery.yml](../.github/workflows/.ops-pipeline-delivery.yml) | ops | reusable | active | Internal pipeline delivery |\n| [.ops-pipeline-execute.yml](../.github/workflows/.ops-pipeline-execute.yml) | ops | reusable | active | Internal pipeline execution |\n| [.ops-release-governance.yml](../.github/workflows/.ops-release-governance.yml) | ops | reusable | active | Release Governance Reconcile |\n| [.ops-stable-candidate-patrol.yml](../.github/workflows/.ops-stable-candidate-patrol.yml) | ops | reusable | active | Buildchain Stable Candidate Patrol |\n| [.ops-tail-reseal.yml](../.github/workflows/.ops-tail-reseal.yml) | ops | reusable | active | V4 Retained Candidate Tail Reseal |\n| [.ops-warrant-cancel.yml](../.github/workflows/.ops-warrant-cancel.yml) | ops | reusable | active | Dev Delivery Warrant Queued Candidate Cancel |\n| [.ops-warrant-close.yml](../.github/workflows/.ops-warrant-close.yml) | ops | reusable | active | Dev Delivery Warrant Close |\n| [.release-artifact-attestation.yml](../.github/workflows/.release-artifact-attestation.yml) | release | reusable | active | Buildchain GitHub Artifact Attestation |\n| [.release-authority.yml](../.github/workflows/.release-authority.yml) | release | reusable | active | Buildchain Sealed Publication Authority |\n| [.release-binary-assets.yml](../.github/workflows/.release-binary-assets.yml) | release | reusable | active | Buildchain Binary Release Assets |\n| [.release-candidate-promote.yml](../.github/workflows/.release-candidate-promote.yml) | release | reusable | active | Release Candidate Promote |\n| [.release-oci-compose-preview.yml](../.github/workflows/.release-oci-compose-preview.yml) | release | reusable | active | Buildchain OCI Compose Preview |\n| [.release-paper.yml](../.github/workflows/.release-paper.yml) | release | reusable | active | Buildchain Paper Release |\n| [.release-pipeline-products.yml](../.github/workflows/.release-pipeline-products.yml) | release | reusable | active | Internal pipeline product publication |\n| [.release-pipeline-version.yml](../.github/workflows/.release-pipeline-version.yml) | release | reusable | active | Internal pipeline version preparation |\n| [.release-promote.yml](../.github/workflows/.release-promote.yml) | release | reusable | active | Release Candidate Promote Advanced |\n| [.release-propagation.yml](../.github/workflows/.release-propagation.yml) | release | reusable | active | Release Propagation |\n| [.release-signing-authority.yml](../.github/workflows/.release-signing-authority.yml) | release | dispatch-service | active | Buildchain Artifact Signing Authority |\n| [.release-tail.yml](../.github/workflows/.release-tail.yml) | release | reusable | active | Declarative Release Tail |\n| [.release-web.yml](../.github/workflows/.release-web.yml) | release | reusable | active | Buildchain Web Surface |\n\n## self\n\n| Workflow | Category | Invocation | Status | Purpose |\n| --- | --- | --- | --- | --- |\n| [buildchain-recover.yml](../.github/workflows/buildchain-recover.yml) | ops | repository | active | Buildchain recovery |\n| [buildchain.yml](../.github/workflows/buildchain.yml) | ops | repository | active | Buildchain pipeline |"
|
|
5434
5434
|
},
|
|
5435
5435
|
{
|
|
5436
5436
|
"id": "manual:workflow-path-migration",
|
|
@@ -10604,8 +10604,8 @@
|
|
|
10604
10604
|
"workflowRegistryPath": "dist/site/workflow-registry.json",
|
|
10605
10605
|
"pageRegistryPath": "dist/site/page-registry.json",
|
|
10606
10606
|
"cliRegistryDigest": "b0cf6f05cea3a3730c2afc07fa767d913242387c9aca6674c7b1a7932d2de31d",
|
|
10607
|
-
"workflowRegistryDigest": "
|
|
10608
|
-
"pageRegistryDigest": "
|
|
10607
|
+
"workflowRegistryDigest": "ffd6cd38980a1c467ff347b8b89b7583f93095fb223540340ac3d940223109a7",
|
|
10608
|
+
"pageRegistryDigest": "65cc6e7d9c2f0d86987ea0d3d6a64a7636b6c59b8db64d1efbd1803e501e97d2"
|
|
10609
10609
|
},
|
|
10610
10610
|
"comparison": {
|
|
10611
10611
|
"missingCliRegistry": [],
|
|
@@ -858,7 +858,7 @@
|
|
|
858
858
|
"status": "repository-internal",
|
|
859
859
|
"owner": "buildchain-workflows",
|
|
860
860
|
"maturity": "repository-internal",
|
|
861
|
-
"introducedVersion": "4.1.
|
|
861
|
+
"introducedVersion": "4.1.6-alpha.0",
|
|
862
862
|
"compatibilityPromise": "current-contract-only",
|
|
863
863
|
"deprecationReplacement": "",
|
|
864
864
|
"sunsetCondition": "explicit-contract-change-review",
|
package/docs/workflow-catalog.md
CHANGED
|
@@ -19,7 +19,7 @@ ai_provenance:
|
|
|
19
19
|
|
|
20
20
|
# Workflow catalog
|
|
21
21
|
|
|
22
|
-
Generated from `architecture/workflow-taxonomy.json`. Every workflow has one canonical implementation
|
|
22
|
+
Generated from `architecture/workflow-taxonomy.json`. Every workflow has one canonical implementation. Historical entry contracts declared in an optional `architecture/consumer-upgrade.json` registry must match their generated canonical implementations byte-for-byte, including job contexts, inputs, outputs, permissions and publisher identities.
|
|
23
23
|
|
|
24
24
|
The two public workflows own normal pipeline execution and exact-attempt recovery. Component workflows are internal runtime implementation, including once-only setup and the dispatch signing service; consumers do not wire these components. Self workflows are the generated consumer pair. Actions own execution steps; JS adapters and Rust/WASM own implementation.
|
|
25
25
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kungfu-tech/buildchain",
|
|
3
|
-
"version": "4.1.
|
|
3
|
+
"version": "4.1.6-alpha.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Buildchain Release Passport, release governance, CLI toolkit, and site facts.",
|
|
6
6
|
"repository": "https://github.com/kungfu-systems/buildchain",
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
function replaceRequired(source, before, after) {
|
|
2
|
+
if (
|
|
3
|
+
!source.includes(before) ||
|
|
4
|
+
source.indexOf(before) !== source.lastIndexOf(before)
|
|
5
|
+
)
|
|
6
|
+
throw new Error(
|
|
7
|
+
"Historical promotion adapter no longer matches its maintained component",
|
|
8
|
+
);
|
|
9
|
+
return source.replace(before, after);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function adaptHistoricalPromotionWorkflow(entry, source) {
|
|
13
|
+
if (entry.adapter === "promotion-v4.0") {
|
|
14
|
+
source = replaceRequired(
|
|
15
|
+
source,
|
|
16
|
+
" runtime-ref: ${{ inputs.runtime-ref }}\n",
|
|
17
|
+
" runtime-ref: ${{ inputs.runtime-ref }}\n compatibility-inputs: ${{ toJSON(inputs) }}\n",
|
|
18
|
+
);
|
|
19
|
+
source = replaceRequired(
|
|
20
|
+
source,
|
|
21
|
+
" request-json: ${{ inputs.request-json }}",
|
|
22
|
+
` request-json: \${{ format('{{"schema":"buildchain.promotion-compatibility/v1","inputs":{0}}}', toJSON(inputs)) }}`,
|
|
23
|
+
);
|
|
24
|
+
source = replaceRequired(
|
|
25
|
+
source,
|
|
26
|
+
" request-json: ${{ steps.node.outputs.request-json }}",
|
|
27
|
+
" request-json: ${{ steps.node.outputs.request-json }}\n historical-inputs-json: ${{ steps.node.outputs.historical-inputs-json }}",
|
|
28
|
+
);
|
|
29
|
+
return replaceRequired(
|
|
30
|
+
source,
|
|
31
|
+
"uses: ./.github/workflows/.release-promote.yml",
|
|
32
|
+
"uses: ./.github/workflows/.release-historical.yml",
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
if (entry.adapter === "promotion-backbone") {
|
|
36
|
+
return replaceRequired(
|
|
37
|
+
source,
|
|
38
|
+
" actions: read\n contents: read\n discussions: read\n pull-requests: read\n",
|
|
39
|
+
" actions: read\n contents: read\n",
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
return source;
|
|
43
|
+
}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { adaptHistoricalPromotionWorkflow } from "./compatibility-promotion-workflows.js";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
|
|
5
|
+
export const CONSUMER_UPGRADE_PATH = "architecture/consumer-upgrade.json";
|
|
6
|
+
|
|
7
|
+
export function readConsumerUpgrade(root, files) {
|
|
8
|
+
const source = files
|
|
9
|
+
? files[CONSUMER_UPGRADE_PATH]
|
|
10
|
+
: fs.existsSync(path.join(root, CONSUMER_UPGRADE_PATH))
|
|
11
|
+
? fs.readFileSync(path.join(root, CONSUMER_UPGRADE_PATH), "utf8")
|
|
12
|
+
: undefined;
|
|
13
|
+
if (!source) return null;
|
|
14
|
+
const contract = JSON.parse(source);
|
|
15
|
+
if (
|
|
16
|
+
contract.schema !== "buildchain.consumer-upgrade/v1" ||
|
|
17
|
+
!/^[a-f0-9]{40}$/u.test(contract.source?.sha || "") ||
|
|
18
|
+
!Array.isArray(contract.entries)
|
|
19
|
+
)
|
|
20
|
+
throw new Error("Invalid consumer upgrade contract");
|
|
21
|
+
return contract;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function compatibilityWorkflowTarget(root, relative, source) {
|
|
25
|
+
const entry = readConsumerUpgrade(root)?.entries.find(
|
|
26
|
+
(item) => item.path === relative,
|
|
27
|
+
);
|
|
28
|
+
if (!entry) return relative;
|
|
29
|
+
const canonical = fs.readFileSync(path.join(root, entry.target), "utf8");
|
|
30
|
+
if (source !== renderCompatibilityWorkflow(entry, canonical))
|
|
31
|
+
throw new Error(
|
|
32
|
+
`${relative}: generated consumer compatibility workflow drift`,
|
|
33
|
+
);
|
|
34
|
+
return entry.target;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Keep the historical job names, outputs, permissions and publisher identity.
|
|
38
|
+
// A nested forwarding job would change required check contexts and OIDC identity.
|
|
39
|
+
// Business steps are always generated from the one maintained implementation.
|
|
40
|
+
export function renderCompatibilityWorkflow(entry, source) {
|
|
41
|
+
const lines = source.split("\n");
|
|
42
|
+
const start = lines.findIndex((line) => /^on:\s*$/u.test(line));
|
|
43
|
+
let end = start + 1;
|
|
44
|
+
while (end < lines.length && !/^[a-z][a-z-]*:/u.test(lines[end])) end++;
|
|
45
|
+
if (start < 0 || !entry.interfaceSource?.startsWith("on:\n"))
|
|
46
|
+
throw new Error(
|
|
47
|
+
`Consumer upgrade entry lacks its retained interface: ${entry.path}`,
|
|
48
|
+
);
|
|
49
|
+
lines.splice(start, end - start, entry.interfaceSource.trimEnd());
|
|
50
|
+
let rendered =
|
|
51
|
+
"# Generated from the consumer upgrade contract; edit the canonical implementation.\n" +
|
|
52
|
+
lines.join("\n");
|
|
53
|
+
if (entry.source || entry.inheritCallerPermissions) {
|
|
54
|
+
const body = rendered.split("\n");
|
|
55
|
+
const permissionStart = body.findIndex((line) =>
|
|
56
|
+
/^permissions:/u.test(line),
|
|
57
|
+
);
|
|
58
|
+
const insertion =
|
|
59
|
+
permissionStart < 0
|
|
60
|
+
? body.findIndex((line) => /^jobs:/u.test(line))
|
|
61
|
+
: permissionStart;
|
|
62
|
+
let permissionEnd = insertion + (permissionStart < 0 ? 0 : 1);
|
|
63
|
+
while (
|
|
64
|
+
permissionStart >= 0 &&
|
|
65
|
+
permissionEnd < body.length &&
|
|
66
|
+
!/^[a-z][a-z-]*:/u.test(body[permissionEnd])
|
|
67
|
+
)
|
|
68
|
+
permissionEnd++;
|
|
69
|
+
const declaration =
|
|
70
|
+
entry.permissions && !entry.inheritCallerPermissions
|
|
71
|
+
? [
|
|
72
|
+
"permissions:",
|
|
73
|
+
...Object.entries(entry.permissions).map(
|
|
74
|
+
([key, value]) => ` ${key}: ${value}`,
|
|
75
|
+
),
|
|
76
|
+
]
|
|
77
|
+
: [];
|
|
78
|
+
body.splice(insertion, permissionEnd - insertion, ...declaration);
|
|
79
|
+
rendered = body.join("\n");
|
|
80
|
+
}
|
|
81
|
+
if (entry.adapter === "build-v4.0") {
|
|
82
|
+
const input = "compatibility-inputs: ${{ inputs.compatibility-inputs }}";
|
|
83
|
+
if (!rendered.includes(input))
|
|
84
|
+
throw new Error(
|
|
85
|
+
"Historical build transport is missing from the canonical facade",
|
|
86
|
+
);
|
|
87
|
+
rendered = rendered.replace(
|
|
88
|
+
input,
|
|
89
|
+
"compatibility-inputs: ${{ toJSON(inputs) }}",
|
|
90
|
+
);
|
|
91
|
+
rendered = rendered.replace(
|
|
92
|
+
"uses: ./.github/workflows/.build.yml",
|
|
93
|
+
"uses: ./.github/workflows/.build-historical.yml",
|
|
94
|
+
);
|
|
95
|
+
rendered += ` summarize:
|
|
96
|
+
name: Summarize build contract
|
|
97
|
+
needs: build
|
|
98
|
+
if: \${{ always() }}
|
|
99
|
+
runs-on: \${{ fromJSON(inputs.control-runner-json) }}
|
|
100
|
+
permissions:
|
|
101
|
+
contents: read
|
|
102
|
+
steps:
|
|
103
|
+
- uses: $/actions/runtime/environment/prepare
|
|
104
|
+
with:
|
|
105
|
+
selection: \${{ needs.build.outputs.runtime-selection }}
|
|
106
|
+
token: \${{ github.token }}
|
|
107
|
+
- uses: ./.buildchain/runtime/actions/build/gate/qualify-contract
|
|
108
|
+
with:
|
|
109
|
+
conclusion: \${{ needs.build.result }}
|
|
110
|
+
result: \${{ needs.build.outputs.result }}
|
|
111
|
+
`;
|
|
112
|
+
}
|
|
113
|
+
if (entry.adapter === "entry-v4.0") {
|
|
114
|
+
const input = " runtime-ref: ${{ inputs.runtime-ref }}\n";
|
|
115
|
+
if (!rendered.includes(input))
|
|
116
|
+
throw new Error(
|
|
117
|
+
"Historical runtime entry is missing from the canonical implementation",
|
|
118
|
+
);
|
|
119
|
+
rendered = rendered.replace(
|
|
120
|
+
input,
|
|
121
|
+
input + " compatibility-inputs: ${{ toJSON(inputs) }}\n",
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
if (entry.adapter === "build-backbone") {
|
|
125
|
+
const start = rendered.indexOf(" attest:\n"),
|
|
126
|
+
end = rendered.indexOf(" deliver:\n", start);
|
|
127
|
+
if (start < 0 || end < 0)
|
|
128
|
+
throw new Error("Historical attestation boundary is missing");
|
|
129
|
+
const job = rendered
|
|
130
|
+
.slice(start, end)
|
|
131
|
+
.replace(/ permissions:\n(?: [^\n]*\n)+/u, "");
|
|
132
|
+
rendered = rendered.slice(0, start) + job + rendered.slice(end);
|
|
133
|
+
const step =
|
|
134
|
+
" - uses: ./.buildchain/runtime/actions/build/lifecycle/plan\n";
|
|
135
|
+
const variables = Object.entries(entry.inputVariables || {}).map(
|
|
136
|
+
([input, variable]) => {
|
|
137
|
+
if (
|
|
138
|
+
!/^[a-z][a-z0-9-]+$/u.test(input) ||
|
|
139
|
+
!/^BUILDCHAIN_[A-Z0-9_]+$/u.test(variable)
|
|
140
|
+
)
|
|
141
|
+
throw new Error("Invalid historical build variable binding");
|
|
142
|
+
return ` BUILDCHAIN_HISTORICAL_${input.replaceAll("-", "_").toUpperCase()}: \${{ vars.${variable} }}`;
|
|
143
|
+
},
|
|
144
|
+
);
|
|
145
|
+
if (variables.length) {
|
|
146
|
+
if (!rendered.includes(step))
|
|
147
|
+
throw new Error("Historical build plan adapter is missing");
|
|
148
|
+
rendered = rendered.replace(
|
|
149
|
+
step,
|
|
150
|
+
step + " env:\n" + variables.join("\n") + "\n",
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return adaptHistoricalPromotionWorkflow(entry, rendered);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export function compatibilityWorkflowEntries(root, files, canonicalEntries) {
|
|
158
|
+
const contract = readConsumerUpgrade(root, files);
|
|
159
|
+
if (!contract) return [];
|
|
160
|
+
const known = new Set(canonicalEntries.map((entry) => entry.path));
|
|
161
|
+
const paths = new Set();
|
|
162
|
+
return contract.entries.map((entry) => {
|
|
163
|
+
if (
|
|
164
|
+
!/^\.github\/workflows\/[.a-z0-9-]+\.yml$/u.test(entry.path) ||
|
|
165
|
+
known.has(entry.path) ||
|
|
166
|
+
paths.has(entry.path) ||
|
|
167
|
+
!known.has(entry.target) ||
|
|
168
|
+
entry.path === entry.target ||
|
|
169
|
+
(entry.adapter &&
|
|
170
|
+
![
|
|
171
|
+
"build-v4.0",
|
|
172
|
+
"entry-v4.0",
|
|
173
|
+
"build-backbone",
|
|
174
|
+
"promotion-v4.0",
|
|
175
|
+
"promotion-backbone",
|
|
176
|
+
].includes(entry.adapter)) ||
|
|
177
|
+
(entry.inheritCallerPermissions &&
|
|
178
|
+
!["build-v4.0", "build-backbone", "promotion-v4.0"].includes(
|
|
179
|
+
entry.adapter,
|
|
180
|
+
)) ||
|
|
181
|
+
!entry.interface ||
|
|
182
|
+
Object.keys(entry.interface).some(
|
|
183
|
+
(key) => !["workflow_call", "workflow_dispatch"].includes(key),
|
|
184
|
+
)
|
|
185
|
+
)
|
|
186
|
+
throw new Error(`Invalid consumer upgrade entry: ${entry.path}`);
|
|
187
|
+
paths.add(entry.path);
|
|
188
|
+
const target = canonicalEntries.find((item) => item.path === entry.target);
|
|
189
|
+
return {
|
|
190
|
+
...target,
|
|
191
|
+
...entry,
|
|
192
|
+
id: entry.path,
|
|
193
|
+
role: "component",
|
|
194
|
+
compatibility: true,
|
|
195
|
+
};
|
|
196
|
+
});
|
|
197
|
+
}
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import { createRequire } from "node:module";
|
|
3
3
|
import path from "node:path";
|
|
4
|
+
import {
|
|
5
|
+
CONSUMER_UPGRADE_PATH,
|
|
6
|
+
compatibilityWorkflowEntries,
|
|
7
|
+
readConsumerUpgrade,
|
|
8
|
+
renderCompatibilityWorkflow,
|
|
9
|
+
} from "../consumer/compatibility-workflows.js";
|
|
4
10
|
import {
|
|
5
11
|
parseWorkflowDocument,
|
|
6
12
|
parseYamlUses,
|
|
@@ -290,6 +296,24 @@ export function checkWorkflowTaxonomy(
|
|
|
290
296
|
: readWorkflowTaxonomy(root),
|
|
291
297
|
entries = validateEntries(policy, errors);
|
|
292
298
|
if (errors.length) return { ok: false, errors };
|
|
299
|
+
let compatibility = [];
|
|
300
|
+
try {
|
|
301
|
+
if (
|
|
302
|
+
policy.consumerUpgradeContract &&
|
|
303
|
+
(policy.consumerUpgradeContract !== CONSUMER_UPGRADE_PATH ||
|
|
304
|
+
!readConsumerUpgrade(root, files))
|
|
305
|
+
)
|
|
306
|
+
throw new Error(
|
|
307
|
+
"Required consumer upgrade contract is missing or changed",
|
|
308
|
+
);
|
|
309
|
+
compatibility = compatibilityWorkflowEntries(
|
|
310
|
+
root,
|
|
311
|
+
files,
|
|
312
|
+
entries.map((entry) => ({ ...entry, path: workflowPath(entry) })),
|
|
313
|
+
);
|
|
314
|
+
} catch (error) {
|
|
315
|
+
return { ok: false, errors: [error.message] };
|
|
316
|
+
}
|
|
293
317
|
files ??= Object.fromEntries(
|
|
294
318
|
discoverWorkflowFiles(root).map((file) => {
|
|
295
319
|
const absolute = path.join(root, file);
|
|
@@ -301,7 +325,10 @@ export function checkWorkflowTaxonomy(
|
|
|
301
325
|
];
|
|
302
326
|
}),
|
|
303
327
|
);
|
|
304
|
-
const declared = new Set(
|
|
328
|
+
const declared = new Set([
|
|
329
|
+
...entries.map(workflowPath),
|
|
330
|
+
...compatibility.map((entry) => entry.path),
|
|
331
|
+
]),
|
|
305
332
|
observed = new Set(
|
|
306
333
|
Object.keys(files).filter((file) =>
|
|
307
334
|
/^\.github\/workflows\/.*\.ya?ml$/iu.test(file),
|
|
@@ -317,6 +344,21 @@ export function checkWorkflowTaxonomy(
|
|
|
317
344
|
errors.push(`registered workflow missing: ${file}`);
|
|
318
345
|
for (const entry of entries)
|
|
319
346
|
validateWorkflow(entry, files[workflowPath(entry)], declared, errors);
|
|
347
|
+
for (const entry of compatibility) {
|
|
348
|
+
validateWorkflow(entry, files[entry.path], declared, errors);
|
|
349
|
+
try {
|
|
350
|
+
if (
|
|
351
|
+
files[entry.target] &&
|
|
352
|
+
files[entry.path] !==
|
|
353
|
+
renderCompatibilityWorkflow(entry, files[entry.target])
|
|
354
|
+
)
|
|
355
|
+
errors.push(
|
|
356
|
+
`${entry.path}: generated consumer compatibility workflow drift`,
|
|
357
|
+
);
|
|
358
|
+
} catch (error) {
|
|
359
|
+
errors.push(`${entry.path}: ${error.message}`);
|
|
360
|
+
}
|
|
361
|
+
}
|
|
320
362
|
if (integration) validateGateIntegration(root, errors);
|
|
321
363
|
if (documentation) {
|
|
322
364
|
const file = path.join(root, TAXONOMY_DOC);
|
|
@@ -329,6 +371,7 @@ export function checkWorkflowTaxonomy(
|
|
|
329
371
|
return {
|
|
330
372
|
ok: !errors.length,
|
|
331
373
|
canonicalCount: entries.length,
|
|
374
|
+
compatibilityCount: compatibility.length,
|
|
332
375
|
fileCount: observed.size,
|
|
333
376
|
errors,
|
|
334
377
|
};
|
|
@@ -364,7 +407,7 @@ export function renderWorkflowCatalog(policy) {
|
|
|
364
407
|
"",
|
|
365
408
|
"# Workflow catalog",
|
|
366
409
|
"",
|
|
367
|
-
"Generated from `architecture/workflow-taxonomy.json`. Every workflow has one canonical implementation
|
|
410
|
+
"Generated from `architecture/workflow-taxonomy.json`. Every workflow has one canonical implementation. Historical entry contracts declared in an optional `architecture/consumer-upgrade.json` registry must match their generated canonical implementations byte-for-byte, including job contexts, inputs, outputs, permissions and publisher identities.",
|
|
368
411
|
"",
|
|
369
412
|
"The two public workflows own normal pipeline execution and exact-attempt recovery. Component workflows are internal runtime implementation, including once-only setup and the dispatch signing service; consumers do not wire these components. Self workflows are the generated consumer pair. Actions own execution steps; JS adapters and Rust/WASM own implementation.",
|
|
370
413
|
"",
|