@kungfu-tech/buildchain 4.0.2-alpha.37 → 4.0.2-alpha.38

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 (41) hide show
  1. package/AGENTS.md +1 -1
  2. package/architecture/agent-change-map.md +2 -2
  3. package/architecture/internal-capabilities.json +2 -2
  4. package/architecture/maintainability-debt.json +3 -3
  5. package/architecture/maintainability-policy.json +3 -3
  6. package/architecture/v4-cross-platform-adopter-qualification.json +1 -1
  7. package/architecture/v4-floating-consumer-policy.json +1 -1
  8. package/architecture/v4-next-development-parity.json +2 -2
  9. package/architecture/v4-release-topology.json +0 -1
  10. package/architecture/v4-stage-capsule-qualification.json +1 -1
  11. package/architecture/v4-tail-reseal-parity.json +8 -6
  12. package/architecture/v4-universal-workflow-train-admission.json +1 -1
  13. package/architecture/workflow-taxonomy.json +18 -15
  14. package/contracts/fixtures/v4-tail-reseal-v1/valid.json +1 -1
  15. package/dist/site/buildchain-contract.json +4 -4
  16. package/dist/site/buildchain-site.json +58 -17
  17. package/dist/site/capability-registry.json +2 -2
  18. package/dist/site/kfd-claims.json +19 -73
  19. package/dist/site/kfd-upstream-aggregate.json +1 -1
  20. package/dist/site/manual-registry.json +2 -2
  21. package/dist/site/node-api-registry.json +1 -1
  22. package/dist/site/page-registry.json +52 -11
  23. package/dist/site/public-surface-audit.json +8 -67
  24. package/dist/site/publication-authority-registry.json +1 -16
  25. package/dist/site/publication-registry.json +4 -4
  26. package/dist/site/site-manifest.json +6 -6
  27. package/dist/site/workflow-registry.json +5 -125
  28. package/docs/next-development-transition.md +1 -1
  29. package/docs/v4-adopter-delivery.md +1 -1
  30. package/docs/v4-stage-capsule.md +1 -1
  31. package/docs/v4-tail-reseal.md +1 -1
  32. package/docs/workflow-catalog.md +5 -3
  33. package/docs/workflow-path-migration.md +109 -0
  34. package/package.json +1 -1
  35. package/packages/core/next-development-projection.js +1 -1
  36. package/scripts/check-v4-floating-consumer-policy-contract.mjs +1 -1
  37. package/scripts/check-v4-public-dogfood-contract.mjs +4 -4
  38. package/scripts/check-v4-universal-workflow-bootstrap.mjs +3 -3
  39. package/scripts/generate-v4-universal-workflow-facades.mjs +4 -3
  40. package/scripts/v4-universal-workflow-engine.mjs +2 -1
  41. package/scripts/workflow-taxonomy.mjs +50 -11
@@ -2746,7 +2746,7 @@
2746
2746
  "status": "preview",
2747
2747
  "owner": "buildchain-workflows",
2748
2748
  "maturity": "preview",
2749
- "introducedVersion": "4.0.2-alpha.37",
2749
+ "introducedVersion": "4.0.2-alpha.38",
2750
2750
  "compatibilityPromise": "preserved-through-the-v3-major-line",
2751
2751
  "deprecationReplacement": "",
2752
2752
  "sunsetCondition": "explicit-breaking-change-review-in-a-future-major-line",
@@ -3943,7 +3943,7 @@
3943
3943
  "status": "preview",
3944
3944
  "owner": "buildchain-workflows",
3945
3945
  "maturity": "preview",
3946
- "introducedVersion": "4.0.2-alpha.37",
3946
+ "introducedVersion": "4.0.2-alpha.38",
3947
3947
  "compatibilityPromise": "preserved-through-the-v3-major-line",
3948
3948
  "deprecationReplacement": "",
3949
3949
  "sunsetCondition": "explicit-breaking-change-review-in-a-future-major-line",
@@ -5970,7 +5970,7 @@
5970
5970
  "status": "preview",
5971
5971
  "owner": "buildchain-workflows",
5972
5972
  "maturity": "preview",
5973
- "introducedVersion": "4.0.2-alpha.37",
5973
+ "introducedVersion": "4.0.2-alpha.38",
5974
5974
  "compatibilityPromise": "preserved-through-the-v3-major-line",
5975
5975
  "deprecationReplacement": "",
5976
5976
  "sunsetCondition": "explicit-breaking-change-review-in-a-future-major-line",
@@ -6001,7 +6001,7 @@
6001
6001
  "status": "preview",
6002
6002
  "owner": "buildchain-workflows",
6003
6003
  "maturity": "preview",
6004
- "introducedVersion": "4.0.2-alpha.37",
6004
+ "introducedVersion": "4.0.2-alpha.38",
6005
6005
  "compatibilityPromise": "preserved-through-the-v3-major-line",
6006
6006
  "deprecationReplacement": "",
6007
6007
  "sunsetCondition": "explicit-breaking-change-review-in-a-future-major-line",
@@ -6032,7 +6032,7 @@
6032
6032
  "status": "preview",
