@kungfu-tech/buildchain 4.0.1-alpha.3 → 4.0.1-alpha.5

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 (95) hide show
  1. package/architecture/decisions/0002-next-development-transition.md +101 -0
  2. package/architecture/internal-capabilities.json +52 -3
  3. package/architecture/maintainability-policy.json +22 -10
  4. package/architecture/v3-core-mechanism-inventory.json +89 -0
  5. package/architecture/v4-capability-state-machine-manifest.json +73 -0
  6. package/architecture/v4-compatibility-facts-parity.json +77 -0
  7. package/architecture/v4-delivery-warrant-shadow-fixtures.json +15 -6
  8. package/architecture/v4-next-development-parity.json +192 -0
  9. package/architecture/v4-release-train-parity.json +1 -0
  10. package/architecture/v4-tail-reseal-parity.json +150 -0
  11. package/bin/buildchain.mjs +16 -1
  12. package/bin/internal/command-registry.mjs +2 -0
  13. package/bin/internal/compatibility-facts-cli.mjs +101 -0
  14. package/contracts/fixtures/next-development-transition-v1/anchored-manual-waiting.json +47 -0
  15. package/contracts/fixtures/next-development-transition-v1/semver-auto-planned.json +47 -0
  16. package/contracts/fixtures/next-development-transition-v1/version-model-cases.json +40 -0
  17. package/contracts/fixtures/v4-compatibility-facts-v1/shared.json +1129 -0
  18. package/contracts/fixtures/v4-floating-consumer-policy-v1/cases.json +7 -1
  19. package/contracts/fixtures/v4-tail-reseal-v1/valid.json +229 -0
  20. package/contracts/next-development-request-v1.schema.json +66 -0
  21. package/contracts/next-development-transition-v1.schema.json +292 -0
  22. package/contracts/v4-compatibility-facts-v1.schema.json +230 -0
  23. package/contracts/v4-tail-reseal-v1.schema.json +276 -0
  24. package/dist/site/agent-index.json +1 -0
  25. package/dist/site/artifact-schemas.json +2 -0
  26. package/dist/site/buildchain-contract.json +1388 -23
  27. package/dist/site/buildchain-site.json +259 -21
  28. package/dist/site/capability-registry.json +10 -8
  29. package/dist/site/cli-registry.json +106 -0
  30. package/dist/site/kfd-claims.json +187 -12
  31. package/dist/site/kfd-upstream-aggregate.json +1 -1
  32. package/dist/site/manual-registry.json +35 -4
  33. package/dist/site/node-api-registry.json +6578 -4492
  34. package/dist/site/page-registry.json +235 -13
  35. package/dist/site/public-surface-audit.json +241 -7
  36. package/dist/site/publication-authority-registry.json +6 -1
  37. package/dist/site/publication-registry.json +4 -4
  38. package/dist/site/release-provenance.json +7 -0
  39. package/dist/site/schemas/v4-compatibility-facts-v1.schema.json +230 -0
  40. package/dist/site/site-manifest.json +24 -8
  41. package/dist/site/workflow-registry.json +36 -4
  42. package/docs/MAP.md +4 -1
  43. package/docs/cli-reference.md +125 -0
  44. package/docs/dev-alpha-candidate-patrol.md +8 -0
  45. package/docs/dev-delivery-warrant.md +8 -4
  46. package/docs/next-development-transition.md +118 -0
  47. package/docs/node-api-reference.md +256 -123
  48. package/docs/v4-compatibility-facts.md +91 -0
  49. package/docs/v4-tail-reseal.md +73 -0
  50. package/docs/versioning.md +4 -3
  51. package/package.json +14 -5
  52. package/packages/core/buildchain-agent-manuals.js +2 -0
  53. package/packages/core/buildchain-compatibility-authority.js +336 -0
  54. package/packages/core/buildchain-compatibility-fact.js +394 -0
  55. package/packages/core/buildchain-compatibility-facts.json +217 -0
  56. package/packages/core/buildchain-compatibility-proof.js +566 -0
  57. package/packages/core/buildchain-contract.js +93 -141
  58. package/packages/core/channel-candidate.js +8 -0
  59. package/packages/core/channel-promotion-baseline.js +55 -0
  60. package/packages/core/dev-alpha-candidate-selection.js +10 -2
  61. package/packages/core/dev-delivery-execution-transfer.js +21 -1
  62. package/packages/core/dev-delivery-process-boundary.js +19 -7
  63. package/packages/core/dev-delivery-provider-heartbeat.js +18 -6
  64. package/packages/core/dev-delivery-warrant-state.js +4 -5
  65. package/packages/core/dev-delivery-warrant.js +1 -0
  66. package/packages/core/kungfu-temporal-fact.js +557 -0
  67. package/packages/core/next-development-candidate-reservation.js +186 -0
  68. package/packages/core/next-development-controller.js +728 -0
  69. package/packages/core/next-development-projection.js +287 -0
  70. package/packages/core/next-development-transition.js +738 -0
  71. package/packages/core/paper-agent-entry.js +11 -5
  72. package/packages/core/paper.js +16 -5
  73. package/packages/core/v4-canonical-contracts.js +5 -0
  74. package/packages/core/v4-floating-consumer-policy.js +29 -9
  75. package/packages/core/v4-tail-reseal-contract.js +26 -0
  76. package/packages/core/v4-tail-reseal-github.js +178 -0
  77. package/packages/core/v4-tail-reseal-receipt.js +225 -0
  78. package/packages/core/v4-tail-reseal.js +594 -0
  79. package/scripts/buildchain-cli-help.mjs +20 -0
  80. package/scripts/check-inventory.mjs +11 -0
  81. package/scripts/check-v4-floating-consumer-policy-contract.mjs +1 -1
  82. package/scripts/dev-alpha-candidate-patrol.mjs +22 -1
  83. package/scripts/dev-pr-auto-merge.mjs +1 -1
  84. package/scripts/generate-next-development-guidance.mjs +49 -0
  85. package/scripts/generate-site-bundle.mjs +16 -3
  86. package/scripts/init-repo.mjs +22 -4
  87. package/scripts/next-development-self-dogfood-harness.mjs +460 -0
  88. package/scripts/next-development-self-dogfood.mjs +597 -0
  89. package/scripts/next-development-transition.mjs +47 -0
  90. package/scripts/release-train-self-dogfood.mjs +94 -92
  91. package/scripts/site-capability-metadata.mjs +12 -0
  92. package/scripts/v4-consumer-policy.mjs +1 -5
  93. package/scripts/v4-tail-reseal-macos-rehearsal.mjs +134 -0
  94. package/scripts/v4-tail-reseal.mjs +416 -0
  95. package/templates/native-dev-delivery.yml +2 -0
