@kungfu-tech/buildchain 2.8.15 → 2.8.16-alpha.2

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.
@@ -44,5 +44,13 @@
44
44
  "release passport assets"
45
45
  ],
46
46
  "owner": "promote-buildchain-ref"
47
+ },
48
+ "distributionIndexes": {
49
+ "homebrewTap": {
50
+ "projectType": "distribution-index",
51
+ "manifest": "tap-manifest.json",
52
+ "command": "buildchain homebrew check",
53
+ "sourceOfTruth": "upstream release passport and sibling evidence"
54
+ }
47
55
  }
48
56
  }
@@ -13,7 +13,9 @@
13
13
  "./artifact-passport": "./packages/core/artifact-passport.js",
14
14
  "./buildchain-contract": "./packages/core/buildchain-contract.js",
15
15
  "./diagnostics": "./packages/core/diagnostics.js",
16
+ "./homebrew": "./packages/core/homebrew.js",
16
17
  "./issue-reporting": "./packages/core/issue-reporting.js",
18
+ "./readme-badges": "./packages/core/readme-badges.js",
17
19
  "./logging": "./packages/core/logging.js",
18
20
  "./kfd-gate": "./packages/core/kfd-gate.js",
19
21
  "./release-candidate": "./packages/core/release-candidate.js",
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
3
  "contract": "kungfu-buildchain-site-manifest",
4
- "generatedAt": "2026-07-07T13:50:19.556Z",
5
- "publishedAt": "2026-07-07T13:50:19.556Z",
4
+ "generatedAt": "2026-07-07T15:32:30.986Z",
5
+ "publishedAt": "2026-07-07T15:32:30.986Z",
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": "2c3127f2954960ad89f5658a090fb9fe19b442ce",
22
+ "sourceRevision": "d61c8a864e12e34bc6c6e2aac2e7ad60e6caebfd",
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.8.15",
40
+ "version": "2.8.16-alpha.2",
41
41
  "versionSource": "package.json#version"
42
42
  },
43
43
  "entrypoint": "buildchain-site.json",
@@ -53,7 +53,7 @@
53
53
  "path": "docs/MAP.md",
54
54
  "plane": "use",
55
55
  "exists": true,
56
- "digest": "sha256:b5cfef531ba8ca655d8d66ffe0e530a0ca2c971daad5880943d2b824216ed043"
56
+ "digest": "sha256:f4300eed89765cee0df38eb92de4d9d3adce4fbf954c735aead3bea74f05d975"
57
57
  },
58
58
  {
59
59
  "id": "install",
@@ -79,6 +79,22 @@
79
79
  "exists": true,
80
80
  "digest": "sha256:190e3537075f37cf8a7e52bf8254606e1d9450d87c5a81dc11df8b56a7d03065"
81
81
  },
82
+ {
83
+ "id": "readme-badges",
84
+ "title": "README badge blocks",
85
+ "path": "docs/readme-badges.md",
86
+ "plane": "use",
87
+ "exists": true,
88
+ "digest": "sha256:3f4a44ea7f3b70cadc78a343fe53ade74b78fa369c19630cc9b926c1e460f66f"
89
+ },
90
+ {
91
+ "id": "homebrew",
92
+ "title": "Homebrew distribution indexes",
93
+ "path": "docs/homebrew.md",
94
+ "plane": "use",
95
+ "exists": true,
96
+ "digest": "sha256:2fc4e8411f35ca86d19d61c7843b9a1fa440f7afea25df13d3aa03342f09f90c"
97
+ },
82
98
  {
83
99
  "id": "binary-distribution",
84
100
  "title": "Binary distribution contract",
@@ -149,7 +165,7 @@
149
165
  "path": "docs/cli.md",
150
166
  "plane": "use",
151
167
  "exists": true,
152
- "digest": "sha256:a8a348181d6419b746e863d1cacc9d6a91aa6ac5cc2b60819843d44487957c49"
168
+ "digest": "sha256:cfb0bf32f2b8b44bf352e79c27e34b7980e0f66e5fa10e4f202975fbb4780ad1"
153
169
  },
