@kungfu-tech/buildchain 2.9.0 → 2.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/docs/MAP.md CHANGED
@@ -21,6 +21,7 @@ manuals explain those facts and give operator examples.
21
21
  | Capability | Machine-readable entry | Manual entry |
22
22
  | --- | --- | --- |
23
23
  | 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) |
24
+ | 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) |
24
25
  | Floating `@v2` drift detection and compatibility issues | `dist/site/buildchain-contract.json` | [`reusable-build-surface.md`](reusable-build-surface.md#floating-ref-contract-lock) |
25
26
  | 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
27
  | 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) |
package/docs/cli.md CHANGED
@@ -71,9 +71,12 @@ import { collectBadgeBundleFacts } from "@kungfu-tech/buildchain/badges";
71
71
  import { collectReadmeBadgeFacts } from "@kungfu-tech/buildchain/readme-badges";
72
72
  import { verifyReleasePassport } from "@kungfu-tech/buildchain/release-passport";
73
73
  import { createReleasePropagationPlan } from "@kungfu-tech/buildchain/release-propagation";
74
+ import { planReleaseLineBootstrap } from "@kungfu-tech/buildchain/release-line-bootstrap";
75
+ import { collectPublicSurfaceReverseAudit } from "@kungfu-tech/buildchain/public-surface-audit";
74
76
  import contractWorld from "@kungfu-tech/buildchain/site/buildchain-contract.json" with { type: "json" };
75
77
  import manualRegistry from "@kungfu-tech/buildchain/site/manual-registry.json" with { type: "json" };
76
78
  import nodeApiRegistry from "@kungfu-tech/buildchain/site/node-api-registry.json" with { type: "json" };
79
+ import publicSurfaceAudit from "@kungfu-tech/buildchain/site/public-surface-audit.json" with { type: "json" };
77
80
  ```
78
81
 
79
82
  Use `dist/site/manual-registry.json` to find the packaged operating manuals and
@@ -121,6 +124,50 @@ buildchain lifecycle run build \
121
124
  --artifact-name "{repo}-{version}-{platform}"
122
125
  ```
123
126
 
127
+ `buildchain release line open` plans or writes the first version-state commit
128
+ for a new semver minor line. It does not publish anything. The dry-run mode is
129
+ the default and returns the dev/alpha/release refs, protection contract, default
130
+ branch action, and initial version before any GitHub mutation happens:
131
+
132
+ ```bash
133
+ buildchain release line open \
134
+ --major 2 \
135
+ --minor 10 \
136
+ --source-ref release/v2/v2.9 \
137
+ --json
138
+ ```
139
+
140
+ The write mode only updates local version-state files. The repository workflow
141
+ `Release Line Bootstrap` wraps this command and, when `apply=true`, commits the
142
+ initial version state, creates `dev/vX/vX.Y`, `alpha/vX/vX.Y`, and
143
+ `release/vX/vX.Y`, applies one-review branch protection, switches the default
144
+ branch, and opens the first dev-to-alpha channel PR:
145
+
146
+ ```bash
147
+ buildchain release line open \
148
+ --major 2 \
149
+ --minor 10 \
150
+ --source-ref release/v2/v2.9 \
151
+ --write \
152
+ --json
153
+ ```
154
+
155
+ `buildchain` also publishes a public surface reverse audit as
156
+ `dist/site/public-surface-audit.json`. The audit enumerates CLI commands from
157
+ `bin/buildchain.mjs`, workflow inputs, action inputs, site pages, and docs
158
+ command references, then compares them with the generated registries. Buildchain
159
+ self-checks fail closed when an enumerable public surface is missing from the
160
+ registry:
161
+
162
+ ```js
163
+ import {
164
+ collectPublicSurfaceReverseAudit,
165
+ assertPublicSurfaceReverseAudit,
166
+ } from "@kungfu-tech/buildchain/public-surface-audit";
167
+
168
+ assertPublicSurfaceReverseAudit(collectPublicSurfaceReverseAudit({ root: process.cwd() }));
169
+ ```
170
+
124
171
  Lifecycle runs also write a Buildchain observability JSONL log at
