@kungfu-tech/buildchain 4.0.2-alpha.5 → 4.0.2-alpha.50

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 (171) hide show
  1. package/AGENTS.md +10 -1
  2. package/CONTRIBUTING.md +24 -0
  3. package/README.md +2 -2
  4. package/actions/promote-buildchain-ref/README.md +1 -1
  5. package/actions/v4-release-candidate-promote/README.md +28 -0
  6. package/architecture/agent-change-map.md +70 -9
  7. package/architecture/ci-lane-change-budget.json +384 -0
  8. package/architecture/internal-capabilities.json +56 -9
  9. package/architecture/maintainability-debt.json +162 -107
  10. package/architecture/maintainability-policy.json +34 -30
  11. package/architecture/release-tail-contract-inventory.json +6 -6
  12. package/architecture/v4-architecture-constitution.md +23 -20
  13. package/architecture/v4-cross-platform-adopter-qualification.json +1 -1
  14. package/architecture/v4-delivery-authority-parity.json +2 -2
  15. package/architecture/v4-delivery-warrant-shadow-bootstrap-plan.json +1 -1
  16. package/architecture/v4-floating-consumer-policy.json +2 -2
  17. package/architecture/v4-next-development-parity.json +5 -5
  18. package/architecture/v4-partial-mutation-recovery-qualification.json +4 -1
  19. package/architecture/v4-platform-stage-checkpoints.json +1 -1
  20. package/architecture/v4-provider-operation-journal-contract.json +5 -2
  21. package/architecture/v4-publication-facade-patches.json +64 -0
  22. package/architecture/v4-release-activation-shadow-domain.json +5 -2
  23. package/architecture/v4-release-topology.json +198 -38
  24. package/architecture/v4-rust-wasm-production-authority.json +58 -0
  25. package/architecture/v4-stable-publication-fence.json +5 -2
  26. package/architecture/v4-stage-capsule-qualification.json +2 -2
  27. package/architecture/v4-tail-reseal-parity.json +8 -6
  28. package/architecture/v4-universal-workflow-bootstrap.json +176 -0
  29. package/architecture/v4-universal-workflow-fault-campaign.json +72 -0
  30. package/architecture/v4-universal-workflow-train-admission.json +40 -0
  31. package/architecture/workflow-taxonomy.json +1462 -0
  32. package/bin/buildchain.mjs +7 -7
  33. package/contracts/buildchain-v2-residuals-v1.json +57 -48
  34. package/contracts/dev-delivery-authority-v2.schema.json +16 -2
  35. package/contracts/fixtures/v4-tail-reseal-v1/valid.json +1 -1
  36. package/contracts/v4-canonical-contracts-v1.schema.json +1 -0
  37. package/dist/site/buildchain-contract.json +93 -48
  38. package/dist/site/buildchain-site.json +276 -72
  39. package/dist/site/capability-registry.json +5 -5
  40. package/dist/site/controller-registry.json +50 -13
  41. package/dist/site/kfd-claims.json +2610 -983
  42. package/dist/site/kfd-upstream-aggregate.json +1 -1
  43. package/dist/site/manual-registry.json +14 -14
  44. package/dist/site/node-api-registry.json +273 -127
  45. package/dist/site/page-registry.json +257 -53
  46. package/dist/site/public-surface-audit.json +3239 -1232
  47. package/dist/site/publication-authority-registry.json +1135 -363
  48. package/dist/site/publication-registry.json +4 -4
  49. package/dist/site/release-provenance.json +2 -1
  50. package/dist/site/schemas/dev-delivery-authority-v2.schema.json +16 -2
  51. package/dist/site/site-manifest.json +18 -18
  52. package/dist/site/workflow-registry.json +5097 -1659
  53. package/docs/MAP.md +2 -0
  54. package/docs/auditable-demo.md +1 -1
  55. package/docs/cli.md +21 -8
  56. package/docs/dev-delivery-warrant.md +1 -1
  57. package/docs/engineering-housekeeper.md +3 -3
  58. package/docs/kfd-support.md +26 -2
  59. package/docs/next-development-transition.md +2 -2
  60. package/docs/node-api-reference.md +216 -205
  61. package/docs/oci-publication.md +160 -0
  62. package/docs/publication-authority.md +2 -2
  63. package/docs/publish-transaction.md +36 -3
  64. package/docs/release-candidate.md +3 -3
  65. package/docs/release-flow.md +67 -19
  66. package/docs/release-governance.md +8 -8
  67. package/docs/release-passport.md +27 -2
  68. package/docs/reusable-build-surface.md +16 -0
  69. package/docs/v4-adopter-delivery.md +2 -2
  70. package/docs/v4-production-release.md +71 -8
  71. package/docs/v4-rust-wasm-production-authority.md +58 -0
  72. package/docs/v4-stage-capsule.md +2 -2
  73. package/docs/v4-tail-reseal.md +1 -1
  74. package/docs/workflow-catalog.md +155 -0
  75. package/docs/workflow-path-migration.md +109 -0
  76. package/package.json +12 -7
  77. package/packages/core/artifact-verification-envelope.js +5 -5
  78. package/packages/core/buildchain-contract.js +1 -1
  79. package/packages/core/buildchain-kfd-claims.js +2 -2
  80. package/packages/core/buildchain-publication-authority.js +43 -26
  81. package/packages/core/buildchain-v4-domain.wasm +0 -0
  82. package/packages/core/ci-lane-change-budget.js +14 -1
  83. package/packages/core/controller-evidence.js +4 -1
  84. package/packages/core/dev-delivery-candidate-identity.js +40 -6
  85. package/packages/core/dev-delivery-warrant-state.js +3 -4
  86. package/packages/core/dev-delivery-warrant.js +12 -2
  87. package/packages/core/github-governance-authority.js +4 -4
  88. package/packages/core/kfd-adopter-manifest.js +46 -47
  89. package/packages/core/next-development-projection.js +2 -2
  90. package/packages/core/next-development-transition.js +5 -6
  91. package/packages/core/oci-compose-qualification.js +140 -0
  92. package/packages/core/oci-publication-bundle.js +281 -0
  93. package/packages/core/oci-publication-graph.js +206 -0
  94. package/packages/core/paper-agent-entry.js +30 -4
  95. package/packages/core/paper-fleet.js +1 -1
  96. package/packages/core/paper-runtime-channels.js +348 -0
  97. package/packages/core/paper-scaffold-content.js +10 -0
  98. package/packages/core/paper.js +37 -71
  99. package/packages/core/publication-sealed-bundle.js +78 -13
  100. package/packages/core/release-line-dry-run.js +1 -1
  101. package/packages/core/release-passport-contract.js +5 -5
  102. package/packages/core/release-passport.js +5 -4
  103. package/packages/core/release-tail-product-capabilities.js +38 -0
  104. package/packages/core/release-tail-provider-plane.js +68 -1048
  105. package/packages/core/v4-canonical-contracts.js +15 -75
  106. package/packages/core/v4-domain-wasm-artifact.js +7 -0
  107. package/packages/core/v4-domain-wasm.js +216 -0
  108. package/packages/core/v4-floating-consumer-evidence.js +1 -1
  109. package/packages/core/v4-floating-consumer-policy.js +1 -1
  110. package/packages/core/v4-partial-mutation-recovery-qualification.js +9 -386
  111. package/packages/core/v4-product-publication.js +59 -0
  112. package/packages/core/v4-protected-publication-source.js +19 -21
  113. package/packages/core/v4-provider-operation-journal.js +18 -487
  114. package/packages/core/v4-provider-readback-idempotency.js +12 -97
  115. package/packages/core/v4-release-activation-shadow.js +13 -500
  116. package/packages/core/v4-release-invocation.js +28 -389
  117. package/packages/core/v4-stable-publication-fence.js +13 -342
  118. package/packages/core/v4-universal-workflow-bootstrap.js +586 -0
  119. package/scripts/binary-publication-evidence.mjs +135 -0
  120. package/scripts/build-contract-core.mjs +1 -14
  121. package/scripts/build-v4-domain-wasm.mjs +189 -0
  122. package/scripts/check-action-bundles.mjs +12 -2
  123. package/scripts/check-ci-lane-change-budget.mjs +4 -1
  124. package/scripts/check-core-mechanism-inventory.mjs +4 -3
  125. package/scripts/check-inventory.mjs +35 -44
  126. package/scripts/check-maintainability.mjs +16 -113
  127. package/scripts/check-v4-floating-consumer-policy-contract.mjs +2 -2
  128. package/scripts/check-v4-public-dogfood-contract.mjs +22 -9
  129. package/scripts/check-v4-release-topology.mjs +236 -50
  130. package/scripts/check-v4-runtime-semantic-closure.mjs +4 -1
  131. package/scripts/check-v4-universal-workflow-bootstrap.mjs +266 -0
  132. package/scripts/check-workflow-taxonomy.mjs +6 -0
  133. package/scripts/copy-v4-domain-wasm.mjs +14 -0
  134. package/scripts/dev-delivery-authority-command-adapters.mjs +1 -1
  135. package/scripts/dev-delivery-authority.mjs +8 -8
  136. package/scripts/dev-delivery-source-proof-reuse.mjs +2 -1
  137. package/scripts/dev-delivery-warrant-options.mjs +14 -9
  138. package/scripts/dev-delivery-warrant-store.mjs +73 -7
  139. package/scripts/dev-delivery-warrant-transition.mjs +109 -0
  140. package/scripts/dev-delivery-warrant.mjs +76 -99
  141. package/scripts/dev-pr-auto-merge.mjs +15 -15
  142. package/scripts/generate-channel-build-workflow.mjs +7 -2
  143. package/scripts/generate-channel-promotion-workflow.mjs +10 -25
  144. package/scripts/generate-site-bundle.mjs +11 -11
  145. package/scripts/generate-v4-universal-workflow-facades.mjs +497 -0
  146. package/scripts/generate-workflow-taxonomy.mjs +25 -0
  147. package/scripts/github-output.mjs +31 -0
  148. package/scripts/maintainability-metrics.mjs +16 -5
  149. package/scripts/maintainability-public-surface.mjs +115 -0
  150. package/scripts/next-development-review.mjs +307 -0
  151. package/scripts/oci-compose-preview.mjs +250 -0
  152. package/scripts/paper-work-fleet-cli.mjs +2 -0
  153. package/scripts/publication-candidate-kind.mjs +93 -0
  154. package/scripts/publication-candidate-sealer.mjs +16 -1
  155. package/scripts/release-asset-client.mjs +91 -0
  156. package/scripts/release-candidate-resolver.mjs +23 -35
  157. package/scripts/resume-from-candidate-run.mjs +11 -18
  158. package/scripts/site-capability-metadata.mjs +1 -0
  159. package/scripts/source-verification-evidence.mjs +344 -0
  160. package/scripts/stable-candidate-qualification.mjs +1 -1
  161. package/scripts/universal-facade-maintainability.mjs +91 -0
  162. package/scripts/v4-product-publication-intent.mjs +129 -0
  163. package/scripts/v4-publication-settlement.mjs +211 -0
  164. package/scripts/v4-universal-workflow-backflow.mjs +212 -0
  165. package/scripts/v4-universal-workflow-engine.mjs +620 -0
  166. package/scripts/v4-universal-workflow-self-dogfood.mjs +205 -0
  167. package/scripts/verify-version-state-delta.mjs +173 -0
  168. package/scripts/workflow-taxonomy.mjs +507 -0
  169. package/templates/native-dev-delivery.yml +4 -7
  170. package/templates/universal-buildchain-bootstrap-recovery.yml +282 -0
  171. package/templates/universal-buildchain-bootstrap.yml +28 -0
