@kungfu-tech/buildchain 3.0.9-alpha.9 → 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 -10
- 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 -4
- package/dist/site/artifact-schemas.json +0 -8
- package/dist/site/buildchain-contract.json +103 -397
- package/dist/site/buildchain-site.json +302 -386
- package/dist/site/capability-registry.json +9 -11
- package/dist/site/cli-registry.json +8 -53
- package/dist/site/controller-registry.json +48 -8
- package/dist/site/kfd-claims.json +129 -167
- package/dist/site/kfd-upstream-aggregate.json +9 -9
- package/dist/site/manual-registry.json +18 -49
- package/dist/site/node-api-registry.json +4345 -7345
- package/dist/site/page-registry.json +278 -346
- package/dist/site/public-surface-audit.json +85 -404
- package/dist/site/publication-authority-registry.json +11 -1
- package/dist/site/publication-registry.json +4 -4
- package/dist/site/release-provenance.json +3 -9
- 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 +78 -35
- package/docs/MAP.md +8 -5
- package/docs/auditable-demo.md +2 -2
- package/docs/aws-us-elastic-runner-burst-plane.md +7 -59
- package/docs/cli-reference.md +15 -213
- package/docs/cli.md +14 -14
- package/docs/dev-alpha-candidate-patrol.md +3 -11
- package/docs/dev-delivery-warrant.md +29 -194
- 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 -554
- 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 -5
- package/package.json +19 -19
- 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-channel-identity.js +3 -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 +20 -67
- package/packages/core/dev-delivery-warrant.js +50 -138
- 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 -16
- 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 -64
- package/scripts/dev-delivery-warrant.mjs +61 -86
- 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 +8 -27
- 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 +3 -20
- 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/dev-delivery-authority-v2.schema.json +0 -253
- 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/dev-delivery-authority-v2.schema.json +0 -442
- 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/dev-delivery-qualification-landing-adr.md +0 -137
- 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-authority.js +0 -996
- package/packages/core/dev-delivery-native-proof.js +0 -418
- 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-authority.mjs +0 -368
- package/scripts/dev-delivery-native-run.mjs +0 -235
- package/scripts/dev-delivery-two-phase-resume.mjs +0 -90
- package/scripts/dev-delivery-two-phase.mjs +0 -577
- 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 -86
|
@@ -2,12 +2,10 @@ import { devDeliveryClone as clone, devDeliveryContentRoot, devDeliveryExactRoot
|
|
|
2
2
|
import { chainedDevDeliveryAttemptInput, createDevDeliveryCandidateIdentity, validateDevDeliveryCandidateChain } from "./dev-delivery-candidate-identity.js";
|
|
3
3
|
import { DEV_DELIVERY_CANCELLATION_RECEIPT_SCHEMA, createCancelQueuedDevDeliveryCandidate } from "./dev-delivery-warrant-cancellation.js";
|
|
4
4
|
import { DEV_DELIVERY_SETTLEMENT_RECEIPT_SCHEMA, createDevDeliveryTerminalSettler } from "./dev-delivery-warrant-settlement.js";
|
|
5
|
-
import { createDevDeliveryWarrantQualifier } from "./dev-delivery-native-proof.js";
|
|
6
5
|
import { compareReleaseBlockerPriority, normalizeReleaseBlockerPriorityClaim } from "./release-blocker-priority.js";
|
|
7
6
|
export { devDeliveryContentRoot } from "./dev-delivery-common.js";
|
|
8
7
|
export { RELEASE_BLOCKER_PRIORITY_CLAIM_SCHEMA, createReleaseBlockerPriorityClaim } from "./release-blocker-priority.js";
|
|
9
8
|
export { SOURCE_QUALIFICATION_PROOF_SCHEMA, PROJECT_CUT_REPLAY_PROOF_SCHEMA, INTEGRATION_DELIVERY_PROOF_SCHEMA, classifyDevDeliveryDelta, createIntegrationDeliveryProof, createProjectCutReplayPlan, createProjectCutReplayProof, createSourceQualificationProof, verifyIntegrationDeliveryProof, verifyProjectCutReplayProof, verifySourceQualificationProof } from "./dev-delivery-proof.js";
|
|
10
|
-
export { DEV_DELIVERY_QUALIFICATION_RECEIPT_SCHEMA, NATIVE_QUALIFICATION_PROOF_SCHEMA, NATIVE_PROOF_REUSE_DECISION_SCHEMA, NATIVE_PROOF_BASE_DELTA_SCHEMA, createNativeProofBaseDelta, createNativeProofReuseDecision, createNativeQualificationProof, verifyNativeProofReuseDecision, verifyNativeQualificationProof } from "./dev-delivery-native-proof.js";
|
|
11
9
|
export { DEV_DELIVERY_CANCELLATION_RECEIPT_SCHEMA };
|
|
12
10
|
export const DEV_DELIVERY_QUEUE_CONTRACT = "kungfu-buildchain-dev-delivery-warrant-queue";
|
|
13
11
|
export const DEV_DELIVERY_WARRANT_SCHEMA = "kungfu.buildchain.dev-delivery-warrant/v1";
|
|
@@ -23,14 +21,7 @@ export const DEV_DELIVERY_PRIORITIES = Object.freeze({
|
|
|
23
21
|
|
|
24
22
|
export const DEV_DELIVERY_CLASSES = Object.freeze(["non-native-fast", "native-proof-required", "cross-platform", "release"]);
|
|
25
23
|
|
|
26
|
-
const TERMINAL_STATES = new Set(["merged", "terminal-failure", "dequeued", "cancelled"
|
|
27
|
-
const TERMINAL_CLASSES = Object.freeze({
|
|
28
|
-
merged: "authoritative-completion",
|
|
29
|
-
"terminal-failure": "authoritative-failure",
|
|
30
|
-
cancelled: "authoritative-cancellation",
|
|
31
|
-
superseded: "authoritative-supersession",
|
|
32
|
-
dequeued: "transient-dequeue",
|
|
33
|
-
});
|
|
24
|
+
const TERMINAL_STATES = new Set(["merged", "terminal-failure", "dequeued", "cancelled"]);
|
|
34
25
|
function nonNegativeInteger(value, label, fallback = 0) {
|
|
35
26
|
const parsed = Number(value ?? fallback);
|
|
36
27
|
if (!Number.isInteger(parsed) || parsed < 0) throw new Error(`${label} must be a non-negative integer`);
|
|
@@ -68,7 +59,7 @@ function normalizeCandidate(input, expected) {
|
|
|
68
59
|
throw new Error(`candidateId mismatch for PR #${identity.pullRequestNumber}`);
|
|
69
60
|
}
|
|
70
61
|
const status = text(input.status || "queued");
|
|
71
|
-
if (!["queued", "selected", "
|
|
62
|
+
if (!["queued", "selected", "proving", "waiting", "blocked", ...TERMINAL_STATES].includes(status)) {
|
|
72
63
|
throw new Error(`unsupported candidate status ${status || "<empty>"}`);
|
|
73
64
|
}
|
|
74
65
|
const candidate = {
|
|
@@ -80,14 +71,6 @@ function normalizeCandidate(input, expected) {
|
|
|
80
71
|
closureRoot: exactRoot(input.closureRoot, "closureRoot"),
|
|
81
72
|
dependencyRoot: exactRoot(input.dependencyRoot, "dependencyRoot"),
|
|
82
73
|
toolchainRoot: exactRoot(input.toolchainRoot, "toolchainRoot"),
|
|
83
|
-
...(input.environmentRoot
|
|
84
|
-
? { environmentRoot: exactRoot(input.environmentRoot, "environmentRoot") }
|
|
85
|
-
: {}),
|
|
86
|
-
...(Object.hasOwn(input, "sourceWorkflowRunId")
|
|
87
|
-
? {
|
|
88
|
-
sourceWorkflowRunId: nonNegativeInteger(input.sourceWorkflowRunId, "candidate sourceWorkflowRunId", 0),
|
|
89
|
-
}
|
|
90
|
-
: {}),
|
|
91
74
|
priority: priority(input.priority),
|
|
92
75
|
enqueuedAt: timestamp(input.enqueuedAt, "candidate enqueuedAt"),
|
|
93
76
|
updatedAt: timestamp(input.updatedAt || input.enqueuedAt, "candidate updatedAt"),
|
|
@@ -96,10 +79,6 @@ function normalizeCandidate(input, expected) {
|
|
|
96
79
|
status,
|
|
97
80
|
terminal: input.terminal || null,
|
|
98
81
|
};
|
|
99
|
-
if (Object.hasOwn(input, "affectedPaths")) {
|
|
100
|
-
if (!Array.isArray(input.affectedPaths)) throw new Error("candidate affectedPaths must be an array");
|
|
101
|
-
candidate.affectedPaths = [...new Set(input.affectedPaths.map(text).filter(Boolean))].sort();
|
|
102
|
-
}
|
|
103
82
|
if (Object.hasOwn(input, "releaseBlockerPriority")) candidate.releaseBlockerPriority = normalizeReleaseBlockerPriorityClaim(input.releaseBlockerPriority, candidate, expected);
|
|
104
83
|
return candidate;
|
|
105
84
|
}
|
|
@@ -160,20 +139,12 @@ export function normalizeDevDeliveryQueue(input, expected = {}) {
|
|
|
160
139
|
warrant.generation = positiveInteger(warrant.generation, "Warrant generation");
|
|
161
140
|
warrant.issuedAt = timestamp(warrant.issuedAt, "Warrant issuedAt");
|
|
162
141
|
warrant.expiresAt = timestamp(warrant.expiresAt, "Warrant expiresAt");
|
|
163
|
-
const
|
|
164
|
-
if (!["provisional", "qualified"].includes(warrantPhase)) throw new Error("active Warrant phase is unsupported");
|
|
165
|
-
if (Object.hasOwn(warrant, "phase")) warrant.phase = warrantPhase;
|
|
166
|
-
if (warrantPhase === "qualified") {
|
|
167
|
-
if (warrant.nativeProofRoot) warrant.nativeProofRoot = exactRoot(warrant.nativeProofRoot, "Warrant nativeProofRoot");
|
|
168
|
-
if (warrant.nativeProofReuseRoot) warrant.nativeProofReuseRoot = exactRoot(warrant.nativeProofReuseRoot, "Warrant nativeProofReuseRoot");
|
|
169
|
-
if (warrant.qualifiedAt) warrant.qualifiedAt = timestamp(warrant.qualifiedAt, "Warrant qualifiedAt");
|
|
170
|
-
}
|
|
171
|
-
const activeCandidates = queue.candidates.filter((candidate) => ["selected", "provisional", "proving", "qualified", "waiting", "blocked"].includes(candidate.status));
|
|
142
|
+
const activeCandidates = queue.candidates.filter((candidate) => ["selected", "proving", "waiting", "blocked"].includes(candidate.status));
|
|
172
143
|
if (activeCandidates.length !== 1 || activeCandidates[0].candidateId !== warrant.candidateId) {
|
|
173
144
|
throw new Error("exactly one active candidate must match the active Warrant");
|
|
174
145
|
}
|
|
175
146
|
if (warrant.releaseBlockerPriority?.claimRoot !== activeCandidates[0].releaseBlockerPriority?.claimRoot) throw new Error("active Warrant release-blocker priority drift");
|
|
176
|
-
} else if (queue.candidates.some((candidate) => ["selected", "
|
|
147
|
+
} else if (queue.candidates.some((candidate) => ["selected", "proving", "waiting", "blocked"].includes(candidate.status))) {
|
|
177
148
|
throw new Error("active candidate exists without an active Warrant");
|
|
178
149
|
}
|
|
179
150
|
const rooted = withQueueRoot(queue);
|
|
@@ -211,8 +182,7 @@ function submissionReceipt({ before, after, candidate, action, now }) {
|
|
|
211
182
|
planRoot: candidate.planRoot,
|
|
212
183
|
closureRoot: candidate.closureRoot,
|
|
213
184
|
dependencyRoot: candidate.dependencyRoot,
|
|
214
|
-
toolchainRoot: candidate.toolchainRoot,
|
|
215
|
-
...(Object.hasOwn(candidate, "affectedPaths") ? { affectedPaths: candidate.affectedPaths } : {}),
|
|
185
|
+
toolchainRoot: candidate.toolchainRoot,
|
|
216
186
|
sourceWorkflowRunId: candidate.sourceWorkflowRunId,
|
|
217
187
|
...(Object.hasOwn(candidate, "releaseBlockerPriority") ? { releaseBlockerPriority: candidate.releaseBlockerPriority } : {}),
|
|
218
188
|
deliveryClass: candidate.deliveryClass,
|
|
@@ -227,21 +197,6 @@ function submissionReceipt({ before, after, candidate, action, now }) {
|
|
|
227
197
|
};
|
|
228
198
|
}
|
|
229
199
|
|
|
230
|
-
function reconcileSourceWorkflowRunId(existing, attempted, activeCandidateId, currentTime) {
|
|
231
|
-
const current = existing.sourceWorkflowRunId || 0;
|
|
232
|
-
const next = attempted.sourceWorkflowRunId || 0;
|
|
233
|
-
if (existing.sourceHead !== attempted.sourceHead) {
|
|
234
|
-
existing.sourceWorkflowRunId = next;
|
|
235
|
-
return "head-change";
|
|
236
|
-
}
|
|
237
|
-
if (current > 0 && next > 0 && current !== next) throw new Error("candidate sourceWorkflowRunId cannot change for the same sourceHead");
|
|
238
|
-
if (current !== 0 || next === 0) return "retained";
|
|
239
|
-
if (activeCandidateId === existing.candidateId) return "active";
|
|
240
|
-
existing.sourceWorkflowRunId = next;
|
|
241
|
-
existing.updatedAt = currentTime;
|
|
242
|
-
return "upgraded";
|
|
243
|
-
}
|
|
244
|
-
|
|
245
200
|
export function submitDevDeliveryCandidate(queueInput, input, { now = new Date().toISOString() } = {}) {
|
|
246
201
|
const transaction = transition(
|
|
247
202
|
queueInput,
|
|
@@ -257,13 +212,7 @@ export function submitDevDeliveryCandidate(queueInput, input, { now = new Date()
|
|
|
257
212
|
},
|
|
258
213
|
queue,
|
|
259
214
|
);
|
|
260
|
-
const chainedInput = chainedDevDeliveryAttemptInput({
|
|
261
|
-
queue,
|
|
262
|
-
candidate,
|
|
263
|
-
input,
|
|
264
|
-
currentTime,
|
|
265
|
-
terminalStates: TERMINAL_STATES,
|
|
266
|
-
});
|
|
215
|
+
const chainedInput = chainedDevDeliveryAttemptInput({ queue, candidate, input, currentTime, terminalStates: TERMINAL_STATES });
|
|
267
216
|
const attemptedCandidate = chainedInput ? normalizeCandidate(chainedInput, queue) : candidate;
|
|
268
217
|
const conflicting = queue.candidates.find((entry) => entry.pullRequestNumber === attemptedCandidate.pullRequestNumber && entry.candidateId !== attemptedCandidate.candidateId && !TERMINAL_STATES.has(entry.status));
|
|
269
218
|
if (conflicting) throw new Error(`PR #${candidate.pullRequestNumber} already has a different active semantic source`);
|
|
@@ -274,27 +223,18 @@ export function submitDevDeliveryCandidate(queueInput, input, { now = new Date()
|
|
|
274
223
|
if (TERMINAL_STATES.has(existing.status)) {
|
|
275
224
|
throw new Error(`candidate ${attemptedCandidate.candidateId} is terminal and cannot be resubmitted`);
|
|
276
225
|
}
|
|
277
|
-
const exactProofFields = ["sourcePatchRoot", "sourceProofRoot", "planRoot", "closureRoot", "dependencyRoot", "toolchainRoot"
|
|
278
|
-
const exactProofMatches = exactProofFields.every((field) => existing[field] === attemptedCandidate[field]) &&
|
|
279
|
-
const bindingAction = reconcileSourceWorkflowRunId(existing, attemptedCandidate, before.activeWarrant?.candidateId, currentTime);
|
|
226
|
+
const exactProofFields = ["sourcePatchRoot", "sourceProofRoot", "planRoot", "closureRoot", "dependencyRoot", "toolchainRoot"];
|
|
227
|
+
const exactProofMatches = exactProofFields.every((field) => existing[field] === attemptedCandidate[field]) && existing.releaseBlockerPriority?.claimRoot === attemptedCandidate.releaseBlockerPriority?.claimRoot;
|
|
280
228
|
if (existing.sourceHead === attemptedCandidate.sourceHead && exactProofMatches) {
|
|
281
|
-
|
|
282
|
-
action = bindingAction === "upgraded" ? "source-workflow-run-upgrade-retained-age" : "duplicate-noop";
|
|
229
|
+
action = "duplicate-noop";
|
|
283
230
|
selected = existing;
|
|
284
231
|
} else {
|
|
285
232
|
if (before.activeWarrant?.candidateId === existing.candidateId) {
|
|
286
|
-
|
|
287
|
-
throw new Error("selected candidate sourceHead cannot change before terminal Warrant closeout");
|
|
288
|
-
}
|
|
289
|
-
action = "active-warrant-retained-noop";
|
|
290
|
-
selected = existing;
|
|
291
|
-
return { candidate: selected, action };
|
|
233
|
+
throw new Error("selected candidate sourceHead cannot change before terminal Warrant closeout");
|
|
292
234
|
}
|
|
293
235
|
const headChanged = existing.sourceHead !== attemptedCandidate.sourceHead;
|
|
294
236
|
existing.sourceHead = attemptedCandidate.sourceHead;
|
|
295
237
|
for (const field of exactProofFields) existing[field] = attemptedCandidate[field];
|
|
296
|
-
if (Object.hasOwn(attemptedCandidate, "affectedPaths")) existing.affectedPaths = attemptedCandidate.affectedPaths;
|
|
297
|
-
else delete existing.affectedPaths;
|
|
298
238
|
if (Object.hasOwn(attemptedCandidate, "releaseBlockerPriority")) existing.releaseBlockerPriority = attemptedCandidate.releaseBlockerPriority;
|
|
299
239
|
else delete existing.releaseBlockerPriority;
|
|
300
240
|
existing.updatedAt = currentTime;
|
|
@@ -362,26 +302,26 @@ function warrantToken(input) {
|
|
|
362
302
|
|
|
363
303
|
export function selectDevDeliveryWarrant(queueInput, { now = new Date().toISOString(), leaseSeconds } = {}) {
|
|
364
304
|
const currentTime = timestamp(now, "now");
|
|
365
|
-
|
|
305
|
+
let queue = normalizeDevDeliveryQueue(queueInput);
|
|
366
306
|
let recoveryReceipt = null;
|
|
367
307
|
if (queue.activeWarrant && Date.parse(queue.activeWarrant.expiresAt) <= Date.parse(currentTime)) {
|
|
368
308
|
const recovered = recoverExpiredDevDeliveryWarrant(queue, {
|
|
369
309
|
now: currentTime,
|
|
370
310
|
});
|
|
311
|
+
queue = recovered.queue;
|
|
371
312
|
recoveryReceipt = recovered.receipt;
|
|
372
313
|
}
|
|
373
314
|
if (queue.activeWarrant) {
|
|
374
|
-
const expired = Date.parse(queue.activeWarrant.expiresAt) <= Date.parse(currentTime);
|
|
375
315
|
const receipt = {
|
|
376
316
|
schema: DEV_DELIVERY_SELECTION_RECEIPT_SCHEMA,
|
|
377
|
-
selected:
|
|
378
|
-
reason:
|
|
317
|
+
selected: true,
|
|
318
|
+
reason: "non-preemptive-active-warrant",
|
|
379
319
|
candidateId: queue.activeWarrant.candidateId,
|
|
380
320
|
fencingToken: queue.activeWarrant.fencingToken,
|
|
381
321
|
leaseGeneration: queue.activeWarrant.generation,
|
|
382
|
-
expectedOldStateRoot:
|
|
322
|
+
expectedOldStateRoot: queue.stateRoot,
|
|
383
323
|
nextStateRoot: queue.stateRoot,
|
|
384
|
-
nextAction:
|
|
324
|
+
nextAction: "Continue the active delivery attempt; later candidates remain visibly queued.",
|
|
385
325
|
};
|
|
386
326
|
return {
|
|
387
327
|
queue,
|
|
@@ -432,18 +372,16 @@ export function selectDevDeliveryWarrant(queueInput, { now = new Date().toISOStr
|
|
|
432
372
|
planRoot: candidate.planRoot,
|
|
433
373
|
closureRoot: candidate.closureRoot,
|
|
434
374
|
dependencyRoot: candidate.dependencyRoot,
|
|
435
|
-
toolchainRoot: candidate.toolchainRoot,
|
|
436
|
-
...(Object.hasOwn(candidate, "affectedPaths") ? { affectedPaths: candidate.affectedPaths } : {}),
|
|
375
|
+
toolchainRoot: candidate.toolchainRoot,
|
|
437
376
|
sourceWorkflowRunId: candidate.sourceWorkflowRunId,
|
|
438
377
|
...(Object.hasOwn(candidate, "releaseBlockerPriority") ? { releaseBlockerPriority: candidate.releaseBlockerPriority } : {}),
|
|
439
378
|
deliveryClass: candidate.deliveryClass,
|
|
440
379
|
generation: next.fencingCounter,
|
|
441
|
-
phase: "provisional",
|
|
442
380
|
expectedOldStateRoot: before.stateRoot,
|
|
443
381
|
issuedAt,
|
|
444
382
|
expiresAt: new Date(Date.parse(issuedAt) + effectiveLeaseSeconds * 1000).toISOString(),
|
|
445
383
|
fencingToken: "",
|
|
446
|
-
nextAction: "
|
|
384
|
+
nextAction: "Replay on the exact current dev base, prove required checks, then enqueue the unchanged PR head.",
|
|
447
385
|
};
|
|
448
386
|
warrant.fencingToken = warrantToken(warrant);
|
|
449
387
|
next.activeWarrant = warrant;
|
|
@@ -470,13 +408,9 @@ export function selectDevDeliveryWarrant(queueInput, { now = new Date().toISOStr
|
|
|
470
408
|
planRoot: transaction.result.candidate.planRoot,
|
|
471
409
|
closureRoot: transaction.result.candidate.closureRoot,
|
|
472
410
|
dependencyRoot: transaction.result.candidate.dependencyRoot,
|
|
473
|
-
toolchainRoot: transaction.result.candidate.toolchainRoot,
|
|
411
|
+
toolchainRoot: transaction.result.candidate.toolchainRoot,
|
|
474
412
|
sourceWorkflowRunId: transaction.result.candidate.sourceWorkflowRunId,
|
|
475
|
-
...(Object.hasOwn(transaction.result.candidate, "releaseBlockerPriority")
|
|
476
|
-
? {
|
|
477
|
-
releaseBlockerPriority: transaction.result.candidate.releaseBlockerPriority,
|
|
478
|
-
}
|
|
479
|
-
: {}),
|
|
413
|
+
...(Object.hasOwn(transaction.result.candidate, "releaseBlockerPriority") ? { releaseBlockerPriority: transaction.result.candidate.releaseBlockerPriority } : {}),
|
|
480
414
|
deliveryClass: transaction.result.candidate.deliveryClass,
|
|
481
415
|
queueAgeSeconds: selected.priority.ageSeconds,
|
|
482
416
|
basePriority: selected.priority.basePriority,
|
|
@@ -484,7 +418,7 @@ export function selectDevDeliveryWarrant(queueInput, { now = new Date().toISOStr
|
|
|
484
418
|
effectivePriority: selected.priority.score,
|
|
485
419
|
fencingToken: transaction.result.warrant.fencingToken,
|
|
486
420
|
leaseGeneration: transaction.result.warrant.generation,
|
|
487
|
-
expectedOldStateRoot:
|
|
421
|
+
expectedOldStateRoot: transaction.expectedOldStateRoot,
|
|
488
422
|
nextStateRoot: transaction.after.stateRoot,
|
|
489
423
|
nextAction: transaction.result.warrant.nextAction,
|
|
490
424
|
};
|
|
@@ -497,12 +431,12 @@ export function selectDevDeliveryWarrant(queueInput, { now = new Date().toISOStr
|
|
|
497
431
|
};
|
|
498
432
|
}
|
|
499
433
|
|
|
500
|
-
function assertWarrantMutation(queue, warrant, now
|
|
434
|
+
function assertWarrantMutation(queue, warrant, now) {
|
|
501
435
|
if (!queue.activeWarrant) throw new Error("no active Delivery Warrant");
|
|
502
436
|
if (text(warrant?.fencingToken) !== queue.activeWarrant.fencingToken) throw new Error("stale fencing token");
|
|
503
437
|
if (Number(warrant?.generation) !== queue.activeWarrant.generation) throw new Error("stale lease generation");
|
|
504
438
|
if (text(warrant?.candidateId) !== queue.activeWarrant.candidateId) throw new Error("Warrant candidate mismatch");
|
|
505
|
-
if (
|
|
439
|
+
if (Date.parse(queue.activeWarrant.expiresAt) <= Date.parse(now)) throw new Error("Delivery Warrant lease expired");
|
|
506
440
|
}
|
|
507
441
|
|
|
508
442
|
export function heartbeatDevDeliveryWarrant(queueInput, warrant, { now = new Date().toISOString(), leaseSeconds } = {}) {
|
|
@@ -514,7 +448,7 @@ export function heartbeatDevDeliveryWarrant(queueInput, warrant, { now = new Dat
|
|
|
514
448
|
const effectiveLeaseSeconds = positiveInteger(leaseSeconds, "leaseSeconds", queue.policy.leaseSeconds);
|
|
515
449
|
queue.activeWarrant.expiresAt = new Date(Date.parse(currentTime) + effectiveLeaseSeconds * 1000).toISOString();
|
|
516
450
|
const candidate = queue.candidates.find((entry) => entry.candidateId === queue.activeWarrant.candidateId);
|
|
517
|
-
candidate.status =
|
|
451
|
+
candidate.status = "proving";
|
|
518
452
|
candidate.updatedAt = currentTime;
|
|
519
453
|
return { candidate, warrant: queue.activeWarrant };
|
|
520
454
|
},
|
|
@@ -538,13 +472,6 @@ export function heartbeatDevDeliveryWarrant(queueInput, warrant, { now = new Dat
|
|
|
538
472
|
};
|
|
539
473
|
}
|
|
540
474
|
|
|
541
|
-
const qualifyDevDeliveryWarrantTransition = createDevDeliveryWarrantQualifier({
|
|
542
|
-
transition,
|
|
543
|
-
assertWarrantMutation,
|
|
544
|
-
});
|
|
545
|
-
export function qualifyDevDeliveryWarrant(queueInput, warrant, options) {
|
|
546
|
-
return qualifyDevDeliveryWarrantTransition(queueInput, warrant, options);
|
|
547
|
-
}
|
|
548
475
|
export function recoverExpiredDevDeliveryWarrant(queueInput, { now = new Date().toISOString() } = {}) {
|
|
549
476
|
const currentTime = timestamp(now, "now");
|
|
550
477
|
const before = normalizeDevDeliveryQueue(queueInput);
|
|
@@ -563,21 +490,33 @@ export function recoverExpiredDevDeliveryWarrant(queueInput, { now = new Date().
|
|
|
563
490
|
receiptRoot: devDeliveryContentRoot(receipt),
|
|
564
491
|
};
|
|
565
492
|
}
|
|
566
|
-
const
|
|
567
|
-
|
|
493
|
+
const transaction = transition(
|
|
494
|
+
before,
|
|
495
|
+
(queue) => {
|
|
496
|
+
const expired = clone(queue.activeWarrant);
|
|
497
|
+
const candidate = queue.candidates.find((entry) => entry.candidateId === expired.candidateId);
|
|
498
|
+
candidate.status = "queued";
|
|
499
|
+
candidate.recoveries += 1;
|
|
500
|
+
candidate.attempts += 1;
|
|
501
|
+
candidate.updatedAt = currentTime;
|
|
502
|
+
queue.activeWarrant = null;
|
|
503
|
+
return { candidate, expired };
|
|
504
|
+
},
|
|
505
|
+
currentTime,
|
|
506
|
+
);
|
|
568
507
|
const receipt = {
|
|
569
508
|
schema: DEV_DELIVERY_LEASE_RECEIPT_SCHEMA,
|
|
570
|
-
action: "expired-lease
|
|
571
|
-
candidateId: candidate.candidateId,
|
|
572
|
-
rejectedFencingToken: expired.fencingToken,
|
|
573
|
-
expiredLeaseGeneration: expired.generation,
|
|
574
|
-
retainedEnqueuedAt: candidate.enqueuedAt,
|
|
575
|
-
expectedOldStateRoot:
|
|
576
|
-
nextStateRoot:
|
|
577
|
-
nextAction: "
|
|
509
|
+
action: "recovered-expired-lease",
|
|
510
|
+
candidateId: transaction.result.candidate.candidateId,
|
|
511
|
+
rejectedFencingToken: transaction.result.expired.fencingToken,
|
|
512
|
+
expiredLeaseGeneration: transaction.result.expired.generation,
|
|
513
|
+
retainedEnqueuedAt: transaction.result.candidate.enqueuedAt,
|
|
514
|
+
expectedOldStateRoot: transaction.expectedOldStateRoot,
|
|
515
|
+
nextStateRoot: transaction.after.stateRoot,
|
|
516
|
+
nextAction: "Re-select through the queue to mint a new lease generation and fencing token.",
|
|
578
517
|
};
|
|
579
518
|
return {
|
|
580
|
-
queue:
|
|
519
|
+
queue: transaction.after,
|
|
581
520
|
receipt,
|
|
582
521
|
receiptRoot: devDeliveryContentRoot(receipt),
|
|
583
522
|
};
|
|
@@ -589,22 +528,16 @@ export function closeDevDeliveryWarrant(queueInput, warrant, { outcome, evidence
|
|
|
589
528
|
if (!TERMINAL_STATES.has(normalizedOutcome)) {
|
|
590
529
|
throw new Error(`outcome must be one of ${[...TERMINAL_STATES].join(", ")}`);
|
|
591
530
|
}
|
|
592
|
-
if (normalizedOutcome === "dequeued") {
|
|
593
|
-
throw new Error("transient dequeue cannot close an active Delivery Warrant");
|
|
594
|
-
}
|
|
595
531
|
const transaction = transition(
|
|
596
532
|
queueInput,
|
|
597
533
|
(queue, before) => {
|
|
598
|
-
assertWarrantMutation(before, warrant, currentTime
|
|
599
|
-
allowExpired: true,
|
|
600
|
-
});
|
|
534
|
+
assertWarrantMutation(before, warrant, currentTime);
|
|
601
535
|
const active = clone(queue.activeWarrant);
|
|
602
536
|
const candidate = queue.candidates.find((entry) => entry.candidateId === active.candidateId);
|
|
603
537
|
candidate.status = normalizedOutcome;
|
|
604
538
|
candidate.updatedAt = currentTime;
|
|
605
539
|
candidate.terminal = {
|
|
606
540
|
outcome: normalizedOutcome,
|
|
607
|
-
terminalClass: TERMINAL_CLASSES[normalizedOutcome],
|
|
608
541
|
reason: text(reason),
|
|
609
542
|
evidenceRoot: exactRoot(evidenceRoot, "evidenceRoot"),
|
|
610
543
|
closedAt: currentTime,
|
|
@@ -620,7 +553,6 @@ export function closeDevDeliveryWarrant(queueInput, warrant, { outcome, evidence
|
|
|
620
553
|
schema: DEV_DELIVERY_LEASE_RECEIPT_SCHEMA,
|
|
621
554
|
action: "terminal-closeout",
|
|
622
555
|
outcome: normalizedOutcome,
|
|
623
|
-
terminalClass: TERMINAL_CLASSES[normalizedOutcome],
|
|
624
556
|
reason: text(reason),
|
|
625
557
|
candidateId: transaction.result.candidate.candidateId,
|
|
626
558
|
fencingToken: transaction.result.active.fencingToken,
|
|
@@ -638,15 +570,8 @@ export function closeDevDeliveryWarrant(queueInput, warrant, { outcome, evidence
|
|
|
638
570
|
}
|
|
639
571
|
|
|
640
572
|
const cancelQueuedDevDeliveryCandidateTransition = createCancelQueuedDevDeliveryCandidate(normalizeDevDeliveryQueue);
|
|
641
|
-
export function cancelQueuedDevDeliveryCandidate(queueInput, input, options) {
|
|
642
|
-
|
|
643
|
-
}
|
|
644
|
-
export const settleDevDeliveryTerminalEvent = createDevDeliveryTerminalSettler({
|
|
645
|
-
normalizeQueue: normalizeDevDeliveryQueue,
|
|
646
|
-
closeWarrant: closeDevDeliveryWarrant,
|
|
647
|
-
cancelQueued: cancelQueuedDevDeliveryCandidate,
|
|
648
|
-
terminalStates: TERMINAL_STATES,
|
|
649
|
-
});
|
|
573
|
+
export function cancelQueuedDevDeliveryCandidate(queueInput, input, options) { return cancelQueuedDevDeliveryCandidateTransition(queueInput, input, options); }
|
|
574
|
+
export const settleDevDeliveryTerminalEvent = createDevDeliveryTerminalSettler({ normalizeQueue: normalizeDevDeliveryQueue, closeWarrant: closeDevDeliveryWarrant, cancelQueued: cancelQueuedDevDeliveryCandidate, terminalStates: TERMINAL_STATES });
|
|
650
575
|
|
|
651
576
|
export function observeDevDeliveryQueue(queueInput, { now = new Date().toISOString() } = {}) {
|
|
652
577
|
const queue = normalizeDevDeliveryQueue(queueInput);
|
|
@@ -673,19 +598,6 @@ export function observeDevDeliveryQueue(queueInput, { now = new Date().toISOStri
|
|
|
673
598
|
queueAgeSeconds: entry.priority.ageSeconds,
|
|
674
599
|
attempts: entry.candidate.attempts,
|
|
675
600
|
recoveries: entry.candidate.recoveries,
|
|
676
|
-
assignmentRoot: entry.candidate.assignmentRoot,
|
|
677
|
-
initiativeRoot: entry.candidate.initiativeRoot,
|
|
678
|
-
sourceIdentityRoot: entry.candidate.sourceIdentityRoot,
|
|
679
|
-
sourcePatchRoot: entry.candidate.sourcePatchRoot,
|
|
680
|
-
sourceProofRoot: entry.candidate.sourceProofRoot,
|
|
681
|
-
planRoot: entry.candidate.planRoot,
|
|
682
|
-
closureRoot: entry.candidate.closureRoot,
|
|
683
|
-
dependencyRoot: entry.candidate.dependencyRoot,
|
|
684
|
-
toolchainRoot: entry.candidate.toolchainRoot, ...(entry.candidate.environmentRoot ? { environmentRoot: entry.candidate.environmentRoot } : {}),
|
|
685
|
-
sourceWorkflowRunId: entry.candidate.sourceWorkflowRunId || 0,
|
|
686
|
-
affectedPaths: entry.candidate.affectedPaths || [],
|
|
687
|
-
deliveryClass: entry.candidate.deliveryClass,
|
|
688
|
-
priority: entry.candidate.priority,
|
|
689
601
|
nextAction: index === 0 && !queue.activeWarrant ? "eligible-for-selection" : "wait-for-active-warrant",
|
|
690
602
|
})),
|
|
691
603
|
observedAt: currentTime,
|
|
@@ -84,14 +84,10 @@ function fileStats(cwd, entries = []) {
|
|
|
84
84
|
});
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
function commandVersion(command, args = ["--version"]) {
|
|
87
|
+
function commandVersion(command, args = ["--version"], cwd = process.cwd()) {
|
|
90
88
|
try {
|
|
91
89
|
return execFileSync(command, args, {
|
|
92
|
-
|
|
93
|
-
// bounded instead of scanning an arbitrary consumer or shared temp root.
|
|
94
|
-
cwd: TOOL_VERSION_PROBE_CWD,
|
|
90
|
+
cwd,
|
|
95
91
|
encoding: "utf8",
|
|
96
92
|
stdio: ["ignore", "pipe", "ignore"],
|
|
97
93
|
timeout: 5000,
|
|
@@ -497,8 +493,7 @@ export function collectRunnerDiagnostics() {
|
|
|
497
493
|
}
|
|
498
494
|
|
|
499
495
|
export function collectToolDiagnostics({ cwd = process.cwd(), tools = ["node", "pnpm", "npm", "git", "cmake", "ninja", "ccache", "sccache"] } = {}) {
|
|
500
|
-
|
|
501
|
-
return Object.fromEntries(tools.map((tool) => [tool, { version: commandVersion(tool) }]));
|
|
496
|
+
return Object.fromEntries(tools.map((tool) => [tool, { version: commandVersion(tool, ["--version"], cwd) }]));
|
|
502
497
|
}
|
|
503
498
|
|
|
504
499
|
function parseJsonDiagnostics(value = "") {
|
|
@@ -54,9 +54,11 @@ const PUBLIC_REPOSITORY_TARGETS = Object.freeze({
|
|
|
54
54
|
target("publish-gate/major", [check("check")], true),
|
|
55
55
|
],
|
|
56
56
|
buildchain: [
|
|
57
|
-
|
|
57
|
+
...["v3/v3.0", "v4/v4.0"].map((line) => target(`dev/${line}`, [check("check")], false)),
|
|
58
58
|
target("alpha/v3/v3.0", [check("check"), check("verify")], false),
|
|
59
59
|
target("release/v3/v3.0", [check("check")], true),
|
|
60
|
+
target("alpha/v4/v4.0", [check("check"), check("verify")], false),
|
|
61
|
+
target("release/v4/v4.0", [check("check"), check("verify")], true),
|
|
60
62
|
target("authority/v3/v3.0/artifact-signing", [check("check"), check("verify")], true),
|
|
61
63
|
target("publish-gate/major", [check("check")], true),
|
|
62
64
|
],
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import kfdCategoryCatalog from "@kungfu-tech/kfd/adopter-conformance/category-profiles.json" with { type: "json" };
|
|
2
|
+
import kfdPackageJson from "@kungfu-tech/kfd/package.json" with { type: "json" };
|
|
3
|
+
import { resolveAdopterCategoryProfiles } from "@kungfu-tech/kfd/adopter-conformance/category-profile-resolver";
|
|
4
|
+
import { verifyAdopterCategoryInstanceManifest } from "@kungfu-tech/kfd/adopter-conformance/category-instance-verifier";
|
|
5
|
+
import { verifyAdopterManifestFromPackage } from "@kungfu-tech/kfd/adopter-conformance/toolchain";
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
ADOPTER_PROTOCOL_DRIVER_INTERFACE,
|
|
9
|
+
adopterDeliveryGateDigest,
|
|
10
|
+
defineAdopterProtocolDriver,
|
|
11
|
+
} from "./adopter-delivery-gate.js";
|
|
12
|
+
|
|
13
|
+
export const KFD_ADOPTER_CATEGORY_PROTOCOL_ID =
|
|
14
|
+
"kfd.adopter-category/instance-manifest";
|
|
15
|
+
export const KFD_ADOPTER_CATEGORY_PROTOCOL_VERSION = "1.0.0";
|
|
16
|
+
export const KFD_ADOPTER_CATEGORY_DRIVER_REPORT_CONTRACT =
|
|
17
|
+
"kungfu-buildchain-kfd-adopter-category-driver-report";
|
|
18
|
+
|
|
19
|
+
function freezeJson(value) {
|
|
20
|
+
if (value && typeof value === "object" && !Object.isFrozen(value)) {
|
|
21
|
+
Object.freeze(value);
|
|
22
|
+
for (const child of Object.values(value)) freezeJson(child);
|
|
23
|
+
}
|
|
24
|
+
return value;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const publishedCatalog = freezeJson(structuredClone(kfdCategoryCatalog));
|
|
28
|
+
|
|
29
|
+
function catalogCopy() {
|
|
30
|
+
return structuredClone(publishedCatalog);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function sameJson(left, right) {
|
|
34
|
+
try {
|
|
35
|
+
return adopterDeliveryGateDigest(left) === adopterDeliveryGateDigest(right);
|
|
36
|
+
} catch {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function issue(code, path, message) {
|
|
42
|
+
return { code, path, message };
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function resolvePublishedKfdAdopterCategoryProfiles(selection) {
|
|
46
|
+
return resolveAdopterCategoryProfiles(
|
|
47
|
+
structuredClone(selection),
|
|
48
|
+
catalogCopy(),
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function verifyPublishedKfdAdopterCategoryInstance(
|
|
53
|
+
instanceManifest,
|
|
54
|
+
{ adopterManifest, verifiedAt, maxAgeSeconds } = {},
|
|
55
|
+
) {
|
|
56
|
+
const adopterReport = verifyAdopterManifestFromPackage(adopterManifest, {
|
|
57
|
+
packageArtifactRoot: instanceManifest?.kfdCut?.packageRoot,
|
|
58
|
+
verifiedAt,
|
|
59
|
+
maxAgeSeconds,
|
|
60
|
+
});
|
|
61
|
+
return verifyAdopterCategoryInstanceManifest(instanceManifest, {
|
|
62
|
+
catalog: catalogCopy(),
|
|
63
|
+
adopterManifest,
|
|
64
|
+
adopterReport,
|
|
65
|
+
verifiedAt,
|
|
66
|
+
maxAgeSeconds,
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function deliveryBindingIssues(request, adopterManifest) {
|
|
71
|
+
const instance = request.declaration;
|
|
72
|
+
const issues = [];
|
|
73
|
+
if (
|
|
74
|
+
request.project.instanceId !== instance?.instanceId ||
|
|
75
|
+
request.project.adopterId !== instance?.project?.adopterId
|
|
76
|
+
) {
|
|
77
|
+
issues.push(
|
|
78
|
+
issue(
|
|
79
|
+
"delivery-kfd-instance-binding-mismatch",
|
|
80
|
+
"/project",
|
|
81
|
+
"Delivery project identity must match the KFD category instance.",
|
|
82
|
+
),
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
if (!sameJson(request.artifact, instance?.project?.artifact)) {
|
|
86
|
+
issues.push(
|
|
87
|
+
issue(
|
|
88
|
+
"delivery-kfd-instance-binding-mismatch",
|
|
89
|
+
"/artifact",
|
|
90
|
+
"Delivery artifact must match the KFD category instance artifact.",
|
|
91
|
+
),
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
if (
|
|
95
|
+
adopterManifest?.kfdCut?.package?.name !== kfdPackageJson.name ||
|
|
96
|
+
adopterManifest?.kfdCut?.package?.version !== kfdPackageJson.version ||
|
|
97
|
+
instance?.kfdCut?.packageVersion !== kfdPackageJson.version
|
|
98
|
+
) {
|
|
99
|
+
issues.push(
|
|
100
|
+
issue(
|
|
101
|
+
"delivery-kfd-package-cut-mismatch",
|
|
102
|
+
"/declaration/kfdCut",
|
|
103
|
+
"KFD declarations must bind the exact installed published package version.",
|
|
104
|
+
),
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
return issues;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function driverReport(categoryReport, adapterIssues) {
|
|
111
|
+
const valid = categoryReport?.valid === true && adapterIssues.length === 0;
|
|
112
|
+
const report = {
|
|
113
|
+
schemaVersion: 1,
|
|
114
|
+
contract: KFD_ADOPTER_CATEGORY_DRIVER_REPORT_CONTRACT,
|
|
115
|
+
valid,
|
|
116
|
+
conforming: valid,
|
|
117
|
+
qualifying: false,
|
|
118
|
+
selfCertified: false,
|
|
119
|
+
independentlyCertified: false,
|
|
120
|
+
kfdPackage: {
|
|
121
|
+
name: kfdPackageJson.name,
|
|
122
|
+
version: kfdPackageJson.version,
|
|
123
|
+
},
|
|
124
|
+
categoryReport,
|
|
125
|
+
adapterIssues,
|
|
126
|
+
nonClaims: [
|
|
127
|
+
"Category conformance does not grant runtime permission or release authorization.",
|
|
128
|
+
"Buildchain carries the published KFD decision and does not certify or reinterpret it.",
|
|
129
|
+
],
|
|
130
|
+
};
|
|
131
|
+
return {
|
|
132
|
+
valid,
|
|
133
|
+
report,
|
|
134
|
+
reportRoot: adopterDeliveryGateDigest(report),
|
|
135
|
+
issues: [...(categoryReport?.issues ?? []), ...adapterIssues],
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export function createKfdAdopterCategoryProtocolDriver() {
|
|
140
|
+
return defineAdopterProtocolDriver({
|
|
141
|
+
interface: ADOPTER_PROTOCOL_DRIVER_INTERFACE,
|
|
142
|
+
id: KFD_ADOPTER_CATEGORY_PROTOCOL_ID,
|
|
143
|
+
version: KFD_ADOPTER_CATEGORY_PROTOCOL_VERSION,
|
|
144
|
+
verify({ request, context }) {
|
|
145
|
+
const adapterIssues = deliveryBindingIssues(
|
|
146
|
+
request,
|
|
147
|
+
context?.adopterManifest,
|
|
148
|
+
);
|
|
149
|
+
let categoryReport = null;
|
|
150
|
+
try {
|
|
151
|
+
categoryReport = verifyPublishedKfdAdopterCategoryInstance(
|
|
152
|
+
request.declaration,
|
|
153
|
+
context,
|
|
154
|
+
);
|
|
155
|
+
} catch {
|
|
156
|
+
adapterIssues.push(
|
|
157
|
+
issue(
|
|
158
|
+
"delivery-kfd-verification-context-invalid",
|
|
159
|
+
"/protocol",
|
|
160
|
+
"Published KFD verification could not reproduce from the supplied exact context.",
|
|
161
|
+
),
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
return driverReport(categoryReport, adapterIssues);
|
|
165
|
+
},
|
|
166
|
+
});
|
|
167
|
+
}
|