@kungfu-tech/buildchain 3.0.6 → 3.0.7-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/README.md +4 -2
  2. package/actions/promote-buildchain-ref/README.md +10 -0
  3. package/actions/release-tail/README.md +17 -0
  4. package/bin/buildchain.mjs +11 -0
  5. package/bin/internal/command-registry.mjs +2 -0
  6. package/contracts/auditable-demo-scenario-v1.schema.json +1 -1
  7. package/contracts/engineering-housekeeper-v1.schema.json +143 -0
  8. package/contracts/fixtures/engineering-housekeeper-v1/cases.json +68 -0
  9. package/contracts/fixtures/release-tail-capabilities-v1/kungfu-alpha.json +273 -0
  10. package/contracts/publication-rehearsal-capsule-v1.schema.json +173 -0
  11. package/contracts/release-tail-capabilities-v1.schema.json +199 -0
  12. package/contracts/release-tail-provider-bindings-v1.schema.json +56 -0
  13. package/dist/site/agent-index.json +3 -0
  14. package/dist/site/artifact-schemas.json +6 -0
  15. package/dist/site/buildchain-contract.json +42 -27
  16. package/dist/site/buildchain-site.json +384 -33
  17. package/dist/site/capability-registry.json +15 -12
  18. package/dist/site/cli-registry.json +102 -0
  19. package/dist/site/controller-registry.json +19 -3
  20. package/dist/site/kfd-claims.json +359 -17
  21. package/dist/site/kfd-upstream-aggregate.json +1 -1
  22. package/dist/site/manual-registry.json +53 -7
  23. package/dist/site/node-api-registry.json +5882 -3605
  24. package/dist/site/page-registry.json +348 -21
  25. package/dist/site/public-surface-audit.json +396 -16
  26. package/dist/site/publication-authority-registry.json +106 -1
  27. package/dist/site/publication-registry.json +4 -4
  28. package/dist/site/release-provenance.json +7 -0
  29. package/dist/site/schemas/publication-rehearsal-capsule-v1.schema.json +269 -0
  30. package/dist/site/schemas/release-tail-capabilities-v1.schema.json +353 -0
  31. package/dist/site/schemas/release-tail-provider-bindings-v1.schema.json +94 -0
  32. package/dist/site/site-manifest.json +35 -11
  33. package/dist/site/workflow-registry.json +204 -10
  34. package/docs/MAP.md +6 -2
  35. package/docs/auditable-demo.md +2 -2
  36. package/docs/cli-reference.md +136 -0
  37. package/docs/dev-delivery-warrant.md +49 -4
  38. package/docs/engineering-housekeeper.md +138 -0
  39. package/docs/lifecycle-protocol.md +4 -2
  40. package/docs/node-api-reference.md +495 -281
  41. package/docs/publication-rehearsal.md +94 -0
  42. package/docs/release-governance.md +17 -2
  43. package/docs/release-tail-contract.md +160 -0
  44. package/docs/release-tail-provider-plane.md +120 -0
  45. package/docs/reusable-build-surface.md +11 -0
  46. package/package.json +11 -3
  47. package/packages/core/artifact-signing.js +61 -0
  48. package/packages/core/buildchain-agent-manuals.js +3 -0
  49. package/packages/core/buildchain-config.js +66 -6
  50. package/packages/core/buildchain-kfd-claims.js +1 -1
  51. package/packages/core/buildchain-publication-authority.js +5 -0
  52. package/packages/core/controller-evidence.js +2 -1
  53. package/packages/core/dev-delivery-warrant-cancellation.js +1 -0
  54. package/packages/core/dev-delivery-warrant-shadow.js +502 -0
  55. package/packages/core/dev-delivery-warrant.js +15 -6
  56. package/packages/core/diagnostics.js +8 -3
  57. package/packages/core/engineering-housekeeper-github-client.js +222 -0
  58. package/packages/core/engineering-housekeeper-github.js +501 -0
  59. package/packages/core/engineering-housekeeper.js +259 -0
  60. package/packages/core/index.js +42 -0
  61. package/packages/core/kfd-gate.js +45 -15
  62. package/packages/core/paper-agent-entry.js +11 -5
  63. package/packages/core/paper-repository.js +1 -0
  64. package/packages/core/paper-scaffold-content.js +21 -0
  65. package/packages/core/paper.js +28 -2
  66. package/packages/core/publication-rehearsal-projection.js +173 -0
  67. package/packages/core/publication-rehearsal-runtime.js +921 -0
  68. package/packages/core/release-passport.js +130 -20
  69. package/packages/core/release-tail-compatibility.js +60 -0
  70. package/packages/core/release-tail-provider-adapters.js +461 -0
  71. package/packages/core/release-tail-provider-plane.js +1228 -0
  72. package/scripts/assemble-publication-artifact-admission.mjs +1 -1
  73. package/scripts/assemble-self-publication-admission.mjs +2 -2
  74. package/scripts/audit-publication-control-plane.mjs +1 -1
  75. package/scripts/auditable-demo-bundle-verification.mjs +2 -3
  76. package/scripts/auditable-demo-platform.mjs +2 -2
  77. package/scripts/auditable-demo-renditions.mjs +1 -1
  78. package/scripts/auditable-demo.mjs +2 -2
  79. package/scripts/build-contract-core.mjs +8 -3
  80. package/scripts/build-standalone-binary.mjs +14 -3
  81. package/scripts/buildchain-cli-help.mjs +13 -0
  82. package/scripts/check-core-mechanism-inventory.mjs +347 -0
  83. package/scripts/check-inventory.mjs +10 -8
  84. package/scripts/check-maintainability.mjs +9 -2
  85. package/scripts/check-release-tail-contract.mjs +435 -0
  86. package/scripts/dev-delivery-warrant.mjs +31 -4
  87. package/scripts/dev-pr-auto-merge.mjs +30 -4
  88. package/scripts/dev-pr-delivery-warrant.mjs +50 -0
  89. package/scripts/engineering-housekeeper-workflow.mjs +394 -0
  90. package/scripts/generate-channel-promotion-workflow.mjs +10 -8
  91. package/scripts/generate-site-bundle.mjs +47 -4
  92. package/scripts/init-repo.mjs +26 -2
  93. package/scripts/inspect-artifact-signing-requests.mjs +6 -0
  94. package/scripts/materialize-self-release-candidate-version.mjs +137 -0
  95. package/scripts/publication-commit-evidence.mjs +69 -23
  96. package/scripts/release-candidate-resolver.mjs +16 -10
  97. package/scripts/release-tail.mjs +159 -0
  98. package/scripts/resume-from-candidate-run.mjs +123 -9
  99. package/scripts/seal-artifact-signing-requests.mjs +6 -0
  100. package/scripts/site-capability-metadata.mjs +13 -0
  101. package/scripts/v4-architecture.mjs +600 -0
  102. package/scripts/web-surface-core.mjs +8 -2
  103. package/scripts/workflow-call-contract.mjs +184 -5
