@kungfu-tech/buildchain 3.0.9-alpha.8 → 4.0.0-alpha.0
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/AGENTS.md +39 -0
- package/README.md +17 -13
- package/actions/promote-buildchain-ref/README.md +0 -10
- package/actions/release-tail/README.md +6 -10
- package/architecture/internal-capabilities.json +502 -0
- package/architecture/maintainability-baseline.json +59 -0
- package/architecture/maintainability-policy.json +1384 -0
- package/architecture/release-tail-contract-inventory.json +587 -0
- package/architecture/v3-core-mechanism-inventory.json +1043 -0
- package/architecture/v3-core-mechanism-inventory.md +67 -0
- package/architecture/v4-adopter-delivery-parity.json +47 -0
- package/architecture/v4-architecture-constitution.md +210 -0
- package/architecture/v4-bootstrap-authority.json +56 -0
- package/architecture/v4-canonical-contract-fixtures.json +105 -0
- package/architecture/v4-capability-state-machine-manifest.json +480 -0
- package/architecture/v4-capability-state-machine-manifest.schema.json +202 -0
- package/architecture/v4-delivery-warrant-shadow-bootstrap-plan.json +830 -0
- package/architecture/v4-delivery-warrant-shadow-bootstrap-plan.md +223 -0
- package/architecture/v4-delivery-warrant-shadow-bootstrap-plan.schema.json +318 -0
- package/architecture/v4-delivery-warrant-shadow-fixtures.json +227 -0
- package/architecture/v4-delivery-warrant-shadow-fixtures.schema.json +67 -0
- package/architecture/v4-exception-ledger.json +5 -0
- package/architecture/v4-exception-ledger.schema.json +56 -0
- package/architecture/v4-partial-mutation-recovery-qualification.json +65 -0
- package/architecture/v4-platform-stage-checkpoints.json +97 -0
- package/architecture/v4-provider-operation-journal-contract.json +113 -0
- package/architecture/v4-release-activation-shadow-domain.json +61 -0
- package/architecture/v4-release-train-parity.json +68 -0
- package/architecture/v4-rust-libnode-bridge-evaluation.json +107 -0
- package/architecture/v4-rust-libnode-bridge-spike.md +85 -0
- package/architecture/v4-stable-publication-fence.json +66 -0
- package/architecture/v4-stage-capsule-contract.json +90 -0
- package/architecture/v4-stage-capsule-qualification.json +99 -0
- package/architecture/v4-stage-capsule-resume-planner.json +52 -0
- package/architecture/v4-stage-capsule-store-contract.json +72 -0
- package/bin/buildchain.mjs +15 -6
- package/contracts/auditable-demo-scenario-v1.schema.json +1 -1
- package/contracts/buildchain-v2-residuals-v1.json +2 -2
- package/contracts/fixtures/v4-delivery-warrant-trace-v1/golden.json +158 -0
- package/contracts/fixtures/v4-delivery-warrant-trace-v1/property.json +380 -0
- package/contracts/fixtures/v4-delivery-warrant-trace-v1/replay.json +163 -0
- package/contracts/fixtures/v4-partial-mutation-recovery-v1/shared.json +155 -0
- package/contracts/fixtures/v4-provider-operation-journal-v1/shared.json +457 -0
- package/contracts/fixtures/v4-provider-readback-idempotency-v1/shared.json +682 -0
- package/contracts/fixtures/v4-release-activation-shadow-v1/shared.json +53 -0
- package/contracts/fixtures/v4-stable-publication-fence-v1/shared.json +56 -0
- package/contracts/fixtures/v4-stage-capsule-resume-v1/late-platform-failure.json +176 -0
- package/contracts/fixtures/v4-stage-capsule-store-v1/shared.json +132 -0
- package/contracts/fixtures/v4-stage-capsule-v1/shared.json +111 -0
- package/contracts/v4-canonical-contracts-v1.schema.json +182 -0
- package/contracts/v4-delivery-warrant-semantic-diff-report-v1.schema.json +284 -0
- package/contracts/v4-delivery-warrant-trace-v1.schema.json +215 -0
- package/contracts/v4-host-contract-v1.schema.json +135 -0
- package/contracts/v4-partial-mutation-recovery-v1.schema.json +168 -0
- package/contracts/v4-provider-operation-journal-v1.schema.json +381 -0
- package/contracts/v4-release-activation-shadow-v1.schema.json +186 -0
- package/contracts/v4-stable-publication-fence-v1.schema.json +125 -0
- package/contracts/v4-stage-capsule-resume-v1.schema.json +225 -0
- package/contracts/v4-stage-capsule-store-v1.schema.json +154 -0
- package/contracts/v4-stage-capsule-v1.schema.json +178 -0
- package/crates/buildchain-v4-bridge/Cargo.lock +213 -0
- package/crates/buildchain-v4-bridge/Cargo.toml +12 -0
- package/crates/buildchain-v4-bridge/src/main.rs +495 -0
- package/dist/site/agent-index.json +0 -3
- package/dist/site/artifact-schemas.json +0 -6
- package/dist/site/buildchain-contract.json +103 -397
- package/dist/site/buildchain-site.json +302 -270
- package/dist/site/capability-registry.json +9 -11
- package/dist/site/cli-registry.json +8 -30
- package/dist/site/controller-registry.json +48 -8
- package/dist/site/kfd-claims.json +129 -142
- package/dist/site/kfd-upstream-aggregate.json +9 -9
- package/dist/site/manual-registry.json +18 -49
- package/dist/site/node-api-registry.json +1882 -4118
- package/dist/site/page-registry.json +278 -230
- package/dist/site/public-surface-audit.json +87 -185
- package/dist/site/publication-authority-registry.json +11 -1
- package/dist/site/publication-registry.json +4 -4
- package/dist/site/release-provenance.json +3 -7
- package/dist/site/schemas/kfd-support-projection-v1.schema.json +106 -0
- package/dist/site/site-manifest.json +22 -38
- package/dist/site/workflow-registry.json +80 -35
- package/docs/MAP.md +8 -4
- package/docs/auditable-demo.md +2 -2
- package/docs/aws-us-elastic-runner-burst-plane.md +7 -59
- package/docs/cli-reference.md +15 -92
- package/docs/cli.md +14 -14
- package/docs/dev-alpha-candidate-patrol.md +3 -11
- package/docs/dev-delivery-warrant.md +28 -100
- package/docs/engineering-housekeeper.md +12 -4
- package/docs/getting-started.md +1 -1
- package/docs/install.md +5 -5
- package/docs/kfd-support.md +2 -7
- package/docs/lifecycle-protocol.md +2 -4
- package/docs/node-api-reference.md +414 -523
- package/docs/release-flow.md +31 -31
- package/docs/release-governance.md +16 -28
- package/docs/release-passport.md +2 -15
- package/docs/release-tail-contract.md +13 -6
- package/docs/release-tail-provider-plane.md +13 -19
- package/docs/release-train.md +4 -4
- package/docs/reusable-build-surface.md +14 -27
- package/docs/site-bundle-contract.md +1 -5
- package/docs/stable-candidate-patrol.md +7 -7
- package/docs/v4-canonical-contracts.md +92 -0
- package/docs/v4-delivery-warrant-read-candidate.md +73 -0
- package/docs/v4-delivery-warrant-semantic-diff.md +75 -0
- package/docs/v4-production-release.md +63 -0
- package/docs/v4-stage-capsule.md +193 -0
- package/docs/versioning.md +3 -3
- package/package.json +19 -17
- package/packages/core/adopter-delivery-gate.js +576 -0
- package/packages/core/adopter-delivery-json.js +66 -0
- package/packages/core/artifact-signing.js +0 -61
- package/packages/core/artifact-verification-envelope.js +5 -5
- package/packages/core/build-facts.js +12 -4
- package/packages/core/buildchain-agent-manuals.js +0 -2
- package/packages/core/buildchain-config.js +4 -69
- package/packages/core/buildchain-contract.js +232 -46
- package/packages/core/buildchain-kfd-claims.js +1 -1
- package/packages/core/channel-candidate.js +0 -8
- package/packages/core/channel-promotion-baseline.js +0 -52
- package/packages/core/controller-evidence.js +3 -4
- package/packages/core/dev-alpha-candidate-selection.js +2 -10
- package/packages/core/dev-delivery-warrant-cancellation.js +0 -1
- package/packages/core/dev-delivery-warrant-settlement.js +1 -5
- package/packages/core/dev-delivery-warrant.js +12 -52
- package/packages/core/diagnostics.js +3 -8
- package/packages/core/github-governance-authority.js +3 -1
- package/packages/core/kfd-adopter-category-driver.js +167 -0
- package/packages/core/kfd-adopter-manifest.js +47 -46
- package/packages/core/kfd-gate.js +15 -45
- package/packages/core/paper-agent-entry.js +7 -16
- package/packages/core/paper-fleet.js +2 -2
- package/packages/core/paper-repository.js +2 -3
- package/packages/core/paper-scaffold-content.js +2 -23
- package/packages/core/paper.js +11 -43
- package/packages/core/publication-reproducibility.js +4 -4
- package/packages/core/release-line-bootstrap.js +21 -8
- package/packages/core/release-passport-contract.js +5 -5
- package/packages/core/release-passport.js +20 -131
- package/packages/core/self-dogfood-version.js +48 -35
- package/packages/core/spawn-command.js +232 -8
- package/packages/core/v4-adopter-delivery-parity.js +219 -0
- package/packages/core/v4-canonical-contracts.js +284 -0
- package/packages/core/v4-delivery-warrant-fixture-runner.js +371 -0
- package/packages/core/v4-delivery-warrant-read-candidate.js +279 -0
- package/packages/core/v4-delivery-warrant-semantic-diff-gate.js +352 -0
- package/packages/core/v4-delivery-warrant-shadow-adapter.js +447 -0
- package/packages/core/v4-partial-mutation-recovery-qualification.js +395 -0
- package/packages/core/v4-platform-stage-checkpoints.js +471 -0
- package/packages/core/v4-provider-operation-journal.js +531 -0
- package/packages/core/v4-provider-readback-idempotency.js +394 -0
- package/packages/core/v4-release-activation-shadow.js +519 -0
- package/packages/core/v4-stable-publication-fence.js +357 -0
- package/packages/core/v4-stage-capsule-local-store.js +426 -0
- package/packages/core/v4-stage-capsule-qualification-campaign.js +512 -0
- package/packages/core/v4-stage-capsule-qualification.js +456 -0
- package/packages/core/v4-stage-capsule-resume-planner.js +397 -0
- package/packages/core/v4-stage-capsule-store.js +401 -0
- package/packages/core/v4-stage-capsule.js +319 -0
- package/scripts/assemble-self-publication-admission.mjs +1 -1
- package/scripts/audit-publication-control-plane.mjs +5 -5
- package/scripts/auditable-demo-bundle-verification.mjs +3 -2
- package/scripts/auditable-demo-platform.mjs +2 -2
- package/scripts/auditable-demo-renditions.mjs +1 -1
- package/scripts/auditable-demo.mjs +2 -2
- package/scripts/aws-macos-jit-controller-core.mjs +13 -346
- package/scripts/aws-macos-jit-controller-runtime.mjs +2 -210
- package/scripts/aws-macos-jit-controller.mjs +37 -275
- package/scripts/aws-macos-jit-core.mjs +3 -41
- package/scripts/aws-macos-jit.mjs +0 -12
- package/scripts/aws-windows-jit-campaign.mjs +2 -2
- package/scripts/aws-windows-jit-controller-core.mjs +1 -1
- package/scripts/aws-windows-jit-controller.mjs +3 -3
- package/scripts/build-contract-core.mjs +3 -8
- package/scripts/build-standalone-binary.mjs +3 -14
- package/scripts/buildchain-channel-router.mjs +4 -0
- package/scripts/buildchain-cli-help.mjs +7 -13
- package/scripts/buildchain-contract-lock.mjs +0 -6
- package/scripts/check-action-bundles.mjs +3 -4
- package/scripts/check-internal-architecture.mjs +7 -6
- package/scripts/check-inventory.mjs +30 -25
- package/scripts/check-v4-public-dogfood-contract.mjs +270 -0
- package/scripts/create-release-bundle.mjs +8 -4
- package/scripts/dev-alpha-candidate-patrol.mjs +1 -22
- package/scripts/dev-delivery-proof.mjs +2 -54
- package/scripts/dev-delivery-warrant.mjs +59 -77
- package/scripts/dev-pr-auto-merge.mjs +4 -30
- package/scripts/dev-pr-delivery-warrant.mjs +0 -55
- package/scripts/dispatch-artifact-signing-authority.mjs +7 -4
- package/scripts/generate-buildchain-kfd-witnesses.mjs +94 -88
- package/scripts/generate-channel-build-workflow.mjs +54 -24
- package/scripts/generate-channel-promotion-workflow.mjs +15 -6
- package/scripts/generate-site-bundle.mjs +5 -21
- package/scripts/git-fetch-process-tree.mjs +34 -1
- package/scripts/init-repo.mjs +64 -159
- package/scripts/inspect-artifact-signing-requests.mjs +0 -6
- package/scripts/locked-source-checkout.mjs +3 -4
- package/scripts/maintainability-metrics.mjs +8 -2
- package/scripts/npm-publish-dry-run.mjs +2 -2
- package/scripts/npm-publish-transaction.mjs +2 -2
- package/scripts/publication-commit-evidence.mjs +23 -69
- package/scripts/release-candidate-resolver.mjs +11 -17
- package/scripts/release-tail.mjs +3 -49
- package/scripts/resume-from-candidate-run.mjs +9 -123
- package/scripts/run-lifecycle-core.mjs +12 -13
- package/scripts/seal-artifact-signing-requests.mjs +17 -21
- package/scripts/site-capability-metadata.mjs +2 -7
- package/scripts/stable-candidate-qualification.mjs +10 -10
- package/scripts/v4-architecture.mjs +12 -2
- package/scripts/v4-bridge-bootstrap.mjs +141 -0
- package/scripts/v4-bridge-evidence.mjs +141 -0
- package/scripts/v4-host-adapter.mjs +182 -0
- package/scripts/v4-platform-stage-checkpoint-rehearsal.mjs +207 -0
- package/scripts/v4-stage-capsule-qualification.mjs +528 -0
- package/scripts/v4-stage-capsule-resume-rehearsal.mjs +57 -0
- package/scripts/v4-warrant-shadow-plan.mjs +601 -0
- package/scripts/verify-golden-path.mjs +5 -5
- package/scripts/web-surface-cloudfront-rewrite.mjs +15 -15
- package/scripts/web-surface-core.mjs +2 -8
- package/scripts/workflow-call-contract.mjs +5 -184
- package/contracts/fixtures/kfd-adopter-release-v1/kfd-4-perspective.json +0 -16
- package/contracts/fixtures/kfd-adopter-release-v1/kfd-4-replay.json +0 -57
- package/contracts/fixtures/next-development-transition-v1/anchored-manual-waiting.json +0 -47
- package/contracts/fixtures/next-development-transition-v1/semver-auto-planned.json +0 -47
- package/contracts/fixtures/next-development-transition-v1/version-model-cases.json +0 -40
- package/contracts/next-development-request-v1.schema.json +0 -66
- package/contracts/next-development-transition-v1.schema.json +0 -292
- package/contracts/publication-rehearsal-capsule-v1.schema.json +0 -173
- package/dist/site/schemas/publication-rehearsal-capsule-v1.schema.json +0 -269
- package/dist/site/schemas/release-tail-capabilities-v1.schema.json +0 -353
- package/dist/site/schemas/release-tail-provider-bindings-v1.schema.json +0 -94
- package/docs/next-development-transition.md +0 -119
- package/docs/publication-rehearsal.md +0 -94
- package/packages/core/buildchain-compatibility-proof.js +0 -631
- package/packages/core/dev-delivery-native-proof.js +0 -333
- package/packages/core/dev-delivery-warrant-shadow.js +0 -502
- package/packages/core/next-development-candidate-reservation.js +0 -186
- package/packages/core/next-development-controller.js +0 -726
- package/packages/core/next-development-projection.js +0 -288
- package/packages/core/next-development-transition.js +0 -738
- package/packages/core/publication-rehearsal-projection.js +0 -173
- package/packages/core/publication-rehearsal-runtime.js +0 -921
- package/scripts/aws-macos-jit-instance-rehydrate.mjs +0 -260
- package/scripts/aws-macos-jit-source-rebind.mjs +0 -724
- package/scripts/dev-delivery-native-run.mjs +0 -187
- package/scripts/dev-delivery-two-phase.mjs +0 -598
- package/scripts/generate-next-development-guidance.mjs +0 -49
- package/scripts/materialize-self-release-candidate-version.mjs +0 -137
- package/scripts/next-development-self-dogfood-harness.mjs +0 -409
- package/scripts/next-development-self-dogfood.mjs +0 -532
- package/scripts/next-development-transition.mjs +0 -47
- package/scripts/release-candidate-tail-reseal.mjs +0 -426
- package/templates/native-dev-delivery.yml +0 -82
package/scripts/release-tail.mjs
CHANGED
|
@@ -11,10 +11,6 @@ import {
|
|
|
11
11
|
writeReleaseTailTransaction,
|
|
12
12
|
} from "../packages/core/release-tail-provider-plane.js";
|
|
13
13
|
import { diagnoseLegacyReleaseTailHooks } from "../packages/core/release-tail-compatibility.js";
|
|
14
|
-
import {
|
|
15
|
-
executePublicationRehearsal,
|
|
16
|
-
publicationRehearsalDiagnostic,
|
|
17
|
-
} from "../packages/core/publication-rehearsal-runtime.js";
|
|
18
14
|
|
|
19
15
|
function flag(args, name, fallback = "") {
|
|
20
16
|
const index = args.indexOf(`--${name}`);
|
|
@@ -38,50 +34,8 @@ function output(value, filePath = "") {
|
|
|
38
34
|
process.stdout.write(`${JSON.stringify(value, null, 2)}\n`);
|
|
39
35
|
}
|
|
40
36
|
|
|
41
|
-
export
|
|
37
|
+
export function runReleaseTailCli(args = process.argv.slice(2)) {
|
|
42
38
|
const [mode = "status", ...options] = args;
|
|
43
|
-
if (mode === "rehearse") {
|
|
44
|
-
const capsulePath = flag(options, "capsule");
|
|
45
|
-
const capsuleRoot = flag(options, "capsule-root");
|
|
46
|
-
const statePath = flag(options, "state");
|
|
47
|
-
const evidencePath = flag(options, "evidence");
|
|
48
|
-
for (const [name, value] of Object.entries({
|
|
49
|
-
"--capsule": capsulePath,
|
|
50
|
-
"--capsule-root": capsuleRoot,
|
|
51
|
-
"--state": statePath,
|
|
52
|
-
"--evidence": evidencePath,
|
|
53
|
-
})) {
|
|
54
|
-
if (!value || !path.isAbsolute(value)) {
|
|
55
|
-
throw new Error(`${name} must be an explicit absolute path`);
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
const capsule = readJson(capsulePath, "--capsule");
|
|
59
|
-
const rehearsalMode = flag(options, "mode", "simulate");
|
|
60
|
-
if (!new Set(["simulate", "replay"]).has(rehearsalMode)) {
|
|
61
|
-
throw new Error("local rehearsal --mode must be simulate or replay");
|
|
62
|
-
}
|
|
63
|
-
const environment = flag(options, "environment-json")
|
|
64
|
-
? readJson(flag(options, "environment-json"), "--environment-json")
|
|
65
|
-
: {};
|
|
66
|
-
let result;
|
|
67
|
-
try {
|
|
68
|
-
result = await executePublicationRehearsal({
|
|
69
|
-
capsule,
|
|
70
|
-
capsuleRoot,
|
|
71
|
-
mode: rehearsalMode,
|
|
72
|
-
environment,
|
|
73
|
-
checkpoint: (transaction) =>
|
|
74
|
-
writeReleaseTailTransaction(statePath, transaction),
|
|
75
|
-
});
|
|
76
|
-
} catch (error) {
|
|
77
|
-
const diagnostic = publicationRehearsalDiagnostic(error, { capsule });
|
|
78
|
-
output(diagnostic, evidencePath);
|
|
79
|
-
throw error;
|
|
80
|
-
}
|
|
81
|
-
writeReleaseTailTransaction(statePath, result.transaction);
|
|
82
|
-
output(result.evidence, evidencePath);
|
|
83
|
-
return result;
|
|
84
|
-
}
|
|
85
39
|
if (mode === "plan") {
|
|
86
40
|
const plan = compileReleaseTailDeclaration(
|
|
87
41
|
readJson(flag(options, "declaration"), "--declaration"),
|
|
@@ -141,7 +95,7 @@ export async function runReleaseTailCli(args = process.argv.slice(2)) {
|
|
|
141
95
|
return report;
|
|
142
96
|
}
|
|
143
97
|
throw new Error(
|
|
144
|
-
"usage: buildchain release-tail <plan|init|status|verify|compat
|
|
98
|
+
"usage: buildchain release-tail <plan|init|status|verify|compat> [--declaration <json-or-path>] [--state <path>] [--hooks-json <json-or-path>] [--output <path>]",
|
|
145
99
|
);
|
|
146
100
|
}
|
|
147
101
|
|
|
@@ -151,7 +105,7 @@ if (
|
|
|
151
105
|
import.meta.url === pathToFileURL(process.argv[1]).href
|
|
152
106
|
) {
|
|
153
107
|
try {
|
|
154
|
-
|
|
108
|
+
runReleaseTailCli();
|
|
155
109
|
} catch (error) {
|
|
156
110
|
console.error(`release-tail: ${error.message}`);
|
|
157
111
|
process.exitCode = 1;
|
|
@@ -95,18 +95,12 @@ 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
|
-
|
|
104
98
|
function readOnlyJson(files, label) {
|
|
105
99
|
if (files.length !== 1) throw new Error(`expected exactly one ${label}, found ${files.length}`);
|
|
106
100
|
return JSON.parse(fs.readFileSync(files[0].absolutePath, "utf8"));
|
|
107
101
|
}
|
|
108
102
|
|
|
109
|
-
|
|
103
|
+
async function readExistingTransaction({ repoInfo, apiUrl, token, fetchImpl, version }) {
|
|
110
104
|
const stateRef = releaseTransactionStateRef(version);
|
|
111
105
|
const response = await githubJson({
|
|
112
106
|
apiUrl,
|
|
@@ -116,31 +110,10 @@ export async function readExistingTransaction({ repoInfo, apiUrl, token, fetchIm
|
|
|
116
110
|
path: `/repos/${repoInfo.owner}/${repoInfo.repo}/contents/state.json?ref=${encodeURIComponent(stateRef)}`,
|
|
117
111
|
});
|
|
118
112
|
if (!response) return undefined;
|
|
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`);
|
|
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`);
|
|
142
115
|
}
|
|
143
|
-
return JSON.parse(Buffer.from(String(
|
|
116
|
+
return JSON.parse(Buffer.from(String(response.content).replace(/\s/g, ""), "base64").toString("utf8"));
|
|
144
117
|
}
|
|
145
118
|
|
|
146
119
|
function outputPath(filePath) {
|
|
@@ -207,7 +180,6 @@ function candidateArtifactNames({ passport, selected, artifacts, artifactPattern
|
|
|
207
180
|
|
|
208
181
|
export function normalizePlatformManifests(downloads, passport) {
|
|
209
182
|
const manifests = [];
|
|
210
|
-
const paths = [];
|
|
211
183
|
const evidenceByArtifact = new Map();
|
|
212
184
|
const platformById = new Map((passport.platformMatrix || []).map((entry) => [String(entry.platformId || ""), entry]));
|
|
213
185
|
const seenPlatformIds = new Set();
|
|
@@ -236,7 +208,6 @@ export function normalizePlatformManifests(downloads, passport) {
|
|
|
236
208
|
manifest.artifactName = expectedPlatform.artifactName;
|
|
237
209
|
seenPlatformIds.add(platformId);
|
|
238
210
|
manifests.push(manifest);
|
|
239
|
-
paths.push(file.absolutePath);
|
|
240
211
|
addEvidence(manifest.artifactName, download.record.files);
|
|
241
212
|
}
|
|
242
213
|
if (String(download.artifact.name).includes("-diagnostics-")) {
|
|
@@ -251,7 +222,7 @@ export function normalizePlatformManifests(downloads, passport) {
|
|
|
251
222
|
artifactName,
|
|
252
223
|
files: [...files.values()].sort((left, right) => left.path.localeCompare(right.path)),
|
|
253
224
|
}));
|
|
254
|
-
return { manifests,
|
|
225
|
+
return { manifests, evidence };
|
|
255
226
|
}
|
|
256
227
|
|
|
257
228
|
function normalizeControllerReceipts(downloads, passport) {
|
|
@@ -297,53 +268,16 @@ export function createRecoveredPublicationCandidate({
|
|
|
297
268
|
return { ...payload, candidateDigest: publicationArtifactCandidateDigest(payload) };
|
|
298
269
|
}
|
|
299
270
|
|
|
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
|
-
|
|
329
271
|
export function createRecoveredPublication({ downloads, bundleRoot, repository, passport, candidateRuntimeSha, publishArtifactKind, publishPackageMain, releasePatterns, platformManifests }) {
|
|
330
272
|
const allFiles = downloads.flatMap((download) => download.files.map((file) => ({
|
|
331
273
|
path: path.relative(bundleRoot, file.absolutePath).split(path.sep).join("/"),
|
|
332
274
|
size: file.size,
|
|
333
275
|
sha256: file.sha256.replace(/^sha256:/, ""),
|
|
334
276
|
absolutePath: file.absolutePath,
|
|
335
|
-
artifactName: String(download.artifact?.name || ""),
|
|
336
277
|
}))).sort((left, right) => left.path.localeCompare(right.path));
|
|
337
278
|
const kind = String(publishArtifactKind || "npm");
|
|
338
279
|
const releaseMatchers = splitPatterns(releasePatterns).map(patternMatcher);
|
|
339
|
-
const
|
|
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)))));
|
|
280
|
+
const releaseAssets = allFiles.filter((file) => releaseMatchers.some((matcher) => matcher.test(path.basename(file.path))));
|
|
347
281
|
if (kind !== "npm") {
|
|
348
282
|
createRecoveredPublicationCandidate({ allFiles, repository, passport, candidateRuntimeSha });
|
|
349
283
|
const version = String(passport.target?.version || "").trim();
|
|
@@ -433,42 +367,6 @@ async function recoverCandidateEvidence({
|
|
|
433
367
|
};
|
|
434
368
|
}
|
|
435
369
|
|
|
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
|
-
|
|
472
370
|
async function resolveTargetAdvance({ observedTargetSha, targetSha, transactionId, existingTransaction, repoInfo, apiUrl, token, fetchImpl }) {
|
|
473
371
|
if (observedTargetSha === targetSha || !transactionId || existingTransaction?.id !== transactionId) return undefined;
|
|
474
372
|
const comparison = await githubJson({ apiUrl, token, fetchImpl, path: `/repos/${repoInfo.owner}/${repoInfo.repo}/compare/${targetSha}...${observedTargetSha}` });
|
|
@@ -596,16 +494,7 @@ export async function resumeFromCandidateRun({
|
|
|
596
494
|
if (publication.manifest) fs.writeFileSync(sealedManifestPath, `${JSON.stringify(publication.manifest, null, 2)}\n`);
|
|
597
495
|
const publishRequiredArtifacts = publication.publishRequiredArtifacts;
|
|
598
496
|
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 });
|
|
604
497
|
const tarballs = publication.npmArtifacts.map((entry) => outputPath(entry.file.absolutePath));
|
|
605
|
-
const githubArtifactAttestationPolicies = recoveredArtifactPathsByBasename(
|
|
606
|
-
downloads,
|
|
607
|
-
"github-artifact-attestation-policy.json",
|
|
608
|
-
);
|
|
609
498
|
return {
|
|
610
499
|
enabled: true,
|
|
611
500
|
action: "reused",
|
|
@@ -618,11 +507,10 @@ export async function resumeFromCandidateRun({
|
|
|
618
507
|
receipt: recovery.receipt,
|
|
619
508
|
publishRequiredArtifacts,
|
|
620
509
|
paths: {
|
|
621
|
-
passport: outputPath(
|
|
510
|
+
passport: outputPath(initialDownloads[0].files.find((file) => path.basename(file.path) === "release-candidate-passport.json").absolutePath),
|
|
622
511
|
buildSummary: outputPath(initialDownloads[1].files.find((file) => path.basename(file.path) === "build-summary.json").absolutePath),
|
|
623
|
-
payloads: outputPath(
|
|
624
|
-
platformManifests:
|
|
625
|
-
githubArtifactAttestationPolicies,
|
|
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))),
|
|
626
514
|
npmTarballs: tarballs,
|
|
627
515
|
releaseAssets: publication.releaseAssets.map((asset) => outputPath(asset.absolutePath)),
|
|
628
516
|
publishRequiredArtifacts: outputPath(requiredArtifactsPath),
|
|
@@ -672,8 +560,6 @@ export async function resumeFromCandidateRunCli() {
|
|
|
672
560
|
"release-candidate-payload-artifacts": result.artifacts.payloads.join(","),
|
|
673
561
|
"release-candidate-payload-dir": result.paths.payloads,
|
|
674
562
|
"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),
|
|
677
563
|
"release-candidate-npm-tarball-paths": result.paths.npmTarballs.join(","),
|
|
678
564
|
"release-candidate-github-release-artifact-paths": result.paths.releaseAssets.join("\n"),
|
|
679
565
|
"publish-required-artifacts-json": JSON.stringify(result.publishRequiredArtifacts),
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import crypto from "node:crypto";
|
|
2
|
-
import { execFileSync
|
|
2
|
+
import { execFileSync } from "node:child_process";
|
|
3
3
|
import fs from "node:fs";
|
|
4
4
|
import os from "node:os";
|
|
5
5
|
import path from "node:path";
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
normalizeLifecycleStage,
|
|
10
10
|
runLifecycleStage,
|
|
11
11
|
} from "../packages/core/buildchain-config.js";
|
|
12
|
+
import { runProcessTreeCommandSync, runShellCommandSync } from "../packages/core/spawn-command.js";
|
|
12
13
|
import {
|
|
13
14
|
createBuildchainLogger,
|
|
14
15
|
readBuildchainLogEvents,
|
|
@@ -201,7 +202,7 @@ function shellCommandArgs(command, shell) {
|
|
|
201
202
|
return [shell, "-c", command];
|
|
202
203
|
}
|
|
203
204
|
if (process.platform === "win32") {
|
|
204
|
-
return [process.env.ComSpec || "cmd.exe", "/d", "/s", "/c", command];
|
|
205
|
+
return [process.env.ComSpec || "cmd.exe", "/d", "/s", "/c", `"${command}"`];
|
|
205
206
|
}
|
|
206
207
|
return [process.env.SHELL || "/bin/sh", "-c", command];
|
|
207
208
|
}
|
|
@@ -244,16 +245,14 @@ function executeSampledShellCommand({
|
|
|
244
245
|
args.push("--requested-parallelism", String(Number(requestedParallelism)));
|
|
245
246
|
}
|
|
246
247
|
args.push("--", ...shellCommandArgs(command, shell));
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
error.status = result.status ?? error.status ?? 1;
|
|
256
|
-
error.signal = result.signal || error.signal || "";
|
|
248
|
+
try {
|
|
249
|
+
runProcessTreeCommandSync(process.execPath, args, {
|
|
250
|
+
cwd,
|
|
251
|
+
env,
|
|
252
|
+
stdio: "inherit",
|
|
253
|
+
timeout,
|
|
254
|
+
});
|
|
255
|
+
} catch (error) {
|
|
257
256
|
attachProcessSampleFailureEvidence(error, processSummaryPath);
|
|
258
257
|
throw error;
|
|
259
258
|
}
|
|
@@ -565,7 +564,7 @@ export function runLifecycle({
|
|
|
565
564
|
timeout: effectiveCommandTimeoutMinutes ? effectiveCommandTimeoutMinutes * 60_000 : undefined,
|
|
566
565
|
});
|
|
567
566
|
} else {
|
|
568
|
-
|
|
567
|
+
runShellCommandSync(command, {
|
|
569
568
|
cwd: resolvedCwd,
|
|
570
569
|
env: commandEnv,
|
|
571
570
|
shell: commandShell,
|
|
@@ -162,10 +162,11 @@ function inferKind(subjectPath, declaredKind) {
|
|
|
162
162
|
return "binary";
|
|
163
163
|
}
|
|
164
164
|
|
|
165
|
-
function run(command, args) {
|
|
165
|
+
function run(command, args, options = {}) {
|
|
166
166
|
const result = spawnSync(command, args, {
|
|
167
167
|
encoding: "utf8",
|
|
168
168
|
stdio: ["ignore", "pipe", "pipe"],
|
|
169
|
+
...options,
|
|
169
170
|
});
|
|
170
171
|
if (result.error || result.status !== 0) {
|
|
171
172
|
throw (
|
|
@@ -205,13 +206,17 @@ function archiveSubject({ subjectPath, outputRoot, id, kind, platform }) {
|
|
|
205
206
|
format = "ditto-zip";
|
|
206
207
|
} else {
|
|
207
208
|
archivePath = path.join(artifactRoot, "subject.tar");
|
|
208
|
-
run(
|
|
209
|
-
"
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
209
|
+
run(
|
|
210
|
+
"tar",
|
|
211
|
+
[
|
|
212
|
+
"-cf",
|
|
213
|
+
path.basename(archivePath),
|
|
214
|
+
"-C",
|
|
215
|
+
path.dirname(subjectPath),
|
|
216
|
+
path.basename(subjectPath),
|
|
217
|
+
],
|
|
218
|
+
{ cwd: artifactRoot },
|
|
219
|
+
);
|
|
215
220
|
format = "tar";
|
|
216
221
|
}
|
|
217
222
|
return {
|
|
@@ -275,19 +280,16 @@ export function sealArtifactSigningRequests({
|
|
|
275
280
|
sourceTreeSha = process.env.BUILDCHAIN_SOURCE_TREE_SHA,
|
|
276
281
|
runtimeSha = process.env.BUILDCHAIN_RUNTIME_SHA,
|
|
277
282
|
platformId = process.env.BUILDCHAIN_PLATFORM_ID,
|
|
278
|
-
requestsEnabled = process.env.BUILDCHAIN_SIGNING_REQUESTS_ENABLED !== "false",
|
|
279
283
|
} = {}) {
|
|
280
284
|
const resolvedWorkspace = path.resolve(workspace);
|
|
281
285
|
const resolvedCwd = path.resolve(resolvedWorkspace, cwd);
|
|
282
286
|
assertInside(resolvedWorkspace, resolvedCwd, "signing working directory");
|
|
283
287
|
const loaded = loadBuildchainConfig(resolvedCwd);
|
|
284
288
|
const declarations = loaded?.config?.signing?.artifacts || [];
|
|
285
|
-
const selected =
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
)
|
|
290
|
-
: [];
|
|
289
|
+
const selected = declarations.filter(
|
|
290
|
+
(entry) =>
|
|
291
|
+
entry.platforms.length === 0 || entry.platforms.includes(platformId),
|
|
292
|
+
);
|
|
291
293
|
const resolvedOutputRoot = path.resolve(resolvedWorkspace, outputRoot);
|
|
292
294
|
assertInside(resolvedWorkspace, resolvedOutputRoot, "signing request output");
|
|
293
295
|
if (selected.length === 0) {
|
|
@@ -379,12 +381,6 @@ export function sealArtifactSigningRequests({
|
|
|
379
381
|
signature: {
|
|
380
382
|
profile: declaration.profile,
|
|
381
383
|
required: declaration.required,
|
|
382
|
-
...(declaration.entitlementsProfile !== "none"
|
|
383
|
-
? {
|
|
384
|
-
entitlementsProfile: declaration.entitlementsProfile,
|
|
385
|
-
entitlementsPaths: declaration.entitlementsPaths,
|
|
386
|
-
}
|
|
387
|
-
: {}),
|
|
388
384
|
},
|
|
389
385
|
});
|
|
390
386
|
const check = validateArtifactSigningRequest(request);
|
|
@@ -84,7 +84,7 @@ export function cliCommandMeta(id) {
|
|
|
84
84
|
"kfd-7-schema": { group: "kfd-trust", purpose: "Print the default KFD-7 schema exposed by the KFD package standards metadata." },
|
|
85
85
|
"kfd-7-gate": { group: "kfd-trust", purpose: "Evaluate a source-bound KFD-7 Domain Profile, evidence obligations, and independent review." },
|
|
86
86
|
"kfd-7-verify": { group: "kfd-trust", purpose: "Verify a retained KFD-7 product-gate result without widening product support." },
|
|
87
|
-
"kfd-support": { group: "kfd-trust", purpose: "Project and verify a
|
|
87
|
+
"kfd-support": { group: "kfd-trust", purpose: "Project and verify a product-owned KFD-1 through KFD-13 support matrix against KFD-4/5/7 gates." },
|
|
88
88
|
"kfd-aggregate": { group: "kfd-trust", purpose: "Return a product KFD view that combines own KFD status with upstream KFD aggregate facts." },
|
|
89
89
|
"kfd-upstream": { group: "kfd-trust", purpose: "Inspect KFD upstream aggregate command families." },
|
|
90
90
|
"kfd-upstream-check": { group: "kfd-trust", purpose: "Validate a KFD upstream aggregate document and fail closed on missing evidence." },
|
|
@@ -139,7 +139,7 @@ export function cliCommandMeta(id) {
|
|
|
139
139
|
"release-line-open": { group: "governance-versioning", purpose: "Plan or write the initial version-state commit for a new minor release line." },
|
|
140
140
|
"release-governance": { group: "governance-versioning", purpose: "Reconcile a managed branch's Buildchain aggregate check to an already-tested pull request SHA." },
|
|
141
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,
|
|
142
|
+
"release-tail": { group: "release-passport-trust", purpose: "Plan, initialize, resume, and verify one declarative provider-owned release-tail transaction." },
|
|
143
143
|
"release-transaction": { group: "release-passport-trust", purpose: "Inspect, recover, finalize, or abort durable release transactions." },
|
|
144
144
|
sample: { group: "observability-diagnostics", purpose: "Inspect sampler command families." },
|
|
145
145
|
"sample-process-tree": { group: "observability-diagnostics", purpose: "Sample process-tree diagnostics for a wrapped command." },
|
|
@@ -203,17 +203,12 @@ export function nodeApiMeta(exportName) {
|
|
|
203
203
|
"./release-candidate": { group: "reusable-build", summary: "PR-stage release-candidate artifact, passport, and promote-only resolver APIs." },
|
|
204
204
|
"./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." },
|
|
205
205
|
"./release-train": { group: "governance-versioning", summary: "Frozen Release Cut identity, rooted Release Train transitions, Dev observations, supersession, replay, and legacy read compatibility APIs." },
|
|
206
|
-
"./next-development-transition": { group: "governance-versioning", summary: "Provider-neutral completed-Alpha preservation and rooted next-development state, version-model, idempotency, and local materialization APIs." },
|
|
207
|
-
"./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." },
|
|
208
|
-
"./next-development-projection": { group: "governance-versioning", summary: "Canonical generated config, Agent, and manual projections for the next-development transition contract." },
|
|
209
206
|
"./stable-candidate-ledger": { group: "governance-versioning", summary: "Immutable alpha candidate ledger, qualification, revocation, selection, and exact stable source-lock APIs." },
|
|
210
207
|
"./release-propagation": { group: "site-and-propagation", summary: "Release propagation graph, plan, and exact upstream lock APIs." },
|
|
211
208
|
"./release-activation-transaction": { group: "release-passport-trust", summary: "Ordered cross-repository activation, exact receipt-set binding, retry, abort, rollback, and shadow-rehearsal APIs." },
|
|
212
209
|
"./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." },
|
|
213
210
|
"./release-tail-provider-adapters": { group: "release-passport-trust", summary: "Buildchain-owned GitHub Release, signed-channel, activation, and released-evidence provider adapters." },
|
|
214
211
|
"./release-tail-compatibility": { group: "release-passport-trust", summary: "Bounded v3 release-hook compatibility diagnostics that reject new executable release-tail inputs." },
|
|
215
|
-
"./publication-rehearsal-runtime": { group: "release-passport-trust", summary: "Content-addressed local, replay, and provider-recording publication rehearsal over the shared release-tail core." },
|
|
216
|
-
"./publication-rehearsal-projection": { group: "release-passport-trust", summary: "Canonical generated config, workflow, and Agent projections for release local constructibility." },
|
|
217
212
|
"./release-line-bootstrap": { group: "governance-versioning", summary: "Semver release-line bootstrap planning and version-state APIs." },
|
|
218
213
|
"./buildchain-contract": { group: "governance-versioning", summary: "Runtime contract world and compatibility digest APIs for floating-ref drift checks." },
|
|
219
214
|
"./controller-evidence": { group: "reusable-build", summary: "Project-independent controller descriptors, source/runtime-bound plans, receipts, aggregates, and validation APIs." },
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import { validateHostedSelfDogfoodEvidence } from "./next-development-self-dogfood.mjs";
|
|
4
|
-
|
|
5
3
|
const DEFAULTS = {
|
|
6
4
|
buildWorkflowFile: "build-surface-fixture.yml",
|
|
7
5
|
buildWorkflowName: "Build Surface Fixture",
|
|
@@ -50,16 +48,18 @@ export function resolveStableCandidateQualificationCandidate({ eventName, inputC
|
|
|
50
48
|
if (text(eventName) !== "workflow_run") {
|
|
51
49
|
throw new Error(`qualification candidate resolver does not admit event ${eventName || "<empty>"}`);
|
|
52
50
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
evidence
|
|
56
|
-
|
|
57
|
-
|
|
51
|
+
const evidence = selfDogfoodEvidence;
|
|
52
|
+
if (
|
|
53
|
+
evidence?.contract !== "kungfu-buildchain-alpha-self-dogfood"
|
|
54
|
+
|| evidence?.status !== "passed"
|
|
55
|
+
|| evidence?.observed?.alpha?.ref !== "v4-alpha"
|
|
56
|
+
) {
|
|
57
|
+
throw new Error("self-dogfood evidence is not a passing v4-alpha observation");
|
|
58
58
|
}
|
|
59
|
-
const observedSha = optionalSha(evidence.observed.alpha.sha, "observed
|
|
60
|
-
const expectedSha = optionalSha(evidence.observed.alpha.expectedSha, "expected
|
|
59
|
+
const observedSha = optionalSha(evidence.observed.alpha.sha, "observed v4-alpha SHA");
|
|
60
|
+
const expectedSha = optionalSha(evidence.observed.alpha.expectedSha, "expected v4-alpha SHA");
|
|
61
61
|
if (!observedSha || observedSha !== expectedSha) {
|
|
62
|
-
throw new Error("self-dogfood evidence does not bind observed and expected
|
|
62
|
+
throw new Error("self-dogfood evidence does not bind observed and expected v4-alpha SHAs");
|
|
63
63
|
}
|
|
64
64
|
return observedSha;
|
|
65
65
|
}
|
|
@@ -238,6 +238,8 @@ function validateCapabilities(capabilities, inventory, issues) {
|
|
|
238
238
|
}
|
|
239
239
|
if (!MIGRATION_PHASES.has(capability?.migrationPhase))
|
|
240
240
|
issues.push(`${capability?.id} has invalid migrationPhase`);
|
|
241
|
+
if (capability?.migrationPhase !== "legacy-retired")
|
|
242
|
+
issues.push(`${capability?.id} must retire its legacy v3 authority`);
|
|
241
243
|
}
|
|
242
244
|
for (const id of inventoryById.keys()) {
|
|
243
245
|
if (!(capabilities || []).some((entry) => entry.sourceInventoryId === id))
|
|
@@ -279,8 +281,12 @@ function validateStateMachines(machines, capabilityIds, issues) {
|
|
|
279
281
|
`${coordinate}.writer.runtime`,
|
|
280
282
|
issues,
|
|
281
283
|
);
|
|
284
|
+
if (machine?.writer?.runtime !== "typescript-v4")
|
|
285
|
+
issues.push(`${machine?.id} writer.runtime must be typescript-v4`);
|
|
282
286
|
if (!MIGRATION_PHASES.has(machine?.migrationPhase))
|
|
283
287
|
issues.push(`${machine?.id} has invalid migrationPhase`);
|
|
288
|
+
if (machine?.migrationPhase !== "legacy-retired")
|
|
289
|
+
issues.push(`${machine?.id} must retire its legacy v3 writer`);
|
|
284
290
|
for (const field of [
|
|
285
291
|
"undeclaredStates",
|
|
286
292
|
"undeclaredEvents",
|
|
@@ -302,8 +308,12 @@ function validateManifest({ manifest, inventory, bootstrap, ledger }) {
|
|
|
302
308
|
issues.push("manifest contract is invalid");
|
|
303
309
|
if (manifest?.releaseLine?.branch !== "dev/v4/v4.0")
|
|
304
310
|
issues.push("releaseLine.branch must be dev/v4/v4.0");
|
|
305
|
-
if (manifest?.releaseLine?.
|
|
306
|
-
issues.push("releaseLine.
|
|
311
|
+
if (manifest?.releaseLine?.productionAuthority !== "v4-native")
|
|
312
|
+
issues.push("releaseLine.productionAuthority must be v4-native");
|
|
313
|
+
if (manifest?.releaseLine?.productionFallback !== null)
|
|
314
|
+
issues.push("releaseLine.productionFallback must be null after cutover");
|
|
315
|
+
if (manifest?.releaseLine?.rollbackRef !== "release/v3/v3.0")
|
|
316
|
+
issues.push("releaseLine.rollbackRef must retain release/v3/v3.0");
|
|
307
317
|
if (
|
|
308
318
|
manifest?.releaseLine?.qualificationMode !==
|
|
309
319
|
"exact-n-minus-one-git-revision"
|