@@ -6,7 +6,11 @@ import fs from "node:fs";
6
6
  import {
7
7
  closeDevDeliveryWarrant,
8
8
  createDevDeliveryQueue,
9
+ createNativeCommandContract,
10
+ createNativeProofReuseDecision,
11
+ createNativeQualificationProof,
9
12
  createReleaseBlockerPriorityClaim,
13
+ qualifyDevDeliveryWarrant,
10
14
  selectDevDeliveryWarrant,
11
15
  submitDevDeliveryCandidate,
12
16
  } from "../packages/core/dev-delivery-warrant.js";
@@ -81,9 +85,12 @@ function branch(value, label) {
81
85
  return normalized;
82
86
  }
83
87
 
84
- function at(recordedAt, seconds) {
85
- return new Date(Date.parse(recordedAt) + seconds * 1000).toISOString();
86
- }
88
+ const at = (recordedAt, seconds) => new Date(Date.parse(recordedAt) + seconds * 1000).toISOString();
89
+
90
+ const normalizeFields = (input, fields, normalizer, prefix = "") =>
91
+ Object.fromEntries(fields.map((field) => [field, normalizer(input?.[field], `${prefix}${field}`)]));
92
+
93
+ const requireEvidence = (condition, message) => { if (!condition) throw new Error(message); };
87
94
 
