@kungfu-tech/buildchain 2.11.12 → 2.11.13-alpha.1

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.
@@ -146,6 +146,17 @@ contract:
146
146
  specific package publication. Direct `alpha/*` or `release/*` channel refs are
147
147
  not valid publish source locks when `require-publish-source-lock` is enabled,
148
148
  and a mismatched `publish-source-sha` fails before any promotion or publish side effects begin.
149
+ The reusable promote workflow serializes non-dry-run promotion intents per
150
+ repository and re-reads `target-ref` before checkout, dependency installation,
151
+ release-candidate resolution, or publish-gate writes. If a queued intent asks
152
+ for an older SHA after the protected channel has advanced, the workflow records
153
+ the requested/current SHA pair, verifies that the current target is ahead of
154
+ the requested commit, and exits successfully as a superseded no-op. Diverged,
155
+ behind, or unreadable comparisons still fail closed.
156
+ The action repeats that check at its mutation boundary for governed promotion
157
+ calls, closing the race between workflow preflight and action start. Direct
158
+ non-governed calls and dry-runs keep the strict target mismatch error so local
159
+ diagnostics cannot silently reinterpret a stale request.
149
160
  The reusable build workflow performs the cheaper channel-ref preflight earlier:
150
161
  after source-lock resolution and before the build matrix, it requires the target
151
162
  channel ref such as `alpha/v22/v22.22` or `release/v22/v22.22` to already point
@@ -4,7 +4,7 @@
4
4
  "product": {
5
5
  "name": "Buildchain",
6
6
  "package": "@kungfu-tech/buildchain",
7
- "version": "2.11.12",
7
+ "version": "2.11.13-alpha.1",
8
8
  "repository": "https://github.com/kungfu-systems/buildchain"
9
9
  },
10
10
  "majorLine": "v2",
@@ -92,7 +92,7 @@
92
92
  "GitHub Release passport and evidence publication is delegated to promote-buildchain-ref after the semver release transaction completes"
93
93
  ],
94
94
  "breakingDigest": "sha256:403d2fcdb0c5eabe749e89102defad69745f70a1556707bec7831fcc2e9fa8f8",
95
- "auditDigest": "sha256:db6fe83e886a04221cc2457d3bdf091cd8607083d5c5e4dc87f40220c2436581"
95
+ "auditDigest": "sha256:1d12801725d7fb1849be6eb92bf4b08842c0260f3a2a09c87548870a3c50ae3e"
96
96
  },
97
97
  {
98
98
  "contractVersion": 1,
@@ -434,7 +434,7 @@
434
434
  "manual entries carry source file digests so downstream sites and agents can detect stale hand-written documentation"
435
435
  ],
436
436
  "breakingDigest": "sha256:7d0d2819e3a3e72989d9c57b5efe9d0bc0a79bc0f2c82a0c7b9d6c5a211a91f2",
437
- "auditDigest": "sha256:9398a20c1d1ba4357fd17cb5cd47f7b276d41e6186bf2b495d65e84ffeedf1c4"
437
+ "auditDigest": "sha256:a74f1e2c4c9a2e4dd16be3d7febd36e450aa7905b7c7c449c3800e3f6a64df2a"
438
438
  },
439
439
  {
440
440
  "contractVersion": 1,
@@ -460,5 +460,5 @@
460
460
  }
461
461
  ],
462
462
  "compatibilityDigest": "sha256:967df7e854fdf582294ddfb6403eff25c00db9518a24051e7d47cbd75527c785",
463
- "contractDigest": "sha256:394335bb5c7d0bf96712314a1051fcb8321fe07fd2d76287d3f5e414e97303fb"
463
+ "contractDigest": "sha256:c84a6ab4605ed94362c10df1982b2667fbb10895938166b6f1be8ba7bd299536"
464
464
  }
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
3
  "contract": "kungfu-buildchain-site-bundle",
4
- "generatedAt": "2026-07-10T04:40:14.828Z",
5
- "publishedAt": "2026-07-10T04:40:14.828Z",
4
+ "generatedAt": "2026-07-10T05:53:36.658Z",
5
+ "publishedAt": "2026-07-10T05:53:36.658Z",
6
6
  "reproducible": true,
7
7
  "timestampPolicy": "ci-injected",
8
8
  "deterministicInputs": [
@@ -19,7 +19,7 @@
19
19
  "declared Buildchain surface manifest contract"
20
20
  ],
21
21
  "sourceDateEpoch": "0",