125
172
  `.buildchain/logs/events.jsonl` by default. Framework events use
126
173
  `source=buildchain`; consumer lifecycle commands use `source=user`. This lets a
@@ -73,6 +73,37 @@ The intended governance split is:
73
73
  - protected branches still require reviewed channel PRs before Buildchain can
74
74
  move any exact or floating release refs.
75
75
 
76
+ ## Opening a Minor Line
77
+
78
+ New minor lines should be opened through Buildchain instead of hand-created
79
+ branches. The reusable entrypoint is the `Release Line Bootstrap` workflow. It
80
+ defaults to dry-run so maintainers can inspect the planned refs, protection
81
+ contract, initial version, and first alpha PR before any mutation.
82
+
83
+ The workflow is backed by the CLI command:
84
+
85
+ ```bash
86
+ buildchain release line open \
87
+ --major 2 \
88
+ --minor 10 \
89
+ --source-ref release/v2/v2.9 \
90
+ --json
91
+ ```
92
+
93
+ When the workflow is run with `apply=true`, Buildchain:
94
+
95
+ - writes the initial version-state commit, such as `2.10.0-alpha.0`;
96
+ - creates `dev/v2/v2.10` from that commit;
97
+ - creates `alpha/v2/v2.10` and `release/v2/v2.10` from the selected source ref;
98
+ - applies branch protection with one approving review and the configured
99
+ required status check;
100
+ - switches the repository default branch to the new dev line when requested;
101
+ - opens the first `dev/v2/v2.10 -> alpha/v2/v2.10` channel PR when requested.
102
+
103
+ This makes minor-line creation a single audited operation. The channel PR still
104
+ goes through the normal verify/review/promotion path before an alpha is
105
+ published.
106
+
76
107
  ## Alpha Promotion
77
108
 
78
109
  ```mermaid
@@ -261,6 +261,16 @@ by downstream sites and by Buildchain's own release passport. Exact release
261
261
  version/SHA binding is deliberately deferred to the promotion witness, so the
262
262
  source registry can remain stable across semver version-state bumps.
263
263
 
264
+ Buildchain also performs a reverse audit before that witness is used. The
265
+ generated `dist/site/public-surface-audit.json` enumerates real CLI commands
266
+ from `bin/buildchain.mjs`, workflow inputs, action inputs, site pages, and docs
267
+ command references, then compares them with the generated registries. Buildchain
268
+ self KFD witnesses include that audit result and classify the collaboration
269
+ interface as closed-world only when the reverse audit passes. If a public
270
+ command, workflow input, action input, or site page is exposed without a
271
+ registry entry, `pnpm run check` fails before release promotion can produce a
272
+ passport.
273
+
264
274
  The product remains the fact source. Before build/publish, the product writes a
265
275
  pre-build witness:
266
276
 
@@ -17,6 +17,7 @@ dist/site/
17
17
  manual-registry.json
18
18
  node-api-registry.json
19
19
  workflow-registry.json
20
+ public-surface-audit.json
20
21
  release-model.json
21
22
  artifact-schemas.json
22
23
  buildchain-contract.json
@@ -51,6 +52,12 @@ internal paths.
51
52
  from `packages/core/buildchain-kfd-claims.js` and enumerates the public release
52
53
  claims plus the KFD-3 collaboration surfaces that Buildchain self-verifies
53
54
  during release promotion.
55
+ `public-surface-audit.json` is the reverse enumeration report for those
56
+ surfaces. It enumerates real CLI commands from `bin/buildchain.mjs`, workflow
57
+ inputs, action inputs, site pages, and documentation command references, then
58
+ compares those sets with `cli-registry.json`, `workflow-registry.json`, and
59
+ `page-registry.json`. Buildchain's self-check fails closed when an enumerable
60
+ public surface is missing from the generated registries.
54
61
 
55
62
  ## Timestamp and Reproducibility Policy
56
63
 
@@ -384,6 +384,16 @@ and `pr-29/buildchain/docs/`. This makes surface-host requests for `/` and
384
384
  `/docs/` resolve to the surface's `index.html` files even when the CloudFront
385
385
  origin is an S3 REST origin rather than an S3 website endpoint.
386
386
 
387
+ For host-per-surface previews, Buildchain also ensures each configured
388
+ CloudFront distribution has `DefaultRootObject = "index.html"` before syncing
389
+ the surface payload. This is required because the child surface host root
390
+ request (`https://buildchain-pr-29.preview.libkungfu.dev/`) must first resolve
391
+ to `/index.html`; the existing host/prefix mapping can then serve the object
392
+ `pr-29/buildchain/index.html`, the same object that explicit
393
+ `/index.html` requests already reach. The operation is idempotent per
394
+ distribution and is emitted once even when multiple surfaces share the same
395
+ CloudFront distribution.
396
+
387
397
  It can also execute a previously saved deploy plan. In that mode Buildchain