@@ -1,4 +1,5 @@
1
1
  import crypto from "node:crypto";
2
+ import { execFileSync } from "node:child_process";
2
3
  import fs from "node:fs";
3
4
  import path from "node:path";
4
5
 
@@ -19,7 +20,10 @@ function requiredString(value, label) {
19
20
 
20
21
  function safeRelativePath(value, label) {
21
22
  const normalized = requiredString(value, label).replaceAll("\\", "/");
22
- if (normalized.startsWith("/") || normalized.split("/").some((part) => part === ".." || part === "")) {
23
+ if (
24
+ normalized.startsWith("/") ||
25
+ normalized.split("/").some((part) => part === ".." || part === "")
26
+ ) {
23
27
  throw new Error(`${label} must be a safe relative path`);
24
28
  }
25
29
  return normalized;
@@ -41,7 +45,8 @@ function sha256File(filePath) {
41
45
  const chunk = Buffer.allocUnsafe(8 * 1024 * 1024);
42
46
  try {
43
47
  let bytesRead = 0;
44
- while ((bytesRead = fs.readSync(descriptor, chunk, 0, chunk.length, null)) > 0) hash.update(chunk.subarray(0, bytesRead));
48
+ while ((bytesRead = fs.readSync(descriptor, chunk, 0, chunk.length, null)) > 0)
49
+ hash.update(chunk.subarray(0, bytesRead));
45
50
  } finally {
46
51
  fs.closeSync(descriptor);
47
52
  }
@@ -60,8 +65,16 @@ function normalizeFile(entry, label) {
60
65
  };
61
66
  }
62
67
 
68
+ function fileInventory(files, label) {
69
+ return (files || []).map((entry, index) => normalizeFile(entry, `${label}[${index}]`))
70
+ .sort((left, right) => left.path.localeCompare(right.path));
71
+ }
72
+
63
73
  function candidatePayload(candidate) {
64
- if (candidate?.contract !== PUBLICATION_ARTIFACT_CANDIDATE_CONTRACT || Number(candidate?.schemaVersion) !== 1) {
74
+ if (
75
+ candidate?.contract !== PUBLICATION_ARTIFACT_CANDIDATE_CONTRACT ||
76
+ Number(candidate?.schemaVersion) !== 1
77
+ ) {
65
78
  throw new Error("publication artifact candidate contract mismatch");
66
79
  }
67
80
  const { candidateDigest: _candidateDigest, ...payload } = candidate;
@@ -91,9 +104,7 @@ export function createPublicationSealedBundle({
91
104
  githubReleaseRequired = true,
92
105
  } = {}) {
93
106
  const { digest } = candidatePayload(candidate);
94
- const files = (candidate.files || [])
95
- .map((entry, index) => normalizeFile(entry, `candidate.files[${index}]`))
96
- .sort((left, right) => left.path.localeCompare(right.path));
107
+ const files = fileInventory(candidate.files, "candidate.files");
97
108
  if (new Set(files.map((entry) => entry.path)).size !== files.length) {
98
109
  throw new Error("publication sealed bundle candidate paths must be unique");
99
110
  }
@@ -119,6 +130,7 @@ export function createPublicationSealedBundle({
119
130
  sha256: npmTarball.sha256,
120
131
  integrity: requiredString(npmIntegrity, "npmIntegrity"),
121
132
  },
133
+ ...(candidate.npmPackages ? { npmPackages: candidate.npmPackages } : {}),
122
134
  releaseAssets,
123
135
  completion: {
124
136
  githubReleaseRequired: Boolean(githubReleaseRequired),
@@ -130,8 +142,56 @@ export function createPublicationSealedBundle({
130
142
  };
131
143
  }
132
144
 
145
+ function verifyNpmPackageSet(manifest, files, resolvedRoot) {
146
+ const npmPackages = manifest.npmPackages;
147
+ if (JSON.stringify(npmPackages) !== JSON.stringify(manifest.candidate.npmPackages)) {
148
+ throw new Error("publication sealed bundle npm package inventory differs from candidate");
149
+ }
150
+ if (npmPackages) {
151
+ if (
152
+ !Array.isArray(npmPackages) ||
153
+ npmPackages.length < 2 ||
154
+ new Set(npmPackages.map((entry) => entry.name)).size !== npmPackages.length ||
155
+ new Set(npmPackages.map((entry) => entry.path)).size !== npmPackages.length
156
+ ) {
157
+ throw new Error("publication sealed bundle npm package inventory must be unique");
158
+ }
159
+ for (const entry of npmPackages) {
160
+ const file = selectFile(files, entry.path, "npmPackages.path");
161
+ const absolutePath = path.resolve(resolvedRoot, file.path);
162
+ const metadata = JSON.parse(
163
+ execFileSync("tar", ["-xOf", path.basename(absolutePath), "package/package.json"], {
164
+ cwd: path.dirname(absolutePath),
165
+ encoding: "utf8",
166
+ }),
167
+ );
168
+ const integrity = `sha512-${crypto.createHash("sha512").update(fs.readFileSync(absolutePath)).digest("base64")}`;
169
+ if (
170
+ entry.name !== metadata.name ||
171
+ entry.version !== metadata.version ||
172
+ entry.size !== file.size ||
173
+ entry.sha256 !== file.sha256 ||
174
+ entry.integrity !== integrity
175
+ ) {
176
+ throw new Error("publication sealed bundle npm package identity or integrity mismatch");
177
+ }
178
+ }
179
+ const main = npmPackages.filter((entry) => entry.role === "main");
180
+ if (
181
+ main.length !== 1 ||
182
+ Object.keys(manifest.npm).some((key) => main[0][key] !== manifest.npm[key])
183
+ ) {
184
+ throw new Error("publication sealed bundle npm main package mismatch");
185
+ }
186
+ }
187
+ return npmPackages;
188
+ }
189
+
133
190
  export function verifyPublicationSealedBundle({ bundleRoot, manifest } = {}) {
134
- if (manifest?.contract !== PUBLICATION_SEALED_BUNDLE_CONTRACT || Number(manifest?.schemaVersion) !== 1) {
191
+ if (
192
+ manifest?.contract !== PUBLICATION_SEALED_BUNDLE_CONTRACT ||
193
+ Number(manifest?.schemaVersion) !== 1
194
+ ) {
135
195
  throw new Error("publication sealed bundle contract mismatch");
136
196
  }
137
197
  const resolvedRoot = path.resolve(requiredString(bundleRoot, "bundleRoot"));
@@ -139,12 +199,8 @@ export function verifyPublicationSealedBundle({ bundleRoot, manifest } = {}) {
139
199
  if (normalizeSha256(manifest.root, "manifest.root") !== digest) {
140
200
  throw new Error("publication sealed bundle root mismatch");
141
201
  }
142
- const files = (manifest.files || [])
143
- .map((entry, index) => normalizeFile(entry, `manifest.files[${index}]`))
144
- .sort((left, right) => left.path.localeCompare(right.path));
145
- const candidateFiles = (manifest.candidate.files || [])
146
- .map((entry, index) => normalizeFile(entry, `candidate.files[${index}]`))
147
- .sort((left, right) => left.path.localeCompare(right.path));
202
+ const files = fileInventory(manifest.files, "manifest.files");
203
+ const candidateFiles = fileInventory(manifest.candidate.files, "candidate.files");
148
204
  if (JSON.stringify(files) !== JSON.stringify(candidateFiles)) {
149
205
  throw new Error("publication sealed bundle file inventory differs from candidate");
150
206
  }
@@ -169,6 +225,7 @@ export function verifyPublicationSealedBundle({ bundleRoot, manifest } = {}) {
169
225
  ) {
170
226
  throw new Error("publication sealed bundle npm tarball inventory mismatch");
171
227
  }
228
+ const npmPackages = verifyNpmPackageSet(manifest, files, resolvedRoot);
172
229
  const releaseAssets = (manifest.releaseAssets || []).map((entry, index) => {
173
230
  const selected = selectFile(files, entry.path, `manifest.releaseAssets[${index}].path`);
174
231
  const normalized = normalizeFile(entry, `manifest.releaseAssets[${index}]`);
@@ -194,6 +251,14 @@ export function verifyPublicationSealedBundle({ bundleRoot, manifest } = {}) {
194
251
  ...entry,
195
252
  absolutePath: path.resolve(resolvedRoot, entry.path),
196
253
  })),
254
+ ...(npmPackages
255
+ ? {
256
+ npmPackages: npmPackages.map((entry) => ({
257
+ ...entry,
258
+ absolutePath: path.resolve(resolvedRoot, entry.path),
259
+ })),
260
+ }
261
+ : {}),
197
262
  manifest,
198
263
  };
199
264
  }
@@ -201,7 +201,7 @@ function explainReleaseLineDryRun({
201
201
  );
202
202
  plan.branchUpdates.push(
203
203
  { ref: targetRef, action: "would move to alpha version-state commit" },
204
- { ref: `dev/v${rule.major}/v${rule.major}.${rule.minor}`, action: "would align dev with the published alpha state" },
204
+ { ref: `dev/v${rule.major}/v${rule.major}.${rule.minor}`, action: rule.major === 4 ? "would prepare the next alpha version on dev through a separate protected PR after publication" : "would align dev with the published alpha state" },
205
205
  );
206
206
  plan.versionState.targetVersions = [exactAlpha.replace(/^next v?/, "").replace(/^v/, "")];
207
207
  plan.notes.push("Alpha promotion opens or advances the test channel; it does not move production refs.");
@@ -405,7 +405,7 @@ export function prepareReleasePassportKfdSections({ kfd1, kfd2Claims, kfd3, kfdA
405
405
  };
406
406
  }
407
407
 
408
- export function collectKfdAdopterReleaseEvidence({ manifest, gateResults = [], comparisonMatrix, sourceSha = "", checkedAt } = {}) {
408
+ export function collectKfdAdopterReleaseEvidence({ manifest, gateResults = [], comparisonMatrix, expectedAdopterId = "kungfu-systems/buildchain", expectedSourceRepository = "", sourceSha = "", checkedAt } = {}) {
409
409
  if (!manifest) {
410
410
  if (comparisonMatrix || gateResults.length > 0) {
411
411
  throw new Error("KFD support and product-gate inputs require --kfd-adopter-manifest-json; --kfd-support-matrix-json is comparison-only");
@@ -414,7 +414,7 @@ export function collectKfdAdopterReleaseEvidence({ manifest, gateResults = [], c
414
414
  }
415
415
  const manifestGate = createKfdAdopterManifestGate({
416
416
  manifest, packageArtifactRoot: installedKfdPackageArtifactRoot(), gateResults,
417
- expectedSourceSha: sourceSha, checkedAt,
417
+ expectedAdopterId, expectedSourceRepository, expectedSourceSha: sourceSha, checkedAt,
418
418
  });
419
419
  const legacyProjection = createKfdLegacySupportMatrixProjection({ manifest, manifestGate });
420
420
  if (comparisonMatrix) {
@@ -425,18 +425,18 @@ export function collectKfdAdopterReleaseEvidence({ manifest, gateResults = [], c
425
425
  }
426
426
  return {
427
427
  manifest, manifestGate, legacyProjection,
428
- binding: createKfdAdopterReleaseBinding({ manifest, manifestGate, legacyProjection, expectedSourceSha: sourceSha }),
428
+ binding: createKfdAdopterReleaseBinding({ manifest, manifestGate, legacyProjection, expectedAdopterId, expectedSourceRepository, expectedSourceSha: sourceSha }),
429
429
  };
430
430
  }
431
431
 
432
- export function validateKfdAdopterReleaseEvidence({ binding, artifactBinding, manifest, manifestGate, legacyProjection, passportLegacyProjection, expectedSourceSha = "" } = {}) {
432
+ export function validateKfdAdopterReleaseEvidence({ binding, artifactBinding, manifest, manifestGate, legacyProjection, passportLegacyProjection, expectedAdopterId = "kungfu-systems/buildchain", expectedSourceRepository = "", expectedSourceSha = "" } = {}) {
433
433
  if (!binding) {
434
434
  return passportLegacyProjection
435
435
  ? [{ code: "kfdSupport.authority", message: "legacy KFD support projection requires the standard adopter manifest binding" }]
436
436
  : [];
437
437
  }
438
438
  const issues = validateKfdAdopterReleaseBinding(binding, {
439
- manifest, manifestGate, legacyProjection, expectedSourceSha,
439
+ manifest, manifestGate, legacyProjection, expectedAdopterId, expectedSourceRepository, expectedSourceSha,
440
440
  }).issues.map((entry) => ({ code: `kfdAdopter.${entry.path || entry.code}`, message: entry.message, details: entry }));
441
441
  if (!artifactBinding || passportStableJson(artifactBinding) !== passportStableJson(binding)) {
442
442
  issues.push({ code: "kfdAdopter.artifactEvidence", message: "release passport and artifact evidence must bind the same exact KFD adopter closure" });
@@ -1431,7 +1431,7 @@ export function createReleasePassport(options = {}) {
1431
1431
  };
1432
1432
  }
1433
1433
 
1434
- function collectKfdAdopterReleaseInputs({ cwd, manifestJson, supportMatrixJson, productGateJsons, sourceSha, checkedAt }) {
1434
+ function collectKfdAdopterReleaseInputs({ cwd, manifestJson, supportMatrixJson, productGateJsons, repository, sourceSha, checkedAt }) {
1435
1435
  const manifestMeta = parseJsonInputWithMeta(manifestJson, undefined, { cwd, label: "kfdAdopterManifestJson" });
1436
1436
  const supportMatrixMeta = parseJsonInputWithMeta(supportMatrixJson, undefined, { cwd, label: "kfdSupportMatrixJson" });
1437
1437
  const productGateMetas = (productGateJsons || [])
@@ -1442,7 +1442,7 @@ function collectKfdAdopterReleaseInputs({ cwd, manifestJson, supportMatrixJson,
1442
1442
  manifest: manifestMeta.value,
1443
1443
  gateResults: productGateMetas.map((meta) => meta.value),
1444
1444
  comparisonMatrix: supportMatrixMeta.value,
1445
- sourceSha,
1445
+ expectedAdopterId: repository || "kungfu-systems/buildchain", expectedSourceRepository: repository, sourceSha,
1446
1446
  checkedAt,
1447
1447
  });
1448
1448
  }
@@ -1620,7 +1620,7 @@ export function collectGitHubReleasePassport({
1620
1620
  const productMechanism = defaultProductMechanism({ repository, productName });
1621
1621
  const kfdAdopterEvidence = collectKfdAdopterReleaseInputs({
1622
1622
  cwd, manifestJson: kfdAdopterManifestJson, supportMatrixJson: kfdSupportMatrixJson,
1623
- productGateJsons: kfdProductGateJsons, sourceSha, checkedAt: resolvedCheckedAt,
1623
+ productGateJsons: kfdProductGateJsons, repository, sourceSha, checkedAt: resolvedCheckedAt,
1624
1624
  });
1625
1625
  const {
1626
1626
  manifest: kfdAdopterManifest,
@@ -2060,7 +2060,8 @@ function validateReleaseEvidenceContracts({
2060
2060
  manifestGate: kfdAdopterManifestGate,
2061
2061
  legacyProjection: kfdSupportEvidence,
2062
2062
  passportLegacyProjection: passport?.kfdSupport,
2063
- expectedSourceSha: optionalString(passport?.release?.sourceSha),
2063
+ expectedAdopterId: optionalString(passport?.product?.repository) || "kungfu-systems/buildchain",
2064
+ expectedSourceRepository: optionalString(passport?.product?.repository), expectedSourceSha: optionalString(passport?.release?.sourceSha),
2064
2065
  })) {
2065
2066
  issues.push(issue("error", entry.code, entry.message, entry.details));
2066
2067
  }
@@ -0,0 +1,38 @@
1
+ export const RELEASE_TAIL_PRODUCT_CAPABILITIES = Object.freeze([
2
+ Object.freeze({
3
+ id: "product.version-state.materialize",
4
+ executor: "provider-adapter",
5
+ adapter: "github-version-state",
6
+ effectKind: "product-version-state-materialization",
7
+ observationKind: "product-version-state-readback",
8
+ receiptKind: "product-version-state",
9
+ transactionState: "preparing",
10
+ }),
11
+ Object.freeze({
12
+ id: "product.package.publish",
13
+ executor: "provider-adapter",
14
+ adapter: "npm-trusted-publishing",
15
+ effectKind: "product-package-publication",
16
+ observationKind: "product-package-readback",
17
+ receiptKind: "product-package-publication",
18
+ transactionState: "publishing",
19
+ }),
20
+ Object.freeze({
21
+ id: "product.oci.publish",
22
+ executor: "provider-adapter",
23
+ adapter: "oci-image-family",
24
+ effectKind: "oci-family-publication",
25
+ observationKind: "oci-family-readback",
26
+ receiptKind: "oci-family-publication",
27
+ transactionState: "publishing",
28
+ }),
29
+ Object.freeze({
30
+ id: "product.release-refs.converge",
31
+ executor: "provider-adapter",
32
+ adapter: "github-release-refs",
33
+ effectKind: "product-release-ref-convergence",
34
+ observationKind: "product-release-ref-readback",
35
+ receiptKind: "product-release-ref-convergence",
36
+ transactionState: "committing",
37
+ }),
38
+ ]);