6033
6033
  "owner": "buildchain-workflows",
6034
6034
  "maturity": "preview",
6035
- "introducedVersion": "4.0.2-alpha.37",
6035
+ "introducedVersion": "4.0.2-alpha.38",
6036
6036
  "compatibilityPromise": "preserved-through-the-v3-major-line",
6037
6037
  "deprecationReplacement": "",
6038
6038
  "sunsetCondition": "explicit-breaking-change-review-in-a-future-major-line",
@@ -6628,126 +6628,6 @@
6628
6628
  "deprecationReplacement": "",
6629
6629
  "sunsetCondition": "explicit-breaking-change-review-in-a-future-major-line",
6630
6630
  "nonDuplicationRationale": "Existing workflow identity retained for caller compatibility and repository orchestration."
6631
- },
6632
- {
6633
- "id": "v4-adopter-delivery",
6634
- "path": ".github/workflows/v4-adopter-delivery.yml",
6635
- "reusable": true,
6636
- "inputs": [
6637
- "archive-path",
6638
- "bootstrap-path",
6639
- "consumer",
6640
- "consumer-ref",
6641
- "consumer-repository",
6642
- "input-path",
6643
- "invocation-source-path",
6644
- "node-version",
6645
- "universal-request-json"
6646
- ],
6647
- "inputCount": 9,
6648
- "secrets": [],
6649
- "secretCount": 0,
6650
- "outputs": [],
6651
- "outputCount": 0,
6652
- "taxonomy": {
6653
- "id": "v4-adopter-delivery",
6654
- "role": "public",
6655
- "category": "build",
6656
- "purpose": "adopter-qualification",
6657
- "status": "active",
6658
- "canonicalPath": ".github/workflows/public-build-adopter-qualification.yml",
6659
- "compatibilityAlias": true
6660
- },
6661
- "surface": "repository-workflow",
6662
- "capabilityGroup": "api-cli-reference",
6663
- "status": "active",
6664
- "owner": "buildchain-workflows",
6665
- "maturity": "active",
6666
- "introducedVersion": "pre-3.0.2-alpha.4",
6667
- "compatibilityPromise": "preserved-through-the-v3-major-line",
6668
- "deprecationReplacement": "",
6669
- "sunsetCondition": "explicit-breaking-change-review-in-a-future-major-line",
6670
- "nonDuplicationRationale": "Existing workflow identity retained for caller compatibility and repository orchestration."
6671
- },
6672
- {
6673
- "id": "v4-stage-capsule-canary",
6674
- "path": ".github/workflows/v4-stage-capsule-canary.yml",
6675
- "reusable": true,
6676
- "inputs": [
6677
- "build-artifact-path",
6678
- "consumer",
6679
- "go-version",
6680
- "install-artifact-path",
6681
- "node-version",
6682
- "universal-request-json",
6683
- "verify-artifact-path"
6684
- ],
6685
- "inputCount": 7,
6686
- "secrets": [],
6687
- "secretCount": 0,
6688
- "outputs": [],
6689
- "outputCount": 0,
6690
- "taxonomy": {
6691
- "id": "v4-stage-capsule-canary",
6692
- "role": "public",
6693
- "category": "build",
6694
- "purpose": "stage-capsule-canary",
6695
- "status": "active",
6696
- "canonicalPath": ".github/workflows/public-build-stage-capsule-canary.yml",
6697
- "compatibilityAlias": true
6698
- },
6699
- "surface": "repository-workflow",
6700
- "capabilityGroup": "api-cli-reference",
6701
- "status": "active",
6702
- "owner": "buildchain-workflows",
6703
- "maturity": "active",
6704
- "introducedVersion": "pre-3.0.2-alpha.4",
6705
- "compatibilityPromise": "preserved-through-the-v3-major-line",
6706
- "deprecationReplacement": "",
6707
- "sunsetCondition": "explicit-breaking-change-review-in-a-future-major-line",
6708
- "nonDuplicationRationale": "Existing workflow identity retained for caller compatibility and repository orchestration."
6709
- },
6710
- {
6711
- "id": "v4-tail-reseal",
6712
- "path": ".github/workflows/v4-tail-reseal.yml",
6713
- "reusable": true,
6714
- "inputs": [
6715
- "artifact-retention-days",
6716
- "consumer-policy-receipt-json",
6717
- "macos-finalization-command",
6718
- "request-json",
6719
- "universal-request-json"
6720
- ],
6721
- "inputCount": 5,
6722
- "secrets": [
6723
- "BUILDCHAIN_EVIDENCE_READ_TOKEN",
6724
- "BUILDCHAIN_SIGNING_TOKEN"
6725
- ],
6726
- "secretCount": 2,
6727
- "outputs": [
6728
- "release-candidate-passport-json",
6729
- "tail-reseal-receipt-root"
6730
- ],
6731
- "outputCount": 2,
6732
- "taxonomy": {
6733
- "id": "v4-tail-reseal",
6734
- "role": "public",
6735
- "category": "ops",
6736
- "purpose": "tail-reseal",
6737
- "status": "active",
6738
- "canonicalPath": ".github/workflows/public-ops-tail-reseal.yml",
6739
- "compatibilityAlias": true
6740
- },
6741
- "surface": "repository-workflow",
6742
- "capabilityGroup": "api-cli-reference",
6743
- "status": "active",
6744
- "owner": "buildchain-workflows",
6745
- "maturity": "active",
6746
- "introducedVersion": "pre-3.0.2-alpha.4",
6747
- "compatibilityPromise": "preserved-through-the-v3-major-line",
6748
- "deprecationReplacement": "",
6749
- "sunsetCondition": "explicit-breaking-change-review-in-a-future-major-line",
6750
- "nonDuplicationRationale": "Existing workflow identity retained for caller compatibility and repository orchestration."
6751
6631
  }