388
398
  recomputes the local artifact hash before running AWS commands and fails closed
389
399
  if the artifact no longer matches the saved plan:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kungfu-tech/buildchain",
3
- "version": "2.9.0",
3
+ "version": "2.9.1",
4
4
  "private": false,
5
5
  "description": "Buildchain Release Passport, release governance, CLI toolkit, and site facts.",
6
6
  "repository": "https://github.com/kungfu-systems/buildchain",
@@ -20,7 +20,9 @@
20
20
  "./diagnostics": "./packages/core/diagnostics.js",
21
21
  "./homebrew": "./packages/core/homebrew.js",
22
22
  "./issue-reporting": "./packages/core/issue-reporting.js",
23
+ "./release-line-bootstrap": "./packages/core/release-line-bootstrap.js",
23
24
  "./readme-badges": "./packages/core/readme-badges.js",
25
+ "./public-surface-audit": "./packages/core/public-surface-audit.js",
24
26
  "./logging": "./packages/core/logging.js",
25
27
  "./kfd-gate": "./packages/core/kfd-gate.js",
26
28
  "./release-candidate": "./packages/core/release-candidate.js",
@@ -36,6 +38,7 @@
36
38
  "./site/node-api-registry.json": "./dist/site/node-api-registry.json",
37
39
  "./site/kfd-claims.json": "./dist/site/kfd-claims.json",
38
40
  "./site/workflow-registry.json": "./dist/site/workflow-registry.json",
41
+ "./site/public-surface-audit.json": "./dist/site/public-surface-audit.json",
39
42
  "./site/release-model.json": "./dist/site/release-model.json",
40
43
  "./site/artifact-schemas.json": "./dist/site/artifact-schemas.json",
41
44
  "./site/buildchain-contract.json": "./dist/site/buildchain-contract.json",
@@ -2,6 +2,10 @@ import crypto from "node:crypto";
2
2
  import fs from "node:fs";
3
3
  import path from "node:path";
4
4
  import { createBuildchainContractWorld, sha256Json } from "./buildchain-contract.js";
5
+ import {
6
+ BUILDCHAIN_PUBLIC_SURFACE_AUDIT_CONTRACT,
7
+ collectPublicSurfaceReverseAudit,
8
+ } from "./public-surface-audit.js";
5
9
 
6
10
  export const BUILDCHAIN_KFD_CLAIM_REGISTRY_CONTRACT = "kungfu-buildchain-kfd-claim-registry";
7
11
  export const BUILDCHAIN_KFD_COLLABORATION_INTERFACE_CONTRACT = "kungfu-buildchain-kfd-collaboration-interface";
