@kungfu-tech/buildchain 2.12.0 → 2.12.1-alpha.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/buildchain.mjs +18 -0
- package/dist/site/buildchain-contract.json +8 -8
- package/dist/site/buildchain-site.json +92 -26
- package/dist/site/capability-registry.json +5 -5
- package/dist/site/cli-registry.json +12 -0
- package/dist/site/kfd-claims.json +182 -14
- package/dist/site/kfd-upstream-aggregate.json +1 -1
- package/dist/site/manual-registry.json +8 -7
- package/dist/site/node-api-registry.json +20 -7
- package/dist/site/page-registry.json +81 -15
- package/dist/site/public-surface-audit.json +95 -10
- package/dist/site/publication-registry.json +4 -4
- package/dist/site/release-provenance.json +1 -0
- package/dist/site/site-manifest.json +11 -11
- package/dist/site/workflow-registry.json +68 -3
- package/docs/MAP.md +3 -0
- package/docs/binary-distribution.md +20 -1
- package/docs/cli.md +17 -0
- package/docs/kfd-support.md +44 -1
- package/docs/lifecycle-protocol.md +12 -0
- package/docs/release-governance.md +23 -0
- package/docs/reusable-build-surface.md +69 -0
- package/docs/stable-candidate-patrol.md +188 -0
- package/package.json +3 -1
- package/packages/core/buildchain-config.js +58 -0
- package/packages/core/buildchain-kfd-claims.js +51 -2
- package/packages/core/buildchain-layout.js +46 -0
- package/packages/core/index.js +19 -0
- package/packages/core/kfd3-surface-register.js +59 -2
- package/packages/core/stable-candidate-ledger.js +276 -0
- package/scripts/build-standalone-binary.mjs +2 -1
- package/scripts/check-inventory.mjs +4 -1
- package/scripts/generate-site-bundle.mjs +9 -1
- package/scripts/init-repo.mjs +1 -1
- package/scripts/locked-source-checkout.mjs +52 -12
- package/scripts/npm-publish-dry-run.mjs +1 -1
- package/scripts/publication-artifact.mjs +1 -1
- package/scripts/publication-package.mjs +1 -1
- package/scripts/release-propagation.mjs +1 -1
- package/scripts/stable-candidate-patrol.mjs +448 -0
- package/scripts/stable-candidate-policy.mjs +25 -0
- package/scripts/stable-candidate-qualification.mjs +239 -0
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"contract": "kungfu-buildchain-site-bundle",
|
|
4
|
-
"generatedAt": "2026-07-
|
|
5
|
-
"publishedAt": "2026-07-
|
|
4
|
+
"generatedAt": "2026-07-13T04:23:40.596Z",
|
|
5
|
+
"publishedAt": "2026-07-13T04:23:40.596Z",
|
|
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": "
|
|
22
|
+
"sourceRevision": "6a389143f2635c16f68971b214f70ed1b600a329",
|
|
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.12.
|
|
40
|
+
"version": "2.12.1-alpha.10",
|
|
41
41
|
"versionSource": "package.json#version"
|
|
42
42
|
},
|
|
43
43
|
"source": {
|
|
@@ -308,7 +308,7 @@
|
|
|
308
308
|
],
|
|
309
309
|
"maturity": "stable",
|
|
310
310
|
"sourcePath": "docs/binary-distribution.md",
|
|
311
|
-
"digest": "sha256:
|
|
311
|
+
"digest": "sha256:08be4e97e1940a45a2c0aa2506012255888c23c1cbf8f5362b27c2b21089eb58",
|
|
312
312
|
"headings": [
|
|
313
313
|
{
|
|
314
314
|
"level": 1,
|
|
@@ -320,6 +320,11 @@
|
|
|
320
320
|
"title": "Asset Rules",
|
|
321
321
|
"anchor": "asset-rules"
|
|
322
322
|
},
|
|
323
|
+
{
|
|
324
|
+
"level": 2,
|
|
325
|
+
"title": "KFD-3 Distribution Declaration",
|
|
326
|
+
"anchor": "kfd-3-distribution-declaration"
|
|
327
|
+
},
|
|
323
328
|
{
|
|
324
329
|
"level": 2,
|
|
325
330
|
"title": "Runner Policy",
|
|
@@ -336,7 +341,7 @@
|
|
|
336
341
|
"anchor": "local-smoke"
|
|
337
342
|
}
|
|
338
343
|
],
|
|
339
|
-
"markdown": "# Binary Distribution\n\nBuildchain's binary distribution is the first high-pressure proof case for the\nRelease Passport protocol. It is not the boundary of the product.\n\n## Asset Rules\n\nGitHub Release assets use platform-specific archives:\n\n- `buildchain-x86_64-unknown-linux-gnu.tar.gz`\n- `buildchain-aarch64-apple-darwin.tar.gz`\n- `buildchain-x86_64-pc-windows-msvc.zip`\n\nThe release lane does not upload loose top-level `buildchain` or\n`buildchain.exe` assets. Linux and macOS both name the executable `buildchain`\ninside their archives, so top-level loose assets would collide when matrix\nartifacts are merged.\n\nRelease asset upload is gated before the matrix starts. Manual\n`workflow_dispatch` runs are binary dry-runs only and must keep\n`upload-release=false`; real GitHub Release uploads must come from a true\n`v*` tag-triggered run so an invalid manual upload request cannot spend the\nthree-platform build matrix and then fail at `gh release upload`.\n\nGitHub Release metadata is deterministic and tag-derived. Exact alpha tags such\nas `v2.6.2-alpha.0` are created or updated with `prerelease=true` and\n`make_latest=false`; exact stable tags such as `v2.6.1` are created or updated\nwith `prerelease=false` and `make_latest=true`. The workflow uses\n`scripts/ensure-github-release.mjs` before asset upload instead of relying on\nGitHub's default latest-release heuristic.\n\nEach archive is accompanied by:\n\n- a platform manifest from the standalone binary builder;\n- platform observability event logs and summaries;\n- `checksums.txt`;\n- Release Passport evidence files;\n- `buildchain-release-bundle.tar.gz`;\n- `buildchain-release-bundle.json`.\n\n## Runner Policy\n\nProduction binary builds use GitHub-hosted runners:\n\n- `ubuntu-24.04`\n- `macos-latest`\n- `windows-2022`\n\nSelf-hosted runners are compatibility fixtures. They can prove that consumers\nwith private runner fleets can still use the protocol, but Buildchain's public\nbinary distribution should stay reproducible on GitHub-hosted runners.\n\n## Evidence Bundle\n\n`buildchain-release-bundle.tar.gz` groups release assets and passport evidence\nunder one archive:\n\n```text\nbuildchain-release-bundle/\n release-assets/\n release-passport/\n buildchain-release-bundle.index.json\n```\n\n`buildchain-release-bundle.json` records the bundle digest and every included\nfile digest. Consumers can download the bundle when they want one artifact for\noffline review, mirroring, or site ingestion.\n\n## Local Smoke\n\n```bash\
|
|
344
|
+
"markdown": "# Binary Distribution\n\nBuildchain's binary distribution is the first high-pressure proof case for the\nRelease Passport protocol. It is not the boundary of the product.\n\n## Asset Rules\n\nGitHub Release assets use platform-specific archives:\n\n- `buildchain-x86_64-unknown-linux-gnu.tar.gz`\n- `buildchain-aarch64-apple-darwin.tar.gz`\n- `buildchain-x86_64-pc-windows-msvc.zip`\n\nThe release lane does not upload loose top-level `buildchain` or\n`buildchain.exe` assets. Linux and macOS both name the executable `buildchain`\ninside their archives, so top-level loose assets would collide when matrix\nartifacts are merged.\n\nRelease asset upload is gated before the matrix starts. Manual\n`workflow_dispatch` runs are binary dry-runs only and must keep\n`upload-release=false`; real GitHub Release uploads must come from a true\n`v*` tag-triggered run so an invalid manual upload request cannot spend the\nthree-platform build matrix and then fail at `gh release upload`.\n\nGitHub Release metadata is deterministic and tag-derived. Exact alpha tags such\nas `v2.6.2-alpha.0` are created or updated with `prerelease=true` and\n`make_latest=false`; exact stable tags such as `v2.6.1` are created or updated\nwith `prerelease=false` and `make_latest=true`. The workflow uses\n`scripts/ensure-github-release.mjs` before asset upload instead of relying on\nGitHub's default latest-release heuristic.\n\nEach archive is accompanied by:\n\n- a platform manifest from the standalone binary builder;\n- platform observability event logs and summaries;\n- `checksums.txt`;\n- Release Passport evidence files;\n- `buildchain-release-bundle.tar.gz`;\n- `buildchain-release-bundle.json`.\n\n## KFD-3 Distribution Declaration\n\nBuildchain self-describes this release lane in `dist/site/kfd-claims.json` as\nthe KFD-3 surface `distribution:buildchain-standalone`. Its declaration assigns\nregistration to Shifu, names `binary:build` as the reproducible task, and lists\nthe artifact kind, platform, and path glob for all three archives. Shifu should\ndiscover the registry through `buildchain layout --json`, not by copying the\nregistry path.\n\nThe repository-owned task is:\n\n```bash\npnpm binary:build\n```\n\nThe release workflow still builds each target on its declared runner. The local\ntask is the stable task identity used by the KFD declaration and local smoke\nchecks; it does not replace the three-platform release matrix.\n\n## Runner Policy\n\nProduction binary builds use GitHub-hosted runners:\n\n- `ubuntu-24.04`\n- `macos-latest`\n- `windows-2022`\n\nSelf-hosted runners are compatibility fixtures. They can prove that consumers\nwith private runner fleets can still use the protocol, but Buildchain's public\nbinary distribution should stay reproducible on GitHub-hosted runners.\n\n## Evidence Bundle\n\n`buildchain-release-bundle.tar.gz` groups release assets and passport evidence\nunder one archive:\n\n```text\nbuildchain-release-bundle/\n release-assets/\n release-passport/\n buildchain-release-bundle.index.json\n```\n\n`buildchain-release-bundle.json` records the bundle digest and every included\nfile digest. Consumers can download the bundle when they want one artifact for\noffline review, mirroring, or site ingestion.\n\n## Local Smoke\n\n```bash\npnpm binary:build -- --version v0.0.0-local\nnode bin/buildchain.mjs collect github-release \\\n --tag v0.0.0-local \\\n --assets-dir dist/binary \\\n --output-dir .buildchain/release-passport\nnode scripts/create-release-bundle.mjs \\\n --assets-dir dist/binary \\\n --passport-dir .buildchain/release-passport \\\n --output-dir .buildchain/release-passport \\\n --tag v0.0.0-local\n```"
|
|
340
345
|
},
|
|
341
346
|
{
|
|
342
347
|
"id": "manual:build-facts",
|
|
@@ -397,7 +402,7 @@
|
|
|
397
402
|
],
|
|
398
403
|
"maturity": "stable",
|
|
399
404
|
"sourcePath": "docs/cli.md",
|
|
400
|
-
"digest": "sha256:
|
|
405
|
+
"digest": "sha256:3b3ac97c353f7549229f1102cca38236e734ec8d08c219d4a6e5ef2a48fc0e16",
|
|
401
406
|
"headings": [
|
|
402
407
|
{
|
|
403
408
|
"level": 1,
|
|
@@ -425,7 +430,7 @@
|
|
|
425
430
|
"anchor": "npm-publish-gate"
|
|
426
431
|
}
|
|
427
432
|
],
|
|
428
|
-
"markdown": "# Buildchain CLI, npm Package, and Toolkit API\n\nBuildchain is published as the public npm package\n`@kungfu-tech/buildchain`. The package contains the `buildchain` command,\nthe importable ESM toolkit APIs, and the local scripts needed to initialize and\nvalidate repositories before they use the reusable GitHub workflow surface.\n\nThe npm package is not the release authority. Release authority still comes\nfrom the protected Buildchain branch and tag state machine. npm publishing is a\nside effect of an exact release tag that has already been produced by that\nstate machine.\n\n## Install and Run\n\nUse the published package directly:\n\n```bash\nnpx @kungfu-tech/buildchain --help\nnpx @kungfu-tech/buildchain init --type package\nnpx @kungfu-tech/buildchain validate --require-version-state\n```\n\nOr install it in a repository:\n\n```bash\npnpm add -D @kungfu-tech/buildchain\npnpm exec buildchain validate\n```\n\nConsumers should pin the exact Buildchain version that was validated in their\nrepository. When dogfooding a fresh Buildchain release immediately after it is\npublished, pnpm may block the install through a minimum release-age policy. In\nthat case, add a temporary package/version-specific `minimumReleaseAgeExclude`\nentry, such as `@kungfu-tech/buildchain@2.2.5`, and remove it once the package\nhas aged past the normal policy window. Do not replace that with a broad\nregistry or scope-wide exclude.\n\nUse the package API directly inside JavaScript build scripts:\n\n```js\nimport { createBuildchainLogger } from \"@kungfu-tech/buildchain/logging\";\n\nconst logger = createBuildchainLogger({ source: \"user\", component: \"build\" });\nawait logger.span(\"build.native\", { phase: \"build\" }, async () => {\n await buildNativeArtifacts();\n});\n```\n\nThe standalone binary and CLI are for workflow steps, shell scripts, and\nnon-JavaScript environments. JavaScript code that already depends on\n`@kungfu-tech/buildchain` should import the toolkit API instead of spawning\n`npx buildchain` or a downloaded binary.\n\n## Node API and Package Exports\n\nBuildchain's public Node API is the package `exports` surface, not arbitrary\ninternal file paths. The npm package also ships\n`dist/site/node-api-registry.json` and exports it as\n`@kungfu-tech/buildchain/site/node-api-registry.json` so agents can enumerate\nthe supported imports from the installed package.\nFor navigation, start with `dist/site/capability-registry.json`: it groups\nmanuals, CLI commands, workflow/action inputs, Node exports, site pages, and KFD\nclaim facts by product capability before an agent chooses a concrete command or\nmanual.\n\nCurrent public import families include:\n\n```js\nimport * as buildchain from \"@kungfu-tech/buildchain\";\nimport { createBuildchainLogger } from \"@kungfu-tech/buildchain/logging\";\nimport { collectModuleBuildFacts } from \"@kungfu-tech/buildchain/build-facts\";\nimport { checkHomebrewTap } from \"@kungfu-tech/buildchain/homebrew\";\nimport { verifyKfd1ReleaseGate } from \"@kungfu-tech/buildchain/kfd-gate\";\nimport { collectBadgeBundleFacts } from \"@kungfu-tech/buildchain/badges\";\nimport { collectReadmeBadgeFacts } from \"@kungfu-tech/buildchain/readme-badges\";\nimport { verifyReleasePassport } from \"@kungfu-tech/buildchain/release-passport\";\nimport { createReleasePropagationPlan } from \"@kungfu-tech/buildchain/release-propagation\";\nimport { planReleaseLineBootstrap } from \"@kungfu-tech/buildchain/release-line-bootstrap\";\nimport { collectPublicSurfaceReverseAudit } from \"@kungfu-tech/buildchain/public-surface-audit\";\nimport contractWorld from \"@kungfu-tech/buildchain/site/buildchain-contract.json\" with { type: \"json\" };\nimport capabilityRegistry from \"@kungfu-tech/buildchain/site/capability-registry.json\" with { type: \"json\" };\nimport manualRegistry from \"@kungfu-tech/buildchain/site/manual-registry.json\" with { type: \"json\" };\nimport nodeApiRegistry from \"@kungfu-tech/buildchain/site/node-api-registry.json\" with { type: \"json\" };\nimport publicSurfaceAudit from \"@kungfu-tech/buildchain/site/public-surface-audit.json\" with { type: \"json\" };\n```\n\nUse `dist/site/manual-registry.json` to find the packaged operating manuals and\ntheir SHA-256 digests. Use `dist/site/buildchain-contract.json` to verify the\nfloating-ref contract world for a runtime such as `@v2`.\n\n## Commands\n\n`buildchain init` writes a starter `.buildchain/buildchain.toml` and a reusable workflow\ncaller at `.github/workflows/build.yml`.\n\nSupported presets:\n\n- `--type package` for Node package repositories with pnpm, npm, or yarn.\n- `--type native` for CMake-style native projects.\n- `--type web-surface` for preview/staging/production site or app deployments.\n- `--type infra-contract` for provider-agnostic infrastructure contract\n validation, observation, contract publication, and downstream propagation\n planning without default mutation. Provider adapters expose built-in command\n plans by default, and only configured `[infra.commands]` hooks can execute.\n- `--type publication-artifact` for papers, reports, specifications, and other\n publication repositories that produce PDFs, metadata, source bundles, and\n site-consumable manifests without becoming web-surface repositories. The\n scaffold uses Buildchain's pinned\n `ghcr.io/kungfu-systems/build-images/latex-pdf-builder:v1.2.0` toolchain for\n LaTeX PDF builds.\n- `--type distribution-index` for Homebrew taps and other index repositories\n whose files are projections of upstream release passport evidence.\n- `--type anchored-package` for packages whose version is anchored to an\n explicit upstream release manifest.\n\nThe native preset includes an opt-in `[diagnostics.native]` profile with common\ntool/cache/artifact probes. Consumers can keep it enabled, adjust the tool and\ndirectory lists, or disable it if a repository does not need native diagnostics.\n\n`buildchain validate` parses `.buildchain/buildchain.toml`, checks configured version-state\nfiles, and can require named lifecycle stages:\n\n```bash\nbuildchain validate \\\n --require-version-state \\\n --require-lifecycle-stages install,build,verify\n```\n\n`buildchain lifecycle run <stage>` executes a lifecycle stage and writes the\nsame deterministic artifact manifest contract used by the reusable workflow:\n\n```bash\nbuildchain lifecycle run build \\\n --artifact-path dist \\\n --artifact-name \"{repo}-{version}-{platform}\"\n```\n\n`buildchain release line open` plans or writes the first version-state commit\nfor a new semver minor line. It does not publish anything. The dry-run mode is\nthe default and returns the dev/alpha/release refs, protection contract, default\nbranch action, and initial version before any GitHub mutation happens:\n\n```bash\nbuildchain release line open \\\n --major 2 \\\n --minor 10 \\\n --source-ref release/v2/v2.9 \\\n --json\n```\n\nThe write mode only updates local version-state files. The repository workflow\n`Release Line Bootstrap` wraps this command and, when `apply=true`, commits the\ninitial version state, creates `dev/vX/vX.Y`, `alpha/vX/vX.Y`, and\n`release/vX/vX.Y`, applies one-review branch protection, switches the default\nbranch, and opens the first dev-to-alpha channel PR:\n\n```bash\nbuildchain release line open \\\n --major 2 \\\n --minor 10 \\\n --source-ref release/v2/v2.9 \\\n --write \\\n --json\n```\n\n`buildchain` also publishes a public surface reverse audit as\n`dist/site/public-surface-audit.json`. The audit enumerates CLI commands from\n`bin/buildchain.mjs`, workflow inputs, action inputs, site pages, and docs\ncommand references, then compares them with the generated registries. Buildchain\nself-checks fail closed when an enumerable public surface is missing from the\nregistry:\n\n```js\nimport {\n collectPublicSurfaceReverseAudit,\n assertPublicSurfaceReverseAudit,\n} from \"@kungfu-tech/buildchain/public-surface-audit\";\n\nassertPublicSurfaceReverseAudit(collectPublicSurfaceReverseAudit({ root: process.cwd() }));\n```\n\n`buildchain kfd` is the product-facing KFD namespace. Schema commands expose the\nmachine-readable KFD standards shipped by `@kungfu-tech/kfd`, while versioned\nsubcommands host concrete product workflows. KFD-1, KFD-2, and KFD-3 are\nfirst-class Buildchain surfaces. KFD-4 is schema-only until Buildchain has a\nreal verification protocol for it.\n\n`status` reports implemented support and the active repo-owned file layout.\n`migrate-layout` moves legacy root files into `.buildchain/`:\n\n```bash\nbuildchain kfd status --json\nbuildchain kfd migrate-layout --write\n```\n\nKFD-1 commands generate and validate contract-world release evidence:\n\n```bash\nbuildchain kfd 1 schema --json\nbuildchain kfd 1 witness --json\nbuildchain kfd 1 gate --witness-json kfd-1-witness.json --json\nbuildchain kfd 1 verify --gate-json kfd-1-gate.json --json\n```\n\nKFD-2 commands validate trust taxonomy entries and generate Buildchain's public\nclaim evidence. Product repositories use the `product-claims` subcommand to\nvalidate and render their own declared KFD-2 release claims under the canonical\nBuildchain KFD layout:\n\n```bash\nbuildchain kfd 2 schema --json\nbuildchain kfd 2 taxonomy --entry-json residual-risk.json --kind residualRisk --json\nbuildchain kfd 2 claims --json\nbuildchain kfd 2 product-claims check --json\nbuildchain kfd 2 product-claims write --json\nbuildchain kfd 2 product-claims render --json\n```\n\nThe default source is `.buildchain/kfd/kfd-2/registry.json`; outputs are\n`.buildchain/kfd/kfd-2/release-claims.json`, per-claim release-passport inputs\nunder `claims/`, and `buildchain-claim-args.txt`. Use `--registry` or\n`--output-dir` only for an explicit product packaging projection. `check` never\nwrites and exits non-zero when outputs drift.\n\nKFD-3 commands are separate from Buildchain's self reverse audit: products can\ndetect standard public surfaces, register the accepted boundary, audit the\ncurrent source or artifact tree, generate a release-passport-compatible witness,\nand expose a capability map for agents:\n\n```bash\nbuildchain kfd schema list --json\nbuildchain kfd schema show kfd-3 --json\nbuildchain kfd 3 detect --kind node-api --kind cli --json\nbuildchain kfd 3 register node-api --product Buildchain\nbuildchain kfd 3 audit --json\nbuildchain kfd 3 witness --kind prebuild --output .buildchain/kfd/kfd-3/collaboration-interface.prebuild.json\nbuildchain kfd 3 query buildchain --json\nbuildchain kfd 4 schema --json\n```\n\nThe public Node API is exported from `@kungfu-tech/buildchain/kfd`. See\n[`kfd-support.md`](kfd-support.md) for the detected / declared / enforced model\nand the agent query flow.\n\nLifecycle runs also write a Buildchain observability JSONL log at\n`.buildchain/logs/events.jsonl` by default. Framework events use\n`source=buildchain`; consumer lifecycle commands use `source=user`. This lets a\nmaintainer tell apart time spent inside Buildchain's artifact/manifest\nframework from time spent in the repository's own build, test, packaging, or\npublish commands. The artifact manifest and summary embed the observability\nsummary for that lifecycle run id, so uploaded artifacts preserve the timing\nfacts without mixing in older JSONL events.\n\n`buildchain log`, `buildchain mark`, and `buildchain span` expose the same event\nprotocol to repository scripts:\n\n```bash\nbuildchain mark --event configure.ready --phase configure --attribute target=release\nbuildchain span --event native.build --phase build -- cmake --build build\nbuildchain log warn --event cache.miss --component conan --attribute token=hidden\nbuildchain log summary --json\nbuildchain verify observability-log .buildchain/logs/events.jsonl --min-events 4 --require-phase build\nbuildchain diagnostics summary .buildchain/artifacts/*/diagnostics.json --json\nbuildchain sample process-tree --label native-build --interval-ms 15000 -- make -j20\n```\n\nDuring `buildchain lifecycle run`, child processes receive\n`BUILDCHAIN_LOG_PATH` and `BUILDCHAIN_LOG_RUN_ID`. A shell, Python, CMake, Conan,\nor JavaScript helper can call `buildchain mark` or `buildchain span` mid-build\nand have those events grouped into the same lifecycle summary.\n`buildchain verify observability-log` is a release gate: it fails when the log\nis missing, has too few events, contains error events, or does not include\nrequired phases, components, or event names.\n\nThe event protocol is JSONL and is also available from the SDK:\n\n```js\nimport { createBuildchainLogger } from \"@kungfu-tech/buildchain/logging\";\n\nconst logger = createBuildchainLogger({ source: \"user\", component: \"native-build\" });\nlogger.mark(\"configure.ready\", { phase: \"configure\" });\n```\n\nSecret-looking attribute keys such as `token`, `password`, `secret`,\n`authorization`, `cookie`, and `private-key` are redacted before they are written.\nFull command strings are not recorded by `span`; scripts should provide stable\nevent names and safe attributes instead.\n\n`buildchain diagnostics summary` reads one or more small diagnostics artifacts\nand emits the same cross-platform summary as the diagnostics SDK:\n\n```bash\nbuildchain diagnostics summary \\\n .buildchain/artifacts/linux-x64/diagnostics.json \\\n .buildchain/artifacts/macos-arm64/diagnostics.json \\\n --output .buildchain/artifacts/diagnostics-summary.json \\\n --json\n```\n\nThe JSON summary keeps per-platform lifecycle stage tables, adds lifecycle\ntotal durations, carries top slow spans, aggregates warning/error counts, and\nsorts the slowest platforms. Each platform row carries compact runner facts,\nchecked tool versions/missing tools, package manager/cache directory details,\ncompiler-cache availability, and a compact process sampler summary: requested\nparallelism, observed max active processes, the ratio between them, sample\ncount, process categories, and the top sampled command basenames. This lets\nmaintainers inspect matrix timing, runner, tool, cache, and concurrency context\nwithout downloading large platform binaries or process sidecars first.\nWhen a sibling `diagnostics-manifest.json` is available, the summary also records\nits file list and verifies the listed `diagnostics.json` byte count and sha256.\nMissing, unreadable, or mismatched sidecar manifests are reported through\n`diagnosticsManifestWarningCount` and the per-platform `diagnosticsManifest`\nfield without failing the timing rollup.\nThe summary also compares each `diagnostics.json` contract to\n`BUILDCHAIN_DIAGNOSTICS_CONTRACT`; mismatches are reported through\n`diagnosticsContractWarningCount` and the per-platform `diagnosticsContract`\nfield so reviewers can separate diagnostics schema drift from lifecycle\nwarnings or build failures.\n\nWithout `--json`, the command prints a compact lifecycle timing table with\ninstall/build/verify/publish, artifact scan/upload, total, warning, and error\ncolumns for each platform, plus `jobs` and `active` columns for requested and\nobserved process concurrency when sampler data is present.\n\n`buildchain facts` collects and verifies source/version/output facts for\nmodules and products:\n\n```bash\nbuildchain facts module \\\n --module native-core \\\n --output .buildchain/facts/native-core.json \\\n --legacy-kungfu-buildinfo framework/core/src/kungfu/yijinjing/kungfubuildinfo.json\n\nbuildchain facts aggregate \\\n --product kungfu \\\n --module-fact .buildchain/facts/native-core.json \\\n --artifact dist/kungfu.zip \\\n --output .buildchain/facts/kungfu.json\n\nbuildchain facts verify --fact .buildchain/facts/kungfu.json\n```\n\nThe same implementation is available from\n`@kungfu-tech/buildchain/build-facts`. Release passports can include these\nfacts with repeated `--build-facts-json` arguments to\n`buildchain collect github-release`. See\n[`build-facts.md`](build-facts.md) for the config schema and Node API.\n\n`buildchain sample process-tree` wraps a long-running command and periodically\nwrites process-tree snapshots:\n\n```bash\nbuildchain sample process-tree \\\n --label native-build \\\n --interval-ms 15000 \\\n --output .buildchain/diagnostics/process-samples.jsonl \\\n --summary-output .buildchain/diagnostics/process-summary.json \\\n -- \\\n make -j20\n```\n\nThe command returns the wrapped command's exit status. The JSONL file contains\nsmall timestamped samples; the summary JSON records requested parallelism,\nobserved concurrency, sampled CPU, command categories, and top command\nbasenames. Use it when a native build requests high parallelism but appears to\nspend long stretches in low-concurrency compile, archive, link, or cache steps.\n\n`buildchain doctor` checks repository readiness before remote side effects:\n\n```bash\nbuildchain doctor --json\n```\n\nIt validates `.buildchain/buildchain.toml`, package-manager detection, Git repository state,\nand the reusable workflow caller. For `version.strategy = \"anchored\"` with\n`version.next = \"manual\"`, it also embeds the anchored package release contract\ncheck: anchor manifest readability, configured version files, trusted\npublishing, package publish order, and required lifecycle stages. Add\n`--require-publish-source-lock` inside a publish job when the doctor report\nshould also fail unless the job is running from a resolved `publish-gate/*`\nsource lock.\n\nAnchored/manual package publish jobs can run the narrower source-lock gate\ndirectly:\n\n```bash\nbuildchain publish-source validate-anchored-release --json\n```\n\nThe command requires `BUILDCHAIN_PUBLISH_SOURCE_REF`,\n`BUILDCHAIN_PUBLISH_SOURCE_SHA`, and `BUILDCHAIN_PUBLISH_SOURCE_LOCKED` from the\nreusable build workflow outputs. It fails closed for direct `alpha/*` or\n`release/*` channel-branch publication, and checks the publish-gate consumer\nversion against configured version files and the anchor manifest. The JSON\nresult is shaped for future `buildchain.libkungfu.dev` fact ingestion.\n\n`buildchain release`, `buildchain web-surface`, `buildchain infra-contract`,\n`buildchain publication-artifact`, `buildchain publish-source`,\n`buildchain badges`, `buildchain homebrew`, and `buildchain build-contract`\nroute to the same implementation used by\nBuildchain's package APIs or GitHub Actions workflows. This keeps local\ninspection and CI behavior on the same implementation path.\n\nGenerate publication artifact metadata after building a paper or report:\n\n```bash\nbuildchain publication-artifact manifest \\\n --source-sha \"$(git rev-parse HEAD)\" \\\n --json\n```\n\nGenerate the Buildchain-owned npm paper package contents from declared\npublication facts:\n\n```bash\nbuildchain publication-artifact npm-package --json\n```\n\nThis command reads `project.type = \"publication-artifact\"`,\n`publication.version`, and `[publish] kind = \"npm-paper-package\"` plus\n`publish.package`; it writes `.buildchain/publication/npm-package` by default.\nThe `paper-release.yml@v2` reusable workflow uses the same command before\nrunning the standard npm publish transaction.\n\nThe command writes `.buildchain/publication/publication-artifact.json`,\n`.buildchain/publication/publication-artifact-passport.json`, a source bundle,\nand, when `[publication.archive]` is configured,\n`.buildchain/publication/publication-registry.json` by default. See\n[`publication-artifacts.md`](publication-artifacts.md) for the repository\ncontract, pinned LaTeX builder, and reusable workflow.\n\nGenerate, check, or update the managed README badge block:\n\n```bash\nbuildchain badges readme --json\nbuildchain badges readme --check\nbuildchain badges readme --write\nbuildchain badges bundle --json\nbuildchain badges bundle --check\nbuildchain badges bundle --write\nbuildchain badges bundle --claims kfd-1,release-passport --write\n```\n\nThe `--json` form emits the `kungfu-buildchain-readme-badge-facts` object.\n`--check` fails closed when the README marker block is missing or stale.\n`--write` inserts or replaces only the marked block. KFD passed badges come\nfrom the repository's own verified release passport; unreleased repositories\ndowngrade to explicit local declarations such as `declared`, `aligned`, or\n`planned`. `buildchain badges bundle` is the focused trust-badge entrypoint: it\nemits `kungfu-buildchain-badge-bundle-facts` and defaults to KFD-1, KFD-2,\nKFD-3, and Release Passport. See [`readme-badges.md`](readme-badges.md) for the\nmarker contract and `[badges]` / `[badges.bundle]` configuration.\n\nGenerate or check Homebrew tap projections from upstream release passports:\n\n```bash\nbuildchain homebrew update-formula \\\n --package buildchain \\\n --release-passport https://github.com/kungfu-systems/buildchain/releases/download/v2.8.15/buildchain.release.json \\\n --write\n\nbuildchain homebrew check --json\n```\n\n`update-formula` writes `Formula/buildchain.rb` and `tap-manifest.json` from\nupstream release passport evidence. `check` fails closed when the Formula,\nmanifest, artifact digests, or KFD status drift from the upstream passport. See\n[`homebrew.md`](homebrew.md) for the distribution-index project contract.\n\n`buildchain collect github-release` creates a release passport bundle from\nGitHub Release assets or a local asset directory:\n\n```bash\nbuildchain collect github-release \\\n --tag v2.2.0 \\\n --repository kungfu-systems/buildchain \\\n --assets-dir dist \\\n --output-dir .buildchain/release-passport\n```\n\nThe bundle includes `buildchain.release.json`, `artifact-evidence.json`,\n`impact.json`, `agent-index.json`, `product-mechanism.json`, `check-report.json`,\nand `llms.txt`. Production binary distribution defaults to GitHub-hosted\nrunners so other projects can reproduce the release lane; self-hosted runners\nremain compatibility fixtures and are recorded as runner facts when used.\n\nFor publish-transaction releases, pass the additional evidence inputs so\n`buildchain.release.json` becomes the unified passport instead of a binary-only\nasset summary:\n\n```bash\nbuildchain collect github-release \\\n --tag v2.3.2 \\\n --repository kungfu-systems/buildchain \\\n --assets-dir dist \\\n --publish-evidence-json .buildchain/release-evidence/v2.3.2/evidence.json \\\n --transaction-json .buildchain/release-state/v2.3.2/state.json \\\n --package-set-json package-set.json \\\n --impact-json impact.json \\\n --trusted-publishing-json trusted-publishing.json \\\n --anchor-manifest-json libnode.release.json \\\n --build-summary-json .buildchain/artifacts/build-summary.json \\\n --platform-manifest-json .buildchain/artifacts/linux-x64/manifest.json \\\n --platform-manifest-json .buildchain/artifacts/darwin-arm64/manifest.json \\\n --platform-manifest-json .buildchain/artifacts/win32-x64/manifest.json \\\n --dist-tag-evidence-json .buildchain/release-evidence/v2.3.2/dist-tag-evidence.json \\\n --kfd-1-witness-json .buildchain/kfd/kfd-1/contract-world.witness.json \\\n --kfd-2-claim-json .buildchain/kfd/kfd-2/release-claims.json \\\n --kfd-3-prebuild-witness-json .buildchain/kfd/kfd-3/collaboration-interface.prebuild.json \\\n --kfd-3-artifact-verify-cmd \"kungfu agent verify --json\" \\\n --release-extra-json '{\"channel\":\"release\",\"targetRef\":\"release/v2/v2.3\"}' \\\n --output-dir .buildchain/release-passport\n```\n\nThe generated passport records the main and platform packages, npm dist-tags,\npublished versions, release source/ref state, anchor manifest digest, registry\nartifact digests, trusted publishing evidence, and Buildchain transaction\nresult. It also records `buildSummary`, `platformArtifactManifests`, and\n`distTagPromotion` when those JSON inputs are supplied. `packageSet` keeps the\nordered package set; `publish.packages[]` is the agent-readable npm publication\nsummary for each main/platform package. For Buildchain releases, verification\nexpects the supplied package set to include the main package plus the three\nplatform packages with version, dist-tag, and digest evidence. Verification\nfails closed if supplied sections are internally incomplete or point to\nartifacts without matching evidence.\n\n`--kfd-1-witness-json` attaches a KFD-1 contract-world release gate. The witness\nis structured JSON: consumers declare the contract world, canonical JSON policy,\nartifact paths, and expected SHA-256 digests. Buildchain imports KFD-owned\nmetadata from `@kungfu-tech/kfd`, freezes the witness before build publication,\nthen verifies the resulting artifact bytes itself and writes the evidence under\nthe KFD-provided top-level key currently named `kfd-1`. Consumers should not\nduplicate this by running repository-specific scripts or invoking the Kungfu\nSDK from their release workflow.\n\nFor the KFD repository, KFD-1 witnesses may be self-hosted standard-contract\nwitnesses: docs, schemas, standards metadata, package exports, and\nsite-consumption entrypoints are checked from source hashes to packaged artifact\nhashes, and the passport records schema IDs, self-hosting boundary, result, and\nresponsibility state.\n\n`--kfd-2-claim-json` attaches explicit public release claims to the KFD-2\nrelease trust passport audit. Buildchain also derives KFD-2 claims from KFD-1\nand KFD-3 gate evidence. Public claims must 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 and emit a\nwarning.\n\n`--kfd-3-prebuild-witness-json` attaches a KFD-3 collaboration-interface\nrelease gate. The product remains the source of truth: it emits a pre-build\nwitness that contains or points to its KFD-3 collaboration interface, declared\nparticipant-facing public surfaces, and registry digest. Buildchain freezes\nthat declaration before publication. The artifact side is supplied either by\n`--kfd-3-artifact-witness-json` or by a product-owned command such as\n`--kfd-3-artifact-verify-cmd \"kungfu agent verify --json\"`. Buildchain then\nchecks closure: every declared shipped public surface must be present in the\nartifact witness, and every artifact-exposed participant-facing public surface\nmust have been declared. The generated passport writes this evidence under the\nKFD-provided top-level key currently named `kfd-3`.\n\nThis gate is useful for agent-facing products because it turns KFD-3 from prose\ninto release evidence. A package cannot claim KFD-3 collaboration-interface\nsupport merely because the docs mention it; the release passport must show the\nfrozen declaration, the artifact-side witness digest, and a passing closure\ncomparison.\nFor the KFD repository itself, the witness can declare docs, schemas, standards\nmetadata, package exports, and site-consumption contracts as grouped public\nsurfaces; the artifact witness must expose the same enumerable package/site\nsurfaces or verification fails closed.\n\n`--impact-json` supplies the surface-aware impact ledger. Production release\npassports (`release/*`) and major publish-gate passports require\n`surfaceImpacts[]`; alpha, local, and legacy passport contexts keep it\noptional. When `surfaceImpacts[]` is required or supplied, the verifier requires\neach entry to include an id, impact, and rationale, and requires\n`versionImpact.final` to match the highest declared surface impact. The\ncollector copies `versionImpact` plus `surfaceImpacts` into\n`buildchain.release.json`. This lets\n`buildchain explain release --for agent --json` state why a release is patch,\nminor, or major instead of relying on file-path memory.\n\nBuildchain dogfoods its observability toolkit in this lane. The standalone\nbuilder writes API-generated events, while the workflow uses `buildchain mark`,\n`buildchain span`, `buildchain verify observability-log`, and `buildchain log\nsummary`; the event logs and summaries are published as release passport assets.\n\nVerify and explain release passports:\n\n```bash\nbuildchain verify release-passport .buildchain/release-passport/buildchain.release.json\nbuildchain explain release --passport .buildchain/release-passport/buildchain.release.json --for agent --json\nbuildchain inspect release --passport .buildchain/release-passport/buildchain.release.json\n```\n\nThe verifier fails closed when required protocol files are absent, artifacts are\nnot covered by evidence, or digests disagree. The explanation output is shaped\nfor agents: trust, completeness, impact, recovery route, and next action.\n\nVerify a published artifact by subject:\n\n```bash\nbuildchain verify artifact ./Kungfu-2.8.0-windows-x64.exe\nbuildchain inspect artifact ./Kungfu-2.8.0-windows-x64.exe --json\nbuildchain explain artifact ./Kungfu-2.8.0-windows-x64.exe --for agent --json\nbuildchain verify artifact npm:@kungfu-tech/libnode@22.22.3-kf.3-alpha.18 \\\n --repository kungfu-systems/libnode \\\n --tag v22.22.3-kf.3-alpha.18 \\\n --json\n```\n\n`verify artifact` computes or obtains the subject digest, discovers the\ndetached release passport, verifies the passport, then requires that the\nsubject digest appears in the passport's release assets, package set, publish\nevidence, or artifact evidence. Outcomes are explicit: `pass`, `fail`, or\n`unverifiable`. A filename is only a hint; trust comes from digest equality.\nFor `npm:<name>@<version>` subjects, Buildchain resolves `dist.integrity` from\nthe npm registry before matching passport evidence. Use `--npm-registry <url>`\nto verify packages from a custom registry; otherwise Buildchain uses\n`npm_config_registry` or `https://registry.npmjs.org/`.\n\nDiscovery is fail-closed and ordered:\n\n1. `--passport <file-or-url>`.\n2. Sidecar pointer, such as `<artifact>.buildchain-passport.json`.\n3. Embedded/package pointer, such as `package.json` `buildchain.releasePassport`.\n4. Local config or org index, such as `.buildchain/artifact-passport-locators.json`.\n5. GitHub Release default discovery from `github-release:` subjects, GitHub\n Release asset URLs, or `--repository <owner/repo> --tag <tag>`.\n6. Custom `--locator-config <json-or-url>`.\n7. `unverifiable` with retry guidance.\n\nLocator files are policy, not protocol. They map subject fields such as\n`name`, `kind`, `version`, `digest`, `repository`, or `tag` to a detached\npassport location:\n\n```json\n{\n \"schemaVersion\": 1,\n \"contract\": \"kungfu-buildchain-artifact-passport-locator\",\n \"locators\": [\n {\n \"match\": {\n \"name\": \"Kungfu-2.8.0-windows-x64.exe\",\n \"digest\": \"sha256:...\"\n },\n \"passport\": \"../release-passport/buildchain.release.json\"\n }\n ]\n}\n```\n\nSupported subject shapes include local files and directories, URLs,\n`npm:<name>@<version>`, `oci:...`, `s3:...`,\n`github-release:<owner/repo>@<tag>/<asset>`, and deployment endpoints. Local\nfiles, directories, and URLs are digestable directly; remote package, OCI,\nobject storage, and deployment subjects should provide a digest or resolve to a\nlocator that records one.\n\nVerify infra-contract lifecycle evidence bundles:\n\n```bash\nbuildchain infra-contract --mode ci --source-sha \"$GITHUB_SHA\"\nbuildchain verify infra-contract-evidence-bundle .buildchain/infra-contract-evidence-bundle.json\n```\n\nThe infra-contract `ci` mode is mutation-free. It writes validate, plan,\ncontract, propagation dry-run, evidence bundle, and verification JSON artifacts\nunder `.buildchain/`, giving reusable workflows one standard responsibility\nchain instead of hand-written command sequences.\n\nThe infra-contract verifier is read-only. It recomputes the bundle hash and\nchecks that desired, plan, approval, apply, observe, contract, and propagate\nevidence remain bound to the same contract artifact. It also recomputes the\nbundle validation summary, so stale or misleading summary booleans fail closed\neven when the bundle hash has been refreshed.\n\n`buildchain release --dry-run` explains the release-line state machine before a\nmaintainer opens or merges a channel PR:\n\n```bash\nbuildchain release --dry-run --target-ref alpha/v2/v2.2\nbuildchain release --dry-run --target-ref release/v2/v2.2 --sha <verified-sha>\nbuildchain release dry-run --target-ref publish-gate/major --source-ref release/v2/v2.2\nbuildchain release explain --target-ref alpha/v2/v2.1 --json\n```\n\nThis is a Buildchain-level dry-run, not an npm dry-run. It explains the legal\nsource branch, exact release or alpha tags, floating tags, channel branches,\nversion-state files, governance checks, and publish transaction behavior that\nwould apply if the corresponding PR merge were promoted. It does not move\nbranches, move tags, edit files, publish npm packages, or run lifecycle publish\ncommands. `release explain` is the same explanation surface with a clearer name.\nPass `--json` for a machine-readable plan.\n\n`buildchain transaction inspect` is the top-level recovery inspection command\nfor the publish transaction state:\n\n```bash\nbuildchain transaction inspect --version v2.1.0-alpha.0\n```\n\nIt reads or locally initializes the durable transaction record and validates\navailable publish evidence. Remote durable refs and public Git ref finalization\nremain owned by `actions/promote-buildchain-ref`; the CLI inspection surface is\nfor preflight and recovery reasoning before a maintainer reruns or resumes a\npromotion.\n\n`buildchain npm dry-run` verifies the package shape before a release tag exists:\n\n```bash\nbuildchain npm dry-run --json\n```\n\nThe command validates `package.json`, infers the exact release tag\n`v${package.json.version}`, chooses npm dist-tag `alpha` for prereleases and\n`latest` for stable releases, runs `npm pack --dry-run --json`, and then runs\n`npm publish --dry-run --access public --tag <alpha|latest>` unless\n`--skip-npm-publish-dry-run` is passed. It never performs a real publish.\n\n## npm Publish Gate\n\nBuildchain's own npm package is published from\n`.github/workflows/buildchain-ref-promotion.yml`, inside the same publish\ntransaction that promotes release refs:\n\n- `v2.0.13-alpha.0` publishes to npm with dist-tag `alpha`.\n- `v2.0.13` publishes to npm with dist-tag `latest`.\n- moving refs such as `v2`, `v2.0`, and `v2.0-alpha` do not match the publish\n workflow and do not publish.\n\nThe promotion workflow uses npm Trusted Publishing through GitHub Actions OIDC.\nIt runs on a GitHub-hosted runner with `id-token: write`, but it does not\nmanually run the release-candidate resolver or promote action. Buildchain's own\ndogfood path calls the declarative `release-candidate-promote.yml` wrapper with\nchannel, target ref/SHA, PR-stage workflow, artifact, status-check, and passport\ninputs. The wrapper generates the version-state commit, runs\n`lifecycle.verify`, runs `lifecycle.publish`, writes Buildchain publish\nevidence, validates that evidence, and only then moves exact tags and floating\nrefs.\n\n```bash\nnode scripts/npm-publish-transaction.mjs\n```\n\nBefore the first real release, configure npm Trusted Publishing for:\n\n- package: `@kungfu-tech/buildchain`\n- repository: `kungfu-systems/buildchain`\n- workflow: `.github/workflows/buildchain-ref-promotion.yml`\n\nNo npm package is published by manual dispatch or ordinary branch builds.\nManual dispatch on `.github/workflows/npm-publish.yml` remains dry-run only, so\nmaintainers can verify package contents and npm publish shape before opening or\nmerging the release PR."
|
|
433
|
+
"markdown": "# Buildchain CLI, npm Package, and Toolkit API\n\nBuildchain is published as the public npm package\n`@kungfu-tech/buildchain`. The package contains the `buildchain` command,\nthe importable ESM toolkit APIs, and the local scripts needed to initialize and\nvalidate repositories before they use the reusable GitHub workflow surface.\n\nThe npm package is not the release authority. Release authority still comes\nfrom the protected Buildchain branch and tag state machine. npm publishing is a\nside effect of an exact release tag that has already been produced by that\nstate machine.\n\n## Install and Run\n\nUse the published package directly:\n\n```bash\nnpx @kungfu-tech/buildchain --help\nnpx @kungfu-tech/buildchain init --type package\nnpx @kungfu-tech/buildchain validate --require-version-state\n```\n\nOr install it in a repository:\n\n```bash\npnpm add -D @kungfu-tech/buildchain\npnpm exec buildchain validate\n```\n\nConsumers should pin the exact Buildchain version that was validated in their\nrepository. When dogfooding a fresh Buildchain release immediately after it is\npublished, pnpm may block the install through a minimum release-age policy. In\nthat case, add a temporary package/version-specific `minimumReleaseAgeExclude`\nentry, such as `@kungfu-tech/buildchain@2.2.5`, and remove it once the package\nhas aged past the normal policy window. Do not replace that with a broad\nregistry or scope-wide exclude.\n\nUse the package API directly inside JavaScript build scripts:\n\n```js\nimport { createBuildchainLogger } from \"@kungfu-tech/buildchain/logging\";\n\nconst logger = createBuildchainLogger({ source: \"user\", component: \"build\" });\nawait logger.span(\"build.native\", { phase: \"build\" }, async () => {\n await buildNativeArtifacts();\n});\n```\n\nThe standalone binary and CLI are for workflow steps, shell scripts, and\nnon-JavaScript environments. JavaScript code that already depends on\n`@kungfu-tech/buildchain` should import the toolkit API instead of spawning\n`npx buildchain` or a downloaded binary.\n\n## Node API and Package Exports\n\nBuildchain's public Node API is the package `exports` surface, not arbitrary\ninternal file paths. The npm package also ships\n`dist/site/node-api-registry.json` and exports it as\n`@kungfu-tech/buildchain/site/node-api-registry.json` so agents can enumerate\nthe supported imports from the installed package.\nFor navigation, start with `dist/site/capability-registry.json`: it groups\nmanuals, CLI commands, workflow/action inputs, Node exports, site pages, and KFD\nclaim facts by product capability before an agent chooses a concrete command or\nmanual.\n\nCurrent public import families include:\n\n```js\nimport * as buildchain from \"@kungfu-tech/buildchain\";\nimport { createBuildchainLogger } from \"@kungfu-tech/buildchain/logging\";\nimport { collectModuleBuildFacts } from \"@kungfu-tech/buildchain/build-facts\";\nimport { checkHomebrewTap } from \"@kungfu-tech/buildchain/homebrew\";\nimport { verifyKfd1ReleaseGate } from \"@kungfu-tech/buildchain/kfd-gate\";\nimport { collectBadgeBundleFacts } from \"@kungfu-tech/buildchain/badges\";\nimport { collectReadmeBadgeFacts } from \"@kungfu-tech/buildchain/readme-badges\";\nimport { verifyReleasePassport } from \"@kungfu-tech/buildchain/release-passport\";\nimport { createReleasePropagationPlan } from \"@kungfu-tech/buildchain/release-propagation\";\nimport { planReleaseLineBootstrap } from \"@kungfu-tech/buildchain/release-line-bootstrap\";\nimport { collectPublicSurfaceReverseAudit } from \"@kungfu-tech/buildchain/public-surface-audit\";\nimport { createBuildchainLayoutDiscovery } from \"@kungfu-tech/buildchain/buildchain-layout\";\nimport contractWorld from \"@kungfu-tech/buildchain/site/buildchain-contract.json\" with { type: \"json\" };\nimport capabilityRegistry from \"@kungfu-tech/buildchain/site/capability-registry.json\" with { type: \"json\" };\nimport manualRegistry from \"@kungfu-tech/buildchain/site/manual-registry.json\" with { type: \"json\" };\nimport nodeApiRegistry from \"@kungfu-tech/buildchain/site/node-api-registry.json\" with { type: \"json\" };\nimport publicSurfaceAudit from \"@kungfu-tech/buildchain/site/public-surface-audit.json\" with { type: \"json\" };\n```\n\nUse `dist/site/manual-registry.json` to find the packaged operating manuals and\ntheir SHA-256 digests. Use `dist/site/buildchain-contract.json` to verify the\nfloating-ref contract world for a runtime such as `@v2`.\n\n## Commands\n\n`buildchain layout` is the stable machine question for repository layout. Tools\nsuch as Shifu should call it instead of copying `.buildchain/` path constants:\n\n```bash\nbuildchain layout --cwd /path/to/repository --json\n```\n\nThe result identifies the Buildchain version pin, repository root and config,\nthe canonical and currently resolved KFD-3 registry paths, and the KFD field\nused to declare Shifu jurisdiction. A repository is in Shifu's distribution\njurisdiction only when a KFD-3 surface explicitly declares\n`distribution.registrar=\"shifu\"`; the presence of Buildchain configuration is\nnot sufficient. The same contract is available through\n`createBuildchainLayoutDiscovery()` from\n`@kungfu-tech/buildchain/buildchain-layout`.\n\n`buildchain init` writes a starter `.buildchain/buildchain.toml` and a reusable workflow\ncaller at `.github/workflows/build.yml`.\n\nSupported presets:\n\n- `--type package` for Node package repositories with pnpm, npm, or yarn.\n- `--type native` for CMake-style native projects.\n- `--type web-surface` for preview/staging/production site or app deployments.\n- `--type infra-contract` for provider-agnostic infrastructure contract\n validation, observation, contract publication, and downstream propagation\n planning without default mutation. Provider adapters expose built-in command\n plans by default, and only configured `[infra.commands]` hooks can execute.\n- `--type publication-artifact` for papers, reports, specifications, and other\n publication repositories that produce PDFs, metadata, source bundles, and\n site-consumable manifests without becoming web-surface repositories. The\n scaffold uses Buildchain's pinned\n `ghcr.io/kungfu-systems/build-images/latex-pdf-builder:v1.2.0` toolchain for\n LaTeX PDF builds.\n- `--type distribution-index` for Homebrew taps and other index repositories\n whose files are projections of upstream release passport evidence.\n- `--type anchored-package` for packages whose version is anchored to an\n explicit upstream release manifest.\n\nThe native preset includes an opt-in `[diagnostics.native]` profile with common\ntool/cache/artifact probes. Consumers can keep it enabled, adjust the tool and\ndirectory lists, or disable it if a repository does not need native diagnostics.\n\n`buildchain validate` parses `.buildchain/buildchain.toml`, checks configured version-state\nfiles, and can require named lifecycle stages:\n\n```bash\nbuildchain validate \\\n --require-version-state \\\n --require-lifecycle-stages install,build,verify\n```\n\n`buildchain lifecycle run <stage>` executes a lifecycle stage and writes the\nsame deterministic artifact manifest contract used by the reusable workflow:\n\n```bash\nbuildchain lifecycle run build \\\n --artifact-path dist \\\n --artifact-name \"{repo}-{version}-{platform}\"\n```\n\n`buildchain release line open` plans or writes the first version-state commit\nfor a new semver minor line. It does not publish anything. The dry-run mode is\nthe default and returns the dev/alpha/release refs, protection contract, default\nbranch action, and initial version before any GitHub mutation happens:\n\n```bash\nbuildchain release line open \\\n --major 2 \\\n --minor 10 \\\n --source-ref release/v2/v2.9 \\\n --json\n```\n\nThe write mode only updates local version-state files. The repository workflow\n`Release Line Bootstrap` wraps this command and, when `apply=true`, commits the\ninitial version state, creates `dev/vX/vX.Y`, `alpha/vX/vX.Y`, and\n`release/vX/vX.Y`, applies one-review branch protection, switches the default\nbranch, and opens the first dev-to-alpha channel PR:\n\n```bash\nbuildchain release line open \\\n --major 2 \\\n --minor 10 \\\n --source-ref release/v2/v2.9 \\\n --write \\\n --json\n```\n\n`buildchain` also publishes a public surface reverse audit as\n`dist/site/public-surface-audit.json`. The audit enumerates CLI commands from\n`bin/buildchain.mjs`, workflow inputs, action inputs, site pages, and docs\ncommand references, then compares them with the generated registries. Buildchain\nself-checks fail closed when an enumerable public surface is missing from the\nregistry:\n\n```js\nimport {\n collectPublicSurfaceReverseAudit,\n assertPublicSurfaceReverseAudit,\n} from \"@kungfu-tech/buildchain/public-surface-audit\";\n\nassertPublicSurfaceReverseAudit(collectPublicSurfaceReverseAudit({ root: process.cwd() }));\n```\n\n`buildchain kfd` is the product-facing KFD namespace. Schema commands expose the\nmachine-readable KFD standards shipped by `@kungfu-tech/kfd`, while versioned\nsubcommands host concrete product workflows. KFD-1, KFD-2, and KFD-3 are\nfirst-class Buildchain surfaces. KFD-4 is schema-only until Buildchain has a\nreal verification protocol for it.\n\n`status` reports implemented support and the active repo-owned file layout.\n`migrate-layout` moves legacy root files into `.buildchain/`:\n\n```bash\nbuildchain kfd status --json\nbuildchain kfd migrate-layout --write\n```\n\nKFD-1 commands generate and validate contract-world release evidence:\n\n```bash\nbuildchain kfd 1 schema --json\nbuildchain kfd 1 witness --json\nbuildchain kfd 1 gate --witness-json kfd-1-witness.json --json\nbuildchain kfd 1 verify --gate-json kfd-1-gate.json --json\n```\n\nKFD-2 commands validate trust taxonomy entries and generate Buildchain's public\nclaim evidence. Product repositories use the `product-claims` subcommand to\nvalidate and render their own declared KFD-2 release claims under the canonical\nBuildchain KFD layout:\n\n```bash\nbuildchain kfd 2 schema --json\nbuildchain kfd 2 taxonomy --entry-json residual-risk.json --kind residualRisk --json\nbuildchain kfd 2 claims --json\nbuildchain kfd 2 product-claims check --json\nbuildchain kfd 2 product-claims write --json\nbuildchain kfd 2 product-claims render --json\n```\n\nThe default source is `.buildchain/kfd/kfd-2/registry.json`; outputs are\n`.buildchain/kfd/kfd-2/release-claims.json`, per-claim release-passport inputs\nunder `claims/`, and `buildchain-claim-args.txt`. Use `--registry` or\n`--output-dir` only for an explicit product packaging projection. `check` never\nwrites and exits non-zero when outputs drift.\n\nKFD-3 commands are separate from Buildchain's self reverse audit: products can\ndetect standard public surfaces, register the accepted boundary, audit the\ncurrent source or artifact tree, generate a release-passport-compatible witness,\nand expose a capability map for agents:\n\n```bash\nbuildchain kfd schema list --json\nbuildchain kfd schema show kfd-3 --json\nbuildchain kfd 3 detect --kind node-api --kind cli --json\nbuildchain kfd 3 register node-api --product Buildchain\nbuildchain kfd 3 audit --json\nbuildchain kfd 3 witness --kind prebuild --output .buildchain/kfd/kfd-3/collaboration-interface.prebuild.json\nbuildchain kfd 3 query buildchain --json\nbuildchain kfd 4 schema --json\n```\n\nThe public Node API is exported from `@kungfu-tech/buildchain/kfd`. See\n[`kfd-support.md`](kfd-support.md) for the detected / declared / enforced model\nand the agent query flow.\n\nLifecycle runs also write a Buildchain observability JSONL log at\n`.buildchain/logs/events.jsonl` by default. Framework events use\n`source=buildchain`; consumer lifecycle commands use `source=user`. This lets a\nmaintainer tell apart time spent inside Buildchain's artifact/manifest\nframework from time spent in the repository's own build, test, packaging, or\npublish commands. The artifact manifest and summary embed the observability\nsummary for that lifecycle run id, so uploaded artifacts preserve the timing\nfacts without mixing in older JSONL events.\n\n`buildchain log`, `buildchain mark`, and `buildchain span` expose the same event\nprotocol to repository scripts:\n\n```bash\nbuildchain mark --event configure.ready --phase configure --attribute target=release\nbuildchain span --event native.build --phase build -- cmake --build build\nbuildchain log warn --event cache.miss --component conan --attribute token=hidden\nbuildchain log summary --json\nbuildchain verify observability-log .buildchain/logs/events.jsonl --min-events 4 --require-phase build\nbuildchain diagnostics summary .buildchain/artifacts/*/diagnostics.json --json\nbuildchain sample process-tree --label native-build --interval-ms 15000 -- make -j20\n```\n\nDuring `buildchain lifecycle run`, child processes receive\n`BUILDCHAIN_LOG_PATH` and `BUILDCHAIN_LOG_RUN_ID`. A shell, Python, CMake, Conan,\nor JavaScript helper can call `buildchain mark` or `buildchain span` mid-build\nand have those events grouped into the same lifecycle summary.\n`buildchain verify observability-log` is a release gate: it fails when the log\nis missing, has too few events, contains error events, or does not include\nrequired phases, components, or event names.\n\nThe event protocol is JSONL and is also available from the SDK:\n\n```js\nimport { createBuildchainLogger } from \"@kungfu-tech/buildchain/logging\";\n\nconst logger = createBuildchainLogger({ source: \"user\", component: \"native-build\" });\nlogger.mark(\"configure.ready\", { phase: \"configure\" });\n```\n\nSecret-looking attribute keys such as `token`, `password`, `secret`,\n`authorization`, `cookie`, and `private-key` are redacted before they are written.\nFull command strings are not recorded by `span`; scripts should provide stable\nevent names and safe attributes instead.\n\n`buildchain diagnostics summary` reads one or more small diagnostics artifacts\nand emits the same cross-platform summary as the diagnostics SDK:\n\n```bash\nbuildchain diagnostics summary \\\n .buildchain/artifacts/linux-x64/diagnostics.json \\\n .buildchain/artifacts/macos-arm64/diagnostics.json \\\n --output .buildchain/artifacts/diagnostics-summary.json \\\n --json\n```\n\nThe JSON summary keeps per-platform lifecycle stage tables, adds lifecycle\ntotal durations, carries top slow spans, aggregates warning/error counts, and\nsorts the slowest platforms. Each platform row carries compact runner facts,\nchecked tool versions/missing tools, package manager/cache directory details,\ncompiler-cache availability, and a compact process sampler summary: requested\nparallelism, observed max active processes, the ratio between them, sample\ncount, process categories, and the top sampled command basenames. This lets\nmaintainers inspect matrix timing, runner, tool, cache, and concurrency context\nwithout downloading large platform binaries or process sidecars first.\nWhen a sibling `diagnostics-manifest.json` is available, the summary also records\nits file list and verifies the listed `diagnostics.json` byte count and sha256.\nMissing, unreadable, or mismatched sidecar manifests are reported through\n`diagnosticsManifestWarningCount` and the per-platform `diagnosticsManifest`\nfield without failing the timing rollup.\nThe summary also compares each `diagnostics.json` contract to\n`BUILDCHAIN_DIAGNOSTICS_CONTRACT`; mismatches are reported through\n`diagnosticsContractWarningCount` and the per-platform `diagnosticsContract`\nfield so reviewers can separate diagnostics schema drift from lifecycle\nwarnings or build failures.\n\nWithout `--json`, the command prints a compact lifecycle timing table with\ninstall/build/verify/publish, artifact scan/upload, total, warning, and error\ncolumns for each platform, plus `jobs` and `active` columns for requested and\nobserved process concurrency when sampler data is present.\n\n`buildchain facts` collects and verifies source/version/output facts for\nmodules and products:\n\n```bash\nbuildchain facts module \\\n --module native-core \\\n --output .buildchain/facts/native-core.json \\\n --legacy-kungfu-buildinfo framework/core/src/kungfu/yijinjing/kungfubuildinfo.json\n\nbuildchain facts aggregate \\\n --product kungfu \\\n --module-fact .buildchain/facts/native-core.json \\\n --artifact dist/kungfu.zip \\\n --output .buildchain/facts/kungfu.json\n\nbuildchain facts verify --fact .buildchain/facts/kungfu.json\n```\n\nThe same implementation is available from\n`@kungfu-tech/buildchain/build-facts`. Release passports can include these\nfacts with repeated `--build-facts-json` arguments to\n`buildchain collect github-release`. See\n[`build-facts.md`](build-facts.md) for the config schema and Node API.\n\n`buildchain sample process-tree` wraps a long-running command and periodically\nwrites process-tree snapshots:\n\n```bash\nbuildchain sample process-tree \\\n --label native-build \\\n --interval-ms 15000 \\\n --output .buildchain/diagnostics/process-samples.jsonl \\\n --summary-output .buildchain/diagnostics/process-summary.json \\\n -- \\\n make -j20\n```\n\nThe command returns the wrapped command's exit status. The JSONL file contains\nsmall timestamped samples; the summary JSON records requested parallelism,\nobserved concurrency, sampled CPU, command categories, and top command\nbasenames. Use it when a native build requests high parallelism but appears to\nspend long stretches in low-concurrency compile, archive, link, or cache steps.\n\n`buildchain doctor` checks repository readiness before remote side effects:\n\n```bash\nbuildchain doctor --json\n```\n\nIt validates `.buildchain/buildchain.toml`, package-manager detection, Git repository state,\nand the reusable workflow caller. For `version.strategy = \"anchored\"` with\n`version.next = \"manual\"`, it also embeds the anchored package release contract\ncheck: anchor manifest readability, configured version files, trusted\npublishing, package publish order, and required lifecycle stages. Add\n`--require-publish-source-lock` inside a publish job when the doctor report\nshould also fail unless the job is running from a resolved `publish-gate/*`\nsource lock.\n\nAnchored/manual package publish jobs can run the narrower source-lock gate\ndirectly:\n\n```bash\nbuildchain publish-source validate-anchored-release --json\n```\n\nThe command requires `BUILDCHAIN_PUBLISH_SOURCE_REF`,\n`BUILDCHAIN_PUBLISH_SOURCE_SHA`, and `BUILDCHAIN_PUBLISH_SOURCE_LOCKED` from the\nreusable build workflow outputs. It fails closed for direct `alpha/*` or\n`release/*` channel-branch publication, and checks the publish-gate consumer\nversion against configured version files and the anchor manifest. The JSON\nresult is shaped for future `buildchain.libkungfu.dev` fact ingestion.\n\n`buildchain release`, `buildchain web-surface`, `buildchain infra-contract`,\n`buildchain publication-artifact`, `buildchain publish-source`,\n`buildchain badges`, `buildchain homebrew`, and `buildchain build-contract`\nroute to the same implementation used by\nBuildchain's package APIs or GitHub Actions workflows. This keeps local\ninspection and CI behavior on the same implementation path.\n\nGenerate publication artifact metadata after building a paper or report:\n\n```bash\nbuildchain publication-artifact manifest \\\n --source-sha \"$(git rev-parse HEAD)\" \\\n --json\n```\n\nGenerate the Buildchain-owned npm paper package contents from declared\npublication facts:\n\n```bash\nbuildchain publication-artifact npm-package --json\n```\n\nThis command reads `project.type = \"publication-artifact\"`,\n`publication.version`, and `[publish] kind = \"npm-paper-package\"` plus\n`publish.package`; it writes `.buildchain/publication/npm-package` by default.\nThe `paper-release.yml@v2` reusable workflow uses the same command before\nrunning the standard npm publish transaction.\n\nThe command writes `.buildchain/publication/publication-artifact.json`,\n`.buildchain/publication/publication-artifact-passport.json`, a source bundle,\nand, when `[publication.archive]` is configured,\n`.buildchain/publication/publication-registry.json` by default. See\n[`publication-artifacts.md`](publication-artifacts.md) for the repository\ncontract, pinned LaTeX builder, and reusable workflow.\n\nGenerate, check, or update the managed README badge block:\n\n```bash\nbuildchain badges readme --json\nbuildchain badges readme --check\nbuildchain badges readme --write\nbuildchain badges bundle --json\nbuildchain badges bundle --check\nbuildchain badges bundle --write\nbuildchain badges bundle --claims kfd-1,release-passport --write\n```\n\nThe `--json` form emits the `kungfu-buildchain-readme-badge-facts` object.\n`--check` fails closed when the README marker block is missing or stale.\n`--write` inserts or replaces only the marked block. KFD passed badges come\nfrom the repository's own verified release passport; unreleased repositories\ndowngrade to explicit local declarations such as `declared`, `aligned`, or\n`planned`. `buildchain badges bundle` is the focused trust-badge entrypoint: it\nemits `kungfu-buildchain-badge-bundle-facts` and defaults to KFD-1, KFD-2,\nKFD-3, and Release Passport. See [`readme-badges.md`](readme-badges.md) for the\nmarker contract and `[badges]` / `[badges.bundle]` configuration.\n\nGenerate or check Homebrew tap projections from upstream release passports:\n\n```bash\nbuildchain homebrew update-formula \\\n --package buildchain \\\n --release-passport https://github.com/kungfu-systems/buildchain/releases/download/v2.8.15/buildchain.release.json \\\n --write\n\nbuildchain homebrew check --json\n```\n\n`update-formula` writes `Formula/buildchain.rb` and `tap-manifest.json` from\nupstream release passport evidence. `check` fails closed when the Formula,\nmanifest, artifact digests, or KFD status drift from the upstream passport. See\n[`homebrew.md`](homebrew.md) for the distribution-index project contract.\n\n`buildchain collect github-release` creates a release passport bundle from\nGitHub Release assets or a local asset directory:\n\n```bash\nbuildchain collect github-release \\\n --tag v2.2.0 \\\n --repository kungfu-systems/buildchain \\\n --assets-dir dist \\\n --output-dir .buildchain/release-passport\n```\n\nThe bundle includes `buildchain.release.json`, `artifact-evidence.json`,\n`impact.json`, `agent-index.json`, `product-mechanism.json`, `check-report.json`,\nand `llms.txt`. Production binary distribution defaults to GitHub-hosted\nrunners so other projects can reproduce the release lane; self-hosted runners\nremain compatibility fixtures and are recorded as runner facts when used.\n\nFor publish-transaction releases, pass the additional evidence inputs so\n`buildchain.release.json` becomes the unified passport instead of a binary-only\nasset summary:\n\n```bash\nbuildchain collect github-release \\\n --tag v2.3.2 \\\n --repository kungfu-systems/buildchain \\\n --assets-dir dist \\\n --publish-evidence-json .buildchain/release-evidence/v2.3.2/evidence.json \\\n --transaction-json .buildchain/release-state/v2.3.2/state.json \\\n --package-set-json package-set.json \\\n --impact-json impact.json \\\n --trusted-publishing-json trusted-publishing.json \\\n --anchor-manifest-json libnode.release.json \\\n --build-summary-json .buildchain/artifacts/build-summary.json \\\n --platform-manifest-json .buildchain/artifacts/linux-x64/manifest.json \\\n --platform-manifest-json .buildchain/artifacts/darwin-arm64/manifest.json \\\n --platform-manifest-json .buildchain/artifacts/win32-x64/manifest.json \\\n --dist-tag-evidence-json .buildchain/release-evidence/v2.3.2/dist-tag-evidence.json \\\n --kfd-1-witness-json .buildchain/kfd/kfd-1/contract-world.witness.json \\\n --kfd-2-claim-json .buildchain/kfd/kfd-2/release-claims.json \\\n --kfd-3-prebuild-witness-json .buildchain/kfd/kfd-3/collaboration-interface.prebuild.json \\\n --kfd-3-artifact-verify-cmd \"kungfu agent verify --json\" \\\n --release-extra-json '{\"channel\":\"release\",\"targetRef\":\"release/v2/v2.3\"}' \\\n --output-dir .buildchain/release-passport\n```\n\nThe generated passport records the main and platform packages, npm dist-tags,\npublished versions, release source/ref state, anchor manifest digest, registry\nartifact digests, trusted publishing evidence, and Buildchain transaction\nresult. It also records `buildSummary`, `platformArtifactManifests`, and\n`distTagPromotion` when those JSON inputs are supplied. `packageSet` keeps the\nordered package set; `publish.packages[]` is the agent-readable npm publication\nsummary for each main/platform package. For Buildchain releases, verification\nexpects the supplied package set to include the main package plus the three\nplatform packages with version, dist-tag, and digest evidence. Verification\nfails closed if supplied sections are internally incomplete or point to\nartifacts without matching evidence.\n\n`--kfd-1-witness-json` attaches a KFD-1 contract-world release gate. The witness\nis structured JSON: consumers declare the contract world, canonical JSON policy,\nartifact paths, and expected SHA-256 digests. Buildchain imports KFD-owned\nmetadata from `@kungfu-tech/kfd`, freezes the witness before build publication,\nthen verifies the resulting artifact bytes itself and writes the evidence under\nthe KFD-provided top-level key currently named `kfd-1`. Consumers should not\nduplicate this by running repository-specific scripts or invoking the Kungfu\nSDK from their release workflow.\n\nFor the KFD repository, KFD-1 witnesses may be self-hosted standard-contract\nwitnesses: docs, schemas, standards metadata, package exports, and\nsite-consumption entrypoints are checked from source hashes to packaged artifact\nhashes, and the passport records schema IDs, self-hosting boundary, result, and\nresponsibility state.\n\n`--kfd-2-claim-json` attaches explicit public release claims to the KFD-2\nrelease trust passport audit. Buildchain also derives KFD-2 claims from KFD-1\nand KFD-3 gate evidence. Public claims must 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 and emit a\nwarning.\n\n`--kfd-3-prebuild-witness-json` attaches a KFD-3 collaboration-interface\nrelease gate. The product remains the source of truth: it emits a pre-build\nwitness that contains or points to its KFD-3 collaboration interface, declared\nparticipant-facing public surfaces, and registry digest. Buildchain freezes\nthat declaration before publication. The artifact side is supplied either by\n`--kfd-3-artifact-witness-json` or by a product-owned command such as\n`--kfd-3-artifact-verify-cmd \"kungfu agent verify --json\"`. Buildchain then\nchecks closure: every declared shipped public surface must be present in the\nartifact witness, and every artifact-exposed participant-facing public surface\nmust have been declared. The generated passport writes this evidence under the\nKFD-provided top-level key currently named `kfd-3`.\n\nThis gate is useful for agent-facing products because it turns KFD-3 from prose\ninto release evidence. A package cannot claim KFD-3 collaboration-interface\nsupport merely because the docs mention it; the release passport must show the\nfrozen declaration, the artifact-side witness digest, and a passing closure\ncomparison.\nFor the KFD repository itself, the witness can declare docs, schemas, standards\nmetadata, package exports, and site-consumption contracts as grouped public\nsurfaces; the artifact witness must expose the same enumerable package/site\nsurfaces or verification fails closed.\n\n`--impact-json` supplies the surface-aware impact ledger. Production release\npassports (`release/*`) and major publish-gate passports require\n`surfaceImpacts[]`; alpha, local, and legacy passport contexts keep it\noptional. When `surfaceImpacts[]` is required or supplied, the verifier requires\neach entry to include an id, impact, and rationale, and requires\n`versionImpact.final` to match the highest declared surface impact. The\ncollector copies `versionImpact` plus `surfaceImpacts` into\n`buildchain.release.json`. This lets\n`buildchain explain release --for agent --json` state why a release is patch,\nminor, or major instead of relying on file-path memory.\n\nBuildchain dogfoods its observability toolkit in this lane. The standalone\nbuilder writes API-generated events, while the workflow uses `buildchain mark`,\n`buildchain span`, `buildchain verify observability-log`, and `buildchain log\nsummary`; the event logs and summaries are published as release passport assets.\n\nVerify and explain release passports:\n\n```bash\nbuildchain verify release-passport .buildchain/release-passport/buildchain.release.json\nbuildchain explain release --passport .buildchain/release-passport/buildchain.release.json --for agent --json\nbuildchain inspect release --passport .buildchain/release-passport/buildchain.release.json\n```\n\nThe verifier fails closed when required protocol files are absent, artifacts are\nnot covered by evidence, or digests disagree. The explanation output is shaped\nfor agents: trust, completeness, impact, recovery route, and next action.\n\nVerify a published artifact by subject:\n\n```bash\nbuildchain verify artifact ./Kungfu-2.8.0-windows-x64.exe\nbuildchain inspect artifact ./Kungfu-2.8.0-windows-x64.exe --json\nbuildchain explain artifact ./Kungfu-2.8.0-windows-x64.exe --for agent --json\nbuildchain verify artifact npm:@kungfu-tech/libnode@22.22.3-kf.3-alpha.18 \\\n --repository kungfu-systems/libnode \\\n --tag v22.22.3-kf.3-alpha.18 \\\n --json\n```\n\n`verify artifact` computes or obtains the subject digest, discovers the\ndetached release passport, verifies the passport, then requires that the\nsubject digest appears in the passport's release assets, package set, publish\nevidence, or artifact evidence. Outcomes are explicit: `pass`, `fail`, or\n`unverifiable`. A filename is only a hint; trust comes from digest equality.\nFor `npm:<name>@<version>` subjects, Buildchain resolves `dist.integrity` from\nthe npm registry before matching passport evidence. Use `--npm-registry <url>`\nto verify packages from a custom registry; otherwise Buildchain uses\n`npm_config_registry` or `https://registry.npmjs.org/`.\n\nDiscovery is fail-closed and ordered:\n\n1. `--passport <file-or-url>`.\n2. Sidecar pointer, such as `<artifact>.buildchain-passport.json`.\n3. Embedded/package pointer, such as `package.json` `buildchain.releasePassport`.\n4. Local config or org index, such as `.buildchain/artifact-passport-locators.json`.\n5. GitHub Release default discovery from `github-release:` subjects, GitHub\n Release asset URLs, or `--repository <owner/repo> --tag <tag>`.\n6. Custom `--locator-config <json-or-url>`.\n7. `unverifiable` with retry guidance.\n\nLocator files are policy, not protocol. They map subject fields such as\n`name`, `kind`, `version`, `digest`, `repository`, or `tag` to a detached\npassport location:\n\n```json\n{\n \"schemaVersion\": 1,\n \"contract\": \"kungfu-buildchain-artifact-passport-locator\",\n \"locators\": [\n {\n \"match\": {\n \"name\": \"Kungfu-2.8.0-windows-x64.exe\",\n \"digest\": \"sha256:...\"\n },\n \"passport\": \"../release-passport/buildchain.release.json\"\n }\n ]\n}\n```\n\nSupported subject shapes include local files and directories, URLs,\n`npm:<name>@<version>`, `oci:...`, `s3:...`,\n`github-release:<owner/repo>@<tag>/<asset>`, and deployment endpoints. Local\nfiles, directories, and URLs are digestable directly; remote package, OCI,\nobject storage, and deployment subjects should provide a digest or resolve to a\nlocator that records one.\n\nVerify infra-contract lifecycle evidence bundles:\n\n```bash\nbuildchain infra-contract --mode ci --source-sha \"$GITHUB_SHA\"\nbuildchain verify infra-contract-evidence-bundle .buildchain/infra-contract-evidence-bundle.json\n```\n\nThe infra-contract `ci` mode is mutation-free. It writes validate, plan,\ncontract, propagation dry-run, evidence bundle, and verification JSON artifacts\nunder `.buildchain/`, giving reusable workflows one standard responsibility\nchain instead of hand-written command sequences.\n\nThe infra-contract verifier is read-only. It recomputes the bundle hash and\nchecks that desired, plan, approval, apply, observe, contract, and propagate\nevidence remain bound to the same contract artifact. It also recomputes the\nbundle validation summary, so stale or misleading summary booleans fail closed\neven when the bundle hash has been refreshed.\n\n`buildchain release --dry-run` explains the release-line state machine before a\nmaintainer opens or merges a channel PR:\n\n```bash\nbuildchain release --dry-run --target-ref alpha/v2/v2.2\nbuildchain release --dry-run --target-ref release/v2/v2.2 --sha <verified-sha>\nbuildchain release dry-run --target-ref publish-gate/major --source-ref release/v2/v2.2\nbuildchain release explain --target-ref alpha/v2/v2.1 --json\n```\n\nThis is a Buildchain-level dry-run, not an npm dry-run. It explains the legal\nsource branch, exact release or alpha tags, floating tags, channel branches,\nversion-state files, governance checks, and publish transaction behavior that\nwould apply if the corresponding PR merge were promoted. It does not move\nbranches, move tags, edit files, publish npm packages, or run lifecycle publish\ncommands. `release explain` is the same explanation surface with a clearer name.\nPass `--json` for a machine-readable plan.\n\n`buildchain transaction inspect` is the top-level recovery inspection command\nfor the publish transaction state:\n\n```bash\nbuildchain transaction inspect --version v2.1.0-alpha.0\n```\n\nIt reads or locally initializes the durable transaction record and validates\navailable publish evidence. Remote durable refs and public Git ref finalization\nremain owned by `actions/promote-buildchain-ref`; the CLI inspection surface is\nfor preflight and recovery reasoning before a maintainer reruns or resumes a\npromotion.\n\n`buildchain npm dry-run` verifies the package shape before a release tag exists:\n\n```bash\nbuildchain npm dry-run --json\n```\n\nThe command validates `package.json`, infers the exact release tag\n`v${package.json.version}`, chooses npm dist-tag `alpha` for prereleases and\n`latest` for stable releases, runs `npm pack --dry-run --json`, and then runs\n`npm publish --dry-run --access public --tag <alpha|latest>` unless\n`--skip-npm-publish-dry-run` is passed. It never performs a real publish.\n\n## npm Publish Gate\n\nBuildchain's own npm package is published from\n`.github/workflows/buildchain-ref-promotion.yml`, inside the same publish\ntransaction that promotes release refs:\n\n- `v2.0.13-alpha.0` publishes to npm with dist-tag `alpha`.\n- `v2.0.13` publishes to npm with dist-tag `latest`.\n- moving refs such as `v2`, `v2.0`, and `v2.0-alpha` do not match the publish\n workflow and do not publish.\n\nThe promotion workflow uses npm Trusted Publishing through GitHub Actions OIDC.\nIt runs on a GitHub-hosted runner with `id-token: write`, but it does not\nmanually run the release-candidate resolver or promote action. Buildchain's own\ndogfood path calls the declarative `release-candidate-promote.yml` wrapper with\nchannel, target ref/SHA, PR-stage workflow, artifact, status-check, and passport\ninputs. The wrapper generates the version-state commit, runs\n`lifecycle.verify`, runs `lifecycle.publish`, writes Buildchain publish\nevidence, validates that evidence, and only then moves exact tags and floating\nrefs.\n\n```bash\nnode scripts/npm-publish-transaction.mjs\n```\n\nBefore the first real release, configure npm Trusted Publishing for:\n\n- package: `@kungfu-tech/buildchain`\n- repository: `kungfu-systems/buildchain`\n- workflow: `.github/workflows/buildchain-ref-promotion.yml`\n\nNo npm package is published by manual dispatch or ordinary branch builds.\nManual dispatch on `.github/workflows/npm-publish.yml` remains dry-run only, so\nmaintainers can verify package contents and npm publish shape before opening or\nmerging the release PR."
|
|
429
434
|
},
|
|
430
435
|
{
|
|
431
436
|
"id": "manual:consumer-issue-reporting",
|
|
@@ -596,7 +601,7 @@
|
|
|
596
601
|
],
|
|
597
602
|
"maturity": "stable",
|
|
598
603
|
"sourcePath": "docs/kfd-support.md",
|
|
599
|
-
"digest": "sha256:
|
|
604
|
+
"digest": "sha256:ab15de33a1a9e292b6da74c00b8b96b7c46330d0553a454d1de4c24c672fc025",
|
|
600
605
|
"headings": [
|
|
601
606
|
{
|
|
602
607
|
"level": 1,
|
|
@@ -633,6 +638,11 @@
|
|
|
633
638
|
"title": "KFD-3",
|
|
634
639
|
"anchor": "kfd-3"
|
|
635
640
|
},
|
|
641
|
+
{
|
|
642
|
+
"level": 2,
|
|
643
|
+
"title": "Shifu Discovery and Distribution Declarations",
|
|
644
|
+
"anchor": "shifu-discovery-and-distribution-declarations"
|
|
645
|
+
},
|
|
636
646
|
{
|
|
637
647
|
"level": 2,
|
|
638
648
|
"title": "Detected, Declared, Enforced",
|
|
@@ -664,7 +674,7 @@
|
|
|
664
674
|
"anchor": "known-gaps"
|
|
665
675
|
}
|
|
666
676
|
],
|
|
667
|
-
"markdown": "# KFD Support\n\nBuildchain implements KFD support as release evidence and product capability\nfacts, not as README prose. The machine-readable sources are:\n\n- `dist/site/kfd-claims.json` for Buildchain-owned public claims and KFD-3\n collaboration surfaces;\n- `dist/site/public-surface-audit.json` for reverse enumeration of exposed CLI,\n workflow, action, site, and documented command surfaces;\n- `buildchain.release.json` for release-specific KFD-1, KFD-2, and KFD-3\n passport results;\n- `.buildchain/buildchain.toml` for repository-owned Buildchain configuration;\n- `.buildchain/kfd/kfd-2/registry.json` for product-owned KFD-2 public claim\n declarations;\n- `.buildchain/kfd/kfd-3/surfaces.json` for product-owned KFD-3 surface\n registration;\n- `.buildchain/contract-lock.json` for accepted floating runtime contracts.\n\nBuildchain still reads the legacy root files `buildchain.toml`,\n`buildchain.contract-lock.json`, `buildchain.kfd3.json`, and the historical\n`.buildchain/kfd/kfd-3-surfaces.json` registry so existing consumers can run\n`buildchain kfd migrate-layout --write`. New repositories should keep\nrepo-owned Buildchain files under `.buildchain/`, with all KFD evidence under\n`.buildchain/kfd/`.\n\n## Unified Namespace\n\nKFD support is exposed through one first-class namespace:\n\n```bash\nbuildchain kfd status --json\nbuildchain kfd migrate-layout --write\nbuildchain kfd schema list --json\nbuildchain kfd 1 witness --json\nbuildchain kfd 2 claims --json\nbuildchain kfd 2 trust-claims --json\nbuildchain kfd 2 trust-assessment --json\nbuildchain kfd upstream roles --json\nbuildchain kfd upstream collect --json\nbuildchain kfd upstream check --json\nbuildchain kfd aggregate --json\nbuildchain kfd 3 query buildchain --json\nbuildchain kfd 4 schema --json\n```\n\nKFD-1, KFD-2, and KFD-3 have concrete Buildchain workflows. KFD-4 is currently\nschema-only in Buildchain: agents can discover and read the KFD-4 schema from\n`@kungfu-tech/kfd`, but Buildchain does not claim KFD-4 verification.\n\n## KFD-1\n\nKFD-1 proves that a product release is bound to one contract world. Buildchain\nuses KFD-1 for its runtime contract, release-passport schemas, packaged docs,\nNode exports, workflows, actions, and site-consumption facts.\n\nFor Buildchain itself, the source registry lives in\n`packages/core/buildchain-kfd-claims.js` and is projected to\n`dist/site/kfd-claims.json`. Release promotion binds that registry to exact\nsource and artifact hashes in the release passport.\n\nBuildchain exposes KFD-1 through:\n\n```bash\nbuildchain kfd 1 schema --json\nbuildchain kfd 1 witness --json\nbuildchain kfd 1 gate --witness-json kfd-1-witness.json --json\nbuildchain kfd 1 verify --gate-json kfd-1-gate.json --json\n```\n\n## KFD-2\n\nKFD-2 requires public trust claims to be backed by machine-readable evidence.\nBuildchain release passports fail or downgrade claims that only have prose.\n\nEvery public claim binds:\n\n- declared source files;\n- machine-readable evidence;\n- source, evidence, and artifact hashes;\n- artifact coordinates;\n- verification result;\n- audit boundary;\n- responsibility state;\n- residual risk.\n\nBuildchain exposes KFD-2 through:\n\n```bash\nbuildchain kfd 2 schema --json\nbuildchain kfd 2 taxonomy --entry-json residual-risk.json --kind residualRisk --json\nbuildchain kfd 2 claims --json\nbuildchain kfd 2 product-claims check --json\nbuildchain kfd 2 product-claims write --json\nbuildchain kfd 2 product-claims render --json\nbuildchain kfd 2 trust-claims --json\nbuildchain kfd 2 trust-assessment --json\n```\n\nProducts declare their own public trust intent once in the canonical tracked\nregistry:\n\n```text\n.buildchain/kfd/kfd-2/registry.json\n```\n\nThe registry uses\n`kungfu-buildchain-kfd-2-product-claims-registry/v1` and binds each claim to a\nsource, machine-readable evidence, artifact coordinates, verification command,\naudit boundary, responsibility, residual risk, and canonical status. Buildchain\ndoes not invent product claims from prose. It validates the declaration, hashes\nthe referenced files, and renders the release-facing outputs:\n\n```text\n.buildchain/kfd/kfd-2/release-claims.json\n.buildchain/kfd/kfd-2/claims/<claim-id>.json\n.buildchain/kfd/kfd-2/buildchain-claim-args.txt\n```\n\n`product-claims check` is read-only and fails on missing, stale, or unexpected\nclaim projections. `write` updates only the declared KFD-2 output set and\nremoves stale generated claim JSON files; unrelated files are preserved.\n`render` prints the expected document set without writing it. Version is read\nfrom the repository's configured Buildchain version state unless explicitly\noverridden. Release pipelines may override channel, tag, or source SHA while\nthe registry remains the stable product-intent source.\n\n`claims` generates Buildchain's release-passport public claim inputs. The\n`trust-claims` and `trust-assessment` commands expose the latest KFD package's\nfoundation KFD-2 facts from `@kungfu-tech/kfd` and validate their taxonomy\nvalues against the KFD-owned `trust-taxonomy` schema. Unknown `riskType`,\n`trustImpact`, `machineProvability`, or `agentAction` values fail validation;\nnew values must be requested upstream in `kungfu-systems/kfd`, not invented in\nBuildchain.\n\n`@kungfu-tech/kfd` is a runtime dependency of Buildchain, not a development-only\ndependency. The public `buildchain kfd ...` CLI and `@kungfu-tech/buildchain/kfd`\nNode API read KFD-owned standards metadata, schemas, foundation trust claims,\nfoundation trust assessments, and taxonomy values at runtime. Moving KFD to\n`devDependencies` would make installed Buildchain packages unable to answer KFD\nqueries in consumer repositories.\n\n## Upstream KFD Aggregation\n\nProducts often depend on multiple KFD-aware upstream components. A product's own\nKFD status is not the same thing as the status of those upstreams, but agents\nstill need one machine-readable view of the upstream trust surface.\n\nBuildchain exposes that view through:\n\n```bash\nbuildchain kfd upstream roles --json\nbuildchain kfd upstream collect --json\nbuildchain kfd upstream check --json\nbuildchain kfd aggregate --json\n```\n\n`upstream collect` reads `.buildchain/buildchain.toml`, resolves declared\npackages from the caller repository, hashes declared evidence assets, and emits\na `kungfu-buildchain-kfd-upstream-aggregate` document. `upstream check` validates\nthat aggregate. `aggregate` combines the product's own Buildchain KFD status\nwith the upstream aggregate.\n\nThis works in development before the consuming repository has published an\nalpha or release. In that state Buildchain can collect and check upstream\nfacts, versions, hashes, roles, and residual risk, but the consuming product\nmust not claim its own KFD status as `passed` until a release passport verifies\nthat product release.\n\nThe repository-owned declaration is intentionally small. Consumers normally\ndeclare the upstream package identity, not Buildchain's inferred role or a\nduplicate semver:\n\n```toml\n[kfd.upstream]\nauto_discover = false\n\n[[kfd.upstream.components]]\nid = \"kfd\"\npackage = \"@kungfu-tech/kfd\"\nrepository = \"kungfu-systems/kfd\"\nevidence = [\n \"package:kfd.release.json\",\n \"package:.buildchain/kfd/kfd-1/contract-world.witness.json\",\n \"package:.buildchain/kfd/kfd-2/release-claims.json\",\n \"package:.buildchain/kfd/kfd-3/collaboration-interface.json\",\n \"package:standards.json\",\n]\n```\n\nThe upstream package version is a single source of truth owned by the package\nmanager. Put the dependency in `package.json` / the lockfile, then let\nBuildchain read the installed package's real `package.json`:\n\n```json\n{\n \"devDependencies\": {\n \"@kungfu-tech/kfd\": \"1.0.0-alpha.21\"\n }\n}\n```\n\nMost consumers should keep `@kungfu-tech/kfd` in `devDependencies`: Buildchain\nuses it during CI, development checks, release evidence collection, and site\ngeneration. Move it to `dependencies` only if the product's own runtime imports\nKFD directly. Buildchain itself keeps KFD in `dependencies` because its public\nCLI and Node API resolve KFD standards, schemas, taxonomy, and foundation trust\nfacts at runtime.\n\nDo not repeat upstream semver values in `.buildchain/buildchain.toml`. Repeating\nversions in both `package.json` and Buildchain config creates stale facts.\n`upstream collect` records the actual installed package version and evidence\nhashes in the aggregate output.\n\n`kfd_1`, `kfd_2`, `kfd_3`, and `kfd_4` are optional capability-state hints. When\nomitted, Buildchain treats the component as `declared`. Use explicit values only\nwhen the upstream package really exposes the corresponding machine evidence,\nfor example:\n\n```toml\nkfd_1 = \"exported-witness\"\nkfd_2 = \"exported-claim\"\nkfd_3 = \"exported-collaboration-interface\"\nkfd_4 = \"schema-metadata\"\n```\n\nAn upstream component may be `declared`, `aligned`, `exported-*`, or another\nexplicit non-passed state when the evidence is package-local. A component may\nclaim `passed` only when the aggregate also binds that component to a release\npassport. Upstream `passed` never upgrades the product's own KFD status; it only\ndescribes the upstream trust surface consumed by the product.\n\n### Upstream Roles\n\nConsumers should normally omit `role`. Buildchain owns the role vocabulary and\ninfers the role from package identity and evidence. The aggregate records:\n\n- `role` - the normalized Buildchain-managed role;\n- `roleSource` - `known-package`, `evidence`, `default`, or `explicit`;\n- `roleReason` - the machine-readable explanation for the chosen role.\n\nThe managed role registry is queryable:\n\n```bash\nbuildchain kfd upstream roles --json\n```\n\nCurrent roles are:\n\n| Role | Meaning |\n| --- | --- |\n| `standard-and-schema-provider` | Provides KFD standards, schemas, taxonomy, or standard-owned witness and claim facts. |\n| `release-passport-and-kfd-gate-provider` | Provides release passport, KFD gate, release claim, or release governance machinery consumed by the product. |\n| `kfd-aware-product-component` | A product component that exposes KFD witness, claim, collaboration-interface, or package evidence without being core KFD infrastructure. |\n| `site-consumption-provider` | Provides site-consumption facts such as site manifests, site bundles, or downstream page-content contracts. |\n| `unknown-kfd-upstream` | Fallback for a declared upstream that has not matched a Buildchain-known package or role-specific evidence. |\n\nIf a consumer explicitly writes `role`, it must be one of that registry. Unknown\nexplicit values fail closed during `upstream check`; Buildchain will not let\nrepositories invent local role spellings that later fragment aggregate reports.\n\nBuildchain dogfoods this model with `@kungfu-tech/kfd` as its upstream\nstandard-and-schema provider. The generated site bundle includes\n`dist/site/kfd-upstream-aggregate.json` so downstream sites and agents can read\nBuildchain's upstream KFD facts from the npm package instead of scraping\nrepository scripts.\n\n## KFD-3\n\nKFD-3 closes participant-facing collaboration surfaces over a declared public\ninterface. Buildchain supports two complementary KFD-3 layers.\n\nThe first layer is Buildchain self-verification. Buildchain reverse-enumerates\nreal CLI commands, reusable workflow inputs, action inputs, site pages, and\ndocumented command references, then compares those facts with the generated\nregistries in `dist/site/`. A missing registry entry fails `pnpm run check`.\n\nThe second layer is product surface registration. Products can ask Buildchain to\ndetect standard public surfaces, write a small product-owned registry, audit the\nregistry against the current artifact/source tree, generate a release-passport\ncompatible witness, and query the resulting capability map.\n\n## Detected, Declared, Enforced\n\nKFD-3 surface registration uses three states.\n\n| State | Meaning |\n| --- | --- |\n| `detected` | Buildchain found a candidate public surface from package metadata, wheel metadata, CLI bins, binary artifacts, docs, or site bundle facts. |\n| `declared` | The product owner accepted that candidate into `.buildchain/kfd/kfd-3/surfaces.json`. |\n| `enforced` | The product has promoted a declared surface to a hard release boundary. Missing enforced surfaces fail release verification. |\n\nDetection does not silently become product intent. `register` is the boundary\ndecision. Existing consumers are unaffected until they opt in.\n\n## CLI\n\nInspect KFD-owned schema facts:\n\n```bash\nbuildchain kfd schema list --json\nbuildchain kfd schema show kfd-1 --json\nbuildchain kfd 4 schema --json\n```\n\nThe KFD schema namespace is discovered from `@kungfu-tech/kfd/standards.json`.\nFor KFD-2 this includes `trustClaims`, `trustAssessment`, `trustTaxonomy`,\n`releaseClaims`, and `releaseTrustPassport`. For KFD-4 Buildchain currently\nexposes the KFD-owned `observerPerspective` schema only.\n\nDetect public surface candidates:\n\n```bash\nbuildchain kfd 3 detect --json\nbuildchain kfd 3 detect --kind node-api --kind cli --json\n```\n\nRegister standard surface classes:\n\n```bash\nbuildchain kfd 3 register node-api --product Buildchain\nbuildchain kfd 3 register cli\nbuildchain kfd 3 register python-api --artifact dist/wheel-unpacked\n```\n\nAudit detected, declared, and enforced surfaces:\n\n```bash\nbuildchain kfd 3 audit --json\n```\n\nGenerate a witness for release passport collection:\n\n```bash\nbuildchain kfd 3 witness \\\n --kind prebuild \\\n --output .buildchain/kfd/kfd-3/collaboration-interface.prebuild.json\n```\n\nQuery capability facts for agents or downstream sites:\n\n```bash\nbuildchain kfd 3 query buildchain --json\nbuildchain kfd 3 query --passport .buildchain/release-passport/buildchain.release.json --json\n```\n\n## Node API\n\nThe CLI is a thin wrapper over the public Node API:\n\n```js\nimport {\n kfd1,\n kfd2,\n kfd3,\n kfd4,\n upstream,\n collectKfdAggregate,\n collectKfdStatus,\n collectKfdUpstreamFacts,\n checkKfdUpstreamFacts,\n listKfdUpstreamRoles,\n listKfdSchemas,\n readKfdSchema,\n} from \"@kungfu-tech/buildchain/kfd\";\n```\n\nAgents should start with `collectKfdStatus()` to learn which standards are\nimplemented and where the repository-owned Buildchain files live. For capability\nuse decisions, prefer `kfd3.queryCapabilities()`. The query result connects each\ncapability to:\n\n- KFD-3 surface identity and state;\n- KFD-1 basis facts such as source and artifact paths or digests;\n- KFD-2 trust evidence when a release passport is attached;\n- residual risk and recommended agent action.\n\n## Standard Detectors\n\nThe initial detector set is intentionally conservative:\n\n- npm packages: `package.json` `exports`, `main`, `types`, and `bin`;\n- Python wheels: unpacked `.dist-info/METADATA`, `RECORD`,\n `entry_points.txt`, and `top_level.txt`;\n- CLI binaries: `package.json#bin` and files under `bin/`;\n- standalone binaries and archives: common binary/archive outputs under\n artifact directories such as `dist/`;\n- documentation: `README.md`, `AGENTS.md`, and `docs/*.md`;\n- site bundles: `dist/site/*.json`.\n\nPython importability alone is not considered public API. A product can extend\nthe registry over time, but the first boundary is metadata-based.\n\n## Buildchain Self Dogfood\n\nBuildchain dogfoods this model in two ways:\n\n- `buildchain kfd 1 witness --json` generates Buildchain's own KFD-1 contract\n world witness;\n- `buildchain kfd 2 claims --json` generates Buildchain's own KFD-2 public\n claim evidence;\n- `buildchain kfd 2 trust-claims --json` and\n `buildchain kfd 2 trust-assessment --json` expose and validate the KFD\n package's foundation KFD-2 trust facts against the latest KFD taxonomy;\n- `dist/site/kfd-claims.json` declares Buildchain's own KFD-3 collaboration\n interface;\n- `buildchain kfd 3 query buildchain --json` resolves the packaged\n Buildchain capability map from that site fact source.\n\nThis lets downstream agents discover Buildchain's supported CLI, Node API,\nrelease passport, workflow, and site bundle surfaces from the npm package\ninstead of scraping source files or README examples.\n\n## Known Gaps\n\nArchive unpacking for `.whl`, `.tar.gz`, `.zip`, and platform-native installers\nis intentionally not part of the first detector. Callers can point\n`--artifact` at an unpacked artifact directory. Future Buildchain versions can\nadd archive readers without changing the registry contract."
|
|
677
|
+
"markdown": "# KFD Support\n\nBuildchain implements KFD support as release evidence and product capability\nfacts, not as README prose. The machine-readable sources are:\n\n- `dist/site/kfd-claims.json` for Buildchain-owned public claims and KFD-3\n collaboration surfaces;\n- `dist/site/public-surface-audit.json` for reverse enumeration of exposed CLI,\n workflow, action, site, and documented command surfaces;\n- `buildchain.release.json` for release-specific KFD-1, KFD-2, and KFD-3\n passport results;\n- `.buildchain/buildchain.toml` for repository-owned Buildchain configuration;\n- `.buildchain/kfd/kfd-2/registry.json` for product-owned KFD-2 public claim\n declarations;\n- `.buildchain/kfd/kfd-3/surfaces.json` for product-owned KFD-3 surface\n registration;\n- `.buildchain/contract-lock.json` for accepted floating runtime contracts.\n\nBuildchain still reads the legacy root files `buildchain.toml`,\n`buildchain.contract-lock.json`, `buildchain.kfd3.json`, and the historical\n`.buildchain/kfd/kfd-3-surfaces.json` registry so existing consumers can run\n`buildchain kfd migrate-layout --write`. New repositories should keep\nrepo-owned Buildchain files under `.buildchain/`, with all KFD evidence under\n`.buildchain/kfd/`.\n\n## Unified Namespace\n\nKFD support is exposed through one first-class namespace:\n\n```bash\nbuildchain kfd status --json\nbuildchain kfd migrate-layout --write\nbuildchain kfd schema list --json\nbuildchain kfd 1 witness --json\nbuildchain kfd 2 claims --json\nbuildchain kfd 2 trust-claims --json\nbuildchain kfd 2 trust-assessment --json\nbuildchain kfd upstream roles --json\nbuildchain kfd upstream collect --json\nbuildchain kfd upstream check --json\nbuildchain kfd aggregate --json\nbuildchain kfd 3 query buildchain --json\nbuildchain kfd 4 schema --json\n```\n\nKFD-1, KFD-2, and KFD-3 have concrete Buildchain workflows. KFD-4 is currently\nschema-only in Buildchain: agents can discover and read the KFD-4 schema from\n`@kungfu-tech/kfd`, but Buildchain does not claim KFD-4 verification.\n\n## KFD-1\n\nKFD-1 proves that a product release is bound to one contract world. Buildchain\nuses KFD-1 for its runtime contract, release-passport schemas, packaged docs,\nNode exports, workflows, actions, and site-consumption facts.\n\nFor Buildchain itself, the source registry lives in\n`packages/core/buildchain-kfd-claims.js` and is projected to\n`dist/site/kfd-claims.json`. Release promotion binds that registry to exact\nsource and artifact hashes in the release passport.\n\nBuildchain exposes KFD-1 through:\n\n```bash\nbuildchain kfd 1 schema --json\nbuildchain kfd 1 witness --json\nbuildchain kfd 1 gate --witness-json kfd-1-witness.json --json\nbuildchain kfd 1 verify --gate-json kfd-1-gate.json --json\n```\n\n## KFD-2\n\nKFD-2 requires public trust claims to be backed by machine-readable evidence.\nBuildchain release passports fail or downgrade claims that only have prose.\n\nEvery public claim binds:\n\n- declared source files;\n- machine-readable evidence;\n- source, evidence, and artifact hashes;\n- artifact coordinates;\n- verification result;\n- audit boundary;\n- responsibility state;\n- residual risk.\n\nBuildchain exposes KFD-2 through:\n\n```bash\nbuildchain kfd 2 schema --json\nbuildchain kfd 2 taxonomy --entry-json residual-risk.json --kind residualRisk --json\nbuildchain kfd 2 claims --json\nbuildchain kfd 2 product-claims check --json\nbuildchain kfd 2 product-claims write --json\nbuildchain kfd 2 product-claims render --json\nbuildchain kfd 2 trust-claims --json\nbuildchain kfd 2 trust-assessment --json\n```\n\nProducts declare their own public trust intent once in the canonical tracked\nregistry:\n\n```text\n.buildchain/kfd/kfd-2/registry.json\n```\n\nThe registry uses\n`kungfu-buildchain-kfd-2-product-claims-registry/v1` and binds each claim to a\nsource, machine-readable evidence, artifact coordinates, verification command,\naudit boundary, responsibility, residual risk, and canonical status. Buildchain\ndoes not invent product claims from prose. It validates the declaration, hashes\nthe referenced files, and renders the release-facing outputs:\n\n```text\n.buildchain/kfd/kfd-2/release-claims.json\n.buildchain/kfd/kfd-2/claims/<claim-id>.json\n.buildchain/kfd/kfd-2/buildchain-claim-args.txt\n```\n\n`product-claims check` is read-only and fails on missing, stale, or unexpected\nclaim projections. `write` updates only the declared KFD-2 output set and\nremoves stale generated claim JSON files; unrelated files are preserved.\n`render` prints the expected document set without writing it. Version is read\nfrom the repository's configured Buildchain version state unless explicitly\noverridden. Release pipelines may override channel, tag, or source SHA while\nthe registry remains the stable product-intent source.\n\n`claims` generates Buildchain's release-passport public claim inputs. The\n`trust-claims` and `trust-assessment` commands expose the latest KFD package's\nfoundation KFD-2 facts from `@kungfu-tech/kfd` and validate their taxonomy\nvalues against the KFD-owned `trust-taxonomy` schema. Unknown `riskType`,\n`trustImpact`, `machineProvability`, or `agentAction` values fail validation;\nnew values must be requested upstream in `kungfu-systems/kfd`, not invented in\nBuildchain.\n\n`@kungfu-tech/kfd` is a runtime dependency of Buildchain, not a development-only\ndependency. The public `buildchain kfd ...` CLI and `@kungfu-tech/buildchain/kfd`\nNode API read KFD-owned standards metadata, schemas, foundation trust claims,\nfoundation trust assessments, and taxonomy values at runtime. Moving KFD to\n`devDependencies` would make installed Buildchain packages unable to answer KFD\nqueries in consumer repositories.\n\n## Upstream KFD Aggregation\n\nProducts often depend on multiple KFD-aware upstream components. A product's own\nKFD status is not the same thing as the status of those upstreams, but agents\nstill need one machine-readable view of the upstream trust surface.\n\nBuildchain exposes that view through:\n\n```bash\nbuildchain kfd upstream roles --json\nbuildchain kfd upstream collect --json\nbuildchain kfd upstream check --json\nbuildchain kfd aggregate --json\n```\n\n`upstream collect` reads `.buildchain/buildchain.toml`, resolves declared\npackages from the caller repository, hashes declared evidence assets, and emits\na `kungfu-buildchain-kfd-upstream-aggregate` document. `upstream check` validates\nthat aggregate. `aggregate` combines the product's own Buildchain KFD status\nwith the upstream aggregate.\n\nThis works in development before the consuming repository has published an\nalpha or release. In that state Buildchain can collect and check upstream\nfacts, versions, hashes, roles, and residual risk, but the consuming product\nmust not claim its own KFD status as `passed` until a release passport verifies\nthat product release.\n\nThe repository-owned declaration is intentionally small. Consumers normally\ndeclare the upstream package identity, not Buildchain's inferred role or a\nduplicate semver:\n\n```toml\n[kfd.upstream]\nauto_discover = false\n\n[[kfd.upstream.components]]\nid = \"kfd\"\npackage = \"@kungfu-tech/kfd\"\nrepository = \"kungfu-systems/kfd\"\nevidence = [\n \"package:kfd.release.json\",\n \"package:.buildchain/kfd/kfd-1/contract-world.witness.json\",\n \"package:.buildchain/kfd/kfd-2/release-claims.json\",\n \"package:.buildchain/kfd/kfd-3/collaboration-interface.json\",\n \"package:standards.json\",\n]\n```\n\nThe upstream package version is a single source of truth owned by the package\nmanager. Put the dependency in `package.json` / the lockfile, then let\nBuildchain read the installed package's real `package.json`:\n\n```json\n{\n \"devDependencies\": {\n \"@kungfu-tech/kfd\": \"1.0.0-alpha.21\"\n }\n}\n```\n\nMost consumers should keep `@kungfu-tech/kfd` in `devDependencies`: Buildchain\nuses it during CI, development checks, release evidence collection, and site\ngeneration. Move it to `dependencies` only if the product's own runtime imports\nKFD directly. Buildchain itself keeps KFD in `dependencies` because its public\nCLI and Node API resolve KFD standards, schemas, taxonomy, and foundation trust\nfacts at runtime.\n\nDo not repeat upstream semver values in `.buildchain/buildchain.toml`. Repeating\nversions in both `package.json` and Buildchain config creates stale facts.\n`upstream collect` records the actual installed package version and evidence\nhashes in the aggregate output.\n\n`kfd_1`, `kfd_2`, `kfd_3`, and `kfd_4` are optional capability-state hints. When\nomitted, Buildchain treats the component as `declared`. Use explicit values only\nwhen the upstream package really exposes the corresponding machine evidence,\nfor example:\n\n```toml\nkfd_1 = \"exported-witness\"\nkfd_2 = \"exported-claim\"\nkfd_3 = \"exported-collaboration-interface\"\nkfd_4 = \"schema-metadata\"\n```\n\nAn upstream component may be `declared`, `aligned`, `exported-*`, or another\nexplicit non-passed state when the evidence is package-local. A component may\nclaim `passed` only when the aggregate also binds that component to a release\npassport. Upstream `passed` never upgrades the product's own KFD status; it only\ndescribes the upstream trust surface consumed by the product.\n\n### Upstream Roles\n\nConsumers should normally omit `role`. Buildchain owns the role vocabulary and\ninfers the role from package identity and evidence. The aggregate records:\n\n- `role` - the normalized Buildchain-managed role;\n- `roleSource` - `known-package`, `evidence`, `default`, or `explicit`;\n- `roleReason` - the machine-readable explanation for the chosen role.\n\nThe managed role registry is queryable:\n\n```bash\nbuildchain kfd upstream roles --json\n```\n\nCurrent roles are:\n\n| Role | Meaning |\n| --- | --- |\n| `standard-and-schema-provider` | Provides KFD standards, schemas, taxonomy, or standard-owned witness and claim facts. |\n| `release-passport-and-kfd-gate-provider` | Provides release passport, KFD gate, release claim, or release governance machinery consumed by the product. |\n| `kfd-aware-product-component` | A product component that exposes KFD witness, claim, collaboration-interface, or package evidence without being core KFD infrastructure. |\n| `site-consumption-provider` | Provides site-consumption facts such as site manifests, site bundles, or downstream page-content contracts. |\n| `unknown-kfd-upstream` | Fallback for a declared upstream that has not matched a Buildchain-known package or role-specific evidence. |\n\nIf a consumer explicitly writes `role`, it must be one of that registry. Unknown\nexplicit values fail closed during `upstream check`; Buildchain will not let\nrepositories invent local role spellings that later fragment aggregate reports.\n\nBuildchain dogfoods this model with `@kungfu-tech/kfd` as its upstream\nstandard-and-schema provider. The generated site bundle includes\n`dist/site/kfd-upstream-aggregate.json` so downstream sites and agents can read\nBuildchain's upstream KFD facts from the npm package instead of scraping\nrepository scripts.\n\n## KFD-3\n\nKFD-3 closes participant-facing collaboration surfaces over a declared public\ninterface. Buildchain supports two complementary KFD-3 layers.\n\nThe first layer is Buildchain self-verification. Buildchain reverse-enumerates\nreal CLI commands, reusable workflow inputs, action inputs, site pages, and\ndocumented command references, then compares those facts with the generated\nregistries in `dist/site/`. A missing registry entry fails `pnpm run check`.\n\nThe second layer is product surface registration. Products can ask Buildchain to\ndetect standard public surfaces, write a small product-owned registry, audit the\nregistry against the current artifact/source tree, generate a release-passport\ncompatible witness, and query the resulting capability map.\n\n## Shifu Discovery and Distribution Declarations\n\nBuildchain owns the repository-layout question; product tools must not copy its\ninternal paths. Shifu and other consumers use this sequence:\n\n1. read the welded `.buildchain-version` pin to select Buildchain;\n2. run `buildchain layout --cwd <repository> --json`;\n3. read the returned `kfd.registries[\"kfd-3\"].path`;\n4. treat a surface as Shifu-managed only when its declaration contains\n `distribution.registrar=\"shifu\"`.\n\nThe layout response uses the\n`kungfu-buildchain-layout-discovery` contract with an explicit schema version.\nChanging or removing its fields is a public contract change. Consumers must not\nfall back to a hard-coded registry location when the command is unavailable or\nreturns an unsupported contract.\n\nA Shifu distribution declaration must contain at least one task and one\nartifact. Every artifact declares `kind`, `platform`, and `pathGlob`; an\noptional `sha256` is a lowercase 64-character hexadecimal digest. This makes\nartifact form and platform machine-readable without asking Shifu to infer them\nfrom filenames:\n\n```json\n{\n \"distribution\": {\n \"registrar\": \"shifu\",\n \"tasks\": [\"binary:build\"],\n \"artifacts\": [\n {\n \"kind\": \"binary\",\n \"platform\": \"linux\",\n \"pathGlob\": \"dist/binary/example-x86_64-unknown-linux-gnu.tar.gz\"\n }\n ]\n }\n}\n```\n\nBuildchain validates this shape whenever a KFD-3 registry is read or written.\nRepositories that do not declare the registrar remain outside Shifu's\ndistribution jurisdiction.\n\n## Detected, Declared, Enforced\n\nKFD-3 surface registration uses three states.\n\n| State | Meaning |\n| --- | --- |\n| `detected` | Buildchain found a candidate public surface from package metadata, wheel metadata, CLI bins, binary artifacts, docs, or site bundle facts. |\n| `declared` | The product owner accepted that candidate into `.buildchain/kfd/kfd-3/surfaces.json`. |\n| `enforced` | The product has promoted a declared surface to a hard release boundary. Missing enforced surfaces fail release verification. |\n\nDetection does not silently become product intent. `register` is the boundary\ndecision. Existing consumers are unaffected until they opt in.\n\n## CLI\n\nInspect KFD-owned schema facts:\n\n```bash\nbuildchain kfd schema list --json\nbuildchain kfd schema show kfd-1 --json\nbuildchain kfd 4 schema --json\n```\n\nThe KFD schema namespace is discovered from `@kungfu-tech/kfd/standards.json`.\nFor KFD-2 this includes `trustClaims`, `trustAssessment`, `trustTaxonomy`,\n`releaseClaims`, and `releaseTrustPassport`. For KFD-4 Buildchain currently\nexposes the KFD-owned `observerPerspective` schema only.\n\nDetect public surface candidates:\n\n```bash\nbuildchain kfd 3 detect --json\nbuildchain kfd 3 detect --kind node-api --kind cli --json\n```\n\nRegister standard surface classes:\n\n```bash\nbuildchain kfd 3 register node-api --product Buildchain\nbuildchain kfd 3 register cli\nbuildchain kfd 3 register python-api --artifact dist/wheel-unpacked\n```\n\nAudit detected, declared, and enforced surfaces:\n\n```bash\nbuildchain kfd 3 audit --json\n```\n\nGenerate a witness for release passport collection:\n\n```bash\nbuildchain kfd 3 witness \\\n --kind prebuild \\\n --output .buildchain/kfd/kfd-3/collaboration-interface.prebuild.json\n```\n\nQuery capability facts for agents or downstream sites:\n\n```bash\nbuildchain kfd 3 query buildchain --json\nbuildchain kfd 3 query --passport .buildchain/release-passport/buildchain.release.json --json\n```\n\n## Node API\n\nThe CLI is a thin wrapper over the public Node API:\n\n```js\nimport {\n kfd1,\n kfd2,\n kfd3,\n kfd4,\n upstream,\n collectKfdAggregate,\n collectKfdStatus,\n collectKfdUpstreamFacts,\n checkKfdUpstreamFacts,\n listKfdUpstreamRoles,\n listKfdSchemas,\n readKfdSchema,\n} from \"@kungfu-tech/buildchain/kfd\";\n```\n\nAgents should start with `collectKfdStatus()` to learn which standards are\nimplemented and where the repository-owned Buildchain files live. For capability\nuse decisions, prefer `kfd3.queryCapabilities()`. The query result connects each\ncapability to:\n\n- KFD-3 surface identity and state;\n- KFD-1 basis facts such as source and artifact paths or digests;\n- KFD-2 trust evidence when a release passport is attached;\n- residual risk and recommended agent action.\n\n## Standard Detectors\n\nThe initial detector set is intentionally conservative:\n\n- npm packages: `package.json` `exports`, `main`, `types`, and `bin`;\n- Python wheels: unpacked `.dist-info/METADATA`, `RECORD`,\n `entry_points.txt`, and `top_level.txt`;\n- CLI binaries: `package.json#bin` and files under `bin/`;\n- standalone binaries and archives: common binary/archive outputs under\n artifact directories such as `dist/`;\n- documentation: `README.md`, `AGENTS.md`, and `docs/*.md`;\n- site bundles: `dist/site/*.json`.\n\nPython importability alone is not considered public API. A product can extend\nthe registry over time, but the first boundary is metadata-based.\n\n## Buildchain Self Dogfood\n\nBuildchain dogfoods this model in two ways:\n\n- `buildchain kfd 1 witness --json` generates Buildchain's own KFD-1 contract\n world witness;\n- `buildchain kfd 2 claims --json` generates Buildchain's own KFD-2 public\n claim evidence;\n- `buildchain kfd 2 trust-claims --json` and\n `buildchain kfd 2 trust-assessment --json` expose and validate the KFD\n package's foundation KFD-2 trust facts against the latest KFD taxonomy;\n- `dist/site/kfd-claims.json` declares Buildchain's own KFD-3 collaboration\n interface, including a Shifu-owned standalone binary distribution surface;\n- `buildchain kfd 3 query buildchain --json` resolves the packaged\n Buildchain capability map from that site fact source.\n\nThis lets downstream agents discover Buildchain's supported CLI, Node API,\nrelease passport, workflow, and site bundle surfaces from the npm package\ninstead of scraping source files or README examples.\n\n## Known Gaps\n\nArchive unpacking for `.whl`, `.tar.gz`, `.zip`, and platform-native installers\nis intentionally not part of the first detector. Callers can point\n`--artifact` at an unpacked artifact directory. Future Buildchain versions can\nadd archive readers without changing the registry contract."
|
|
668
678
|
},
|
|
669
679
|
{
|
|
670
680
|
"id": "manual:lifecycle-protocol",
|
|
@@ -678,7 +688,7 @@
|
|
|
678
688
|
],
|
|
679
689
|
"maturity": "stable",
|
|
680
690
|
"sourcePath": "docs/lifecycle-protocol.md",
|
|
681
|
-
"digest": "sha256:
|
|
691
|
+
"digest": "sha256:bef6f703a76667c731dccea6a0385b2196b5a23438ce4bc39894561530975f21",
|
|
682
692
|
"headings": [
|
|
683
693
|
{
|
|
684
694
|
"level": 1,
|
|
@@ -761,7 +771,7 @@
|
|
|
761
771
|
"anchor": "design-boundaries"
|
|
762
772
|
}
|
|
763
773
|
],
|
|
764
|
-
"markdown": "# Lifecycle Protocol\n\nBuildchain uses `.buildchain/buildchain.toml` as the v2 repository configuration format.\nThe file is optional for simple JavaScript repositories, but it is the preferred\nway to describe release version state and lifecycle commands when a project is\nnot a plain pnpm, npm, or yarn workspace.\n\nFor compatibility, Buildchain still reads a legacy root `buildchain.toml` when\n`.buildchain/buildchain.toml` is absent. New repositories should use the\n`.buildchain/` layout so all Buildchain-owned local state lives under one\ndirectory.\n\nOnly TOML is supported in v2. YAML, JSON, and JavaScript config files are not\nloaded.\n\n## Minimal File\n\n```toml\nschema = 1\n\n[version]\nrequired = true\n\n[[version.files]]\ntype = \"json\"\npath = \"package.json\"\nkey = \"version\"\n\n[lifecycle.verify]\ncommands = [\n \"pnpm run check\",\n]\n```\n\n`schema = 1` is required. Buildchain fails closed when the schema is missing or\nunknown.\n\n## Version State\n\nVersion state is the source file evidence that matches a release tag. During\npromotion, Buildchain writes the selected release or prerelease version into the\nconfigured files, verifies the resulting tree, creates a source version commit,\nthen moves exact and floating refs.\n\nSupported version file types:\n\n| Type | Use case | Required fields |\n| --- | --- | --- |\n| `json` | `package.json`, JSON manifests | `path`, `key` |\n| `toml` | `pyproject.toml`, other TOML manifests | `path`, `key` |\n| `regex` | `CMakeLists.txt`, `conanfile.py`, plain version files | `path`, `pattern`, `replacement` |\n\n`key` is a dotted key path:\n\n```toml\n[[version.files]]\ntype = \"toml\"\npath = \"pyproject.toml\"\nkey = \"project.version\"\n```\n\nConfigured JSON and TOML version files are semantic no-ops when the declared\nkey already equals the requested version. Buildchain preserves the repository's\noriginal TOML bytes in that case instead of serializing the whole document and\ncreating formatter-only release state. When a TOML version really changes,\nBuildchain applies a parser-verified lossless edit to that key and fails closed\nif it cannot prove a unique edit; unrelated arrays, comments, and formatting\nremain repository-owned.\n\nRegex files must expose the current version through a named capture group called\n`version`:\n\n```toml\n[[version.files]]\ntype = \"regex\"\npath = \"CMakeLists.txt\"\npattern = 'project\\([^)]* VERSION (?<version>[^ )]+)'\nreplacement = '${version}'\n```\n\nIf `version.required = true`, promotion fails when no configured version files\nare available.\n\n### Anchored Manual Versions\n\nSome repositories do not derive their package version from the Buildchain\nrelease tag. `libnode` is the canonical example: the package version is anchored\nto an explicitly selected upstream Node.js release such as `22.22.3-kf.0`, while\nthe channel line may be `release/v22/v22.22`.\n\nThose repositories can opt into anchored manual semantics:\n\n```toml\n[version]\nrequired = true\nstrategy = \"anchored\"\nnext = \"manual\"\nmanifest = \"libnode.release.json\"\n\n[[version.files]]\ntype = \"json\"\npath = \"package.json\"\nkey = \"version\"\n```\n\nWith `strategy = \"anchored\"` and `next = \"manual\"`:\n\n- Buildchain validates the configured version files and anchor manifest, but it\n does not rewrite those files to the Buildchain release tag.\n- `lifecycle.verify` is the project-owned truth gate. It should compare the\n package version, anchor manifest, and upstream source/submodule state.\n- release promotion still creates the exact/floating production refs for the\n current line;\n- release promotion does not auto-create the next alpha branch or tag;\n- the action output `next-anchor-required` is `true`, signaling that the next\n upstream anchor line must be created explicitly by the repository.\n\nThe configured anchor manifest must be JSON or TOML. Buildchain does not\ninterpret project-specific field names; it only loads the manifest and exposes\nits top-level fields to validation summaries and lifecycle environment:\n\n```text\nBUILDCHAIN_VERSION_STRATEGY=anchored\nBUILDCHAIN_VERSION_NEXT=manual\nBUILDCHAIN_ANCHOR_MANIFEST=libnode.release.json\nBUILDCHAIN_ANCHOR_MANIFEST_JSON={\"nodeTag\":\"v22.22.3\",...}\n```\n\nThe upstream anchor decision remains outside Buildchain. A future line such as\n`dev/v24/v24.xx` should be created by an explicit repository workflow or human\ndecision after the upstream version has been selected and checked in.\n\n## Lifecycle Stages\n\nLifecycle stages are declarative shell commands. A stage can use exactly one of:\n\n- `command`: one shell command;\n- `commands`: multiple shell commands run in order;\n- `script`: a multiline shell script.\n\nAny command failure fails the stage. `timeout_minutes`, `retries`, `shell`, and\n`env` can be attached to a stage.\n\nDuring version-state verification, Buildchain also sets `BUILDCHAIN_VERSION` to\nthe release or prerelease version being verified.\n\n```toml\n[lifecycle.install]\ntimeout_minutes = 10\nretries = 3\ncommands = [\n \"pnpm install --frozen-lockfile\",\n]\n\n[lifecycle.build]\ncommands = [\n \"pnpm run build\",\n \"pnpm run package\",\n]\n\n[lifecycle.verify]\nshell = \"bash\"\nscript = \"\"\"\nset -euo pipefail\npnpm run check\ngit diff --check\n\"\"\"\n```\n\nShared environment variables can be declared once:\n\n```toml\n[lifecycle.env]\nPYTHONUNBUFFERED = \"1\"\n```\n\nStage-specific environment variables override shared lifecycle environment:\n\n```toml\n[lifecycle.test]\ncommand = \"pytest\"\n\n[lifecycle.test.env]\nPYTHONPATH = \"src\"\n```\n\n### Publish Stage\n\n`lifecycle.publish` is the project-owned side-effect stage. It may call npm,\nPyPI, Conan, CMake packaging scripts, Docker/OCI registries, S3 uploaders, or\nany other publisher. Buildchain does not assume the tool; it assumes the\nevidence contract.\n\n```toml\n[lifecycle.publish]\nscript = \"\"\"\nset -euo pipefail\npython scripts/publish_wheels.py\nnode scripts/publish-images.mjs\nnode scripts/write-publish-evidence.mjs\n\"\"\"\n```\n\nWhen `actions/promote-buildchain-ref` runs with `publish-transaction: \"true\"`,\nthe publish stage receives the transaction identity plus the resolved publish\ncontract:\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\nBUILDCHAIN_PUBLISH_MODE\nBUILDCHAIN_PUBLISH_AUTH\nBUILDCHAIN_NPM_DIST_TAG\nBUILDCHAIN_PACKAGE_SET_ORDER\nBUILDCHAIN_PACKAGE_SET_MAIN_PACKAGE\n```\n\nThe stage must write publish evidence JSON. Buildchain validates that evidence\nbefore exact tags and floating refs move. In GitHub Actions, the promotion\naction also persists `state.json` and `evidence.json` to\n`refs/heads/buildchain/release-state/<version>` so fresh runners can recover\nwithout local workspace residue. See\n[`docs/publish-transaction.md`](publish-transaction.md) for the state machine,\nevidence schema, and recovery commands.\n\nFor npm packages, prefer:\n\n```toml\n[publish]\nmode = \"publish-final-version\"\nauth = \"trusted-publishing\"\ndist_tag = \"latest\"\n```\n\nUse `mode = \"promote-existing-version\"` only for explicit same-version\ndist-tag recovery, and pair it with `auth = \"npm-token\"`. Trusted Publishing\ndoes not authorize `npm dist-tag add`; Buildchain fails that combination before\nany publish transaction side effect.\n\n## Promotion Semantics\n\n`actions/promote-buildchain-ref` consumes `version.files`, `lifecycle.verify`,\nand optionally `lifecycle.publish`.\n\nThe verify stage runs after Buildchain has applied the generated version-state\nchanges to the local checkout, and before it creates release commits or moves\nrefs. After the command finishes, Buildchain checks that only declared\nversion-state files changed. This prevents verification from quietly adding\nextra source changes to the release commit.\n\nBuildchain-owned untracked runtime evidence is excluded only through an exact\ninternal allowlist. This includes contract-drift issue material under\n`.buildchain/contract-drift/` and the paper workflow's\n`.buildchain/publication-result.json`, alongside release-candidate, passport,\nrelease-state, KFD, and runtime evidence directories. Tracked changes, ordinary\nsource files, and undeclared `.buildchain/*` paths still fail version\nverification.\n\nOn protected alpha and release branches, the generated version-state commit is\napplied by the promotion automation after the reviewed channel PR has merged.\nBuildchain keeps review requirements, conversation resolution, strict status\nchecks, and admin enforcement for human channel changes, but adds the\nauthenticated promotion token user or app to the managed bypass allowlist for\ngenerated release bookkeeping. Buildchain also creates the configured required\ncheck on the exact generated version-state commit before patching the protected\nref, then applies the protected ref update with the declared generated ref\nupdate token. The reusable wrapper uses\n`secrets.BUILDCHAIN_PROMOTION_TOKEN || github.token` for that protected\nbookkeeping update. If release finalization bookkeeping is still rejected,\nBuildchain creates or reuses a same-repository `buildchain/version-state/*` PR\nfrom the current target channel head and reports `finalization-needed=true` so\na later idempotent promotion run can resume. Strict alpha bookkeeping remains\nfail-fast with a token/protection diagnostic instead of asking humans to review\na post-publish version-state PR.\n\nFor `version.strategy = \"anchored\"` with `version.next = \"manual\"`, release\npromotion does not generate a Buildchain-owned version-state commit. In that\nmode, a protected `alpha -> release` PR may carry the declared `version.files`\nfrom the tested alpha package version to the final package version, and may\ncarry the configured `version.manifest` with it. Buildchain only accepts that\nrelease tree difference when the PR is the valid channel-promotion PR, the\nchanged paths are limited to those declared version files plus the anchor\nmanifest, and `lifecycle.verify` or `verification-command` has validated the\nchecked-out release material. Any code or undeclared file change still fails the\nrelease tree gate.\n\nThe action input `verification-command` remains supported. When it is provided,\nit overrides `lifecycle.verify` for that invocation. The override inherits\n`[lifecycle.env]` and `lifecycle.verify.env`; when the configured stage declares\n`shell`, it also inherits that shell. If the stage has no explicit shell,\nBuildchain preserves the platform-default shell for compatibility.\n\n## Migration Preflight\n\nHeavy repositories can validate their Buildchain declaration before they are\nready to run the real build. `actions/validate-config` checks that\n`.buildchain/buildchain.toml` parses, configured version-state files exist, configured\nversion keys are strings, and required lifecycle stage names are declared.\nFor web-surface repositories it also validates `project`, `channels`, `deploy`,\n`retention`, and `security` declarations.\n\nIt does not run lifecycle commands. This is useful for repositories such as\n`libnode`, where `lifecycle.build` represents an expensive multi-platform native\nbuild and the first migration milestone is to prove the release metadata and\nlifecycle protocol without consuming build runners.\n\n```yaml\n- uses: kungfu-systems/buildchain/actions/validate-config@v2\n with:\n require-version-state: \"true\"\n require-lifecycle-stages: \"install,build,verify\"\n```\n\nWeb-surface repositories can use the same action without requiring version\nstate:\n\n```yaml\n- uses: kungfu-systems/buildchain/actions/validate-config@v2\n with:\n require-lifecycle-stages: \"build,verify\"\n```\n\nThe action exposes project and deploy metadata through outputs such as\n`project-type`, `project-site`, `channels`, and `deploy-adapters-json`.\n\n## Web-Surface Projects\n\n`project.type = \"web-surface\"` is for sites, docs, browser apps, and operator\nconsoles whose release object is a deployed surface, not a package version.\n\n```toml\nschema = 1\n\n[project]\ntype = \"web-surface\"\nname = \"site-libkungfu-dev\"\nsite = \"libkungfu-dev\"\n\n[channels.preview]\nurl_pattern = \"https://{alias}.preview.libkungfu.dev\"\nvisibility = \"ephemeral\"\nnoindex = true\n\n[channels.staging]\nurl = \"https://staging.libkungfu.dev\"\nvisibility = \"protected\"\naccess_control = \"managed-network\"\nedge_auth = \"none\"\nnoindex = true\npromotable = true\n\n[channels.production]\nurl = \"https://libkungfu.dev\"\nvisibility = \"public\"\ncanonical = true\nnoindex = false\n\n[surfaces.hub]\npath = \"/\"\nproduction_url = \"https://libkungfu.dev\"\nstaging_url = \"https://staging.libkungfu.dev\"\npreview_url_pattern = \"https://{alias}.preview.libkungfu.dev\"\n\n[surfaces.core]\npath = \"/core/\"\nproduction_url = \"https://core.libkungfu.dev\"\nstaging_url = \"https://core.staging.libkungfu.dev\"\npreview_url_pattern = \"https://core-{alias}.preview.libkungfu.dev\"\n\n[deploy.production]\nadapter = \"aws-s3-cloudfront\"\nbucket = \"libkungfu-dev-production\"\nartifact_path = \"dist\"\nsecret_refs = [\"AWS_ROLE_ARN\"]\n```\n\nSee [Web-surface deployments](web-surface-deployments.md) for named surface host\nmappings, the manifest, preview alias, retention, cleanup, and dry-run deploy\ncontract.\n\n## Infra-Contract Projects\n\n`project.type = \"infra-contract\"` is for infrastructure contract repositories\nthat need provider-neutral desired, plan, approval, apply, observe, contract,\nand propagation evidence. `buildchain init --type infra-contract` wires\n`lifecycle.verify` to `buildchain infra-contract --mode ci`, which writes\nmutation-free plan, contract, propagation dry-run, evidence bundle, and\nverification artifacts under `.buildchain/`. The surface supports\nmanual-observed, observe-only, and mocked adapter fixtures without reading\ncloud state files or executing live infrastructure mutation. See\n[Infra Contract](infra-contract.md).\n\n## Examples\n\n### Node Workspace\n\n```toml\nschema = 1\n\n[version]\nrequired = true\n\n[[version.files]]\ntype = \"json\"\npath = \"package.json\"\nkey = \"version\"\n\n[lifecycle.verify]\ncommands = [\n \"pnpm run check\",\n]\n```\n\n### Python Package\n\n```toml\nschema = 1\n\n[version]\nrequired = true\n\n[[version.files]]\ntype = \"toml\"\npath = \"pyproject.toml\"\nkey = \"project.version\"\n\n[lifecycle.install]\ncommand = \"python -m pip install -e .[test]\"\n\n[lifecycle.build]\ncommand = \"python -m build\"\n\n[lifecycle.verify]\ncommands = [\n \"python -m build\",\n \"pytest\",\n]\n```\n\n### CMake and Conan\n\n```toml\nschema = 1\n\n[[version.files]]\ntype = \"regex\"\npath = \"CMakeLists.txt\"\npattern = 'project\\([^)]* VERSION (?<version>[^ )]+)'\nreplacement = '${version}'\n\n[lifecycle.configure]\ncommands = [\n \"conan install . --build=missing\",\n \"cmake -S . -B build -DCMAKE_BUILD_TYPE=Release\",\n]\n\n[lifecycle.build]\ncommand = \"cmake --build build --config Release\"\n\n[lifecycle.verify]\ncommands = [\n \"cmake --build build --config Release\",\n \"ctest --test-dir build --output-on-failure\",\n]\n```\n\n### Docker Image\n\n```toml\nschema = 1\n\n[[version.files]]\ntype = \"json\"\npath = \"package.json\"\nkey = \"version\"\n\n[lifecycle.build]\ncommand = \"docker build -f Dockerfile -t kungfutrader/example:${BUILDCHAIN_VERSION} .\"\n\n[lifecycle.verify]\ncommand = \"docker build -f Dockerfile -t kungfutrader/example:verify .\"\n```\n\nDocker publishing is an external side effect and should be gated by a release\nworkflow after version-state promotion has been verified.\n\n## Design Boundaries\n\nThe lifecycle protocol is also the command source for the reusable build\nsurface. `.github/workflows/.build.yml` runs `lifecycle.install`,\n`lifecycle.build`, and `lifecycle.verify` by default, while allowing callers to\noverride each stage with explicit workflow inputs. The underlying\n`actions/run-lifecycle` action can be used directly by repositories that need a\ncustom workflow but still want Buildchain's lifecycle and deterministic manifest\ncontract.\n\nBuildchain lifecycle commands are data, not executable configuration files.\nThey make release behavior reviewable in pull requests and keep the release\nfact chain simple:\n\n1. choose the channel branch and release line;\n2. generate a source version commit from declared version files;\n3. verify that exact tree;\n4. move exact tags and floating refs only after verification succeeds;\n5. run publish or deployment side effects in separately gated workflows."
|
|
774
|
+
"markdown": "# Lifecycle Protocol\n\nBuildchain uses `.buildchain/buildchain.toml` as the v2 repository configuration format.\nThe file is optional for simple JavaScript repositories, but it is the preferred\nway to describe release version state and lifecycle commands when a project is\nnot a plain pnpm, npm, or yarn workspace.\n\nFor compatibility, Buildchain still reads a legacy root `buildchain.toml` when\n`.buildchain/buildchain.toml` is absent. New repositories should use the\n`.buildchain/` layout so all Buildchain-owned local state lives under one\ndirectory.\n\nOnly TOML is supported in v2. YAML, JSON, and JavaScript config files are not\nloaded.\n\n## Minimal File\n\n```toml\nschema = 1\n\n[version]\nrequired = true\n\n[[version.files]]\ntype = \"json\"\npath = \"package.json\"\nkey = \"version\"\n\n[lifecycle.verify]\ncommands = [\n \"pnpm run check\",\n]\n```\n\n`schema = 1` is required. Buildchain fails closed when the schema is missing or\nunknown.\n\n## Version State\n\nVersion state is the source file evidence that matches a release tag. During\npromotion, Buildchain writes the selected release or prerelease version into the\nconfigured files, verifies the resulting tree, creates a source version commit,\nthen moves exact and floating refs.\n\nSupported version file types:\n\n| Type | Use case | Required fields |\n| --- | --- | --- |\n| `json` | `package.json`, JSON manifests | `path`, `key` |\n| `toml` | `pyproject.toml`, other TOML manifests | `path`, `key` |\n| `regex` | `CMakeLists.txt`, `conanfile.py`, plain version files | `path`, `pattern`, `replacement` |\n\n`key` is a dotted key path:\n\n```toml\n[[version.files]]\ntype = \"toml\"\npath = \"pyproject.toml\"\nkey = \"project.version\"\n```\n\nConfigured JSON and TOML version files are semantic no-ops when the declared\nkey already equals the requested version. Buildchain preserves the repository's\noriginal TOML bytes in that case instead of serializing the whole document and\ncreating formatter-only release state. When a TOML version really changes,\nBuildchain applies a parser-verified lossless edit to that key and fails closed\nif it cannot prove a unique edit; unrelated arrays, comments, and formatting\nremain repository-owned.\n\nRegex files must expose the current version through a named capture group called\n`version`:\n\n```toml\n[[version.files]]\ntype = \"regex\"\npath = \"CMakeLists.txt\"\npattern = 'project\\([^)]* VERSION (?<version>[^ )]+)'\nreplacement = '${version}'\n```\n\nIf `version.required = true`, promotion fails when no configured version files\nare available.\n\n### Anchored Manual Versions\n\nSome repositories do not derive their package version from the Buildchain\nrelease tag. `libnode` is the canonical example: the package version is anchored\nto an explicitly selected upstream Node.js release such as `22.22.3-kf.0`, while\nthe channel line may be `release/v22/v22.22`.\n\nThose repositories can opt into anchored manual semantics:\n\n```toml\n[version]\nrequired = true\nstrategy = \"anchored\"\nnext = \"manual\"\nmanifest = \"libnode.release.json\"\n\n[[version.files]]\ntype = \"json\"\npath = \"package.json\"\nkey = \"version\"\n```\n\nWith `strategy = \"anchored\"` and `next = \"manual\"`:\n\n- Buildchain validates the configured version files and anchor manifest, but it\n does not rewrite those files to the Buildchain release tag.\n- `lifecycle.verify` is the project-owned truth gate. It should compare the\n package version, anchor manifest, and upstream source/submodule state.\n- release promotion still creates the exact/floating production refs for the\n current line;\n- release promotion does not auto-create the next alpha branch or tag;\n- the action output `next-anchor-required` is `true`, signaling that the next\n upstream anchor line must be created explicitly by the repository.\n\nThe configured anchor manifest must be JSON or TOML. Buildchain does not\ninterpret project-specific field names; it only loads the manifest and exposes\nits top-level fields to validation summaries and lifecycle environment:\n\n```text\nBUILDCHAIN_VERSION_STRATEGY=anchored\nBUILDCHAIN_VERSION_NEXT=manual\nBUILDCHAIN_ANCHOR_MANIFEST=libnode.release.json\nBUILDCHAIN_ANCHOR_MANIFEST_JSON={\"nodeTag\":\"v22.22.3\",...}\n```\n\nThe upstream anchor decision remains outside Buildchain. A future line such as\n`dev/v24/v24.xx` should be created by an explicit repository workflow or human\ndecision after the upstream version has been selected and checked in.\n\n## Lifecycle Stages\n\nLifecycle stages are declarative shell commands. A stage can use exactly one of:\n\n- `command`: one shell command;\n- `commands`: multiple shell commands run in order;\n- `script`: a multiline shell script.\n\nAny command failure fails the stage. `timeout_minutes`, `retries`, `shell`, and\n`env` can be attached to a stage.\n\nDuring version-state verification, Buildchain also sets `BUILDCHAIN_VERSION` to\nthe release or prerelease version being verified.\n\n```toml\n[lifecycle.install]\ntimeout_minutes = 10\nretries = 3\ncommands = [\n \"pnpm install --frozen-lockfile\",\n]\n\n[lifecycle.build]\ncommands = [\n \"pnpm run build\",\n \"pnpm run package\",\n]\n\n[lifecycle.check]\ncommand = \"pnpm run check:source\"\n\n[lifecycle.verify]\nshell = \"bash\"\nscript = \"\"\"\nset -euo pipefail\npnpm run check\ngit diff --check\n\"\"\"\n```\n\n`lifecycle.check` is the repository-owned source-acceptance gate. It should\nvalidate the checked-out source revision without entering the build, artifact,\nor release lifecycle. Consumers can run it on GitHub-hosted Linux through\n`.github/workflows/check.yml@v2` with `mode: source`; the reusable workflow runs\nonly `lifecycle.install` and `lifecycle.check`. The default `mode: verify`\ncontinues to run `lifecycle.install` and `lifecycle.verify` for existing callers.\nThe reusable job name remains `check`, and `upload-artifacts: false` disables\nevidence upload without changing the job conclusion used by branch protection.\n\nShared environment variables can be declared once:\n\n```toml\n[lifecycle.env]\nPYTHONUNBUFFERED = \"1\"\n```\n\nStage-specific environment variables override shared lifecycle environment:\n\n```toml\n[lifecycle.test]\ncommand = \"pytest\"\n\n[lifecycle.test.env]\nPYTHONPATH = \"src\"\n```\n\n### Publish Stage\n\n`lifecycle.publish` is the project-owned side-effect stage. It may call npm,\nPyPI, Conan, CMake packaging scripts, Docker/OCI registries, S3 uploaders, or\nany other publisher. Buildchain does not assume the tool; it assumes the\nevidence contract.\n\n```toml\n[lifecycle.publish]\nscript = \"\"\"\nset -euo pipefail\npython scripts/publish_wheels.py\nnode scripts/publish-images.mjs\nnode scripts/write-publish-evidence.mjs\n\"\"\"\n```\n\nWhen `actions/promote-buildchain-ref` runs with `publish-transaction: \"true\"`,\nthe publish stage receives the transaction identity plus the resolved publish\ncontract:\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\nBUILDCHAIN_PUBLISH_MODE\nBUILDCHAIN_PUBLISH_AUTH\nBUILDCHAIN_NPM_DIST_TAG\nBUILDCHAIN_PACKAGE_SET_ORDER\nBUILDCHAIN_PACKAGE_SET_MAIN_PACKAGE\n```\n\nThe stage must write publish evidence JSON. Buildchain validates that evidence\nbefore exact tags and floating refs move. In GitHub Actions, the promotion\naction also persists `state.json` and `evidence.json` to\n`refs/heads/buildchain/release-state/<version>` so fresh runners can recover\nwithout local workspace residue. See\n[`docs/publish-transaction.md`](publish-transaction.md) for the state machine,\nevidence schema, and recovery commands.\n\nFor npm packages, prefer:\n\n```toml\n[publish]\nmode = \"publish-final-version\"\nauth = \"trusted-publishing\"\ndist_tag = \"latest\"\n```\n\nUse `mode = \"promote-existing-version\"` only for explicit same-version\ndist-tag recovery, and pair it with `auth = \"npm-token\"`. Trusted Publishing\ndoes not authorize `npm dist-tag add`; Buildchain fails that combination before\nany publish transaction side effect.\n\n## Promotion Semantics\n\n`actions/promote-buildchain-ref` consumes `version.files`, `lifecycle.verify`,\nand optionally `lifecycle.publish`.\n\nThe verify stage runs after Buildchain has applied the generated version-state\nchanges to the local checkout, and before it creates release commits or moves\nrefs. After the command finishes, Buildchain checks that only declared\nversion-state files changed. This prevents verification from quietly adding\nextra source changes to the release commit.\n\nBuildchain-owned untracked runtime evidence is excluded only through an exact\ninternal allowlist. This includes contract-drift issue material under\n`.buildchain/contract-drift/` and the paper workflow's\n`.buildchain/publication-result.json`, alongside release-candidate, passport,\nrelease-state, KFD, and runtime evidence directories. Tracked changes, ordinary\nsource files, and undeclared `.buildchain/*` paths still fail version\nverification.\n\nOn protected alpha and release branches, the generated version-state commit is\napplied by the promotion automation after the reviewed channel PR has merged.\nBuildchain keeps review requirements, conversation resolution, strict status\nchecks, and admin enforcement for human channel changes, but adds the\nauthenticated promotion token user or app to the managed bypass allowlist for\ngenerated release bookkeeping. Buildchain also creates the configured required\ncheck on the exact generated version-state commit before patching the protected\nref, then applies the protected ref update with the declared generated ref\nupdate token. The reusable wrapper uses\n`secrets.BUILDCHAIN_PROMOTION_TOKEN || github.token` for that protected\nbookkeeping update. If release finalization bookkeeping is still rejected,\nBuildchain creates or reuses a same-repository `buildchain/version-state/*` PR\nfrom the current target channel head and reports `finalization-needed=true` so\na later idempotent promotion run can resume. Strict alpha bookkeeping remains\nfail-fast with a token/protection diagnostic instead of asking humans to review\na post-publish version-state PR.\n\nFor `version.strategy = \"anchored\"` with `version.next = \"manual\"`, release\npromotion does not generate a Buildchain-owned version-state commit. In that\nmode, a protected `alpha -> release` PR may carry the declared `version.files`\nfrom the tested alpha package version to the final package version, and may\ncarry the configured `version.manifest` with it. Buildchain only accepts that\nrelease tree difference when the PR is the valid channel-promotion PR, the\nchanged paths are limited to those declared version files plus the anchor\nmanifest, and `lifecycle.verify` or `verification-command` has validated the\nchecked-out release material. Any code or undeclared file change still fails the\nrelease tree gate.\n\nThe action input `verification-command` remains supported. When it is provided,\nit overrides `lifecycle.verify` for that invocation. The override inherits\n`[lifecycle.env]` and `lifecycle.verify.env`; when the configured stage declares\n`shell`, it also inherits that shell. If the stage has no explicit shell,\nBuildchain preserves the platform-default shell for compatibility.\n\n## Migration Preflight\n\nHeavy repositories can validate their Buildchain declaration before they are\nready to run the real build. `actions/validate-config` checks that\n`.buildchain/buildchain.toml` parses, configured version-state files exist, configured\nversion keys are strings, and required lifecycle stage names are declared.\nFor web-surface repositories it also validates `project`, `channels`, `deploy`,\n`retention`, and `security` declarations.\n\nIt does not run lifecycle commands. This is useful for repositories such as\n`libnode`, where `lifecycle.build` represents an expensive multi-platform native\nbuild and the first migration milestone is to prove the release metadata and\nlifecycle protocol without consuming build runners.\n\n```yaml\n- uses: kungfu-systems/buildchain/actions/validate-config@v2\n with:\n require-version-state: \"true\"\n require-lifecycle-stages: \"install,build,verify\"\n```\n\nWeb-surface repositories can use the same action without requiring version\nstate:\n\n```yaml\n- uses: kungfu-systems/buildchain/actions/validate-config@v2\n with:\n require-lifecycle-stages: \"build,verify\"\n```\n\nThe action exposes project and deploy metadata through outputs such as\n`project-type`, `project-site`, `channels`, and `deploy-adapters-json`.\n\n## Web-Surface Projects\n\n`project.type = \"web-surface\"` is for sites, docs, browser apps, and operator\nconsoles whose release object is a deployed surface, not a package version.\n\n```toml\nschema = 1\n\n[project]\ntype = \"web-surface\"\nname = \"site-libkungfu-dev\"\nsite = \"libkungfu-dev\"\n\n[channels.preview]\nurl_pattern = \"https://{alias}.preview.libkungfu.dev\"\nvisibility = \"ephemeral\"\nnoindex = true\n\n[channels.staging]\nurl = \"https://staging.libkungfu.dev\"\nvisibility = \"protected\"\naccess_control = \"managed-network\"\nedge_auth = \"none\"\nnoindex = true\npromotable = true\n\n[channels.production]\nurl = \"https://libkungfu.dev\"\nvisibility = \"public\"\ncanonical = true\nnoindex = false\n\n[surfaces.hub]\npath = \"/\"\nproduction_url = \"https://libkungfu.dev\"\nstaging_url = \"https://staging.libkungfu.dev\"\npreview_url_pattern = \"https://{alias}.preview.libkungfu.dev\"\n\n[surfaces.core]\npath = \"/core/\"\nproduction_url = \"https://core.libkungfu.dev\"\nstaging_url = \"https://core.staging.libkungfu.dev\"\npreview_url_pattern = \"https://core-{alias}.preview.libkungfu.dev\"\n\n[deploy.production]\nadapter = \"aws-s3-cloudfront\"\nbucket = \"libkungfu-dev-production\"\nartifact_path = \"dist\"\nsecret_refs = [\"AWS_ROLE_ARN\"]\n```\n\nSee [Web-surface deployments](web-surface-deployments.md) for named surface host\nmappings, the manifest, preview alias, retention, cleanup, and dry-run deploy\ncontract.\n\n## Infra-Contract Projects\n\n`project.type = \"infra-contract\"` is for infrastructure contract repositories\nthat need provider-neutral desired, plan, approval, apply, observe, contract,\nand propagation evidence. `buildchain init --type infra-contract` wires\n`lifecycle.verify` to `buildchain infra-contract --mode ci`, which writes\nmutation-free plan, contract, propagation dry-run, evidence bundle, and\nverification artifacts under `.buildchain/`. The surface supports\nmanual-observed, observe-only, and mocked adapter fixtures without reading\ncloud state files or executing live infrastructure mutation. See\n[Infra Contract](infra-contract.md).\n\n## Examples\n\n### Node Workspace\n\n```toml\nschema = 1\n\n[version]\nrequired = true\n\n[[version.files]]\ntype = \"json\"\npath = \"package.json\"\nkey = \"version\"\n\n[lifecycle.verify]\ncommands = [\n \"pnpm run check\",\n]\n```\n\n### Python Package\n\n```toml\nschema = 1\n\n[version]\nrequired = true\n\n[[version.files]]\ntype = \"toml\"\npath = \"pyproject.toml\"\nkey = \"project.version\"\n\n[lifecycle.install]\ncommand = \"python -m pip install -e .[test]\"\n\n[lifecycle.build]\ncommand = \"python -m build\"\n\n[lifecycle.verify]\ncommands = [\n \"python -m build\",\n \"pytest\",\n]\n```\n\n### CMake and Conan\n\n```toml\nschema = 1\n\n[[version.files]]\ntype = \"regex\"\npath = \"CMakeLists.txt\"\npattern = 'project\\([^)]* VERSION (?<version>[^ )]+)'\nreplacement = '${version}'\n\n[lifecycle.configure]\ncommands = [\n \"conan install . --build=missing\",\n \"cmake -S . -B build -DCMAKE_BUILD_TYPE=Release\",\n]\n\n[lifecycle.build]\ncommand = \"cmake --build build --config Release\"\n\n[lifecycle.verify]\ncommands = [\n \"cmake --build build --config Release\",\n \"ctest --test-dir build --output-on-failure\",\n]\n```\n\n### Docker Image\n\n```toml\nschema = 1\n\n[[version.files]]\ntype = \"json\"\npath = \"package.json\"\nkey = \"version\"\n\n[lifecycle.build]\ncommand = \"docker build -f Dockerfile -t kungfutrader/example:${BUILDCHAIN_VERSION} .\"\n\n[lifecycle.verify]\ncommand = \"docker build -f Dockerfile -t kungfutrader/example:verify .\"\n```\n\nDocker publishing is an external side effect and should be gated by a release\nworkflow after version-state promotion has been verified.\n\n## Design Boundaries\n\nThe lifecycle protocol is also the command source for the reusable build\nsurface. `.github/workflows/.build.yml` runs `lifecycle.install`,\n`lifecycle.build`, and `lifecycle.verify` by default, while allowing callers to\noverride each stage with explicit workflow inputs. The underlying\n`actions/run-lifecycle` action can be used directly by repositories that need a\ncustom workflow but still want Buildchain's lifecycle and deterministic manifest\ncontract.\n\nBuildchain lifecycle commands are data, not executable configuration files.\nThey make release behavior reviewable in pull requests and keep the release\nfact chain simple:\n\n1. choose the channel branch and release line;\n2. generate a source version commit from declared version files;\n3. verify that exact tree;\n4. move exact tags and floating refs only after verification succeeds;\n5. run publish or deployment side effects in separately gated workflows."
|
|
765
775
|
},
|
|
766
776
|
{
|
|
767
777
|
"id": "manual:map",
|
|
@@ -775,7 +785,7 @@
|
|
|
775
785
|
],
|
|
776
786
|
"maturity": "stable",
|
|
777
787
|
"sourcePath": "docs/MAP.md",
|
|
778
|
-
"digest": "sha256:
|
|
788
|
+
"digest": "sha256:0735009b21cea9227f2c9b9bcbec1219898f4d211776b60aa030ace65821ec80",
|
|
779
789
|
"headings": [
|
|
780
790
|
{
|
|
781
791
|
"level": 1,
|
|
@@ -803,7 +813,7 @@
|
|
|
803
813
|
"anchor": "how-this-map-is-maintained"
|
|
804
814
|
}
|
|
805
815
|
],
|
|
806
|
-
"markdown": "# Documentation Map\n\nStart here. Find the question you have; follow it to the document that answers\nit. This map is meant to be readable by both a person skimming for the right doc\nand an agent grounding a specific claim.\n\nEach row carries a **plane** - *why* (intent / rationale), *verify* (trust the\nrunning artifact), *use* (consume / extend) - and a **status**:\n\n- `stable` - current and holds.\n- `draft` - exists, rough or incomplete.\n- `to write` - planned; the material exists but is not yet a single doc.\n- `retired` - intentionally not part of the active Buildchain v2 surface.\n\n## Capability Coverage\n\nThis package should be usable by an agent from the npm artifact alone. The\nmachine-readable `dist/site/` bundle is the first fact source; the Markdown\nmanuals explain those facts and give operator examples.\n\n`dist/site/capability-registry.json` is the capability navigation entrypoint.\nIt groups the public surface into stable product areas so sites and agents do\nnot have to infer structure from file names. Each page, manual, CLI command,\nworkflow, action, and Node API export also carries a `capabilityGroup`,\n`audience`, and `maturity` field in its own registry.\n\n| Capability group | Primary facts | Primary manuals |\n| --- | --- | --- |\n| Getting Started | `capability-registry.json`, `product-mechanism.json` | [`install.md`](install.md), [`product-mechanism.md`](product-mechanism.md), [`cli.md`](cli.md) |\n| Release Passport and Trust | `release-model.json`, `artifact-schemas.json`, `kfd-claims.json` | [`release-passport.md`](release-passport.md), [`release-candidate.md`](release-candidate.md), [`publish-transaction.md`](publish-transaction.md), [`binary-distribution.md`](binary-distribution.md) |\n| Reusable Build and Lifecycle | `workflow-registry.json`, `release-model.json` | [`reusable-build-surface.md`](reusable-build-surface.md), [`lifecycle-protocol.md`](lifecycle-protocol.md) |\n| KFD Trust and Surface Closure | `kfd-claims.json`, `public-surface-audit.json`, `cli-registry.json`, `node-api-registry.json` | [`kfd-support.md`](kfd-support.md), [`release-passport.md`](release-passport.md) |\n| Site Bundle, Web Surfaces, and Propagation | `buildchain-site.json`, `site-manifest.json`, `page-registry.json`, `release-model.json` | [`site-bundle-contract.md`](site-bundle-contract.md), [`web-surface-deployments.md`](web-surface-deployments.md), [`release-propagation.md`](release-propagation.md) |\n| Publication Artifacts | `publication-registry.json`, `workflow-registry.json`, `node-api-registry.json`, `manual-registry.json`, `kungfu-buildchain-publication-artifact-registry` | [`publication-artifacts.md`](publication-artifacts.md), [`reusable-build-surface.md`](reusable-build-surface.md) |\n| Distribution Indexes and Badges | `badge-endpoint-registry.json`, `node-api-registry.json`, `manual-registry.json` | [`readme-badges.md`](readme-badges.md), [`homebrew.md`](homebrew.md) |\n| Build Facts, Observability, and Diagnostics | `cli-registry.json`, `node-api-registry.json`, lifecycle artifacts | [`build-facts.md`](build-facts.md), [`toolkit-observability.md`](toolkit-observability.md), [`consumer-issue-reporting.md`](consumer-issue-reporting.md) |\n| Governance, Versioning, and Runtime Drift | `buildchain-contract.json`, `workflow-registry.json`, `release-model.json` | [`release-governance.md`](release-governance.md), [`release-flow.md`](release-flow.md), [`versioning.md`](versioning.md), [`runtime-train-validation.md`](runtime-train-validation.md) |\n| CLI and Node API Reference | `cli-registry.json`, `node-api-registry.json`, `workflow-registry.json`, `manual-registry.json` | [`cli.md`](cli.md), [`../packages/core/README.md`](../packages/core/README.md) |\n\n| Capability | Machine-readable entry | Manual entry |\n| --- | --- | --- |\n| Capability-grouped KFD navigation | `dist/site/capability-registry.json`, `dist/site/page-registry.json`, `dist/site/manual-registry.json`, `dist/site/cli-registry.json`, `dist/site/node-api-registry.json` | this map, [`site-bundle-contract.md`](site-bundle-contract.md), [`kfd-support.md`](kfd-support.md) |\n| KFD-1 / KFD-2 / KFD-3 release-passport gates | `dist/site/kfd-claims.json`, `dist/site/buildchain-contract.json`, `dist/site/artifact-schemas.json` | [`release-passport.md`](release-passport.md) |\n| KFD-3 public surface reverse audit | `dist/site/public-surface-audit.json`, `dist/site/cli-registry.json`, `dist/site/workflow-registry.json`, `dist/site/page-registry.json` | [`cli.md`](cli.md), [`site-bundle-contract.md`](site-bundle-contract.md) |\n| KFD-1 / KFD-2 / KFD-3 first-class CLI and Node API | `.buildchain/kfd/kfd-3/surfaces.json`, `dist/site/kfd-claims.json`, `buildchain.release.json`, KFD schemas from `@kungfu-tech/kfd` | [`kfd-support.md`](kfd-support.md), [`cli.md`](cli.md#commands) |\n| Floating `@v2` drift detection and compatibility issues | `dist/site/buildchain-contract.json` | [`reusable-build-surface.md`](reusable-build-surface.md#floating-ref-contract-lock) |\n| npm publish transactions, evidence, dist-tags, and recovery | `dist/site/release-model.json`, `dist/site/artifact-schemas.json` | [`publish-transaction.md`](publish-transaction.md) |\n| Git/source/version/module/product build facts | `dist/site/node-api-registry.json`, `dist/site/cli-registry.json`, `kungfu-buildchain-module-build-facts`, `kungfu-buildchain-product-build-facts` | [`build-facts.md`](build-facts.md) |\n| GitHub Release passport/evidence publication | `dist/site/release-model.json`, `dist/site/artifact-schemas.json` | [`release-governance.md`](release-governance.md), [`release-candidate.md`](release-candidate.md) |\n| release propagation for package/publication/site chains | `dist/site/release-model.json` | [`release-propagation.md`](release-propagation.md) |\n| publication artifact manifests, immutable archive registries, source bundles, and paper repository workflows | `dist/site/publication-registry.json`, `dist/site/workflow-registry.json`, `dist/site/node-api-registry.json`, `kungfu-buildchain-publication-artifact-manifest`, `kungfu-buildchain-publication-artifact-registry` | [`publication-artifacts.md`](publication-artifacts.md) |\n| Generated badge bundles, README badge blocks, and badge facts | `dist/site/node-api-registry.json`, `dist/site/manual-registry.json`, `kungfu-buildchain-badge-bundle-facts`, `kungfu-buildchain-readme-badge-facts` | [`readme-badges.md`](readme-badges.md) |\n| Homebrew tap distribution indexes | `dist/site/node-api-registry.json`, `dist/site/buildchain-contract.json` | [`homebrew.md`](homebrew.md) |\n| Buildchain CLI manual | `dist/site/cli-registry.json`, `dist/site/manual-registry.json` | [`cli.md`](cli.md) |\n| Node API / package exports | `dist/site/node-api-registry.json`, `dist/site/release-provenance.json` | [`cli.md`](cli.md#node-api-and-package-exports) |\n\n`dist/site/kfd-claims.json` is generated from\n`packages/core/buildchain-kfd-claims.js`. Treat that module and JSON file as the\nsource claim registry; this map and the manuals explain those claims but do not\nreplace them.\n\n## Map\n\n| Your question | Document | Plane | Status |\n| --- | --- | --- | --- |\n| What is Buildchain, in one idea? | [`../README.md`](../README.md) | - | stable |\n| Why is Buildchain a Release Passport mechanism rather than a generic workflow collection? | [`product-mechanism.md`](product-mechanism.md) | why | stable |\n| How do agents and contributors enter this repo? | [`../AGENTS.md`](../AGENTS.md) + [`../CONTRIBUTING.md`](../CONTRIBUTING.md) | use | stable |\n| How do I install a standalone binary or npm package? | [`install.md`](install.md) | use | stable |\n| How do I run the `buildchain` CLI? | [`cli.md`](cli.md) | use | stable |\n| How do I import Buildchain toolkit APIs from JavaScript build code? | [`toolkit-observability.md`](toolkit-observability.md) + [`../packages/core/README.md`](../packages/core/README.md) | use | stable |\n| How do I initialize a new repository? | [`cli.md`](cli.md) + [`lifecycle-protocol.md`](lifecycle-protocol.md) | use | stable |\n| Why does Buildchain use branch-driven release governance? | [`release-governance.md`](release-governance.md) | why | stable |\n| How do protected dev branches and scheduled ready-PR merging work? | [`release-governance.md`](release-governance.md#protected-dev-branches) | use | stable |\n| How do I run daily, weekly, or monthly repository patrols? | [`release-governance.md`](release-governance.md#buildchain-patrol) | use | stable |\n| How does Buildchain decide patch, minor, and major release lines? | [`versioning.md`](versioning.md) | why | stable |\n| What exact branch/tag state machine runs on alpha, release, and major gate? | [`release-flow.md`](release-flow.md) | verify | stable |\n| What did Buildchain migrate or retire from old action repositories? | [`migration-inventory.md`](migration-inventory.md) | verify | stable |\n| What is the active action and workflow source of truth? | [`ownership.md`](ownership.md) | verify | stable |\n| How do I declare version files and custom lifecycle commands? | [`lifecycle-protocol.md`](lifecycle-protocol.md) | use | stable |\n| How does publish evidence, recovery, and finalization work? | [`publish-transaction.md`](publish-transaction.md) | verify | stable |\n| How do I collect and verify module/product build facts from Git source, version files, and outputs? | [`build-facts.md`](build-facts.md) + [`cli.md`](cli.md) | use/verify | stable |\n| How do I publish or verify release passport artifacts? | [`release-passport.md`](release-passport.md) | use | stable |\n| How do I gate release artifacts with KFD-1 contract-world witnesses? | [`release-passport.md`](release-passport.md#kfd-1-contract-world-release-gate) | verify/use | stable |\n| How do I declare, render, and audit product KFD-2 release trust claims? | [`kfd-support.md`](kfd-support.md#kfd-2) + [`release-passport.md`](release-passport.md#kfd-2-release-trust-passport-audit) + [`cli.md`](cli.md) | verify/use | stable |\n| How do I gate KFD-3 collaboration-interface releases? | [`release-passport.md`](release-passport.md#kfd-3-collaboration-interface-release-gate) + [`cli.md`](cli.md) | verify/use | stable |\n| How do I detect, register, audit, witness, or query KFD-3 product surfaces? | [`kfd-support.md`](kfd-support.md) + [`cli.md`](cli.md) | verify/use | stable |\n| How do I keep `@v2` floating refs while detecting Buildchain contract drift? | [`reusable-build-surface.md`](reusable-build-surface.md#floating-ref-contract-lock) | verify/use | stable |\n| How do I propagate finalized upstream releases to downstream package/site PRs? | [`release-propagation.md`](release-propagation.md) | use | preview |\n| How do paper or report repositories publish PDFs, metadata, source bundles, site-consumable manifests, npm packages, and GitHub Releases? | [`publication-artifacts.md`](publication-artifacts.md) | use | stable |\n| How do I generate KFD / Release Passport badge bundles without hand-maintaining Markdown? | [`readme-badges.md`](readme-badges.md) + [`cli.md`](cli.md) | use | stable |\n| How do I generate and verify a Homebrew tap from release passport evidence? | [`homebrew.md`](homebrew.md) + [`cli.md`](cli.md) | use/verify | stable |\n| How do I prove a PR-stage reusable build is the artifact source promoted later? | [`release-candidate.md`](release-candidate.md) + [`reusable-build-surface.md`](reusable-build-surface.md) | verify | stable |\n| Why are binary release assets archived by platform, and where is the single bundle? | [`binary-distribution.md`](binary-distribution.md) | verify | stable |\n| How do I add timestamped logs inside build scripts? | [`toolkit-observability.md`](toolkit-observability.md) | use | stable |\n| What package-owned facts should buildchain.libkungfu.dev render? | [`site-bundle-contract.md`](site-bundle-contract.md) | use | stable |\n| How do I call the reusable build workflow? | [`reusable-build-surface.md`](reusable-build-surface.md) | use | stable |\n| How do I use one build job that follows alpha during development and stable for releases? | [`reusable-build-surface.md`](reusable-build-surface.md#automatic-channel-router) | use | preview |\n| How do self-hosted runners relay large artifacts through S3 before GitHub artifacts? | [`reusable-build-surface.md`](reusable-build-surface.md#artifact-transfer-relay) | use | stable |\n| How do self-hosted runners reuse local Git checkout caches without weakening source locks? | [`reusable-build-surface.md`](reusable-build-surface.md#locked-source-checkout-cache) | use | stable |\n| How do I validate an unreleased Buildchain runtime train while keeping `@v2`? | [`runtime-train-validation.md`](runtime-train-validation.md) | use | stable |\n| How do I deploy a site/app preview, staging, or production surface? | [`web-surface-deployments.md`](web-surface-deployments.md) | use | stable |\n| How do I publish observed infrastructure contracts for downstream consumers? | [`infra-contract.md`](infra-contract.md) | use | preview |\n| How do I use the active actions directly? | [`../actions/validate-config/README.md`](../actions/validate-config/README.md), [`../actions/run-lifecycle/README.md`](../actions/run-lifecycle/README.md), [`../actions/promote-buildchain-ref/README.md`](../actions/promote-buildchain-ref/README.md), [`../actions/report-buildchain-issue/README.md`](../actions/report-buildchain-issue/README.md) | use | stable |\n| How can a consumer workflow report a Buildchain-owned failure back to Buildchain? | [`consumer-issue-reporting.md`](consumer-issue-reporting.md) + [`../actions/report-buildchain-issue/README.md`](../actions/report-buildchain-issue/README.md) | use | stable |\n| What do the fixture repositories demonstrate? | [`../fixtures/libnode-shaped/README.md`](../fixtures/libnode-shaped/README.md), [`../fixtures/publish-transaction-shaped/README.md`](../fixtures/publish-transaction-shaped/README.md), [`../fixtures/web-surface-shaped/README.md`](../fixtures/web-surface-shaped/README.md), [`../fixtures/publication-artifact-shaped/README.md`](../fixtures/publication-artifact-shaped/README.md) | verify | stable |\n| What license and contribution terms apply? | [`../LICENSE`](../LICENSE) + [`../LICENSE-POLICY.md`](../LICENSE-POLICY.md) | use | stable |\n| What trademark, official-service, and provider-compliance boundaries apply? | [`../TRADEMARK.md`](../TRADEMARK.md) + [`../ACCEPTABLE_USE.md`](../ACCEPTABLE_USE.md) + [`../PROVIDER_COMPLIANCE.md`](../PROVIDER_COMPLIANCE.md) | use | stable |\n| How do I report a vulnerability? | [`../SECURITY.md`](../SECURITY.md) | use | stable |\n\n## Also asking about\n\n- **ABV / old workflows / old action repositories** -> [`release-governance.md`](release-governance.md)\n and [`migration-inventory.md`](migration-inventory.md).\n- **v2 / v2-alpha / v2.0 / v2.0-alpha / exact tags / floating tags** ->\n [`release-governance.md`](release-governance.md) and\n [`release-flow.md`](release-flow.md).\n- **Buildchain self-dogfood / released alpha canary / stable compatibility lane** ->\n [`release-governance.md`](release-governance.md#buildchain-alpha-self-dogfood).\n- **v2.1 vs v2.2 / when to open a new minor line** ->\n [`versioning.md`](versioning.md).\n- **dry-run / what would happen if this channel PR merges** -> [`cli.md`](cli.md)\n and [`release-flow.md`](release-flow.md).\n- **protected dev branches / scheduled ready-PR merge / daily-weekly-monthly patrol** ->\n [`release-governance.md`](release-governance.md#protected-dev-branches) and\n [`release-governance.md`](release-governance.md#buildchain-patrol).\n- **pnpm / npm / yarn / package-manager adapters** ->\n [`lifecycle-protocol.md`](lifecycle-protocol.md).\n- **pip / Conan / CMake / custom commands** -> [`lifecycle-protocol.md`](lifecycle-protocol.md)\n and [`reusable-build-surface.md`](reusable-build-surface.md).\n- **libnode / native artifacts / self-hosted runner matrix** ->\n [`reusable-build-surface.md`](reusable-build-surface.md) and\n [`../fixtures/libnode-shaped/README.md`](../fixtures/libnode-shaped/README.md).\n- **S3 artifact relay / self-hosted runner artifact transfer** ->\n [`reusable-build-surface.md`](reusable-build-surface.md#artifact-transfer-relay).\n- **local Git checkout cache / self-hosted source transport** ->\n [`reusable-build-surface.md`](reusable-build-surface.md#locked-source-checkout-cache).\n- **runtime train validation / temporary `buildchain-ref` override** ->\n [`runtime-train-validation.md`](runtime-train-validation.md) and\n [`reusable-build-surface.md`](reusable-build-surface.md).\n- **consumer workflow feedback / automatic Buildchain GitHub issues** ->\n [`consumer-issue-reporting.md`](consumer-issue-reporting.md).\n- **PR-stage RC artifacts / promote-only release candidates** ->\n [`release-candidate.md`](release-candidate.md) and\n [`reusable-build-surface.md`](reusable-build-surface.md).\n- **infra contract / observed infrastructure outputs / downstream contract propagation** ->\n [`infra-contract.md`](infra-contract.md).\n- **standalone binary install / platform archives / GitHub Release bundle** ->\n [`install.md`](install.md), [`binary-distribution.md`](binary-distribution.md),\n and [`release-passport.md`](release-passport.md).\n- **Trusted Publishing / npm / publish evidence / recovery** ->\n [`cli.md`](cli.md) and [`publish-transaction.md`](publish-transaction.md).\n- **Git source digest / module build facts / product build facts / legacy\n Kungfu build info** -> [`build-facts.md`](build-facts.md) and [`cli.md`](cli.md).\n- **release chains / upstream package or publication artifact as source of truth / site synchronization** ->\n [`release-propagation.md`](release-propagation.md).\n- **paper repositories / PDFs / publication manifests / immutable archive registries / source bundles** ->\n [`publication-artifacts.md`](publication-artifacts.md).\n- **README status badges / KFD badge bundles / badge facts JSON** ->\n [`readme-badges.md`](readme-badges.md) and [`cli.md`](cli.md).\n- **Homebrew taps / distribution indexes / Formula drift checks** ->\n [`homebrew.md`](homebrew.md) and [`cli.md`](cli.md).\n- **KFD-1 contract worlds / byte-for-byte release gates** ->\n [`release-passport.md`](release-passport.md#kfd-1-contract-world-release-gate).\n- **KFD-2 public release trust claim audit** ->\n [`release-passport.md`](release-passport.md#kfd-2-release-trust-passport-audit).\n- **KFD-3 collaboration-interface / agent-facing control surface closure** ->\n [`release-passport.md`](release-passport.md#kfd-3-collaboration-interface-release-gate).\n- **floating `@v2` / contract lock / compatible drift issue** ->\n [`reusable-build-surface.md`](reusable-build-surface.md#floating-ref-contract-lock).\n- **GitHub Release passport / binary assets / artifact evidence / agent release checks** ->\n [`release-passport.md`](release-passport.md),\n [`binary-distribution.md`](binary-distribution.md), and [`cli.md`](cli.md).\n- **Buildchain logging / timestamps / consumer build phase timing** ->\n [`toolkit-observability.md`](toolkit-observability.md) for JavaScript API\n imports, and [`cli.md`](cli.md) for workflow or shell command usage.\n- **buildchain.libkungfu.dev / package-owned site facts** ->\n [`site-bundle-contract.md`](site-bundle-contract.md).\n- **sites / web previews / staging / production gates** ->\n [`web-surface-deployments.md`](web-surface-deployments.md).\n- **trademark / fork / official service / provider compliance / release\n evidence boundary** -> [`../TRADEMARK.md`](../TRADEMARK.md),\n [`../ACCEPTABLE_USE.md`](../ACCEPTABLE_USE.md), and\n [`../PROVIDER_COMPLIANCE.md`](../PROVIDER_COMPLIANCE.md).\n\n## How this map is maintained\n\n- A document becomes a row here when it is a stable entrypoint for a user,\n contributor, or workflow consumer.\n- A row's status must never claim more than the artifact delivers.\n- `why` documents explain intent and design pressure; `verify` and `use`\n documents should state what is guaranteed, where to verify it, and the current\n maturity of that guarantee."
|
|
816
|
+
"markdown": "# Documentation Map\n\nStart here. Find the question you have; follow it to the document that answers\nit. This map is meant to be readable by both a person skimming for the right doc\nand an agent grounding a specific claim.\n\nEach row carries a **plane** - *why* (intent / rationale), *verify* (trust the\nrunning artifact), *use* (consume / extend) - and a **status**:\n\n- `stable` - current and holds.\n- `draft` - exists, rough or incomplete.\n- `to write` - planned; the material exists but is not yet a single doc.\n- `retired` - intentionally not part of the active Buildchain v2 surface.\n\n## Capability Coverage\n\nThis package should be usable by an agent from the npm artifact alone. The\nmachine-readable `dist/site/` bundle is the first fact source; the Markdown\nmanuals explain those facts and give operator examples.\n\n`dist/site/capability-registry.json` is the capability navigation entrypoint.\nIt groups the public surface into stable product areas so sites and agents do\nnot have to infer structure from file names. Each page, manual, CLI command,\nworkflow, action, and Node API export also carries a `capabilityGroup`,\n`audience`, and `maturity` field in its own registry.\n\n| Capability group | Primary facts | Primary manuals |\n| --- | --- | --- |\n| Getting Started | `capability-registry.json`, `product-mechanism.json` | [`install.md`](install.md), [`product-mechanism.md`](product-mechanism.md), [`cli.md`](cli.md) |\n| Release Passport and Trust | `release-model.json`, `artifact-schemas.json`, `kfd-claims.json` | [`release-passport.md`](release-passport.md), [`release-candidate.md`](release-candidate.md), [`publish-transaction.md`](publish-transaction.md), [`binary-distribution.md`](binary-distribution.md) |\n| Reusable Build and Lifecycle | `workflow-registry.json`, `release-model.json` | [`reusable-build-surface.md`](reusable-build-surface.md), [`lifecycle-protocol.md`](lifecycle-protocol.md) |\n| KFD Trust and Surface Closure | `kfd-claims.json`, `public-surface-audit.json`, `cli-registry.json`, `node-api-registry.json` | [`kfd-support.md`](kfd-support.md), [`release-passport.md`](release-passport.md) |\n| Site Bundle, Web Surfaces, and Propagation | `buildchain-site.json`, `site-manifest.json`, `page-registry.json`, `release-model.json` | [`site-bundle-contract.md`](site-bundle-contract.md), [`web-surface-deployments.md`](web-surface-deployments.md), [`release-propagation.md`](release-propagation.md) |\n| Publication Artifacts | `publication-registry.json`, `workflow-registry.json`, `node-api-registry.json`, `manual-registry.json`, `kungfu-buildchain-publication-artifact-registry` | [`publication-artifacts.md`](publication-artifacts.md), [`reusable-build-surface.md`](reusable-build-surface.md) |\n| Distribution Indexes and Badges | `badge-endpoint-registry.json`, `node-api-registry.json`, `manual-registry.json` | [`readme-badges.md`](readme-badges.md), [`homebrew.md`](homebrew.md) |\n| Build Facts, Observability, and Diagnostics | `cli-registry.json`, `node-api-registry.json`, lifecycle artifacts | [`build-facts.md`](build-facts.md), [`toolkit-observability.md`](toolkit-observability.md), [`consumer-issue-reporting.md`](consumer-issue-reporting.md) |\n| Governance, Versioning, and Runtime Drift | `buildchain-contract.json`, `workflow-registry.json`, `release-model.json` | [`release-governance.md`](release-governance.md), [`release-flow.md`](release-flow.md), [`versioning.md`](versioning.md), [`runtime-train-validation.md`](runtime-train-validation.md) |\n| CLI and Node API Reference | `cli-registry.json`, `node-api-registry.json`, `workflow-registry.json`, `manual-registry.json` | [`cli.md`](cli.md), [`../packages/core/README.md`](../packages/core/README.md) |\n\n| Capability | Machine-readable entry | Manual entry |\n| --- | --- | --- |\n| Capability-grouped KFD navigation | `dist/site/capability-registry.json`, `dist/site/page-registry.json`, `dist/site/manual-registry.json`, `dist/site/cli-registry.json`, `dist/site/node-api-registry.json` | this map, [`site-bundle-contract.md`](site-bundle-contract.md), [`kfd-support.md`](kfd-support.md) |\n| KFD-1 / KFD-2 / KFD-3 release-passport gates | `dist/site/kfd-claims.json`, `dist/site/buildchain-contract.json`, `dist/site/artifact-schemas.json` | [`release-passport.md`](release-passport.md) |\n| KFD-3 public surface reverse audit | `dist/site/public-surface-audit.json`, `dist/site/cli-registry.json`, `dist/site/workflow-registry.json`, `dist/site/page-registry.json` | [`cli.md`](cli.md), [`site-bundle-contract.md`](site-bundle-contract.md) |\n| KFD-1 / KFD-2 / KFD-3 first-class CLI and Node API | `.buildchain/kfd/kfd-3/surfaces.json`, `dist/site/kfd-claims.json`, `buildchain.release.json`, KFD schemas from `@kungfu-tech/kfd` | [`kfd-support.md`](kfd-support.md), [`cli.md`](cli.md#commands) |\n| Floating `@v2` drift detection and compatibility issues | `dist/site/buildchain-contract.json` | [`reusable-build-surface.md`](reusable-build-surface.md#floating-ref-contract-lock) |\n| npm publish transactions, evidence, dist-tags, and recovery | `dist/site/release-model.json`, `dist/site/artifact-schemas.json` | [`publish-transaction.md`](publish-transaction.md) |\n| Git/source/version/module/product build facts | `dist/site/node-api-registry.json`, `dist/site/cli-registry.json`, `kungfu-buildchain-module-build-facts`, `kungfu-buildchain-product-build-facts` | [`build-facts.md`](build-facts.md) |\n| GitHub Release passport/evidence publication | `dist/site/release-model.json`, `dist/site/artifact-schemas.json` | [`release-governance.md`](release-governance.md), [`release-candidate.md`](release-candidate.md) |\n| release propagation for package/publication/site chains | `dist/site/release-model.json` | [`release-propagation.md`](release-propagation.md) |\n| publication artifact manifests, immutable archive registries, source bundles, and paper repository workflows | `dist/site/publication-registry.json`, `dist/site/workflow-registry.json`, `dist/site/node-api-registry.json`, `kungfu-buildchain-publication-artifact-manifest`, `kungfu-buildchain-publication-artifact-registry` | [`publication-artifacts.md`](publication-artifacts.md) |\n| Generated badge bundles, README badge blocks, and badge facts | `dist/site/node-api-registry.json`, `dist/site/manual-registry.json`, `kungfu-buildchain-badge-bundle-facts`, `kungfu-buildchain-readme-badge-facts` | [`readme-badges.md`](readme-badges.md) |\n| Homebrew tap distribution indexes | `dist/site/node-api-registry.json`, `dist/site/buildchain-contract.json` | [`homebrew.md`](homebrew.md) |\n| Buildchain CLI manual | `dist/site/cli-registry.json`, `dist/site/manual-registry.json` | [`cli.md`](cli.md) |\n| Node API / package exports | `dist/site/node-api-registry.json`, `dist/site/release-provenance.json` | [`cli.md`](cli.md#node-api-and-package-exports) |\n\n`dist/site/kfd-claims.json` is generated from\n`packages/core/buildchain-kfd-claims.js`. Treat that module and JSON file as the\nsource claim registry; this map and the manuals explain those claims but do not\nreplace them.\n\n## Map\n\n| Your question | Document | Plane | Status |\n| --- | --- | --- | --- |\n| What is Buildchain, in one idea? | [`../README.md`](../README.md) | - | stable |\n| Why is Buildchain a Release Passport mechanism rather than a generic workflow collection? | [`product-mechanism.md`](product-mechanism.md) | why | stable |\n| How do agents and contributors enter this repo? | [`../AGENTS.md`](../AGENTS.md) + [`../CONTRIBUTING.md`](../CONTRIBUTING.md) | use | stable |\n| How do I install a standalone binary or npm package? | [`install.md`](install.md) | use | stable |\n| How do I run the `buildchain` CLI? | [`cli.md`](cli.md) | use | stable |\n| How do I import Buildchain toolkit APIs from JavaScript build code? | [`toolkit-observability.md`](toolkit-observability.md) + [`../packages/core/README.md`](../packages/core/README.md) | use | stable |\n| How do I initialize a new repository? | [`cli.md`](cli.md) + [`lifecycle-protocol.md`](lifecycle-protocol.md) | use | stable |\n| Why does Buildchain use branch-driven release governance? | [`release-governance.md`](release-governance.md) | why | stable |\n| How do protected dev branches and scheduled ready-PR merging work? | [`release-governance.md`](release-governance.md#protected-dev-branches) | use | stable |\n| How do I run daily, weekly, or monthly repository patrols? | [`release-governance.md`](release-governance.md#buildchain-patrol) | use | stable |\n| How does Buildchain decide patch, minor, and major release lines? | [`versioning.md`](versioning.md) | why | stable |\n| What exact branch/tag state machine runs on alpha, release, and major gate? | [`release-flow.md`](release-flow.md) | verify | stable |\n| What did Buildchain migrate or retire from old action repositories? | [`migration-inventory.md`](migration-inventory.md) | verify | stable |\n| What is the active action and workflow source of truth? | [`ownership.md`](ownership.md) | verify | stable |\n| How do I declare version files and custom lifecycle commands? | [`lifecycle-protocol.md`](lifecycle-protocol.md) | use | stable |\n| How does publish evidence, recovery, and finalization work? | [`publish-transaction.md`](publish-transaction.md) | verify | stable |\n| How do I collect and verify module/product build facts from Git source, version files, and outputs? | [`build-facts.md`](build-facts.md) + [`cli.md`](cli.md) | use/verify | stable |\n| How do I publish or verify release passport artifacts? | [`release-passport.md`](release-passport.md) | use | stable |\n| How do I gate release artifacts with KFD-1 contract-world witnesses? | [`release-passport.md`](release-passport.md#kfd-1-contract-world-release-gate) | verify/use | stable |\n| How do I declare, render, and audit product KFD-2 release trust claims? | [`kfd-support.md`](kfd-support.md#kfd-2) + [`release-passport.md`](release-passport.md#kfd-2-release-trust-passport-audit) + [`cli.md`](cli.md) | verify/use | stable |\n| How do I gate KFD-3 collaboration-interface releases? | [`release-passport.md`](release-passport.md#kfd-3-collaboration-interface-release-gate) + [`cli.md`](cli.md) | verify/use | stable |\n| How do I detect, register, audit, witness, or query KFD-3 product surfaces? | [`kfd-support.md`](kfd-support.md) + [`cli.md`](cli.md) | verify/use | stable |\n| How do I keep `@v2` floating refs while detecting Buildchain contract drift? | [`reusable-build-surface.md`](reusable-build-surface.md#floating-ref-contract-lock) | verify/use | stable |\n| How do I propagate finalized upstream releases to downstream package/site PRs? | [`release-propagation.md`](release-propagation.md) | use | preview |\n| How do paper or report repositories publish PDFs, metadata, source bundles, site-consumable manifests, npm packages, and GitHub Releases? | [`publication-artifacts.md`](publication-artifacts.md) | use | stable |\n| How do I generate KFD / Release Passport badge bundles without hand-maintaining Markdown? | [`readme-badges.md`](readme-badges.md) + [`cli.md`](cli.md) | use | stable |\n| How do I generate and verify a Homebrew tap from release passport evidence? | [`homebrew.md`](homebrew.md) + [`cli.md`](cli.md) | use/verify | stable |\n| How do I prove a PR-stage reusable build is the artifact source promoted later? | [`release-candidate.md`](release-candidate.md) + [`reusable-build-surface.md`](reusable-build-surface.md) | verify | stable |\n| Why are binary release assets archived by platform, and where is the single bundle? | [`binary-distribution.md`](binary-distribution.md) | verify | stable |\n| How do I add timestamped logs inside build scripts? | [`toolkit-observability.md`](toolkit-observability.md) | use | stable |\n| What package-owned facts should buildchain.libkungfu.dev render? | [`site-bundle-contract.md`](site-bundle-contract.md) | use | stable |\n| How do I call the reusable build workflow? | [`reusable-build-surface.md`](reusable-build-surface.md) | use | stable |\n| How do I use one build job that follows alpha during development and stable for releases? | [`reusable-build-surface.md`](reusable-build-surface.md#automatic-channel-router) | use | preview |\n| How do self-hosted runners relay large artifacts through S3 before GitHub artifacts? | [`reusable-build-surface.md`](reusable-build-surface.md#artifact-transfer-relay) | use | stable |\n| How do self-hosted runners reuse local Git checkout caches without weakening source locks? | [`reusable-build-surface.md`](reusable-build-surface.md#locked-source-checkout-cache) | use | stable |\n| How do I validate an unreleased Buildchain runtime train while keeping `@v2`? | [`runtime-train-validation.md`](runtime-train-validation.md) | use | stable |\n| How do I automatically qualify alpha candidates and publish the newest non-revoked qualified candidate at a fixed window? | [`stable-candidate-patrol.md`](stable-candidate-patrol.md) | use | preview |\n| How do I deploy a site/app preview, staging, or production surface? | [`web-surface-deployments.md`](web-surface-deployments.md) | use | stable |\n| How do I publish observed infrastructure contracts for downstream consumers? | [`infra-contract.md`](infra-contract.md) | use | preview |\n| How do I use the active actions directly? | [`../actions/validate-config/README.md`](../actions/validate-config/README.md), [`../actions/run-lifecycle/README.md`](../actions/run-lifecycle/README.md), [`../actions/promote-buildchain-ref/README.md`](../actions/promote-buildchain-ref/README.md), [`../actions/report-buildchain-issue/README.md`](../actions/report-buildchain-issue/README.md) | use | stable |\n| How can a consumer workflow report a Buildchain-owned failure back to Buildchain? | [`consumer-issue-reporting.md`](consumer-issue-reporting.md) + [`../actions/report-buildchain-issue/README.md`](../actions/report-buildchain-issue/README.md) | use | stable |\n| What do the fixture repositories demonstrate? | [`../fixtures/libnode-shaped/README.md`](../fixtures/libnode-shaped/README.md), [`../fixtures/publish-transaction-shaped/README.md`](../fixtures/publish-transaction-shaped/README.md), [`../fixtures/web-surface-shaped/README.md`](../fixtures/web-surface-shaped/README.md), [`../fixtures/publication-artifact-shaped/README.md`](../fixtures/publication-artifact-shaped/README.md) | verify | stable |\n| What license and contribution terms apply? | [`../LICENSE`](../LICENSE) + [`../LICENSE-POLICY.md`](../LICENSE-POLICY.md) | use | stable |\n| What trademark, official-service, and provider-compliance boundaries apply? | [`../TRADEMARK.md`](../TRADEMARK.md) + [`../ACCEPTABLE_USE.md`](../ACCEPTABLE_USE.md) + [`../PROVIDER_COMPLIANCE.md`](../PROVIDER_COMPLIANCE.md) | use | stable |\n| How do I report a vulnerability? | [`../SECURITY.md`](../SECURITY.md) | use | stable |\n\n## Also asking about\n\n- **ABV / old workflows / old action repositories** -> [`release-governance.md`](release-governance.md)\n and [`migration-inventory.md`](migration-inventory.md).\n- **v2 / v2-alpha / v2.0 / v2.0-alpha / exact tags / floating tags** ->\n [`release-governance.md`](release-governance.md) and\n [`release-flow.md`](release-flow.md).\n- **Buildchain self-dogfood / released alpha canary / stable compatibility lane** ->\n [`release-governance.md`](release-governance.md#buildchain-alpha-self-dogfood).\n- **qualified alpha ledger / scheduled stable selection / hold and revoke** ->\n [`stable-candidate-patrol.md`](stable-candidate-patrol.md).\n- **v2.1 vs v2.2 / when to open a new minor line** ->\n [`versioning.md`](versioning.md).\n- **dry-run / what would happen if this channel PR merges** -> [`cli.md`](cli.md)\n and [`release-flow.md`](release-flow.md).\n- **protected dev branches / scheduled ready-PR merge / daily-weekly-monthly patrol** ->\n [`release-governance.md`](release-governance.md#protected-dev-branches) and\n [`release-governance.md`](release-governance.md#buildchain-patrol).\n- **pnpm / npm / yarn / package-manager adapters** ->\n [`lifecycle-protocol.md`](lifecycle-protocol.md).\n- **pip / Conan / CMake / custom commands** -> [`lifecycle-protocol.md`](lifecycle-protocol.md)\n and [`reusable-build-surface.md`](reusable-build-surface.md).\n- **libnode / native artifacts / self-hosted runner matrix** ->\n [`reusable-build-surface.md`](reusable-build-surface.md) and\n [`../fixtures/libnode-shaped/README.md`](../fixtures/libnode-shaped/README.md).\n- **S3 artifact relay / self-hosted runner artifact transfer** ->\n [`reusable-build-surface.md`](reusable-build-surface.md#artifact-transfer-relay).\n- **local Git checkout cache / self-hosted source transport** ->\n [`reusable-build-surface.md`](reusable-build-surface.md#locked-source-checkout-cache).\n- **runtime train validation / temporary `buildchain-ref` override** ->\n [`runtime-train-validation.md`](runtime-train-validation.md) and\n [`reusable-build-surface.md`](reusable-build-surface.md).\n- **consumer workflow feedback / automatic Buildchain GitHub issues** ->\n [`consumer-issue-reporting.md`](consumer-issue-reporting.md).\n- **PR-stage RC artifacts / promote-only release candidates** ->\n [`release-candidate.md`](release-candidate.md) and\n [`reusable-build-surface.md`](reusable-build-surface.md).\n- **infra contract / observed infrastructure outputs / downstream contract propagation** ->\n [`infra-contract.md`](infra-contract.md).\n- **standalone binary install / platform archives / GitHub Release bundle** ->\n [`install.md`](install.md), [`binary-distribution.md`](binary-distribution.md),\n and [`release-passport.md`](release-passport.md).\n- **Trusted Publishing / npm / publish evidence / recovery** ->\n [`cli.md`](cli.md) and [`publish-transaction.md`](publish-transaction.md).\n- **Git source digest / module build facts / product build facts / legacy\n Kungfu build info** -> [`build-facts.md`](build-facts.md) and [`cli.md`](cli.md).\n- **release chains / upstream package or publication artifact as source of truth / site synchronization** ->\n [`release-propagation.md`](release-propagation.md).\n- **paper repositories / PDFs / publication manifests / immutable archive registries / source bundles** ->\n [`publication-artifacts.md`](publication-artifacts.md).\n- **README status badges / KFD badge bundles / badge facts JSON** ->\n [`readme-badges.md`](readme-badges.md) and [`cli.md`](cli.md).\n- **Homebrew taps / distribution indexes / Formula drift checks** ->\n [`homebrew.md`](homebrew.md) and [`cli.md`](cli.md).\n- **KFD-1 contract worlds / byte-for-byte release gates** ->\n [`release-passport.md`](release-passport.md#kfd-1-contract-world-release-gate).\n- **KFD-2 public release trust claim audit** ->\n [`release-passport.md`](release-passport.md#kfd-2-release-trust-passport-audit).\n- **KFD-3 collaboration-interface / agent-facing control surface closure** ->\n [`release-passport.md`](release-passport.md#kfd-3-collaboration-interface-release-gate).\n- **floating `@v2` / contract lock / compatible drift issue** ->\n [`reusable-build-surface.md`](reusable-build-surface.md#floating-ref-contract-lock).\n- **GitHub Release passport / binary assets / artifact evidence / agent release checks** ->\n [`release-passport.md`](release-passport.md),\n [`binary-distribution.md`](binary-distribution.md), and [`cli.md`](cli.md).\n- **Buildchain logging / timestamps / consumer build phase timing** ->\n [`toolkit-observability.md`](toolkit-observability.md) for JavaScript API\n imports, and [`cli.md`](cli.md) for workflow or shell command usage.\n- **buildchain.libkungfu.dev / package-owned site facts** ->\n [`site-bundle-contract.md`](site-bundle-contract.md).\n- **sites / web previews / staging / production gates** ->\n [`web-surface-deployments.md`](web-surface-deployments.md).\n- **trademark / fork / official service / provider compliance / release\n evidence boundary** -> [`../TRADEMARK.md`](../TRADEMARK.md),\n [`../ACCEPTABLE_USE.md`](../ACCEPTABLE_USE.md), and\n [`../PROVIDER_COMPLIANCE.md`](../PROVIDER_COMPLIANCE.md).\n\n## How this map is maintained\n\n- A document becomes a row here when it is a stable entrypoint for a user,\n contributor, or workflow consumer.\n- A row's status must never claim more than the artifact delivers.\n- `why` documents explain intent and design pressure; `verify` and `use`\n documents should state what is guaranteed, where to verify it, and the current\n maturity of that guarantee."
|
|
807
817
|
},
|
|
808
818
|
{
|
|
809
819
|
"id": "manual:migration-inventory",
|
|
@@ -1225,7 +1235,7 @@
|
|
|
1225
1235
|
],
|
|
1226
1236
|
"maturity": "stable",
|
|
1227
1237
|
"sourcePath": "docs/release-governance.md",
|
|
1228
|
-
"digest": "sha256:
|
|
1238
|
+
"digest": "sha256:3ae2bbc2df394726f350e58be1a71dd0379b99b19cd6ccf15fbe3b843f3890b6",
|
|
1229
1239
|
"headings": [
|
|
1230
1240
|
{
|
|
1231
1241
|
"level": 1,
|
|
@@ -1313,7 +1323,7 @@
|
|
|
1313
1323
|
"anchor": "operational-reading-order"
|
|
1314
1324
|
}
|
|
1315
1325
|
],
|
|
1316
|
-
"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- `v2-alpha` is the latest test channel on the highest published alpha minor in major `2`.\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`, `v2.0-alpha`, and `v2-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.\n8. Moves `vX-alpha` only when `X.Y` is the highest minor in major `X` with a published alpha; older minor alpha work records a skip and cannot move the major channel backwards.\n\nThis keeps the test channel self-describing. If a consumer checks out\n`v2.0-alpha` or `v2-alpha`, the manifests and exact alpha tag agree. The major\nalpha ref removes routine consumer edits when Buildchain opens a newer minor,\nwhile exact tags and SHAs remain the reproducible audit choice.\n\n### Buildchain Alpha Self-Dogfood\n\nBuildchain continuously consumes its own current major alpha through\n`.github/workflows/buildchain-alpha-self-dogfood.yml`. Both lanes call the\nreleased channel router at `build.yml@v2-alpha`. The auto lane must resolve\n`v2-alpha`; the explicit stable lane must resolve `v2`. Both execute the same\ndeclared install, build, and verify fixture, proving that a single consumer\nsurface routes to distinct released runtimes without duplicating lifecycle\nconfiguration in the consumer.\n\nThe reusable build trust gate reads `job.workflow_ref`, which identifies the\ncalled workflow and its selected ref. It does not infer the runtime from\n`github.workflow_ref`, because GitHub defines that context as the caller\nworkflow identity during a reusable call.\n\nThe router selects `.buildchain/alpha-contract-lock.json` for alpha and\n`.buildchain/contract-lock.json` for stable. The alpha lock records the exact\nreviewed alpha SHA and compatibility digest; it does not replace the stable\nconsumer lock. A later alpha with only compatible additive drift continues,\nwhile a changed breaking digest fails until the new alpha contract is reviewed.\n\nThe evidence job resolves `v2-alpha` and `v2` through the GitHub refs API,\ncompares those immutable SHAs with the reusable workflow outputs, verifies the\n`alpha` and `stable` classifications, and uploads a JSON evidence artifact.\nThe canary runs after successful Buildchain ref promotion, on a daily fallback\nschedule, and on manual dispatch. It shares the release-promotion concurrency\ngroup, so another promotion cannot move the floating refs between runtime\nresolution and evidence comparison.\n\nThis is a post-publication consumer canary, not a release bootstrap. Source\nverification still runs the current commit, and\n`buildchain-ref-promotion.yml` still passes the verified exact SHA into the\npromotion workflow. Patrol, dev-merge, repair, and promotion defaults remain on\nstable or exact refs so a broken alpha cannot prevent Buildchain from publishing\nits fix. When Buildchain opens a new major, inventory validation requires this\nworkflow's fixed GitHub `uses` refs to move from `vN`/`vN-alpha` to the new\nmajor; GitHub does not allow expressions in a reusable-workflow `uses` ref.\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.\n11. Moves `vX-alpha` to that next alpha only when this remains the highest published alpha minor.\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\n### Stable Release Throttle And Canary Gate\n\nBuildchain's own stable channel has an additional pre-publication gate. It is\nevaluated after the PR-stage release candidate has been resolved and before the\npublish-gate ref, package registry, exact stable tag, or floating stable refs\nare mutated. Train refs and alpha promotion do not execute this gate.\n\nAll alpha and release promotions first run a metadata-only release-candidate\npreflight after queued-intent revalidation. The preflight uses the same resolver\nand exact target SHA as the publication job, but does not download payloads or\ninstall the candidate repository dependencies. Missing channel PRs, stale\nworkflow runs, expired passport pairs, and insufficient payload artifact sets\ntherefore fail before the full promotion job starts. The publication job still\ndownloads and validates the exact evidence again at the trust boundary; the\npreflight moves failure earlier without weakening the final check.\n\nThe policy is versioned in `.buildchain/stable-release-policy.json`. A stable\ncandidate is allowed only when all of these facts are true:\n\n- the candidate resolves to an immutable exact alpha tag and its GitHub\n prerelease timestamp;\n- at least 24 hours have passed since the preceding stable patch on the same\n minor line;\n- the preceding stable-to-alpha comparison contains a product or public\n contract path, not only version, test, evidence, or retrospective changes;\n- the version-bound impact record has a non-empty summary and at least one\n surface impact;\n- the `Build Surface Fixture` release-candidate run succeeded;\n- `site-libkungfu-dev` completed its no-apply `Buildchain Stable Canary` and an allowed\n maintainer attested that successful run on the exact alpha SHA through the\n `buildchain-canary/site-libkungfu-dev` commit-status context;\n- the canary runtime input is exactly the candidate alpha tag or the 40-character\n commit SHA resolved from that tag; a successful status pointing at another\n workflow, repository, tag, floating ref, or SHA is rejected as mismatched;\n- at least one hour has elapsed after the last required canary completed.\n\nThe machine report is written to\n`.buildchain/release-passport/stable-release-gate.json`. A passing report is\nuploaded with the stable release passport. A blocked run writes the same report\nbefore failing, so the missing or stale condition is inspectable without\nopening a publication transaction.\n\nGitHub's Actions run REST object does not expose `workflow_dispatch` inputs.\nBuildchain therefore verifies the run's `workflow_id` against the authoritative\nworkflow metadata, then reads the exact runtime from the workflow-owned\n`<workflow name> / <runtime ref>` run-name when no input field is available.\nAn explicit API input, when present, remains authoritative and cannot be\noverridden by the display name.\n\nThe cooldown is a minimum interval, not an instruction to release every day.\nCompatible work should still be batched until a stable release has a concrete\nconsumer need. Changing the interval, canary set, attestors, product path\nboundary, or soak time is a reviewed policy change.\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\nOnce the durable release transaction is `complete` and the exact/floating\nstable refs have moved, next-alpha preparation is post-release bookkeeping. A\nfailure there records `deferred-post-release-bookkeeping` and\n`next-anchor-required` instead of retroactively reporting the stable release as\nfailed. Generated next-alpha merges use the current dev tree as their base and\noverlay only declared version-state paths, preserving concurrent dev changes.\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 canonical consumer required check context is `check / check`, matching the\nreusable workflow call plus its `check` job. Buildchain's own `Verify` workflow\nemits the repository-local context `check`, so Buildchain self-promotion,\nrelease-line bootstrap, and dogfood patrol wrappers pass `check` explicitly.\nRelease governance preserves the exact context emitted by the repository and\nrecords branch-protection policy before/after facts; it does not rewrite one\ncontext shape into the other. Consumer repositories can keep their context\nstable 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 / 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- every major with a published alpha has a cross-minor floating tag such as `v2-alpha`, owned by its highest published alpha minor;\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."
|
|
1326
|
+
"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- `v2-alpha` is the latest test channel on the highest published alpha minor in major `2`.\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`, `v2.0-alpha`, and `v2-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.\n8. Moves `vX-alpha` only when `X.Y` is the highest minor in major `X` with a published alpha; older minor alpha work records a skip and cannot move the major channel backwards.\n\nThis keeps the test channel self-describing. If a consumer checks out\n`v2.0-alpha` or `v2-alpha`, the manifests and exact alpha tag agree. The major\nalpha ref removes routine consumer edits when Buildchain opens a newer minor,\nwhile exact tags and SHAs remain the reproducible audit choice.\n\n### Buildchain Alpha Self-Dogfood\n\nBuildchain continuously consumes its own current major alpha through\n`.github/workflows/buildchain-alpha-self-dogfood.yml`. Both lanes call the\nreleased channel router at `build.yml@v2-alpha`. The auto lane must resolve\n`v2-alpha`; the explicit stable lane must resolve `v2`. Both execute the same\ndeclared install, build, and verify fixture, proving that a single consumer\nsurface routes to distinct released runtimes without duplicating lifecycle\nconfiguration in the consumer.\n\nThe reusable build trust gate reads `job.workflow_ref`, which identifies the\ncalled workflow and its selected ref. It does not infer the runtime from\n`github.workflow_ref`, because GitHub defines that context as the caller\nworkflow identity during a reusable call.\n\nThe router selects `.buildchain/alpha-contract-lock.json` for alpha and\n`.buildchain/contract-lock.json` for stable. The alpha lock records the exact\nreviewed alpha SHA and compatibility digest; it does not replace the stable\nconsumer lock. A later alpha with only compatible additive drift continues,\nwhile a changed breaking digest fails until the new alpha contract is reviewed.\n\nThe evidence job resolves `v2-alpha` and `v2` through the GitHub refs API,\ncompares those immutable SHAs with the reusable workflow outputs, verifies the\n`alpha` and `stable` classifications, and uploads a JSON evidence artifact.\nThe canary runs after successful Buildchain ref promotion, on a daily fallback\nschedule, and on manual dispatch. It shares the release-promotion concurrency\ngroup, so another promotion cannot move the floating refs between runtime\nresolution and evidence comparison.\n\nThis is a post-publication consumer canary, not a release bootstrap. Source\nverification still runs the current commit, and\n`buildchain-ref-promotion.yml` still passes the verified exact SHA into the\npromotion workflow. Patrol, dev-merge, repair, and promotion defaults remain on\nstable or exact refs so a broken alpha cannot prevent Buildchain from publishing\nits fix. When Buildchain opens a new major, inventory validation requires this\nworkflow's fixed GitHub `uses` refs to move from `vN`/`vN-alpha` to the new\nmajor; GitHub does not allow expressions in a reusable-workflow `uses` ref.\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.\n11. Moves `vX-alpha` to that next alpha only when this remains the highest published alpha minor.\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\n### Stable Release Throttle And Canary Gate\n\nBuildchain's own stable channel has an additional pre-publication gate. It is\nevaluated after the PR-stage release candidate has been resolved and before the\npublish-gate ref, package registry, exact stable tag, or floating stable refs\nare mutated. Train refs and alpha promotion do not execute this gate.\n\nAll alpha and release promotions first run a metadata-only release-candidate\npreflight after queued-intent revalidation. The preflight uses the same resolver\nand exact target SHA as the publication job, but does not download payloads or\ninstall the candidate repository dependencies. Missing channel PRs, stale\nworkflow runs, expired passport pairs, and insufficient payload artifact sets\ntherefore fail before the full promotion job starts. The publication job still\ndownloads and validates the exact evidence again at the trust boundary; the\npreflight moves failure earlier without weakening the final check.\n\nThe policy is versioned in `.buildchain/stable-release-policy.json`. A stable\ncandidate is allowed only when all of these facts are true:\n\n- the candidate resolves to an immutable exact alpha tag and its GitHub\n prerelease timestamp;\n- at least 24 hours have passed since the preceding stable patch on the same\n minor line;\n- the preceding stable-to-alpha comparison contains a product or public\n contract path, not only version, test, evidence, or retrospective changes;\n- the version-bound impact record has a non-empty summary and at least one\n surface impact;\n- the `Build Surface Fixture` release-candidate run succeeded;\n- `site-libkungfu-dev` completed its no-apply `Buildchain Stable Canary` and an allowed\n maintainer attested that successful run on the exact alpha SHA through the\n `buildchain-canary/site-libkungfu-dev` commit-status context;\n- the canary runtime input is exactly the candidate alpha tag or the 40-character\n commit SHA resolved from that tag; a successful status pointing at another\n workflow, repository, tag, floating ref, or SHA is rejected as mismatched;\n- at least one hour has elapsed after the last required canary completed.\n\nThe machine report is written to\n`.buildchain/release-passport/stable-release-gate.json`. A passing report is\nuploaded with the stable release passport. A blocked run writes the same report\nbefore failing, so the missing or stale condition is inspectable without\nopening a publication transaction.\n\nGitHub's Actions run REST object does not expose `workflow_dispatch` inputs.\nBuildchain therefore verifies the run's `workflow_id` against the authoritative\nworkflow metadata, then reads the exact runtime from the workflow-owned\n`<workflow name> / <runtime ref>` run-name when no input field is available.\nAn explicit API input, when present, remains authoritative and cannot be\noverridden by the display name.\n\nThe cooldown is a minimum interval, not an instruction to release every day.\nCompatible work should still be batched until a stable release has a concrete\nconsumer need. Changing the interval, canary set, attestors, product path\nboundary, or soak time is a reviewed policy change.\n\nRepositories that want a predictable scheduled stable window can use\n[`Stable Candidate Patrol`](stable-candidate-patrol.md). It persists each exact\nalpha independently, qualifies it after repository-declared checks and soak,\nand selects the newest qualified non-revoked candidate. A newer soaking alpha\ndoes not invalidate an older qualified candidate. The selected tree enters the\nexisting strict `publish-gate/release/<line>/<version> -> release/<line>` PR\npath, so scheduled selection changes release intent timing without weakening\nsource locks, review, verification, publish transactions, or passports.\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\nOnce the durable release transaction is `complete` and the exact/floating\nstable refs have moved, next-alpha preparation is post-release bookkeeping. A\nfailure there records `deferred-post-release-bookkeeping` and\n`next-anchor-required` instead of retroactively reporting the stable release as\nfailed. Generated next-alpha merges use the current dev tree as their base and\noverlay only declared version-state paths, preserving concurrent dev changes.\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 canonical consumer required check context is `check / check`, matching the\nreusable workflow call plus its `check` job. Buildchain's own `Verify` workflow\nemits the repository-local context `check`, so Buildchain self-promotion,\nrelease-line bootstrap, and dogfood patrol wrappers pass `check` explicitly.\nRelease governance preserves the exact context emitted by the repository and\nrecords branch-protection policy before/after facts; it does not rewrite one\ncontext shape into the other. Consumer repositories can keep their context\nstable 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\nDevelopment pull requests that need source acceptance without product build or\nartifact verification can opt into `mode: source`. That mode runs only\n`lifecycle.install` and `lifecycle.check` on GitHub-hosted `ubuntu-24.04` while\npreserving the stable `check / check` required-check context. Existing callers\nremain on `mode: verify` by default, and callers may set\n`upload-artifacts: false` without weakening the job conclusion.\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 / 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| `.github/workflows/stable-candidate-patrol.yml` | repository-selected release window | qualify immutable alpha candidates and open the exact source-lock stable PR |\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\nStable Candidate Patrol is separate from those maintenance cadences because its\ncaller-owned cron is a release-intent window. Its candidate ledger and selection\nremain generic; registry-specific side effects still run through the normal\nrepository `lifecycle.publish` transaction. See\n[`stable-candidate-patrol.md`](stable-candidate-patrol.md).\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- every major with a published alpha has a cross-minor floating tag such as `v2-alpha`, owned by its highest published alpha minor;\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."
|
|
1317
1327
|
},
|
|
1318
1328
|
{
|
|
1319
1329
|
"id": "manual:release-passport",
|
|
@@ -1436,7 +1446,7 @@
|
|
|
1436
1446
|
],
|
|
1437
1447
|
"maturity": "stable",
|
|
1438
1448
|
"sourcePath": "docs/reusable-build-surface.md",
|
|
1439
|
-
"digest": "sha256:
|
|
1449
|
+
"digest": "sha256:fbc74dee3a6f2283ea69a2a9a31945ac82ccaf1d270995539f5d80235ab74614",
|
|
1440
1450
|
"headings": [
|
|
1441
1451
|
{
|
|
1442
1452
|
"level": 1,
|
|
@@ -1458,6 +1468,11 @@
|
|
|
1458
1468
|
"title": "Linux Job Containers",
|
|
1459
1469
|
"anchor": "linux-job-containers"
|
|
1460
1470
|
},
|
|
1471
|
+
{
|
|
1472
|
+
"level": 2,
|
|
1473
|
+
"title": "Native Rust Toolchains",
|
|
1474
|
+
"anchor": "native-rust-toolchains"
|
|
1475
|
+
},
|
|
1461
1476
|
{
|
|
1462
1477
|
"level": 2,
|
|
1463
1478
|
"title": "Buildchain Runtime Override",
|
|
@@ -1468,6 +1483,11 @@
|
|
|
1468
1483
|
"title": "Floating Ref Contract Lock",
|
|
1469
1484
|
"anchor": "floating-ref-contract-lock"
|
|
1470
1485
|
},
|
|
1486
|
+
{
|
|
1487
|
+
"level": 2,
|
|
1488
|
+
"title": "Shifu Cache Profile Passthrough",
|
|
1489
|
+
"anchor": "shifu-cache-profile-passthrough"
|
|
1490
|
+
},
|
|
1471
1491
|
{
|
|
1472
1492
|
"level": 2,
|
|
1473
1493
|
"title": "Locked Source Checkout Cache",
|
|
@@ -1524,7 +1544,7 @@
|
|
|
1524
1544
|
"anchor": "fixture"
|
|
1525
1545
|
}
|
|
1526
1546
|
],
|
|
1527
|
-
"markdown": "# Reusable Build Surface\n\nBuildchain v2 provides a reusable build workflow for repositories that need\nBuildchain's release semantics but cannot be described as a simple Node package.\nThe first target shape is `libnode`: expensive native builds, multiple operating\nsystems, self-hosted runner labels, and release artifacts that must be auditable.\n\n## Automatic Channel Router\n\nThe preferred consumer surface is one reusable workflow call. After v2.12\nreaches the stable major ref, consumers keep this configuration for both alpha\ndevelopment and stable release work:\n\n```yaml\njobs:\n build:\n uses: kungfu-systems/buildchain/.github/workflows/build.yml@v2\n permissions:\n contents: read\n issues: write\n id-token: write\n with:\n working-directory: .\n artifact-name: libnode\n runner-preset: kungfu-v4-self-hosted\n publish-channel: none\n secrets: inherit\n```\n\n`buildchain-channel` defaults to `auto`. Selection uses this precedence:\n\n1. an explicit `buildchain-ref` train, SHA, or official channel;\n2. an explicit `buildchain-channel: alpha|stable`;\n3. `publish-channel: alpha|release|major`;\n4. GitHub release prerelease metadata;\n5. a canonical semver tag;\n6. non-release PR, push, dispatch, schedule, and workflow-run events default to\n alpha.\n\nThe resolved runtime is `vN-alpha` for development and prerelease intent and\n`vN` for stable release intent. Unknown custom publish channels, malformed\nrelease events, and non-semver release-like tags fail before the build matrix;\nthey never guess alpha for a stable release.\n\nThe router automatically selects `.buildchain/alpha-contract-lock.json` for\nalpha and `.buildchain/contract-lock.json` for stable. A repository can override\nthe common path with `buildchain-contract-lock-path`, or override one channel\nwith `buildchain-alpha-contract-lock-path` /\n`buildchain-stable-contract-lock-path`.\n\nOnly repositories changing the default policy need extra routing input:\n\n```yaml\nwith:\n buildchain-channel: stable\n```\n\nDuring the v2.12 prerelease evaluation window, canaries use\n`build.yml@v2-alpha`. The same router then selects `v2-alpha` or stable `v2` as\nthe runtime. Production consumers should adopt `build.yml@v2` after the router\nhas reached stable; this keeps the routing shell itself on a stable ref.\n\nThe router is generated from `.build.yml`'s input/output surface. Run\n`node scripts/generate-channel-build-workflow.mjs` after changing the advanced\nbuild workflow; inventory and unit tests reject a stale generated router.\n\n## Advanced Workflow\n\nConsumers that need direct workflow-shell or runtime control call the advanced\nsurface:\n\n```yaml\njobs:\n build:\n uses: kungfu-systems/buildchain/.github/workflows/.build.yml@v2\n with:\n working-directory: .\n artifact-name: libnode\n runner-preset: kungfu-v4-self-hosted\n linux-container-preset: kungfu-verify\n artifact-name-template: \"{artifact}-{platform}-{sha}\"\n artifact-paths: |\n dist\n build/stage\n expected-artifacts-json: >-\n {\"minFiles\":2,\"requiredPaths\":[\"dist/libnode.tar.gz\",\"dist/checksums.txt\"]}\n process-summary-path: .buildchain/diagnostics/process-summary.json\n release-candidate: true\n publish-channel: release\n publish-source-ref: publish-gate/release/v22/v22.22/22.22.3-kf.0\n```\n\n`runner-preset` is the stable first-class surface for known runner fleets:\n\n| Preset | Platforms |\n| ----------------------- | ------------------------------------------------------------------------ |\n| `github-hosted` | `ubuntu-24.04`, `macos-latest`, `windows-2022` |\n| `kungfu-v4-self-hosted` | Kungfu Linux x64, macOS ARM64, and Windows x64 self-hosted runner labels |\n| `custom` | Requires `platforms-json` |\n\nCallers can still provide a custom matrix with `platforms-json`. Each platform\nobject has:\n\n| Field | Meaning |\n| -------- | ------------------------------------------------- |\n| `id` | Stable artifact/platform key, such as `linux-x64` |\n| `name` | Human-readable job name |\n| `runner` | JSON string passed to `runs-on` after `fromJSON` |\n\nThe runner field is intentionally a JSON string so callers can pass either\nGitHub-hosted runners or multi-label self-hosted runners without Buildchain\nguessing the labels.\n\nOnly include platforms that should run. GitHub schedules matrix jobs before\nsteps execute, so a disabled entry with unavailable runner labels can still\nblock the workflow queue.\n\n## Linux Job Containers\n\nLinux build platforms can run inside a digest-pinned job container while macOS\nand Windows keep using native runners. This is the recommended way to remove\nmoving Linux runner prerequisites from Buildchain consumers: the Linux host only\nneeds a GitHub Actions runner, Docker, and network access; common verification\ntools come from the image contract.\n\nUse the Kungfu verification image for lifecycle stages that need Git, jq,\nPython, uv, and fnm, but do not need native compilation:\n\n```yaml\njobs:\n build:\n uses: kungfu-systems/buildchain/.github/workflows/.build.yml@v2\n with:\n runner-preset: kungfu-v4-self-hosted\n linux-container-preset: kungfu-verify\n```\n\n`kungfu-verify` resolves to:\n\n```text\nghcr.io/kungfu-systems/build-images/kungfu-verify@sha256:11f0ba64267ce88174a4f73a9bf833ff4e9c59cd16ec3d08a6432a06c2be6fb1\n```\n\nCallers that own a different Linux image can pass it explicitly:\n\n```yaml\nwith:\n linux-container-preset: custom\n linux-container-image: ghcr.io/example/project-build@sha256:<digest>\n```\n\n`linux-container-image` should be pinned by digest. A floating tag makes the\nrunner surface mutable and weakens Buildchain's release evidence.\n\nThe workflow splits the matrix into two build jobs:\n\n- Linux platforms go to `build-linux-container` when a Linux container is\n configured.\n- All other platforms go to `build-native`.\n\nArtifact names, manifest paths, expected artifact checks, publish-source locks,\nand aggregate summaries are the same in both jobs. The split is an execution\ndetail, not a different artifact contract.\n\nThe container image provides `fnm` but does not preinstall Node. Buildchain uses\n`fnm` inside the container to install the requested `node-version` before it\nruns Buildchain runtime scripts or lifecycle actions.\n\nDo not use `kungfu-verify` for stages that need CMake, Ninja, ccache, Conan, or\nDocker image publishing. Those should use a heavier native-build image or remain\non a host runner until their image contract is explicit.\n\n## Buildchain Runtime Override\n\nStable consumers should keep the reusable workflow pinned to stable refs such as\n`@v2`. The optional `buildchain-ref` input is empty by default; empty means\nBuildchain resolves and executes the stable runtime selected by the workflow\nshell. The full train validation protocol is documented in\n[`runtime-train-validation.md`](runtime-train-validation.md).\n\nFor one-off manual validation, a trusted maintainer can run the caller workflow\nwith a temporary runtime override:\n\n```yaml\non:\n workflow_dispatch:\n inputs:\n buildchain-ref:\n description: \"Temporary Buildchain runtime ref for trusted manual validation\"\n required: false\n default: \"\"\n\njobs:\n build:\n uses: kungfu-systems/buildchain/.github/workflows/.build.yml@v2\n with:\n buildchain-ref: ${{ inputs.buildchain-ref || '' }}\n```\n\nAllowed override refs are deliberately narrow:\n\n| Ref form | Meaning |\n| --- | --- |\n| `train/v2/v2.3/<capability>` | Temporary capability train under the active minor line |\n| `refs/heads/train/v2/v2.3/<capability>` | Explicit branch ref for the same train |\n| `<40-character SHA>` | Exact immutable Buildchain runtime commit |\n\nOverride requests fail closed unless the event is `workflow_dispatch` and the\nactor has write, maintain, or admin permission on the caller repository.\nPull requests, including same-repository pull requests and fork-originated pull\nrequests, cannot use `buildchain-ref` override. This keeps automated PR builds on\nthe stable runtime surface.\n\nEvery run resolves the runtime ref to an immutable SHA before checkout. The job\nsummary and aggregate build summary record the workflow shell ref, requested\nruntime ref, resolved runtime ref, runtime SHA, stability class, trust decision,\nand rollback ref. Train refs are development validation refs: they do not move\n`v2`, `vX.Y`, `vX.Y-alpha`, npm dist-tags, or production release refs, and they\nmust not be pinned as long-term production dependencies.\n\nRuntime override validates Buildchain runtime scripts, CLI code, local actions,\nconfig parsing, and lifecycle behavior. It cannot validate changes that require\nthe outer reusable workflow YAML itself to change, such as new jobs,\npermissions, workflow outputs, or matrix topology. Those changes need a canary\nworkflow path or a temporary explicit workflow ref.\n\n## Floating Ref Contract Lock\n\nStable consumers should use floating major refs such as `@v2`, but a floating\nref is not blind trust. Each released Buildchain ref carries a package-owned\nruntime contract world in `dist/site/buildchain-contract.json`. Consumers may\nkeep a small lock file, `.buildchain/contract-lock.json`, recording the\nBuildchain ref, resolved SHA, contract digest, compatibility digest, accepted\nmajor line, and compatibility policy they reviewed.\n\nThe reusable build trust gate checks this lock before any heavy matrix job:\n\n1. resolve the Buildchain runtime ref, for example `v2`, to an immutable SHA;\n2. read `dist/site/buildchain-contract.json` from that checked-out Buildchain\n ref;\n3. read the consumer's `.buildchain/contract-lock.json`;\n4. compare the accepted contract with the current contract.\n\nSHA drift alone is not a failure. `v2` is expected to advance. Buildchain only\nfails fast when the accepted contract is no longer compatible, for example a\nrequired input is removed, a required output disappears, a protected behavior\npromise changes, or the major line changes. Additive changes such as optional\ninputs, optional outputs, diagnostics, or documentation updates continue under\nthe default `major-compatible` policy.\n\n```yaml\njobs:\n build:\n uses: kungfu-systems/buildchain/.github/workflows/.build.yml@v2\n permissions:\n contents: read\n issues: write\n id-token: write\n with:\n buildchain-contract-lock-path: .buildchain/contract-lock.json\n buildchain-contract-compatibility-policy: major-compatible\n buildchain-contract-drift-issue-mode: compatible-and-breaking\n```\n\nWhen compatible drift is detected, the build continues and Buildchain opens or\nupdates a low-priority issue in the consumer repository. The issue records the\nold SHA/digest, new SHA/digest, compatibility result, workflow run, and the next\naction: review the Buildchain release notes and update the lock. When breaking\ndrift is detected, the same issue path is used, but the trust gate fails before\nmatrix build or publish work starts. If the workflow token cannot write issues,\nBuildchain writes a copyable issue body into the job summary.\n\nThe lock is intentionally small. It does not copy the full contract. The full\ncontract remains in the Buildchain ref and package; the consumer records only\nwhat it accepted and the policy used to compare future floating-ref movement.\n\nAdvanced alpha-channel consumers select the matching workflow shell:\n\n```yaml\njobs:\n build:\n uses: kungfu-systems/buildchain/.github/workflows/.build.yml@v2-alpha\n with:\n buildchain-contract-lock-path: .buildchain/contract-lock.json\n```\n\nThe runtime follows the called workflow through `job.workflow_ref`. Callers may\nalso pass `buildchain-ref: v2-alpha` explicitly; official floating refs are\nordinary channel selections and are allowed on pull requests and pushes. Train\nrefs and exact SHAs remain trusted manual overrides.\n\n## Locked Source Checkout Cache\n\nSelf-hosted runners that build large repositories can opt into a locked checkout\ncache for both the consumer source and the Buildchain runtime. This changes only\nthe Git object transport. Buildchain still resolves `publish-source-sha` and the\nruntime SHA before any build runner starts, checks out those exact commits, and\nverifies each final `HEAD` plus the resolved consumer source tree SHA before\nlifecycle commands run.\n\n```yaml\njobs:\n build:\n uses: kungfu-systems/buildchain/.github/workflows/.build.yml@v2\n with:\n runner-preset: kungfu-v4-self-hosted\n checkout-cache-mode: auto\n checkout-cache-mirror-url-template: ${{ vars.BUILDCHAIN_CHECKOUT_CACHE_MIRROR_URL_TEMPLATE }}\n checkout-cache-reference-repository-template: ${{ vars.BUILDCHAIN_CHECKOUT_CACHE_REFERENCE_REPOSITORY_TEMPLATE }}\n checkout-cache-fallback: github\n checkout-cache-timeout-seconds: 60\n checkout-cache-github-timeout-seconds: 600\n checkout-cache-fetch-attempts: 3\n```\n\n`checkout-cache-mode` accepts:\n\n| Mode | Behavior |\n| --- | --- |\n| `off` | Default. Buildchain fetches the locked commit from GitHub. |\n| `auto` | Try the trusted cache first; on miss, record the miss and fall back according to `checkout-cache-fallback`. |\n| `require` | Require the cache to provide the locked commit and fail before lifecycle work if unavailable. |\n\nThe cache can be a local/LAN mirror URL template or a runner-local bare\nreference repository template. Templates support `{owner}`, `{repo}`,\n`{repository}`, `{repositorySlug}`, and `{sha}`. The workflow also reads\nrepository or organization variables named\n`BUILDCHAIN_CHECKOUT_CACHE_MIRROR_URL_TEMPLATE` and\n`BUILDCHAIN_CHECKOUT_CACHE_REFERENCE_REPOSITORY_TEMPLATE`, so consumers can keep\nprivate LAN topology out of repository YAML.\n\nThe GitHub-hosted trust gate resolves the reusable workflow shell to an exact\ncommit and uploads that shell's small checkout bootstrap script. Native and\nLinux-container build jobs download the bootstrap, then use the same cache\npolicy to obtain both the selected Buildchain runtime and consumer source at\ntheir already resolved immutable SHAs. Keeping the bootstrap owned by the\nworkflow shell is important when `@vN-alpha` routes a stable release to an older\n`vN` runtime: the stable runtime does not need to already contain the newest\ncheckout transport implementation. This also prevents a large direct\n`actions/checkout` runtime clone from becoming a separate timeout path on\nconstrained self-hosted uplinks. The bootstrap artifact does not contain the\nruntime repository and cannot move either selected ref.\n\nDo not read cache URLs or reference paths from PR-controlled files such as\n`.buildchain/buildchain.toml`. These values are trusted workflow inputs or repo/org\nvariables. Buildchain does not pass GitHub credentials to cache mirrors or\nreference repositories. If it must fall back to GitHub, the workflow token is\nused only for the GitHub fetch path. Cache attempts use\n`checkout-cache-timeout-seconds`; the potentially larger GitHub fallback uses\nthe independent `checkout-cache-github-timeout-seconds` budget (600 seconds by\ndefault). Buildchain fetches the advertised source ref before trying an exact\nSHA, so a cache hit or stale-cache seed can contribute objects and the fallback\ndoes not first waste a full timeout on an unadvertised SHA. Retryable timeout\nand transient network failures use the bounded `checkout-cache-fetch-attempts`\nbudget; permanent failures stop immediately. Diagnostics record both timeout\nbudgets and the actual GitHub fetch attempts before exact HEAD/tree\nverification.\n\nEach platform diagnostics artifact includes `source-checkout.json` and embeds a\ncompact `sourceCheckout` summary in `diagnostics.json`: mode, transport,\nhit/miss, fallback reason, duration, final HEAD verification, and tree\nverification. Remote URLs are sanitized and local reference paths are represented\nby a short display name plus fingerprint, not by secret-bearing credentials.\nRuntime checkout evidence is uploaded separately as `runtime-checkout.json`,\nincluding cache transport, fallback attempts, and exact runtime `HEAD`\nverification, even when a later lifecycle step fails.\n\nWhen a Buildchain maintainer asks for downstream validation, the expected\nrequest is:\n\n```text\nBuildchain train ready: buildchain-ref=train/v2/v2.3/<capability>.\nKeep uses: ...@v2; run workflow_dispatch with that buildchain-ref and report the runtime evidence summary.\n```\n\nAfter validation succeeds, the Buildchain change should continue through the\nnormal mainline and release path. Do not treat the train as a pending merge\nitem; it is only a temporary fast-use, diagnostic, and rollback channel. It may\nremain for a retention window after release, with old trains handled by a\nseparate periodic cleanup task.\n\n## Workflow Outputs\n\nThe reusable workflow exposes the resolved contract:\n\n| Output | Meaning |\n| --------------------------------- | ------------------------------------------------------------------------------- |\n| `runner-preset` | Resolved preset, or `custom` when `platforms-json` was provided |\n| `platforms-json` | Exact matrix JSON used by the build job |\n| `platform-count` | Number of matrix platforms |\n| `linux-container-enabled` | `true` when Linux platforms are routed through a job container |\n| `linux-container-image` | Resolved digest-pinned Linux job container image |\n| `build-summary-artifact` | Uploaded aggregate summary artifact name |\n| `build-diagnostics-summary-artifact` | Uploaded aggregate diagnostics summary artifact name |\n| `release-candidate-passport-artifact` | Uploaded PR-stage release-candidate passport artifact name when `release-candidate` is enabled |\n| `release-candidate-passport-json` | Compact release-candidate passport JSON when `release-candidate` is enabled |\n| `build-summary-json` | Compact aggregate JSON with platform count, file count, and byte total |\n| `build-diagnostics-summary-json` | Compact aggregate diagnostics JSON with platform, lifecycle warning/error, diagnostics contract warning, and sidecar manifest warning totals |\n| `trusted-event` | `true` when the event is trusted enough to reach build runners |\n| `buildchain-runtime-ref` | Runtime ref selected after applying the empty-default or override policy |\n| `buildchain-runtime-sha` | Immutable Buildchain runtime commit used by all runtime checkouts |\n| `buildchain-runtime-class` | `stable`, `alpha`, `train`, `exact-sha`, or `development` |\n| `buildchain-runtime-override` | `true` when a train or exact-SHA `buildchain-ref` override was accepted |\n| `buildchain-runtime-trust-decision` | Runtime override trust decision |\n| `buildchain-contract-lock-status` | `unchanged`, `compatible-drift`, `breaking-drift`, `missing-lock`, `non-floating-runtime`, or first-release `runtime-contract-unavailable` |\n| `buildchain-contract-lock-drift` | `true` when the floating runtime SHA or contract digest changed |\n| `buildchain-contract-digest` | Current Buildchain runtime contract digest |\n| `publish-channel` | Resolved publish channel requested by the caller |\n| `publish-allowed` | `true` only when this event/ref may publish after verification |\n| `publish-reason` | Human-readable reason for the publish gate decision |\n| `publish-source-ref` | Gate source ref that was resolved before checkout |\n| `publish-source-sha` | Exact source commit used by checkout, build, verify, and artifacts |\n| `publish-source-locked` | `true` when a `publish-gate/*` source ref was explicitly locked |\n| `publish-source-channel` | `alpha`, `release`, `anchor`, or `major` parsed from the source ref |\n| `publish-source-line` | Product line parsed from source refs such as `v22/v22.22` |\n| `publish-source-consumer-version` | Consumer package version parsed from source refs |\n| `release-manifest-json` | Resolved release manifest including source lock, version state, and anchor data |\n\nThe aggregate summaries are intentionally artifacts as well as outputs. GitHub\nActions matrix outputs are not a reliable place to carry every platform's full\nmanifest, so Buildchain uploads each platform manifest and then emits one\naggregate build summary artifact after the matrix completes. Buildchain uploads\n`diagnostics-summary.json` as a separate aggregate diagnostics summary artifact,\na compact rollup of each platform's small diagnostics upload. The rollup keeps\nper-platform runner facts, checked tool versions/missing tools, package\nmanager/cache directory details, compiler-cache availability, lifecycle timing,\nprocess sampler context, and links back to the exact platform artifacts. Each\nplatform diagnostics upload includes `diagnostics.json`,\n`diagnostics-manifest.json`, the lifecycle `events.jsonl`, and process sampler\nsidecars when enabled, so slow-build diagnosis does not require downloading the\nbinary platform artifact or the aggregate build summary. The sidecar manifest\nrecords the uploaded diagnostics files with bytes and sha256 hashes. Each\n`diagnostics.json` also records the related binary artifact name, manifest\nartifact name, diagnostics artifact name, diagnostics sidecar manifest path, and\nplatform id in `links`, so a reviewer can navigate from the small diagnostics\nartifact back to the exact platform outputs when deeper inspection is needed.\nThe workflow output `build-diagnostics-summary-json` includes\n`diagnosticsContractWarningCount` and `diagnosticsManifestWarningCount` so\nrelease jobs can detect drifting diagnostics JSON contracts and missing or\ndrifting diagnostics sidecar manifests without downloading the per-platform\ndiagnostics artifacts first.\n\n## Artifact Transfer Relay\n\nBy default, platform jobs upload payloads, manifests, and diagnostics directly\nto GitHub artifacts:\n\n```yaml\nwith:\n artifact-transfer-mode: github-artifacts\n```\n\nLarge self-hosted native builds can opt into the first-class S3 relay path:\n\n```yaml\njobs:\n build:\n uses: kungfu-systems/buildchain/.github/workflows/.build.yml@v2\n with:\n runner-preset: kungfu-v4-self-hosted\n artifact-transfer-mode: s3-to-github-artifacts\n artifact-relay-s3-bucket: ${{ vars.BUILDCHAIN_ARTIFACT_RELAY_S3_BUCKET }}\n artifact-relay-s3-region: ${{ vars.BUILDCHAIN_ARTIFACT_RELAY_S3_REGION }}\n artifact-relay-s3-prefix: ${{ vars.BUILDCHAIN_ARTIFACT_RELAY_S3_PREFIX }}\n```\n\nIn relay mode, each self-hosted platform job uploads the heavy payload files to\nS3 and uploads only a small `relay-manifest.json` to GitHub. A GitHub-hosted\n`relay-artifacts` job then assumes the configured download role, downloads the\npayloads from S3, verifies every file by SHA256, and re-uploads the normal\nGitHub artifacts under the same artifact names that direct mode uses. Downstream\nsummary, release-candidate, and promote-only workflows therefore continue to\nconsume GitHub artifacts and do not need custom S3 logic.\nThe relay implementation uses Node.js plus the standard AWS environment\ncredentials from GitHub OIDC; runner images and build containers do not need the\nAWS CLI installed.\n\nAfter the GitHub artifact uploads succeed, Buildchain deletes the S3 objects\nlisted in the relay manifest for that platform. If any download, verification,\nor GitHub artifact upload fails, cleanup is skipped so maintainers can inspect\nthe retained S3 payload. Configure a short bucket lifecycle expiration as a\ncost and cleanup backstop.\n\nThe relay configuration is intentionally generic. Buildchain does not hard-code\norganization buckets, regions, or role ARNs. Callers may pass explicit inputs,\nor set repository/organization variables and secrets using these names:\n\n| Variable or secret | Meaning |\n| --- | --- |\n| `BUILDCHAIN_ARTIFACT_RELAY_S3_BUCKET` | Relay bucket name |\n| `BUILDCHAIN_ARTIFACT_RELAY_S3_REGION` | Relay bucket region |\n| `BUILDCHAIN_ARTIFACT_RELAY_S3_PREFIX` | Relay object prefix; defaults to `buildchain-artifacts` |\n| `BUILDCHAIN_ARTIFACT_RELAY_S3_ROLE_ARN` | Shared OIDC role ARN for upload and download |\n| `BUILDCHAIN_ARTIFACT_RELAY_S3_UPLOAD_ROLE_ARN` | Upload OIDC role ARN for self-hosted build jobs |\n| `BUILDCHAIN_ARTIFACT_RELAY_S3_DOWNLOAD_ROLE_ARN` | Download OIDC role ARN for the GitHub-hosted relay job |\n| `BUILDCHAIN_ARTIFACT_RELAY_S3_OIDC_AUDIENCE` | Optional OIDC audience override |\n\nFor AWS China regions, Buildchain defaults the OIDC audience to\n`sts.amazonaws.com.cn`; other regions default to `sts.amazonaws.com`. The caller\nworkflow must allow `id-token: write`, and the target role trust policy should\nrestrict GitHub OIDC claims to the expected organization, repository, workflow,\nand branch/ref. The S3 permissions should be scoped to the relay bucket/prefix\nused by the repository.\nUpload roles need write/delete access under the relay prefix; download roles\nneed read access plus delete access for successful cleanup.\n\nRelay mode is opt-in and does not affect forks or open-source users that do not\nconfigure S3. Missing bucket, region, upload role, or download role values fail\nbefore the heavy build matrix is scheduled. Buildchain treats S3 as a transport\ncache, not as the final release evidence store; the final audit entry remains\nthe GitHub artifact set plus the Buildchain build summary and release-candidate\npassport.\n\nSet `release-candidate: true` when the successful reusable build is meant to be\nthe artifact source promoted later. Buildchain then uploads\n`release-candidate-passport.json` under the\n`<artifact-name>-release-candidate-<publish-source-sha>` artifact name. Promotion\njobs can pass that passport to `promote-buildchain-ref` with\n`promote-only-release-candidate: \"true\"` so source, channel, platforms, and the\naggregate build-summary hash are checked before publish-gate side effects. The\npassport records the locked commit's Git tree SHA, so a post-merge channel HEAD\ncan be accepted only when it is tree-equivalent to the PR-stage build evidence.\n\n## Publish Gate\n\nBuildchain separates \"may build/verify\" from \"may publish.\" A same-repository\npull request may be trusted enough to run the build matrix, but it still must\nnot publish packages, S3 objects, release pages, or preview aliases. Publishing\nis allowed only when the caller explicitly requests a channel and the current\nevent/ref matches that channel.\n\nUse `publish-channel` to request a channel:\n\n```yaml\njobs:\n build:\n uses: kungfu-systems/buildchain/.github/workflows/.build.yml@v2\n with:\n publish-channel: release\n\n publish:\n needs: build\n if: ${{ needs.build.outputs.publish-allowed == 'true' }}\n runs-on: ubuntu-24.04\n steps:\n - run: ./scripts/publish.sh\n```\n\nDefault channels are:\n\n| Channel | Allowed refs |\n| --------- | ---------------------------------------------------------------------------------------------------- |\n| `none` | Never publishes; this is the default |\n| `alpha` | `alpha/vN/vN.M` branches or exact `vN.M.P-alpha.K` tags |\n| `release` | `release/vN/vN.M` branches or release tags such as `vN.M.P`, `vN.M`, `vN` |\n| `major` | `publish-gate/major`, legacy `major-gate`, or next-major release tags such as `vN.0.0`, `vN.0`, `vN` |\n\nPull request events always produce `publish-allowed=false`, even when the PR is\nfrom the same repository. Untrusted fork events also produce\n`publish-allowed=false`; with the default `untrusted-policy: fail`, the workflow\nthen fails before any build runner starts.\n\nProjects with their own channel names can pass `publish-refs-json`:\n\n```yaml\nwith:\n publish-channel: nightly\n publish-refs-json: >-\n {\"nightly\":[\"^refs/heads/nightly/v\\\\d+$\"]}\n```\n\nThe aggregate build summary includes the same publish gate decision under\n`publishGate`, so a downloaded artifact summary explains both what was built and\nwhy it was or was not eligible to publish.\n\n## Publish Source Lock\n\n`publish-channel` answers \"may this event publish?\" Source lock answers \"which\nsource tree is the publish decision about?\" A caller can pass `publish-source-ref`\nto bind a publish run to a reviewed gate branch before any checkout happens:\n\n| Ref | Meaning |\n| ------------------------------------------------ | --------------------------------------------------------------------------- |\n| `publish-gate/alpha/<line>/<consumer-version>` | Build and publish an alpha candidate for a consumer line |\n| `publish-gate/release/<line>/<consumer-version>` | Build and publish a production candidate for a consumer line |\n| `publish-gate/anchor` | Resolve an explicit anchor request; it does not publish artifacts by itself |\n| `publish-gate/major` | Gate the next major source state |\n| `major-gate` | Legacy compatibility alias for the major gate |\n\nFor alpha and release refs, `<line>` is intentionally allowed to contain `/`, so\nKungfu-style lines such as `v22/v22.22` stay readable. The final path segment is\nthe consumer-visible version, for example `22.22.3-kf.0`.\n\nThe reusable workflow resolves the branch tip to `publish-source-sha`, checks out\nthat SHA in every build job, and uses the same SHA in artifact names, manifests,\nand aggregate summaries. Reruns therefore rebuild the same source tree even if a\ngate branch moves later.\n\nBefore any heavy build matrix is scheduled, the workflow also verifies that the\ntarget channel ref implied by the source lock already points at\n`publish-source-sha` and that the target channel HEAD came from the required\nmerged same-repository channel PR. `publish-gate/alpha/<line>/<version>` must\nmatch `alpha/<line>` and have PR lineage `dev/<line> -> alpha/<line>`;\n`publish-gate/release/<line>/<version>` must match `release/<line>` and have PR\nlineage `alpha/<line> -> release/<line>`. If either check fails, the run fails\nfast with a diagnostic telling maintainers to merge the source commit through\nthe channel PR first. This keeps verify from spending runner time on a source\ntree that cannot legally enter the requested publish channel.\n\nThe resolved release manifest is uploaded as an artifact and emitted as\n`release-manifest-json`. It records:\n\n- source ref, source SHA, channel, line, and consumer version;\n- configured version strategy and configured version-state files;\n- each version file's value, with release gates failing closed if the configured\n files do not equal the consumer version;\n- anchor manifest summary for anchored/manual projects;\n- explicit anchor request JSON for `publish-gate/anchor`;\n- publish registry, dist-tag, and gate visibility metadata.\n\nPublish side-effect jobs should verify the lock immediately before publishing:\n\n```yaml\n- name: Verify publish gate did not move\n run: node .buildchain/runtime/scripts/verify-publish-source-lock.mjs\n env:\n BUILDCHAIN_PUBLISH_SOURCE_REF: ${{ needs.build.outputs.publish-source-ref }}\n BUILDCHAIN_PUBLISH_SOURCE_SHA: ${{ needs.build.outputs.publish-source-sha }}\n BUILDCHAIN_SOURCE_REPOSITORY: ${{ github.repository }}\n GITHUB_TOKEN: ${{ github.token }}\n```\n\nIf the branch tip no longer matches the manifest SHA, the publish job must fail\nclosed. Moving a gate branch creates a new publish decision and should produce a\nnew build run.\n\n## Release Candidate Promote-Only\n\nFor native package sets, the PR build is the only heavy build. When a PR targets\n`alpha/<line>` or `release/<line>`, `.build.yml` uploads a release-candidate\nbundle next to the platform artifacts. The bundle contains:\n\n- `release-candidate.passport.json`;\n- the aggregate `build-summary.json`;\n- copied platform manifest evidence for the built platforms.\n\nThe passport records two separate source identities:\n\n- `builtSourceSha` / `builtSourceTreeSha`: the PR-stage source that produced the\n artifacts, usually the PR merge ref;\n- `promotionChannelSha` / `promotionChannelTreeSha`: the post-merge channel\n commit used for publish authority.\n\nThe reusable promote wrapper resolves the merged PR, finds exactly one matching\nPR-stage release-candidate artifact, downloads it with the build summary and\npayload artifacts from the same PR-stage run, validates the payload count,\ncompares the built tree with the promotion channel tree, locks\n`publish-gate/{alpha,release,major}` to the promotion channel commit, and then\ncalls `actions/promote-buildchain-ref` with\n`promote-only-release-candidate: \"true\"` and\n`require-publish-source-lock: \"true\"`. The wrapper passes the created\n`publish-gate/*` ref, target SHA, and `locked=true` into the promote action, so\nfloating `@v2` consumers receive publish-side source-lock drift protection by\ndefault. It also defaults `branch-protection-bypass-apps` to `github-actions`\nso the workflow automation can apply generated version-state and channel\nbookkeeping on protected `dev`/`alpha`/`release` branches after the reviewed\nchannel PR has merged; consumers using a different promotion identity can pass\n`branch-protection-bypass-users`, `branch-protection-bypass-teams`, or a\ndifferent app slug declaratively. The wrapper uses\n`secrets.BUILDCHAIN_PROMOTION_TOKEN || github.token` as the generated ref update\ntoken for protected bookkeeping PATCH calls, so a bypass-capable promotion token\ncan sync dev immediately after alpha/release publish without a post-publish PR.\nIt does not call `.build.yml`, does not create a matrix, and must fail before\npublish if the RC evidence, payload set, or source-lock ref is missing or\nambiguous.\n\n```yaml\njobs:\n promote:\n uses: kungfu-systems/buildchain/.github/workflows/release-candidate-promote.yml@v2\n secrets:\n buildchain-issue-app-id: ${{ secrets.BUILDCHAIN_ISSUE_APP_ID }}\n buildchain-issue-app-private-key: ${{ secrets.BUILDCHAIN_ISSUE_APP_PRIVATE_KEY }}\n with:\n channel: alpha\n target-ref: alpha/v22/v22.22\n artifact-name: libnode\n # Defaults to build.yml / Build. Override only when the PR-stage build\n # workflow uses a different file or display name.\n release-candidate-workflow-file: build.yml\n release-candidate-workflow-name: Build\n package-manager: npm\n publish-target: npm\n runner-preset: github-hosted\n trusted-publishing: true\n github-release: true\n required-status-check: check / check\n required-artifact-count: 3\n publish-dist-tag: alpha\n publish-package-set-order: platforms-first-main-last\n publish-package-main: \"@kungfu-tech/libnode\"\n release-passport-product-name: Libnode\n buildchain-contract-lock-path: .buildchain/contract-lock.json\n buildchain-contract-drift-issue-mode: compatible-and-breaking\n```\n\n`buildchain-issue-app-id` and `buildchain-issue-app-private-key` are optional\nbut recommended for cross-repository consumers. They should identify a GitHub\nApp installation with `issues: write` on `kungfu-systems/buildchain`; the\nwrapper mints the installation token before calling\n`actions/report-buildchain-issue`. Consumers can also pass a pre-minted\n`buildchain-issue-token`. If both are omitted, the wrapper falls back to\n`BUILDCHAIN_ISSUE_TOKEN`, `BUILDCHAIN_PROMOTION_TOKEN`, and then the consumer\nworkflow's `github.token`; the last fallback can only report issues when it has\nwrite access to the target Buildchain repository.\n\n`publish-required-artifacts-json` can still be passed explicitly for custom\npublish targets. For the default `publish-artifact-kind: npm` path, consumers do\nnot download artifacts or run repository scripts to build publish evidence. The\nwrapper downloads the PR-stage payload artifacts, finds the downloaded `.tgz`\npackages, reads each tarball's `package/package.json` for the real scoped\npackage name and version, computes the npm `sha512-...` integrity from the\ntarball bytes, marks the package matching `publish-package-main` as `role:\nmain`, marks the rest as `role: platform`, and passes the generated\n`publish-required-artifacts-json` to `promote-buildchain-ref` before any publish\nside effect. Downloaded platform manifests are still passed into the release\npassport unless `release-passport-platform-manifest-paths` is set explicitly.\nThe same Buildchain contract lock check runs before release-candidate\nresolution and before publish. A compatible `v2` drift leaves an issue in the\nconsumer repository but does not trigger a second heavy build; an incompatible\ndrift fails before publish side effects.\n\nThe wrapper publishes the public release tag as a GitHub Release by default.\nAfter `promote-buildchain-ref` reports a complete release transaction, the\nwrapper creates or updates the public release, marks semver prerelease tags\nsuch as `v1.2.3-alpha.0`, `v1.2.3-rc.1`, or `v22.22.3-kf.3-alpha.7` as\n`prerelease=true` and `make_latest=false`, marks stable semver tags as latest,\nand uploads the publish evidence file plus every file in the generated release\npassport directory, including `buildchain.release.json` and `check-report.json`.\nFor anchored/manual package releases, the public release tag is derived from the\npublished package version and the internal exact transaction tag remains\navailable in the release passport.\nConsumers do not need to hand-write `gh release` logic to trigger\n`release.published` propagation. Set `github-release: false` only for\nrepositories that intentionally do not maintain GitHub Releases.\nIf the transaction still needs protected-ref finalization, the wrapper defers\nGitHub Release creation until the later run that reaches `state=complete`.\n\nCustom publish jobs can also repeat the channel-ref preflight:\n\n```yaml\n- name: Verify publish channel ref still matches\n run: node .buildchain/runtime/scripts/verify-publish-channel-ref.mjs\n env:\n BUILDCHAIN_PUBLISH_SOURCE_REF: ${{ needs.build.outputs.publish-source-ref }}\n BUILDCHAIN_PUBLISH_SOURCE_SHA: ${{ needs.build.outputs.publish-source-sha }}\n BUILDCHAIN_SOURCE_REPOSITORY: ${{ github.repository }}\n GITHUB_TOKEN: ${{ github.token }}\n```\n\nAnchored/manual package release jobs should also make the Buildchain promotion\naction validate that publication is entering through the same\n`publish-gate/{alpha,release,major}` source-lock contract before any package\npublish side effect:\n\n```yaml\n- name: Promote release ref and publish npm package set\n uses: kungfu-systems/buildchain/actions/promote-buildchain-ref@v2\n with:\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```\n\n`target-ref` stays the Buildchain channel promotion target, such as\n`alpha/v22/v22.22`, `release/v22/v22.22`, or `publish-gate/major`.\n`publish-source-ref` is the reviewed source-lock branch that authorized this\nspecific package publication. For alpha and release package publications, the\nsource-lock branch must point at the exact channel-line commit that promotion is\nvalidating; it is not a replacement for `target-ref`.\n\nThis keeps the version bump commit, publish authorization, and auditable publish\nentrypoint on the Buildchain source-lock protocol. The CLI form\n`buildchain publish-source validate-anchored-release --json` is still useful for\ncustom publish scripts, but the preferred GitHub Actions gate is the promotion\naction input above. A publish job that still runs directly from `alpha/*` or\n`release/*` channel branches fails this check because those refs are channel\nstate, not publish-gate decisions.\n\n## Package-Set Publish Plan\n\nProjects that publish multiple packages should treat package publication as a\npackage-set operation. Buildchain's package-set planner uses these rules:\n\n- platform packages publish first;\n- the main package publishes last;\n- the dist-tag move happens only after the full package set is present;\n- reruns accept already-published packages only when package name, version, and\n integrity match;\n- an existing package with different integrity is a hard failure.\n\nThis keeps a consumer from observing a floating dist-tag that points to a main\npackage before all platform artifacts for the same source SHA are available.\n\n## Command Sources\n\nThe workflow runs `.buildchain/buildchain.toml` lifecycle stages by default:\n\n```toml\n[lifecycle.install]\ncommand = \"corepack yarn install --immutable\"\n\n[lifecycle.build]\ncommands = [\n \"corepack yarn make\",\n \"corepack yarn build\",\n]\n\n[lifecycle.verify]\ncommand = \"corepack yarn test\"\n```\n\nCallers can override any stage for one invocation:\n\n```yaml\nwith:\n build-command: cmake --build build --config Release\n verify-command: ctest --test-dir build --output-on-failure\n```\n\nThe reusable build workflow samples the build lifecycle by default and carries\nthe generated summary into the final verify diagnostics. Callers can override\nthe sidecar path or disable sampling:\n\n```yaml\nwith:\n sample-process-tree: true\n process-summary-path: .buildchain/diagnostics/process-summary.json\n process-sample-interval-ms: 15000\n requested-parallelism: 20\n```\n\nWhen `sample-process-tree` is true, Buildchain wraps either `build-command` or\nthe configured `lifecycle.build` stage with `buildchain sample process-tree`.\nThe path is relative to the checked-out workspace and is read again during the\nfinal verify lifecycle. Custom workflows can still write their own sampler\nsummary and pass `process-summary-path`; Buildchain reads the file after the\nlifecycle command finishes, so it may be produced during the same invocation.\nWhen the build stage is optional, the reusable workflow treats the default\nsampler path as optional during verify; an explicitly supplied\n`process-summary-path` remains required.\n\nFor custom workflows, use the action directly:\n\n```yaml\n- uses: kungfu-systems/buildchain/actions/run-lifecycle@v2\n with:\n stage: build\n required: \"true\"\n artifact-name: libnode-linux-x64-${{ github.sha }}\n artifact-paths: |\n dist\n build/stage\n```\n\n## Artifact Contract\n\nEach platform upload uses `artifact-name-template`. The default is:\n\n```text\n{artifact}-{platform}-{sha}\n```\n\nSupported placeholders are `{artifact}`, `{artifactName}`, `{platform}`,\n`{platformId}`, `{platformName}`, `{sha}`, `{shortSha}`, `{ref}`, `{runId}`,\nand `{runAttempt}`. Invalid GitHub artifact name characters are normalized to\n`-`, so `{ref}` remains deterministic even for refs such as\n`refs/heads/dev/v2/v2.0`.\n\nEach platform also writes and uploads:\n\n```text\n.buildchain/artifacts/<platform-id>/manifest.json\n.buildchain/artifacts/<platform-id>/summary.json\n```\n\nThe manifest schema is:\n\n```json\n{\n \"schemaVersion\": 1,\n \"contract\": \"kungfu-buildchain-artifact\",\n \"artifactName\": \"libnode-linux-x64-<sha>\",\n \"platform\": {\n \"id\": \"linux-x64\",\n \"name\": \"Linux x64\",\n \"os\": \"Linux\",\n \"arch\": \"X64\"\n },\n \"git\": {\n \"repository\": \"kungfu-systems/libnode\",\n \"sha\": \"<sha>\",\n \"ref\": \"<ref>\",\n \"runId\": \"<run id>\",\n \"runAttempt\": \"<attempt>\"\n },\n \"lifecycle\": {\n \"stage\": \"verify\",\n \"commandSource\": \"buildchain.toml\",\n \"executed\": true\n },\n \"summary\": {\n \"contract\": \"kungfu-buildchain-artifact-summary\",\n \"artifactName\": \"libnode-linux-x64-<sha>\",\n \"fileCount\": 1,\n \"totalBytes\": 1234,\n \"digest\": \"<hex>\"\n },\n \"expectedArtifacts\": {\n \"ok\": true,\n \"source\": \"expected-artifacts-json\",\n \"checks\": []\n },\n \"files\": [\n {\n \"path\": \"dist/example.zip\",\n \"size\": 1234,\n \"sha256\": \"<hex>\"\n }\n ]\n}\n```\n\nArtifact names do not include actor names, timestamps, or retry counters. Reruns\nproduce a new GitHub Actions run but keep the same source SHA/platform contract.\n\n`expected-artifacts-json` fails the build before upload when the artifact does\nnot match the caller's declared contract. Supported checks are:\n\n| Field | Meaning |\n| --------------- | ------------------------------------ |\n| `minFiles` | Minimum number of manifest files |\n| `maxFiles` | Maximum number of manifest files |\n| `minTotalBytes` | Minimum total byte count |\n| `requiredPaths` | Exact manifest paths that must exist |\n\n## Trusted Event Gate\n\nThe workflow has an explicit `trust-gate` job. By default, pull requests from\nforks fail before any build job can reach self-hosted runners, secrets,\npublishing credentials, or heavyweight build commands. Same-repository PRs,\nworkflow dispatches, and protected branch events can proceed.\n\nIf a repository wants fork PRs to skip rather than fail, it can set:\n\n```yaml\nwith:\n untrusted-policy: skip\n```\n\nDo not set `require-trusted-event: false` for workflows that use self-hosted\nrunners or secrets.\n\n`require-trusted-event` controls access to build runners. It does not override\nthe publish gate: pull requests remain non-publishing events.\n\n## Fixture\n\n`fixtures/libnode-shaped` is the contract fixture. It has:\n\n- `package.json` version state;\n- `.buildchain/buildchain.toml` with `install`, `build`, `verify`, and `publish`;\n- cross-platform Node scripts that create small `dist/` outputs;\n- `Build Surface Fixture` workflow coverage.\n\nThe fixture proves the reusable surface without running the real libnode native\nbuild."
|
|
1547
|
+
"markdown": "# Reusable Build Surface\n\nBuildchain v2 provides a reusable build workflow for repositories that need\nBuildchain's release semantics but cannot be described as a simple Node package.\nThe first target shape is `libnode`: expensive native builds, multiple operating\nsystems, self-hosted runner labels, and release artifacts that must be auditable.\n\n## Automatic Channel Router\n\nThe preferred consumer surface is one reusable workflow call. After v2.12\nreaches the stable major ref, consumers keep this configuration for both alpha\ndevelopment and stable release work:\n\n```yaml\njobs:\n build:\n uses: kungfu-systems/buildchain/.github/workflows/build.yml@v2\n permissions:\n contents: read\n issues: write\n id-token: write\n with:\n working-directory: .\n artifact-name: libnode\n runner-preset: kungfu-v4-self-hosted\n publish-channel: none\n secrets: inherit\n```\n\n`buildchain-channel` defaults to `auto`. Selection uses this precedence:\n\n1. an explicit `buildchain-ref` train, SHA, or official channel;\n2. an explicit `buildchain-channel: alpha|stable`;\n3. `publish-channel: alpha|release|major`;\n4. GitHub release prerelease metadata;\n5. a canonical semver tag;\n6. non-release PR, push, dispatch, schedule, and workflow-run events default to\n alpha.\n\nThe resolved runtime is `vN-alpha` for development and prerelease intent and\n`vN` for stable release intent. Unknown custom publish channels, malformed\nrelease events, and non-semver release-like tags fail before the build matrix;\nthey never guess alpha for a stable release.\n\nThe router automatically selects `.buildchain/alpha-contract-lock.json` for\nalpha and `.buildchain/contract-lock.json` for stable. A repository can override\nthe common path with `buildchain-contract-lock-path`, or override one channel\nwith `buildchain-alpha-contract-lock-path` /\n`buildchain-stable-contract-lock-path`.\n\nOnly repositories changing the default policy need extra routing input:\n\n```yaml\nwith:\n buildchain-channel: stable\n```\n\nDuring the v2.12 prerelease evaluation window, canaries use\n`build.yml@v2-alpha`. The same router then selects `v2-alpha` or stable `v2` as\nthe runtime. Production consumers should adopt `build.yml@v2` after the router\nhas reached stable; this keeps the routing shell itself on a stable ref.\n\nThe router is generated from `.build.yml`'s input/output surface. Run\n`node scripts/generate-channel-build-workflow.mjs` after changing the advanced\nbuild workflow; inventory and unit tests reject a stale generated router.\n\n## Advanced Workflow\n\nConsumers that need direct workflow-shell or runtime control call the advanced\nsurface:\n\n```yaml\njobs:\n build:\n uses: kungfu-systems/buildchain/.github/workflows/.build.yml@v2\n with:\n working-directory: .\n artifact-name: libnode\n runner-preset: kungfu-v4-self-hosted\n linux-container-preset: kungfu-verify\n artifact-name-template: \"{artifact}-{platform}-{sha}\"\n artifact-paths: |\n dist\n build/stage\n expected-artifacts-json: >-\n {\"minFiles\":2,\"requiredPaths\":[\"dist/libnode.tar.gz\",\"dist/checksums.txt\"]}\n process-summary-path: .buildchain/diagnostics/process-summary.json\n release-candidate: true\n publish-channel: release\n publish-source-ref: publish-gate/release/v22/v22.22/22.22.3-kf.0\n```\n\n`runner-preset` is the stable first-class surface for known runner fleets:\n\n| Preset | Platforms |\n| ----------------------- | ------------------------------------------------------------------------ |\n| `github-hosted` | `ubuntu-24.04`, `macos-latest`, `windows-2022` |\n| `kungfu-v4-self-hosted` | Kungfu Linux x64, macOS ARM64, and Windows x64 self-hosted runner labels |\n| `custom` | Requires `platforms-json` |\n\nCallers can still provide a custom matrix with `platforms-json`. Each platform\nobject has:\n\n| Field | Meaning |\n| -------- | ------------------------------------------------- |\n| `id` | Stable artifact/platform key, such as `linux-x64` |\n| `name` | Human-readable job name |\n| `runner` | JSON string passed to `runs-on` after `fromJSON` |\n\nThe runner field is intentionally a JSON string so callers can pass either\nGitHub-hosted runners or multi-label self-hosted runners without Buildchain\nguessing the labels.\n\nOnly include platforms that should run. GitHub schedules matrix jobs before\nsteps execute, so a disabled entry with unavailable runner labels can still\nblock the workflow queue.\n\n## Linux Job Containers\n\nLinux build platforms can run inside a digest-pinned job container while macOS\nand Windows keep using native runners. This is the recommended way to remove\nmoving Linux runner prerequisites from Buildchain consumers: the Linux host only\nneeds a GitHub Actions runner, Docker, and network access; common verification\ntools come from the image contract.\n\nUse the Kungfu verification image for lifecycle stages that need Git, jq,\nPython, uv, and fnm, but do not need native compilation:\n\n```yaml\njobs:\n build:\n uses: kungfu-systems/buildchain/.github/workflows/.build.yml@v2\n with:\n runner-preset: kungfu-v4-self-hosted\n linux-container-preset: kungfu-verify\n```\n\n`kungfu-verify` resolves to:\n\n```text\nghcr.io/kungfu-systems/build-images/kungfu-verify@sha256:11f0ba64267ce88174a4f73a9bf833ff4e9c59cd16ec3d08a6432a06c2be6fb1\n```\n\nCallers that own a different Linux image can pass it explicitly:\n\n```yaml\nwith:\n linux-container-preset: custom\n linux-container-image: ghcr.io/example/project-build@sha256:<digest>\n```\n\n`linux-container-image` should be pinned by digest. A floating tag makes the\nrunner surface mutable and weakens Buildchain's release evidence.\n\nThe workflow splits the matrix into two build jobs:\n\n- Linux platforms go to `build-linux-container` when a Linux container is\n configured.\n- All other platforms go to `build-native`.\n\nArtifact names, manifest paths, expected artifact checks, publish-source locks,\nand aggregate summaries are the same in both jobs. The split is an execution\ndetail, not a different artifact contract.\n\n## Native Rust Toolchains\n\nNative lifecycle jobs can request an isolated Rust installation instead of\ndepending on a self-hosted runner user's PATH:\n\n```yaml\nwith:\n setup-rust: true\n rust-toolchain: \"1.96.0\"\n rustup-dist-server: \"https://rsproxy.cn\"\n rustup-update-root: \"https://rsproxy.cn/rustup\"\n cargo-registry-index: ${{ vars.BUILDCHAIN_CARGO_REGISTRY_INDEX }}\n```\n\n`setup-rust` defaults to `false`, so existing consumers are unchanged. When it\nis enabled, Buildchain installs `rust-toolchain` before the install, build, and\nverify lifecycle stages on every native matrix platform. Windows uses the\nofficial rustup bootstrap through `cmd.exe` and `curl.exe` into runner-temporary\nCargo and rustup homes, so it works under a restrictive PowerShell execution\npolicy and the service account does not depend on another user's PATH or mutate\nhost toolchain state. Pin an exact toolchain for release builds. Linux container jobs continue\nto obtain Rust from their digest-pinned image contract; Buildchain does not\nmutate that container surface.\n\nThe rustup server inputs are optional and default to Rust's official servers.\nConsumers behind a slow cross-border link may select a trusted transport mirror;\nrustup still verifies the selected toolchain's distribution metadata and\ncomponent checksums.\n\n`cargo-registry-index` is also optional. When set, Buildchain exposes it to\nCargo as `CARGO_REGISTRIES_CRATES_IO_INDEX` for every native lifecycle stage,\nso a self-hosted runner can use a repository or organization variable without\ncommitting private LAN topology to public workflow YAML. The endpoint must be a\ncrates.io-compatible index whose `config.json` download contract serves the\nmatching checksum-verified crate archives. An empty value preserves Cargo's\nnormal crates.io behavior.\n\nThe container image provides `fnm` but does not preinstall Node. Buildchain uses\n`fnm` inside the container to install the requested `node-version` before it\nruns Buildchain runtime scripts or lifecycle actions.\n\nDo not use `kungfu-verify` for stages that need CMake, Ninja, ccache, Conan, or\nDocker image publishing. Those should use a heavier native-build image or remain\non a host runner until their image contract is explicit.\n\n## Buildchain Runtime Override\n\nStable consumers should keep the reusable workflow pinned to stable refs such as\n`@v2`. The optional `buildchain-ref` input is empty by default; empty means\nBuildchain resolves and executes the stable runtime selected by the workflow\nshell. The full train validation protocol is documented in\n[`runtime-train-validation.md`](runtime-train-validation.md).\n\nFor one-off manual validation, a trusted maintainer can run the caller workflow\nwith a temporary runtime override:\n\n```yaml\non:\n workflow_dispatch:\n inputs:\n buildchain-ref:\n description: \"Temporary Buildchain runtime ref for trusted manual validation\"\n required: false\n default: \"\"\n\njobs:\n build:\n uses: kungfu-systems/buildchain/.github/workflows/.build.yml@v2\n with:\n buildchain-ref: ${{ inputs.buildchain-ref || '' }}\n```\n\nAllowed override refs are deliberately narrow:\n\n| Ref form | Meaning |\n| --- | --- |\n| `train/v2/v2.3/<capability>` | Temporary capability train under the active minor line |\n| `refs/heads/train/v2/v2.3/<capability>` | Explicit branch ref for the same train |\n| `<40-character SHA>` | Exact immutable Buildchain runtime commit |\n\nOverride requests fail closed unless the event is `workflow_dispatch` and the\nactor has write, maintain, or admin permission on the caller repository.\nPull requests, including same-repository pull requests and fork-originated pull\nrequests, cannot use `buildchain-ref` override. This keeps automated PR builds on\nthe stable runtime surface.\n\nEvery run resolves the runtime ref to an immutable SHA before checkout. The job\nsummary and aggregate build summary record the workflow shell ref, requested\nruntime ref, resolved runtime ref, runtime SHA, stability class, trust decision,\nand rollback ref. Train refs are development validation refs: they do not move\n`v2`, `vX.Y`, `vX.Y-alpha`, npm dist-tags, or production release refs, and they\nmust not be pinned as long-term production dependencies.\n\nRuntime override validates Buildchain runtime scripts, CLI code, local actions,\nconfig parsing, and lifecycle behavior. It cannot validate changes that require\nthe outer reusable workflow YAML itself to change, such as new jobs,\npermissions, workflow outputs, or matrix topology. Those changes need a canary\nworkflow path or a temporary explicit workflow ref.\n\n## Floating Ref Contract Lock\n\nStable consumers should use floating major refs such as `@v2`, but a floating\nref is not blind trust. Each released Buildchain ref carries a package-owned\nruntime contract world in `dist/site/buildchain-contract.json`. Consumers may\nkeep a small lock file, `.buildchain/contract-lock.json`, recording the\nBuildchain ref, resolved SHA, contract digest, compatibility digest, accepted\nmajor line, and compatibility policy they reviewed.\n\nThe reusable build trust gate checks this lock before any heavy matrix job:\n\n1. resolve the Buildchain runtime ref, for example `v2`, to an immutable SHA;\n2. read `dist/site/buildchain-contract.json` from that checked-out Buildchain\n ref;\n3. read the consumer's `.buildchain/contract-lock.json`;\n4. compare the accepted contract with the current contract.\n\nSHA drift alone is not a failure. `v2` is expected to advance. Buildchain only\nfails fast when the accepted contract is no longer compatible, for example a\nrequired input is removed, a required output disappears, a protected behavior\npromise changes, or the major line changes. Additive changes such as optional\ninputs, optional outputs, diagnostics, or documentation updates continue under\nthe default `major-compatible` policy.\n\n```yaml\njobs:\n build:\n uses: kungfu-systems/buildchain/.github/workflows/.build.yml@v2\n permissions:\n contents: read\n issues: write\n id-token: write\n with:\n buildchain-contract-lock-path: .buildchain/contract-lock.json\n buildchain-contract-compatibility-policy: major-compatible\n buildchain-contract-drift-issue-mode: compatible-and-breaking\n```\n\nWhen compatible drift is detected, the build continues and Buildchain opens or\nupdates a low-priority issue in the consumer repository. The issue records the\nold SHA/digest, new SHA/digest, compatibility result, workflow run, and the next\naction: review the Buildchain release notes and update the lock. When breaking\ndrift is detected, the same issue path is used, but the trust gate fails before\nmatrix build or publish work starts. If the workflow token cannot write issues,\nBuildchain writes a copyable issue body into the job summary.\n\nThe lock is intentionally small. It does not copy the full contract. The full\ncontract remains in the Buildchain ref and package; the consumer records only\nwhat it accepted and the policy used to compare future floating-ref movement.\n\nAdvanced alpha-channel consumers select the matching workflow shell:\n\n```yaml\njobs:\n build:\n uses: kungfu-systems/buildchain/.github/workflows/.build.yml@v2-alpha\n with:\n buildchain-contract-lock-path: .buildchain/contract-lock.json\n```\n\nThe runtime follows the called workflow through `job.workflow_ref`. Callers may\nalso pass `buildchain-ref: v2-alpha` explicitly; official floating refs are\nordinary channel selections and are allowed on pull requests and pushes. Train\nrefs and exact SHAs remain trusted manual overrides.\n\n## Shifu Cache Profile Passthrough\n\nBuildchain can carry one trusted Shifu cache-profile reference and its exact\ndigest into lifecycle execution. Its contract is an opaque reference and digest\nonly. This surface is deliberately opaque:\nBuildchain does not fetch the profile, parse JSON, select cache services,\nrewrite bindings, decide fallback, or emit Shifu resolution evidence. Those\nsemantics remain owned by the consumer's pinned Shifu implementation.\n\n```yaml\njobs:\n build:\n uses: kungfu-systems/buildchain/.github/workflows/build.yml@v2\n with:\n shifu-cache-profile-ref: ${{ vars.SHIFU_CACHE_PROFILE_REF }}\n shifu-cache-profile-digest: ${{ vars.SHIFU_CACHE_PROFILE_DIGEST }}\n```\n\nThe reusable workflow passes the pair as `SHIFU_CACHE_PROFILE_REF` and\n`SHIFU_CACHE_PROFILE_DIGEST` to install, build, and verify lifecycle commands.\nThe consumer must invoke its Shifu cache-aware execution surface. An empty pair\npreserves existing behavior; a consumer Shifu should fail closed when exactly\none value is present or the resolved bytes do not match the expected digest.\n\nUse trusted repository or organization variables rather than PR-controlled\nfiles for private/LAN references. The variables must remain secret-free; any\ncredentials use a separate provider-approved secret surface and must not be\nembedded in the profile reference. This passthrough is separate from\nBuildchain's locked source checkout cache below: Buildchain owns checkout\ntransport and source identity, while Shifu owns post-checkout execution cache\nbindings and receipts.\n\n## Locked Source Checkout Cache\n\nSelf-hosted runners that build large repositories can opt into a locked checkout\ncache for both the consumer source and the Buildchain runtime. This changes only\nthe Git object transport. Buildchain still resolves `publish-source-sha` and the\nruntime SHA before any build runner starts, checks out those exact commits, and\nverifies each final `HEAD` plus the resolved consumer source tree SHA before\nlifecycle commands run.\n\n```yaml\njobs:\n build:\n uses: kungfu-systems/buildchain/.github/workflows/.build.yml@v2\n with:\n runner-preset: kungfu-v4-self-hosted\n checkout-cache-mode: auto\n checkout-cache-mirror-url-template: ${{ vars.BUILDCHAIN_CHECKOUT_CACHE_MIRROR_URL_TEMPLATE }}\n checkout-cache-reference-repository-template: ${{ vars.BUILDCHAIN_CHECKOUT_CACHE_REFERENCE_REPOSITORY_TEMPLATE }}\n checkout-cache-fallback: github\n checkout-cache-timeout-seconds: 60\n checkout-cache-github-timeout-seconds: 600\n checkout-cache-fetch-attempts: 3\n```\n\n`checkout-cache-mode` accepts:\n\n| Mode | Behavior |\n| --- | --- |\n| `off` | Default. Buildchain fetches the locked commit from GitHub. |\n| `auto` | Try the trusted cache first; on miss, record the miss and fall back according to `checkout-cache-fallback`. |\n| `require` | Require the cache to provide the locked commit and fail before lifecycle work if unavailable. |\n\nThe cache can be a local/LAN mirror URL template or a runner-local bare\nreference repository template. Templates support `{owner}`, `{repo}`,\n`{repository}`, `{repositorySlug}`, and `{sha}`. The workflow also reads\nrepository or organization variables named\n`BUILDCHAIN_CHECKOUT_CACHE_MIRROR_URL_TEMPLATE` and\n`BUILDCHAIN_CHECKOUT_CACHE_REFERENCE_REPOSITORY_TEMPLATE`, so consumers can keep\nprivate LAN topology out of repository YAML.\n\nThe GitHub-hosted trust gate resolves the reusable workflow shell to an exact\ncommit and uploads that shell's small checkout bootstrap script. Native and\nLinux-container build jobs download the bootstrap, then use the same cache\npolicy to obtain both the selected Buildchain runtime and consumer source at\ntheir already resolved immutable SHAs. Keeping the bootstrap owned by the\nworkflow shell is important when `@vN-alpha` routes a stable release to an older\n`vN` runtime: the stable runtime does not need to already contain the newest\ncheckout transport implementation. This also prevents a large direct\n`actions/checkout` runtime clone from becoming a separate timeout path on\nconstrained self-hosted uplinks. The bootstrap artifact does not contain the\nruntime repository and cannot move either selected ref.\n\nDo not read cache URLs or reference paths from PR-controlled files such as\n`.buildchain/buildchain.toml`. These values are trusted workflow inputs or repo/org\nvariables. Buildchain does not pass GitHub credentials to cache mirrors or\nreference repositories. If it must fall back to GitHub, the workflow token is\nused only for the GitHub fetch path. Cache attempts use\n`checkout-cache-timeout-seconds`; the potentially larger GitHub fallback uses\nthe independent `checkout-cache-github-timeout-seconds` budget (600 seconds by\ndefault). Buildchain fetches the advertised source ref before trying an exact\nSHA, so a cache hit or stale-cache seed can contribute objects and the fallback\ndoes not first waste a full timeout on an unadvertised SHA. Retryable timeout\nand transient network failures use the bounded `checkout-cache-fetch-attempts`\nbudget; permanent failures stop immediately. Diagnostics record both timeout\nbudgets and the actual GitHub fetch attempts before exact HEAD/tree\nverification.\n\nEach platform diagnostics artifact includes `source-checkout.json` and embeds a\ncompact `sourceCheckout` summary in `diagnostics.json`: mode, transport,\nhit/miss, fallback reason, duration, final HEAD verification, and tree\nverification. Remote URLs are sanitized and local reference paths are represented\nby a short display name plus fingerprint, not by secret-bearing credentials.\nRuntime checkout evidence is uploaded separately as `runtime-checkout.json`,\nincluding cache transport, fallback attempts, and exact runtime `HEAD`\nverification, even when a later lifecycle step fails.\n\nWhen a Buildchain maintainer asks for downstream validation, the expected\nrequest is:\n\n```text\nBuildchain train ready: buildchain-ref=train/v2/v2.3/<capability>.\nKeep uses: ...@v2; run workflow_dispatch with that buildchain-ref and report the runtime evidence summary.\n```\n\nAfter validation succeeds, the Buildchain change should continue through the\nnormal mainline and release path. Do not treat the train as a pending merge\nitem; it is only a temporary fast-use, diagnostic, and rollback channel. It may\nremain for a retention window after release, with old trains handled by a\nseparate periodic cleanup task.\n\n## Workflow Outputs\n\nThe reusable workflow exposes the resolved contract:\n\n| Output | Meaning |\n| --------------------------------- | ------------------------------------------------------------------------------- |\n| `runner-preset` | Resolved preset, or `custom` when `platforms-json` was provided |\n| `platforms-json` | Exact matrix JSON used by the build job |\n| `platform-count` | Number of matrix platforms |\n| `linux-container-enabled` | `true` when Linux platforms are routed through a job container |\n| `linux-container-image` | Resolved digest-pinned Linux job container image |\n| `build-summary-artifact` | Uploaded aggregate summary artifact name |\n| `build-diagnostics-summary-artifact` | Uploaded aggregate diagnostics summary artifact name |\n| `release-candidate-passport-artifact` | Uploaded PR-stage release-candidate passport artifact name when `release-candidate` is enabled |\n| `release-candidate-passport-json` | Compact release-candidate passport JSON when `release-candidate` is enabled |\n| `build-summary-json` | Compact aggregate JSON with platform count, file count, and byte total |\n| `build-diagnostics-summary-json` | Compact aggregate diagnostics JSON with platform, lifecycle warning/error, diagnostics contract warning, and sidecar manifest warning totals |\n| `trusted-event` | `true` when the event is trusted enough to reach build runners |\n| `buildchain-runtime-ref` | Runtime ref selected after applying the empty-default or override policy |\n| `buildchain-runtime-sha` | Immutable Buildchain runtime commit used by all runtime checkouts |\n| `buildchain-runtime-class` | `stable`, `alpha`, `train`, `exact-sha`, or `development` |\n| `buildchain-runtime-override` | `true` when a train or exact-SHA `buildchain-ref` override was accepted |\n| `buildchain-runtime-trust-decision` | Runtime override trust decision |\n| `buildchain-contract-lock-status` | `unchanged`, `compatible-drift`, `breaking-drift`, `missing-lock`, `non-floating-runtime`, or first-release `runtime-contract-unavailable` |\n| `buildchain-contract-lock-drift` | `true` when the floating runtime SHA or contract digest changed |\n| `buildchain-contract-digest` | Current Buildchain runtime contract digest |\n| `publish-channel` | Resolved publish channel requested by the caller |\n| `publish-allowed` | `true` only when this event/ref may publish after verification |\n| `publish-reason` | Human-readable reason for the publish gate decision |\n| `publish-source-ref` | Gate source ref that was resolved before checkout |\n| `publish-source-sha` | Exact source commit used by checkout, build, verify, and artifacts |\n| `publish-source-locked` | `true` when a `publish-gate/*` source ref was explicitly locked |\n| `publish-source-channel` | `alpha`, `release`, `anchor`, or `major` parsed from the source ref |\n| `publish-source-line` | Product line parsed from source refs such as `v22/v22.22` |\n| `publish-source-consumer-version` | Consumer package version parsed from source refs |\n| `release-manifest-json` | Resolved release manifest including source lock, version state, and anchor data |\n\nThe aggregate summaries are intentionally artifacts as well as outputs. GitHub\nActions matrix outputs are not a reliable place to carry every platform's full\nmanifest, so Buildchain uploads each platform manifest and then emits one\naggregate build summary artifact after the matrix completes. Buildchain uploads\n`diagnostics-summary.json` as a separate aggregate diagnostics summary artifact,\na compact rollup of each platform's small diagnostics upload. The rollup keeps\nper-platform runner facts, checked tool versions/missing tools, package\nmanager/cache directory details, compiler-cache availability, lifecycle timing,\nprocess sampler context, and links back to the exact platform artifacts. Each\nplatform diagnostics upload includes `diagnostics.json`,\n`diagnostics-manifest.json`, the lifecycle `events.jsonl`, and process sampler\nsidecars when enabled, so slow-build diagnosis does not require downloading the\nbinary platform artifact or the aggregate build summary. The sidecar manifest\nrecords the uploaded diagnostics files with bytes and sha256 hashes. Each\n`diagnostics.json` also records the related binary artifact name, manifest\nartifact name, diagnostics artifact name, diagnostics sidecar manifest path, and\nplatform id in `links`, so a reviewer can navigate from the small diagnostics\nartifact back to the exact platform outputs when deeper inspection is needed.\nThe workflow output `build-diagnostics-summary-json` includes\n`diagnosticsContractWarningCount` and `diagnosticsManifestWarningCount` so\nrelease jobs can detect drifting diagnostics JSON contracts and missing or\ndrifting diagnostics sidecar manifests without downloading the per-platform\ndiagnostics artifacts first.\n\n## Artifact Transfer Relay\n\nBy default, platform jobs upload payloads, manifests, and diagnostics directly\nto GitHub artifacts:\n\n```yaml\nwith:\n artifact-transfer-mode: github-artifacts\n```\n\nLarge self-hosted native builds can opt into the first-class S3 relay path:\n\n```yaml\njobs:\n build:\n uses: kungfu-systems/buildchain/.github/workflows/.build.yml@v2\n with:\n runner-preset: kungfu-v4-self-hosted\n artifact-transfer-mode: s3-to-github-artifacts\n artifact-relay-s3-bucket: ${{ vars.BUILDCHAIN_ARTIFACT_RELAY_S3_BUCKET }}\n artifact-relay-s3-region: ${{ vars.BUILDCHAIN_ARTIFACT_RELAY_S3_REGION }}\n artifact-relay-s3-prefix: ${{ vars.BUILDCHAIN_ARTIFACT_RELAY_S3_PREFIX }}\n```\n\nIn relay mode, each self-hosted platform job uploads the heavy payload files to\nS3 and uploads only a small `relay-manifest.json` to GitHub. A GitHub-hosted\n`relay-artifacts` job then assumes the configured download role, downloads the\npayloads from S3, verifies every file by SHA256, and re-uploads the normal\nGitHub artifacts under the same artifact names that direct mode uses. Downstream\nsummary, release-candidate, and promote-only workflows therefore continue to\nconsume GitHub artifacts and do not need custom S3 logic.\nThe relay implementation uses Node.js plus the standard AWS environment\ncredentials from GitHub OIDC; runner images and build containers do not need the\nAWS CLI installed.\n\nAfter the GitHub artifact uploads succeed, Buildchain deletes the S3 objects\nlisted in the relay manifest for that platform. If any download, verification,\nor GitHub artifact upload fails, cleanup is skipped so maintainers can inspect\nthe retained S3 payload. Configure a short bucket lifecycle expiration as a\ncost and cleanup backstop.\n\nThe relay configuration is intentionally generic. Buildchain does not hard-code\norganization buckets, regions, or role ARNs. Callers may pass explicit inputs,\nor set repository/organization variables and secrets using these names:\n\n| Variable or secret | Meaning |\n| --- | --- |\n| `BUILDCHAIN_ARTIFACT_RELAY_S3_BUCKET` | Relay bucket name |\n| `BUILDCHAIN_ARTIFACT_RELAY_S3_REGION` | Relay bucket region |\n| `BUILDCHAIN_ARTIFACT_RELAY_S3_PREFIX` | Relay object prefix; defaults to `buildchain-artifacts` |\n| `BUILDCHAIN_ARTIFACT_RELAY_S3_ROLE_ARN` | Shared OIDC role ARN for upload and download |\n| `BUILDCHAIN_ARTIFACT_RELAY_S3_UPLOAD_ROLE_ARN` | Upload OIDC role ARN for self-hosted build jobs |\n| `BUILDCHAIN_ARTIFACT_RELAY_S3_DOWNLOAD_ROLE_ARN` | Download OIDC role ARN for the GitHub-hosted relay job |\n| `BUILDCHAIN_ARTIFACT_RELAY_S3_OIDC_AUDIENCE` | Optional OIDC audience override |\n\nFor AWS China regions, Buildchain defaults the OIDC audience to\n`sts.amazonaws.com.cn`; other regions default to `sts.amazonaws.com`. The caller\nworkflow must allow `id-token: write`, and the target role trust policy should\nrestrict GitHub OIDC claims to the expected organization, repository, workflow,\nand branch/ref. The S3 permissions should be scoped to the relay bucket/prefix\nused by the repository.\nUpload roles need write/delete access under the relay prefix; download roles\nneed read access plus delete access for successful cleanup.\n\nRelay mode is opt-in and does not affect forks or open-source users that do not\nconfigure S3. Missing bucket, region, upload role, or download role values fail\nbefore the heavy build matrix is scheduled. Buildchain treats S3 as a transport\ncache, not as the final release evidence store; the final audit entry remains\nthe GitHub artifact set plus the Buildchain build summary and release-candidate\npassport.\n\nSet `release-candidate: true` when the successful reusable build is meant to be\nthe artifact source promoted later. Buildchain then uploads\n`release-candidate-passport.json` under the\n`<artifact-name>-release-candidate-<publish-source-sha>` artifact name. Promotion\njobs can pass that passport to `promote-buildchain-ref` with\n`promote-only-release-candidate: \"true\"` so source, channel, platforms, and the\naggregate build-summary hash are checked before publish-gate side effects. The\npassport records the locked commit's Git tree SHA, so a post-merge channel HEAD\ncan be accepted only when it is tree-equivalent to the PR-stage build evidence.\n\n## Publish Gate\n\nBuildchain separates \"may build/verify\" from \"may publish.\" A same-repository\npull request may be trusted enough to run the build matrix, but it still must\nnot publish packages, S3 objects, release pages, or preview aliases. Publishing\nis allowed only when the caller explicitly requests a channel and the current\nevent/ref matches that channel.\n\nUse `publish-channel` to request a channel:\n\n```yaml\njobs:\n build:\n uses: kungfu-systems/buildchain/.github/workflows/.build.yml@v2\n with:\n publish-channel: release\n\n publish:\n needs: build\n if: ${{ needs.build.outputs.publish-allowed == 'true' }}\n runs-on: ubuntu-24.04\n steps:\n - run: ./scripts/publish.sh\n```\n\nDefault channels are:\n\n| Channel | Allowed refs |\n| --------- | ---------------------------------------------------------------------------------------------------- |\n| `none` | Never publishes; this is the default |\n| `alpha` | `alpha/vN/vN.M` branches or exact `vN.M.P-alpha.K` tags |\n| `release` | `release/vN/vN.M` branches or release tags such as `vN.M.P`, `vN.M`, `vN` |\n| `major` | `publish-gate/major`, legacy `major-gate`, or next-major release tags such as `vN.0.0`, `vN.0`, `vN` |\n\nPull request events always produce `publish-allowed=false`, even when the PR is\nfrom the same repository. Untrusted fork events also produce\n`publish-allowed=false`; with the default `untrusted-policy: fail`, the workflow\nthen fails before any build runner starts.\n\nProjects with their own channel names can pass `publish-refs-json`:\n\n```yaml\nwith:\n publish-channel: nightly\n publish-refs-json: >-\n {\"nightly\":[\"^refs/heads/nightly/v\\\\d+$\"]}\n```\n\nThe aggregate build summary includes the same publish gate decision under\n`publishGate`, so a downloaded artifact summary explains both what was built and\nwhy it was or was not eligible to publish.\n\n## Publish Source Lock\n\n`publish-channel` answers \"may this event publish?\" Source lock answers \"which\nsource tree is the publish decision about?\" A caller can pass `publish-source-ref`\nto bind a publish run to a reviewed gate branch before any checkout happens:\n\n| Ref | Meaning |\n| ------------------------------------------------ | --------------------------------------------------------------------------- |\n| `publish-gate/alpha/<line>/<consumer-version>` | Build and publish an alpha candidate for a consumer line |\n| `publish-gate/release/<line>/<consumer-version>` | Build and publish a production candidate for a consumer line |\n| `publish-gate/anchor` | Resolve an explicit anchor request; it does not publish artifacts by itself |\n| `publish-gate/major` | Gate the next major source state |\n| `major-gate` | Legacy compatibility alias for the major gate |\n\nFor alpha and release refs, `<line>` is intentionally allowed to contain `/`, so\nKungfu-style lines such as `v22/v22.22` stay readable. The final path segment is\nthe consumer-visible version, for example `22.22.3-kf.0`.\n\nThe reusable workflow resolves the branch tip to `publish-source-sha`, checks out\nthat SHA in every build job, and uses the same SHA in artifact names, manifests,\nand aggregate summaries. Reruns therefore rebuild the same source tree even if a\ngate branch moves later.\n\nBefore any heavy build matrix is scheduled, the workflow also verifies that the\ntarget channel ref implied by the source lock already points at\n`publish-source-sha` and that the target channel HEAD came from the required\nmerged same-repository channel PR. `publish-gate/alpha/<line>/<version>` must\nmatch `alpha/<line>` and have PR lineage `dev/<line> -> alpha/<line>`;\n`publish-gate/release/<line>/<version>` must match `release/<line>` and have PR\nlineage `alpha/<line> -> release/<line>`. If either check fails, the run fails\nfast with a diagnostic telling maintainers to merge the source commit through\nthe channel PR first. This keeps verify from spending runner time on a source\ntree that cannot legally enter the requested publish channel.\n\nThe resolved release manifest is uploaded as an artifact and emitted as\n`release-manifest-json`. It records:\n\n- source ref, source SHA, channel, line, and consumer version;\n- configured version strategy and configured version-state files;\n- each version file's value, with release gates failing closed if the configured\n files do not equal the consumer version;\n- anchor manifest summary for anchored/manual projects;\n- explicit anchor request JSON for `publish-gate/anchor`;\n- publish registry, dist-tag, and gate visibility metadata.\n\nPublish side-effect jobs should verify the lock immediately before publishing:\n\n```yaml\n- name: Verify publish gate did not move\n run: node .buildchain/runtime/scripts/verify-publish-source-lock.mjs\n env:\n BUILDCHAIN_PUBLISH_SOURCE_REF: ${{ needs.build.outputs.publish-source-ref }}\n BUILDCHAIN_PUBLISH_SOURCE_SHA: ${{ needs.build.outputs.publish-source-sha }}\n BUILDCHAIN_SOURCE_REPOSITORY: ${{ github.repository }}\n GITHUB_TOKEN: ${{ github.token }}\n```\n\nIf the branch tip no longer matches the manifest SHA, the publish job must fail\nclosed. Moving a gate branch creates a new publish decision and should produce a\nnew build run.\n\n## Release Candidate Promote-Only\n\nFor native package sets, the PR build is the only heavy build. When a PR targets\n`alpha/<line>` or `release/<line>`, `.build.yml` uploads a release-candidate\nbundle next to the platform artifacts. The bundle contains:\n\n- `release-candidate.passport.json`;\n- the aggregate `build-summary.json`;\n- copied platform manifest evidence for the built platforms.\n\nThe passport records two separate source identities:\n\n- `builtSourceSha` / `builtSourceTreeSha`: the PR-stage source that produced the\n artifacts, usually the PR merge ref;\n- `promotionChannelSha` / `promotionChannelTreeSha`: the post-merge channel\n commit used for publish authority.\n\nThe reusable promote wrapper resolves the merged PR, finds exactly one matching\nPR-stage release-candidate artifact, downloads it with the build summary and\npayload artifacts from the same PR-stage run, validates the payload count,\ncompares the built tree with the promotion channel tree, locks\n`publish-gate/{alpha,release,major}` to the promotion channel commit, and then\ncalls `actions/promote-buildchain-ref` with\n`promote-only-release-candidate: \"true\"` and\n`require-publish-source-lock: \"true\"`. The wrapper passes the created\n`publish-gate/*` ref, target SHA, and `locked=true` into the promote action, so\nfloating `@v2` consumers receive publish-side source-lock drift protection by\ndefault. It also defaults `branch-protection-bypass-apps` to `github-actions`\nso the workflow automation can apply generated version-state and channel\nbookkeeping on protected `dev`/`alpha`/`release` branches after the reviewed\nchannel PR has merged; consumers using a different promotion identity can pass\n`branch-protection-bypass-users`, `branch-protection-bypass-teams`, or a\ndifferent app slug declaratively. The wrapper uses\n`secrets.BUILDCHAIN_PROMOTION_TOKEN || github.token` as the generated ref update\ntoken for protected bookkeeping PATCH calls, so a bypass-capable promotion token\ncan sync dev immediately after alpha/release publish without a post-publish PR.\nIt does not call `.build.yml`, does not create a matrix, and must fail before\npublish if the RC evidence, payload set, or source-lock ref is missing or\nambiguous.\n\n```yaml\njobs:\n promote:\n uses: kungfu-systems/buildchain/.github/workflows/release-candidate-promote.yml@v2\n secrets:\n buildchain-issue-app-id: ${{ secrets.BUILDCHAIN_ISSUE_APP_ID }}\n buildchain-issue-app-private-key: ${{ secrets.BUILDCHAIN_ISSUE_APP_PRIVATE_KEY }}\n with:\n channel: alpha\n target-ref: alpha/v22/v22.22\n artifact-name: libnode\n # Defaults to build.yml / Build. Override only when the PR-stage build\n # workflow uses a different file or display name.\n release-candidate-workflow-file: build.yml\n release-candidate-workflow-name: Build\n package-manager: npm\n publish-target: npm\n runner-preset: github-hosted\n trusted-publishing: true\n github-release: true\n required-status-check: check / check\n required-artifact-count: 3\n publish-dist-tag: alpha\n publish-package-set-order: platforms-first-main-last\n publish-package-main: \"@kungfu-tech/libnode\"\n release-passport-product-name: Libnode\n buildchain-contract-lock-path: .buildchain/contract-lock.json\n buildchain-contract-drift-issue-mode: compatible-and-breaking\n```\n\n`buildchain-issue-app-id` and `buildchain-issue-app-private-key` are optional\nbut recommended for cross-repository consumers. They should identify a GitHub\nApp installation with `issues: write` on `kungfu-systems/buildchain`; the\nwrapper mints the installation token before calling\n`actions/report-buildchain-issue`. Consumers can also pass a pre-minted\n`buildchain-issue-token`. If both are omitted, the wrapper falls back to\n`BUILDCHAIN_ISSUE_TOKEN`, `BUILDCHAIN_PROMOTION_TOKEN`, and then the consumer\nworkflow's `github.token`; the last fallback can only report issues when it has\nwrite access to the target Buildchain repository.\n\n`publish-required-artifacts-json` can still be passed explicitly for custom\npublish targets. For the default `publish-artifact-kind: npm` path, consumers do\nnot download artifacts or run repository scripts to build publish evidence. The\nwrapper downloads the PR-stage payload artifacts, finds the downloaded `.tgz`\npackages, reads each tarball's `package/package.json` for the real scoped\npackage name and version, computes the npm `sha512-...` integrity from the\ntarball bytes, marks the package matching `publish-package-main` as `role:\nmain`, marks the rest as `role: platform`, and passes the generated\n`publish-required-artifacts-json` to `promote-buildchain-ref` before any publish\nside effect. Downloaded platform manifests are still passed into the release\npassport unless `release-passport-platform-manifest-paths` is set explicitly.\nThe same Buildchain contract lock check runs before release-candidate\nresolution and before publish. A compatible `v2` drift leaves an issue in the\nconsumer repository but does not trigger a second heavy build; an incompatible\ndrift fails before publish side effects.\n\nThe wrapper publishes the public release tag as a GitHub Release by default.\nAfter `promote-buildchain-ref` reports a complete release transaction, the\nwrapper creates or updates the public release, marks semver prerelease tags\nsuch as `v1.2.3-alpha.0`, `v1.2.3-rc.1`, or `v22.22.3-kf.3-alpha.7` as\n`prerelease=true` and `make_latest=false`, marks stable semver tags as latest,\nand uploads the publish evidence file plus every file in the generated release\npassport directory, including `buildchain.release.json` and `check-report.json`.\nFor anchored/manual package releases, the public release tag is derived from the\npublished package version and the internal exact transaction tag remains\navailable in the release passport.\nConsumers do not need to hand-write `gh release` logic to trigger\n`release.published` propagation. Set `github-release: false` only for\nrepositories that intentionally do not maintain GitHub Releases.\nIf the transaction still needs protected-ref finalization, the wrapper defers\nGitHub Release creation until the later run that reaches `state=complete`.\n\nCustom publish jobs can also repeat the channel-ref preflight:\n\n```yaml\n- name: Verify publish channel ref still matches\n run: node .buildchain/runtime/scripts/verify-publish-channel-ref.mjs\n env:\n BUILDCHAIN_PUBLISH_SOURCE_REF: ${{ needs.build.outputs.publish-source-ref }}\n BUILDCHAIN_PUBLISH_SOURCE_SHA: ${{ needs.build.outputs.publish-source-sha }}\n BUILDCHAIN_SOURCE_REPOSITORY: ${{ github.repository }}\n GITHUB_TOKEN: ${{ github.token }}\n```\n\nAnchored/manual package release jobs should also make the Buildchain promotion\naction validate that publication is entering through the same\n`publish-gate/{alpha,release,major}` source-lock contract before any package\npublish side effect:\n\n```yaml\n- name: Promote release ref and publish npm package set\n uses: kungfu-systems/buildchain/actions/promote-buildchain-ref@v2\n with:\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```\n\n`target-ref` stays the Buildchain channel promotion target, such as\n`alpha/v22/v22.22`, `release/v22/v22.22`, or `publish-gate/major`.\n`publish-source-ref` is the reviewed source-lock branch that authorized this\nspecific package publication. For alpha and release package publications, the\nsource-lock branch must point at the exact channel-line commit that promotion is\nvalidating; it is not a replacement for `target-ref`.\n\nThis keeps the version bump commit, publish authorization, and auditable publish\nentrypoint on the Buildchain source-lock protocol. The CLI form\n`buildchain publish-source validate-anchored-release --json` is still useful for\ncustom publish scripts, but the preferred GitHub Actions gate is the promotion\naction input above. A publish job that still runs directly from `alpha/*` or\n`release/*` channel branches fails this check because those refs are channel\nstate, not publish-gate decisions.\n\n## Package-Set Publish Plan\n\nProjects that publish multiple packages should treat package publication as a\npackage-set operation. Buildchain's package-set planner uses these rules:\n\n- platform packages publish first;\n- the main package publishes last;\n- the dist-tag move happens only after the full package set is present;\n- reruns accept already-published packages only when package name, version, and\n integrity match;\n- an existing package with different integrity is a hard failure.\n\nThis keeps a consumer from observing a floating dist-tag that points to a main\npackage before all platform artifacts for the same source SHA are available.\n\n## Command Sources\n\nThe workflow runs `.buildchain/buildchain.toml` lifecycle stages by default:\n\n```toml\n[lifecycle.install]\ncommand = \"corepack yarn install --immutable\"\n\n[lifecycle.build]\ncommands = [\n \"corepack yarn make\",\n \"corepack yarn build\",\n]\n\n[lifecycle.verify]\ncommand = \"corepack yarn test\"\n```\n\nCallers can override any stage for one invocation:\n\n```yaml\nwith:\n build-command: cmake --build build --config Release\n verify-command: ctest --test-dir build --output-on-failure\n```\n\nThe reusable build workflow samples the build lifecycle by default and carries\nthe generated summary into the final verify diagnostics. Callers can override\nthe sidecar path or disable sampling:\n\n```yaml\nwith:\n sample-process-tree: true\n process-summary-path: .buildchain/diagnostics/process-summary.json\n process-sample-interval-ms: 15000\n requested-parallelism: 20\n```\n\nWhen `sample-process-tree` is true, Buildchain wraps either `build-command` or\nthe configured `lifecycle.build` stage with `buildchain sample process-tree`.\nThe path is relative to the checked-out workspace and is read again during the\nfinal verify lifecycle. Custom workflows can still write their own sampler\nsummary and pass `process-summary-path`; Buildchain reads the file after the\nlifecycle command finishes, so it may be produced during the same invocation.\nWhen the build stage is optional, the reusable workflow treats the default\nsampler path as optional during verify; an explicitly supplied\n`process-summary-path` remains required.\n\nFor custom workflows, use the action directly:\n\n```yaml\n- uses: kungfu-systems/buildchain/actions/run-lifecycle@v2\n with:\n stage: build\n required: \"true\"\n artifact-name: libnode-linux-x64-${{ github.sha }}\n artifact-paths: |\n dist\n build/stage\n```\n\n## Artifact Contract\n\nEach platform upload uses `artifact-name-template`. The default is:\n\n```text\n{artifact}-{platform}-{sha}\n```\n\nSupported placeholders are `{artifact}`, `{artifactName}`, `{platform}`,\n`{platformId}`, `{platformName}`, `{sha}`, `{shortSha}`, `{ref}`, `{runId}`,\nand `{runAttempt}`. Invalid GitHub artifact name characters are normalized to\n`-`, so `{ref}` remains deterministic even for refs such as\n`refs/heads/dev/v2/v2.0`.\n\nEach platform also writes and uploads:\n\n```text\n.buildchain/artifacts/<platform-id>/manifest.json\n.buildchain/artifacts/<platform-id>/summary.json\n```\n\nThe manifest schema is:\n\n```json\n{\n \"schemaVersion\": 1,\n \"contract\": \"kungfu-buildchain-artifact\",\n \"artifactName\": \"libnode-linux-x64-<sha>\",\n \"platform\": {\n \"id\": \"linux-x64\",\n \"name\": \"Linux x64\",\n \"os\": \"Linux\",\n \"arch\": \"X64\"\n },\n \"git\": {\n \"repository\": \"kungfu-systems/libnode\",\n \"sha\": \"<sha>\",\n \"ref\": \"<ref>\",\n \"runId\": \"<run id>\",\n \"runAttempt\": \"<attempt>\"\n },\n \"lifecycle\": {\n \"stage\": \"verify\",\n \"commandSource\": \"buildchain.toml\",\n \"executed\": true\n },\n \"summary\": {\n \"contract\": \"kungfu-buildchain-artifact-summary\",\n \"artifactName\": \"libnode-linux-x64-<sha>\",\n \"fileCount\": 1,\n \"totalBytes\": 1234,\n \"digest\": \"<hex>\"\n },\n \"expectedArtifacts\": {\n \"ok\": true,\n \"source\": \"expected-artifacts-json\",\n \"checks\": []\n },\n \"files\": [\n {\n \"path\": \"dist/example.zip\",\n \"size\": 1234,\n \"sha256\": \"<hex>\"\n }\n ]\n}\n```\n\nArtifact names do not include actor names, timestamps, or retry counters. Reruns\nproduce a new GitHub Actions run but keep the same source SHA/platform contract.\n\n`expected-artifacts-json` fails the build before upload when the artifact does\nnot match the caller's declared contract. Supported checks are:\n\n| Field | Meaning |\n| --------------- | ------------------------------------ |\n| `minFiles` | Minimum number of manifest files |\n| `maxFiles` | Maximum number of manifest files |\n| `minTotalBytes` | Minimum total byte count |\n| `requiredPaths` | Exact manifest paths that must exist |\n\n## Trusted Event Gate\n\nThe workflow has an explicit `trust-gate` job. By default, pull requests from\nforks fail before any build job can reach self-hosted runners, secrets,\npublishing credentials, or heavyweight build commands. Same-repository PRs,\nworkflow dispatches, and protected branch events can proceed.\n\nIf a repository wants fork PRs to skip rather than fail, it can set:\n\n```yaml\nwith:\n untrusted-policy: skip\n```\n\nDo not set `require-trusted-event: false` for workflows that use self-hosted\nrunners or secrets.\n\n`require-trusted-event` controls access to build runners. It does not override\nthe publish gate: pull requests remain non-publishing events.\n\n## Fixture\n\n`fixtures/libnode-shaped` is the contract fixture. It has:\n\n- `package.json` version state;\n- `.buildchain/buildchain.toml` with `install`, `build`, `verify`, and `publish`;\n- cross-platform Node scripts that create small `dist/` outputs;\n- `Build Surface Fixture` workflow coverage.\n\nThe fixture proves the reusable surface without running the real libnode native\nbuild."
|
|
1528
1548
|
},
|
|
1529
1549
|
{
|
|
1530
1550
|
"id": "manual:runtime-train-validation",
|
|
@@ -1625,6 +1645,52 @@
|
|
|
1625
1645
|
],
|
|
1626
1646
|
"markdown": "# Site Bundle Contract\n\n`@kungfu-tech/buildchain` publishes `dist/site/` as the package-owned fact\nsource for `buildchain.libkungfu.dev` and other documentation surfaces.\n\nThe website may design navigation, visual hierarchy, examples, and explanatory\ncopy around these facts. It should not hand-write the current Buildchain\nrelease mechanics, command registry, workflow registry, or artifact schema.\n\n## Files\n\n```text\ndist/site/\n buildchain-site.json\n site-manifest.json\n publication-registry.json\n capability-registry.json\n cli-registry.json\n manual-registry.json\n node-api-registry.json\n workflow-registry.json\n public-surface-audit.json\n release-model.json\n artifact-schemas.json\n buildchain-contract.json\n kfd-claims.json\n product-mechanism.json\n release-provenance.json\n agent-index.json\n```\n\n`buildchain-site.json` is the top-level bundle entrypoint.\nIt includes a `homepage` object generated from `README.md`, including\n`homepage.sections`, `homepage.displayPlan`, and a\n`homepage.rendererContract` that is implementation metadata rather than\nordinary homepage copy. Site repositories should consume those fields instead\nof parsing `README.md` themselves.\nIt also includes a `pages` collection that mirrors `page-registry.json`, so a\nsite repository can build the full Buildchain public documentation surface from\nthe npm package without scanning the source checkout.\n`capability-registry.json` is the navigation spine for that page surface. It\ngroups manuals, pages, CLI commands, workflows, actions, Node API exports, and\nKFD claim facts into stable product capability groups. Site repositories should\nrender navigation from this registry first, then use `page-registry.json`,\n`manual-registry.json`, `cli-registry.json`, `node-api-registry.json`, and\n`workflow-registry.json` for the concrete entries inside each group.\n`page-registry.json` is the complete page fact source: README homepage content,\nall packaged `docs/*.md` manuals, action README files, the Node API package\noverview, and fixture guides.\n`buildchain-contract.json` is the machine-readable Buildchain runtime contract\nworld used by floating-ref contract locks. It records public workflow/action/CLI\nsurfaces, compatibility digests, and audit digests for the files that implement\nthose surfaces.\n`manual-registry.json` enumerates the packaged Markdown manuals with source\ndigests so an agent can find complete operating documentation from the npm\nartifact. `node-api-registry.json` enumerates public Node import surfaces from\n`package.json#exports`, so agents do not have to infer supported APIs from\ninternal paths.\n`kfd-claims.json` is the Buildchain-owned KFD claim registry. It is generated\nfrom `packages/core/buildchain-kfd-claims.js` and enumerates the public release\nclaims plus the KFD-3 collaboration surfaces that Buildchain self-verifies\nduring release promotion.\n`public-surface-audit.json` is the reverse enumeration report for those\nsurfaces. It enumerates real CLI commands from `bin/buildchain.mjs`, workflow\ninputs, action inputs, site pages, and documentation command references, then\ncompares those sets with `cli-registry.json`, `workflow-registry.json`, and\n`page-registry.json`. Buildchain's self-check fails closed when an enumerable\npublic surface is missing from the generated registries.\n`publication-registry.json` is the package-owned publication archive registry\nfor downstream papers surfaces. Site repositories can render latest reader\nroutes, immutable version artifact routes, source bundles, and publication\npassport links from this file instead of keeping their own fixture registry.\n\n## Timestamp and Reproducibility Policy\n\nEvery Buildchain-owned surface manifest uses the same timestamp policy fields:\n\n- `generatedAt`: when the manifest JSON was generated.\n- `publishedAt`: when the surface was published, when known.\n- `reproducible`: whether the manifest declares its reproducibility inputs.\n- `timestampPolicy`: `ci-injected` for release/workflow-generated public\n artifacts, or `source-date-epoch` for local deterministic source checks.\n- `deterministicInputs`: the source files, revisions, package metadata, and\n declared Buildchain contracts that determine the manifest bytes.\n- `sourceDateEpoch` / `sourceRevision`: the deterministic time input or source\n revision used to reproduce the manifest.\n- `timestampPolicyDetails.timestampFieldsParticipateInArtifactDigest`: whether\n timestamp fields are included in the artifact digest being audited.\n\nThe policy is defined by `@kungfu-tech/buildchain/surface-manifest` and applies\nto the root site bundle, `site-manifest.json`, and web-surface deployment\nmanifests for named surfaces such as KFD, Buildchain, and Core. Site\nrepositories should render these fields; they should not invent their own\nmanifest time semantics.\n\nSource checkouts may use `SOURCE_DATE_EPOCH` for deterministic local checks.\nPublished CI/release artifacts should inject real timestamps with\n`BUILDCHAIN_SITE_GENERATED_AT` / `BUILDCHAIN_SITE_PUBLISHED_AT` or the matching\n`BUILDCHAIN_SURFACE_*` variables, so public manifests do not expose epoch time\nas if it were a real metadata time.\n\nVersion-state branches may already contain a generated manifest for the current\npackage version with `timestampPolicy: ci-injected`. In that case\n`generate-site-bundle.mjs --check` preserves the existing timestamp policy as\nthe deterministic input instead of rewriting public release metadata back to\nepoch time.\n\n## npm Consumption\n\n```bash\nnpm install @kungfu-tech/buildchain\n```\n\nThen read files from:\n\n```text\nnode_modules/@kungfu-tech/buildchain/dist/site/\n```\n\nPackage exports are also provided for direct JSON-aware consumers:\n\n```js\nimport siteManifest from \"@kungfu-tech/buildchain/site/site-manifest.json\" with { type: \"json\" };\n```\n\n## Generation\n\n```bash\npnpm run generate:site\npnpm run check:site\n```\n\n`check:site` fails when generated files are stale. `pnpm run check` includes\nthis gate, so release candidates cannot publish an out-of-date site bundle.\n\n## Scope\n\nThe P0 bundle includes:\n\n- README-derived homepage fields and display plan;\n- capability-grouped navigation facts for docs, CLI, Node API, workflows,\n actions, and KFD claims;\n- complete markdown page registry for public Buildchain docs, action manuals,\n Node API overview, and fixtures;\n- site manifest;\n- publication archive registry for downstream papers surfaces;\n- CLI command registry;\n- manual registry for packaged agent-facing documentation;\n- Node API registry for public package exports;\n- workflow/action registry;\n- release model facts;\n- artifact and evidence schema index;\n- Buildchain runtime contract world for `@v2` floating-ref compatibility checks,\n KFD-1/KFD-2/KFD-3 release gates, GitHub Release evidence publication, and\n site-consumption contracts;\n- Buildchain KFD claim registry for release-passport self verification and\n agent-first public claim discovery;\n- product mechanism manifest;\n- release provenance;\n- agent read order.\n\nFuture minor lines can add examples, recipes, fixture indexes, and richer\nschema metadata without breaking existing consumers.\n\n`release-propagation.md` describes the package-to-package or package-to-site\nrelease chain model. The site bundle exposes that document and the\n`release-propagation` CLI entry so downstream sites can render the current\nBuildchain-owned propagation contract instead of hand-writing it.\n`publication-registry.json` is the static site-consumption entrypoint for\npublication archive pages. It uses the\n`kungfu-buildchain-publication-release-registry` contract and declares the\nmutable latest/canonical routes separately from append-only immutable version\nprefixes.\n\n## Rendering Boundary\n\nBuildchain owns the homepage wording, section ordering intent, complete\nmarkdown page registry, release model facts, workflow/action registry, CLI\nregistry, manual registry, Node API registry, KFD claim registry, and\nrelease-passport evidence vocabulary. The site owns HTML, CSS, responsive\nlayout, navigation, visual assets, decorative media, markdown-to-HTML rendering,\nand progressive disclosure within the Buildchain-provided\n`homepage.displayPlan` and page metadata.\n\nThe page registry is also part of Buildchain's KFD-3 collaboration-interface\nsurface. Releases declare it as a site-consumption contract, and Buildchain's\nKFD-3 witness generation includes the underlying markdown sources as public\ndocumentation surfaces. If a page is public enough for the site to render, it\nmust be declared and hash-bound in the package-owned site bundle."
|
|
1627
1647
|
},
|
|
1648
|
+
{
|
|
1649
|
+
"id": "manual:stable-candidate-patrol",
|
|
1650
|
+
"title": "Stable Candidate Patrol",
|
|
1651
|
+
"route": "/docs/stable-candidate-patrol",
|
|
1652
|
+
"category": "manual",
|
|
1653
|
+
"capabilityGroup": "getting-started",
|
|
1654
|
+
"audience": [
|
|
1655
|
+
"agent"
|
|
1656
|
+
],
|
|
1657
|
+
"maturity": "stable",
|
|
1658
|
+
"sourcePath": "docs/stable-candidate-patrol.md",
|
|
1659
|
+
"digest": "sha256:b78530dcd07a506307a1385b3f5d2d091e8e1e0a60dd33748aca44db6f7ba241",
|
|
1660
|
+
"headings": [
|
|
1661
|
+
{
|
|
1662
|
+
"level": 1,
|
|
1663
|
+
"title": "Stable Candidate Patrol",
|
|
1664
|
+
"anchor": "stable-candidate-patrol"
|
|
1665
|
+
},
|
|
1666
|
+
{
|
|
1667
|
+
"level": 2,
|
|
1668
|
+
"title": "Candidate lifecycle",
|
|
1669
|
+
"anchor": "candidate-lifecycle"
|
|
1670
|
+
},
|
|
1671
|
+
{
|
|
1672
|
+
"level": 2,
|
|
1673
|
+
"title": "Repository policy",
|
|
1674
|
+
"anchor": "repository-policy"
|
|
1675
|
+
},
|
|
1676
|
+
{
|
|
1677
|
+
"level": 2,
|
|
1678
|
+
"title": "Exact-source stable promotion",
|
|
1679
|
+
"anchor": "exact-source-stable-promotion"
|
|
1680
|
+
},
|
|
1681
|
+
{
|
|
1682
|
+
"level": 2,
|
|
1683
|
+
"title": "Hold, revoke, and immediate release",
|
|
1684
|
+
"anchor": "hold-revoke-and-immediate-release"
|
|
1685
|
+
},
|
|
1686
|
+
{
|
|
1687
|
+
"level": 2,
|
|
1688
|
+
"title": "Durable recovery",
|
|
1689
|
+
"anchor": "durable-recovery"
|
|
1690
|
+
}
|
|
1691
|
+
],
|
|
1692
|
+
"markdown": "---\nstatus: preview\nperiod: ongoing\ntheme: stable-candidate-patrol\ndoc_type: architecture-and-usage\nsource_level: local-files\nconfidence: high\nsensitivity: public\nevidence_grade: A\nreview_state: self-reviewed\nlast_reviewed: 2026-07-11\nai_provenance:\n model_family: GPT-5\n product: Codex\n generated_at: 2026-07-11\n visible_context: Buildchain candidate passport, stable gate, Patrol, publish transaction, exact source-lock PR contracts, tests, and user consensus.\n invisible_context_boundary: No credentials, private logs, or unpublished consumer content were used.\n---\n\n# Stable Candidate Patrol\n\nBuildchain can treat every exact alpha as an independent stable candidate. A\nnew alpha creates a new candidate; it does not silently revoke an older alpha\nthat already completed its checks and soak interval.\n\n## Candidate lifecycle\n\nThe durable ledger contract is `kungfu-buildchain-stable-candidate-ledger`:\n\n```text\nregistered -> soaking -> qualified -> promoted\n \\-> revoked\n```\n\nEach entry binds an exact alpha version to one immutable commit SHA. Registering\nthe same version at another SHA fails closed. Qualification records the required\nchecks, their completion times, the derived soak start, and elapsed time.\n\nScheduled selection chooses the newest `qualified` candidate that is neither\n`revoked` nor already `promoted`. A newer alpha that is still `soaking` does not\nhide an older qualified candidate. Once a stable version is promoted, remaining\nalphas for that exact stable version are closed because that immutable stable\nversion has been consumed; their later product changes continue through the\nnext patch alpha prepared by the normal release transaction.\n\nFor Buildchain's own release line, successful Alpha Self-Dogfood starts an\nidempotent qualification producer for the exact alpha SHA. It dispatches the\nexisting `Build Surface Fixture` at the immutable exact tag, runs the existing\n`site-libkungfu-dev` no-apply canary with the exact SHA, and writes the declared\ncommit-status attestation only after that authoritative canary succeeds. The\nproducer creates evidence only: Patrol still owns qualification and selection,\nand the normal source-lock PR, stable gate, transaction, and branch protections\nremain mandatory.\n\nCross-repository dispatch and repository-local attestation use separate tokens.\nThe promotion token can start the no-apply consumer workflow, while the\nrepository-scoped Actions token writes the status as `github-actions[bot]` only\nafter the producer has observed the successful authoritative workflow run. The\nstable gate still verifies the workflow identity, exact runtime SHA, target URL,\nand allowed attestor before accepting that status.\n\n## Repository policy\n\nDeclare the default once in `.buildchain/buildchain.toml`:\n\n```toml\n[release.stable]\nstrategy = \"latest-qualified-alpha\"\ntimezone = \"Asia/Shanghai\"\npublish_at = \"03:00\"\nminimum_soak_seconds = 3600\nrequired_checks = [\n \"alpha-release\",\n \"workflow:Build\",\n \"status:buildchain-canary/consumer\",\n]\nauto_promote = true\nauto_merge = true\n```\n\nCheck identifiers use these forms:\n\n- `alpha-release`: the exact GitHub prerelease publication fact;\n- `workflow:<name>`: a successful Actions workflow run on the exact candidate SHA;\n- `status:<context>`: a successful commit status on the exact candidate SHA;\n- an unprefixed value: an exact status context or check-run name.\n\nCandidate discovery uses immutable exact alpha Git tags. When a repository also\npublishes GitHub prereleases, `alpha-release` binds qualification to that public\nrelease fact. Repositories that intentionally disable GitHub Releases omit\n`alpha-release` and declare their own exact-SHA workflow/status evidence; tag\ncommit time remains the earliest possible soak start.\n\n`publish_at` and `timezone` are the auditable policy declaration. GitHub only\nstarts scheduled workflows from caller-owned cron, so the thin caller keeps the\nmatching UTC trigger:\n\n```yaml\nname: Stable Candidate Patrol\n\non:\n schedule:\n - cron: \"0 19 * * *\" # 03:00 Asia/Shanghai\n workflow_dispatch:\n inputs:\n release-now:\n description: Exact alpha selected by explicit human authority\n required: false\n default: \"\"\n\npermissions:\n contents: write\n pull-requests: write\n checks: read\n statuses: read\n\njobs:\n stable:\n uses: kungfu-systems/buildchain/.github/workflows/stable-candidate-patrol.yml@v2\n with:\n release-now: ${{ inputs.release-now }}\n dry-run: false\n secrets:\n promotion-token: ${{ secrets.BUILDCHAIN_PROMOTION_TOKEN }}\n```\n\nThe promotion token must be repository-owned and capable of creating the\nmachine ledger branch, exact source-lock branch, and pull request. Repositories\nthat require an approving review can set `auto-approve: true` only when their\nGitHub Actions policy explicitly allows the caller token to approve the PR;\notherwise a repository-owned App or review bot supplies the approval. The\ngenerated PR may use auto-merge, but it never bypasses the target branch checks.\n\n## Exact-source stable promotion\n\nFor a selected `2.12.0-alpha.4`, Patrol creates the immutable source branch:\n\n```text\npublish-gate/release/v2/v2.12/2.12.0-alpha.4\n```\n\nand opens it against `release/v2/v2.12`. This is an existing strict Buildchain\ngovernance path. The PR freezes the qualified candidate even if `v2.12-alpha`\nor `alpha/v2/v2.12` has already moved to alpha.5. Normal Verify,\nrelease-candidate resolution, source-tree equivalence, publish transaction,\npassport, registry, tag, and floating-ref checks still run.\n\n## Hold, revoke, and immediate release\n\nPersistent repository controls can be supplied as reusable-workflow inputs or\nrepository variables:\n\n```text\nBUILDCHAIN_STABLE_HOLD=true\nBUILDCHAIN_STABLE_HOLD_REASON=release freeze\nBUILDCHAIN_STABLE_REVOKED_ALPHA_VERSIONS=2.12.0-alpha.5,2.12.0-alpha.7\nBUILDCHAIN_STABLE_REVOKE_REASON=consumer regression\n```\n\nRevocation is explicit evidence; publishing a newer alpha alone is not\nrevocation. A manual `workflow_dispatch` `release-now` chooses one exact,\nnon-revoked candidate immediately. It may bypass the scheduled soak decision,\nbut cannot change candidate SHA, reuse a consumed stable version, or bypass the\nsource-lock PR and publish transaction.\n\nFor Buildchain's own stable gate, Patrol automatically projects that explicit\nhuman decision into the exact-candidate `BUILDCHAIN_STABLE_RELEASE_NOW` and\nreason variables. A later Patrol run removes them after it observes the public\nstable release. This is an internal compatibility projection, not a manual user\nstep; the durable authority record remains the candidate ledger entry and PR.\n\n## Durable recovery\n\nThe default ledger ref is derived from the release line, for example:\n\n```text\nbuildchain/candidate-ledger/v2/v2.12\n```\n\nIt stores `.buildchain/stable-candidate-ledger.json`. Patrol runs are serialized\nper repository and release line. Repeated runs reuse the same exact source-lock\nbranch and PR, while later runs observe the public stable release and mark the\ncandidate `promoted`.\n\nWhen Patrol is enabled after a stable version already exists, it reconstructs\nthat consumed patch from GitHub Release truth and closes historical alpha\ncandidates for the same stable version. It never attempts to republish an\nalready claimed exact stable version."
|
|
1693
|
+
},
|
|
1628
1694
|
{
|
|
1629
1695
|
"id": "manual:toolkit-observability",
|
|
1630
1696
|
"title": "Toolkit Observability",
|
|
@@ -2098,7 +2164,7 @@
|
|
|
2098
2164
|
"pageRegistry": {
|
|
2099
2165
|
"path": "page-registry.json",
|
|
2100
2166
|
"contract": "kungfu-buildchain-site-page-registry",
|
|
2101
|
-
"pageCount":
|
|
2167
|
+
"pageCount": 46,
|
|
2102
2168
|
"categories": [
|
|
2103
2169
|
"action",
|
|
2104
2170
|
"api",
|
|
@@ -2217,7 +2283,7 @@
|
|
|
2217
2283
|
"path": "docs/MAP.md",
|
|
2218
2284
|
"plane": "use",
|
|
2219
2285
|
"exists": true,
|
|
2220
|
-
"digest": "sha256:
|
|
2286
|
+
"digest": "sha256:0735009b21cea9227f2c9b9bcbec1219898f4d211776b60aa030ace65821ec80"
|
|
2221
2287
|
},
|
|
2222
2288
|
{
|
|
2223
2289
|
"id": "install",
|
|
@@ -2273,7 +2339,7 @@
|
|
|
2273
2339
|
"path": "docs/binary-distribution.md",
|
|
2274
2340
|
"plane": "verify",
|
|
2275
2341
|
"exists": true,
|
|
2276
|
-
"digest": "sha256:
|
|
2342
|
+
"digest": "sha256:08be4e97e1940a45a2c0aa2506012255888c23c1cbf8f5362b27c2b21089eb58"
|
|
2277
2343
|
},
|
|
2278
2344
|
{
|
|
2279
2345
|
"id": "consumer-issue-reporting",
|
|
@@ -2337,7 +2403,7 @@
|
|
|
2337
2403
|
"path": "docs/cli.md",
|
|
2338
2404
|
"plane": "use",
|
|
2339
2405
|
"exists": true,
|
|
2340
|
-
"digest": "sha256:
|
|
2406
|
+
"digest": "sha256:3b3ac97c353f7549229f1102cca38236e734ec8d08c219d4a6e5ef2a48fc0e16"
|
|
2341
2407
|
},
|
|
2342
2408
|
{
|
|
2343
2409
|
"id": "build-facts",
|
|
@@ -2353,7 +2419,7 @@
|
|
|
2353
2419
|
"path": "docs/kfd-support.md",
|
|
2354
2420
|
"plane": "verify",
|
|
2355
2421
|
"exists": true,
|
|
2356
|
-
"digest": "sha256:
|
|
2422
|
+
"digest": "sha256:ab15de33a1a9e292b6da74c00b8b96b7c46330d0553a454d1de4c24c672fc025"
|
|
2357
2423
|
},
|
|
2358
2424
|
{
|
|
2359
2425
|
"id": "lifecycle-protocol",
|
|
@@ -2361,7 +2427,7 @@
|
|
|
2361
2427
|
"path": "docs/lifecycle-protocol.md",
|
|
2362
2428
|
"plane": "use",
|
|
2363
2429
|
"exists": true,
|
|
2364
|
-
"digest": "sha256:
|
|
2430
|
+
"digest": "sha256:bef6f703a76667c731dccea6a0385b2196b5a23438ce4bc39894561530975f21"
|
|
2365
2431
|
},
|
|
2366
2432
|
{
|
|
2367
2433
|
"id": "reusable-build-surface",
|
|
@@ -2369,7 +2435,7 @@
|
|
|
2369
2435
|
"path": "docs/reusable-build-surface.md",
|
|
2370
2436
|
"plane": "use",
|
|
2371
2437
|
"exists": true,
|
|
2372
|
-
"digest": "sha256:
|
|
2438
|
+
"digest": "sha256:fbc74dee3a6f2283ea69a2a9a31945ac82ccaf1d270995539f5d80235ab74614"
|
|
2373
2439
|
},
|
|
2374
2440
|
{
|
|
2375
2441
|
"id": "publish-transaction",
|
|
@@ -2385,7 +2451,7 @@
|
|
|
2385
2451
|
"path": "docs/release-governance.md",
|
|
2386
2452
|
"plane": "why",
|
|
2387
2453
|
"exists": true,
|
|
2388
|
-
"digest": "sha256:
|
|
2454
|
+
"digest": "sha256:3ae2bbc2df394726f350e58be1a71dd0379b99b19cd6ccf15fbe3b843f3890b6"
|
|
2389
2455
|
},
|
|
2390
2456
|
{
|
|
2391
2457
|
"id": "release-flow",
|