6752
6632
  ],
6753
6633
  "actionSource": "actions/*/action.yml reverse input enumeration",
@@ -77,7 +77,7 @@ invalid.
77
77
  ## Public self-dogfood and adoption
78
78
 
79
79
  `.github/workflows/self-build-public-consumer-dogfood.yml` remains the exact thin
80
- consumer of the public `v4-stage-capsule-canary.yml@v4-alpha` contract. Its
80
+ consumer of the public `public-build-stage-capsule-canary.yml@v4-alpha` contract. Its
81
81
  declared `lifecycle.verify` runs `pnpm run check`, so the same public path
82
82
  executes pure recovery tests that inject a transient durable-state write
83
83
  failure, restore the adapter operation on a fresh runner, supersede stale work
@@ -110,7 +110,7 @@ artifact_profile_selector = "package"
110
110
  ```
111
111
 
112
112
  The public reusable workflow is
113
- `kungfu-systems/buildchain/.github/workflows/v4-adopter-delivery.yml@v4` for
113
+ `kungfu-systems/buildchain/.github/workflows/public-build-adopter-qualification.yml@v4` for
114
114
  stable use and `@v4-alpha` during prerelease evaluation. It resolves the exact
115
115
  called-workflow SHA, enforces floating selector plus dual-lock consumer
116
116
  admission, and runs the same CLI on Linux, macOS, and Windows. Buildchain
@@ -136,7 +136,7 @@ shadow-only: it does not skip a v3 production stage or move v3 authority.
136
136
  `architecture/v4-stage-capsule-qualification.json` closes the Wave 2
137
137
  qualification boundary. Buildchain and external repositories use the same
138
138
  Buildchain-owned public reusable workflow,
139
- `.github/workflows/v4-stage-capsule-canary.yml`. Buildchain's caller is the thin
139
+ `.github/workflows/public-build-stage-capsule-canary.yml`. Buildchain's caller is the thin
140
140
  `.github/workflows/self-build-public-consumer-dogfood.yml`; it has no steps, copied
141
141
  orchestration, local action, direct qualification invocation, or private
142
142
  consumer profile. Candidate recursion is resolved only by publishing the exact
@@ -56,7 +56,7 @@ receipt creation and verification.
56
56
  ## Reusable workflow
57
57
 
58
58
  Consumers invoke
59
- `kungfu-systems/buildchain/.github/workflows/v4-tail-reseal.yml@v4-alpha` from a
59
+ `kungfu-systems/buildchain/.github/workflows/public-ops-tail-reseal.yml@v4-alpha` from a
60
60
  trusted, same-repository workflow. The caller supplies the rooted request, the
61
61
  original candidate consumer-policy receipt, a reviewed macOS finalization
62
62
  command, and the explicitly named signing secret. The command must write:
@@ -56,6 +56,8 @@ must explain its scope in review. New aliases cannot be invented: compatibility
56
56
  must name an exact migration source with a reason and removal condition.
57
57
  The policy, generator, checker, tests, required CI chain and CODEOWNERS require
58
58
  independent `kungfu-origin` review. No wildcard compatibility admission is allowed.
59
+ Workflow filenames cannot contain version tokens such as `v4` or `v5`.
60
+ Retired aliases cannot be recreated or called; see [path migration](workflow-path-migration.md).
59
61
 
60
62
  A role, category or implementation edit must preserve or deliberately update
61
63
  all related declarations. Run `pnpm run generate:workflows` and
@@ -65,12 +67,12 @@ all related declarations. Run `pnpm run generate:workflows` and
65
67
 
66
68
  | Canonical workflow | Category | Invocation | Status | Purpose | Compatibility path |
67
69
  | --- | --- | --- | --- | --- | --- |
68
- | [public-build-adopter-qualification.yml](../.github/workflows/public-build-adopter-qualification.yml) | build | reusable | active | V4 Adopter Delivery | `v4-adopter-delivery.yml` |
70
+ | [public-build-adopter-qualification.yml](../.github/workflows/public-build-adopter-qualification.yml) | build | reusable | active | V4 Adopter Delivery | |
69
71
  | [public-build-candidate.yml](../.github/workflows/public-build-candidate.yml) | build | reusable | active | Buildchain Channel Build | `build.yml` |
70
72
  | [public-build-check.yml](../.github/workflows/public-build-check.yml) | build | reusable | active | Buildchain Check | `check.yml` |
71
73
  | [public-build-demo.yml](../.github/workflows/public-build-demo.yml) | build | reusable | active | Buildchain Declarative Binary Auditable Demo | `.declarative-auditable-demo.yml` |
72
74
  | [public-build-publication.yml](../.github/workflows/public-build-publication.yml) | build | reusable | active | Buildchain Publication Artifact | `publication-artifact.yml` |
73
- | [public-build-stage-capsule-canary.yml](../.github/workflows/public-build-stage-capsule-canary.yml) | build | reusable | active | V4 Stage Capsule Canary | `v4-stage-capsule-canary.yml` |
75
+ | [public-build-stage-capsule-canary.yml](../.github/workflows/public-build-stage-capsule-canary.yml) | build | reusable | active | V4 Stage Capsule Canary | |
74
76
  | [public-ops-alpha-candidate-patrol.yml](../.github/workflows/public-ops-alpha-candidate-patrol.yml) | ops | reusable | active | Buildchain Dev to Alpha Candidate Patrol | `dev-alpha-candidate-patrol.yml` |
75
77
  | [public-ops-bootstrap-recovery.yml](../.github/workflows/public-ops-bootstrap-recovery.yml) | ops | reusable | active | Universal Buildchain Bootstrap Recovery | `universal-bootstrap-recovery.yml` |
76
78
  | [public-ops-bootstrap.yml](../.github/workflows/public-ops-bootstrap.yml) | ops | reusable | active | Buildchain Universal Bootstrap | `bootstrap.yml` |
@@ -84,7 +86,7 @@ all related declarations. Run `pnpm run generate:workflows` and
84
86
  | [public-ops-patrol.yml](../.github/workflows/public-ops-patrol.yml) | ops | reusable | active | Buildchain Patrol | `buildchain-patrol.yml` |
85
87
  | [public-ops-release-governance.yml](../.github/workflows/public-ops-release-governance.yml) | ops | reusable | active | Release Governance Reconcile | `release-governance-reconcile.yml` |
86
88
  | [public-ops-stable-candidate-patrol.yml](../.github/workflows/public-ops-stable-candidate-patrol.yml) | ops | reusable | active | Buildchain Stable Candidate Patrol | `stable-candidate-patrol.yml` |
87
- | [public-ops-tail-reseal.yml](../.github/workflows/public-ops-tail-reseal.yml) | ops | reusable | active | V4 Retained Candidate Tail Reseal | `v4-tail-reseal.yml` |
89
+ | [public-ops-tail-reseal.yml](../.github/workflows/public-ops-tail-reseal.yml) | ops | reusable | active | V4 Retained Candidate Tail Reseal | |
88
90
  | [public-ops-warrant-cancel.yml](../.github/workflows/public-ops-warrant-cancel.yml) | ops | reusable | active | Dev Delivery Warrant Queued Candidate Cancel | `dev-delivery-warrant-cancel.yml` |
89
91
  | [public-ops-warrant-close.yml](../.github/workflows/public-ops-warrant-close.yml) | ops | reusable | active | Dev Delivery Warrant Close | `dev-delivery-warrant-close.yml` |
90
92
  | [public-release-artifact-attestation.yml](../.github/workflows/public-release-artifact-attestation.yml) | release | reusable | active | Buildchain GitHub Artifact Attestation | `github-artifact-attestation.yml` |
@@ -0,0 +1,109 @@
1
+ ---
2
+ status: draft
3
+ period: ongoing
4
+ theme: workflow-path-migration
5
+ doc_type: migration-guide
6
+ source_level: local-files
7
+ confidence: high
8
+ sensitivity: public
9
+ evidence_grade: B
10
+ review_state: unreviewed
11
+ last_reviewed: 2026-09-06
12
+ ai_provenance:
13
+ model_family: GPT-6
14
+ product: Codex
15
+ generated_at: 2026-09-05
16
+ visible_context: Exact GitHub channel refs and workflow files on 23 organization default branches
17
+ invisible_context_boundary: Other branches, private or unlisted consumers and future floating ref updates were not established by this audit
18
+ ---
19
+
20
+ # Version-prefixed workflow path migration
21
+
22
+ This source change retires three filenames. Their reusable capabilities, inputs,
23
+ outputs, jobs and permission envelopes remain at the canonical paths below.
24
+ Keep the existing channel selector and dual contract-lock policy when migrating.
25
+
26
+ | Retired path | Canonical path |
27
+ | --- | --- |
28
+ | `v4-adopter-delivery.yml` | `public-build-adopter-qualification.yml` |
29
+ | `v4-stage-capsule-canary.yml` | `public-build-stage-capsule-canary.yml` |
30
+ | `v4-tail-reseal.yml` | `public-ops-tail-reseal.yml` |
31
+
32
+ All paths are beneath `.github/workflows/`. The taxonomy gate rejects version
33
+ segments in filenames and calls to version-prefixed Buildchain workflows. An
34
+ explicit retirement record keeps the original migration identity for historical
35
+ metrics and frozen facade source; generators resolve that identity to the
36
+ canonical implementation and cannot recreate the removed file.
37
+
38
+ ## Development merge and channel rollout
39
+
40
+ The development change retires these filenames on `dev/v4/v4.0`, updates the
41
+ Buildchain-owned callers, and enforces the canonical paths through generators
42
+ and required checks. Its delivery boundary is the protected development merge.
43
+ External-repository migration and stable publication are separate follow-up
44
+ work and do not block this development merge.
45
+
46
+ The published channel boundary still requires the following rollout order:
47
+
48
+ 1. Publish and verify the canonical entries on every affected channel while the
49
+ old entries remain available. The admission identity must match the actual
50
+ invoked canonical workflow, rather than its previous filename.
51
+ 2. Migrate consumers on their existing floating channels, refresh locks through
52
+ the supported contract acceptance path if required, and verify real consumer
53
+ runs. Stable callers remain on stable; alpha callers remain on alpha.
54
+ 3. Before publishing the retirement into a channel, recheck its live consumers
55
+ and resolve any remaining old-path calls. A protected development merge does
56
+ not by itself establish this channel readiness.
57
+
58
+ ## Initial consumer readback
59
+
60
+ On 2026-09-05, all workflow files from 23 accessible `kungfu-systems` repository
61
+ _default branches_ were read at their returned Git revisions. Five calls were
62
+ found in three repositories. This is a bounded inventory, not evidence that
63
+ unknown or non-default-branch consumers do not exist.
64
+
65
+ | Repository and observed revision | Caller | Existing selector |
66
+ | --- | --- | --- |
67
+ | Buildchain `d434a73d2d4fb010ee80fede2bf3ce872b1d04c8` | `self-build-adopter-dogfood.yml` | `v4-alpha` |
68
+ | Buildchain `d434a73d2d4fb010ee80fede2bf3ce872b1d04c8` | `self-build-public-consumer-dogfood.yml` | `v4-alpha` |
69
+ | agent-hub-demo `3f5de882b63464d70c50df0fd7ca418f487b794b` | `v4-adopter-delivery-qualification.yml` | `v4-alpha` |
70
+ | agent-hub-demo `3f5de882b63464d70c50df0fd7ca418f487b794b` | `v4-stage-capsule-canary.yml` | `v4` |
71
+ | taolu `6dcccdc3bd2c8b1801c7f6decea08ae7877aac2b` | `verify.yml` | `v4-alpha` |
72
+
73
+ The initial published channel readback was `v4` at
74
+ `da5e2db8384313e899eace87aea0a1a8e28c0aa8` and `v4-alpha` at
75
+ `dd87f43f7122b41c4ce7f1f6d1888521cc7f892f`. Neither contained the three canonical
76
+ filenames at that initial readback. The later evidence below records progress
77
+ without changing the scope or revisions of that initial inventory.
78
+
79
+ ## Rollout evidence as of 2026-09-06
80
+
81
+ The canonical invocation-identity preparation was merged in
82
+ [Buildchain PR 3508](https://github.com/kungfu-systems/buildchain/pull/3508).
83
+ All three canonical paths are available in the immutable `v4.0.2-alpha.35`
84
+ release (`feab078f5d7c9927a3525154003e321700e8ca30`) and the later
85
+ `v4.0.2-alpha.37` release (`f5fa1a4a3e8d83eccee79c077e5f48417760c9df`).
86
+ The floating `v4-alpha` readback selects alpha.37.
87
+
88
+ [Taolu PR 30](https://github.com/kungfu-systems/taolu/pull/30) migrated its
89
+ Stage Capsule call on `@v4-alpha`, preserving the existing dual locks.
90
+ Its exact source `b3f4c12578d733ff44165ff1acafe131251b8907` passed
91
+ [consumer Verify](https://github.com/kungfu-systems/taolu/actions/runs/33975786413)
92
+ on all declared platforms and
93
+ [native delivery](https://github.com/kungfu-systems/taolu/actions/runs/34005576362).
94
+ The protected dev landing is `7e15123733110ad8ce484241934bbf0ef99fbb45`.
95
+
96
+ The stable `v4` readback remains
97
+ `da5e2db8384313e899eace87aea0a1a8e28c0aa8`, which does not contain the canonical
98
+ paths. Stable publication and the agent-hub-demo migration remain **pending**
99
+ outside this development change's completion boundary. The alpha.35
100
+ [Build Surface Fixture](https://github.com/kungfu-systems/buildchain/actions/runs/34005360217)
101
+ passed, but this individual result does not establish complete stable
102
+ qualification or authorize moving the stable channel.
103
+
104
+ ## Recovery
105
+
106
+ Before channel retirement, revert consumer changes to the still-available old
107
+ paths if verification fails. After retirement, restore the exact previous
108
+ provider implementation through a reviewed corrective commit and normal
109
+ publication; do not rewrite immutable release tags or bypass admission checks.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kungfu-tech/buildchain",
3
- "version": "4.0.2-alpha.37",
3
+ "version": "4.0.2-alpha.38",
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",
@@ -244,7 +244,7 @@ invalid.
244
244
  ## Public self-dogfood and adoption
245
245
 
246
246
  \`.github/workflows/self-build-public-consumer-dogfood.yml\` remains the exact thin
247
- consumer of the public \`v4-stage-capsule-canary.yml@v4-alpha\` contract. Its
247
+ consumer of the public \`public-build-stage-capsule-canary.yml@v4-alpha\` contract. Its
248
248
  declared \`lifecycle.verify\` runs \`pnpm run check\`, so the same public path
249
249
  executes pure recovery tests that inject a transient durable-state write
250
250
  failure, restore the adapter operation on a fresh runner, supersede stale work
@@ -148,7 +148,7 @@ export function checkV4FloatingConsumerPolicyContract() {
148
148
  "Resolve controller identities",
149
149
  "Install Buildchain runtime dependencies",
150
150
  ]);
151
- const stageCanary = read(".github/workflows/v4-stage-capsule-canary.yml");
151
+ const stageCanary = read(".github/workflows/public-build-stage-capsule-canary.yml");
152
152
  if (
153
153
  !stageCanary.includes("consumer-admission:") ||
154
154
  !stageCanary.includes("needs: consumer-admission")
@@ -10,7 +10,7 @@ const DEFAULT_ROOT = path.resolve(
10
10
  "..",
11
11
  );
12
12
  const CALLER_PATH = ".github/workflows/self-build-public-consumer-dogfood.yml";
13
- const REUSABLE_PATH = ".github/workflows/v4-stage-capsule-canary.yml";
13
+ const REUSABLE_PATH = ".github/workflows/public-build-stage-capsule-canary.yml";
14
14
  export const V4_PUBLIC_DOGFOOD_ALPHA_REF = "v4-alpha";
15
15
  const PRIVATE_CONSUMER = ["buildchain", "self", "dogfood"].join("-");
16
16
  const PRIVATE_SHADOW = ["kungfu", "shadow"].join("-");
@@ -27,7 +27,7 @@ permissions:
27
27
 
28
28
  jobs:
29
29
  dogfood:
30
- uses: kungfu-systems/buildchain/.github/workflows/v4-stage-capsule-canary.yml@${validationRef}
30
+ uses: kungfu-systems/buildchain/.github/workflows/public-build-stage-capsule-canary.yml@${validationRef}
31
31
  with:
32
32
  consumer: buildchain
33
33
  node-version: "24"
@@ -114,7 +114,7 @@ function assertWorkflowInventory(root) {
114
114
  fail(`${relative} invokes the private qualification script directly`);
115
115
  if (
116
116
  relative !== CALLER_PATH &&
117
- text.includes(".github/workflows/v4-stage-capsule-canary.yml@")
117
+ text.includes(".github/workflows/public-build-stage-capsule-canary.yml@")
118
118
  )
119
119
  fail(`${relative} creates a second v4 dogfood caller`);
120
120
  if (relative !== REUSABLE_PATH && relative !== CALLER_PATH)
@@ -162,7 +162,7 @@ function assertArchitecture(root) {
162
162
  !dogfood ||
163
163
  dogfood.callerWorkflow !== CALLER_PATH ||
164
164
  dogfood.reusableWorkflow !==
165
- "kungfu-systems/buildchain/.github/workflows/v4-stage-capsule-canary.yml" ||
165
+ "kungfu-systems/buildchain/.github/workflows/public-build-stage-capsule-canary.yml" ||
166
166
  dogfood.runtimeBinding !== "job.workflow_sha" ||
167
167
  dogfood.consumerSourceBinding !== "github.sha" ||
168
168
  JSON.stringify(dogfood.executableStages) !==
@@ -1,5 +1,5 @@
1
1
  import assert from "node:assert/strict";
2
- import { projectWorkflowIdentities } from "./workflow-taxonomy.mjs";
2
+ import { currentWorkflowPath, projectWorkflowIdentities } from "./workflow-taxonomy.mjs";
3
3
  import crypto from "node:crypto";
4
4
  import fs from "node:fs";
5
5
  import path from "node:path";
@@ -48,7 +48,7 @@ assert.deepEqual(
48
48
  );
49
49
  for (const relative of contract.inventoryWorkflows)
50
50
  assert.ok(
51
- fs.statSync(path.join(root, relative)).isFile(),
51
+ fs.statSync(path.join(root, currentWorkflowPath(root, relative))).isFile(),
52
52
  `inventoried workflow is unavailable: ${relative}`,
53
53
  );
54
54
  assert.deepEqual(
@@ -87,7 +87,7 @@ for (const relative of contract.bootstrapGovernedWorkflows) {
87
87
  contract.inventoryWorkflows.includes(relative),
88
88
  `Bootstrap-governed workflow is outside the inventory: ${relative}`,
89
89
  );
90
- const source = fs.readFileSync(path.join(root, relative), "utf8");
90
+ const source = fs.readFileSync(path.join(root, currentWorkflowPath(root, relative)), "utf8");
91
91
  assert.ok(
92
92
  relative === contract.bootstrap.publicWorkflow ||
93
93
  /uses:\s+(?:\.\/)?\.github\/workflows\/bootstrap\.yml/u.test(source) ||
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import fs from "node:fs";
3
3
  import crypto from "node:crypto";
4
- import { writeWorkflowSource, rewriteRepositoryWorkflowPaths } from "./workflow-taxonomy.mjs";
4
+ import { currentWorkflowPath, writeWorkflowSource, rewriteRepositoryWorkflowPaths } from "./workflow-taxonomy.mjs";
5
5
  import path from "node:path";
6
6
  import { execFileSync } from "node:child_process";
7
7
  import { fileURLToPath } from "node:url";
@@ -426,14 +426,15 @@ function main() {
426
426
  );
427
427
  }
428
428
  for (const relative of activeFacadePaths()) {
429
- const target = path.join(root, relative);
429
+ const current = currentWorkflowPath(root, relative);
430
+ const target = path.join(root, current);
430
431
  const source = fresh
431
432
  ? frozenFacadeSource(relative)
432
433
  : fs.readFileSync(target, "utf8");
433
434
  if (check) verify(source, relative);
434
435
  else
435
436
  writeWorkflowSource(
436
- root, relative,
437
+ root, current,
437
438
  migrateV4UniversalWorkflowFacade(source, relative),
438
439
  );
439
440
  }
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import crypto from "node:crypto";
3
3
  import fs from "node:fs";
4
+ import { currentWorkflowPath } from "./workflow-taxonomy.mjs";
4
5
  import path from "node:path";
5
6
  import { execFileSync } from "node:child_process";
6
7
  import {
@@ -192,7 +193,7 @@ function executeBootstrapConformance(request, admission) {
192
193
  fail("candidate Bootstrap conformance does not close execution semantics");
193
194
  for (const relative of architecture.bootstrapGovernedWorkflows) {
194
195
  const source = fs.readFileSync(
195
- new URL(`../${relative}`, import.meta.url),
196
+ path.join(path.resolve(import.meta.dirname, ".."), currentWorkflowPath(path.resolve(import.meta.dirname, ".."), relative)),
196
197
  "utf8",
197
198
  );
198
199
  if (
@@ -12,6 +12,7 @@ const ROLES = ["public", "component", "self"];
12
12
  const CATEGORIES = ["build", "release", "ops"];
13
13
  const SLUG = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/u;
14
14
  const WORKFLOW = /^\.github\/workflows\/[.a-z0-9-]+\.ya?ml$/u;
15
+ const VERSION_TOKEN = /(?:^|[.-])v\d+(?:[.-]|$)/iu;
15
16
  const PROTECTED = [
16
17
  TAXONOMY_PATH,
17
18
  "scripts/workflow-taxonomy.mjs",
@@ -40,6 +41,10 @@ function validateEntryRole(entry, errors) {
40
41
  errors.push(`${entry.id}: invalid category`);
41
42
  if (!SLUG.test(entry.purpose || ""))
42
43
  errors.push(`${entry.id}: invalid purpose slug`);
44
+ if (VERSION_TOKEN.test(path.posix.basename(workflowPath(entry))))
45
+ errors.push(
46
+ `${entry.id}: workflow filenames cannot contain version tokens`,
47
+ );
43
48
  for (const field of ["summary", "owner", "rationale"]) {
44
49
  if (typeof entry[field] !== "string" || !entry[field].trim())
45
50
  errors.push(`${entry.id}: missing ${field}`);
@@ -57,6 +62,15 @@ function validateEntryRole(entry, errors) {
57
62
  }
58
63
 
59
64
  function validateMigration(policy, entry, declared, errors) {
65
+ if (entry.retiredAlias) {
66
+ if (
67
+ entry.compatibility ||
68
+ entry.retiredAlias.path !== entry.migration?.previousPath ||
69
+ !entry.retiredAlias.reason?.trim() ||
70
+ entry.retiredAlias.migrationGuide !== "docs/workflow-path-migration.md"
71
+ )
72
+ errors.push(`${entry.id}: invalid alias retirement record`);
73
+ }
60
74
  if (entry.migration) {
61
75
  if (
62
76
  !WORKFLOW.test(entry.migration.previousPath || "") ||
@@ -73,6 +87,10 @@ function validateMigration(policy, entry, declared, errors) {
73
87
  }
74
88
  if (entry.compatibility) {
75
89
  const alias = entry.compatibility;
90
+ if (VERSION_TOKEN.test(path.posix.basename(alias.path || "")))
91
+ errors.push(
92
+ `${entry.id}: version-prefixed compatibility aliases are retired`,
93
+ );
76
94
  if (entry.role === "self")
77
95
  errors.push(
78
96
  `${entry.id}: repository event wrappers cannot have duplicate aliases`,
@@ -167,6 +185,14 @@ function validateWorkflow(root, entry, declared, errors) {
167
185
  const absolute = path.join(root, file);
168
186
  if (!fs.existsSync(absolute) || !fs.lstatSync(absolute).isFile()) return;
169
187
  const text = fs.readFileSync(absolute, "utf8");
188
+ if (
189
+ entry.retiredAlias &&
190
+ text.includes("BUILDCHAIN_INVOKED_WORKFLOW:") &&
191
+ !text.includes(`BUILDCHAIN_INVOKED_WORKFLOW: ${file}\n`)
192
+ )
193
+ errors.push(
194
+ `${file}: consumer admission must bind the canonical invoked workflow`,
195
+ );
170
196
  const document = parseWorkflowDocument(text);
171
197
  if (entry.role === "self")
172
198
  validateRepositoryReferences(file, document, text, declared, errors);
@@ -195,6 +221,13 @@ function validateWorkflow(root, entry, declared, errors) {
195
221
  );
196
222
  }
197
223
  for (const call of parseYamlUses(text)) {
224
+ const remote = call.value.match(
225
+ /^kungfu-systems\/buildchain\/(\.github\/workflows\/[^@]+)@/u,
226
+ );
227
+ if (remote && VERSION_TOKEN.test(path.posix.basename(remote[1])))
228
+ errors.push(
229
+ `${file}:${call.line}: retired version-prefixed workflow call ${remote[1]}`,
230
+ );
198
231
  const local = call.value.match(/^\.\/(\.github\/workflows\/[^@]+)$/u);
199
232
  if (local && !declared.has(local[1]))
200
233
  errors.push(
@@ -276,6 +309,8 @@ export function checkWorkflowTaxonomy(
276
309
  );
277
310
  const observed = new Set(discoverWorkflowFiles(root));
278
311
  for (const file of observed) {
312
+ if (VERSION_TOKEN.test(path.posix.basename(file)))
313
+ errors.push(`workflow filenames cannot contain version tokens: ${file}`);
279
314
  if (!declared.has(file)) errors.push(`unregistered workflow: ${file}`);
280
315
  if (!fs.lstatSync(path.join(root, file)).isFile())
281
316
  errors.push(`workflow must be a regular file: ${file}`);
@@ -334,6 +369,8 @@ export function writeWorkflowSource(root, relative, text) {
334
369
  (item) =>
335
370
  workflowPath(item) === relative || item.compatibility?.path === relative,
336
371
  );
372
+ if (policy?.entries.some((item) => item.retiredAlias?.path === relative))
373
+ throw new Error(`${relative}: cannot regenerate a retired workflow alias`);
337
374
  const outputs = entry
338
375
  ? [
339
376
  workflowPath(entry),
@@ -345,19 +382,10 @@ export function writeWorkflowSource(root, relative, text) {
345
382
 
346
383
  export function rewriteRepositoryWorkflowPaths(root, text) {
347
384
  for (const entry of readWorkflowTaxonomy(root)?.entries || []) {
348
- if (
349
- ["v4-adopter-delivery", "v4-stage-capsule-canary"].includes(entry.id) &&
350
- entry.compatibility
351
- ) {
352
- const canonical = workflowPath(entry);
353
- const legacy = entry.compatibility.path;
354
- text = text.replaceAll(
355
- `BUILDCHAIN_INVOKED_WORKFLOW: ${legacy}\n`,
356
- `BUILDCHAIN_INVOKED_WORKFLOW: \${{ startsWith(job.workflow_ref, 'kungfu-systems/buildchain/${canonical}@') && '${canonical}' || '${legacy}' }}\n`,
357
- );
358
- }
359
385
  if (entry.role === "self" && entry.migration)
360
386
  text = text.replaceAll(entry.migration.previousPath, workflowPath(entry));
387
+ if (entry.retiredAlias)
388
+ text = text.replaceAll(entry.retiredAlias.path, workflowPath(entry));
361
389
  if (entry.id === "build-surface-fixture")
362
390
  text = text.replaceAll(
363
391
  "build-surface-fixture.yml",
@@ -367,6 +395,15 @@ export function rewriteRepositoryWorkflowPaths(root, text) {
367
395
  return text;
368
396
  }
369
397
 
398
+ // Historical inventories and debt ledgers retain their original identity. File
399
+ // access resolves only explicitly retired aliases to the registered implementation.
400
+ export function currentWorkflowPath(root, relative) {
401
+ const entry = readWorkflowTaxonomy(root)?.entries.find(
402
+ (item) => item.retiredAlias?.path === relative,
403
+ );
404
+ return entry ? workflowPath(entry) : relative;
405
+ }
406
+
370
407
  export function workflowCompatibilityIdentity(root, relative, text) {
371
408
  const entry = readWorkflowTaxonomy(root)?.entries.find(
372
409
  (item) => workflowPath(item) === relative && item.compatibility,
@@ -441,6 +478,8 @@ export function renderWorkflowCatalog(policy) {
441
478
  "must name an exact migration source with a reason and removal condition.",
442
479
  "The policy, generator, checker, tests, required CI chain and CODEOWNERS require",
443
480
  "independent `kungfu-origin` review. No wildcard compatibility admission is allowed.",
481
+ "Workflow filenames cannot contain version tokens such as `v4` or `v5`.",
482
+ "Retired aliases cannot be recreated or called; see [path migration](workflow-path-migration.md).",
444
483
  "",
445
484
  "A role, category or implementation edit must preserve or deliberately update",
446
485
  "all related declarations. Run `pnpm run generate:workflows` and",