154
170
  {
155
171
  "id": "lifecycle-protocol",
@@ -213,7 +229,7 @@
213
229
  "path": "docs/web-surface-deployments.md",
214
230
  "plane": "use",
215
231
  "exists": true,
216
- "digest": "sha256:f42cc7a81dbeb1b31bec21de61e9807af317bda4055f693ab807b15d9ec77367"
232
+ "digest": "sha256:4c7334fe2284fec3c1249124b0ff85f1242eb7a76d4b2c537c8b2cb6e0e598c1"
217
233
  }
218
234
  ],
219
235
  "facts": [
package/docs/MAP.md CHANGED
@@ -25,6 +25,8 @@ manuals explain those facts and give operator examples.
25
25
  | npm publish transactions, evidence, dist-tags, and recovery | `dist/site/release-model.json`, `dist/site/artifact-schemas.json` | [`publish-transaction.md`](publish-transaction.md) |
26
26
  | 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) |
27
27
  | release propagation for package/site chains | `dist/site/release-model.json` | [`release-propagation.md`](release-propagation.md) |
28
+ | Generated README badge blocks and badge facts | `dist/site/node-api-registry.json`, `dist/site/manual-registry.json`, `kungfu-buildchain-readme-badge-facts` | [`readme-badges.md`](readme-badges.md) |
29
+ | Homebrew tap distribution indexes | `dist/site/node-api-registry.json`, `dist/site/buildchain-contract.json` | [`homebrew.md`](homebrew.md) |
28
30
  | Buildchain CLI manual | `dist/site/cli-registry.json`, `dist/site/manual-registry.json` | [`cli.md`](cli.md) |