22
- "sourceRevision": "dd0ccdcbfa432e8856ba01735c25b6427a1ff1c0",
22
+ "sourceRevision": "6bd30d696e19cf2b391b190c734e55886daa6ee3",
23
23
  "timestampPolicyDetails": {
24
24
  "contract": "kungfu-buildchain-surface-timestamp-policy",
25
25
  "timestampFields": [
@@ -37,7 +37,7 @@
37
37
  },
38
38
  "package": {
39
39
  "name": "@kungfu-tech/buildchain",
40
- "version": "2.11.12",
40
+ "version": "2.11.13-alpha.1",
41
41
  "versionSource": "package.json#version"
42
42
  },
43
43
  "source": {
@@ -177,7 +177,7 @@
177
177
  ],
178
178
  "maturity": "stable",
179
179
  "sourcePath": "actions/promote-buildchain-ref/README.md",
180
- "digest": "sha256:74939b21339b8d945a428e16119e9a214b670ccfddb6455eb885e35986c40996",
180
+ "digest": "sha256:f1ca20e536f7c0de7ed85784a6b08edfd9aeeb0d2653ec4cff1f4edc2553caf5",
181
181
  "headings": [
182
182
  {
183
183
  "level": 1,
@@ -195,7 +195,7 @@
195
195
  "anchor": "publish-transactions"
196
196
  }
197
197
  ],
198
- "markdown": "# promote-buildchain-ref\n\nInternal buildchain action for promoting verified buildchain release-line and\ncompatibility refs from buildchain release channels:\n\n- `alpha/v2/v2.0` creates or reuses the next exact prerelease tag such as\n `v2.0.1-alpha.0`, writes that version into package version state, points the\n alpha and dev channel branches at the version commit, then promotes\n `v2.0-alpha`;\n- `release/v2/v2.0` creates or reuses the next exact release tag such as\n `v2.0.0`, writes that version into package version state, points the release\n channel branch and release tags at the release commit, then prepares a second\n source commit for the next exact prerelease tag such as `v2.0.1-alpha.0` and\n points the alpha/dev channel branches plus `v2.0-alpha` at that prerelease\n commit;\n- `publish-gate/major` accepts a reviewed PR from a production release line such\n as `release/v2/v2.0`, writes the next major production version such as\n `v3.0.0`, points `publish-gate/major`, `release/v3/v3.0`, `v3.0`, and `v3`\n at that release commit, then prepares `v3.0.1-alpha.0` for\n `alpha/v3/v3.0`, `dev/v3/v3.0`, and `v3.0-alpha`. The older `major-gate`\n branch name is a compatibility alias only.\n\nThe release branch name defines the minor line. For example,\n`release/v2/v2.1` creates `v2.1.N`, promotes `v2.1`, and promotes `v2` only\nwhen the next minor tag such as `v2.2` does not already exist.\n\nThe action updates version state in `lerna.json`, root `package.json`, and\nworkspace package manifests discovered from package manager metadata\n(`package.json` workspaces, `lerna.json` packages, or `pnpm-workspace.yaml`).\nPackage manager detection is adaptive (`pnpm`, `npm`, or `yarn`) and is recorded\nin logs.\n\nRepositories can also provide `buildchain.toml` to declare version-state files\nand `lifecycle.verify`. TOML-configured version files take precedence over\npackage-manager discovery and can target JSON, TOML, or regex-based files. The\nversion commit itself is written through the GitHub Git Data API so the ref\ngraph is the durable source of truth. Repositories without any supported version\nstate degrade to ref-only promotion only when strict version state is disabled.\n\n## Dry Run\n\nUse `dry-run: \"true\"` or the CLI `buildchain release --dry-run` before merging a\nchannel PR when you need to understand what Buildchain would do. This dry-run is\nat the Buildchain release-line level. It explains:\n\n- the legal source branch for the target channel;\n- exact release or alpha tags that would be created or reused;\n- floating tags and channel branches that would move;\n- version-state files and verification lifecycle that would apply;\n- branch protection, PR lineage, and release-from-alpha checks;\n- publish transaction behavior when `lifecycle.publish` or\n `publish-transaction` is enabled.\n\nIt does not move refs, move tags, write package files, run publish commands, or\npublish npm packages. The GitHub action dry-run still calls GitHub APIs to\nresolve the current target SHA and concrete pending ref updates, but every\nwrite is reported as a dry-run update.\n\nRepositories whose package version is anchored to an explicitly selected\nupstream release can opt into manual next-anchor behavior:\n\n```toml\n[version]\nrequired = true\nstrategy = \"anchored\"\nnext = \"manual\"\nmanifest = \"libnode.release.json\"\n```\n\nIn this mode, the action validates the configured version files and anchor\nmanifest through the repository's verify lifecycle, but it does not rewrite the\npackage version to match the Buildchain release tag. After a production\nrelease, it sets `next-anchor-required=true` and does not auto-create the next\nalpha branch or tag. The repository must create the next upstream anchor line\nexplicitly, then run the normal channel promotion flow for that line.\n\nWhen branch protection requires pull requests, generated version-state commits\nstill run through promotion automation first. The action updates\nBuildchain-managed channel protection before generated bookkeeping, adds the\nauthenticated promotion token user or app to the bypass allowlist, creates the\nconfigured required check on the exact generated version-state commit, then\ntries to apply that commit directly. If GitHub still rejects release\nfinalization bookkeeping, Buildchain creates or reuses a same-repository\n`buildchain/version-state/*` PR based on the current target channel head and\nreturns `finalization-needed=true`; a later idempotent promotion run can resume\nfrom the durable transaction state. Strict alpha promotion still fails with a\nconfiguration diagnostic instead of opening a post-publish human PR. Reusable\nwrapper callers should allow `checks: write` so the generated check is owned by\nGitHub Actions and matches the managed branch protection rule.\n\nFor Buildchain-owned automation, callers may pass\n`branch-protection-bypass-apps`, `branch-protection-bypass-users`, or\n`branch-protection-bypass-teams`. The action still configures managed\n`dev/vN/vN.M`, `alpha/vN/vN.M`, and `release/vN/vN.M` branches with one\nrequired approving review, strict GitHub Actions checks, admin enforcement,\nconversation resolution, no force pushes, and no deletions; the bypass\nallowance only lets the named automation identity apply generated version-state\nor channel bookkeeping without a second human review after the reviewed channel\nPR has already merged. Direct action calls automatically include the current\npromotion token's authenticated user or app when GitHub exposes it; explicit\ninputs are supplemental allowlist entries for less discoverable release\nauthorities.\n\n## Publish Transactions\n\nPromotion can also own external publish side effects. Enable this only from a\ntrusted channel workflow:\n\n```yaml\n- uses: kungfu-systems/buildchain/actions/promote-buildchain-ref@v2\n with:\n token: ${{ secrets.BUILDCHAIN_PROMOTION_TOKEN }}\n generated-ref-update-token: ${{ secrets.BUILDCHAIN_PROMOTION_TOKEN }}\n sha: ${{ github.sha }}\n target-ref: release/v2/v2.0\n publish-transaction: \"true\"\n publish-mode: publish-final-version\n publish-auth: trusted-publishing\n publish-required-artifacts-json: >-\n [\n {\"kind\":\"npm\",\"name\":\"@kungfu-tech/buildchain\",\"ref\":\"2.0.0\",\"digest\":\"sha256:...\"}\n ]\n```\n\nFor anchored/manual package repositories that build through the reusable\nworkflow, keep the publish entrypoint on the `publish-gate/*` source-lock\ncontract:\n\n```yaml\n- uses: kungfu-systems/buildchain/actions/promote-buildchain-ref@v2\n with:\n token: ${{ secrets.BUILDCHAIN_PROMOTION_TOKEN }}\n sha: ${{ needs.build.outputs.publish-source-sha }}\n target-ref: release/v22/v22.22\n require-publish-source-lock: \"true\"\n publish-source-ref: ${{ needs.build.outputs.publish-source-ref }}\n publish-source-sha: ${{ needs.build.outputs.publish-source-sha }}\n publish-source-locked: ${{ needs.build.outputs.publish-source-locked }}\n publish-transaction: \"true\"\n publish-mode: publish-final-version\n publish-auth: trusted-publishing\n```\n\n`target-ref` remains the channel promotion target that must point at `sha`.\n`publish-source-ref` is the reviewed source-lock branch that authorized this\nspecific package publication. Direct `alpha/*` or `release/*` channel refs are\nnot valid publish source locks when `require-publish-source-lock` is enabled,\nand a mismatched `publish-source-sha` fails before any promotion or publish side effects begin.\nThe reusable build workflow performs the cheaper channel-ref preflight earlier:\nafter source-lock resolution and before the build matrix, it requires the target\nchannel ref such as `alpha/v22/v22.22` or `release/v22/v22.22` to already point\nat the locked `publish-source-sha`. If not, maintainers should merge the source\ncommit through the channel PR first.\n\nFor promote-only release candidates, attach the PR-stage reusable build evidence\nand fail before publish-gate side effects if it no longer matches:\n\n```yaml\n- uses: kungfu-systems/buildchain/actions/promote-buildchain-ref@v2\n with:\n token: ${{ secrets.BUILDCHAIN_PROMOTION_TOKEN }}\n sha: ${{ needs.build.outputs.publish-source-sha }}\n target-ref: alpha/v22/v22.22\n promote-only-release-candidate: \"true\"\n release-candidate-passport-path: .buildchain/artifacts/release-candidate-passport.json\n release-candidate-build-summary-path: .buildchain/artifacts/build-summary.json\n```\n\nThe action validates repository, channel, source identity, platform matrix, and\nthe aggregate build-summary hash before it writes version state, opens\nrelease-state, runs publish transaction logic, or moves tags/branches. Source\nidentity accepts the exact source SHA, the PR merge ref SHA, or the promoted\nchannel HEAD's Git tree SHA matching the passport tree hash. If validation\nfails, run or attach the verified channel PR build first instead of promoting a\nstale or unproven artifact set.\n\nWhen enabled, the action creates or resumes a release transaction keyed by\nrepository, version, source SHA, and target ref. It persists that transaction to\na machine-managed branch under `buildchain/release-state/<version>`, with\n`state.json` and, once available, `evidence.json`. Fresh GitHub runners read\nthat durable ref before running publish, so reruns do not depend on a previous\nrunner's local `.buildchain` directory.\n\nThe action runs `lifecycle.publish` from `buildchain.toml` or the explicit\n`publish-command` input, then validates publish evidence before exact tags and\nfloating refs move. If durable state persistence fails, the action fails closed\nbefore publish or public ref finalization.\n\n`publish-mode` defaults to `publish-final-version`, the token-free path for\nnormal npm Trusted Publishing. Same-version alpha-to-latest recovery must be\ndeclared as `publish-mode: promote-existing-version` and\n`publish-auth: npm-token`; Buildchain runs `npm whoami` before it creates\nrelease-state or moves any `npm dist-tag`. The Trusted Publishing mode is not\nallowed to perform `npm dist-tag add`.\n\nBuildchain itself uses this path for npm. Its `lifecycle.publish` runs\n`node scripts/npm-publish-transaction.mjs`, which publishes\n`@kungfu-tech/buildchain` through npm Trusted Publishing and writes npm\nartifact evidence into the transaction before release refs move. The separate\n`.github/workflows/npm-publish.yml` workflow is dry-run only.\n\nPublish lifecycle environment:\n\n```text\nBUILDCHAIN_VERSION\nBUILDCHAIN_CHANNEL\nBUILDCHAIN_SOURCE_SHA\nBUILDCHAIN_TARGET_REF\nBUILDCHAIN_RELEASE_STATE\nBUILDCHAIN_EVIDENCE_DIR\nBUILDCHAIN_RELEASE_SHA\nBUILDCHAIN_RELEASE_MATERIAL_SHA\nBUILDCHAIN_PUBLISH_TOOLING_SHA\nBUILDCHAIN_PUBLISH_EVIDENCE\n```\n\nThe action outputs `transaction-id`, `transaction-state`,\n`transaction-exact-tag`, `public-release-tag`, `transaction-release-sha`,\n`transaction-state-ref`, `transaction-state-sha`, `transaction-state-path`,\n`publish-evidence-path`, and `release-passport-path`, `release-passport-output-dir`,\n`release-passport-state-sha`, and `finalization-needed`.\n`transaction-state-ref` is the durable recovery location.\n`release-passport-state-sha` is the durable ref commit after the generated\n`release-passport/*` files have been uploaded into that recovery ref.\n`finalization-needed=true` means publish evidence is valid, but protected branch\nor ref finalization needs a later idempotent promotion run. For release\nfinalization, Buildchain may create a same-repository generated version-state\nPR when GitHub rejects the direct protected ref update; that PR is Buildchain\nbookkeeping, not a consumer-authored release change.\nSet `github-release: \"true\"` when the semver promotion should also publish the\npublic GitHub Release. After the release transaction reaches `complete` and\n`finalization-needed` is false, the action creates or updates the GitHub Release\nfor `public-release-tag`, applies deterministic semver metadata\n(`prerelease=true` and `make_latest=false` for prerelease tags, latest for stable\ntags), and uploads the publish evidence file plus generated release passport\nassets. For anchored/manual package releases, `public-release-tag` is derived\nfrom the published package version, while `transaction-exact-tag` remains the\ninternal Buildchain transaction ref for recovery and audit. If the transaction is\nnot complete yet, the action defers GitHub Release publication to the next\nidempotent promotion run.\n\nAfter a publish transaction reaches `complete`, the action generates the unified\n`buildchain-release-passport` in `.buildchain/release-passport` by default and\npersists those files under `release-passport/` in the durable release-state ref.\nSet `release-passport-product-name` to record the consumer product name, for\nexample `Libnode`, instead of the default `Buildchain`.\nSet `release-passport-kfd-1-witness-jsons` to newline-separated KFD-1\ncontract-world witness JSON paths when released artifacts must prove\nbyte-for-byte KFD contract surfaces. Buildchain imports the KFD metadata from\n`@kungfu-tech/kfd`, freezes the witness, verifies artifact bytes, and writes the\nresult under the KFD-provided `kfd-1` passport section.\nSet `release-passport-kfd-2-claim-jsons` to newline-separated KFD-2 public\nrelease trust claim JSON paths when a release makes additional human/agent\nvisible claims. Buildchain requires each public claim to bind declared sources,\nmachine-readable evidence, hashes, artifact coordinates, verification results,\naudit boundary, responsibility state, and residual risk. Unbound claims fail\npassport verification; prose-only claims downgrade the KFD-2 audit.\nSet `release-passport-kfd-3-prebuild-witness-jsons` to newline-separated KFD-3\ncollaboration-interface pre-build witness paths, then provide artifact-side\nevidence with `release-passport-kfd-3-artifact-witness-jsons` or a\nproduct-owned `release-passport-kfd-3-artifact-verify-command` such as\n`kungfu agent verify --json`. Buildchain compares declared shipped public\nsurfaces with artifact-exposed public surfaces and writes the result under the\nKFD-provided `kfd-3` passport section.\nBuildchain's own release workflow sets `release-passport-buildchain-self-kfd:\n\"true\"`. In that mode the action generates Buildchain-owned KFD-1/2/3 witnesses\ninside the final version-state workspace, after the release transaction has\nmaterialized generated files such as `package.json` and `dist/site/*`. This\nkeeps self-hosted KFD witness hashes bound to the exact published package\ninstead of to a pre-promotion checkout.\nWhen present, the passport includes the aggregate build summary, platform\nartifact manifests, npm publish evidence, dist-tag promotion evidence, the\nrelease-state ref, trusted publishing metadata, and the Buildchain transaction\nresult. After the first passport upload, Buildchain backfills the durable\nrelease-state SHA into `buildchain.release.json` and persists the passport\nagain, so the consumer-side passport is a complete audit entrypoint. Set\n`release-passport: \"false\"` only for a controlled recovery run that must skip\npassport generation.\n\nFinalization recovery is anchored to the durable transaction, not to a single\nworkflow run SHA. After generated version-state bookkeeping is applied, the\ncurrent channel head can be the generated version-state commit or a historical\nmerge commit that contains or corresponds to the recorded `release_material_sha`;\nit does not have to equal the original `source_sha` or the transaction\n`release_sha`. Reruns accept exact tags that already point at the transaction\nrelease/material SHA or the finalized channel head, and continue moving any\nmissing floating tags or dev/alpha refs before marking the transaction\n`complete`.\n\nNormal reruns accept already-published artifacts only when evidence matches.\nMissing required artifacts can be published on the next run. Conflicting\nartifacts put the transaction into `repair_required`; `abandoned` and\n`failed_permanently` also fail closed unless `publish-transaction-override` is\nset for a controlled repair.\n\nIn strict buildchain promotion, ref movement is also gated by the old ABV\ngovernance semantics:\n\n- the target channel branch protection details must be readable, must enforce\n protection for administrators, and must require approving PR review plus the\n strict `check` job from the `Verify` workflow;\n- alpha promotion must come from a merged same-repository PR\n `dev/vN/vN.M -> alpha/vN/vN.M`, or from a strict same-line\n `publish-gate/alpha/vN/vN.M/<version> -> alpha/vN/vN.M` source-lock PR;\n- release promotion must come from a merged same-repository PR\n `alpha/vN/vN.M -> release/vN/vN.M`, or from a strict same-line\n `publish-gate/release/vN/vN.M/<version> -> release/vN/vN.M` source-lock PR;\n- major promotion must come from a merged same-repository PR\n `release/vN/vN.M -> publish-gate/major`;\n- release promotion must have an exact alpha tag for the same patch line, and\n the release source tree must match that alpha tag tree, so release does not\n introduce new code after alpha;\n- anchored/manual release promotion may differ from that alpha tree only in\n declared `version.files` and the configured anchor manifest, and only when the\n checked-out release material has passed `lifecycle.verify` or the explicit\n `verification-command`;\n- generated release and next-alpha version-state trees can be verified locally\n with either the `verification-command` input or `buildchain.toml`\n `lifecycle.verify` before any tags or channel refs move.\n\nThe promotion workflow should use `BUILDCHAIN_PROMOTION_TOKEN` for non-dry-run\npromotion. The token is the buildchain equivalent of the old ABV runner release\nauthority: protected branch review and check rules guard human channel merges,\nwhile the reusable build trust gate now checks the source-lock channel HEAD and\nmerged same-repository PR lineage before heavy build runners start. This action\nstill independently rechecks PR lineage, alpha/release tree equivalence, and\ngenerated version-state verification before moving channel refs and tags.\nGenerated version-state direct ref updates can use a separate\n`generated-ref-update-token`; the reusable wrapper defaults it to\n`secrets.BUILDCHAIN_PROMOTION_TOKEN || github.token`. Consumers that protect\n`dev/*`, `alpha/*`, or `release/*` with one required review should configure\n`BUILDCHAIN_PROMOTION_TOKEN` as the bypass-capable release authority, so\npost-publish dev/alpha/release bookkeeping completes without a human PR.\nThe reusable `release-candidate-promote.yml` wrapper defaults\n`branch-protection-bypass-apps` to `github-actions`, so flow-internal promotion\ncan complete generated `dev`/`alpha`/`release` bookkeeping while ordinary human\npushes and PR merges remain governed by the one-review branch protection rule.\nThe promotion action also auto-discovers the current token's authenticated user\nor app and adds it to the managed bypass allowlist, so consumers do not have to\ndeclare the same release authority twice.\n\nThe tag names intentionally follow the old ABV release semantics:\nexact release tags are `vX.Y.Z`, exact alpha tags are `vX.Y.Z-alpha.N`, floating\nrelease tags are minor/major tags such as `v2.0` and `v2`, and floating alpha\ntags are minor-line tags such as `v2.0-alpha`. Bare tags such as `1.0.0` are not\nmaintained as buildchain release entrypoints.\n\nRepository rulesets should protect exact tags, not every `v*` tag. A ruleset\nsuch as `refs/tags/v*` also protects floating channel tags like `v2.0-alpha`,\nwhich Buildchain must update after exact tags and publish evidence are durable.\nUse an exact-tag rule such as `refs/tags/v*.*.*` for immutable evidence tags and\nleave floating channel tags mutable for the promotion token."
198
+ "markdown": "# promote-buildchain-ref\n\nInternal buildchain action for promoting verified buildchain release-line and\ncompatibility refs from buildchain release channels:\n\n- `alpha/v2/v2.0` creates or reuses the next exact prerelease tag such as\n `v2.0.1-alpha.0`, writes that version into package version state, points the\n alpha and dev channel branches at the version commit, then promotes\n `v2.0-alpha`;\n- `release/v2/v2.0` creates or reuses the next exact release tag such as\n `v2.0.0`, writes that version into package version state, points the release\n channel branch and release tags at the release commit, then prepares a second\n source commit for the next exact prerelease tag such as `v2.0.1-alpha.0` and\n points the alpha/dev channel branches plus `v2.0-alpha` at that prerelease\n commit;\n- `publish-gate/major` accepts a reviewed PR from a production release line such\n as `release/v2/v2.0`, writes the next major production version such as\n `v3.0.0`, points `publish-gate/major`, `release/v3/v3.0`, `v3.0`, and `v3`\n at that release commit, then prepares `v3.0.1-alpha.0` for\n `alpha/v3/v3.0`, `dev/v3/v3.0`, and `v3.0-alpha`. The older `major-gate`\n branch name is a compatibility alias only.\n\nThe release branch name defines the minor line. For example,\n`release/v2/v2.1` creates `v2.1.N`, promotes `v2.1`, and promotes `v2` only\nwhen the next minor tag such as `v2.2` does not already exist.\n\nThe action updates version state in `lerna.json`, root `package.json`, and\nworkspace package manifests discovered from package manager metadata\n(`package.json` workspaces, `lerna.json` packages, or `pnpm-workspace.yaml`).\nPackage manager detection is adaptive (`pnpm`, `npm`, or `yarn`) and is recorded\nin logs.\n\nRepositories can also provide `buildchain.toml` to declare version-state files\nand `lifecycle.verify`. TOML-configured version files take precedence over\npackage-manager discovery and can target JSON, TOML, or regex-based files. The\nversion commit itself is written through the GitHub Git Data API so the ref\ngraph is the durable source of truth. Repositories without any supported version\nstate degrade to ref-only promotion only when strict version state is disabled.\n\n## Dry Run\n\nUse `dry-run: \"true\"` or the CLI `buildchain release --dry-run` before merging a\nchannel PR when you need to understand what Buildchain would do. This dry-run is\nat the Buildchain release-line level. It explains:\n\n- the legal source branch for the target channel;\n- exact release or alpha tags that would be created or reused;\n- floating tags and channel branches that would move;\n- version-state files and verification lifecycle that would apply;\n- branch protection, PR lineage, and release-from-alpha checks;\n- publish transaction behavior when `lifecycle.publish` or\n `publish-transaction` is enabled.\n\nIt does not move refs, move tags, write package files, run publish commands, or\npublish npm packages. The GitHub action dry-run still calls GitHub APIs to\nresolve the current target SHA and concrete pending ref updates, but every\nwrite is reported as a dry-run update.\n\nRepositories whose package version is anchored to an explicitly selected\nupstream release can opt into manual next-anchor behavior:\n\n```toml\n[version]\nrequired = true\nstrategy = \"anchored\"\nnext = \"manual\"\nmanifest = \"libnode.release.json\"\n```\n\nIn this mode, the action validates the configured version files and anchor\nmanifest through the repository's verify lifecycle, but it does not rewrite the\npackage version to match the Buildchain release tag. After a production\nrelease, it sets `next-anchor-required=true` and does not auto-create the next\nalpha branch or tag. The repository must create the next upstream anchor line\nexplicitly, then run the normal channel promotion flow for that line.\n\nWhen branch protection requires pull requests, generated version-state commits\nstill run through promotion automation first. The action updates\nBuildchain-managed channel protection before generated bookkeeping, adds the\nauthenticated promotion token user or app to the bypass allowlist, creates the\nconfigured required check on the exact generated version-state commit, then\ntries to apply that commit directly. If GitHub still rejects release\nfinalization bookkeeping, Buildchain creates or reuses a same-repository\n`buildchain/version-state/*` PR based on the current target channel head and\nreturns `finalization-needed=true`; a later idempotent promotion run can resume\nfrom the durable transaction state. Strict alpha promotion still fails with a\nconfiguration diagnostic instead of opening a post-publish human PR. Reusable\nwrapper callers should allow `checks: write` so the generated check is owned by\nGitHub Actions and matches the managed branch protection rule.\n\nFor Buildchain-owned automation, callers may pass\n`branch-protection-bypass-apps`, `branch-protection-bypass-users`, or\n`branch-protection-bypass-teams`. The action still configures managed\n`dev/vN/vN.M`, `alpha/vN/vN.M`, and `release/vN/vN.M` branches with one\nrequired approving review, strict GitHub Actions checks, admin enforcement,\nconversation resolution, no force pushes, and no deletions; the bypass\nallowance only lets the named automation identity apply generated version-state\nor channel bookkeeping without a second human review after the reviewed channel\nPR has already merged. Direct action calls automatically include the current\npromotion token's authenticated user or app when GitHub exposes it; explicit\ninputs are supplemental allowlist entries for less discoverable release\nauthorities.\n\n## Publish Transactions\n\nPromotion can also own external publish side effects. Enable this only from a\ntrusted channel workflow:\n\n```yaml\n- uses: kungfu-systems/buildchain/actions/promote-buildchain-ref@v2\n with:\n token: ${{ secrets.BUILDCHAIN_PROMOTION_TOKEN }}\n generated-ref-update-token: ${{ secrets.BUILDCHAIN_PROMOTION_TOKEN }}\n sha: ${{ github.sha }}\n target-ref: release/v2/v2.0\n publish-transaction: \"true\"\n publish-mode: publish-final-version\n publish-auth: trusted-publishing\n publish-required-artifacts-json: >-\n [\n {\"kind\":\"npm\",\"name\":\"@kungfu-tech/buildchain\",\"ref\":\"2.0.0\",\"digest\":\"sha256:...\"}\n ]\n```\n\nFor anchored/manual package repositories that build through the reusable\nworkflow, keep the publish entrypoint on the `publish-gate/*` source-lock\ncontract:\n\n```yaml\n- uses: kungfu-systems/buildchain/actions/promote-buildchain-ref@v2\n with:\n token: ${{ secrets.BUILDCHAIN_PROMOTION_TOKEN }}\n sha: ${{ needs.build.outputs.publish-source-sha }}\n target-ref: release/v22/v22.22\n require-publish-source-lock: \"true\"\n publish-source-ref: ${{ needs.build.outputs.publish-source-ref }}\n publish-source-sha: ${{ needs.build.outputs.publish-source-sha }}\n publish-source-locked: ${{ needs.build.outputs.publish-source-locked }}\n publish-transaction: \"true\"\n publish-mode: publish-final-version\n publish-auth: trusted-publishing\n```\n\n`target-ref` remains the channel promotion target that must point at `sha`.\n`publish-source-ref` is the reviewed source-lock branch that authorized this\nspecific package publication. Direct `alpha/*` or `release/*` channel refs are\nnot valid publish source locks when `require-publish-source-lock` is enabled,\nand a mismatched `publish-source-sha` fails before any promotion or publish side effects begin.\nThe reusable promote workflow serializes non-dry-run promotion intents per\nrepository and re-reads `target-ref` before checkout, dependency installation,\nrelease-candidate resolution, or publish-gate writes. If a queued intent asks\nfor an older SHA after the protected channel has advanced, the workflow records\nthe requested/current SHA pair, verifies that the current target is ahead of\nthe requested commit, and exits successfully as a superseded no-op. Diverged,\nbehind, or unreadable comparisons still fail closed.\nThe action repeats that check at its mutation boundary for governed promotion\ncalls, closing the race between workflow preflight and action start. Direct\nnon-governed calls and dry-runs keep the strict target mismatch error so local\ndiagnostics cannot silently reinterpret a stale request.\nThe reusable build workflow performs the cheaper channel-ref preflight earlier:\nafter source-lock resolution and before the build matrix, it requires the target\nchannel ref such as `alpha/v22/v22.22` or `release/v22/v22.22` to already point\nat the locked `publish-source-sha`. If not, maintainers should merge the source\ncommit through the channel PR first.\n\nFor promote-only release candidates, attach the PR-stage reusable build evidence\nand fail before publish-gate side effects if it no longer matches:\n\n```yaml\n- uses: kungfu-systems/buildchain/actions/promote-buildchain-ref@v2\n with:\n token: ${{ secrets.BUILDCHAIN_PROMOTION_TOKEN }}\n sha: ${{ needs.build.outputs.publish-source-sha }}\n target-ref: alpha/v22/v22.22\n promote-only-release-candidate: \"true\"\n release-candidate-passport-path: .buildchain/artifacts/release-candidate-passport.json\n release-candidate-build-summary-path: .buildchain/artifacts/build-summary.json\n```\n\nThe action validates repository, channel, source identity, platform matrix, and\nthe aggregate build-summary hash before it writes version state, opens\nrelease-state, runs publish transaction logic, or moves tags/branches. Source\nidentity accepts the exact source SHA, the PR merge ref SHA, or the promoted\nchannel HEAD's Git tree SHA matching the passport tree hash. If validation\nfails, run or attach the verified channel PR build first instead of promoting a\nstale or unproven artifact set.\n\nWhen enabled, the action creates or resumes a release transaction keyed by\nrepository, version, source SHA, and target ref. It persists that transaction to\na machine-managed branch under `buildchain/release-state/<version>`, with\n`state.json` and, once available, `evidence.json`. Fresh GitHub runners read\nthat durable ref before running publish, so reruns do not depend on a previous\nrunner's local `.buildchain` directory.\n\nThe action runs `lifecycle.publish` from `buildchain.toml` or the explicit\n`publish-command` input, then validates publish evidence before exact tags and\nfloating refs move. If durable state persistence fails, the action fails closed\nbefore publish or public ref finalization.\n\n`publish-mode` defaults to `publish-final-version`, the token-free path for\nnormal npm Trusted Publishing. Same-version alpha-to-latest recovery must be\ndeclared as `publish-mode: promote-existing-version` and\n`publish-auth: npm-token`; Buildchain runs `npm whoami` before it creates\nrelease-state or moves any `npm dist-tag`. The Trusted Publishing mode is not\nallowed to perform `npm dist-tag add`.\n\nBuildchain itself uses this path for npm. Its `lifecycle.publish` runs\n`node scripts/npm-publish-transaction.mjs`, which publishes\n`@kungfu-tech/buildchain` through npm Trusted Publishing and writes npm\nartifact evidence into the transaction before release refs move. The separate\n`.github/workflows/npm-publish.yml` workflow is dry-run only.\n\nPublish lifecycle environment:\n\n```text\nBUILDCHAIN_VERSION\nBUILDCHAIN_CHANNEL\nBUILDCHAIN_SOURCE_SHA\nBUILDCHAIN_TARGET_REF\nBUILDCHAIN_RELEASE_STATE\nBUILDCHAIN_EVIDENCE_DIR\nBUILDCHAIN_RELEASE_SHA\nBUILDCHAIN_RELEASE_MATERIAL_SHA\nBUILDCHAIN_PUBLISH_TOOLING_SHA\nBUILDCHAIN_PUBLISH_EVIDENCE\n```\n\nThe action outputs `transaction-id`, `transaction-state`,\n`transaction-exact-tag`, `public-release-tag`, `transaction-release-sha`,\n`transaction-state-ref`, `transaction-state-sha`, `transaction-state-path`,\n`publish-evidence-path`, and `release-passport-path`, `release-passport-output-dir`,\n`release-passport-state-sha`, and `finalization-needed`.\n`transaction-state-ref` is the durable recovery location.\n`release-passport-state-sha` is the durable ref commit after the generated\n`release-passport/*` files have been uploaded into that recovery ref.\n`finalization-needed=true` means publish evidence is valid, but protected branch\nor ref finalization needs a later idempotent promotion run. For release\nfinalization, Buildchain may create a same-repository generated version-state\nPR when GitHub rejects the direct protected ref update; that PR is Buildchain\nbookkeeping, not a consumer-authored release change.\nSet `github-release: \"true\"` when the semver promotion should also publish the\npublic GitHub Release. After the release transaction reaches `complete` and\n`finalization-needed` is false, the action creates or updates the GitHub Release\nfor `public-release-tag`, applies deterministic semver metadata\n(`prerelease=true` and `make_latest=false` for prerelease tags, latest for stable\ntags), and uploads the publish evidence file plus generated release passport\nassets. For anchored/manual package releases, `public-release-tag` is derived\nfrom the published package version, while `transaction-exact-tag` remains the\ninternal Buildchain transaction ref for recovery and audit. If the transaction is\nnot complete yet, the action defers GitHub Release publication to the next\nidempotent promotion run.\n\nAfter a publish transaction reaches `complete`, the action generates the unified\n`buildchain-release-passport` in `.buildchain/release-passport` by default and\npersists those files under `release-passport/` in the durable release-state ref.\nSet `release-passport-product-name` to record the consumer product name, for\nexample `Libnode`, instead of the default `Buildchain`.\nSet `release-passport-kfd-1-witness-jsons` to newline-separated KFD-1\ncontract-world witness JSON paths when released artifacts must prove\nbyte-for-byte KFD contract surfaces. Buildchain imports the KFD metadata from\n`@kungfu-tech/kfd`, freezes the witness, verifies artifact bytes, and writes the\nresult under the KFD-provided `kfd-1` passport section.\nSet `release-passport-kfd-2-claim-jsons` to newline-separated KFD-2 public\nrelease trust claim JSON paths when a release makes additional human/agent\nvisible claims. Buildchain requires each public claim to bind declared sources,\nmachine-readable evidence, hashes, artifact coordinates, verification results,\naudit boundary, responsibility state, and residual risk. Unbound claims fail\npassport verification; prose-only claims downgrade the KFD-2 audit.\nSet `release-passport-kfd-3-prebuild-witness-jsons` to newline-separated KFD-3\ncollaboration-interface pre-build witness paths, then provide artifact-side\nevidence with `release-passport-kfd-3-artifact-witness-jsons` or a\nproduct-owned `release-passport-kfd-3-artifact-verify-command` such as\n`kungfu agent verify --json`. Buildchain compares declared shipped public\nsurfaces with artifact-exposed public surfaces and writes the result under the\nKFD-provided `kfd-3` passport section.\nBuildchain's own release workflow sets `release-passport-buildchain-self-kfd:\n\"true\"`. In that mode the action generates Buildchain-owned KFD-1/2/3 witnesses\ninside the final version-state workspace, after the release transaction has\nmaterialized generated files such as `package.json` and `dist/site/*`. This\nkeeps self-hosted KFD witness hashes bound to the exact published package\ninstead of to a pre-promotion checkout.\nWhen present, the passport includes the aggregate build summary, platform\nartifact manifests, npm publish evidence, dist-tag promotion evidence, the\nrelease-state ref, trusted publishing metadata, and the Buildchain transaction\nresult. After the first passport upload, Buildchain backfills the durable\nrelease-state SHA into `buildchain.release.json` and persists the passport\nagain, so the consumer-side passport is a complete audit entrypoint. Set\n`release-passport: \"false\"` only for a controlled recovery run that must skip\npassport generation.\n\nFinalization recovery is anchored to the durable transaction, not to a single\nworkflow run SHA. After generated version-state bookkeeping is applied, the\ncurrent channel head can be the generated version-state commit or a historical\nmerge commit that contains or corresponds to the recorded `release_material_sha`;\nit does not have to equal the original `source_sha` or the transaction\n`release_sha`. Reruns accept exact tags that already point at the transaction\nrelease/material SHA or the finalized channel head, and continue moving any\nmissing floating tags or dev/alpha refs before marking the transaction\n`complete`.\n\nNormal reruns accept already-published artifacts only when evidence matches.\nMissing required artifacts can be published on the next run. Conflicting\nartifacts put the transaction into `repair_required`; `abandoned` and\n`failed_permanently` also fail closed unless `publish-transaction-override` is\nset for a controlled repair.\n\nIn strict buildchain promotion, ref movement is also gated by the old ABV\ngovernance semantics:\n\n- the target channel branch protection details must be readable, must enforce\n protection for administrators, and must require approving PR review plus the\n strict `check` job from the `Verify` workflow;\n- alpha promotion must come from a merged same-repository PR\n `dev/vN/vN.M -> alpha/vN/vN.M`, or from a strict same-line\n `publish-gate/alpha/vN/vN.M/<version> -> alpha/vN/vN.M` source-lock PR;\n- release promotion must come from a merged same-repository PR\n `alpha/vN/vN.M -> release/vN/vN.M`, or from a strict same-line\n `publish-gate/release/vN/vN.M/<version> -> release/vN/vN.M` source-lock PR;\n- major promotion must come from a merged same-repository PR\n `release/vN/vN.M -> publish-gate/major`;\n- release promotion must have an exact alpha tag for the same patch line, and\n the release source tree must match that alpha tag tree, so release does not\n introduce new code after alpha;\n- anchored/manual release promotion may differ from that alpha tree only in\n declared `version.files` and the configured anchor manifest, and only when the\n checked-out release material has passed `lifecycle.verify` or the explicit\n `verification-command`;\n- generated release and next-alpha version-state trees can be verified locally\n with either the `verification-command` input or `buildchain.toml`\n `lifecycle.verify` before any tags or channel refs move.\n\nThe promotion workflow should use `BUILDCHAIN_PROMOTION_TOKEN` for non-dry-run\npromotion. The token is the buildchain equivalent of the old ABV runner release\nauthority: protected branch review and check rules guard human channel merges,\nwhile the reusable build trust gate now checks the source-lock channel HEAD and\nmerged same-repository PR lineage before heavy build runners start. This action\nstill independently rechecks PR lineage, alpha/release tree equivalence, and\ngenerated version-state verification before moving channel refs and tags.\nGenerated version-state direct ref updates can use a separate\n`generated-ref-update-token`; the reusable wrapper defaults it to\n`secrets.BUILDCHAIN_PROMOTION_TOKEN || github.token`. Consumers that protect\n`dev/*`, `alpha/*`, or `release/*` with one required review should configure\n`BUILDCHAIN_PROMOTION_TOKEN` as the bypass-capable release authority, so\npost-publish dev/alpha/release bookkeeping completes without a human PR.\nThe reusable `release-candidate-promote.yml` wrapper defaults\n`branch-protection-bypass-apps` to `github-actions`, so flow-internal promotion\ncan complete generated `dev`/`alpha`/`release` bookkeeping while ordinary human\npushes and PR merges remain governed by the one-review branch protection rule.\nThe promotion action also auto-discovers the current token's authenticated user\nor app and adds it to the managed bypass allowlist, so consumers do not have to\ndeclare the same release authority twice.\n\nThe tag names intentionally follow the old ABV release semantics:\nexact release tags are `vX.Y.Z`, exact alpha tags are `vX.Y.Z-alpha.N`, floating\nrelease tags are minor/major tags such as `v2.0` and `v2`, and floating alpha\ntags are minor-line tags such as `v2.0-alpha`. Bare tags such as `1.0.0` are not\nmaintained as buildchain release entrypoints.\n\nRepository rulesets should protect exact tags, not every `v*` tag. A ruleset\nsuch as `refs/tags/v*` also protects floating channel tags like `v2.0-alpha`,\nwhich Buildchain must update after exact tags and publish evidence are durable.\nUse an exact-tag rule such as `refs/tags/v*.*.*` for immutable evidence tags and\nleave floating channel tags mutable for the promotion token."
199
199
  },
200
200
  {
201
201
  "id": "action:report-buildchain-issue",
@@ -1225,7 +1225,7 @@
1225
1225
  ],
1226
1226
  "maturity": "stable",
1227
1227
  "sourcePath": "docs/release-governance.md",
1228
- "digest": "sha256:69218a4749170e1f84b82f211d57187a7ff33f1a510aced587e240d1d901b9e7",
1228
+ "digest": "sha256:9c8e3f096d314b2d0ea9a6badfdf263006e190aaa6e861489bdd05c93d3eaf04",
1229
1229
  "headings": [
1230
1230
  {
1231
1231
  "level": 1,
@@ -1303,7 +1303,7 @@
1303
1303
  "anchor": "operational-reading-order"
1304
1304
  }
1305
1305
  ],