@@ -95,12 +95,18 @@ function findFiles(root, predicate) {
95
95
  return collectFiles(root).filter((file) => predicate(file.path, file.absolutePath));
96
96
  }
97
97
 
98
+ export function recoveredArtifactPathsByBasename(downloads, filename) {
99
+ return downloads.flatMap((download) => download.files
100
+ .filter((file) => path.basename(file.path) === filename)
101
+ .map((file) => outputPath(file.absolutePath)));
102
+ }
103
+
98
104
  function readOnlyJson(files, label) {
99
105
  if (files.length !== 1) throw new Error(`expected exactly one ${label}, found ${files.length}`);
100
106
  return JSON.parse(fs.readFileSync(files[0].absolutePath, "utf8"));
101
107
  }
102
108
 
103
- async function readExistingTransaction({ repoInfo, apiUrl, token, fetchImpl, version }) {
109
+ export async function readExistingTransaction({ repoInfo, apiUrl, token, fetchImpl, version }) {
104
110
  const stateRef = releaseTransactionStateRef(version);
105
111
  const response = await githubJson({
106
112
  apiUrl,
@@ -110,10 +116,31 @@ async function readExistingTransaction({ repoInfo, apiUrl, token, fetchImpl, ver
110
116
  path: `/repos/${repoInfo.owner}/${repoInfo.repo}/contents/state.json?ref=${encodeURIComponent(stateRef)}`,
111
117
  });
112
118
  if (!response) return undefined;
113
- if (response.type !== "file" || response.encoding !== "base64" || !response.content) {
114
- throw new Error(`durable transaction ${stateRef} did not expose a base64 state.json file`);
119
+ if (response.type !== "file") {
120
+ throw new Error(`durable transaction ${stateRef} did not expose a state.json file`);
121
+ }
122
+ let encoded = response.encoding === "base64" && response.content
123
+ ? response
124
+ : undefined;
125
+ if (!encoded) {
126
+ const blobSha = String(response.sha || "").trim();
127
+ if (!/^[0-9a-f]{40}$/i.test(blobSha)) {
128
+ throw new Error(`durable transaction ${stateRef} did not expose inline content or an exact blob identity`);
129
+ }
130
+ encoded = await githubJson({
131
+ apiUrl,
132
+ token,
133
+ fetchImpl,
134
+ path: `/repos/${repoInfo.owner}/${repoInfo.repo}/git/blobs/${blobSha}`,
135
+ });
136
+ if (String(encoded?.sha || "").trim() !== blobSha) {
137
+ throw new Error(`durable transaction ${stateRef} blob identity drifted from ${blobSha}`);
138
+ }
139
+ }
140
+ if (encoded?.encoding !== "base64" || !encoded.content) {
141
+ throw new Error(`durable transaction ${stateRef} did not expose base64 state.json content`);
115
142
  }
116
- return JSON.parse(Buffer.from(String(response.content).replace(/\s/g, ""), "base64").toString("utf8"));
143
+ return JSON.parse(Buffer.from(String(encoded.content).replace(/\s/g, ""), "base64").toString("utf8"));
117
144
  }
118
145
 
119
146
  function outputPath(filePath) {
@@ -180,6 +207,7 @@ function candidateArtifactNames({ passport, selected, artifacts, artifactPattern
180
207
 
181
208
  export function normalizePlatformManifests(downloads, passport) {
182
209
  const manifests = [];
210
+ const paths = [];
183
211
  const evidenceByArtifact = new Map();
184
212
  const platformById = new Map((passport.platformMatrix || []).map((entry) => [String(entry.platformId || ""), entry]));
185
213
  const seenPlatformIds = new Set();
@@ -208,6 +236,7 @@ export function normalizePlatformManifests(downloads, passport) {
208
236
  manifest.artifactName = expectedPlatform.artifactName;
209
237
  seenPlatformIds.add(platformId);
210
238
  manifests.push(manifest);
239
+ paths.push(file.absolutePath);
211
240
  addEvidence(manifest.artifactName, download.record.files);
212
241
  }
213
242
  if (String(download.artifact.name).includes("-diagnostics-")) {
@@ -222,7 +251,7 @@ export function normalizePlatformManifests(downloads, passport) {
222
251
  artifactName,
223
252
  files: [...files.values()].sort((left, right) => left.path.localeCompare(right.path)),
224
253
  }));
225
- return { manifests, evidence };
254
+ return { manifests, paths, evidence };
226
255
  }
227
256
 
228
257
  function normalizeControllerReceipts(downloads, passport) {
@@ -268,16 +297,53 @@ export function createRecoveredPublicationCandidate({
268
297
  return { ...payload, candidateDigest: publicationArtifactCandidateDigest(payload) };
269
298
  }
270
299
 
300
+ export function deduplicateReleaseAssets(files = []) {
301
+ const assets = new Map();
302
+ for (const file of files) {
303
+ const name = path.basename(file.path);
304
+ const existing = assets.get(name);
305
+ if (!existing) {
306
+ assets.set(name, file);
307
+ continue;
308
+ }
309
+ const digest = String(file.sha256 || "").replace(/^sha256:/, "");
310
+ const existingDigest = String(existing.sha256 || "").replace(/^sha256:/, "");
311
+ if (digest !== existingDigest || Number(file.size) !== Number(existing.size)) {
312
+ throw new Error(
313
+ `recovered GitHub Release asset basename collision: ${name} maps to different sealed bytes`,
314
+ );
315
+ }
316
+ if (
317
+ String(file.path).length < String(existing.path).length ||
318
+ (String(file.path).length === String(existing.path).length &&
319
+ String(file.path).localeCompare(String(existing.path)) < 0)
320
+ ) {
321
+ assets.set(name, file);
322
+ }
323
+ }
324
+ return [...assets.values()].sort((left, right) =>
325
+ path.basename(left.path).localeCompare(path.basename(right.path)),
326
+ );
327
+ }
328
+
271
329
  export function createRecoveredPublication({ downloads, bundleRoot, repository, passport, candidateRuntimeSha, publishArtifactKind, publishPackageMain, releasePatterns, platformManifests }) {
272
330
  const allFiles = downloads.flatMap((download) => download.files.map((file) => ({
273
331
  path: path.relative(bundleRoot, file.absolutePath).split(path.sep).join("/"),
274
332
  size: file.size,
275
333
  sha256: file.sha256.replace(/^sha256:/, ""),
276
334
  absolutePath: file.absolutePath,
335
+ artifactName: String(download.artifact?.name || ""),
277
336
  }))).sort((left, right) => left.path.localeCompare(right.path));
278
337
  const kind = String(publishArtifactKind || "npm");
279
338
  const releaseMatchers = splitPatterns(releasePatterns).map(patternMatcher);
280
- const releaseAssets = allFiles.filter((file) => releaseMatchers.some((matcher) => matcher.test(path.basename(file.path))));
339
+ const platformArtifactNames = new Set(
340
+ platformManifests.map((manifest) => String(manifest.artifactName || "")).filter(Boolean),
341
+ );
342
+ const releaseAssetFiles = kind !== "npm" && platformArtifactNames.size > 0
343
+ ? allFiles.filter((file) => platformArtifactNames.has(file.artifactName))
344
+ : allFiles;
345
+ const releaseAssets = deduplicateReleaseAssets(releaseAssetFiles.filter((file) =>
346
+ releaseMatchers.some((matcher) => matcher.test(path.basename(file.path)))));
281
347
  if (kind !== "npm") {
282
348
  createRecoveredPublicationCandidate({ allFiles, repository, passport, candidateRuntimeSha });
283
349
  const version = String(passport.target?.version || "").trim();
@@ -367,6 +433,42 @@ async function recoverCandidateEvidence({
367
433
  };
368
434
  }
369
435
 
436
+ export function exposeRecoveredPayloadRoot({ resolvedOutput, bundleRoot }) {
437
+ const recoveredPayloadRoot = path.join(bundleRoot, "artifacts");
438
+ if (!fs.existsSync(recoveredPayloadRoot) || !fs.statSync(recoveredPayloadRoot).isDirectory()) {
439
+ throw new Error(`recovered candidate payload root is missing: ${recoveredPayloadRoot}`);
440
+ }
441
+ const compatibilityRoot = path.join(resolvedOutput, "payloads");
442
+ try {
443
+ fs.lstatSync(compatibilityRoot);
444
+ if (fs.realpathSync(compatibilityRoot) !== fs.realpathSync(recoveredPayloadRoot)) {
445
+ throw new Error(`recovered candidate payload compatibility path is already occupied: ${compatibilityRoot}`);
446
+ }
447
+ } catch (error) {
448
+ if (error?.code !== "ENOENT") throw error;
449
+ fs.symlinkSync(path.relative(resolvedOutput, recoveredPayloadRoot), compatibilityRoot, "dir");
450
+ }
451
+ return compatibilityRoot;
452
+ }
453
+
454
+ export function exposeRecoveredPassportPath({ resolvedOutput, recoveredPassportPath }) {
455
+ if (!fs.existsSync(recoveredPassportPath) || !fs.statSync(recoveredPassportPath).isFile()) {
456
+ throw new Error(`recovered candidate passport is missing: ${recoveredPassportPath}`);
457
+ }
458
+ const recoveredPassportRoot = path.dirname(recoveredPassportPath);
459
+ const compatibilityRoot = path.join(resolvedOutput, "passport");
460
+ try {
461
+ fs.lstatSync(compatibilityRoot);
462
+ if (fs.realpathSync(compatibilityRoot) !== fs.realpathSync(recoveredPassportRoot)) {
463
+ throw new Error(`recovered candidate passport compatibility path is already occupied: ${compatibilityRoot}`);
464
+ }
465
+ } catch (error) {
466
+ if (error?.code !== "ENOENT") throw error;
467
+ fs.symlinkSync(path.relative(resolvedOutput, recoveredPassportRoot), compatibilityRoot, "dir");
468
+ }
469
+ return path.join(compatibilityRoot, path.basename(recoveredPassportPath));
470
+ }
471
+
370
472
  async function resolveTargetAdvance({ observedTargetSha, targetSha, transactionId, existingTransaction, repoInfo, apiUrl, token, fetchImpl }) {
371
473
  if (observedTargetSha === targetSha || !transactionId || existingTransaction?.id !== transactionId) return undefined;
372
474
  const comparison = await githubJson({ apiUrl, token, fetchImpl, path: `/repos/${repoInfo.owner}/${repoInfo.repo}/compare/${targetSha}...${observedTargetSha}` });
@@ -494,7 +596,16 @@ export async function resumeFromCandidateRun({
494
596
  if (publication.manifest) fs.writeFileSync(sealedManifestPath, `${JSON.stringify(publication.manifest, null, 2)}\n`);
495
597
  const publishRequiredArtifacts = publication.publishRequiredArtifacts;
496
598
  fs.writeFileSync(requiredArtifactsPath, `${JSON.stringify(publishRequiredArtifacts, null, 2)}\n`);
599
+ const payloadRoot = exposeRecoveredPayloadRoot({ resolvedOutput, bundleRoot });
600
+ const recoveredPassportPath = initialDownloads[0].files.find(
601
+ (file) => path.basename(file.path) === "release-candidate-passport.json",
602
+ ).absolutePath;
603
+ const passportPath = exposeRecoveredPassportPath({ resolvedOutput, recoveredPassportPath });
497
604
  const tarballs = publication.npmArtifacts.map((entry) => outputPath(entry.file.absolutePath));
605
+ const githubArtifactAttestationPolicies = recoveredArtifactPathsByBasename(
606
+ downloads,
607
+ "github-artifact-attestation-policy.json",
608
+ );
498
609
  return {
499
610
  enabled: true,
500
611
  action: "reused",
@@ -507,10 +618,11 @@ export async function resumeFromCandidateRun({
507
618
  receipt: recovery.receipt,
508
619
  publishRequiredArtifacts,
509
620
  paths: {
510
- passport: outputPath(initialDownloads[0].files.find((file) => path.basename(file.path) === "release-candidate-passport.json").absolutePath),
621
+ passport: outputPath(passportPath),
511
622
  buildSummary: outputPath(initialDownloads[1].files.find((file) => path.basename(file.path) === "build-summary.json").absolutePath),
512
- payloads: outputPath(path.join(bundleRoot, "artifacts")),
513
- platformManifests: downloads.flatMap((download) => download.files.filter((file) => path.basename(file.path) === "manifest.json").map((file) => outputPath(file.absolutePath))),
623
+ payloads: outputPath(payloadRoot),
624
+ platformManifests: platformManifestEvidence.paths.map(outputPath),
625
+ githubArtifactAttestationPolicies,
514
626
  npmTarballs: tarballs,
515
627
  releaseAssets: publication.releaseAssets.map((asset) => outputPath(asset.absolutePath)),
516
628
  publishRequiredArtifacts: outputPath(requiredArtifactsPath),
@@ -560,6 +672,8 @@ export async function resumeFromCandidateRunCli() {
560
672
  "release-candidate-payload-artifacts": result.artifacts.payloads.join(","),
561
673
  "release-candidate-payload-dir": result.paths.payloads,
562
674
  "release-candidate-platform-manifest-paths": result.paths.platformManifests.join(","),
675
+ "release-candidate-github-artifact-attestation-policy-paths": result.paths.githubArtifactAttestationPolicies.join(","),
676
+ "release-candidate-github-artifact-attestation-policy-count": String(result.paths.githubArtifactAttestationPolicies.length),
563
677
  "release-candidate-npm-tarball-paths": result.paths.npmTarballs.join(","),
564
678
  "release-candidate-github-release-artifact-paths": result.paths.releaseAssets.join("\n"),
565
679
  "publish-required-artifacts-json": JSON.stringify(result.publishRequiredArtifacts),
@@ -376,6 +376,12 @@ export function sealArtifactSigningRequests({
376
376
  signature: {
377
377
  profile: declaration.profile,
378
378
  required: declaration.required,
379
+ ...(declaration.entitlementsProfile !== "none"
380
+ ? {
381
+ entitlementsProfile: declaration.entitlementsProfile,
382
+ entitlementsPaths: declaration.entitlementsPaths,
383
+ }
384
+ : {}),
379
385
  },
380
386
  });
381
387
  const check = validateArtifactSigningRequest(request);
@@ -12,6 +12,11 @@ function capabilityGroup(id) {
12
12
  export function cliCommandMeta(id) {
13
13
  const map = new Map(Object.entries({
14
14
  audit: { group: "release-passport-trust", purpose: "Inspect read-only publication authority audit commands." },
15
+ architecture: { group: "governance-versioning", purpose: "Inspect and qualify the Buildchain v4 capability and state-machine architecture contract." },
16
+ "architecture-list": { group: "governance-versioning", purpose: "Generate the Agent-readable capability list from the validated v4 architecture manifest." },
17
+ "architecture-qualify": { group: "governance-versioning", purpose: "Qualify an exact candidate against a distinct N-1 Git authority revision without candidate self-qualification." },
18
+ "architecture-show": { group: "governance-versioning", purpose: "Generate one capability and its state-machine details from the validated v4 architecture manifest." },
19
+ "architecture-validate": { group: "governance-versioning", purpose: "Validate v4 dependency direction, ownership, writers, budgets, recovery declarations, and exception policy." },
15
20
  "audit-publication-control-plane": { group: "release-passport-trust", purpose: "Read GitHub publication controls, bind provider-enforced npm identity, and emit a sanitized expiring receipt." },
16
21
  "audit-github-governance": { group: "governance-versioning", purpose: "Read the managed GitHub zone, aggregate native protection and ownership, and emit sanitized fail-closed governance receipts." },
17
22
  badges: { group: "distribution-indexes", purpose: "Inspect README badge command families." },
@@ -134,6 +139,7 @@ export function cliCommandMeta(id) {
134
139
  "release-line-open": { group: "governance-versioning", purpose: "Plan or write the initial version-state commit for a new minor release line." },
135
140
  "release-governance": { group: "governance-versioning", purpose: "Reconcile a managed branch's Buildchain aggregate check to an already-tested pull request SHA." },
136
141
  "release-propagation": { group: "site-and-propagation", purpose: "Route exact Paper, KFD, Buildchain, or Core Site updates through one resumable propagation Work." },
142
+ "release-tail": { group: "release-passport-trust", purpose: "Plan, initialize, rehearse, resume, and verify one declarative provider-owned release-tail transaction." },
137
143
  "release-transaction": { group: "release-passport-trust", purpose: "Inspect, recover, finalize, or abort durable release transactions." },
138
144
  sample: { group: "observability-diagnostics", purpose: "Inspect sampler command families." },
139
145
  "sample-process-tree": { group: "observability-diagnostics", purpose: "Sample process-tree diagnostics for a wrapped command." },
@@ -182,6 +188,8 @@ export function nodeApiMeta(exportName) {
182
188
  "./publication-control-plane-audit": { group: "release-passport-trust", summary: "Read-only publication control-plane snapshot evaluation APIs." },
183
189
  "./buildchain-publication-authority": { group: "release-passport-trust", summary: "Buildchain-owned closed-world publication authority descriptor registry." },
184
190
  "./github-governance-authority": { group: "governance-versioning", summary: "Fail-closed GitHub ownership, effective-policy, managed-zone admission, rollout-plan, and immutable receipt APIs." },
191
+ "./engineering-housekeeper": { group: "governance-versioning", summary: "Provider-neutral repository hygiene classification, deterministic plan and receipt, apply-time revalidation, and replay APIs." },
192
+ "./engineering-housekeeper-github": { group: "governance-versioning", summary: "Paginated GitHub repository hygiene inventory, default-dry-run execution, exact-head mutation fences, and rooted provider receipts." },
185
193
  "./artifact-passport": { group: "release-passport-trust", summary: "Artifact passport digest and evidence helper APIs." },
186
194
  "./artifact-verification-envelope": { group: "release-passport-trust", summary: "Sealed exact-root, lifecycle, identity, and existing KFD assessment inputs for KFX admission." },
187
195
  "./artifact-signing": { group: "reusable-build", summary: "Credential-free artifact signing declarations, source-bound requests, authority receipts, profile resolution, and fail-closed validation APIs." },
@@ -197,6 +205,11 @@ export function nodeApiMeta(exportName) {
197
205
  "./stable-candidate-ledger": { group: "governance-versioning", summary: "Immutable alpha candidate ledger, qualification, revocation, selection, and exact stable source-lock APIs." },
198
206
  "./release-propagation": { group: "site-and-propagation", summary: "Release propagation graph, plan, and exact upstream lock APIs." },
199
207
  "./release-activation-transaction": { group: "release-passport-trust", summary: "Ordered cross-repository activation, exact receipt-set binding, retry, abort, rollback, and shadow-rehearsal APIs." },
208
+ "./release-tail-provider-plane": { group: "release-passport-trust", summary: "Versioned declarative release-tail parsing, deterministic effect planning, durable transaction execution, readback, retry, and rooted receipt APIs." },
209
+ "./release-tail-provider-adapters": { group: "release-passport-trust", summary: "Buildchain-owned GitHub Release, signed-channel, activation, and released-evidence provider adapters." },
210
+ "./release-tail-compatibility": { group: "release-passport-trust", summary: "Bounded v3 release-hook compatibility diagnostics that reject new executable release-tail inputs." },
211
+ "./publication-rehearsal-runtime": { group: "release-passport-trust", summary: "Content-addressed local, replay, and provider-recording publication rehearsal over the shared release-tail core." },
212
+ "./publication-rehearsal-projection": { group: "release-passport-trust", summary: "Canonical generated config, workflow, and Agent projections for release local constructibility." },
200
213
  "./release-line-bootstrap": { group: "governance-versioning", summary: "Semver release-line bootstrap planning and version-state APIs." },
201
214
  "./buildchain-contract": { group: "governance-versioning", summary: "Runtime contract world and compatibility digest APIs for floating-ref drift checks." },
202
215
  "./controller-evidence": { group: "reusable-build", summary: "Project-independent controller descriptors, source/runtime-bound plans, receipts, aggregates, and validation APIs." },