@@ -41,6 +45,7 @@ const SITE_CONTRACT_FILES = Object.freeze([
41
45
  "dist/site/manual-registry.json",
42
46
  "dist/site/node-api-registry.json",
43
47
  "dist/site/workflow-registry.json",
48
+ "dist/site/public-surface-audit.json",
44
49
  "dist/site/release-model.json",
45
50
  "dist/site/artifact-schemas.json",
46
51
  "dist/site/buildchain-contract.json",
@@ -55,6 +60,7 @@ const SCHEMA_AND_STANDARD_FILES = Object.freeze([
55
60
  "packages/core/release-passport.js",
56
61
  "packages/core/buildchain-contract.js",
57
62
  "packages/core/buildchain-kfd-claims.js",
63
+ "packages/core/public-surface-audit.js",
58
64
  "dist/site/artifact-schemas.json",
59
65
  "dist/site/buildchain-contract.json",
60
66
  ]);
@@ -79,6 +85,51 @@ const EXTRA_KFD1_FILES = Object.freeze([
79
85
  "scripts/ensure-github-release.mjs",
80
86
  ]);
81
87
 
88
+ function publicSurfaceReverseAudit({ root }) {
89
+ if (!fileExists(root, "bin/buildchain.mjs")) {
90
+ return {
91
+ schemaVersion: 1,
92
+ contract: BUILDCHAIN_PUBLIC_SURFACE_AUDIT_CONTRACT,
93
+ status: "unavailable",
94
+ summary: { failureCount: 0 },
95
+ enumerated: {
96
+ cliCommands: [],
97
+ workflowInputs: [],
98
+ actionInputs: [],
99
+ sitePages: [],
100
+ docCommandRefs: [],
101
+ },
102
+ declared: {},
103
+ comparison: {
104
+ missingCliRegistry: [],
105
+ missingWorkflowRegistry: [],
106
+ missingActionRegistry: [],
107
+ missingPageRegistry: [],
108
+ unknownDocCommandRefs: [],
109
+ },
110
+ auditBoundary: {
111
+ mode: "not-enumerated",
112
+ scope: "Fixture or partial source tree without bin/buildchain.mjs",
113
+ residualRisk: ["Reverse audit is only enforceable in a complete Buildchain source tree."],
114
+ },
115
+ };
116
+ }
117
+ return collectPublicSurfaceReverseAudit({ root });
118
+ }
119
+
120
+ function publicSurfaceAuditEvidence(root) {
121
+ const relPath = "dist/site/public-surface-audit.json";
122
+ const audit = publicSurfaceReverseAudit({ root });
123
+ return {
124
+ contract: BUILDCHAIN_PUBLIC_SURFACE_AUDIT_CONTRACT,
125
+ path: relPath,
126
+ status: audit.status,
127
+ sha256: fileExists(root, relPath) ? sha256File(root, relPath) : "",
128
+ summary: audit.summary,
129
+ auditBoundary: audit.auditBoundary,
130
+ };
131
+ }
132
+
82
133
  function immediateReadmes(root, dir) {
83
134
  const absoluteDir = path.join(root, dir);
84
135
  if (!fs.existsSync(absoluteDir)) return [];
@@ -214,6 +265,23 @@ export function createBuildchainPublicClaimDefinitions() {
214
265
  "dist/site/site-manifest.json",
215
266
  ],
216
267
  },
268
+ {
269
+ id: "claim:buildchain-public-surface-reverse-audit",
270
+ claim: "Buildchain fails closed when enumerable public CLI, workflow, action, site page, or documentation command surfaces are exposed without a matching machine registry entry.",
271
+ sourcePaths: [
272
+ "packages/core/public-surface-audit.js",
273
+ "scripts/generate-site-bundle.mjs",
274
+ "scripts/check-inventory.mjs",
275
+ "bin/buildchain.mjs",
276
+ ],
277
+ artifactPaths: [
278
+ "dist/site/public-surface-audit.json",
279
+ "dist/site/cli-registry.json",
280
+ "dist/site/workflow-registry.json",
281
+ "dist/site/page-registry.json",
282
+ "dist/site/kfd-claims.json",
283
+ ],
284
+ },
217
285
  {
218
286
  id: "claim:buildchain-readme-badge-facts",
219
287
  claim: "Buildchain README status badges are generated from repository-owned facts and verified release-passport evidence, not hand-maintained README prose.",
@@ -309,6 +377,7 @@ export function createBuildchainPublicClaimDefinitions() {
309
377
 
310
378
  export function createBuildchainKfdSurfaceRegistry({ root = process.cwd() } = {}) {
311
379
  const pkg = packageJson(root);
380
+ const reverseAudit = publicSurfaceReverseAudit({ root });
312
381
  const exports = Object.entries(pkg.exports || {})
313
382
  .filter(([specifier]) => !specifier.startsWith("./site/") && specifier !== "./package.json")
314
383
  .map(([specifier, target]) => surface(
@@ -337,18 +406,40 @@ export function createBuildchainKfdSurfaceRegistry({ root = process.cwd() } = {}
337
406
  ];
338
407
  const siteConsumptionContracts = SITE_CONTRACT_FILES.map((relPath) => surface(`site:${relPath}`, "site-consumption-contract", relPath));
339
408
  const controlSurfaces = WORKFLOW_AND_ACTION_FILES.map((relPath) => surface(`control:${relPath}`, relPath.includes("actions/") ? "action" : "workflow", relPath));
409
+ const reverseEnumeratedSurfaces = uniqueById([
410
+ ...reverseAudit.enumerated.cliCommands.map((entry) => surface(`cli:${entry.id}`, "cli-command", "bin/buildchain.mjs", {
411
+ name: entry.usage,
412
+ reverseAuditSource: entry.source,
413
+ })),
414
+ ...reverseAudit.enumerated.workflowInputs.map((entry) => surface(`workflow:${entry.id}`, "workflow", entry.path, {
415
+ inputCount: entry.inputCount,
416
+ inputs: entry.inputs,
417
+ reverseAuditSource: ".github/workflows",
418
+ })),
419
+ ...reverseAudit.enumerated.actionInputs.map((entry) => surface(`action:${entry.id}`, "action", entry.path, {
420
+ inputCount: entry.inputCount,
421
+ inputs: entry.inputs,
422
+ reverseAuditSource: "actions/*/action.yml",
423
+ })),
424
+ ...reverseAudit.enumerated.sitePages.map((entry) => surface(`site-page:${entry.id}`, "site-page", "dist/site/page-registry.json", {
425
+ pagePath: entry.path,
426
+ reverseAuditSource: "dist/site/page-registry.json",
427
+ })),
428
+ ]);
340
429
  return {
341
430
  schemaVersion: 1,
342
431
  contract: BUILDCHAIN_KFD_COLLABORATION_INTERFACE_CONTRACT,
432
+ reverseAudit: publicSurfaceAuditEvidence(root),
343
433
  groups: {
344
434
  docs,
345
435
  schemas,
346
436
  standardsMetadata,
347
437
  packageExports: exports,
348
438
  siteConsumptionContracts,
439
+ reverseEnumeratedSurfaces,
349
440
  },
350
441
  additionalSurfaces: controlSurfaces,
351
- publicSurfaceCount: docs.length + schemas.length + standardsMetadata.length + exports.length + siteConsumptionContracts.length + controlSurfaces.length,
442
+ publicSurfaceCount: docs.length + schemas.length + standardsMetadata.length + exports.length + siteConsumptionContracts.length + reverseEnumeratedSurfaces.length + controlSurfaces.length,
352
443
  };
353
444
  }
354
445
 
@@ -366,6 +457,7 @@ export function createBuildchainKfdClaimRegistry({ root = process.cwd(), sourceS
366
457
  sourceModule: "packages/core/buildchain-kfd-claims.js",
367
458
  },
368
459
  runtimeContract: runtimeContractSummary({ root }),
460
+ publicSurfaceReverseAudit: publicSurfaceAuditEvidence(root),
369
461
  publicClaims: createBuildchainPublicClaimDefinitions(),
370
462
  collaborationSurfaces: createBuildchainKfdSurfaceRegistry({ root }),
371
463
  };
@@ -427,6 +519,7 @@ export function createBuildchainKfd1Witness({ root = process.cwd(), sourceSha =
427
519
  export function createBuildchainKfd3PrebuildWitness({ root = process.cwd(), sourceSha = "" } = {}) {
428
520
  const registry = createBuildchainKfdClaimRegistry({ root, sourceSha });
429
521
  const surfaces = createBuildchainKfdSurfaceRegistry({ root });
522
+ const reverseAudit = publicSurfaceAuditEvidence(root);
430
523
  const digest = `sha256:${sha256Json(registry)}`;
431
524
  return {
432
525
  schemaVersion: 1,
@@ -458,21 +551,24 @@ export function createBuildchainKfd3PrebuildWitness({ root = process.cwd(), sour
458
551
  standardsMetadata: surfaces.groups.standardsMetadata,
459
552
  packageExports: surfaces.groups.packageExports,
460
553
  siteConsumptionContracts: surfaces.groups.siteConsumptionContracts,
554
+ reverseEnumeratedSurfaces: surfaces.groups.reverseEnumeratedSurfaces,
461
555
  surfaces: surfaces.additionalSurfaces,
556
+ reverseAudit,
462
557
  closure: {
463
- classificationMode: "closed-world",
464
- reachableSurfaceMode: "declared-boundary",
558
+ classificationMode: reverseAudit.status === "passed" ? "closed-world" : "partial",
559
+ reachableSurfaceMode: reverseAudit.status === "passed" ? "reverse-enumerated-boundary" : "declared-boundary",
465
560
  unclassifiedEntrypointsPolicy: "fail",
466
- nonExhaustivelyEnumerableSurfaces: [],
561
+ nonExhaustivelyEnumerableSurfaces: reverseAudit.status === "passed" ? [] : [reverseAudit.auditBoundary?.scope || "public surface reverse audit unavailable"],
467
562
  explicitlyExemptedSurfaces: [],
468
563
  },
469
564
  },
470
565
  auditBoundary: {
471
- mode: "closed-world",
566
+ mode: reverseAudit.status === "passed" ? "closed-world" : "partial",
472
567
  scope: "Buildchain public human/agent release, workflow, package, and site-consumption surfaces",
473
- reachableSurfaceMode: "declared-boundary",
568
+ reachableSurfaceMode: reverseAudit.status === "passed" ? "reverse-enumerated-boundary" : "declared-boundary",
474
569
  unclassifiedPolicy: "fail",
475
- nonExhaustivelyEnumerableSurfaces: [],
570
+ reverseAudit,
571
+ nonExhaustivelyEnumerableSurfaces: reverseAudit.status === "passed" ? [] : [reverseAudit.auditBoundary?.scope || "public surface reverse audit unavailable"],
476
572
  explicitlyExemptedSurfaces: [],
477
573
  },
478
574
  residualRisk: [],
@@ -487,6 +583,7 @@ export function createBuildchainKfd3PrebuildWitness({ root = process.cwd(), sour
487
583
  export function createBuildchainKfd3ArtifactWitness({ root = process.cwd(), sourceSha = "" } = {}) {
488
584
  const registry = createBuildchainKfdClaimRegistry({ root, sourceSha });
489
585
  const surfaces = createBuildchainKfdSurfaceRegistry({ root });
586
+ const reverseAudit = publicSurfaceAuditEvidence(root);
490
587
  return {
491
588
  schemaVersion: 1,
492
589
  id: "buildchain-collaboration-interface",
@@ -507,7 +604,15 @@ export function createBuildchainKfd3ArtifactWitness({ root = process.cwd(), sour
507
604
  standardsMetadata: surfaces.groups.standardsMetadata,
508
605
  packageExports: surfaces.groups.packageExports,
509
606
  siteConsumptionContracts: surfaces.groups.siteConsumptionContracts,
607
+ reverseEnumeratedSurfaces: surfaces.groups.reverseEnumeratedSurfaces,
510
608
  surfaces: surfaces.additionalSurfaces,
609
+ reverseAudit,
610
+ auditBoundary: {
611
+ mode: reverseAudit.status === "passed" ? "closed-world" : "partial",
612
+ reachableSurfaceMode: reverseAudit.status === "passed" ? "reverse-enumerated-boundary" : "declared-boundary",
613
+ reverseAudit,
614
+ nonExhaustivelyEnumerableSurfaces: reverseAudit.status === "passed" ? [] : [reverseAudit.auditBoundary?.scope || "public surface reverse audit unavailable"],
615
+ },
511
616
  verifier: {
512
617
  name: "Buildchain self KFD witness generator",
513
618
  source: "scripts/generate-buildchain-kfd-witnesses.mjs",
@@ -519,11 +624,17 @@ export function createBuildchainKfd2Claims({ root = process.cwd(), witnessFiles
519
624
  const evidenceFiles = Object.entries(witnessFiles)
520
625
  .filter(([, relPath]) => relPath)
521
626
  .map(([id, relPath]) => fileEvidence(root, relPath, { id }));
627
+ const reverseAuditEvidence = publicSurfaceAuditEvidence(root);
522
628
  return createBuildchainPublicClaimDefinitions().map((definition) => {
523
629
  const sourceBindings = uniqueById(definition.sourcePaths.map((relPath) => fileEvidence(root, relPath)));
524
630
  const artifacts = uniqueById(definition.artifactPaths.map((relPath) => fileEvidence(root, relPath)));
525
631
  const machineEvidence = [
526
632
  ...evidenceFiles,
633
+ fileEvidence(root, "dist/site/public-surface-audit.json", {
634
+ id: "public-surface-reverse-audit",
635
+ contract: reverseAuditEvidence.contract,
636
+ status: reverseAuditEvidence.status,
637
+ }),
527
638
  { id: "buildchain-kfd-claim-definition", digest: `sha256:${sha256Json(definition)}` },
528
639
  ];
529
640
  return {
@@ -137,6 +137,11 @@ export {
137
137
  sha256Json as sha256BuildchainContractJson,
138
138
  } from "./buildchain-contract.js";
139
139
 
140
+ export {
141
+ planReleaseLineBootstrap,
142
+ writeReleaseLineBootstrapVersionState,
143
+ } from "./release-line-bootstrap.js";
144
+
140
145
  export {
141
146
  BUILDCHAIN_JSON_FORMATTING_POLICY,
142
147
  KFD1_RELEASE_GATE_CONTRACT,
@@ -169,6 +174,17 @@ export {
169
174
  createBuildchainPublicClaimDefinitions,
170
175
  } from "./buildchain-kfd-claims.js";
171
176
 
177
+ export {
178
+ BUILDCHAIN_PUBLIC_SURFACE_AUDIT_CONTRACT,
179
+ assertPublicSurfaceReverseAudit,
180
+ collectPublicSurfaceReverseAudit,
181
+ enumerateActionInputs,
182
+ enumerateCliCommandsFromBin,
183
+ enumerateDocCommandRefs,
184
+ enumerateSitePages,
185
+ enumerateWorkflowInputs,
186
+ } from "./public-surface-audit.js";
187
+
172
188
  export {
173
189
  AGENT_INDEX_CONTRACT,
174
190
  ARTIFACT_EVIDENCE_CONTRACT,