1306
- "markdown": "# Release Governance\n\nBuildchain v2 preserves the release semantics of the older ABV workflow while\nmoving the implementation into one modern repository.\n\nThe central idea is simple: a reviewed merge into a release channel is the\nrelease intent. Automation must then create the version-state commit, exact tag,\nfloating tag, and next alpha state that make that intent true in Git.\n\n## Design Problem\n\nKungfu release automation has to keep four facts aligned:\n\n1. The source tree that was reviewed.\n2. The package version recorded in manifests such as `package.json` or\n `lerna.json`.\n3. The exact immutable release or prerelease tag.\n4. The floating channel refs that consumers actually use.\n\nIf any one of these facts is updated by hand, the system can split:\n\n- a consumer can fetch `v2.0` and receive a tree whose package version still\n says the previous release;\n- a maintainer can move `v2` without producing an exact `v2.0.N` audit tag;\n- an alpha can be promoted to production even though the release tree is not the\n same tree that was tested;\n- a protected branch merge can succeed while the follow-up version commit is\n missing, or a flow-internal generated `dev`/`alpha`/`release` ref update can\n fail after publish because the automation identity was not declared in the\n branch-protection review bypass allowance.\n\nThe older ABV workflow addressed this by letting GitHub PRs drive release\nstate. Buildchain keeps that choice because it makes release intent reviewable,\nobservable, and recoverable from Git history.\n\n## What ABV Contributed\n\nThe old ABV model was not just \"bump a version number.\" It encoded a governance\nloop:\n\n- release branches are named as channels: `dev`, `alpha`, `release`, and the\n administrative `publish-gate/major`;\n- a PR from one channel to the next is the release request;\n- verify jobs check that the branch pair is valid before merge;\n- a maintainer review is required before the branch moves;\n- after merge, automation writes the version change and moves tags;\n- exact tags and floating refs are aligned with the resulting commit;\n- the next development channel is prepared automatically.\n\nABV also kept the version-state mutation in the repository. For JavaScript\nrepositories that usually meant changing `lerna.json` and/or `package.json`.\nThat commit is important because the tag alone is not enough evidence: the\nsource tree should also declare the version that the tag advertises.\n\nBuildchain v2 treats that as a hard semantic requirement for its own release\nline.\n\n## Buildchain Implementation\n\nBuildchain implements the same governance loop with:\n\n- `.github/workflows/release-verify.yml` for PR verification;\n- `.github/workflows/buildchain-ref-promotion.yml` for post-verify ref\n promotion; this workflow dogfoods the declarative\n `release-candidate-promote.yml` wrapper and does not hand-wire resolver,\n artifact download, publish-gate, or promote action steps;\n- Buildchain self promotion enables `release-passport-buildchain-self-kfd`, so\n the promote action generates KFD-1 witnesses, KFD-2 public claim JSON, and\n KFD-3 collaboration-interface witnesses from the final version-state workspace\n before release passport finalization. The witness hashes therefore bind to the\n exact published package and site facts from\n `packages/core/buildchain-kfd-claims.js` instead of relying on prose release\n notes;\n- `actions/promote-buildchain-ref` for branch, tag, version-state, and\n governance checks;\n- package-manager adapters that can update version state for pnpm, npm, and\n yarn style repositories;\n- `buildchain.toml` lifecycle configuration for repositories whose version\n state or verification commands are not Node package-manager defaults.\n\nThe implementation is intentionally stricter than a local release script:\n\n- manual workflow dispatch can only do dry-run promotion;\n- non-dry-run promotion must be driven by a completed `Verify` workflow;\n- target branch protection details must be readable, and branch protection must\n apply to administrators as well as regular contributors;\n- alpha promotion must come from a merged same-repository PR from\n `dev/vX/vX.Y` to `alpha/vX/vX.Y`;\n- release promotion must come from a merged same-repository PR from\n `alpha/vX/vX.Y` to `release/vX/vX.Y`;\n- major promotion must come from a merged same-repository PR from\n `release/vX/vX.Y` to `publish-gate/major`;\n- release promotion requires an existing same-patch alpha tag and checks the\n release source tree against that tested alpha tree;\n- generated version-state commits are verified before refs move.\n\n## Version Lines\n\nKungfu uses Python-like version lines where a minor line can represent a\nlong-lived product train. A line such as `v2.0` can produce many production\npatch releases:\n\n```text\nv2.0.0\nv2.0.1\nv2.0.2\n...\nv2.0.1234\n```\n\nThis is why Buildchain maintains both exact and floating refs:\n\n- `v2.0.2` is immutable release evidence;\n- `v2.0` is the latest production release on the `2.0` line;\n- `v2` is the selected stable major-line entrypoint;\n- `v2.0.3-alpha.0` is immutable alpha evidence;\n- `v2.0-alpha` is the latest test channel for the `2.0` line.\n\nA release does not mean \"minor is complete.\" It means \"this patch on this minor\nline is now production.\"\n\nGitHub repository rules must preserve that distinction. Exact tags such as\n`v2.0.2` and `v2.0.3-alpha.0` should be immutable. Floating channel tags such as\n`v2`, `v2.0`, and `v2.0-alpha` must remain movable by the Buildchain promotion\ntoken after governance checks and publish evidence pass. A tag ruleset that\nprotects every `refs/tags/v*` ref is too broad because it also locks the\nfloating channel tags that Buildchain is required to update. Prefer exact-tag\npatterns such as `refs/tags/v*.*.*` for immutable release evidence, while\nleaving floating channel tags under Buildchain automation control.\n\n## Alpha Semantics\n\nAn alpha merge is:\n\n```text\ndev/vX/vX.Y -> alpha/vX/vX.Y\n```\n\nBuildchain then:\n\n1. Computes the next prerelease for the minor line.\n2. Writes version state such as `vX.Y.Z-alpha.N`.\n3. Verifies the generated version-state tree.\n4. Creates or reuses the exact alpha tag.\n5. Moves `alpha/vX/vX.Y` to the generated alpha commit.\n6. Moves `dev/vX/vX.Y` to the same generated alpha commit when this is a\n fast-forward update.\n7. Moves `vX.Y-alpha` to the same generated alpha commit.\n\nThis keeps the test channel self-describing. If a consumer checks out\n`v2.0-alpha`, the manifests and exact alpha tag agree.\n\nIf `dev/vX/vX.Y` has already advanced before generated alpha version-state\nbookkeeping can sync back, Buildchain records `skipped-non-fast-forward` for the\ndev sync and still completes the exact and floating alpha tags for the reviewed\nalpha commit. Later dev changes must go through their own dev-to-alpha\npromotion instead of rewinding dev. The normal path is direct: after alpha\nmerges, Buildchain applies the generated version-state commit to alpha and then\nfast-forwards dev to the same commit without a human version-state PR.\n\nIf alpha finalization is resumed after generated version-state bookkeeping was\npartially applied, Buildchain accepts the current alpha head as the generated\ncommit, or as a historical merge commit that contains the recorded release\nmaterial. An already-created exact alpha tag may point at the transaction\nrelease/material SHA or at the finalized alpha head; missing floating alpha\ntags are retried before the transaction becomes `complete`.\n\n## Release Semantics\n\nA release merge is:\n\n```text\nalpha/vX/vX.Y -> release/vX/vX.Y\n```\n\nBuildchain then:\n\n1. Finds the same-patch alpha tag that was tested.\n2. Checks that the release source tree matches that alpha tag tree, excluding\n only generated version-state differences.\n3. Writes final release version state such as `vX.Y.Z`.\n4. Verifies the generated release tree.\n5. Creates or reuses the exact release tag `vX.Y.Z`.\n6. Moves `release/vX/vX.Y` to the exact release commit.\n7. Moves `vX.Y` to the exact release commit.\n8. Moves `vX` when this minor line should be the stable major entrypoint.\n9. Prepares the next alpha version-state commit, such as\n `vX.Y.(Z+1)-alpha.0`.\n10. Moves `alpha/vX/vX.Y`, `dev/vX/vX.Y`, and `vX.Y-alpha` to that next alpha\n commit.\n\nThe production channel and the test channel therefore intentionally diverge\nafter release: production stays on the release commit, while alpha/dev continue\nat the next prerelease commit.\n\nIf release finalization is resumed after generated version-state bookkeeping was\npartially applied, Buildchain applies the same recovery rule: the current\nrelease head may be the generated commit, or a historical merge commit that\ncontains the recorded release material, existing exact tags and alpha/dev refs\nare accepted when they match the transaction, and missing floating `vX.Y` or\n`vX` tags are retried idempotently before completion.\n\n## Major Gate Semantics\n\nA major gate merge is:\n\n```text\nrelease/vX/vX.Y -> publish-gate/major\n```\n\n`publish-gate/major` is the explicit replacement for the older ABV `main`\nchannel. The name is intentionally operational: it is a gate for a rare\nadministrator decision, not the active trunk. Keeping this decision in the same\nPR UI as alpha and release promotion keeps the human workflow simple while\navoiding the misleading meaning of `main`. The older `major-gate` branch name is\na compatibility alias only.\n\nBuildchain then:\n\n1. Verifies the source is a merged same-repository PR from a protected release\n line into `publish-gate/major`.\n2. Writes the next major production version state, such as `v(X+1).0.0`.\n3. Creates or reuses the exact release tag `v(X+1).0.0`.\n4. Moves `publish-gate/major` and `release/v(X+1)/v(X+1).0` to that release commit.\n5. Moves `v(X+1).0` and `v(X+1)` to that release commit.\n6. Prepares the next alpha version-state commit, such as\n `v(X+1).0.1-alpha.0`.\n7. Moves `alpha/v(X+1)/v(X+1).0`, `dev/v(X+1)/v(X+1).0`, and\n `v(X+1).0-alpha` to that next alpha commit.\n\nChecking out `publish-gate/major` should therefore look like a frozen release\nstate, not like a branch where day-to-day source work continues. Day-to-day\nsource work continues on `dev/vX/vX.Y`.\n\n## Protected Dev Branches\n\n`dev/vX/vX.Y` is a protected development channel, not a scratch branch. Normal\nsource changes should be made on work branches such as `feature/*`, `fix/*`,\n`chore/*`, `docs/*`, `ci/*`, or `refactor/*`, then reviewed through a pull\nrequest into the target dev line.\n\nThis keeps the earliest development channel audit-friendly:\n\n- the version line being changed is visible in the PR base branch;\n- CI and required checks run before the channel moves;\n- branch protection can prevent direct pushes and stale merges;\n- later `dev -> alpha -> release` promotion inherits a reviewable source\n lineage instead of trying to reconstruct how the dev branch changed.\n\nBuildchain provides the reusable\n`.github/workflows/dev-pr-auto-merge.yml` workflow for repositories that want a\nscheduled or manual \"merge ready dev PRs\" pass. The consumer repository owns\nthe trigger schedule, but the merge decision is declared through workflow\ninputs: target dev branch, required status/check names, ready and block labels,\nallowed work-branch prefixes, review requirements, maximum merges per run,\nmerge method, and dry-run mode.\n\nThe workflow defaults are conservative. A PR is skipped unless it targets the\nconfigured dev line, is not a draft, has the ready label, has no block label,\ncomes from the same repository, uses an allowed work-branch prefix, has a\ncurrent approval, is mergeable, and has the configured required checks passing.\nAfter each merge, the next PR is re-evaluated before it can move the protected\ndev branch. This prevents one merge from silently making the next candidate\nstale or conflicting.\n\nThe required check should be the `check` job. Repositories can keep that job\nname stable while changing the actual verification command declaratively in\n`buildchain.toml`:\n\n```toml\n[lifecycle.install]\ncommand = \"cargo fetch --locked\"\n\n[lifecycle.verify]\ncommand = \"cargo test --workspace --locked\"\n```\n\nConsumers that want Buildchain to own the check wrapper can call\n`.github/workflows/check.yml@v2`. The wrapper runs the declared\n`lifecycle.install` and `lifecycle.verify` stages and fails the `check` job when\neither declaration is missing or the command exits non-zero.\n\nTypical consumer wrapper:\n\n```yaml\nname: Merge Ready Dev PRs\n\non:\n schedule:\n - cron: \"17 * * * *\"\n workflow_dispatch:\n inputs:\n dry-run:\n type: boolean\n default: true\n\njobs:\n merge-dev:\n uses: kungfu-systems/buildchain/.github/workflows/dev-pr-auto-merge.yml@v2\n permissions:\n contents: write\n pull-requests: write\n checks: read\n statuses: read\n with:\n target-branch: dev/v2/v2.6\n required-status-checks: check\n ready-label: ready\n block-labels: blocked,do-not-merge\n max-merges: 1\n dry-run: ${{ inputs.dry-run || false }}\n```\n\n## Buildchain Patrol\n\n`dev-pr-auto-merge.yml` remains the focused merge primitive. For repositories\nthat want a stable day-to-day operations contract, Buildchain also exposes a\npatrol workflow family:\n\n| Workflow | Intended cadence | Default intent |\n| --- | --- | --- |\n| `.github/workflows/patrol-daily.yml` | daily | lightweight inspection plus ready dev PR maintenance |\n| `.github/workflows/patrol-weekly.yml` | weekly | release-state, passport, gate, and stale-state health checks as they are added |\n| `.github/workflows/patrol-monthly.yml` | monthly | governance, permission, branch-protection, and workflow drift checks as they are added |\n\nThe cadence names describe patrol intensity, not release cadence:\n\n- daily patrol can run every day without implying a daily release;\n- weekly patrol is for medium-cost maintenance and audit checks;\n- monthly patrol is for structural drift checks that should not block ordinary\n development velocity.\n\nConsumers should schedule thin callers and keep their YAML declarative. For\nexample:\n\n```yaml\nname: Buildchain Daily Patrol\n\non:\n schedule:\n - cron: \"17 2 * * *\"\n workflow_dispatch:\n\njobs:\n patrol:\n uses: kungfu-systems/buildchain/.github/workflows/patrol-daily.yml@v2\n with:\n dry-run: false\n max-actions: 1\n```\n\nWeekly and monthly callers use the matching wrapper:\n\n```yaml\njobs:\n patrol:\n uses: kungfu-systems/buildchain/.github/workflows/patrol-weekly.yml@v2\n with:\n dry-run: true\n```\n\nAll three wrappers default to the `v2` floating Buildchain runtime. When\n`target-branch` is omitted, the caller's current/default branch selects the\nactive semver dev line, so consumers do not pin patrol to a stale minor branch.\nThe separate workflow names keep consumer schedules readable and stable while\nBuildchain adds new checks behind the cadence wrappers.\n\n## Package-Manager Adapters\n\nOld ABV assumed JavaScript repositories with root version state and often\nLerna. Buildchain keeps the version-state contract but does not assume every\nrepository is yarn/Lerna.\n\nThe promotion action discovers and updates:\n\n- root `package.json`;\n- `lerna.json`;\n- package manifests from `package.json` workspaces;\n- package manifests from `lerna.json` packages;\n- package manifests from `pnpm-workspace.yaml`.\n\nIt then runs the repository's detected package manager semantics where needed:\n\n- pnpm repositories use pnpm-oriented workspace discovery;\n- npm repositories use npm/package-lock semantics where present;\n- yarn repositories use yarn-style metadata where present.\n\nFor Buildchain itself, version state is required. For a consumer repository that\nhas no package manifest, the same action can degrade to ref-only behavior only\nwhen that is explicitly allowed by the caller.\n\n## Lifecycle Configuration\n\n`buildchain.toml` is the v2 user configuration format. It lets a repository\ndeclare version-state files and lifecycle commands without pretending every\nproject is a Node workspace. Supported version files include JSON, TOML, and\nregex-based files such as `CMakeLists.txt` or `conanfile.py`.\n\nThe promotion action currently consumes `version.files` and `lifecycle.verify`.\nThe verify stage runs after generated version-state changes are applied locally\nand before any release refs move. If `verification-command` is passed directly\nto the action, that explicit command overrides `lifecycle.verify`.\n\nProtected release-line branches keep their normal human review gate. Managed\n`dev/vN/vN.M`, `alpha/vN/vN.M`, and `release/vN/vN.M` branches are configured\nwith one required approving review, strict GitHub Actions checks, administrator\nenforcement, conversation resolution, no force pushes, and no deletions. The\nreusable `release-candidate-promote.yml` wrapper defaults\n`branch-protection-bypass-apps` to `github-actions`, which lets the workflow's\nautomation identity apply generated version-state or post-publish channel\nbookkeeping after the reviewed channel PR has merged. Direct\n`promote-buildchain-ref` callers must opt into the same controlled bypass with\n`branch-protection-bypass-apps`, `branch-protection-bypass-users`, or\n`branch-protection-bypass-teams`; the action also adds the current promotion\ntoken's authenticated user or app to the managed bypass allowlist. Before\npatching a protected generated bookkeeping ref, the action creates the\nconfigured required check on the exact generated version-state commit, so strict\nstatus checks are satisfied by machine-verifiable Buildchain evidence rather\nthan a human PR. The protected ref PATCH itself uses the generated ref update\ntoken; the reusable wrapper defaults it to\n`secrets.BUILDCHAIN_PROMOTION_TOKEN || github.token`. If direct generated\nrelease finalization bookkeeping is still rejected, Buildchain creates or\nreuses a same-repository `buildchain/version-state/*` PR based on the current\ntarget channel head and records `finalization-needed=true` in the durable\ntransaction output. Strict alpha bookkeeping still fails with a\ntoken/protection diagnostic instead of creating a post-publish PR.\nBuildchain's own promotion workflow reads `BUILDCHAIN_PROMOTION_BYPASS_APPS`,\n`BUILDCHAIN_PROMOTION_BYPASS_USERS`, and\n`BUILDCHAIN_PROMOTION_BYPASS_TEAMS` repository variables so the declared bypass\nidentity can match the actual `BUILDCHAIN_PROMOTION_TOKEN` actor, but consumers\ndo not need to duplicate that actor manually when the token identity is\ndiscoverable.\n\n## What This Guarantees\n\nWhen the loop succeeds, maintainers and consumers can rely on these facts:\n\n- every production release has an exact tag such as `v2.0.2`;\n- every production minor line has a floating tag such as `v2.0`;\n- every selected stable major has a floating tag such as `v2`;\n- every next-major release is driven by a reviewed `release -> publish-gate/major` PR,\n not a hidden manual button;\n- every test channel has an exact alpha tag such as `v2.0.3-alpha.0`;\n- every alpha minor line has a floating tag such as `v2.0-alpha`;\n- version manifests match the tag visible from the same commit;\n- production releases are derived from the alpha tree that was tested;\n- manual non-dry-run promotion cannot bypass PR review and verification;\n- flow-internal automation bypasses apply only to declared GitHub Apps, users,\n or teams on Buildchain-managed channel branch protection, while one-review\n protection remains enforced for humans;\n- admin users cannot make a channel promotion valid by temporarily bypassing\n branch protection.\n\nThis is the practical meaning of \"governance closed loop\" in Buildchain: the\ndecision, code, version state, and Git refs close over the same evidence chain.\n\n## What This Does Not Do\n\nBuildchain release promotion does not embed registry clients or product-specific\npublish logic. When publish transactions are enabled, `promote-buildchain-ref`\ncan run the consumer's `lifecycle.publish` command and own the transaction,\nevidence validation, durable recovery state, and ref finalization order. The\nconsumer repository still owns registry truth: npm, PyPI, OCI, S3, Conan, CMake\npackaging, download pages, dist-tags, and similar side effects must be\nimplemented by project lifecycle commands that emit Buildchain publish evidence.\n\nEvery Buildchain publish model that can run registry side effects must bind the\npublish entrypoint to an immutable `publish-gate/*` source lock. The reusable\n`release-candidate-promote.yml@v2` wrapper creates or updates that gate ref and\npasses `require-publish-source-lock`, `publish-source-ref`,\n`publish-source-sha`, and `publish-source-locked` to\n`promote-buildchain-ref`. Direct action callers must pass the same four inputs\nfrom the reusable build outputs. Workflows that only collect passports or run\ndry-run package checks do not move publish refs and are not publish-gate\npublication models.\n\nSemver GitHub Release publication is owned by `promote-buildchain-ref`, not by\nconsumer shell glue. Consumers normally use the `release-candidate-promote.yml`\nwrapper, where GitHub Release publication is enabled by default and can be\ndisabled with `github-release: false`; the wrapper passes that declaration to\nthe action. After the publish transaction reaches `complete`, Buildchain creates\nor updates the public GitHub Release and uploads the generated\n`buildchain.release.json`, release-passport assets, and publish evidence. Semver\nprerelease tags are marked `prerelease=true` and `make_latest=false`; stable\nsemver tags are marked latest. For anchored/manual package releases, the public\nrelease tag defaults to `v<publishedVersion>` while the internal exact\ntransaction tag remains in the release passport and release-state ref. This is\nthe supported path for downstream\n`release.published` propagation across semver, major, and promote-only release\ncandidate publication models.\n\nBuildchain also does not maintain bare exact tags such as `1.0.0`. The supported\nexact release and alpha refs are v-prefixed:\n\n```text\nv2.0.0\nv2.0.1-alpha.0\n```\n\n## Operational Reading Order\n\nWhen debugging or extending release behavior, read in this order:\n\n1. `docs/release-flow.md`\n2. `.github/workflows/release-verify.yml`\n3. `.github/workflows/buildchain-ref-promotion.yml`\n4. `.github/workflows/release-candidate-promote.yml`\n5. `actions/promote-buildchain-ref/README.md`\n6. `actions/promote-buildchain-ref/src/`\n7. `docs/migration-inventory.md`\n\nThat path gives the policy first, the workflow trigger second, and the action\nimplementation last."
1306
+ "markdown": "# Release Governance\n\nBuildchain v2 preserves the release semantics of the older ABV workflow while\nmoving the implementation into one modern repository.\n\nThe central idea is simple: a reviewed merge into a release channel is the\nrelease intent. Automation must then create the version-state commit, exact tag,\nfloating tag, and next alpha state that make that intent true in Git.\n\n## Design Problem\n\nKungfu release automation has to keep four facts aligned:\n\n1. The source tree that was reviewed.\n2. The package version recorded in manifests such as `package.json` or\n `lerna.json`.\n3. The exact immutable release or prerelease tag.\n4. The floating channel refs that consumers actually use.\n\nIf any one of these facts is updated by hand, the system can split:\n\n- a consumer can fetch `v2.0` and receive a tree whose package version still\n says the previous release;\n- a maintainer can move `v2` without producing an exact `v2.0.N` audit tag;\n- an alpha can be promoted to production even though the release tree is not the\n same tree that was tested;\n- a protected branch merge can succeed while the follow-up version commit is\n missing, or a flow-internal generated `dev`/`alpha`/`release` ref update can\n fail after publish because the automation identity was not declared in the\n branch-protection review bypass allowance.\n\nThe older ABV workflow addressed this by letting GitHub PRs drive release\nstate. Buildchain keeps that choice because it makes release intent reviewable,\nobservable, and recoverable from Git history.\n\n## What ABV Contributed\n\nThe old ABV model was not just \"bump a version number.\" It encoded a governance\nloop:\n\n- release branches are named as channels: `dev`, `alpha`, `release`, and the\n administrative `publish-gate/major`;\n- a PR from one channel to the next is the release request;\n- verify jobs check that the branch pair is valid before merge;\n- a maintainer review is required before the branch moves;\n- after merge, automation writes the version change and moves tags;\n- exact tags and floating refs are aligned with the resulting commit;\n- the next development channel is prepared automatically.\n\nABV also kept the version-state mutation in the repository. For JavaScript\nrepositories that usually meant changing `lerna.json` and/or `package.json`.\nThat commit is important because the tag alone is not enough evidence: the\nsource tree should also declare the version that the tag advertises.\n\nBuildchain v2 treats that as a hard semantic requirement for its own release\nline.\n\n## Buildchain Implementation\n\nBuildchain implements the same governance loop with:\n\n- `.github/workflows/release-verify.yml` for PR verification;\n- `.github/workflows/buildchain-ref-promotion.yml` for post-verify ref\n promotion; this workflow dogfoods the declarative\n `release-candidate-promote.yml` wrapper and does not hand-wire resolver,\n artifact download, publish-gate, or promote action steps;\n- Buildchain self promotion enables `release-passport-buildchain-self-kfd`, so\n the promote action generates KFD-1 witnesses, KFD-2 public claim JSON, and\n KFD-3 collaboration-interface witnesses from the final version-state workspace\n before release passport finalization. The witness hashes therefore bind to the\n exact published package and site facts from\n `packages/core/buildchain-kfd-claims.js` instead of relying on prose release\n notes;\n- `actions/promote-buildchain-ref` for branch, tag, version-state, and\n governance checks;\n- package-manager adapters that can update version state for pnpm, npm, and\n yarn style repositories;\n- `buildchain.toml` lifecycle configuration for repositories whose version\n state or verification commands are not Node package-manager defaults.\n\nThe implementation is intentionally stricter than a local release script:\n\n- manual workflow dispatch can only do dry-run promotion;\n- non-dry-run promotion must be driven by a completed `Verify` workflow;\n- target branch protection details must be readable, and branch protection must\n apply to administrators as well as regular contributors;\n- alpha promotion must come from a merged same-repository PR from\n `dev/vX/vX.Y` to `alpha/vX/vX.Y`;\n- release promotion must come from a merged same-repository PR from\n `alpha/vX/vX.Y` to `release/vX/vX.Y`;\n- major promotion must come from a merged same-repository PR from\n `release/vX/vX.Y` to `publish-gate/major`;\n- release promotion requires an existing same-patch alpha tag and checks the\n release source tree against that tested alpha tree;\n- generated version-state commits are verified before refs move.\n\nPromotion intents are serialized globally per caller repository with\n`cancel-in-progress: false`. A queued intent re-reads its protected target ref\nbefore checkout, dependency installation, release-candidate resolution, or any\npublish-gate/ref mutation. If the ref already points at a newer SHA, that older\nintent is no longer release authority: the workflow records the requested and\ncurrent SHAs, proves that the current target is ahead of the requested commit,\nand completes as a `target-ref-advanced` superseded no-op. Diverged or behind\ncomparisons are not superseded transactions and still fail closed.\nMissing refs, unreadable repository state, invalid channels, governance\nfailures, and artifact mismatches still fail closed. The promote action repeats\nthe target check at the mutation boundary, so a ref that advances after the\nworkflow preflight cannot receive a second set of publication side effects.\n\n## Version Lines\n\nKungfu uses Python-like version lines where a minor line can represent a\nlong-lived product train. A line such as `v2.0` can produce many production\npatch releases:\n\n```text\nv2.0.0\nv2.0.1\nv2.0.2\n...\nv2.0.1234\n```\n\nThis is why Buildchain maintains both exact and floating refs:\n\n- `v2.0.2` is immutable release evidence;\n- `v2.0` is the latest production release on the `2.0` line;\n- `v2` is the selected stable major-line entrypoint;\n- `v2.0.3-alpha.0` is immutable alpha evidence;\n- `v2.0-alpha` is the latest test channel for the `2.0` line.\n\nA release does not mean \"minor is complete.\" It means \"this patch on this minor\nline is now production.\"\n\nGitHub repository rules must preserve that distinction. Exact tags such as\n`v2.0.2` and `v2.0.3-alpha.0` should be immutable. Floating channel tags such as\n`v2`, `v2.0`, and `v2.0-alpha` must remain movable by the Buildchain promotion\ntoken after governance checks and publish evidence pass. A tag ruleset that\nprotects every `refs/tags/v*` ref is too broad because it also locks the\nfloating channel tags that Buildchain is required to update. Prefer exact-tag\npatterns such as `refs/tags/v*.*.*` for immutable release evidence, while\nleaving floating channel tags under Buildchain automation control.\n\n## Alpha Semantics\n\nAn alpha merge is:\n\n```text\ndev/vX/vX.Y -> alpha/vX/vX.Y\n```\n\nBuildchain then:\n\n1. Computes the next prerelease for the minor line.\n2. Writes version state such as `vX.Y.Z-alpha.N`.\n3. Verifies the generated version-state tree.\n4. Creates or reuses the exact alpha tag.\n5. Moves `alpha/vX/vX.Y` to the generated alpha commit.\n6. Moves `dev/vX/vX.Y` to the same generated alpha commit when this is a\n fast-forward update.\n7. Moves `vX.Y-alpha` to the same generated alpha commit.\n\nThis keeps the test channel self-describing. If a consumer checks out\n`v2.0-alpha`, the manifests and exact alpha tag agree.\n\nIf `dev/vX/vX.Y` has already advanced before generated alpha version-state\nbookkeeping can sync back, Buildchain records `skipped-non-fast-forward` for the\ndev sync and still completes the exact and floating alpha tags for the reviewed\nalpha commit. Later dev changes must go through their own dev-to-alpha\npromotion instead of rewinding dev. The normal path is direct: after alpha\nmerges, Buildchain applies the generated version-state commit to alpha and then\nfast-forwards dev to the same commit without a human version-state PR.\n\nIf alpha finalization is resumed after generated version-state bookkeeping was\npartially applied, Buildchain accepts the current alpha head as the generated\ncommit, or as a historical merge commit that contains the recorded release\nmaterial. An already-created exact alpha tag may point at the transaction\nrelease/material SHA or at the finalized alpha head; missing floating alpha\ntags are retried before the transaction becomes `complete`.\n\n## Release Semantics\n\nA release merge is:\n\n```text\nalpha/vX/vX.Y -> release/vX/vX.Y\n```\n\nBuildchain then:\n\n1. Finds the same-patch alpha tag that was tested.\n2. Checks that the release source tree matches that alpha tag tree, excluding\n only generated version-state differences.\n3. Writes final release version state such as `vX.Y.Z`.\n4. Verifies the generated release tree.\n5. Creates or reuses the exact release tag `vX.Y.Z`.\n6. Moves `release/vX/vX.Y` to the exact release commit.\n7. Moves `vX.Y` to the exact release commit.\n8. Moves `vX` when this minor line should be the stable major entrypoint.\n9. Prepares the next alpha version-state commit, such as\n `vX.Y.(Z+1)-alpha.0`.\n10. Moves `alpha/vX/vX.Y`, `dev/vX/vX.Y`, and `vX.Y-alpha` to that next alpha\n commit.\n\nThe production channel and the test channel therefore intentionally diverge\nafter release: production stays on the release commit, while alpha/dev continue\nat the next prerelease commit.\n\nIf release finalization is resumed after generated version-state bookkeeping was\npartially applied, Buildchain applies the same recovery rule: the current\nrelease head may be the generated commit, or a historical merge commit that\ncontains the recorded release material, existing exact tags and alpha/dev refs\nare accepted when they match the transaction, and missing floating `vX.Y` or\n`vX` tags are retried idempotently before completion.\n\n## Major Gate Semantics\n\nA major gate merge is:\n\n```text\nrelease/vX/vX.Y -> publish-gate/major\n```\n\n`publish-gate/major` is the explicit replacement for the older ABV `main`\nchannel. The name is intentionally operational: it is a gate for a rare\nadministrator decision, not the active trunk. Keeping this decision in the same\nPR UI as alpha and release promotion keeps the human workflow simple while\navoiding the misleading meaning of `main`. The older `major-gate` branch name is\na compatibility alias only.\n\nBuildchain then:\n\n1. Verifies the source is a merged same-repository PR from a protected release\n line into `publish-gate/major`.\n2. Writes the next major production version state, such as `v(X+1).0.0`.\n3. Creates or reuses the exact release tag `v(X+1).0.0`.\n4. Moves `publish-gate/major` and `release/v(X+1)/v(X+1).0` to that release commit.\n5. Moves `v(X+1).0` and `v(X+1)` to that release commit.\n6. Prepares the next alpha version-state commit, such as\n `v(X+1).0.1-alpha.0`.\n7. Moves `alpha/v(X+1)/v(X+1).0`, `dev/v(X+1)/v(X+1).0`, and\n `v(X+1).0-alpha` to that next alpha commit.\n\nChecking out `publish-gate/major` should therefore look like a frozen release\nstate, not like a branch where day-to-day source work continues. Day-to-day\nsource work continues on `dev/vX/vX.Y`.\n\n## Protected Dev Branches\n\n`dev/vX/vX.Y` is a protected development channel, not a scratch branch. Normal\nsource changes should be made on work branches such as `feature/*`, `fix/*`,\n`chore/*`, `docs/*`, `ci/*`, or `refactor/*`, then reviewed through a pull\nrequest into the target dev line.\n\nThis keeps the earliest development channel audit-friendly:\n\n- the version line being changed is visible in the PR base branch;\n- CI and required checks run before the channel moves;\n- branch protection can prevent direct pushes and stale merges;\n- later `dev -> alpha -> release` promotion inherits a reviewable source\n lineage instead of trying to reconstruct how the dev branch changed.\n\nBuildchain provides the reusable\n`.github/workflows/dev-pr-auto-merge.yml` workflow for repositories that want a\nscheduled or manual \"merge ready dev PRs\" pass. The consumer repository owns\nthe trigger schedule, but the merge decision is declared through workflow\ninputs: target dev branch, required status/check names, ready and block labels,\nallowed work-branch prefixes, review requirements, maximum merges per run,\nmerge method, and dry-run mode.\n\nThe workflow defaults are conservative. A PR is skipped unless it targets the\nconfigured dev line, is not a draft, has the ready label, has no block label,\ncomes from the same repository, uses an allowed work-branch prefix, has a\ncurrent approval, is mergeable, and has the configured required checks passing.\nAfter each merge, the next PR is re-evaluated before it can move the protected\ndev branch. This prevents one merge from silently making the next candidate\nstale or conflicting.\n\nThe required check should be the `check` job. Repositories can keep that job\nname stable while changing the actual verification command declaratively in\n`buildchain.toml`:\n\n```toml\n[lifecycle.install]\ncommand = \"cargo fetch --locked\"\n\n[lifecycle.verify]\ncommand = \"cargo test --workspace --locked\"\n```\n\nConsumers that want Buildchain to own the check wrapper can call\n`.github/workflows/check.yml@v2`. The wrapper runs the declared\n`lifecycle.install` and `lifecycle.verify` stages and fails the `check` job when\neither declaration is missing or the command exits non-zero.\n\nTypical consumer wrapper:\n\n```yaml\nname: Merge Ready Dev PRs\n\non:\n schedule:\n - cron: \"17 * * * *\"\n workflow_dispatch:\n inputs:\n dry-run:\n type: boolean\n default: true\n\njobs:\n merge-dev:\n uses: kungfu-systems/buildchain/.github/workflows/dev-pr-auto-merge.yml@v2\n permissions:\n contents: write\n pull-requests: write\n checks: read\n statuses: read\n with:\n target-branch: dev/v2/v2.6\n required-status-checks: check\n ready-label: ready\n block-labels: blocked,do-not-merge\n max-merges: 1\n dry-run: ${{ inputs.dry-run || false }}\n```\n\n## Buildchain Patrol\n\n`dev-pr-auto-merge.yml` remains the focused merge primitive. For repositories\nthat want a stable day-to-day operations contract, Buildchain also exposes a\npatrol workflow family:\n\n| Workflow | Intended cadence | Default intent |\n| --- | --- | --- |\n| `.github/workflows/patrol-daily.yml` | daily | lightweight inspection plus ready dev PR maintenance |\n| `.github/workflows/patrol-weekly.yml` | weekly | release-state, passport, gate, and stale-state health checks as they are added |\n| `.github/workflows/patrol-monthly.yml` | monthly | governance, permission, branch-protection, and workflow drift checks as they are added |\n\nThe cadence names describe patrol intensity, not release cadence:\n\n- daily patrol can run every day without implying a daily release;\n- weekly patrol is for medium-cost maintenance and audit checks;\n- monthly patrol is for structural drift checks that should not block ordinary\n development velocity.\n\nConsumers should schedule thin callers and keep their YAML declarative. For\nexample:\n\n```yaml\nname: Buildchain Daily Patrol\n\non:\n schedule:\n - cron: \"17 2 * * *\"\n workflow_dispatch:\n\njobs:\n patrol:\n uses: kungfu-systems/buildchain/.github/workflows/patrol-daily.yml@v2\n with:\n dry-run: false\n max-actions: 1\n```\n\nWeekly and monthly callers use the matching wrapper:\n\n```yaml\njobs:\n patrol:\n uses: kungfu-systems/buildchain/.github/workflows/patrol-weekly.yml@v2\n with:\n dry-run: true\n```\n\nAll three wrappers default to the `v2` floating Buildchain runtime. When\n`target-branch` is omitted, the caller's current/default branch selects the\nactive semver dev line, so consumers do not pin patrol to a stale minor branch.\nThe separate workflow names keep consumer schedules readable and stable while\nBuildchain adds new checks behind the cadence wrappers.\n\n## Package-Manager Adapters\n\nOld ABV assumed JavaScript repositories with root version state and often\nLerna. Buildchain keeps the version-state contract but does not assume every\nrepository is yarn/Lerna.\n\nThe promotion action discovers and updates:\n\n- root `package.json`;\n- `lerna.json`;\n- package manifests from `package.json` workspaces;\n- package manifests from `lerna.json` packages;\n- package manifests from `pnpm-workspace.yaml`.\n\nIt then runs the repository's detected package manager semantics where needed:\n\n- pnpm repositories use pnpm-oriented workspace discovery;\n- npm repositories use npm/package-lock semantics where present;\n- yarn repositories use yarn-style metadata where present.\n\nFor Buildchain itself, version state is required. For a consumer repository that\nhas no package manifest, the same action can degrade to ref-only behavior only\nwhen that is explicitly allowed by the caller.\n\n## Lifecycle Configuration\n\n`buildchain.toml` is the v2 user configuration format. It lets a repository\ndeclare version-state files and lifecycle commands without pretending every\nproject is a Node workspace. Supported version files include JSON, TOML, and\nregex-based files such as `CMakeLists.txt` or `conanfile.py`.\n\nThe promotion action currently consumes `version.files` and `lifecycle.verify`.\nThe verify stage runs after generated version-state changes are applied locally\nand before any release refs move. If `verification-command` is passed directly\nto the action, that explicit command overrides `lifecycle.verify`.\n\nProtected release-line branches keep their normal human review gate. Managed\n`dev/vN/vN.M`, `alpha/vN/vN.M`, and `release/vN/vN.M` branches are configured\nwith one required approving review, strict GitHub Actions checks, administrator\nenforcement, conversation resolution, no force pushes, and no deletions. The\nreusable `release-candidate-promote.yml` wrapper defaults\n`branch-protection-bypass-apps` to `github-actions`, which lets the workflow's\nautomation identity apply generated version-state or post-publish channel\nbookkeeping after the reviewed channel PR has merged. Direct\n`promote-buildchain-ref` callers must opt into the same controlled bypass with\n`branch-protection-bypass-apps`, `branch-protection-bypass-users`, or\n`branch-protection-bypass-teams`; the action also adds the current promotion\ntoken's authenticated user or app to the managed bypass allowlist. Before\npatching a protected generated bookkeeping ref, the action creates the\nconfigured required check on the exact generated version-state commit, so strict\nstatus checks are satisfied by machine-verifiable Buildchain evidence rather\nthan a human PR. The protected ref PATCH itself uses the generated ref update\ntoken; the reusable wrapper defaults it to\n`secrets.BUILDCHAIN_PROMOTION_TOKEN || github.token`. If direct generated\nrelease finalization bookkeeping is still rejected, Buildchain creates or\nreuses a same-repository `buildchain/version-state/*` PR based on the current\ntarget channel head and records `finalization-needed=true` in the durable\ntransaction output. Strict alpha bookkeeping still fails with a\ntoken/protection diagnostic instead of creating a post-publish PR.\nBuildchain's own promotion workflow reads `BUILDCHAIN_PROMOTION_BYPASS_APPS`,\n`BUILDCHAIN_PROMOTION_BYPASS_USERS`, and\n`BUILDCHAIN_PROMOTION_BYPASS_TEAMS` repository variables so the declared bypass\nidentity can match the actual `BUILDCHAIN_PROMOTION_TOKEN` actor, but consumers\ndo not need to duplicate that actor manually when the token identity is\ndiscoverable.\n\n## What This Guarantees\n\nWhen the loop succeeds, maintainers and consumers can rely on these facts:\n\n- every production release has an exact tag such as `v2.0.2`;\n- every production minor line has a floating tag such as `v2.0`;\n- every selected stable major has a floating tag such as `v2`;\n- every next-major release is driven by a reviewed `release -> publish-gate/major` PR,\n not a hidden manual button;\n- every test channel has an exact alpha tag such as `v2.0.3-alpha.0`;\n- every alpha minor line has a floating tag such as `v2.0-alpha`;\n- version manifests match the tag visible from the same commit;\n- production releases are derived from the alpha tree that was tested;\n- manual non-dry-run promotion cannot bypass PR review and verification;\n- flow-internal automation bypasses apply only to declared GitHub Apps, users,\n or teams on Buildchain-managed channel branch protection, while one-review\n protection remains enforced for humans;\n- admin users cannot make a channel promotion valid by temporarily bypassing\n branch protection.\n\nThis is the practical meaning of \"governance closed loop\" in Buildchain: the\ndecision, code, version state, and Git refs close over the same evidence chain.\n\n## What This Does Not Do\n\nBuildchain release promotion does not embed registry clients or product-specific\npublish logic. When publish transactions are enabled, `promote-buildchain-ref`\ncan run the consumer's `lifecycle.publish` command and own the transaction,\nevidence validation, durable recovery state, and ref finalization order. The\nconsumer repository still owns registry truth: npm, PyPI, OCI, S3, Conan, CMake\npackaging, download pages, dist-tags, and similar side effects must be\nimplemented by project lifecycle commands that emit Buildchain publish evidence.\n\nEvery Buildchain publish model that can run registry side effects must bind the\npublish entrypoint to an immutable `publish-gate/*` source lock. The reusable\n`release-candidate-promote.yml@v2` wrapper creates or updates that gate ref and\npasses `require-publish-source-lock`, `publish-source-ref`,\n`publish-source-sha`, and `publish-source-locked` to\n`promote-buildchain-ref`. Direct action callers must pass the same four inputs\nfrom the reusable build outputs. Workflows that only collect passports or run\ndry-run package checks do not move publish refs and are not publish-gate\npublication models.\n\nSemver GitHub Release publication is owned by `promote-buildchain-ref`, not by\nconsumer shell glue. Consumers normally use the `release-candidate-promote.yml`\nwrapper, where GitHub Release publication is enabled by default and can be\ndisabled with `github-release: false`; the wrapper passes that declaration to\nthe action. After the publish transaction reaches `complete`, Buildchain creates\nor updates the public GitHub Release and uploads the generated\n`buildchain.release.json`, release-passport assets, and publish evidence. Semver\nprerelease tags are marked `prerelease=true` and `make_latest=false`; stable\nsemver tags are marked latest. For anchored/manual package releases, the public\nrelease tag defaults to `v<publishedVersion>` while the internal exact\ntransaction tag remains in the release passport and release-state ref. This is\nthe supported path for downstream\n`release.published` propagation across semver, major, and promote-only release\ncandidate publication models.\n\nBuildchain also does not maintain bare exact tags such as `1.0.0`. The supported\nexact release and alpha refs are v-prefixed:\n\n```text\nv2.0.0\nv2.0.1-alpha.0\n```\n\n## Operational Reading Order\n\nWhen debugging or extending release behavior, read in this order:\n\n1. `docs/release-flow.md`\n2. `.github/workflows/release-verify.yml`\n3. `.github/workflows/buildchain-ref-promotion.yml`\n4. `.github/workflows/release-candidate-promote.yml`\n5. `actions/promote-buildchain-ref/README.md`\n6. `actions/promote-buildchain-ref/src/`\n7. `docs/migration-inventory.md`\n\nThat path gives the policy first, the workflow trigger second, and the action\nimplementation last."
1307
1307
  },