29
31
  | Node API / package exports | `dist/site/node-api-registry.json`, `dist/site/release-provenance.json` | [`cli.md`](cli.md#node-api-and-package-exports) |
30
32
 
@@ -59,6 +61,8 @@ replace them.
59
61
  | 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 |
60
62
  | 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 |
61
63
  | How do I propagate finalized upstream releases to downstream package/site PRs? | [`release-propagation.md`](release-propagation.md) | use | preview |
64
+ | How do I generate README status badges without hand-maintaining Markdown? | [`readme-badges.md`](readme-badges.md) + [`cli.md`](cli.md) | use | stable |
65
+ | How do I generate and verify a Homebrew tap from release passport evidence? | [`homebrew.md`](homebrew.md) + [`cli.md`](cli.md) | use/verify | stable |
62
66
  | 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 |
63
67
  | Why are binary release assets archived by platform, and where is the single bundle? | [`binary-distribution.md`](binary-distribution.md) | verify | stable |
64
68
  | How do I add timestamped logs inside build scripts? | [`toolkit-observability.md`](toolkit-observability.md) | use | stable |
@@ -115,6 +119,10 @@ replace them.
115
119
  [`cli.md`](cli.md) and [`publish-transaction.md`](publish-transaction.md).
116
120
  - **release chains / upstream package as source of truth / site synchronization** ->
117
121
  [`release-propagation.md`](release-propagation.md).
122
+ - **README status badges / KFD badge blocks / badge facts JSON** ->
123
+ [`readme-badges.md`](readme-badges.md) and [`cli.md`](cli.md).
124
+ - **Homebrew taps / distribution indexes / Formula drift checks** ->
125
+ [`homebrew.md`](homebrew.md) and [`cli.md`](cli.md).
118
126
  - **KFD-1 contract worlds / byte-for-byte release gates** ->
119
127
  [`release-passport.md`](release-passport.md#kfd-1-contract-world-release-gate).
120
128
  - **KFD-2 public release trust claim audit** ->
package/docs/cli.md CHANGED
@@ -64,7 +64,9 @@ Current public import families include:
64
64
  ```js
65
65
  import * as buildchain from "@kungfu-tech/buildchain";
66
66
  import { createBuildchainLogger } from "@kungfu-tech/buildchain/logging";
67
+ import { checkHomebrewTap } from "@kungfu-tech/buildchain/homebrew";
67
68
  import { verifyKfd1ReleaseGate } from "@kungfu-tech/buildchain/kfd-gate";
69
+ import { collectReadmeBadgeFacts } from "@kungfu-tech/buildchain/readme-badges";
68
70
  import { verifyReleasePassport } from "@kungfu-tech/buildchain/release-passport";
69
71
  import { createReleasePropagationPlan } from "@kungfu-tech/buildchain/release-propagation";
70
72
  import contractWorld from "@kungfu-tech/buildchain/site/buildchain-contract.json" with { type: "json" };
@@ -90,6 +92,8 @@ Supported presets:
90
92
  validation, observation, contract publication, and downstream propagation
91
93
  planning without default mutation. Provider adapters expose built-in command
92
94
  plans by default, and only configured `[infra.commands]` hooks can execute.
95
+ - `--type distribution-index` for Homebrew taps and other index repositories
96
+ whose files are projections of upstream release passport evidence.
93
97
  - `--type anchored-package` for packages whose version is anchored to an
94
98
  explicit upstream release manifest.
95
99
 
@@ -244,9 +248,42 @@ version against configured version files and the anchor manifest. The JSON
244
248
  result is shaped for future `buildchain.libkungfu.dev` fact ingestion.
245
249
 
246
250
  `buildchain release`, `buildchain web-surface`, `buildchain infra-contract`,
247
- `buildchain publish-source`, and `buildchain build-contract` route to the same scripts used by Buildchain's
248
- GitHub Actions workflows. This keeps local inspection and CI behavior on the
249
- same implementation path.
251
+ `buildchain publish-source`, `buildchain badges`, `buildchain homebrew`, and
252
+ `buildchain build-contract` route to the same implementation used by
253
+ Buildchain's package APIs or GitHub Actions workflows. This keeps local
254
+ inspection and CI behavior on the same implementation path.
255
+
256
+ Generate, check, or update the managed README badge block:
257
+
258
+ ```bash
259
+ buildchain badges readme --json
260
+ buildchain badges readme --check
261
+ buildchain badges readme --write
262
+ ```
263
+
264
+ The `--json` form emits the `kungfu-buildchain-readme-badge-facts` object.
265
+ `--check` fails closed when the README marker block is missing or stale.
266
+ `--write` inserts or replaces only the marked block. KFD passed badges come
267
+ from the repository's own verified release passport; unreleased repositories
268
+ downgrade to explicit local declarations such as `declared`, `aligned`, or
269
+ `planned`. See [`readme-badges.md`](readme-badges.md) for the marker contract
270
+ and `[badges]` configuration.
271
+
272
+ Generate or check Homebrew tap projections from upstream release passports:
273
+
274
+ ```bash
275
+ buildchain homebrew update-formula \
276
+ --package buildchain \
277
+ --release-passport https://github.com/kungfu-systems/buildchain/releases/download/v2.8.15/buildchain.release.json \
278
+ --write
279
+
280
+ buildchain homebrew check --json
281
+ ```
282
+
283
+ `update-formula` writes `Formula/buildchain.rb` and `tap-manifest.json` from
284
+ upstream release passport evidence. `check` fails closed when the Formula,
285
+ manifest, artifact digests, or KFD status drift from the upstream passport. See
286
+ [`homebrew.md`](homebrew.md) for the distribution-index project contract.
250
287
 
251
288
  `buildchain collect github-release` creates a release passport bundle from
252
289
  GitHub Release assets or a local asset directory:
@@ -0,0 +1,116 @@
1
+ # Homebrew Distribution Indexes
2
+
3
+ Buildchain treats a Homebrew tap as a distribution-index project: the tap
4
+ contains Formula or Cask files, but those files are projections of upstream
5
+ release passports. Version, download URLs, SHA-256 digests, KFD status, and
6
+ evidence links come from the upstream product release, not from hand-maintained
7
+ tap prose.
8
+
9
+ ## Configuration
10
+
11
+ Use `project.type = "distribution-index"` for tap repositories:
12
+
13
+ ```toml
14
+ schema = 1
15
+
16
+ [project]
17
+ type = "distribution-index"
18
+ name = "homebrew-tap"
19
+
20
+ [lifecycle.verify]
21
+ command = "buildchain homebrew check"
22
+ ```
23
+
24
+ The tap manifest is the repository-owned declaration of which upstream releases
25
+ are indexed. Buildchain writes `tap-manifest.json` as a machine-readable
26
+ projection:
27
+
28
+ ```json
29
+ {
30
+ "schema": 1,
31
+ "contract": "kungfu-buildchain-homebrew-tap-manifest",
32
+ "kind": "homebrew-tap",
33
+ "entries": [
34
+ {
35
+ "type": "formula",
36
+ "name": "buildchain",
37
+ "path": "Formula/buildchain.rb",
38
+ "upstream": {
39
+ "repository": "kungfu-systems/buildchain",
40
+ "tag": "v2.8.15",
41
+ "releasePassportUrl": "https://github.com/kungfu-systems/buildchain/releases/download/v2.8.15/buildchain.release.json"
42
+ },
43
+ "version": "2.8.15",
44
+ "kfd": {
45
+ "kfd-1": "passed",
46
+ "kfd-2": "passed",
47
+ "kfd-3": "passed"
48
+ },
49
+ "artifacts": [
50
+ {
51
+ "platform": "darwin-arm64",
52
+ "url": "https://github.com/kungfu-systems/buildchain/releases/download/v2.8.15/buildchain-aarch64-apple-darwin.tar.gz",
53
+ "sha256": "..."
54
+ }
55
+ ]
56
+ }
57
+ ]
58
+ }
59
+ ```
60
+
61
+ ## CLI
62
+
63
+ Update a formula and manifest from an upstream passport:
64
+
65
+ ```bash
66
+ buildchain homebrew update-formula \
67
+ --package buildchain \
68
+ --release-passport https://github.com/kungfu-systems/buildchain/releases/download/v2.8.15/buildchain.release.json \
69
+ --write
70
+ ```
71
+
72
+ Check that the tap still matches upstream evidence:
73
+
74
+ ```bash
75
+ buildchain homebrew check --json
76
+ ```
77
+
78
+ `check` fails closed when:
79
+
80
+ - the upstream release passport or its sibling evidence does not verify;
81
+ - `Formula/buildchain.rb` drifts from the projected version, URLs, or SHA-256
82
+ digests;
83
+ - `tap-manifest.json` drifts from the projected upstream evidence;
84
+ - the tap claims KFD-1, KFD-2, or KFD-3 passed without a verified upstream
85
+ passport section.
86
+
87
+ ## Node API
88
+
89
+ Use the public `@kungfu-tech/buildchain/homebrew` export:
90
+
91
+ ```js
92
+ import {
93
+ collectHomebrewTapFacts,
94
+ renderHomebrewFormula,
95
+ checkHomebrewTap,
96
+ updateHomebrewTap,
97
+ } from "@kungfu-tech/buildchain/homebrew";
98
+ ```
99
+
100
+ The API is the single implementation source. The CLI is a thin wrapper over
101
+ these functions, so CI and local update commands evaluate the same facts.
102
+
103
+ ## Trust Model
104
+
105
+ Formula metadata is not source of truth. A tap entry may claim `kfd-1`,
106
+ `kfd-2`, or `kfd-3` passed only when the upstream release passport verifies and
107
+ the corresponding passport section is `status = "passed"`. If verification
108
+ fails, Buildchain downgrades the projected KFD status to `unverified` and
109
+ `buildchain homebrew check` fails.
110
+
111
+ In short: KFD passed in a tap means the upstream release passport passed, not
112
+ that the tap author typed a passing status.
113
+
114
+ This makes Homebrew taps suitable for automated distribution-index CI: the tap
115
+ can move quickly while still proving that every download URL and digest is
116
+ bound to release passport evidence.
@@ -0,0 +1,124 @@
1
+ # README Badge Blocks
2
+
3
+ Buildchain can generate a managed README badge block from repository-owned
4
+ facts. The README keeps only a projection; the source facts remain in
5
+ `buildchain.toml`, package metadata, workflow files, and the repository's own
6
+ release passport.
7
+
8
+ The managed block is delimited by:
9
+
10
+ ```markdown
11
+ <!-- buildchain:badges:start -->
12
+ ...
13
+ <!-- buildchain:badges:end -->
14
+ ```
15
+
16
+ Buildchain owns only that block. Everything outside the markers remains normal
17
+ README content.
18
+
19
+ ## Node API
20
+
21
+ Use the public package export:
22
+
23
+ ```js
24
+ import {
25
+ collectReadmeBadgeFacts,
26
+ renderReadmeBadgeBlock,
27
+ checkReadmeBadgeBlock,
28
+ updateReadmeBadgeBlock,
29
+ } from "@kungfu-tech/buildchain/readme-badges";
30
+ ```
31
+
32
+ `collectReadmeBadgeFacts({ cwd })` returns a machine-readable object with
33
+ contract `kungfu-buildchain-readme-badge-facts`. It collects repository
34
+ identity, package name/version/license, configured platforms, configured
35
+ workflow status badges, release passport location and verification result, and
36
+ KFD badge state. When present, it also summarizes local KFD claim registry and
37
+ product-mechanism facts from the package-owned site bundle, so downstream
38
+ agents can connect README badges back to Buildchain's KFD/source-of-truth
39
+ surfaces.
40
+
41
+ `renderReadmeBadgeBlock(facts)` renders deterministic Markdown from that facts
42
+ object. `checkReadmeBadgeBlock({ readmeText, facts })` compares the current
43
+ README marker block against the expected block and reports missing or stale
44
+ drift. `updateReadmeBadgeBlock({ readmeText, facts })` inserts or replaces the
45
+ managed block.
46
+
47
+ The Node API is the implementation source. The CLI delegates to it.
48
+
49
+ ## CLI
50
+
51
+ Generate facts as JSON:
52
+
53
+ ```bash
54
+ buildchain badges readme --json
55
+ ```
56
+
57
+ Fail closed when the README block is missing or stale:
58
+
59
+ ```bash
60
+ buildchain badges readme --check
61
+ ```
62
+
63
+ Insert or replace the block:
64
+
65
+ ```bash
66
+ buildchain badges readme --write
67
+ ```
68
+
69
+ All commands accept `--cwd <dir>` and `--readme <path>`. Repositories can add
70
+ `buildchain badges readme --check` to CI so badge drift is detected like any
71
+ other generated release-facing surface.
72
+
73
+ ## Configuration
74
+
75
+ The optional `[badges]` table in `buildchain.toml` declares local facts that
76
+ cannot be inferred safely:
77
+
78
+ ```toml
79
+ [badges]
80
+ release_passport = "https://github.com/example/project/releases/latest/download/buildchain.release.json"
81
+ kfd_1 = "declared"
82
+ kfd_2 = "planned"
83
+ kfd_3 = "aligned"
84
+ platforms = ["macOS", "Linux", "Windows"]
85
+ workflows = ["verify.yml", "build.yml"]
86
+ ```
87
+
88
+ `release_passport` may be a local path or URL. If omitted, Buildchain tries
89
+ `buildchain.release.json`, then `.buildchain/release-passport/buildchain.release.json`,
90
+ then the repository's latest GitHub Release asset when the GitHub repository
91
+ can be discovered.
92
+
93
+ ## KFD Badge Rules
94
+
95
+ KFD passed is evidence-backed. A repository may display `KFD-1 passed`,
96
+ `KFD-2 passed`, or `KFD-3 passed` only when its own release passport verifies
97
+ successfully and the corresponding passport section has `status: "passed"`.
98
+
99
+ When no release passport exists yet, or when the passport cannot be verified,
100
+ Buildchain downgrades each KFD badge to the explicit local declaration such as
101
+ `declared`, `aligned`, or `planned`. A local `passed` declaration is treated as
102
+ `declared`; unknown local states are normalized to a non-passed fallback.
103
+
104
+ Buildchain's own README may link to Buildchain's own release passport. Other
105
+ repositories must not claim Buildchain's KFD status as their own; their badge
106
+ links must point to their own release passport or evidence page.
107
+
108
+ ## CI Contract
109
+
110
+ Recommended CI gate:
111
+
112
+ ```bash
113
+ buildchain badges readme --check
114
+ ```
115
+
116
+ The check fails when:
117
+
118
+ - the marker block is missing;
119
+ - generated Markdown differs from repository facts;
120
+ - a previously hand-written KFD passed claim is not backed by the repository's
121
+ verified release passport facts.
122
+
123
+ The machine-readable facts object should be used by downstream site renderers
124
+ or audit tools when Markdown badges are not enough.
@@ -264,12 +264,32 @@ rollback:
264
264
  "alias": "sha-abcdef123456",
265
265
  "url": "https://sha-abcdef123456.preview.libkungfu.dev",
266
266
  "sourcePath": "/",
267
+ "artifactPathPrefix": "",
268
+ "viewerPathPrefix": "/",
269
+ "directoryIndex": "index.html",
270
+ "directoryIndexResolution": true,
267
271
  "canonicalUrl": "https://libkungfu.dev",
268
272
  "bucket": "libkungfu-dev-preview",
269
273
  "distributionId": "E-PREVIEW",
270
274
  "originPath": "",
271
275
  "objectPrefix": "sha-abcdef123456",
272
276
  "manifestKey": ".buildchain/deployments/sha-abcdef123456/hub.json",
277
+ "routing": {
278
+ "contract": "kungfu-buildchain-web-surface-path-prefix-rewrite",
279
+ "viewerPathPrefix": "/",
280
+ "artifactPathPrefix": "",
281
+ "objectPrefix": "sha-abcdef123456",
282
+ "directoryIndex": "index.html",
283
+ "directoryIndexResolution": true
284
+ },
285
+ "smokeUrls": [
286
+ {
287
+ "kind": "root",
288
+ "requestPath": "/",
289
+ "url": "https://sha-abcdef123456.preview.libkungfu.dev/",
290
+ "required": true
291
+ }
292
+ ],
273
293
  "noindex": true,
274
294
  "accessControl": "none"
275
295
  }
@@ -343,6 +363,19 @@ node scripts/web-surface.mjs \
343
363
  --output .buildchain/web-surface-staging-apply.json
344
364
  ```
345
365
 
366
+ For multi-surface sites, each surface host is treated as a root-relative view
367
+ of that surface's artifact path prefix. For example, a `buildchain` surface with
368
+ `path = "/buildchain/"` and preview URL
369
+ `https://buildchain-pr-29.preview.libkungfu.dev` syncs the artifact subtree
370
+ `dist/buildchain/` to the preview object prefix `pr-29/buildchain`. A viewer
371
+ request for `https://buildchain-pr-29.preview.libkungfu.dev/docs/` therefore
372
+ resolves against the artifact's `dist/buildchain/docs/index.html`, not
373
+ `dist/docs/index.html` and not the hub surface root. The deployment manifest
374
+ records this as `routing.contract =
375
+ "kungfu-buildchain-web-surface-path-prefix-rewrite"` with
376
+ `viewerPathPrefix = "/"`, `artifactPathPrefix = "buildchain"`, and
377
+ `directoryIndexResolution = true`.
378
+
346
379
  It can also execute a previously saved deploy plan. In that mode Buildchain
347
380
  recomputes the local artifact hash before running AWS commands and fails closed
348
381
  if the artifact no longer matches the saved plan:
@@ -414,7 +447,7 @@ The production preflight checks that:
414
447
  `kfd.libkungfu.dev`;
415
448
  - DNS resolves for every surface host.
416
449
 
417
- After production apply, the workflow runs:
450
+ After preview, staging, and production apply, the workflow runs:
418
451
 
419
452
  ```bash
420
453
  node scripts/web-surface.mjs \
@@ -424,13 +457,18 @@ node scripts/web-surface.mjs \
424
457
  --output .buildchain/web-surface-production-health.json
425
458
  ```
426
459
 
427
- The health check fetches every surface URL from the apply result and fails
428
- production if a response is unreachable, returns an unexpected status, or still
429
- sends `x-robots-tag: noindex`. It also verifies that each surface binding
430
- recorded a deployment manifest pointer. The production release passport embeds
431
- the deploy plan, apply result, production preflight, and health check so a
432
- reviewer or agent can audit why the production site changed and whether every
433
- declared host was actually covered.
460
+ The health check fetches every surface root URL and the nested smoke URLs
461
+ recorded in each surface binding. Nested smoke URLs are derived from the
462
+ artifact files under the surface path prefix, with directory index resolution
463
+ such as `dist/buildchain/docs/index.html` becoming `/docs/` on the buildchain
464
+ preview host. This fails closed when a deploy reports success but a child page
465
+ returns 403 or another unexpected status. Production additionally fails if a
466
+ response is unreachable, returns an unexpected status, or still sends
467
+ `x-robots-tag: noindex`. The health check also verifies that each surface
468
+ binding recorded a deployment manifest pointer. The production release passport
469
+ embeds the deploy plan, apply result, production preflight, and health check so
470
+ a reviewer or agent can audit why the production site changed and whether every
471
+ declared host and nested route was actually covered.
434
472
 
435
473
  ## Cleanup Plans
436
474
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kungfu-tech/buildchain",
3
- "version": "2.8.15",
3
+ "version": "2.8.16-alpha.2",
4
4
  "private": false,
5
5
  "description": "Buildchain Release Passport, release governance, CLI toolkit, and site facts.",
6
6
  "repository": "https://github.com/kungfu-systems/buildchain",
@@ -16,7 +16,9 @@
16
16
  "./artifact-passport": "./packages/core/artifact-passport.js",
17
17
  "./buildchain-contract": "./packages/core/buildchain-contract.js",
18
18
  "./diagnostics": "./packages/core/diagnostics.js",
19
+ "./homebrew": "./packages/core/homebrew.js",
19
20
  "./issue-reporting": "./packages/core/issue-reporting.js",
21
+ "./readme-badges": "./packages/core/readme-badges.js",
20
22
  "./logging": "./packages/core/logging.js",
21
23
  "./kfd-gate": "./packages/core/kfd-gate.js",
22
24
  "./release-candidate": "./packages/core/release-candidate.js",
@@ -14,6 +14,8 @@ Current shared surfaces:
14
14
  `@kungfu-tech/buildchain/diagnostics`;
15
15
  - release passport creation and verification through
16
16
  `@kungfu-tech/buildchain/release-passport`.
17
+ - managed README badge facts and marker blocks through
18
+ `@kungfu-tech/buildchain/readme-badges`.
17
19
 
18
20
  ## Toolkit Imports
19
21
 
@@ -53,3 +55,13 @@ const { collectRunnerDiagnostics } = await import("@kungfu-tech/buildchain/diagn
53
55
  Web-surface validation stays in core because both local scripts and GitHub
54
56
  Actions need the same fail-closed interpretation of project, channel, deploy,
55
57
  retention, and staging security declarations.
58
+
59
+ README badge consumers should import the public subpath and treat Markdown as a
60
+ projection of the returned facts:
61
+
62
+ ```js
63
+ import { collectReadmeBadgeFacts, renderReadmeBadgeBlock } from "@kungfu-tech/buildchain/readme-badges";
64
+
65
+ const facts = await collectReadmeBadgeFacts({ cwd: process.cwd() });
66
+ const markdown = renderReadmeBadgeBlock(facts);
67
+ ```
@@ -9,7 +9,7 @@ const RESERVED_LIFECYCLE_KEYS = new Set(["env", "shell"]);
9
9
  const SUPPORTED_VERSION_FILE_TYPES = new Set(["json", "toml", "regex"]);
10
10
  const SUPPORTED_VERSION_STRATEGIES = new Set(["semver", "anchored"]);
11
11
  const SUPPORTED_VERSION_NEXT = new Set(["auto", "manual"]);
12
- const SUPPORTED_PROJECT_TYPES = new Set(["package", "web-surface", "infra-contract"]);
12
+ const SUPPORTED_PROJECT_TYPES = new Set(["package", "web-surface", "infra-contract", "distribution-index"]);
13
13
  const SUPPORTED_PUBLISH_MODES = new Set(["publish-final-version", "promote-existing-version"]);
14
14
  const SUPPORTED_PUBLISH_AUTH = new Set(["trusted-publishing", "npm-token"]);
15
15
  const SUPPORTED_PACKAGE_SET_ORDER = new Set(["as-provided", "platforms-first-main-last"]);
@@ -237,7 +237,7 @@ function normalizeProjectSection(project) {
237
237
  assertPlainObject(project, "project");
238
238
  const type = assertString(project.type, "project.type");
239
239
  if (!SUPPORTED_PROJECT_TYPES.has(type)) {
240
- throw new Error("project.type must be one of package, web-surface, or infra-contract");
240
+ throw new Error("project.type must be one of package, web-surface, infra-contract, or distribution-index");
241
241
  }
242
242
  const normalized = { type };
243
243
  for (const key of ["name", "site"]) {
@@ -309,6 +309,9 @@ export function createBuildchainContractWorld({ root = process.cwd(), packageJso
309
309
  optionalInputs: [
310
310
  "validate",
311
311
  "lifecycle",
312
+ "badges readme",
313
+ "homebrew update-formula",
314
+ "homebrew check",
312
315
  "collect github-release",
313
316
  "verify release-passport",
314
317
  "release-propagation",
@@ -316,6 +319,59 @@ export function createBuildchainContractWorld({ root = process.cwd(), packageJso
316
319
  ],
317
320
  guarantees: [
318
321
  "CLI commands are stable within the major line unless the contract major changes",
322
+ "README badge block checks and writes are generated from machine-readable repository facts",
323
+ ],
324
+ }),
325
+ surface(root, {
326
+ id: "homebrew-distribution-index",
327
+ kind: "node-api",
328
+ path: "packages/core/homebrew.js",
329
+ requiredInputs: ["upstream release passport"],
330
+ requiredOutputs: [
331
+ "kungfu-buildchain-homebrew-tap-facts",
332
+ "kungfu-buildchain-homebrew-tap-manifest",
333
+ "Formula/*.rb",
334
+ ],
335
+ breakingDefaults: {
336
+ projectType: "distribution-index",
337
+ tapManifest: "tap-manifest.json",
338
+ kfdPassedSource: "verified upstream release passport",
339
+ },
340
+ optionalInputs: [
341
+ "buildchain.toml [project] type=distribution-index",
342
+ "Formula path",
343
+ "manifest path",
344
+ "release passport URL or local path",
345
+ ],
346
+ guarantees: [
347
+ "Formula metadata is a deterministic projection of upstream release passport evidence",
348
+ "tap-manifest.json is checked against upstream version, URLs, SHA-256 digests, and KFD status",
349
+ "KFD passed claims fail closed unless the upstream release passport verifies the corresponding section",
350
+ "CLI and JavaScript callers use the same Node API implementation",
351
+ ],
352
+ }),
353
+ surface(root, {
354
+ id: "readme-badge-facts",
355
+ kind: "node-api",
356
+ path: "packages/core/readme-badges.js",
357
+ requiredInputs: ["repository checkout"],
358
+ requiredOutputs: ["kungfu-buildchain-readme-badge-facts"],
359
+ breakingDefaults: {
360
+ markerStart: "<!-- buildchain:badges:start -->",
361
+ markerEnd: "<!-- buildchain:badges:end -->",
362
+ kfdPassedSource: "verified repository-owned release passport",
363
+ },
364
+ optionalInputs: [
365
+ "buildchain.toml [badges]",
366
+ "release passport URL or local path",
367
+ "workflow file list",
368
+ "platform declarations",
369
+ ],
370
+ guarantees: [
371
+ "README badge Markdown is a deterministic projection of badge facts",
372
+ "KFD passed badges require the repository's own verified release passport section",
373
+ "unreleased repositories downgrade KFD status to explicit non-passed declarations",
374
+ "CLI and JavaScript callers use the same Node API implementation",
319
375
  ],
320
376
  }),
321
377
  surface(root, {