88
95
  function normalizeDelivery(input, expected) {
89
96
  const delivery = {
@@ -92,59 +99,44 @@ function normalizeDelivery(input, expected) {
92
99
  "delivery.pullRequestNumber",
93
100
  ),
94
101
  baseBranch: branch(input?.baseBranch, "delivery.baseBranch"),
95
- headSha: sha(input?.headSha, "delivery.headSha"),
96
- headTreeSha: sha(input?.headTreeSha, "delivery.headTreeSha"),
97
- state: text(input?.state, "delivery.state"),
98
- reviewState: text(input?.reviewState, "delivery.reviewState"),
99
- reviewHeadSha: sha(input?.reviewHeadSha, "delivery.reviewHeadSha"),
100
- mergeSha: sha(input?.mergeSha, "delivery.mergeSha"),
101
- mergeTreeSha: sha(input?.mergeTreeSha, "delivery.mergeTreeSha"),
102
- ciHeadSha: sha(input?.ciHeadSha, "delivery.ciHeadSha"),
103
- ciConclusion: text(input?.ciConclusion, "delivery.ciConclusion"),
104
- reviewRoot: root(input?.reviewRoot, "delivery.reviewRoot"),
105
- ciRoot: root(input?.ciRoot, "delivery.ciRoot"),
106
- mergeRoot: root(input?.mergeRoot, "delivery.mergeRoot"),
107
- artifactRoot: root(input?.artifactRoot, "delivery.artifactRoot"),
108
- installedProductRoot: root(
109
- input?.installedProductRoot,
110
- "delivery.installedProductRoot",
102
+ ...normalizeFields(
103
+ input,
104
+ ["headSha", "headTreeSha", "reviewHeadSha", "mergeSha", "mergeTreeSha", "ciHeadSha"],
105
+ sha,
106
+ "delivery.",
107
+ ),
108
+ ...normalizeFields(input, ["state", "reviewState", "ciConclusion"], text, "delivery."),
109
+ ...normalizeFields(
110
+ input,
111
+ ["reviewRoot", "ciRoot", "mergeRoot", "artifactRoot", "installedProductRoot"],
112
+ root,
113
+ "delivery.",
111
114
  ),
112
115
  };
113
- if (delivery.baseBranch !== expected.sourceBranch) {
114
- throw new Error(
115
- "protected delivery base does not match the Release Cut source branch",
116
- );
117
- }
118
- if (
119
- delivery.state !== "MERGED" ||
120
- delivery.reviewState !== "APPROVED" ||
121
- delivery.ciConclusion !== "success"
122
- ) {
123
- throw new Error(
124
- "protected delivery is not merged, approved, and CI-successful",
125
- );
126
- }
127
- if (
128
- delivery.headSha !== expected.devLandingSha ||
129
- delivery.reviewHeadSha !== delivery.headSha
130
- ) {
131
- throw new Error(
132
- "protected delivery review does not bind the exact repaired head",
133
- );
134
- }
135
- if (
136
- delivery.headTreeSha !== expected.cutCandidateTreeSha ||
137
- delivery.mergeTreeSha !== delivery.headTreeSha
138
- ) {
139
- throw new Error(
140
- "protected delivery merge tree does not equal the repaired candidate tree",
141
- );
142
- }
143
- if (delivery.ciHeadSha !== delivery.mergeSha) {
144
- throw new Error(
145
- "protected delivery CI does not bind the merge-group result",
146
- );
147
- }
116
+ requireEvidence(
117
+ delivery.baseBranch === expected.sourceBranch,
118
+ "protected delivery base does not match the Release Cut source branch",
119
+ );
120
+ requireEvidence(
121
+ delivery.state === "MERGED" &&
122
+ delivery.reviewState === "APPROVED" &&
123
+ delivery.ciConclusion === "success",
124
+ "protected delivery is not merged, approved, and CI-successful",
125
+ );
126
+ requireEvidence(
127
+ delivery.headSha === expected.devLandingSha &&
128
+ delivery.reviewHeadSha === delivery.headSha,
129
+ "protected delivery review does not bind the exact repaired head",
130
+ );
131
+ requireEvidence(
132
+ delivery.headTreeSha === expected.cutCandidateTreeSha &&
133
+ delivery.mergeTreeSha === delivery.headTreeSha,
134
+ "protected delivery merge tree does not equal the repaired candidate tree",
135
+ );
136
+ requireEvidence(
137
+ delivery.ciHeadSha === delivery.mergeSha,
138
+ "protected delivery CI does not bind the merge-group result",
139
+ );
148
140
  return delivery;
149
141
  }
150
142
 
@@ -153,50 +145,32 @@ function normalizeInput(input = {}) {
153
145
  repository: repository(input.repository),
154
146
  sourceBranch: branch(input.sourceBranch, "sourceBranch"),
155
147
  targetBranch: branch(input.targetBranch, "targetBranch"),
156
- assignmentRoot: root(input.assignmentRoot, "assignmentRoot"),
157
- initiativeRoot: root(input.initiativeRoot, "initiativeRoot"),
158
- dependencyProofRoot: root(input.dependencyProofRoot, "dependencyProofRoot"),
159
- originDevSha: sha(input.originDevSha, "originDevSha"),
160
- candidateSha: sha(input.candidateSha, "candidateSha"),
161
- candidateTreeSha: sha(input.candidateTreeSha, "candidateTreeSha"),
162
- alphaBaseSha: sha(input.alphaBaseSha, "alphaBaseSha"),
163
- buildchainRuntimeSha: sha(
164
- input.buildchainRuntimeSha,
165
- "buildchainRuntimeSha",
166
- ),
167
- observedDevSha: sha(input.observedDevSha, "observedDevSha"),
168
- blockerRoot: root(input.blockerRoot, "blockerRoot"),
169
- patchRoot: root(input.patchRoot, "patchRoot"),
170
- cutCandidateSha: sha(input.cutCandidateSha, "cutCandidateSha"),
171
- cutCandidateTreeSha: sha(input.cutCandidateTreeSha, "cutCandidateTreeSha"),
172
- cutLandingEvidenceRoot: root(
173
- input.cutLandingEvidenceRoot,
174
- "cutLandingEvidenceRoot",
148
+ ...normalizeFields(
149
+ input,
150
+ ["assignmentRoot", "initiativeRoot", "dependencyProofRoot", "environmentRoot", "blockerRoot", "patchRoot", "cutLandingEvidenceRoot", "devConflictEvidenceRoot", "devLandingEvidenceRoot"],
151
+ root,
175
152
  ),
176
- devBaseSha: sha(input.devBaseSha, "devBaseSha"),
177
- devLandingSha: sha(input.devLandingSha, "devLandingSha"),
178
- devConflictEvidenceRoot: root(
179
- input.devConflictEvidenceRoot,
180
- "devConflictEvidenceRoot",
181
- ),
182
- devLandingEvidenceRoot: root(
183
- input.devLandingEvidenceRoot,
184
- "devLandingEvidenceRoot",
153
+ ...normalizeFields(
154
+ input,
155
+ ["originDevSha", "candidateSha", "candidateTreeSha", "alphaBaseSha", "buildchainRuntimeSha", "observedDevSha", "cutCandidateSha", "cutCandidateTreeSha", "devBaseSha", "devLandingSha"],
156
+ sha,
185
157
  ),
158
+ nativeCommand: text(input.nativeCommand, "nativeCommand"),
159
+ nativeExecutionReceipt: structuredClone(input.nativeExecutionReceipt || {}),
186
160
  ordinaryPullRequestNumber: positiveInteger(
187
161
  input.ordinaryPullRequestNumber,
188
162
  "ordinaryPullRequestNumber",
189
163
  ),
190
164
  recordedAt: timestamp(input.recordedAt, "recordedAt"),
191
165
  };
192
- if (normalized.observedDevSha === normalized.originDevSha) {
193
- throw new Error(
194
- "self-dogfood requires dev to advance beyond the frozen origin",
195
- );
196
- }
197
- if (normalized.cutCandidateSha === normalized.candidateSha) {
198
- throw new Error("self-dogfood requires a successor repair candidate");
199
- }
166
+ requireEvidence(
167
+ normalized.observedDevSha !== normalized.originDevSha,
168
+ "self-dogfood requires dev to advance beyond the frozen origin",
169
+ );
170
+ requireEvidence(
171
+ normalized.cutCandidateSha !== normalized.candidateSha,
172
+ "self-dogfood requires a successor repair candidate",
173
+ );
200
174
  normalized.delivery = normalizeDelivery(input.delivery, normalized);
201
175
  return normalized;
202
176
  }
@@ -214,6 +188,10 @@ function deliveryCandidate(input, deliveryClass = "release") {
214
188
  closureRoot: input.closureRoot,
215
189
  dependencyRoot: input.dependencyRoot,
216
190
  toolchainRoot: input.toolchainRoot,
191
+ ...(input.environmentRoot ? { environmentRoot: input.environmentRoot } : {}),
192
+ ...(input.nativeCommand
193
+ ? { nativeCommandContract: createNativeCommandContract(input.nativeCommand) }
194
+ : {}),
217
195
  deliveryClass,
218
196
  priority: "ordinary",
219
197
  ...(input.releaseBlockerPriority
@@ -366,7 +344,7 @@ function runQueueCampaign(value, repaired, priorityClaim) {
366
344
  dependencyRoot: value.dependencyProofRoot,
367
345
  toolchainRoot: value.dependencyProofRoot,
368
346
  },
369
- "native-proof-required",
347
+ "non-native-fast",
370
348
  );
371
349
  queue = submitDevDeliveryCandidate(queue, ordinary, {
372
350
  now: at(value.recordedAt, 6),
@@ -388,6 +366,8 @@ function runQueueCampaign(value, repaired, priorityClaim) {
388
366
  closureRoot: value.delivery.mergeRoot,
389
367
  dependencyRoot: value.dependencyProofRoot,
390
368
  toolchainRoot: value.delivery.installedProductRoot,
369
+ environmentRoot: value.environmentRoot,
370
+ nativeCommand: value.nativeCommand,
391
371
  releaseBlockerPriority: priorityClaim,
392
372
  });
393
373
  const submitted = submitDevDeliveryCandidate(queue, blocker, {
@@ -426,7 +406,29 @@ function runQueueCampaign(value, repaired, priorityClaim) {
426
406
  "eligible release blocker did not receive bounded priority",
427
407
  );
428
408
  }
429
- const closed = closeDevDeliveryWarrant(selected.queue, selected.warrant, {
409
+ const nativeCommandRoot = createNativeCommandContract(value.nativeCommand).commandRoot;
410
+ const proof = createNativeQualificationProof({
411
+ ...selected.warrant,
412
+ repository: value.repository,
413
+ protectedBase: value.sourceBranch,
414
+ qualifiedBase: value.devBaseSha,
415
+ nativeCommandRoot,
416
+ nativeExecutionReceipt: value.nativeExecutionReceipt,
417
+ affectedPaths: [], shardEvidenceRoots: [],
418
+ qualifiedAt: at(value.recordedAt, 12),
419
+ });
420
+ const current = {
421
+ ...selected.warrant,
422
+ nativeCommandRoot,
423
+ currentBase: value.devBaseSha,
424
+ graphKnown: true, attributionComplete: true,
425
+ changedPaths: [], renames: [],
426
+ };
427
+ const reuseDecision = createNativeProofReuseDecision({ proof, current });
428
+ const qualified = qualifyDevDeliveryWarrant(selected.queue, selected.warrant, {
429
+ nativeProof: proof, reuseDecision, current, now: at(value.recordedAt, 12),
430
+ });
431
+ const closed = closeDevDeliveryWarrant(qualified.queue, qualified.warrant, {
430
432
  outcome: "merged",
431
433
  evidenceRoot: value.delivery.mergeRoot,
432
434
  now: at(value.recordedAt, 13),
@@ -39,6 +39,10 @@ export function cliCommandMeta(id) {
39
39
  "explain-artifact": { group: "release-passport-trust", purpose: "Explain artifact evidence for humans or agents." },
40
40
  "explain-release": { group: "release-passport-trust", purpose: "Explain a release passport for humans or agents." },
41
41
  facts: { group: "observability-diagnostics", purpose: "Inspect build facts command families." },
42
+ "facts-compatibility-project": { group: "governance-versioning", purpose: "Project legacy digest and proof views from the current Cut-bound compatibility Fact registry." },
43
+ "facts-compatibility-query": { group: "governance-versioning", purpose: "Verify one explicit directional compatibility path and emit a rooted receipt." },
44
+ "facts-compatibility-query-template": { group: "governance-versioning", purpose: "Create a direct query template for one current compatibility Fact." },
45
+ "facts-compatibility-verify": { group: "governance-versioning", purpose: "Verify the exact append-only compatibility Fact registry and current Cut." },
42
46
  help: { group: "getting-started", purpose: "Print Buildchain CLI help." },
43
47
  homebrew: { group: "distribution-indexes", purpose: "Inspect Homebrew distribution-index command families." },
44
48
  "homebrew-check": { group: "distribution-indexes", purpose: "Verify Homebrew tap metadata against upstream release passport evidence." },
@@ -139,6 +143,7 @@ export function cliCommandMeta(id) {
139
143
  "paper-status": { group: "reusable-build", purpose: "Report explicit evidence for every paper lifecycle state without unsupported inference." },
140
144
  "paper-work-start": { group: "getting-started", purpose: "Create a safe Paper work branch from the exact canonical remote development SHA." },
141
145
  "paper-work-submit": { group: "governance-versioning", purpose: "Push a Paper work branch without force and open or reuse the correctly targeted development PR." },
146
+ "next-development": { group: "governance-versioning", purpose: "Plan or apply one rooted declared-path next-development version transition without release or ref authority." },
142
147
  "publish-source": { group: "release-passport-trust", purpose: "Create, inspect, or verify publish-gate source-lock refs." },
143
148
  "publication-artifact": { group: "reusable-build", purpose: "Generate publication artifact manifests, passports, and source bundles for paper/report repositories." },
144
149
  "publication-artifact-manifest": { group: "reusable-build", purpose: "Write a site-consumable publication artifact manifest, publication passport, and source bundle." },
@@ -151,6 +156,7 @@ export function cliCommandMeta(id) {
151
156
  "release-governance": { group: "governance-versioning", purpose: "Reconcile a managed branch's Buildchain aggregate check to an already-tested pull request SHA." },
152
157
  "release-propagation": { group: "site-and-propagation", purpose: "Route exact Paper, KFD, Buildchain, or Core Site updates through one resumable propagation Work." },
153
158
  "release-tail": { group: "release-passport-trust", purpose: "Plan, initialize, resume, and verify one declarative provider-owned release-tail transaction." },
159
+ "tail-reseal": { group: "release-passport-trust", purpose: "Plan, admit, byte-verify, and seal one exact retained v4 Alpha candidate signing-finalization tail." },
154
160
  "release-transaction": { group: "release-passport-trust", purpose: "Inspect, recover, finalize, or abort durable release transactions." },
155
161
  sample: { group: "observability-diagnostics", purpose: "Inspect sampler command families." },
156
162
  "sample-process-tree": { group: "observability-diagnostics", purpose: "Sample process-tree diagnostics for a wrapped command." },
@@ -215,8 +221,13 @@ export function nodeApiMeta(exportName) {
215
221
  "./release-candidate": { group: "reusable-build", summary: "PR-stage release-candidate artifact, passport, and promote-only resolver APIs." },
216
222
  "./v4-floating-consumer-policy": { group: "governance-versioning", summary: "Semantic floating-selector admission, dual-lock receipt, and independent v4 consumer certification APIs." },
217
223
  "./v4-runtime-ref-resume-authority": { group: "release-passport-trust", summary: "Transient exact-runtime authorization, persisted-selector rejection, fresh-attempt Stage Capsule reuse, and A+B Passport lineage APIs." },
224
+ "./v4-tail-reseal": { group: "release-passport-trust", summary: "Effect-pure retained Stage Capsule validation and explicit Warrant-, credential-, and release-tail-fenced macOS reseal planning APIs." },
225
+ "./v4-tail-reseal-receipt": { group: "release-passport-trust", summary: "Four-platform byte readback, standard candidate Passport binding, and terminal v4 tail-reseal receipt APIs." },
218
226
  "./release-candidate-recovery": { group: "release-passport-trust", summary: "Fail-closed verification and immutable receipts for reusing a successful sealed candidate run without rebuilding product payloads." },
219
227
  "./release-train": { group: "governance-versioning", summary: "Frozen Release Cut identity, rooted Release Train transitions, Dev observations, supersession, replay, and legacy read compatibility APIs." },
228
+ "./next-development-transition": { group: "governance-versioning", summary: "Provider-neutral completed-Alpha preservation and rooted next-development state, version-model, idempotency, and local materialization APIs." },
229
+ "./next-development-controller": { group: "governance-versioning", summary: "Durable completed-Alpha child scheduling, fresh-runner checkpoint resume, latest protected-Dev reconciliation, and exact version-root readback APIs." },
230
+ "./next-development-projection": { group: "governance-versioning", summary: "Canonical generated config, Agent, workflow-header, and manual projections for the next-development transition contract." },
220
231
  "./stable-candidate-ledger": { group: "governance-versioning", summary: "Immutable alpha candidate ledger, qualification, revocation, selection, and exact stable source-lock APIs." },
221
232
  "./release-propagation": { group: "site-and-propagation", summary: "Release propagation graph, plan, and exact upstream lock APIs." },
222
233
  "./release-activation-transaction": { group: "release-passport-trust", summary: "Ordered cross-repository activation, exact receipt-set binding, retry, abort, rollback, and shadow-rehearsal APIs." },
@@ -225,6 +236,7 @@ export function nodeApiMeta(exportName) {
225
236
  "./release-tail-compatibility": { group: "release-passport-trust", summary: "Bounded v3 release-hook compatibility diagnostics that reject new executable release-tail inputs." },
226
237
  "./release-line-bootstrap": { group: "governance-versioning", summary: "Semver release-line bootstrap planning and version-state APIs." },
227
238
  "./buildchain-contract": { group: "governance-versioning", summary: "Runtime contract world and compatibility digest APIs for floating-ref drift checks." },
239
+ "./compatibility-fact-authority": { group: "governance-versioning", summary: "Directional Cut-bound compatibility Fact, lifecycle, explicit path receipt, legacy projection, and Release Passport evidence APIs." },
228
240
  "./controller-evidence": { group: "reusable-build", summary: "Project-independent controller descriptors, source/runtime-bound plans, receipts, aggregates, and validation APIs." },
229
241
  "./surface-manifest": { group: "site-and-propagation", summary: "Surface manifest timestamp and reproducibility policy APIs." },
230
242
  "./issue-reporting": { group: "observability-diagnostics", summary: "Buildchain-owned issue reporting API for workflow friction feedback." },
@@ -139,10 +139,6 @@ export function certifyCommand(options = {}) {
139
139
  stableLockPath,
140
140
  alphaLockPath,
141
141
  });
142
- const selectedLock =
143
- receipt?.invocation?.visibleSelector === "v4-alpha"
144
- ? readJson(path.join(callerRoot, alphaLockPath))
145
- : readJson(path.join(callerRoot, stableLockPath));
146
142
  const authorityScan = scanV4FloatingConsumerPolicy({
147
143
  root: callerRoot,
148
144
  repository,
@@ -150,7 +146,7 @@ export function certifyCommand(options = {}) {
150
146
  invokedWorkflow,
151
147
  invocationSourcePath: receipt?.invocation?.sourcePath,
152
148
  expectedInvocationChannel: receipt?.invocation?.channel,
153
- resolvedWorkflowSha: selectedLock.buildchain?.resolvedSha,
149
+ resolvedWorkflowSha: receipt?.invocation?.resolvedWorkflowSha,
154
150
  resolvedRuntimeSha,
155
151
  stableLockPath,
156
152
  alphaLockPath,
@@ -0,0 +1,134 @@
1
+ #!/usr/bin/env node
2
+
3
+ import crypto from "node:crypto";
4
+ import fs from "node:fs";
5
+ import os from "node:os";
6
+ import path from "node:path";
7
+ import { pathToFileURL } from "node:url";
8
+
9
+ import { v4ContentRoot } from "../packages/core/v4-canonical-contracts.js";
10
+ import { verifyV4TailResealPlatform } from "./v4-tail-reseal.mjs";
11
+
12
+ function flag(args, name, fallback = "") {
13
+ const index = args.indexOf(`--${name}`);
14
+ return index < 0 ? fallback : String(args[index + 1] || "");
15
+ }
16
+
17
+ function fileRoot(file) {
18
+ return `sha256:${crypto
19
+ .createHash("sha256")
20
+ .update(fs.readFileSync(file))
21
+ .digest("hex")}`;
22
+ }
23
+
24
+ function writeCandidate(root, request, content) {
25
+ const platform = request.platforms.find(({ id }) => id === "macos-arm64");
26
+ const payload = path.join(root, "product/release/macos-arm64/payload.bin");
27
+ fs.mkdirSync(path.dirname(payload), { recursive: true });
28
+ fs.writeFileSync(payload, content);
29
+ const relative = path.relative(root, payload);
30
+ const file = {
31
+ path: relative,
32
+ size: fs.statSync(payload).size,
33
+ digest: fileRoot(payload),
34
+ };
35
+ const manifest = {
36
+ contract: "kungfu-buildchain-artifact",
37
+ artifactName: platform.artifactName,
38
+ git: {
39
+ repository: request.repository,
40
+ sha: request.source.sha,
41
+ treeSha: request.source.treeSha,
42
+ runId: String(request.source.runId),
43
+ runAttempt: String(request.source.runAttempt),
44
+ },
45
+ platform: { id: platform.id, name: platform.name },
46
+ files: [
47
+ {
48
+ path: relative,
49
+ size: file.size,
50
+ sha256: file.digest.replace(/^sha256:/u, ""),
51
+ },
52
+ ],
53
+ summary: { fileCount: 1, totalBytes: file.size },
54
+ };
55
+ const manifestPath = path.join(root, "evidence/macos-arm64/manifest.json");
56
+ fs.mkdirSync(path.dirname(manifestPath), { recursive: true });
57
+ fs.writeFileSync(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`);
58
+ return {
59
+ artifactRoot: v4ContentRoot("tail-reseal-artifact-files", [file]),
60
+ manifestRoot: fileRoot(manifestPath),
61
+ };
62
+ }
63
+
64
+ export function rehearseV4TailResealMacos({
65
+ fixturePath = "contracts/fixtures/v4-tail-reseal-v1/valid.json",
66
+ outputPath = "",
67
+ } = {}) {
68
+ const request = JSON.parse(
69
+ fs.readFileSync(path.resolve(fixturePath), "utf8"),
70
+ );
71
+ const workRoot = fs.mkdtempSync(
72
+ path.join(os.tmpdir(), "buildchain-v4-tail-macos-"),
73
+ );
74
+ try {
75
+ const retainedRoots = writeCandidate(workRoot, request, "unsigned");
76
+ const platform = request.platforms.find(({ id }) => id === "macos-arm64");
77
+ Object.assign(platform, retainedRoots);
78
+ const retained = verifyV4TailResealPlatform({
79
+ request,
80
+ platformId: "macos-arm64",
81
+ artifactRoot: workRoot,
82
+ mode: "retained",
83
+ });
84
+ writeCandidate(workRoot, request, "signed-and-notarized");
85
+ const resealed = verifyV4TailResealPlatform({
86
+ request,
87
+ platformId: "macos-arm64",
88
+ artifactRoot: workRoot,
89
+ mode: "resealed",
90
+ providerReadbackRoot: request.signing.providerReadbackRoot,
91
+ });
92
+ const payload = {
93
+ schema: "kungfu-buildchain-v4-tail-reseal-macos-rehearsal/v1",
94
+ platformId: "macos-arm64",
95
+ retained,
96
+ resealed,
97
+ buildStagesExecuted: 0,
98
+ signingFinalizationExecutions: 1,
99
+ providerReadbackRoot: request.signing.providerReadbackRoot,
100
+ };
101
+ const evidence = {
102
+ ...payload,
103
+ evidenceRoot: v4ContentRoot("tail-reseal-admission", payload),
104
+ };
105
+ if (outputPath) {
106
+ const output = path.resolve(outputPath);
107
+ fs.mkdirSync(path.dirname(output), { recursive: true });
108
+ fs.writeFileSync(output, `${JSON.stringify(evidence, null, 2)}\n`);
109
+ }
110
+ return evidence;
111
+ } finally {
112
+ fs.rmSync(workRoot, { recursive: true, force: true });
113
+ }
114
+ }
115
+
116
+ if (
117
+ process.argv[1] &&
118
+ import.meta.url === pathToFileURL(process.argv[1]).href
119
+ ) {
120
+ try {
121
+ const evidence = rehearseV4TailResealMacos({
122
+ fixturePath: flag(
123
+ process.argv.slice(2),
124
+ "fixture",
125
+ "contracts/fixtures/v4-tail-reseal-v1/valid.json",
126
+ ),
127
+ outputPath: flag(process.argv.slice(2), "output"),
128
+ });
129
+ process.stdout.write(`${JSON.stringify(evidence, null, 2)}\n`);
130
+ } catch (error) {
131
+ console.error(`v4-tail-reseal-macos-rehearsal: ${error.message}`);
132
+ process.exitCode = 1;
133
+ }
134
+ }