1308
1308
  {
1309
1309
  "id": "manual:release-passport",
@@ -2365,7 +2365,7 @@
2365
2365
  "path": "docs/release-governance.md",
2366
2366
  "plane": "why",
2367
2367
  "exists": true,
2368
- "digest": "sha256:69218a4749170e1f84b82f211d57187a7ff33f1a510aced587e240d1d901b9e7"
2368
+ "digest": "sha256:9c8e3f096d314b2d0ea9a6badfdf263006e190aaa6e861489bdd05c93d3eaf04"
2369
2369
  },
2370
2370
  {
2371
2371
  "id": "release-flow",
@@ -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": "b6229e57934c0c1f741726b7dcc411e84d6211dc383a4d3c9ece8c930efb5c74",
24
+ "sha256": "b4f8f62e9db46d620bab4afc96a9630fc1cb2c9814fb2c2d7b3605852b7eb49a",
25
25
  "summary": {
26
26
  "cliCommandCount": 74,
27
27
  "workflowCount": 37,
@@ -208,7 +208,7 @@
208
208
  "contract": "kungfu-buildchain-public-surface-reverse-audit",
209
209
  "path": "dist/site/public-surface-audit.json",
210
210
  "status": "passed",
211
- "sha256": "b6229e57934c0c1f741726b7dcc411e84d6211dc383a4d3c9ece8c930efb5c74",
211
+ "sha256": "b4f8f62e9db46d620bab4afc96a9630fc1cb2c9814fb2c2d7b3605852b7eb49a",
212
212
  "summary": {
213
213
  "cliCommandCount": 74,
214
214
  "workflowCount": 37,
@@ -4,7 +4,7 @@
4
4
  "product": {
5
5
  "id": "kungfu-tech-buildchain",
6
6
  "name": "@kungfu-tech/buildchain",
7
- "version": "2.11.12",
7
+ "version": "2.11.13-alpha.1",
8
8
  "repository": "https://github.com/kungfu-systems/buildchain"
9
9
  },
10
10
  "source": {
@@ -300,7 +300,7 @@
300
300
  "title": "Release governance",
301
301
  "path": "docs/release-governance.md",
302
302
  "plane": "why",
303
- "digest": "sha256:69218a4749170e1f84b82f211d57187a7ff33f1a510aced587e240d1d901b9e7",
303
+ "digest": "sha256:9c8e3f096d314b2d0ea9a6badfdf263006e190aaa6e861489bdd05c93d3eaf04",
304
304
  "capabilityGroup": "governance-versioning",
305
305
  "audience": [
306
306
  "maintainer",
@@ -113,7 +113,7 @@
113
113
  ],
114
114
  "maturity": "stable",
115
115
  "sourcePath": "actions/promote-buildchain-ref/README.md",
116
- "digest": "sha256:74939b21339b8d945a428e16119e9a214b670ccfddb6455eb885e35986c40996",
116
+ "digest": "sha256:f1ca20e536f7c0de7ed85784a6b08edfd9aeeb0d2653ec4cff1f4edc2553caf5",
117
117
  "headings": [
118
118
  {
119
119
  "level": 1,
@@ -131,7 +131,7 @@
131
131
  "anchor": "publish-transactions"
132
132
  }
133
133
  ],
134
- "markdown": "# promote-buildchain-ref\n\nInternal buildchain action for promoting verified buildchain release-line and\ncompatibility refs from buildchain release channels:\n\n- `alpha/v2/v2.0` creates or reuses the next exact prerelease tag such as\n `v2.0.1-alpha.0`, writes that version into package version state, points the\n alpha and dev channel branches at the version commit, then promotes\n `v2.0-alpha`;\n- `release/v2/v2.0` creates or reuses the next exact release tag such as\n `v2.0.0`, writes that version into package version state, points the release\n channel branch and release tags at the release commit, then prepares a second\n source commit for the next exact prerelease tag such as `v2.0.1-alpha.0` and\n points the alpha/dev channel branches plus `v2.0-alpha` at that prerelease\n commit;\n- `publish-gate/major` accepts a reviewed PR from a production release line such\n as `release/v2/v2.0`, writes the next major production version such as\n `v3.0.0`, points `publish-gate/major`, `release/v3/v3.0`, `v3.0`, and `v3`\n at that release commit, then prepares `v3.0.1-alpha.0` for\n `alpha/v3/v3.0`, `dev/v3/v3.0`, and `v3.0-alpha`. The older `major-gate`\n branch name is a compatibility alias only.\n\nThe release branch name defines the minor line. For example,\n`release/v2/v2.1` creates `v2.1.N`, promotes `v2.1`, and promotes `v2` only\nwhen the next minor tag such as `v2.2` does not already exist.\n\nThe action updates version state in `lerna.json`, root `package.json`, and\nworkspace package manifests discovered from package manager metadata\n(`package.json` workspaces, `lerna.json` packages, or `pnpm-workspace.yaml`).\nPackage manager detection is adaptive (`pnpm`, `npm`, or `yarn`) and is recorded\nin logs.\n\nRepositories can also provide `buildchain.toml` to declare version-state files\nand `lifecycle.verify`. TOML-configured version files take precedence over\npackage-manager discovery and can target JSON, TOML, or regex-based files. The\nversion commit itself is written through the GitHub Git Data API so the ref\ngraph is the durable source of truth. Repositories without any supported version\nstate degrade to ref-only promotion only when strict version state is disabled.\n\n## Dry Run\n\nUse `dry-run: \"true\"` or the CLI `buildchain release --dry-run` before merging a\nchannel PR when you need to understand what Buildchain would do. This dry-run is\nat the Buildchain release-line level. It explains:\n\n- the legal source branch for the target channel;\n- exact release or alpha tags that would be created or reused;\n- floating tags and channel branches that would move;\n- version-state files and verification lifecycle that would apply;\n- branch protection, PR lineage, and release-from-alpha checks;\n- publish transaction behavior when `lifecycle.publish` or\n `publish-transaction` is enabled.\n\nIt does not move refs, move tags, write package files, run publish commands, or\npublish npm packages. The GitHub action dry-run still calls GitHub APIs to\nresolve the current target SHA and concrete pending ref updates, but every\nwrite is reported as a dry-run update.\n\nRepositories whose package version is anchored to an explicitly selected\nupstream release can opt into manual next-anchor behavior:\n\n```toml\n[version]\nrequired = true\nstrategy = \"anchored\"\nnext = \"manual\"\nmanifest = \"libnode.release.json\"\n```\n\nIn this mode, the action validates the configured version files and anchor\nmanifest through the repository's verify lifecycle, but it does not rewrite the\npackage version to match the Buildchain release tag. After a production\nrelease, it sets `next-anchor-required=true` and does not auto-create the next\nalpha branch or tag. The repository must create the next upstream anchor line\nexplicitly, then run the normal channel promotion flow for that line.\n\nWhen branch protection requires pull requests, generated version-state commits\nstill run through promotion automation first. The action updates\nBuildchain-managed channel protection before generated bookkeeping, adds the\nauthenticated promotion token user or app to the bypass allowlist, creates the\nconfigured required check on the exact generated version-state commit, then\ntries to apply that commit directly. If GitHub still rejects release\nfinalization bookkeeping, Buildchain creates or reuses a same-repository\n`buildchain/version-state/*` PR based on the current target channel head and\nreturns `finalization-needed=true`; a later idempotent promotion run can resume\nfrom the durable transaction state. Strict alpha promotion still fails with a\nconfiguration diagnostic instead of opening a post-publish human PR. Reusable\nwrapper callers should allow `checks: write` so the generated check is owned by\nGitHub Actions and matches the managed branch protection rule.\n\nFor Buildchain-owned automation, callers may pass\n`branch-protection-bypass-apps`, `branch-protection-bypass-users`, or\n`branch-protection-bypass-teams`. The action still configures managed\n`dev/vN/vN.M`, `alpha/vN/vN.M`, and `release/vN/vN.M` branches with one\nrequired approving review, strict GitHub Actions checks, admin enforcement,\nconversation resolution, no force pushes, and no deletions; the bypass\nallowance only lets the named automation identity apply generated version-state\nor channel bookkeeping without a second human review after the reviewed channel\nPR has already merged. Direct action calls automatically include the current\npromotion token's authenticated user or app when GitHub exposes it; explicit\ninputs are supplemental allowlist entries for less discoverable release\nauthorities.\n\n## Publish Transactions\n\nPromotion can also own external publish side effects. Enable this only from a\ntrusted channel workflow:\n\n```yaml\n- uses: kungfu-systems/buildchain/actions/promote-buildchain-ref@v2\n with:\n token: ${{ secrets.BUILDCHAIN_PROMOTION_TOKEN }}\n generated-ref-update-token: ${{ secrets.BUILDCHAIN_PROMOTION_TOKEN }}\n sha: ${{ github.sha }}\n target-ref: release/v2/v2.0\n publish-transaction: \"true\"\n publish-mode: publish-final-version\n publish-auth: trusted-publishing\n publish-required-artifacts-json: >-\n [\n {\"kind\":\"npm\",\"name\":\"@kungfu-tech/buildchain\",\"ref\":\"2.0.0\",\"digest\":\"sha256:...\"}\n ]\n```\n\nFor anchored/manual package repositories that build through the reusable\nworkflow, keep the publish entrypoint on the `publish-gate/*` source-lock\ncontract:\n\n```yaml\n- uses: kungfu-systems/buildchain/actions/promote-buildchain-ref@v2\n with:\n token: ${{ secrets.BUILDCHAIN_PROMOTION_TOKEN }}\n sha: ${{ needs.build.outputs.publish-source-sha }}\n target-ref: release/v22/v22.22\n require-publish-source-lock: \"true\"\n publish-source-ref: ${{ needs.build.outputs.publish-source-ref }}\n publish-source-sha: ${{ needs.build.outputs.publish-source-sha }}\n publish-source-locked: ${{ needs.build.outputs.publish-source-locked }}\n publish-transaction: \"true\"\n publish-mode: publish-final-version\n publish-auth: trusted-publishing\n```\n\n`target-ref` remains the channel promotion target that must point at `sha`.\n`publish-source-ref` is the reviewed source-lock branch that authorized this\nspecific package publication. Direct `alpha/*` or `release/*` channel refs are\nnot valid publish source locks when `require-publish-source-lock` is enabled,\nand a mismatched `publish-source-sha` fails before any promotion or publish side effects begin.\nThe reusable build workflow performs the cheaper channel-ref preflight earlier:\nafter source-lock resolution and before the build matrix, it requires the target\nchannel ref such as `alpha/v22/v22.22` or `release/v22/v22.22` to already point\nat the locked `publish-source-sha`. If not, maintainers should merge the source\ncommit through the channel PR first.\n\nFor promote-only release candidates, attach the PR-stage reusable build evidence\nand fail before publish-gate side effects if it no longer matches:\n\n```yaml\n- uses: kungfu-systems/buildchain/actions/promote-buildchain-ref@v2\n with:\n token: ${{ secrets.BUILDCHAIN_PROMOTION_TOKEN }}\n sha: ${{ needs.build.outputs.publish-source-sha }}\n target-ref: alpha/v22/v22.22\n promote-only-release-candidate: \"true\"\n release-candidate-passport-path: .buildchain/artifacts/release-candidate-passport.json\n release-candidate-build-summary-path: .buildchain/artifacts/build-summary.json\n```\n\nThe action validates repository, channel, source identity, platform matrix, and\nthe aggregate build-summary hash before it writes version state, opens\nrelease-state, runs publish transaction logic, or moves tags/branches. Source\nidentity accepts the exact source SHA, the PR merge ref SHA, or the promoted\nchannel HEAD's Git tree SHA matching the passport tree hash. If validation\nfails, run or attach the verified channel PR build first instead of promoting a\nstale or unproven artifact set.\n\nWhen enabled, the action creates or resumes a release transaction keyed by\nrepository, version, source SHA, and target ref. It persists that transaction to\na machine-managed branch under `buildchain/release-state/<version>`, with\n`state.json` and, once available, `evidence.json`. Fresh GitHub runners read\nthat durable ref before running publish, so reruns do not depend on a previous\nrunner's local `.buildchain` directory.\n\nThe action runs `lifecycle.publish` from `buildchain.toml` or the explicit\n`publish-command` input, then validates publish evidence before exact tags and\nfloating refs move. If durable state persistence fails, the action fails closed\nbefore publish or public ref finalization.\n\n`publish-mode` defaults to `publish-final-version`, the token-free path for\nnormal npm Trusted Publishing. Same-version alpha-to-latest recovery must be\ndeclared as `publish-mode: promote-existing-version` and\n`publish-auth: npm-token`; Buildchain runs `npm whoami` before it creates\nrelease-state or moves any `npm dist-tag`. The Trusted Publishing mode is not\nallowed to perform `npm dist-tag add`.\n\nBuildchain itself uses this path for npm. Its `lifecycle.publish` runs\n`node scripts/npm-publish-transaction.mjs`, which publishes\n`@kungfu-tech/buildchain` through npm Trusted Publishing and writes npm\nartifact evidence into the transaction before release refs move. The separate\n`.github/workflows/npm-publish.yml` workflow is dry-run only.\n\nPublish lifecycle environment:\n\n```text\nBUILDCHAIN_VERSION\nBUILDCHAIN_CHANNEL\nBUILDCHAIN_SOURCE_SHA\nBUILDCHAIN_TARGET_REF\nBUILDCHAIN_RELEASE_STATE\nBUILDCHAIN_EVIDENCE_DIR\nBUILDCHAIN_RELEASE_SHA\nBUILDCHAIN_RELEASE_MATERIAL_SHA\nBUILDCHAIN_PUBLISH_TOOLING_SHA\nBUILDCHAIN_PUBLISH_EVIDENCE\n```\n\nThe action outputs `transaction-id`, `transaction-state`,\n`transaction-exact-tag`, `public-release-tag`, `transaction-release-sha`,\n`transaction-state-ref`, `transaction-state-sha`, `transaction-state-path`,\n`publish-evidence-path`, and `release-passport-path`, `release-passport-output-dir`,\n`release-passport-state-sha`, and `finalization-needed`.\n`transaction-state-ref` is the durable recovery location.\n`release-passport-state-sha` is the durable ref commit after the generated\n`release-passport/*` files have been uploaded into that recovery ref.\n`finalization-needed=true` means publish evidence is valid, but protected branch\nor ref finalization needs a later idempotent promotion run. For release\nfinalization, Buildchain may create a same-repository generated version-state\nPR when GitHub rejects the direct protected ref update; that PR is Buildchain\nbookkeeping, not a consumer-authored release change.\nSet `github-release: \"true\"` when the semver promotion should also publish the\npublic GitHub Release. After the release transaction reaches `complete` and\n`finalization-needed` is false, the action creates or updates the GitHub Release\nfor `public-release-tag`, applies deterministic semver metadata\n(`prerelease=true` and `make_latest=false` for prerelease tags, latest for stable\ntags), and uploads the publish evidence file plus generated release passport\nassets. For anchored/manual package releases, `public-release-tag` is derived\nfrom the published package version, while `transaction-exact-tag` remains the\ninternal Buildchain transaction ref for recovery and audit. If the transaction is\nnot complete yet, the action defers GitHub Release publication to the next\nidempotent promotion run.\n\nAfter a publish transaction reaches `complete`, the action generates the unified\n`buildchain-release-passport` in `.buildchain/release-passport` by default and\npersists those files under `release-passport/` in the durable release-state ref.\nSet `release-passport-product-name` to record the consumer product name, for\nexample `Libnode`, instead of the default `Buildchain`.\nSet `release-passport-kfd-1-witness-jsons` to newline-separated KFD-1\ncontract-world witness JSON paths when released artifacts must prove\nbyte-for-byte KFD contract surfaces. Buildchain imports the KFD metadata from\n`@kungfu-tech/kfd`, freezes the witness, verifies artifact bytes, and writes the\nresult under the KFD-provided `kfd-1` passport section.\nSet `release-passport-kfd-2-claim-jsons` to newline-separated KFD-2 public\nrelease trust claim JSON paths when a release makes additional human/agent\nvisible claims. Buildchain requires each public claim to bind declared sources,\nmachine-readable evidence, hashes, artifact coordinates, verification results,\naudit boundary, responsibility state, and residual risk. Unbound claims fail\npassport verification; prose-only claims downgrade the KFD-2 audit.\nSet `release-passport-kfd-3-prebuild-witness-jsons` to newline-separated KFD-3\ncollaboration-interface pre-build witness paths, then provide artifact-side\nevidence with `release-passport-kfd-3-artifact-witness-jsons` or a\nproduct-owned `release-passport-kfd-3-artifact-verify-command` such as\n`kungfu agent verify --json`. Buildchain compares declared shipped public\nsurfaces with artifact-exposed public surfaces and writes the result under the\nKFD-provided `kfd-3` passport section.\nBuildchain's own release workflow sets `release-passport-buildchain-self-kfd:\n\"true\"`. In that mode the action generates Buildchain-owned KFD-1/2/3 witnesses\ninside the final version-state workspace, after the release transaction has\nmaterialized generated files such as `package.json` and `dist/site/*`. This\nkeeps self-hosted KFD witness hashes bound to the exact published package\ninstead of to a pre-promotion checkout.\nWhen present, the passport includes the aggregate build summary, platform\nartifact manifests, npm publish evidence, dist-tag promotion evidence, the\nrelease-state ref, trusted publishing metadata, and the Buildchain transaction\nresult. After the first passport upload, Buildchain backfills the durable\nrelease-state SHA into `buildchain.release.json` and persists the passport\nagain, so the consumer-side passport is a complete audit entrypoint. Set\n`release-passport: \"false\"` only for a controlled recovery run that must skip\npassport generation.\n\nFinalization recovery is anchored to the durable transaction, not to a single\nworkflow run SHA. After generated version-state bookkeeping is applied, the\ncurrent channel head can be the generated version-state commit or a historical\nmerge commit that contains or corresponds to the recorded `release_material_sha`;\nit does not have to equal the original `source_sha` or the transaction\n`release_sha`. Reruns accept exact tags that already point at the transaction\nrelease/material SHA or the finalized channel head, and continue moving any\nmissing floating tags or dev/alpha refs before marking the transaction\n`complete`.\n\nNormal reruns accept already-published artifacts only when evidence matches.\nMissing required artifacts can be published on the next run. Conflicting\nartifacts put the transaction into `repair_required`; `abandoned` and\n`failed_permanently` also fail closed unless `publish-transaction-override` is\nset for a controlled repair.\n\nIn strict buildchain promotion, ref movement is also gated by the old ABV\ngovernance semantics:\n\n- the target channel branch protection details must be readable, must enforce\n protection for administrators, and must require approving PR review plus the\n strict `check` job from the `Verify` workflow;\n- alpha promotion must come from a merged same-repository PR\n `dev/vN/vN.M -> alpha/vN/vN.M`, or from a strict same-line\n `publish-gate/alpha/vN/vN.M/<version> -> alpha/vN/vN.M` source-lock PR;\n- release promotion must come from a merged same-repository PR\n `alpha/vN/vN.M -> release/vN/vN.M`, or from a strict same-line\n `publish-gate/release/vN/vN.M/<version> -> release/vN/vN.M` source-lock PR;\n- major promotion must come from a merged same-repository PR\n `release/vN/vN.M -> publish-gate/major`;\n- release promotion must have an exact alpha tag for the same patch line, and\n the release source tree must match that alpha tag tree, so release does not\n introduce new code after alpha;\n- anchored/manual release promotion may differ from that alpha tree only in\n declared `version.files` and the configured anchor manifest, and only when the\n checked-out release material has passed `lifecycle.verify` or the explicit\n `verification-command`;\n- generated release and next-alpha version-state trees can be verified locally\n with either the `verification-command` input or `buildchain.toml`\n `lifecycle.verify` before any tags or channel refs move.\n\nThe promotion workflow should use `BUILDCHAIN_PROMOTION_TOKEN` for non-dry-run\npromotion. The token is the buildchain equivalent of the old ABV runner release\nauthority: protected branch review and check rules guard human channel merges,\nwhile the reusable build trust gate now checks the source-lock channel HEAD and\nmerged same-repository PR lineage before heavy build runners start. This action\nstill independently rechecks PR lineage, alpha/release tree equivalence, and\ngenerated version-state verification before moving channel refs and tags.\nGenerated version-state direct ref updates can use a separate\n`generated-ref-update-token`; the reusable wrapper defaults it to\n`secrets.BUILDCHAIN_PROMOTION_TOKEN || github.token`. Consumers that protect\n`dev/*`, `alpha/*`, or `release/*` with one required review should configure\n`BUILDCHAIN_PROMOTION_TOKEN` as the bypass-capable release authority, so\npost-publish dev/alpha/release bookkeeping completes without a human PR.\nThe reusable `release-candidate-promote.yml` wrapper defaults\n`branch-protection-bypass-apps` to `github-actions`, so flow-internal promotion\ncan complete generated `dev`/`alpha`/`release` bookkeeping while ordinary human\npushes and PR merges remain governed by the one-review branch protection rule.\nThe promotion action also auto-discovers the current token's authenticated user\nor app and adds it to the managed bypass allowlist, so consumers do not have to\ndeclare the same release authority twice.\n\nThe tag names intentionally follow the old ABV release semantics:\nexact release tags are `vX.Y.Z`, exact alpha tags are `vX.Y.Z-alpha.N`, floating\nrelease tags are minor/major tags such as `v2.0` and `v2`, and floating alpha\ntags are minor-line tags such as `v2.0-alpha`. Bare tags such as `1.0.0` are not\nmaintained as buildchain release entrypoints.\n\nRepository rulesets should protect exact tags, not every `v*` tag. A ruleset\nsuch as `refs/tags/v*` also protects floating channel tags like `v2.0-alpha`,\nwhich Buildchain must update after exact tags and publish evidence are durable.\nUse an exact-tag rule such as `refs/tags/v*.*.*` for immutable evidence tags and\nleave floating channel tags mutable for the promotion token."
134
+ "markdown": "# promote-buildchain-ref\n\nInternal buildchain action for promoting verified buildchain release-line and\ncompatibility refs from buildchain release channels:\n\n- `alpha/v2/v2.0` creates or reuses the next exact prerelease tag such as\n `v2.0.1-alpha.0`, writes that version into package version state, points the\n alpha and dev channel branches at the version commit, then promotes\n `v2.0-alpha`;\n- `release/v2/v2.0` creates or reuses the next exact release tag such as\n `v2.0.0`, writes that version into package version state, points the release\n channel branch and release tags at the release commit, then prepares a second\n source commit for the next exact prerelease tag such as `v2.0.1-alpha.0` and\n points the alpha/dev channel branches plus `v2.0-alpha` at that prerelease\n commit;\n- `publish-gate/major` accepts a reviewed PR from a production release line such\n as `release/v2/v2.0`, writes the next major production version such as\n `v3.0.0`, points `publish-gate/major`, `release/v3/v3.0`, `v3.0`, and `v3`\n at that release commit, then prepares `v3.0.1-alpha.0` for\n `alpha/v3/v3.0`, `dev/v3/v3.0`, and `v3.0-alpha`. The older `major-gate`\n branch name is a compatibility alias only.\n\nThe release branch name defines the minor line. For example,\n`release/v2/v2.1` creates `v2.1.N`, promotes `v2.1`, and promotes `v2` only\nwhen the next minor tag such as `v2.2` does not already exist.\n\nThe action updates version state in `lerna.json`, root `package.json`, and\nworkspace package manifests discovered from package manager metadata\n(`package.json` workspaces, `lerna.json` packages, or `pnpm-workspace.yaml`).\nPackage manager detection is adaptive (`pnpm`, `npm`, or `yarn`) and is recorded\nin logs.\n\nRepositories can also provide `buildchain.toml` to declare version-state files\nand `lifecycle.verify`. TOML-configured version files take precedence over\npackage-manager discovery and can target JSON, TOML, or regex-based files. The\nversion commit itself is written through the GitHub Git Data API so the ref\ngraph is the durable source of truth. Repositories without any supported version\nstate degrade to ref-only promotion only when strict version state is disabled.\n\n## Dry Run\n\nUse `dry-run: \"true\"` or the CLI `buildchain release --dry-run` before merging a\nchannel PR when you need to understand what Buildchain would do. This dry-run is\nat the Buildchain release-line level. It explains:\n\n- the legal source branch for the target channel;\n- exact release or alpha tags that would be created or reused;\n- floating tags and channel branches that would move;\n- version-state files and verification lifecycle that would apply;\n- branch protection, PR lineage, and release-from-alpha checks;\n- publish transaction behavior when `lifecycle.publish` or\n `publish-transaction` is enabled.\n\nIt does not move refs, move tags, write package files, run publish commands, or\npublish npm packages. The GitHub action dry-run still calls GitHub APIs to\nresolve the current target SHA and concrete pending ref updates, but every\nwrite is reported as a dry-run update.\n\nRepositories whose package version is anchored to an explicitly selected\nupstream release can opt into manual next-anchor behavior:\n\n```toml\n[version]\nrequired = true\nstrategy = \"anchored\"\nnext = \"manual\"\nmanifest = \"libnode.release.json\"\n```\n\nIn this mode, the action validates the configured version files and anchor\nmanifest through the repository's verify lifecycle, but it does not rewrite the\npackage version to match the Buildchain release tag. After a production\nrelease, it sets `next-anchor-required=true` and does not auto-create the next\nalpha branch or tag. The repository must create the next upstream anchor line\nexplicitly, then run the normal channel promotion flow for that line.\n\nWhen branch protection requires pull requests, generated version-state commits\nstill run through promotion automation first. The action updates\nBuildchain-managed channel protection before generated bookkeeping, adds the\nauthenticated promotion token user or app to the bypass allowlist, creates the\nconfigured required check on the exact generated version-state commit, then\ntries to apply that commit directly. If GitHub still rejects release\nfinalization bookkeeping, Buildchain creates or reuses a same-repository\n`buildchain/version-state/*` PR based on the current target channel head and\nreturns `finalization-needed=true`; a later idempotent promotion run can resume\nfrom the durable transaction state. Strict alpha promotion still fails with a\nconfiguration diagnostic instead of opening a post-publish human PR. Reusable\nwrapper callers should allow `checks: write` so the generated check is owned by\nGitHub Actions and matches the managed branch protection rule.\n\nFor Buildchain-owned automation, callers may pass\n`branch-protection-bypass-apps`, `branch-protection-bypass-users`, or\n`branch-protection-bypass-teams`. The action still configures managed\n`dev/vN/vN.M`, `alpha/vN/vN.M`, and `release/vN/vN.M` branches with one\nrequired approving review, strict GitHub Actions checks, admin enforcement,\nconversation resolution, no force pushes, and no deletions; the bypass\nallowance only lets the named automation identity apply generated version-state\nor channel bookkeeping without a second human review after the reviewed channel\nPR has already merged. Direct action calls automatically include the current\npromotion token's authenticated user or app when GitHub exposes it; explicit\ninputs are supplemental allowlist entries for less discoverable release\nauthorities.\n\n## Publish Transactions\n\nPromotion can also own external publish side effects. Enable this only from a\ntrusted channel workflow:\n\n```yaml\n- uses: kungfu-systems/buildchain/actions/promote-buildchain-ref@v2\n with:\n token: ${{ secrets.BUILDCHAIN_PROMOTION_TOKEN }}\n generated-ref-update-token: ${{ secrets.BUILDCHAIN_PROMOTION_TOKEN }}\n sha: ${{ github.sha }}\n target-ref: release/v2/v2.0\n publish-transaction: \"true\"\n publish-mode: publish-final-version\n publish-auth: trusted-publishing\n publish-required-artifacts-json: >-\n [\n {\"kind\":\"npm\",\"name\":\"@kungfu-tech/buildchain\",\"ref\":\"2.0.0\",\"digest\":\"sha256:...\"}\n ]\n```\n\nFor anchored/manual package repositories that build through the reusable\nworkflow, keep the publish entrypoint on the `publish-gate/*` source-lock\ncontract:\n\n```yaml\n- uses: kungfu-systems/buildchain/actions/promote-buildchain-ref@v2\n with:\n token: ${{ secrets.BUILDCHAIN_PROMOTION_TOKEN }}\n sha: ${{ needs.build.outputs.publish-source-sha }}\n target-ref: release/v22/v22.22\n require-publish-source-lock: \"true\"\n publish-source-ref: ${{ needs.build.outputs.publish-source-ref }}\n publish-source-sha: ${{ needs.build.outputs.publish-source-sha }}\n publish-source-locked: ${{ needs.build.outputs.publish-source-locked }}\n publish-transaction: \"true\"\n publish-mode: publish-final-version\n publish-auth: trusted-publishing\n```\n\n`target-ref` remains the channel promotion target that must point at `sha`.\n`publish-source-ref` is the reviewed source-lock branch that authorized this\nspecific package publication. Direct `alpha/*` or `release/*` channel refs are\nnot valid publish source locks when `require-publish-source-lock` is enabled,\nand a mismatched `publish-source-sha` fails before any promotion or publish side effects begin.\nThe reusable promote workflow serializes non-dry-run promotion intents per\nrepository and re-reads `target-ref` before checkout, dependency installation,\nrelease-candidate resolution, or publish-gate writes. If a queued intent asks\nfor an older SHA after the protected channel has advanced, the workflow records\nthe requested/current SHA pair, verifies that the current target is ahead of\nthe requested commit, and exits successfully as a superseded no-op. Diverged,\nbehind, or unreadable comparisons still fail closed.\nThe action repeats that check at its mutation boundary for governed promotion\ncalls, closing the race between workflow preflight and action start. Direct\nnon-governed calls and dry-runs keep the strict target mismatch error so local\ndiagnostics cannot silently reinterpret a stale request.\nThe reusable build workflow performs the cheaper channel-ref preflight earlier:\nafter source-lock resolution and before the build matrix, it requires the target\nchannel ref such as `alpha/v22/v22.22` or `release/v22/v22.22` to already point\nat the locked `publish-source-sha`. If not, maintainers should merge the source\ncommit through the channel PR first.\n\nFor promote-only release candidates, attach the PR-stage reusable build evidence\nand fail before publish-gate side effects if it no longer matches:\n\n```yaml\n- uses: kungfu-systems/buildchain/actions/promote-buildchain-ref@v2\n with:\n token: ${{ secrets.BUILDCHAIN_PROMOTION_TOKEN }}\n sha: ${{ needs.build.outputs.publish-source-sha }}\n target-ref: alpha/v22/v22.22\n promote-only-release-candidate: \"true\"\n release-candidate-passport-path: .buildchain/artifacts/release-candidate-passport.json\n release-candidate-build-summary-path: .buildchain/artifacts/build-summary.json\n```\n\nThe action validates repository, channel, source identity, platform matrix, and\nthe aggregate build-summary hash before it writes version state, opens\nrelease-state, runs publish transaction logic, or moves tags/branches. Source\nidentity accepts the exact source SHA, the PR merge ref SHA, or the promoted\nchannel HEAD's Git tree SHA matching the passport tree hash. If validation\nfails, run or attach the verified channel PR build first instead of promoting a\nstale or unproven artifact set.\n\nWhen enabled, the action creates or resumes a release transaction keyed by\nrepository, version, source SHA, and target ref. It persists that transaction to\na machine-managed branch under `buildchain/release-state/<version>`, with\n`state.json` and, once available, `evidence.json`. Fresh GitHub runners read\nthat durable ref before running publish, so reruns do not depend on a previous\nrunner's local `.buildchain` directory.\n\nThe action runs `lifecycle.publish` from `buildchain.toml` or the explicit\n`publish-command` input, then validates publish evidence before exact tags and\nfloating refs move. If durable state persistence fails, the action fails closed\nbefore publish or public ref finalization.\n\n`publish-mode` defaults to `publish-final-version`, the token-free path for\nnormal npm Trusted Publishing. Same-version alpha-to-latest recovery must be\ndeclared as `publish-mode: promote-existing-version` and\n`publish-auth: npm-token`; Buildchain runs `npm whoami` before it creates\nrelease-state or moves any `npm dist-tag`. The Trusted Publishing mode is not\nallowed to perform `npm dist-tag add`.\n\nBuildchain itself uses this path for npm. Its `lifecycle.publish` runs\n`node scripts/npm-publish-transaction.mjs`, which publishes\n`@kungfu-tech/buildchain` through npm Trusted Publishing and writes npm\nartifact evidence into the transaction before release refs move. The separate\n`.github/workflows/npm-publish.yml` workflow is dry-run only.\n\nPublish lifecycle environment:\n\n```text\nBUILDCHAIN_VERSION\nBUILDCHAIN_CHANNEL\nBUILDCHAIN_SOURCE_SHA\nBUILDCHAIN_TARGET_REF\nBUILDCHAIN_RELEASE_STATE\nBUILDCHAIN_EVIDENCE_DIR\nBUILDCHAIN_RELEASE_SHA\nBUILDCHAIN_RELEASE_MATERIAL_SHA\nBUILDCHAIN_PUBLISH_TOOLING_SHA\nBUILDCHAIN_PUBLISH_EVIDENCE\n```\n\nThe action outputs `transaction-id`, `transaction-state`,\n`transaction-exact-tag`, `public-release-tag`, `transaction-release-sha`,\n`transaction-state-ref`, `transaction-state-sha`, `transaction-state-path`,\n`publish-evidence-path`, and `release-passport-path`, `release-passport-output-dir`,\n`release-passport-state-sha`, and `finalization-needed`.\n`transaction-state-ref` is the durable recovery location.\n`release-passport-state-sha` is the durable ref commit after the generated\n`release-passport/*` files have been uploaded into that recovery ref.\n`finalization-needed=true` means publish evidence is valid, but protected branch\nor ref finalization needs a later idempotent promotion run. For release\nfinalization, Buildchain may create a same-repository generated version-state\nPR when GitHub rejects the direct protected ref update; that PR is Buildchain\nbookkeeping, not a consumer-authored release change.\nSet `github-release: \"true\"` when the semver promotion should also publish the\npublic GitHub Release. After the release transaction reaches `complete` and\n`finalization-needed` is false, the action creates or updates the GitHub Release\nfor `public-release-tag`, applies deterministic semver metadata\n(`prerelease=true` and `make_latest=false` for prerelease tags, latest for stable\ntags), and uploads the publish evidence file plus generated release passport\nassets. For anchored/manual package releases, `public-release-tag` is derived\nfrom the published package version, while `transaction-exact-tag` remains the\ninternal Buildchain transaction ref for recovery and audit. If the transaction is\nnot complete yet, the action defers GitHub Release publication to the next\nidempotent promotion run.\n\nAfter a publish transaction reaches `complete`, the action generates the unified\n`buildchain-release-passport` in `.buildchain/release-passport` by default and\npersists those files under `release-passport/` in the durable release-state ref.\nSet `release-passport-product-name` to record the consumer product name, for\nexample `Libnode`, instead of the default `Buildchain`.\nSet `release-passport-kfd-1-witness-jsons` to newline-separated KFD-1\ncontract-world witness JSON paths when released artifacts must prove\nbyte-for-byte KFD contract surfaces. Buildchain imports the KFD metadata from\n`@kungfu-tech/kfd`, freezes the witness, verifies artifact bytes, and writes the\nresult under the KFD-provided `kfd-1` passport section.\nSet `release-passport-kfd-2-claim-jsons` to newline-separated KFD-2 public\nrelease trust claim JSON paths when a release makes additional human/agent\nvisible claims. Buildchain requires each public claim to bind declared sources,\nmachine-readable evidence, hashes, artifact coordinates, verification results,\naudit boundary, responsibility state, and residual risk. Unbound claims fail\npassport verification; prose-only claims downgrade the KFD-2 audit.\nSet `release-passport-kfd-3-prebuild-witness-jsons` to newline-separated KFD-3\ncollaboration-interface pre-build witness paths, then provide artifact-side\nevidence with `release-passport-kfd-3-artifact-witness-jsons` or a\nproduct-owned `release-passport-kfd-3-artifact-verify-command` such as\n`kungfu agent verify --json`. Buildchain compares declared shipped public\nsurfaces with artifact-exposed public surfaces and writes the result under the\nKFD-provided `kfd-3` passport section.\nBuildchain's own release workflow sets `release-passport-buildchain-self-kfd:\n\"true\"`. In that mode the action generates Buildchain-owned KFD-1/2/3 witnesses\ninside the final version-state workspace, after the release transaction has\nmaterialized generated files such as `package.json` and `dist/site/*`. This\nkeeps self-hosted KFD witness hashes bound to the exact published package\ninstead of to a pre-promotion checkout.\nWhen present, the passport includes the aggregate build summary, platform\nartifact manifests, npm publish evidence, dist-tag promotion evidence, the\nrelease-state ref, trusted publishing metadata, and the Buildchain transaction\nresult. After the first passport upload, Buildchain backfills the durable\nrelease-state SHA into `buildchain.release.json` and persists the passport\nagain, so the consumer-side passport is a complete audit entrypoint. Set\n`release-passport: \"false\"` only for a controlled recovery run that must skip\npassport generation.\n\nFinalization recovery is anchored to the durable transaction, not to a single\nworkflow run SHA. After generated version-state bookkeeping is applied, the\ncurrent channel head can be the generated version-state commit or a historical\nmerge commit that contains or corresponds to the recorded `release_material_sha`;\nit does not have to equal the original `source_sha` or the transaction\n`release_sha`. Reruns accept exact tags that already point at the transaction\nrelease/material SHA or the finalized channel head, and continue moving any\nmissing floating tags or dev/alpha refs before marking the transaction\n`complete`.\n\nNormal reruns accept already-published artifacts only when evidence matches.\nMissing required artifacts can be published on the next run. Conflicting\nartifacts put the transaction into `repair_required`; `abandoned` and\n`failed_permanently` also fail closed unless `publish-transaction-override` is\nset for a controlled repair.\n\nIn strict buildchain promotion, ref movement is also gated by the old ABV\ngovernance semantics:\n\n- the target channel branch protection details must be readable, must enforce\n protection for administrators, and must require approving PR review plus the\n strict `check` job from the `Verify` workflow;\n- alpha promotion must come from a merged same-repository PR\n `dev/vN/vN.M -> alpha/vN/vN.M`, or from a strict same-line\n `publish-gate/alpha/vN/vN.M/<version> -> alpha/vN/vN.M` source-lock PR;\n- release promotion must come from a merged same-repository PR\n `alpha/vN/vN.M -> release/vN/vN.M`, or from a strict same-line\n `publish-gate/release/vN/vN.M/<version> -> release/vN/vN.M` source-lock PR;\n- major promotion must come from a merged same-repository PR\n `release/vN/vN.M -> publish-gate/major`;\n- release promotion must have an exact alpha tag for the same patch line, and\n the release source tree must match that alpha tag tree, so release does not\n introduce new code after alpha;\n- anchored/manual release promotion may differ from that alpha tree only in\n declared `version.files` and the configured anchor manifest, and only when the\n checked-out release material has passed `lifecycle.verify` or the explicit\n `verification-command`;\n- generated release and next-alpha version-state trees can be verified locally\n with either the `verification-command` input or `buildchain.toml`\n `lifecycle.verify` before any tags or channel refs move.\n\nThe promotion workflow should use `BUILDCHAIN_PROMOTION_TOKEN` for non-dry-run\npromotion. The token is the buildchain equivalent of the old ABV runner release\nauthority: protected branch review and check rules guard human channel merges,\nwhile the reusable build trust gate now checks the source-lock channel HEAD and\nmerged same-repository PR lineage before heavy build runners start. This action\nstill independently rechecks PR lineage, alpha/release tree equivalence, and\ngenerated version-state verification before moving channel refs and tags.\nGenerated version-state direct ref updates can use a separate\n`generated-ref-update-token`; the reusable wrapper defaults it to\n`secrets.BUILDCHAIN_PROMOTION_TOKEN || github.token`. Consumers that protect\n`dev/*`, `alpha/*`, or `release/*` with one required review should configure\n`BUILDCHAIN_PROMOTION_TOKEN` as the bypass-capable release authority, so\npost-publish dev/alpha/release bookkeeping completes without a human PR.\nThe reusable `release-candidate-promote.yml` wrapper defaults\n`branch-protection-bypass-apps` to `github-actions`, so flow-internal promotion\ncan complete generated `dev`/`alpha`/`release` bookkeeping while ordinary human\npushes and PR merges remain governed by the one-review branch protection rule.\nThe promotion action also auto-discovers the current token's authenticated user\nor app and adds it to the managed bypass allowlist, so consumers do not have to\ndeclare the same release authority twice.\n\nThe tag names intentionally follow the old ABV release semantics:\nexact release tags are `vX.Y.Z`, exact alpha tags are `vX.Y.Z-alpha.N`, floating\nrelease tags are minor/major tags such as `v2.0` and `v2`, and floating alpha\ntags are minor-line tags such as `v2.0-alpha`. Bare tags such as `1.0.0` are not\nmaintained as buildchain release entrypoints.\n\nRepository rulesets should protect exact tags, not every `v*` tag. A ruleset\nsuch as `refs/tags/v*` also protects floating channel tags like `v2.0-alpha`,\nwhich Buildchain must update after exact tags and publish evidence are durable.\nUse an exact-tag rule such as `refs/tags/v*.*.*` for immutable evidence tags and\nleave floating channel tags mutable for the promotion token."
135
135
  },
136
136
  {
137
137
  "id": "action:report-buildchain-issue",
@@ -1161,7 +1161,7 @@
1161
1161
  ],
1162
1162
  "maturity": "stable",
1163
1163
  "sourcePath": "docs/release-governance.md",
1164
- "digest": "sha256:69218a4749170e1f84b82f211d57187a7ff33f1a510aced587e240d1d901b9e7",
1164
+ "digest": "sha256:9c8e3f096d314b2d0ea9a6badfdf263006e190aaa6e861489bdd05c93d3eaf04",
1165
1165
  "headings": [
1166
1166
  {
1167
1167
  "level": 1,
@@ -1239,7 +1239,7 @@
1239
1239
  "anchor": "operational-reading-order"
1240
1240
  }
1241
1241
  ],
1242
- "markdown": "# Release Governance\n\nBuildchain v2 preserves the release semantics of the older ABV workflow while\nmoving the implementation into one modern repository.\n\nThe central idea is simple: a reviewed merge into a release channel is the\nrelease intent. Automation must then create the version-state commit, exact tag,\nfloating tag, and next alpha state that make that intent true in Git.\n\n## Design Problem\n\nKungfu release automation has to keep four facts aligned:\n\n1. The source tree that was reviewed.\n2. The package version recorded in manifests such as `package.json` or\n `lerna.json`.\n3. The exact immutable release or prerelease tag.\n4. The floating channel refs that consumers actually use.\n\nIf any one of these facts is updated by hand, the system can split:\n\n- a consumer can fetch `v2.0` and receive a tree whose package version still\n says the previous release;\n- a maintainer can move `v2` without producing an exact `v2.0.N` audit tag;\n- an alpha can be promoted to production even though the release tree is not the\n same tree that was tested;\n- a protected branch merge can succeed while the follow-up version commit is\n missing, or a flow-internal generated `dev`/`alpha`/`release` ref update can\n fail after publish because the automation identity was not declared in the\n branch-protection review bypass allowance.\n\nThe older ABV workflow addressed this by letting GitHub PRs drive release\nstate. Buildchain keeps that choice because it makes release intent reviewable,\nobservable, and recoverable from Git history.\n\n## What ABV Contributed\n\nThe old ABV model was not just \"bump a version number.\" It encoded a governance\nloop:\n\n- release branches are named as channels: `dev`, `alpha`, `release`, and the\n administrative `publish-gate/major`;\n- a PR from one channel to the next is the release request;\n- verify jobs check that the branch pair is valid before merge;\n- a maintainer review is required before the branch moves;\n- after merge, automation writes the version change and moves tags;\n- exact tags and floating refs are aligned with the resulting commit;\n- the next development channel is prepared automatically.\n\nABV also kept the version-state mutation in the repository. For JavaScript\nrepositories that usually meant changing `lerna.json` and/or `package.json`.\nThat commit is important because the tag alone is not enough evidence: the\nsource tree should also declare the version that the tag advertises.\n\nBuildchain v2 treats that as a hard semantic requirement for its own release\nline.\n\n## Buildchain Implementation\n\nBuildchain implements the same governance loop with:\n\n- `.github/workflows/release-verify.yml` for PR verification;\n- `.github/workflows/buildchain-ref-promotion.yml` for post-verify ref\n promotion; this workflow dogfoods the declarative\n `release-candidate-promote.yml` wrapper and does not hand-wire resolver,\n artifact download, publish-gate, or promote action steps;\n- Buildchain self promotion enables `release-passport-buildchain-self-kfd`, so\n the promote action generates KFD-1 witnesses, KFD-2 public claim JSON, and\n KFD-3 collaboration-interface witnesses from the final version-state workspace\n before release passport finalization. The witness hashes therefore bind to the\n exact published package and site facts from\n `packages/core/buildchain-kfd-claims.js` instead of relying on prose release\n notes;\n- `actions/promote-buildchain-ref` for branch, tag, version-state, and\n governance checks;\n- package-manager adapters that can update version state for pnpm, npm, and\n yarn style repositories;\n- `buildchain.toml` lifecycle configuration for repositories whose version\n state or verification commands are not Node package-manager defaults.\n\nThe implementation is intentionally stricter than a local release script:\n\n- manual workflow dispatch can only do dry-run promotion;\n- non-dry-run promotion must be driven by a completed `Verify` workflow;\n- target branch protection details must be readable, and branch protection must\n apply to administrators as well as regular contributors;\n- alpha promotion must come from a merged same-repository PR from\n `dev/vX/vX.Y` to `alpha/vX/vX.Y`;\n- release promotion must come from a merged same-repository PR from\n `alpha/vX/vX.Y` to `release/vX/vX.Y`;\n- major promotion must come from a merged same-repository PR from\n `release/vX/vX.Y` to `publish-gate/major`;\n- release promotion requires an existing same-patch alpha tag and checks the\n release source tree against that tested alpha tree;\n- generated version-state commits are verified before refs move.\n\n## Version Lines\n\nKungfu uses Python-like version lines where a minor line can represent a\nlong-lived product train. A line such as `v2.0` can produce many production\npatch releases:\n\n```text\nv2.0.0\nv2.0.1\nv2.0.2\n...\nv2.0.1234\n```\n\nThis is why Buildchain maintains both exact and floating refs:\n\n- `v2.0.2` is immutable release evidence;\n- `v2.0` is the latest production release on the `2.0` line;\n- `v2` is the selected stable major-line entrypoint;\n- `v2.0.3-alpha.0` is immutable alpha evidence;\n- `v2.0-alpha` is the latest test channel for the `2.0` line.\n\nA release does not mean \"minor is complete.\" It means \"this patch on this minor\nline is now production.\"\n\nGitHub repository rules must preserve that distinction. Exact tags such as\n`v2.0.2` and `v2.0.3-alpha.0` should be immutable. Floating channel tags such as\n`v2`, `v2.0`, and `v2.0-alpha` must remain movable by the Buildchain promotion\ntoken after governance checks and publish evidence pass. A tag ruleset that\nprotects every `refs/tags/v*` ref is too broad because it also locks the\nfloating channel tags that Buildchain is required to update. Prefer exact-tag\npatterns such as `refs/tags/v*.*.*` for immutable release evidence, while\nleaving floating channel tags under Buildchain automation control.\n\n## Alpha Semantics\n\nAn alpha merge is:\n\n```text\ndev/vX/vX.Y -> alpha/vX/vX.Y\n```\n\nBuildchain then:\n\n1. Computes the next prerelease for the minor line.\n2. Writes version state such as `vX.Y.Z-alpha.N`.\n3. Verifies the generated version-state tree.\n4. Creates or reuses the exact alpha tag.\n5. Moves `alpha/vX/vX.Y` to the generated alpha commit.\n6. Moves `dev/vX/vX.Y` to the same generated alpha commit when this is a\n fast-forward update.\n7. Moves `vX.Y-alpha` to the same generated alpha commit.\n\nThis keeps the test channel self-describing. If a consumer checks out\n`v2.0-alpha`, the manifests and exact alpha tag agree.\n\nIf `dev/vX/vX.Y` has already advanced before generated alpha version-state\nbookkeeping can sync back, Buildchain records `skipped-non-fast-forward` for the\ndev sync and still completes the exact and floating alpha tags for the reviewed\nalpha commit. Later dev changes must go through their own dev-to-alpha\npromotion instead of rewinding dev. The normal path is direct: after alpha\nmerges, Buildchain applies the generated version-state commit to alpha and then\nfast-forwards dev to the same commit without a human version-state PR.\n\nIf alpha finalization is resumed after generated version-state bookkeeping was\npartially applied, Buildchain accepts the current alpha head as the generated\ncommit, or as a historical merge commit that contains the recorded release\nmaterial. An already-created exact alpha tag may point at the transaction\nrelease/material SHA or at the finalized alpha head; missing floating alpha\ntags are retried before the transaction becomes `complete`.\n\n## Release Semantics\n\nA release merge is:\n\n```text\nalpha/vX/vX.Y -> release/vX/vX.Y\n```\n\nBuildchain then:\n\n1. Finds the same-patch alpha tag that was tested.\n2. Checks that the release source tree matches that alpha tag tree, excluding\n only generated version-state differences.\n3. Writes final release version state such as `vX.Y.Z`.\n4. Verifies the generated release tree.\n5. Creates or reuses the exact release tag `vX.Y.Z`.\n6. Moves `release/vX/vX.Y` to the exact release commit.\n7. Moves `vX.Y` to the exact release commit.\n8. Moves `vX` when this minor line should be the stable major entrypoint.\n9. Prepares the next alpha version-state commit, such as\n `vX.Y.(Z+1)-alpha.0`.\n10. Moves `alpha/vX/vX.Y`, `dev/vX/vX.Y`, and `vX.Y-alpha` to that next alpha\n commit.\n\nThe production channel and the test channel therefore intentionally diverge\nafter release: production stays on the release commit, while alpha/dev continue\nat the next prerelease commit.\n\nIf release finalization is resumed after generated version-state bookkeeping was\npartially applied, Buildchain applies the same recovery rule: the current\nrelease head may be the generated commit, or a historical merge commit that\ncontains the recorded release material, existing exact tags and alpha/dev refs\nare accepted when they match the transaction, and missing floating `vX.Y` or\n`vX` tags are retried idempotently before completion.\n\n## Major Gate Semantics\n\nA major gate merge is:\n\n```text\nrelease/vX/vX.Y -> publish-gate/major\n```\n\n`publish-gate/major` is the explicit replacement for the older ABV `main`\nchannel. The name is intentionally operational: it is a gate for a rare\nadministrator decision, not the active trunk. Keeping this decision in the same\nPR UI as alpha and release promotion keeps the human workflow simple while\navoiding the misleading meaning of `main`. The older `major-gate` branch name is\na compatibility alias only.\n\nBuildchain then:\n\n1. Verifies the source is a merged same-repository PR from a protected release\n line into `publish-gate/major`.\n2. Writes the next major production version state, such as `v(X+1).0.0`.\n3. Creates or reuses the exact release tag `v(X+1).0.0`.\n4. Moves `publish-gate/major` and `release/v(X+1)/v(X+1).0` to that release commit.\n5. Moves `v(X+1).0` and `v(X+1)` to that release commit.\n6. Prepares the next alpha version-state commit, such as\n `v(X+1).0.1-alpha.0`.\n7. Moves `alpha/v(X+1)/v(X+1).0`, `dev/v(X+1)/v(X+1).0`, and\n `v(X+1).0-alpha` to that next alpha commit.\n\nChecking out `publish-gate/major` should therefore look like a frozen release\nstate, not like a branch where day-to-day source work continues. Day-to-day\nsource work continues on `dev/vX/vX.Y`.\n\n## Protected Dev Branches\n\n`dev/vX/vX.Y` is a protected development channel, not a scratch branch. Normal\nsource changes should be made on work branches such as `feature/*`, `fix/*`,\n`chore/*`, `docs/*`, `ci/*`, or `refactor/*`, then reviewed through a pull\nrequest into the target dev line.\n\nThis keeps the earliest development channel audit-friendly:\n\n- the version line being changed is visible in the PR base branch;\n- CI and required checks run before the channel moves;\n- branch protection can prevent direct pushes and stale merges;\n- later `dev -> alpha -> release` promotion inherits a reviewable source\n lineage instead of trying to reconstruct how the dev branch changed.\n\nBuildchain provides the reusable\n`.github/workflows/dev-pr-auto-merge.yml` workflow for repositories that want a\nscheduled or manual \"merge ready dev PRs\" pass. The consumer repository owns\nthe trigger schedule, but the merge decision is declared through workflow\ninputs: target dev branch, required status/check names, ready and block labels,\nallowed work-branch prefixes, review requirements, maximum merges per run,\nmerge method, and dry-run mode.\n\nThe workflow defaults are conservative. A PR is skipped unless it targets the\nconfigured dev line, is not a draft, has the ready label, has no block label,\ncomes from the same repository, uses an allowed work-branch prefix, has a\ncurrent approval, is mergeable, and has the configured required checks passing.\nAfter each merge, the next PR is re-evaluated before it can move the protected\ndev branch. This prevents one merge from silently making the next candidate\nstale or conflicting.\n\nThe required check should be the `check` job. Repositories can keep that job\nname stable while changing the actual verification command declaratively in\n`buildchain.toml`:\n\n```toml\n[lifecycle.install]\ncommand = \"cargo fetch --locked\"\n\n[lifecycle.verify]\ncommand = \"cargo test --workspace --locked\"\n```\n\nConsumers that want Buildchain to own the check wrapper can call\n`.github/workflows/check.yml@v2`. The wrapper runs the declared\n`lifecycle.install` and `lifecycle.verify` stages and fails the `check` job when\neither declaration is missing or the command exits non-zero.\n\nTypical consumer wrapper:\n\n```yaml\nname: Merge Ready Dev PRs\n\non:\n schedule:\n - cron: \"17 * * * *\"\n workflow_dispatch:\n inputs:\n dry-run:\n type: boolean\n default: true\n\njobs:\n merge-dev:\n uses: kungfu-systems/buildchain/.github/workflows/dev-pr-auto-merge.yml@v2\n permissions:\n contents: write\n pull-requests: write\n checks: read\n statuses: read\n with:\n target-branch: dev/v2/v2.6\n required-status-checks: check\n ready-label: ready\n block-labels: blocked,do-not-merge\n max-merges: 1\n dry-run: ${{ inputs.dry-run || false }}\n```\n\n## Buildchain Patrol\n\n`dev-pr-auto-merge.yml` remains the focused merge primitive. For repositories\nthat want a stable day-to-day operations contract, Buildchain also exposes a\npatrol workflow family:\n\n| Workflow | Intended cadence | Default intent |\n| --- | --- | --- |\n| `.github/workflows/patrol-daily.yml` | daily | lightweight inspection plus ready dev PR maintenance |\n| `.github/workflows/patrol-weekly.yml` | weekly | release-state, passport, gate, and stale-state health checks as they are added |\n| `.github/workflows/patrol-monthly.yml` | monthly | governance, permission, branch-protection, and workflow drift checks as they are added |\n\nThe cadence names describe patrol intensity, not release cadence:\n\n- daily patrol can run every day without implying a daily release;\n- weekly patrol is for medium-cost maintenance and audit checks;\n- monthly patrol is for structural drift checks that should not block ordinary\n development velocity.\n\nConsumers should schedule thin callers and keep their YAML declarative. For\nexample:\n\n```yaml\nname: Buildchain Daily Patrol\n\non:\n schedule:\n - cron: \"17 2 * * *\"\n workflow_dispatch:\n\njobs:\n patrol:\n uses: kungfu-systems/buildchain/.github/workflows/patrol-daily.yml@v2\n with:\n dry-run: false\n max-actions: 1\n```\n\nWeekly and monthly callers use the matching wrapper:\n\n```yaml\njobs:\n patrol:\n uses: kungfu-systems/buildchain/.github/workflows/patrol-weekly.yml@v2\n with:\n dry-run: true\n```\n\nAll three wrappers default to the `v2` floating Buildchain runtime. When\n`target-branch` is omitted, the caller's current/default branch selects the\nactive semver dev line, so consumers do not pin patrol to a stale minor branch.\nThe separate workflow names keep consumer schedules readable and stable while\nBuildchain adds new checks behind the cadence wrappers.\n\n## Package-Manager Adapters\n\nOld ABV assumed JavaScript repositories with root version state and often\nLerna. Buildchain keeps the version-state contract but does not assume every\nrepository is yarn/Lerna.\n\nThe promotion action discovers and updates:\n\n- root `package.json`;\n- `lerna.json`;\n- package manifests from `package.json` workspaces;\n- package manifests from `lerna.json` packages;\n- package manifests from `pnpm-workspace.yaml`.\n\nIt then runs the repository's detected package manager semantics where needed:\n\n- pnpm repositories use pnpm-oriented workspace discovery;\n- npm repositories use npm/package-lock semantics where present;\n- yarn repositories use yarn-style metadata where present.\n\nFor Buildchain itself, version state is required. For a consumer repository that\nhas no package manifest, the same action can degrade to ref-only behavior only\nwhen that is explicitly allowed by the caller.\n\n## Lifecycle Configuration\n\n`buildchain.toml` is the v2 user configuration format. It lets a repository\ndeclare version-state files and lifecycle commands without pretending every\nproject is a Node workspace. Supported version files include JSON, TOML, and\nregex-based files such as `CMakeLists.txt` or `conanfile.py`.\n\nThe promotion action currently consumes `version.files` and `lifecycle.verify`.\nThe verify stage runs after generated version-state changes are applied locally\nand before any release refs move. If `verification-command` is passed directly\nto the action, that explicit command overrides `lifecycle.verify`.\n\nProtected release-line branches keep their normal human review gate. Managed\n`dev/vN/vN.M`, `alpha/vN/vN.M`, and `release/vN/vN.M` branches are configured\nwith one required approving review, strict GitHub Actions checks, administrator\nenforcement, conversation resolution, no force pushes, and no deletions. The\nreusable `release-candidate-promote.yml` wrapper defaults\n`branch-protection-bypass-apps` to `github-actions`, which lets the workflow's\nautomation identity apply generated version-state or post-publish channel\nbookkeeping after the reviewed channel PR has merged. Direct\n`promote-buildchain-ref` callers must opt into the same controlled bypass with\n`branch-protection-bypass-apps`, `branch-protection-bypass-users`, or\n`branch-protection-bypass-teams`; the action also adds the current promotion\ntoken's authenticated user or app to the managed bypass allowlist. Before\npatching a protected generated bookkeeping ref, the action creates the\nconfigured required check on the exact generated version-state commit, so strict\nstatus checks are satisfied by machine-verifiable Buildchain evidence rather\nthan a human PR. The protected ref PATCH itself uses the generated ref update\ntoken; the reusable wrapper defaults it to\n`secrets.BUILDCHAIN_PROMOTION_TOKEN || github.token`. If direct generated\nrelease finalization bookkeeping is still rejected, Buildchain creates or\nreuses a same-repository `buildchain/version-state/*` PR based on the current\ntarget channel head and records `finalization-needed=true` in the durable\ntransaction output. Strict alpha bookkeeping still fails with a\ntoken/protection diagnostic instead of creating a post-publish PR.\nBuildchain's own promotion workflow reads `BUILDCHAIN_PROMOTION_BYPASS_APPS`,\n`BUILDCHAIN_PROMOTION_BYPASS_USERS`, and\n`BUILDCHAIN_PROMOTION_BYPASS_TEAMS` repository variables so the declared bypass\nidentity can match the actual `BUILDCHAIN_PROMOTION_TOKEN` actor, but consumers\ndo not need to duplicate that actor manually when the token identity is\ndiscoverable.\n\n## What This Guarantees\n\nWhen the loop succeeds, maintainers and consumers can rely on these facts:\n\n- every production release has an exact tag such as `v2.0.2`;\n- every production minor line has a floating tag such as `v2.0`;\n- every selected stable major has a floating tag such as `v2`;\n- every next-major release is driven by a reviewed `release -> publish-gate/major` PR,\n not a hidden manual button;\n- every test channel has an exact alpha tag such as `v2.0.3-alpha.0`;\n- every alpha minor line has a floating tag such as `v2.0-alpha`;\n- version manifests match the tag visible from the same commit;\n- production releases are derived from the alpha tree that was tested;\n- manual non-dry-run promotion cannot bypass PR review and verification;\n- flow-internal automation bypasses apply only to declared GitHub Apps, users,\n or teams on Buildchain-managed channel branch protection, while one-review\n protection remains enforced for humans;\n- admin users cannot make a channel promotion valid by temporarily bypassing\n branch protection.\n\nThis is the practical meaning of \"governance closed loop\" in Buildchain: the\ndecision, code, version state, and Git refs close over the same evidence chain.\n\n## What This Does Not Do\n\nBuildchain release promotion does not embed registry clients or product-specific\npublish logic. When publish transactions are enabled, `promote-buildchain-ref`\ncan run the consumer's `lifecycle.publish` command and own the transaction,\nevidence validation, durable recovery state, and ref finalization order. The\nconsumer repository still owns registry truth: npm, PyPI, OCI, S3, Conan, CMake\npackaging, download pages, dist-tags, and similar side effects must be\nimplemented by project lifecycle commands that emit Buildchain publish evidence.\n\nEvery Buildchain publish model that can run registry side effects must bind the\npublish entrypoint to an immutable `publish-gate/*` source lock. The reusable\n`release-candidate-promote.yml@v2` wrapper creates or updates that gate ref and\npasses `require-publish-source-lock`, `publish-source-ref`,\n`publish-source-sha`, and `publish-source-locked` to\n`promote-buildchain-ref`. Direct action callers must pass the same four inputs\nfrom the reusable build outputs. Workflows that only collect passports or run\ndry-run package checks do not move publish refs and are not publish-gate\npublication models.\n\nSemver GitHub Release publication is owned by `promote-buildchain-ref`, not by\nconsumer shell glue. Consumers normally use the `release-candidate-promote.yml`\nwrapper, where GitHub Release publication is enabled by default and can be\ndisabled with `github-release: false`; the wrapper passes that declaration to\nthe action. After the publish transaction reaches `complete`, Buildchain creates\nor updates the public GitHub Release and uploads the generated\n`buildchain.release.json`, release-passport assets, and publish evidence. Semver\nprerelease tags are marked `prerelease=true` and `make_latest=false`; stable\nsemver tags are marked latest. For anchored/manual package releases, the public\nrelease tag defaults to `v<publishedVersion>` while the internal exact\ntransaction tag remains in the release passport and release-state ref. This is\nthe supported path for downstream\n`release.published` propagation across semver, major, and promote-only release\ncandidate publication models.\n\nBuildchain also does not maintain bare exact tags such as `1.0.0`. The supported\nexact release and alpha refs are v-prefixed:\n\n```text\nv2.0.0\nv2.0.1-alpha.0\n```\n\n## Operational Reading Order\n\nWhen debugging or extending release behavior, read in this order:\n\n1. `docs/release-flow.md`\n2. `.github/workflows/release-verify.yml`\n3. `.github/workflows/buildchain-ref-promotion.yml`\n4. `.github/workflows/release-candidate-promote.yml`\n5. `actions/promote-buildchain-ref/README.md`\n6. `actions/promote-buildchain-ref/src/`\n7. `docs/migration-inventory.md`\n\nThat path gives the policy first, the workflow trigger second, and the action\nimplementation last."
1242
+ "markdown": "# Release Governance\n\nBuildchain v2 preserves the release semantics of the older ABV workflow while\nmoving the implementation into one modern repository.\n\nThe central idea is simple: a reviewed merge into a release channel is the\nrelease intent. Automation must then create the version-state commit, exact tag,\nfloating tag, and next alpha state that make that intent true in Git.\n\n## Design Problem\n\nKungfu release automation has to keep four facts aligned:\n\n1. The source tree that was reviewed.\n2. The package version recorded in manifests such as `package.json` or\n `lerna.json`.\n3. The exact immutable release or prerelease tag.\n4. The floating channel refs that consumers actually use.\n\nIf any one of these facts is updated by hand, the system can split:\n\n- a consumer can fetch `v2.0` and receive a tree whose package version still\n says the previous release;\n- a maintainer can move `v2` without producing an exact `v2.0.N` audit tag;\n- an alpha can be promoted to production even though the release tree is not the\n same tree that was tested;\n- a protected branch merge can succeed while the follow-up version commit is\n missing, or a flow-internal generated `dev`/`alpha`/`release` ref update can\n fail after publish because the automation identity was not declared in the\n branch-protection review bypass allowance.\n\nThe older ABV workflow addressed this by letting GitHub PRs drive release\nstate. Buildchain keeps that choice because it makes release intent reviewable,\nobservable, and recoverable from Git history.\n\n## What ABV Contributed\n\nThe old ABV model was not just \"bump a version number.\" It encoded a governance\nloop:\n\n- release branches are named as channels: `dev`, `alpha`, `release`, and the\n administrative `publish-gate/major`;\n- a PR from one channel to the next is the release request;\n- verify jobs check that the branch pair is valid before merge;\n- a maintainer review is required before the branch moves;\n- after merge, automation writes the version change and moves tags;\n- exact tags and floating refs are aligned with the resulting commit;\n- the next development channel is prepared automatically.\n\nABV also kept the version-state mutation in the repository. For JavaScript\nrepositories that usually meant changing `lerna.json` and/or `package.json`.\nThat commit is important because the tag alone is not enough evidence: the\nsource tree should also declare the version that the tag advertises.\n\nBuildchain v2 treats that as a hard semantic requirement for its own release\nline.\n\n## Buildchain Implementation\n\nBuildchain implements the same governance loop with:\n\n- `.github/workflows/release-verify.yml` for PR verification;\n- `.github/workflows/buildchain-ref-promotion.yml` for post-verify ref\n promotion; this workflow dogfoods the declarative\n `release-candidate-promote.yml` wrapper and does not hand-wire resolver,\n artifact download, publish-gate, or promote action steps;\n- Buildchain self promotion enables `release-passport-buildchain-self-kfd`, so\n the promote action generates KFD-1 witnesses, KFD-2 public claim JSON, and\n KFD-3 collaboration-interface witnesses from the final version-state workspace\n before release passport finalization. The witness hashes therefore bind to the\n exact published package and site facts from\n `packages/core/buildchain-kfd-claims.js` instead of relying on prose release\n notes;\n- `actions/promote-buildchain-ref` for branch, tag, version-state, and\n governance checks;\n- package-manager adapters that can update version state for pnpm, npm, and\n yarn style repositories;\n- `buildchain.toml` lifecycle configuration for repositories whose version\n state or verification commands are not Node package-manager defaults.\n\nThe implementation is intentionally stricter than a local release script:\n\n- manual workflow dispatch can only do dry-run promotion;\n- non-dry-run promotion must be driven by a completed `Verify` workflow;\n- target branch protection details must be readable, and branch protection must\n apply to administrators as well as regular contributors;\n- alpha promotion must come from a merged same-repository PR from\n `dev/vX/vX.Y` to `alpha/vX/vX.Y`;\n- release promotion must come from a merged same-repository PR from\n `alpha/vX/vX.Y` to `release/vX/vX.Y`;\n- major promotion must come from a merged same-repository PR from\n `release/vX/vX.Y` to `publish-gate/major`;\n- release promotion requires an existing same-patch alpha tag and checks the\n release source tree against that tested alpha tree;\n- generated version-state commits are verified before refs move.\n\nPromotion intents are serialized globally per caller repository with\n`cancel-in-progress: false`. A queued intent re-reads its protected target ref\nbefore checkout, dependency installation, release-candidate resolution, or any\npublish-gate/ref mutation. If the ref already points at a newer SHA, that older\nintent is no longer release authority: the workflow records the requested and\ncurrent SHAs, proves that the current target is ahead of the requested commit,\nand completes as a `target-ref-advanced` superseded no-op. Diverged or behind\ncomparisons are not superseded transactions and still fail closed.\nMissing refs, unreadable repository state, invalid channels, governance\nfailures, and artifact mismatches still fail closed. The promote action repeats\nthe target check at the mutation boundary, so a ref that advances after the\nworkflow preflight cannot receive a second set of publication side effects.\n\n## Version Lines\n\nKungfu uses Python-like version lines where a minor line can represent a\nlong-lived product train. A line such as `v2.0` can produce many production\npatch releases:\n\n```text\nv2.0.0\nv2.0.1\nv2.0.2\n...\nv2.0.1234\n```\n\nThis is why Buildchain maintains both exact and floating refs:\n\n- `v2.0.2` is immutable release evidence;\n- `v2.0` is the latest production release on the `2.0` line;\n- `v2` is the selected stable major-line entrypoint;\n- `v2.0.3-alpha.0` is immutable alpha evidence;\n- `v2.0-alpha` is the latest test channel for the `2.0` line.\n\nA release does not mean \"minor is complete.\" It means \"this patch on this minor\nline is now production.\"\n\nGitHub repository rules must preserve that distinction. Exact tags such as\n`v2.0.2` and `v2.0.3-alpha.0` should be immutable. Floating channel tags such as\n`v2`, `v2.0`, and `v2.0-alpha` must remain movable by the Buildchain promotion\ntoken after governance checks and publish evidence pass. A tag ruleset that\nprotects every `refs/tags/v*` ref is too broad because it also locks the\nfloating channel tags that Buildchain is required to update. Prefer exact-tag\npatterns such as `refs/tags/v*.*.*` for immutable release evidence, while\nleaving floating channel tags under Buildchain automation control.\n\n## Alpha Semantics\n\nAn alpha merge is:\n\n```text\ndev/vX/vX.Y -> alpha/vX/vX.Y\n```\n\nBuildchain then:\n\n1. Computes the next prerelease for the minor line.\n2. Writes version state such as `vX.Y.Z-alpha.N`.\n3. Verifies the generated version-state tree.\n4. Creates or reuses the exact alpha tag.\n5. Moves `alpha/vX/vX.Y` to the generated alpha commit.\n6. Moves `dev/vX/vX.Y` to the same generated alpha commit when this is a\n fast-forward update.\n7. Moves `vX.Y-alpha` to the same generated alpha commit.\n\nThis keeps the test channel self-describing. If a consumer checks out\n`v2.0-alpha`, the manifests and exact alpha tag agree.\n\nIf `dev/vX/vX.Y` has already advanced before generated alpha version-state\nbookkeeping can sync back, Buildchain records `skipped-non-fast-forward` for the\ndev sync and still completes the exact and floating alpha tags for the reviewed\nalpha commit. Later dev changes must go through their own dev-to-alpha\npromotion instead of rewinding dev. The normal path is direct: after alpha\nmerges, Buildchain applies the generated version-state commit to alpha and then\nfast-forwards dev to the same commit without a human version-state PR.\n\nIf alpha finalization is resumed after generated version-state bookkeeping was\npartially applied, Buildchain accepts the current alpha head as the generated\ncommit, or as a historical merge commit that contains the recorded release\nmaterial. An already-created exact alpha tag may point at the transaction\nrelease/material SHA or at the finalized alpha head; missing floating alpha\ntags are retried before the transaction becomes `complete`.\n\n## Release Semantics\n\nA release merge is:\n\n```text\nalpha/vX/vX.Y -> release/vX/vX.Y\n```\n\nBuildchain then:\n\n1. Finds the same-patch alpha tag that was tested.\n2. Checks that the release source tree matches that alpha tag tree, excluding\n only generated version-state differences.\n3. Writes final release version state such as `vX.Y.Z`.\n4. Verifies the generated release tree.\n5. Creates or reuses the exact release tag `vX.Y.Z`.\n6. Moves `release/vX/vX.Y` to the exact release commit.\n7. Moves `vX.Y` to the exact release commit.\n8. Moves `vX` when this minor line should be the stable major entrypoint.\n9. Prepares the next alpha version-state commit, such as\n `vX.Y.(Z+1)-alpha.0`.\n10. Moves `alpha/vX/vX.Y`, `dev/vX/vX.Y`, and `vX.Y-alpha` to that next alpha\n commit.\n\nThe production channel and the test channel therefore intentionally diverge\nafter release: production stays on the release commit, while alpha/dev continue\nat the next prerelease commit.\n\nIf release finalization is resumed after generated version-state bookkeeping was\npartially applied, Buildchain applies the same recovery rule: the current\nrelease head may be the generated commit, or a historical merge commit that\ncontains the recorded release material, existing exact tags and alpha/dev refs\nare accepted when they match the transaction, and missing floating `vX.Y` or\n`vX` tags are retried idempotently before completion.\n\n## Major Gate Semantics\n\nA major gate merge is:\n\n```text\nrelease/vX/vX.Y -> publish-gate/major\n```\n\n`publish-gate/major` is the explicit replacement for the older ABV `main`\nchannel. The name is intentionally operational: it is a gate for a rare\nadministrator decision, not the active trunk. Keeping this decision in the same\nPR UI as alpha and release promotion keeps the human workflow simple while\navoiding the misleading meaning of `main`. The older `major-gate` branch name is\na compatibility alias only.\n\nBuildchain then:\n\n1. Verifies the source is a merged same-repository PR from a protected release\n line into `publish-gate/major`.\n2. Writes the next major production version state, such as `v(X+1).0.0`.\n3. Creates or reuses the exact release tag `v(X+1).0.0`.\n4. Moves `publish-gate/major` and `release/v(X+1)/v(X+1).0` to that release commit.\n5. Moves `v(X+1).0` and `v(X+1)` to that release commit.\n6. Prepares the next alpha version-state commit, such as\n `v(X+1).0.1-alpha.0`.\n7. Moves `alpha/v(X+1)/v(X+1).0`, `dev/v(X+1)/v(X+1).0`, and\n `v(X+1).0-alpha` to that next alpha commit.\n\nChecking out `publish-gate/major` should therefore look like a frozen release\nstate, not like a branch where day-to-day source work continues. Day-to-day\nsource work continues on `dev/vX/vX.Y`.\n\n## Protected Dev Branches\n\n`dev/vX/vX.Y` is a protected development channel, not a scratch branch. Normal\nsource changes should be made on work branches such as `feature/*`, `fix/*`,\n`chore/*`, `docs/*`, `ci/*`, or `refactor/*`, then reviewed through a pull\nrequest into the target dev line.\n\nThis keeps the earliest development channel audit-friendly:\n\n- the version line being changed is visible in the PR base branch;\n- CI and required checks run before the channel moves;\n- branch protection can prevent direct pushes and stale merges;\n- later `dev -> alpha -> release` promotion inherits a reviewable source\n lineage instead of trying to reconstruct how the dev branch changed.\n\nBuildchain provides the reusable\n`.github/workflows/dev-pr-auto-merge.yml` workflow for repositories that want a\nscheduled or manual \"merge ready dev PRs\" pass. The consumer repository owns\nthe trigger schedule, but the merge decision is declared through workflow\ninputs: target dev branch, required status/check names, ready and block labels,\nallowed work-branch prefixes, review requirements, maximum merges per run,\nmerge method, and dry-run mode.\n\nThe workflow defaults are conservative. A PR is skipped unless it targets the\nconfigured dev line, is not a draft, has the ready label, has no block label,\ncomes from the same repository, uses an allowed work-branch prefix, has a\ncurrent approval, is mergeable, and has the configured required checks passing.\nAfter each merge, the next PR is re-evaluated before it can move the protected\ndev branch. This prevents one merge from silently making the next candidate\nstale or conflicting.\n\nThe required check should be the `check` job. Repositories can keep that job\nname stable while changing the actual verification command declaratively in\n`buildchain.toml`:\n\n```toml\n[lifecycle.install]\ncommand = \"cargo fetch --locked\"\n\n[lifecycle.verify]\ncommand = \"cargo test --workspace --locked\"\n```\n\nConsumers that want Buildchain to own the check wrapper can call\n`.github/workflows/check.yml@v2`. The wrapper runs the declared\n`lifecycle.install` and `lifecycle.verify` stages and fails the `check` job when\neither declaration is missing or the command exits non-zero.\n\nTypical consumer wrapper:\n\n```yaml\nname: Merge Ready Dev PRs\n\non:\n schedule:\n - cron: \"17 * * * *\"\n workflow_dispatch:\n inputs:\n dry-run:\n type: boolean\n default: true\n\njobs:\n merge-dev:\n uses: kungfu-systems/buildchain/.github/workflows/dev-pr-auto-merge.yml@v2\n permissions:\n contents: write\n pull-requests: write\n checks: read\n statuses: read\n with:\n target-branch: dev/v2/v2.6\n required-status-checks: check\n ready-label: ready\n block-labels: blocked,do-not-merge\n max-merges: 1\n dry-run: ${{ inputs.dry-run || false }}\n```\n\n## Buildchain Patrol\n\n`dev-pr-auto-merge.yml` remains the focused merge primitive. For repositories\nthat want a stable day-to-day operations contract, Buildchain also exposes a\npatrol workflow family:\n\n| Workflow | Intended cadence | Default intent |\n| --- | --- | --- |\n| `.github/workflows/patrol-daily.yml` | daily | lightweight inspection plus ready dev PR maintenance |\n| `.github/workflows/patrol-weekly.yml` | weekly | release-state, passport, gate, and stale-state health checks as they are added |\n| `.github/workflows/patrol-monthly.yml` | monthly | governance, permission, branch-protection, and workflow drift checks as they are added |\n\nThe cadence names describe patrol intensity, not release cadence:\n\n- daily patrol can run every day without implying a daily release;\n- weekly patrol is for medium-cost maintenance and audit checks;\n- monthly patrol is for structural drift checks that should not block ordinary\n development velocity.\n\nConsumers should schedule thin callers and keep their YAML declarative. For\nexample:\n\n```yaml\nname: Buildchain Daily Patrol\n\non:\n schedule:\n - cron: \"17 2 * * *\"\n workflow_dispatch:\n\njobs:\n patrol:\n uses: kungfu-systems/buildchain/.github/workflows/patrol-daily.yml@v2\n with:\n dry-run: false\n max-actions: 1\n```\n\nWeekly and monthly callers use the matching wrapper:\n\n```yaml\njobs:\n patrol:\n uses: kungfu-systems/buildchain/.github/workflows/patrol-weekly.yml@v2\n with:\n dry-run: true\n```\n\nAll three wrappers default to the `v2` floating Buildchain runtime. When\n`target-branch` is omitted, the caller's current/default branch selects the\nactive semver dev line, so consumers do not pin patrol to a stale minor branch.\nThe separate workflow names keep consumer schedules readable and stable while\nBuildchain adds new checks behind the cadence wrappers.\n\n## Package-Manager Adapters\n\nOld ABV assumed JavaScript repositories with root version state and often\nLerna. Buildchain keeps the version-state contract but does not assume every\nrepository is yarn/Lerna.\n\nThe promotion action discovers and updates:\n\n- root `package.json`;\n- `lerna.json`;\n- package manifests from `package.json` workspaces;\n- package manifests from `lerna.json` packages;\n- package manifests from `pnpm-workspace.yaml`.\n\nIt then runs the repository's detected package manager semantics where needed:\n\n- pnpm repositories use pnpm-oriented workspace discovery;\n- npm repositories use npm/package-lock semantics where present;\n- yarn repositories use yarn-style metadata where present.\n\nFor Buildchain itself, version state is required. For a consumer repository that\nhas no package manifest, the same action can degrade to ref-only behavior only\nwhen that is explicitly allowed by the caller.\n\n## Lifecycle Configuration\n\n`buildchain.toml` is the v2 user configuration format. It lets a repository\ndeclare version-state files and lifecycle commands without pretending every\nproject is a Node workspace. Supported version files include JSON, TOML, and\nregex-based files such as `CMakeLists.txt` or `conanfile.py`.\n\nThe promotion action currently consumes `version.files` and `lifecycle.verify`.\nThe verify stage runs after generated version-state changes are applied locally\nand before any release refs move. If `verification-command` is passed directly\nto the action, that explicit command overrides `lifecycle.verify`.\n\nProtected release-line branches keep their normal human review gate. Managed\n`dev/vN/vN.M`, `alpha/vN/vN.M`, and `release/vN/vN.M` branches are configured\nwith one required approving review, strict GitHub Actions checks, administrator\nenforcement, conversation resolution, no force pushes, and no deletions. The\nreusable `release-candidate-promote.yml` wrapper defaults\n`branch-protection-bypass-apps` to `github-actions`, which lets the workflow's\nautomation identity apply generated version-state or post-publish channel\nbookkeeping after the reviewed channel PR has merged. Direct\n`promote-buildchain-ref` callers must opt into the same controlled bypass with\n`branch-protection-bypass-apps`, `branch-protection-bypass-users`, or\n`branch-protection-bypass-teams`; the action also adds the current promotion\ntoken's authenticated user or app to the managed bypass allowlist. Before\npatching a protected generated bookkeeping ref, the action creates the\nconfigured required check on the exact generated version-state commit, so strict\nstatus checks are satisfied by machine-verifiable Buildchain evidence rather\nthan a human PR. The protected ref PATCH itself uses the generated ref update\ntoken; the reusable wrapper defaults it to\n`secrets.BUILDCHAIN_PROMOTION_TOKEN || github.token`. If direct generated\nrelease finalization bookkeeping is still rejected, Buildchain creates or\nreuses a same-repository `buildchain/version-state/*` PR based on the current\ntarget channel head and records `finalization-needed=true` in the durable\ntransaction output. Strict alpha bookkeeping still fails with a\ntoken/protection diagnostic instead of creating a post-publish PR.\nBuildchain's own promotion workflow reads `BUILDCHAIN_PROMOTION_BYPASS_APPS`,\n`BUILDCHAIN_PROMOTION_BYPASS_USERS`, and\n`BUILDCHAIN_PROMOTION_BYPASS_TEAMS` repository variables so the declared bypass\nidentity can match the actual `BUILDCHAIN_PROMOTION_TOKEN` actor, but consumers\ndo not need to duplicate that actor manually when the token identity is\ndiscoverable.\n\n## What This Guarantees\n\nWhen the loop succeeds, maintainers and consumers can rely on these facts:\n\n- every production release has an exact tag such as `v2.0.2`;\n- every production minor line has a floating tag such as `v2.0`;\n- every selected stable major has a floating tag such as `v2`;\n- every next-major release is driven by a reviewed `release -> publish-gate/major` PR,\n not a hidden manual button;\n- every test channel has an exact alpha tag such as `v2.0.3-alpha.0`;\n- every alpha minor line has a floating tag such as `v2.0-alpha`;\n- version manifests match the tag visible from the same commit;\n- production releases are derived from the alpha tree that was tested;\n- manual non-dry-run promotion cannot bypass PR review and verification;\n- flow-internal automation bypasses apply only to declared GitHub Apps, users,\n or teams on Buildchain-managed channel branch protection, while one-review\n protection remains enforced for humans;\n- admin users cannot make a channel promotion valid by temporarily bypassing\n branch protection.\n\nThis is the practical meaning of \"governance closed loop\" in Buildchain: the\ndecision, code, version state, and Git refs close over the same evidence chain.\n\n## What This Does Not Do\n\nBuildchain release promotion does not embed registry clients or product-specific\npublish logic. When publish transactions are enabled, `promote-buildchain-ref`\ncan run the consumer's `lifecycle.publish` command and own the transaction,\nevidence validation, durable recovery state, and ref finalization order. The\nconsumer repository still owns registry truth: npm, PyPI, OCI, S3, Conan, CMake\npackaging, download pages, dist-tags, and similar side effects must be\nimplemented by project lifecycle commands that emit Buildchain publish evidence.\n\nEvery Buildchain publish model that can run registry side effects must bind the\npublish entrypoint to an immutable `publish-gate/*` source lock. The reusable\n`release-candidate-promote.yml@v2` wrapper creates or updates that gate ref and\npasses `require-publish-source-lock`, `publish-source-ref`,\n`publish-source-sha`, and `publish-source-locked` to\n`promote-buildchain-ref`. Direct action callers must pass the same four inputs\nfrom the reusable build outputs. Workflows that only collect passports or run\ndry-run package checks do not move publish refs and are not publish-gate\npublication models.\n\nSemver GitHub Release publication is owned by `promote-buildchain-ref`, not by\nconsumer shell glue. Consumers normally use the `release-candidate-promote.yml`\nwrapper, where GitHub Release publication is enabled by default and can be\ndisabled with `github-release: false`; the wrapper passes that declaration to\nthe action. After the publish transaction reaches `complete`, Buildchain creates\nor updates the public GitHub Release and uploads the generated\n`buildchain.release.json`, release-passport assets, and publish evidence. Semver\nprerelease tags are marked `prerelease=true` and `make_latest=false`; stable\nsemver tags are marked latest. For anchored/manual package releases, the public\nrelease tag defaults to `v<publishedVersion>` while the internal exact\ntransaction tag remains in the release passport and release-state ref. This is\nthe supported path for downstream\n`release.published` propagation across semver, major, and promote-only release\ncandidate publication models.\n\nBuildchain also does not maintain bare exact tags such as `1.0.0`. The supported\nexact release and alpha refs are v-prefixed:\n\n```text\nv2.0.0\nv2.0.1-alpha.0\n```\n\n## Operational Reading Order\n\nWhen debugging or extending release behavior, read in this order:\n\n1. `docs/release-flow.md`\n2. `.github/workflows/release-verify.yml`\n3. `.github/workflows/buildchain-ref-promotion.yml`\n4. `.github/workflows/release-candidate-promote.yml`\n5. `actions/promote-buildchain-ref/README.md`\n6. `actions/promote-buildchain-ref/src/`\n7. `docs/migration-inventory.md`\n\nThat path gives the policy first, the workflow trigger second, and the action\nimplementation last."
1243
1243
  },
1244
1244
  {
1245
1245
  "id": "manual:release-passport",
@@ -2504,7 +2504,7 @@
2504
2504
  "pageRegistryPath": "dist/site/page-registry.json",
2505
2505
  "cliRegistryDigest": "fb33fe38423f56ebf95919e2b58e13dc2f544aee10169bc87d7afe980bc1b142",
2506
2506
  "workflowRegistryDigest": "4041321df08640a802a87ff0fbe8584d95dc416945b43778727adb820cab9097",
2507
- "pageRegistryDigest": "02dec6f220bb6649ca38c5691c99b4d3037a2f5ae7cea4937f72a266cd3bf38e"
2507
+ "pageRegistryDigest": "303b9f332b3849ebfeae626d09a1238c5431e438df17b8eb1ff4aa7e686dbf20"
2508
2508
  },
2509
2509
  "comparison": {
2510
2510
  "missingCliRegistry": [],
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
3
  "contract": "kungfu-buildchain-publication-release-registry",
4
- "generatedAt": "2026-07-10T04:40:14.828Z",
5
- "publishedAt": "2026-07-10T04:40:14.828Z",
4
+ "generatedAt": "2026-07-10T05:53:36.658Z",
5
+ "publishedAt": "2026-07-10T05:53:36.658Z",
6
6
  "reproducible": true,
7
7
  "timestampPolicy": "ci-injected",
8
8
  "deterministicInputs": [
@@ -19,7 +19,7 @@
19
19
  "declared Buildchain surface manifest contract"
20
20
  ],
21
21
  "sourceDateEpoch": "0",
22
- "sourceRevision": "dd0ccdcbfa432e8856ba01735c25b6427a1ff1c0",
22
+ "sourceRevision": "6bd30d696e19cf2b391b190c734e55886daa6ee3",
23
23
  "timestampPolicyDetails": {
24
24
  "contract": "kungfu-buildchain-surface-timestamp-policy",
25
25
  "timestampFields": [
@@ -32,7 +32,7 @@
32
32
  },
33
33
  "package": {
34
34
  "name": "@kungfu-tech/buildchain",
35
- "version": "2.11.12",
35
+ "version": "2.11.13-alpha.1",
36
36
  "versionSource": "package.json#version"
37
37
  },
38
38
  "sourceKind": "package-site-bundle",
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
3
  "contract": "kungfu-buildchain-site-manifest",
4
- "generatedAt": "2026-07-10T04:40:14.828Z",
5
- "publishedAt": "2026-07-10T04:40:14.828Z",
4
+ "generatedAt": "2026-07-10T05:53:36.658Z",
5
+ "publishedAt": "2026-07-10T05:53:36.658Z",
6
6
  "reproducible": true,
7
7
  "timestampPolicy": "ci-injected",
8
8
  "deterministicInputs": [
@@ -19,7 +19,7 @@
19
19
  "declared Buildchain surface manifest contract"
20
20
  ],
21
21
  "sourceDateEpoch": "0",
22
- "sourceRevision": "dd0ccdcbfa432e8856ba01735c25b6427a1ff1c0",
22
+ "sourceRevision": "6bd30d696e19cf2b391b190c734e55886daa6ee3",
23
23
  "timestampPolicyDetails": {
24
24
  "contract": "kungfu-buildchain-surface-timestamp-policy",
25
25
  "timestampFields": [
@@ -37,7 +37,7 @@
37
37
  },
38
38
  "package": {
39
39
  "name": "@kungfu-tech/buildchain",
40
- "version": "2.11.12",
40
+ "version": "2.11.13-alpha.1",
41
41
  "versionSource": "package.json#version"
42
42
  },
43
43
  "entrypoint": "buildchain-site.json",
@@ -221,7 +221,7 @@
221
221
  "path": "docs/release-governance.md",
222
222
  "plane": "why",
223
223
  "exists": true,
224
- "digest": "sha256:69218a4749170e1f84b82f211d57187a7ff33f1a510aced587e240d1d901b9e7"
224
+ "digest": "sha256:9c8e3f096d314b2d0ea9a6badfdf263006e190aaa6e861489bdd05c93d3eaf04"
225
225
  },
226
226
  {
227
227
  "id": "release-flow",
@@ -94,6 +94,19 @@ The implementation is intentionally stricter than a local release script:
94
94
  release source tree against that tested alpha tree;
95
95
  - generated version-state commits are verified before refs move.
96
96
 
97
+ Promotion intents are serialized globally per caller repository with
98
+ `cancel-in-progress: false`. A queued intent re-reads its protected target ref
99
+ before checkout, dependency installation, release-candidate resolution, or any
100
+ publish-gate/ref mutation. If the ref already points at a newer SHA, that older
101
+ intent is no longer release authority: the workflow records the requested and
102
+ current SHAs, proves that the current target is ahead of the requested commit,
103
+ and completes as a `target-ref-advanced` superseded no-op. Diverged or behind
104
+ comparisons are not superseded transactions and still fail closed.
105
+ Missing refs, unreadable repository state, invalid channels, governance
106
+ failures, and artifact mismatches still fail closed. The promote action repeats
107
+ the target check at the mutation boundary, so a ref that advances after the
108
+ workflow preflight cannot receive a second set of publication side effects.
109
+
97
110
  ## Version Lines
98
111
 
99
112
  Kungfu uses Python-like version lines where a minor line can represent a
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kungfu-tech/buildchain",
3
- "version": "2.11.12",
3
+ "version": "2.11.13-alpha.1",
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",