@kungfu-tech/buildchain 4.0.2-alpha.28 → 4.0.2-alpha.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/architecture/agent-change-map.md +3 -0
  2. package/architecture/internal-capabilities.json +5 -2
  3. package/architecture/maintainability-debt.json +4 -3
  4. package/architecture/maintainability-policy.json +5 -5
  5. package/bin/buildchain.mjs +7 -7
  6. package/contracts/dev-delivery-authority-v2.schema.json +16 -2
  7. package/dist/site/buildchain-contract.json +5 -5
  8. package/dist/site/buildchain-site.json +7 -7
  9. package/dist/site/kfd-claims.json +2 -2
  10. package/dist/site/kfd-upstream-aggregate.json +1 -1
  11. package/dist/site/manual-registry.json +1 -1
  12. package/dist/site/node-api-registry.json +6 -6
  13. package/dist/site/page-registry.json +2 -2
  14. package/dist/site/public-surface-audit.json +2 -2
  15. package/dist/site/publication-registry.json +4 -4
  16. package/dist/site/schemas/dev-delivery-authority-v2.schema.json +16 -2
  17. package/dist/site/site-manifest.json +5 -5
  18. package/dist/site/workflow-registry.json +4 -4
  19. package/docs/node-api-reference.md +4 -4
  20. package/package.json +1 -1
  21. package/packages/core/dev-delivery-candidate-identity.js +14 -35
  22. package/packages/core/dev-delivery-warrant-state.js +3 -4
  23. package/packages/core/dev-delivery-warrant.js +12 -2
  24. package/scripts/build-contract-core.mjs +1 -14
  25. package/scripts/dev-delivery-authority-command-adapters.mjs +1 -1
  26. package/scripts/dev-delivery-authority.mjs +8 -8
  27. package/scripts/dev-delivery-source-proof-reuse.mjs +2 -1
  28. package/scripts/dev-delivery-warrant-options.mjs +14 -9
  29. package/scripts/dev-delivery-warrant.mjs +3 -2
  30. package/scripts/github-output.mjs +31 -0
  31. package/scripts/release-candidate-resolver.mjs +8 -8
  32. package/templates/native-dev-delivery.yml +4 -7
@@ -8905,8 +8905,8 @@
8905
8905
  "workflowRegistryPath": "dist/site/workflow-registry.json",
8906
8906
  "pageRegistryPath": "dist/site/page-registry.json",
8907
8907
  "cliRegistryDigest": "fbc23073bbae240489a2f826b2c26daadc58e704050c5f8df366509f5c5a1c3e",
8908
- "workflowRegistryDigest": "d89f5d875f63d04ba2ab055fe3741acb72c5a537e53db8af9df3fe3170317d52",
8909
- "pageRegistryDigest": "ae0b1b9c7b883027cf53403221ff2fe2e41ad1aa4d16851d4550e89947d6d6d7"
8908
+ "workflowRegistryDigest": "2ed63e5df83b2a9e069c9ffb139612ab7d25db037e275625c0c15e38b822b517",
8909
+ "pageRegistryDigest": "182e0474bd22e436c079396460f654a0fa310cef11316c03a0996852e9dcdc5b"
8910
8910
  },
8911
8911
  "comparison": {
8912
8912
  "missingCliRegistry": [],
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
3
  "contract": "kungfu-buildchain-publication-release-registry",
4
- "generatedAt": "2026-09-03T11:14:58.000Z",
5
- "publishedAt": "2026-09-03T11:14:58.000Z",
4
+ "generatedAt": "2026-09-04T06:13:05.000Z",
5
+ "publishedAt": "2026-09-04T06:13:05.000Z",
6
6
  "reproducible": true,
7
7
  "timestampPolicy": "ci-injected",
8
8
  "deterministicInputs": [
@@ -19,7 +19,7 @@
19
19
  "declared Buildchain surface manifest contract"
20
20
  ],
21
21
  "sourceDateEpoch": "0",
22
- "sourceRevision": "6b0935c5663d38893a9ff4688fed4cbbe6b9f0ac",
22
+ "sourceRevision": "2c0f05aceb6bf547dea5a2edc5556c87a74f03fc",
23
23
  "timestampPolicyDetails": {
24
24
  "contract": "kungfu-buildchain-surface-timestamp-policy",
25
25
  "timestampFields": [
@@ -32,7 +32,7 @@
32
32
  },
33
33
  "package": {
34
34
  "name": "@kungfu-tech/buildchain",
35
- "version": "4.0.2-alpha.28",
35
+ "version": "4.0.2-alpha.30",
36
36
  "versionSource": "package.json#version"
37
37
  },
38
38
  "sourceKind": "package-site-bundle",
@@ -558,8 +558,6 @@
558
558
  "repository",
559
559
  "protectedBase",
560
560
  "pullRequestNumber",
561
- "assignmentRoot",
562
- "initiativeRoot",
563
561
  "sourceIdentityRoot",
564
562
  "deliveryClass",
565
563
  "candidateId",
@@ -576,10 +574,26 @@
576
574
  "qualification",
577
575
  "terminal"
578
576
  ],
577
+ "oneOf": [
578
+ {
579
+ "required": ["sourceRoot"],
580
+ "not": {
581
+ "anyOf": [
582
+ { "required": ["assignmentRoot"] },
583
+ { "required": ["initiativeRoot"] }
584
+ ]
585
+ }
586
+ },
587
+ {
588
+ "required": ["assignmentRoot", "initiativeRoot"],
589
+ "not": { "required": ["sourceRoot"] }
590
+ }
591
+ ],
579
592
  "properties": {
580
593
  "repository": { "type": "string" },
581
594
  "protectedBase": { "type": "string" },
582
595
  "pullRequestNumber": { "type": "integer", "minimum": 1 },
596
+ "sourceRoot": { "$ref": "#/$defs/root" },
583
597
  "assignmentRoot": { "$ref": "#/$defs/root" },
584
598
  "initiativeRoot": { "$ref": "#/$defs/root" },
585
599
  "sourceIdentityRoot": { "$ref": "#/$defs/root" },
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
3
  "contract": "kungfu-buildchain-site-manifest",
4
- "generatedAt": "2026-09-03T11:14:58.000Z",
5
- "publishedAt": "2026-09-03T11:14:58.000Z",
4
+ "generatedAt": "2026-09-04T06:13:05.000Z",
5
+ "publishedAt": "2026-09-04T06:13:05.000Z",
6
6
  "reproducible": true,
7
7
  "timestampPolicy": "ci-injected",
8
8
  "deterministicInputs": [
@@ -19,7 +19,7 @@
19
19
  "declared Buildchain surface manifest contract"
20
20
  ],
21
21
  "sourceDateEpoch": "0",
22
- "sourceRevision": "6b0935c5663d38893a9ff4688fed4cbbe6b9f0ac",
22
+ "sourceRevision": "2c0f05aceb6bf547dea5a2edc5556c87a74f03fc",
23
23
  "timestampPolicyDetails": {
24
24
  "contract": "kungfu-buildchain-surface-timestamp-policy",
25
25
  "timestampFields": [
@@ -37,7 +37,7 @@
37
37
  },
38
38
  "package": {
39
39
  "name": "@kungfu-tech/buildchain",
40
- "version": "4.0.2-alpha.28",
40
+ "version": "4.0.2-alpha.30",
41
41
  "versionSource": "package.json#version"
42
42
  },
43
43
  "entrypoint": "buildchain-site.json",
@@ -253,7 +253,7 @@
253
253
  "path": "docs/node-api-reference.md",
254
254
  "plane": "use",
255
255
  "exists": true,
256
- "digest": "sha256:977a362563fd8fb93571dd670fea95b2285751140bfca2bc4d133123a0b4bb20"
256
+ "digest": "sha256:5bf8600323e802258023088612be0f68d86fef9ea409e9250dd55358c907f65a"
257
257
  },
258
258
  {
259
259
  "id": "build-facts",
@@ -1926,7 +1926,7 @@
1926
1926
  "status": "preview",
1927
1927
  "owner": "buildchain-workflows",
1928
1928
  "maturity": "preview",
1929
- "introducedVersion": "4.0.2-alpha.28",
1929
+ "introducedVersion": "4.0.2-alpha.30",
1930
1930
  "compatibilityPromise": "preserved-through-the-v3-major-line",
1931
1931
  "deprecationReplacement": "",
1932
1932
  "sunsetCondition": "explicit-breaking-change-review-in-a-future-major-line",
@@ -1947,7 +1947,7 @@
1947
1947
  "status": "preview",
1948
1948
  "owner": "buildchain-workflows",
1949
1949
  "maturity": "preview",
1950
- "introducedVersion": "4.0.2-alpha.28",
1950
+ "introducedVersion": "4.0.2-alpha.30",
1951
1951
  "compatibilityPromise": "preserved-through-the-v3-major-line",
1952
1952
  "deprecationReplacement": "",
1953
1953
  "sunsetCondition": "explicit-breaking-change-review-in-a-future-major-line",
@@ -1968,7 +1968,7 @@
1968
1968
  "status": "preview",
1969
1969
  "owner": "buildchain-workflows",
1970
1970
  "maturity": "preview",
1971
- "introducedVersion": "4.0.2-alpha.28",
1971
+ "introducedVersion": "4.0.2-alpha.30",
1972
1972
  "compatibilityPromise": "preserved-through-the-v3-major-line",
1973
1973
  "deprecationReplacement": "",
1974
1974
  "sunsetCondition": "explicit-breaking-change-review-in-a-future-major-line",
@@ -2019,7 +2019,7 @@
2019
2019
  "status": "preview",
2020
2020
  "owner": "buildchain-workflows",
2021
2021
  "maturity": "preview",
2022
- "introducedVersion": "4.0.2-alpha.28",
2022
+ "introducedVersion": "4.0.2-alpha.30",
2023
2023
  "compatibilityPromise": "preserved-through-the-v3-major-line",
2024
2024
  "deprecationReplacement": "",
2025
2025
  "sunsetCondition": "explicit-breaking-change-review-in-a-future-major-line",
@@ -1692,7 +1692,7 @@ Target: `./packages/core/dev-delivery-warrant.js`. Public symbols: 59.
1692
1692
 
1693
1693
  | Symbol | Kind and signature | Parameters | Return | Errors | Side effects | Example | Source |
1694
1694
  | --- | --- | --- | --- | --- | --- | --- | --- |
1695
- | `cancelQueuedDevDeliveryCandidate` | function: function cancelQueuedDevDeliveryCandidate(queueInput, input, options) | queueInput, input, options | unknown | Errors from called operations may propagate; no narrower throw contract is declared in source. | none-detected-by-static-source-scan | `import { cancelQueuedDevDeliveryCandidate } from "@kungfu-tech/buildchain/dev-delivery-warrant";` | `packages/core/dev-delivery-warrant.js:520` |
1695
+ | `cancelQueuedDevDeliveryCandidate` | function: function cancelQueuedDevDeliveryCandidate(queueInput, input, options) | queueInput, input, options | unknown | Errors from called operations may propagate; no narrower throw contract is declared in source. | none-detected-by-static-source-scan | `import { cancelQueuedDevDeliveryCandidate } from "@kungfu-tech/buildchain/dev-delivery-warrant";` | `packages/core/dev-delivery-warrant.js:521` |
1696
1696
  | `classifyDevDeliveryDelta` | function: function classifyDevDeliveryDelta({ proof, current = {} } = {}) | { proof, current = {} } = {} | unknown | Errors from called operations may propagate; no narrower throw contract is declared in source. | none-detected-by-static-source-scan | `import { classifyDevDeliveryDelta } from "@kungfu-tech/buildchain/dev-delivery-warrant";` | `packages/core/dev-delivery-proof.js:109` |
1697
1697
  | `closeDevDeliveryWarrant` | function: function closeDevDeliveryWarrant(queueInput, warrant, { outcome, evidenceRoot, reason = "", providerFailureAuthority = null, now = new Date().toISOString(), } = {}) | queueInput, warrant, { outcome, evidenceRoot, reason = "", providerFailureAuthority = null, now = new Date().toISOString(), } = {} | unknown | May throw an Error on rejected input or failed operations; follow the linked source contract. | none-detected-by-static-source-scan | `import { closeDevDeliveryWarrant } from "@kungfu-tech/buildchain/dev-delivery-warrant";` | `packages/core/dev-delivery-warrant.js:395` |
1698
1698
  | `createDevDeliveryQueue` | value: createDevDeliveryQueue | none | unknown | No narrower error contract was mechanically discoverable. | unknown | `import { createDevDeliveryQueue } from "@kungfu-tech/buildchain/dev-delivery-warrant";` | `packages/core/dev-delivery-warrant.js:1` |
@@ -1733,15 +1733,15 @@ Target: `./packages/core/dev-delivery-warrant.js`. Public symbols: 59.
1733
1733
  | `NATIVE_QUALIFICATION_PROOF_SCHEMA` | constant: const NATIVE_QUALIFICATION_PROOF_SCHEMA | none | value | Import does not declare a throw contract. | none-on-import | `import { NATIVE_QUALIFICATION_PROOF_SCHEMA } from "@kungfu-tech/buildchain/dev-delivery-warrant";` | `packages/core/dev-delivery-native-proof.js:31` |
1734
1734
  | `normalizeDevDeliveryQueue` | value: normalizeDevDeliveryQueue | none | unknown | No narrower error contract was mechanically discoverable. | unknown | `import { normalizeDevDeliveryQueue } from "@kungfu-tech/buildchain/dev-delivery-warrant";` | `packages/core/dev-delivery-warrant.js:1` |
1735
1735
  | `normalizeNativeCommandContract` | value: normalizeNativeCommandContract | none | unknown | No narrower error contract was mechanically discoverable. | unknown | `import { normalizeNativeCommandContract } from "@kungfu-tech/buildchain/dev-delivery-warrant";` | `packages/core/dev-delivery-native-proof.js:1` |
1736
- | `observeDevDeliveryQueue` | function: function observeDevDeliveryQueue(queueInput, { now = new Date().toISOString(), allowLegacyV3Readback = false } = {}) | queueInput, { now = new Date().toISOString(), allowLegacyV3Readback = false } = {} | unknown | Errors from called operations may propagate; no narrower throw contract is declared in source. | none-detected-by-static-source-scan | `import { observeDevDeliveryQueue } from "@kungfu-tech/buildchain/dev-delivery-warrant";` | `packages/core/dev-delivery-warrant.js:534` |
1736
+ | `observeDevDeliveryQueue` | function: function observeDevDeliveryQueue(queueInput, { now = new Date().toISOString(), allowLegacyV3Readback = false } = {}) | queueInput, { now = new Date().toISOString(), allowLegacyV3Readback = false } = {} | unknown | Errors from called operations may propagate; no narrower throw contract is declared in source. | none-detected-by-static-source-scan | `import { observeDevDeliveryQueue } from "@kungfu-tech/buildchain/dev-delivery-warrant";` | `packages/core/dev-delivery-warrant.js:535` |
1737
1737
  | `PROJECT_CUT_REPLAY_PROOF_SCHEMA` | constant: const PROJECT_CUT_REPLAY_PROOF_SCHEMA | none | value | Import does not declare a throw contract. | none-on-import | `import { PROJECT_CUT_REPLAY_PROOF_SCHEMA } from "@kungfu-tech/buildchain/dev-delivery-warrant";` | `packages/core/dev-delivery-proof.js:5` |
1738
1738
  | `qualifyDevDeliveryWarrant` | constant: const qualifyDevDeliveryWarrant | none | value | Import does not declare a throw contract. | none-on-import | `import { qualifyDevDeliveryWarrant } from "@kungfu-tech/buildchain/dev-delivery-warrant";` | `packages/core/dev-delivery-warrant.js:391` |
1739
1739
  | `rankDevDeliveryCandidates` | value: rankDevDeliveryCandidates | none | unknown | No narrower error contract was mechanically discoverable. | unknown | `import { rankDevDeliveryCandidates } from "@kungfu-tech/buildchain/dev-delivery-warrant";` | `packages/core/dev-delivery-warrant.js:1` |
1740
- | `reconcileDevDeliveryTerminalEvidence` | constant: const reconcileDevDeliveryTerminalEvidence | none | value | Import does not declare a throw contract. | none-on-import | `import { reconcileDevDeliveryTerminalEvidence } from "@kungfu-tech/buildchain/dev-delivery-warrant";` | `packages/core/dev-delivery-warrant.js:529` |
1740
+ | `reconcileDevDeliveryTerminalEvidence` | constant: const reconcileDevDeliveryTerminalEvidence | none | value | Import does not declare a throw contract. | none-on-import | `import { reconcileDevDeliveryTerminalEvidence } from "@kungfu-tech/buildchain/dev-delivery-warrant";` | `packages/core/dev-delivery-warrant.js:530` |
1741
1741
  | `recoverExpiredDevDeliveryWarrant` | function: function recoverExpiredDevDeliveryWarrant(queueInput, { now = new Date().toISOString() } = {}) | queueInput, { now = new Date().toISOString() } = {} | unknown | Errors from called operations may propagate; no narrower throw contract is declared in source. | none-detected-by-static-source-scan | `import { recoverExpiredDevDeliveryWarrant } from "@kungfu-tech/buildchain/dev-delivery-warrant";` | `packages/core/dev-delivery-warrant.js:312` |
1742
1742
  | `RELEASE_BLOCKER_PRIORITY_CLAIM_SCHEMA` | constant: const RELEASE_BLOCKER_PRIORITY_CLAIM_SCHEMA | none | value | Import does not declare a throw contract. | none-on-import | `import { RELEASE_BLOCKER_PRIORITY_CLAIM_SCHEMA } from "@kungfu-tech/buildchain/dev-delivery-warrant";` | `packages/core/release-blocker-priority.js:15` |
1743
1743
  | `selectDevDeliveryWarrant` | function: function selectDevDeliveryWarrant(queueInput, { now = new Date().toISOString(), leaseSeconds } = {}) | queueInput, { now = new Date().toISOString(), leaseSeconds } = {} | unknown | May throw an Error on rejected input or failed operations; follow the linked source contract. | none-detected-by-static-source-scan | `import { selectDevDeliveryWarrant } from "@kungfu-tech/buildchain/dev-delivery-warrant";` | `packages/core/dev-delivery-warrant.js:106` |
1744
- | `settleDevDeliveryTerminalEvent` | constant: const settleDevDeliveryTerminalEvent | none | value | Import does not declare a throw contract. | none-on-import | `import { settleDevDeliveryTerminalEvent } from "@kungfu-tech/buildchain/dev-delivery-warrant";` | `packages/core/dev-delivery-warrant.js:523` |
1744
+ | `settleDevDeliveryTerminalEvent` | constant: const settleDevDeliveryTerminalEvent | none | value | Import does not declare a throw contract. | none-on-import | `import { settleDevDeliveryTerminalEvent } from "@kungfu-tech/buildchain/dev-delivery-warrant";` | `packages/core/dev-delivery-warrant.js:524` |
1745
1745
  | `SOURCE_QUALIFICATION_PROOF_SCHEMA` | constant: const SOURCE_QUALIFICATION_PROOF_SCHEMA | none | value | Import does not declare a throw contract. | none-on-import | `import { SOURCE_QUALIFICATION_PROOF_SCHEMA } from "@kungfu-tech/buildchain/dev-delivery-warrant";` | `packages/core/dev-delivery-proof.js:3` |
1746
1746
  | `SOURCE_QUALIFICATION_PROOF_V2_SCHEMA` | constant: const SOURCE_QUALIFICATION_PROOF_V2_SCHEMA | none | value | Import does not declare a throw contract. | none-on-import | `import { SOURCE_QUALIFICATION_PROOF_V2_SCHEMA } from "@kungfu-tech/buildchain/dev-delivery-warrant";` | `packages/core/dev-delivery-proof.js:4` |
1747
1747
  | `submitDevDeliveryCandidate` | value: submitDevDeliveryCandidate | none | unknown | No narrower error contract was mechanically discoverable. | unknown | `import { submitDevDeliveryCandidate } from "@kungfu-tech/buildchain/dev-delivery-warrant";` | `packages/core/dev-delivery-warrant.js:1` |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kungfu-tech/buildchain",
3
- "version": "4.0.2-alpha.28",
3
+ "version": "4.0.2-alpha.30",
4
4
  "private": false,
5
5
  "description": "Buildchain Release Passport, release governance, CLI toolkit, and site facts.",
6
6
  "repository": "https://github.com/kungfu-systems/buildchain",
@@ -20,7 +20,12 @@ export const EXACT_DEV_DELIVERY_PROOF_FIELDS = Object.freeze([
20
20
  "environmentRoot",
21
21
  "sourceWorkflowRunId",
22
22
  ]);
23
-
23
+ export function devDeliverySourceBinding(input = {}) {
24
+ const [sourceRoot, assignmentRoot, initiativeRoot] = ["sourceRoot", "assignmentRoot", "initiativeRoot"].map((field) => String(input[field] || "").trim());
25
+ if (sourceRoot && !assignmentRoot && !initiativeRoot) return { sourceRoot: exactRoot(sourceRoot, "sourceRoot") };
26
+ if (!sourceRoot && assignmentRoot && initiativeRoot) return { assignmentRoot: exactRoot(assignmentRoot, "assignmentRoot"), initiativeRoot: exactRoot(initiativeRoot, "initiativeRoot") };
27
+ throw new Error("provide sourceRoot alone or both historical roots");
28
+ }
24
29
  export function matchesExactDevDeliveryCandidate(existing, attempted) {
25
30
  return (
26
31
  existing.sourceHead === attempted.sourceHead &&
@@ -37,18 +42,11 @@ export function matchesExactDevDeliveryCandidate(existing, attempted) {
37
42
  attempted.releaseBlockerPriority?.claimRoot
38
43
  );
39
44
  }
40
-
41
45
  export function reuseExactActiveDevDeliverySourceProof(active, input) {
42
46
  const exact =
43
47
  ["provisional", "qualified"].includes(active?.phase) &&
44
- [
45
- "pullRequestNumber",
46
- "assignmentRoot",
47
- "initiativeRoot",
48
- "sourceIdentityRoot",
49
- "deliveryClass",
50
- "priority",
51
- ].every((field) => active[field] === input[field]) &&
48
+ ["sourceRoot", "assignmentRoot", "initiativeRoot"].every((field) => active[field] === input[field]) &&
49
+ ["pullRequestNumber", "sourceIdentityRoot", "deliveryClass", "priority"].every((field) => active[field] === input[field]) &&
52
50
  matchesExactDevDeliveryCandidate(active, {
53
51
  ...input,
54
52
  sourceProofRoot: active.sourceProofRoot,
@@ -56,41 +54,22 @@ export function reuseExactActiveDevDeliverySourceProof(active, input) {
56
54
  return exact ? { ...input, sourceProofRoot: active.sourceProofRoot } : input;
57
55
  }
58
56
 
59
- export function createDevDeliveryCandidateIdentity(
60
- input,
61
- expected,
62
- deliveryClass,
63
- ) {
57
+ export function createDevDeliveryCandidateIdentity(input, expected, deliveryClass) {
64
58
  const identity = {
65
59
  repository: expected.repository,
66
60
  protectedBase: expected.protectedBase,
67
- pullRequestNumber: positiveInteger(
68
- input.pullRequestNumber,
69
- "pullRequestNumber",
70
- ),
71
- assignmentRoot: exactRoot(input.assignmentRoot, "assignmentRoot"),
72
- initiativeRoot: exactRoot(input.initiativeRoot, "initiativeRoot"),
73
- sourceIdentityRoot: exactRoot(
74
- input.sourceIdentityRoot,
75
- "sourceIdentityRoot",
76
- ),
61
+ pullRequestNumber: positiveInteger(input.pullRequestNumber, "pullRequestNumber"),
62
+ ...devDeliverySourceBinding(input),
63
+ sourceIdentityRoot: exactRoot(input.sourceIdentityRoot, "sourceIdentityRoot"),
77
64
  deliveryClass: deliveryClass(input.deliveryClass),
78
65
  };
79
66
  if (input.identitySemantics) {
80
- if (text(input.identitySemantics) !== CHAINED_ATTEMPT_IDENTITY) {
81
- throw new Error(
82
- `unsupported candidate identity semantics ${input.identitySemantics}`,
83
- );
84
- }
67
+ if (text(input.identitySemantics) !== CHAINED_ATTEMPT_IDENTITY) throw new Error(`unsupported candidate identity semantics ${input.identitySemantics}`);
85
68
  identity.identitySemantics = CHAINED_ATTEMPT_IDENTITY;
86
- identity.predecessorCandidateId = exactRoot(
87
- input.predecessorCandidateId,
88
- "predecessorCandidateId",
89
- );
69
+ identity.predecessorCandidateId = exactRoot(input.predecessorCandidateId, "predecessorCandidateId");
90
70
  }
91
71
  return { ...identity, candidateId: devDeliveryContentRoot(identity) };
92
72
  }
93
-
94
73
  export function validateDevDeliveryCandidateChain(candidates, terminalStates) {
95
74
  const precedingCandidates = new Map();
96
75
  const latestByPullRequest = new Map();
@@ -12,6 +12,7 @@ import {
12
12
  import {
13
13
  chainedDevDeliveryAttemptInput,
14
14
  createDevDeliveryCandidateIdentity,
15
+ devDeliverySourceBinding,
15
16
  EXACT_DEV_DELIVERY_PROOF_FIELDS,
16
17
  matchesExactDevDeliveryCandidate,
17
18
  validateDevDeliveryCandidateChain,
@@ -86,8 +87,7 @@ export function issueDevDeliveryWarrant(
86
87
  candidateId: candidate.candidateId,
87
88
  pullRequestNumber: candidate.pullRequestNumber,
88
89
  sourceHead: candidate.sourceHead,
89
- assignmentRoot: candidate.assignmentRoot,
90
- initiativeRoot: candidate.initiativeRoot,
90
+ ...devDeliverySourceBinding(candidate),
91
91
  sourceIdentityRoot: candidate.sourceIdentityRoot,
92
92
  sourcePatchRoot: candidate.sourcePatchRoot,
93
93
  sourceProofRoot: candidate.sourceProofRoot,
@@ -413,8 +413,7 @@ function submissionReceipt({ before, after, candidate, action, now }) {
413
413
  candidateId: candidate.candidateId,
414
414
  pullRequestNumber: candidate.pullRequestNumber,
415
415
  sourceHead: candidate.sourceHead,
416
- assignmentRoot: candidate.assignmentRoot,
417
- initiativeRoot: candidate.initiativeRoot,
416
+ ...devDeliverySourceBinding(candidate),
418
417
  sourceIdentityRoot: candidate.sourceIdentityRoot,
419
418
  sourcePatchRoot: candidate.sourcePatchRoot,
420
419
  sourceProofRoot: candidate.sourceProofRoot,
@@ -198,8 +198,8 @@ export function selectDevDeliveryWarrant(
198
198
  candidateId: transaction.result.candidate.candidateId,
199
199
  pullRequestNumber: transaction.result.candidate.pullRequestNumber,
200
200
  sourceHead: transaction.result.candidate.sourceHead,
201
- assignmentRoot: transaction.result.candidate.assignmentRoot,
202
- initiativeRoot: transaction.result.candidate.initiativeRoot,
201
+ ...candidateSourceBinding(transaction.result.candidate),
202
+
203
203
  sourceIdentityRoot: transaction.result.candidate.sourceIdentityRoot,
204
204
  sourcePatchRoot: transaction.result.candidate.sourcePatchRoot,
205
205
  sourceProofRoot: transaction.result.candidate.sourceProofRoot,
@@ -488,6 +488,7 @@ function createDevDeliverySuccessorWake(queue, now) {
488
488
  "candidateId",
489
489
  "pullRequestNumber",
490
490
  "sourceHead",
491
+ "sourceRoot",
491
492
  "assignmentRoot",
492
493
  "initiativeRoot",
493
494
  "sourceIdentityRoot",
@@ -586,3 +587,12 @@ export function observeDevDeliveryQueue(
586
587
  observedAt: currentTime,
587
588
  };
588
589
  }
590
+
591
+ function candidateSourceBinding(candidate) {
592
+ return candidate.sourceRoot
593
+ ? { sourceRoot: candidate.sourceRoot }
594
+ : {
595
+ assignmentRoot: candidate.assignmentRoot,
596
+ initiativeRoot: candidate.initiativeRoot,
597
+ };
598
+ }
@@ -3,6 +3,7 @@ import fs from "node:fs";
3
3
  import path from "node:path";
4
4
  import { macosJitRunnerLabel } from "./aws-macos-jit-core.mjs";
5
5
  import { windowsJitRunnerLabel } from "./aws-windows-jit-core.mjs";
6
+ export { writeGitHubOutputs } from "./github-output.mjs";
6
7
  export const RUNNER_PRESETS = Object.freeze({
7
8
  "github-hosted": [
8
9
  { id: "linux-x64", name: "Linux x64", platform: "linux", runner: '["ubuntu-24.04"]', capabilities: ["node"] },
@@ -1201,20 +1202,6 @@ export function validateExpectedArtifacts({ expected, files, summary }) {
1201
1202
  return { ok: true, source: "expected-artifacts-json", checks };
1202
1203
  }
1203
1204
 
1204
- export function writeGitHubOutputs(outputs) {
1205
- const outputPath = process.env.GITHUB_OUTPUT;
1206
- if (!outputPath) {
1207
- for (const [key, value] of Object.entries(outputs)) {
1208
- console.log(`${key}=${value}`);
1209
- }
1210
- return;
1211
- }
1212
- const lines = Object.entries(outputs).map(
1213
- ([key, value]) => `${key}=${value}`,
1214
- );
1215
- fs.appendFileSync(outputPath, `${lines.join("\n")}\n`);
1216
- }
1217
-
1218
1205
  export function findJsonFiles(root) {
1219
1206
  if (!fs.existsSync(root)) {
1220
1207
  return [];
@@ -1,4 +1,3 @@
1
- import fs from "node:fs";
2
1
  import path from "node:path";
3
2
  import {
4
3
  acquireDevDeliveryLandingWarrant,
@@ -66,6 +65,7 @@ function submitCandidate(state, options) {
66
65
  {
67
66
  pullRequestNumber: options.pullRequestNumber,
68
67
  sourceHead: options.sourceHead,
68
+ sourceRoot: options.sourceRoot,
69
69
  assignmentRoot: options.assignmentRoot,
70
70
  initiativeRoot: options.initiativeRoot,
71
71
  sourceIdentityRoot: options.sourceIdentityRoot,
@@ -276,16 +276,16 @@ export function devDeliveryAuthorityCliOptions(
276
276
  "source-head",
277
277
  environment.BUILDCHAIN_DEV_DELIVERY_SOURCE_HEAD,
278
278
  ),
279
- assignmentRoot: flag(
279
+ sourceRoot: flag(
280
280
  rest,
281
- "assignment-root",
282
- environment.BUILDCHAIN_DEV_DELIVERY_ASSIGNMENT_ROOT,
283
- ),
284
- initiativeRoot: flag(
285
- rest,
286
- "initiative-root",
287
- environment.BUILDCHAIN_DEV_DELIVERY_INITIATIVE_ROOT,
281
+ "source-root",
282
+ environment.BUILDCHAIN_WORK_SOURCE_ROOT ||
283
+ environment.BUILDCHAIN_DEV_DELIVERY_SOURCE_ROOT,
288
284
  ),
285
+ // Retired roots remain readable in persisted historical candidates.
286
+ // New authority submissions accept only the Work sourceRoot above.
287
+ // Retired CLI flags are intentionally ignored by this parser.
288
+ // This prevents producers from reconstructing obsolete identities.
289
289
  sourceIdentityRoot: flag(
290
290
  rest,
291
291
  "source-identity-root",
@@ -479,6 +479,7 @@ function cliInput(args) {
479
479
  export function sourceProofReuseCli(args = process.argv.slice(2)) {
480
480
  const [command = "", ...rest] = args;
481
481
  const input = cliInput(rest);
482
+ if (command === "predicates") return sourceQualificationPredicates(input);
482
483
  if (command === "seal") {
483
484
  const proof = sealSourceQualificationProof(input);
484
485
  writeJson(input.outputPath, proof);
@@ -527,7 +528,7 @@ export function sourceProofReuseCli(args = process.argv.slice(2)) {
527
528
  return decision;
528
529
  }
529
530
  throw new Error(
530
- "usage: dev-delivery-source-proof-reuse.mjs <seal|verify> [options]",
531
+ "usage: dev-delivery-source-proof-reuse.mjs <predicates|seal|verify> [options]",
531
532
  );
532
533
  }
533
534
 
@@ -1,8 +1,8 @@
1
+ import fs from "node:fs";
1
2
  export function flag(args, name, fallback = "") {
2
3
  const index = args.indexOf(`--${name}`);
3
4
  return index === -1 ? fallback : args[index + 1] || "";
4
5
  }
5
-
6
6
  export function hasFlag(args, name) {
7
7
  return args.includes(`--${name}`);
8
8
  }
@@ -79,16 +79,16 @@ export function devDeliveryCliOptions(args = [], environment = process.env) {
79
79
  "source-head",
80
80
  environment.BUILDCHAIN_DEV_DELIVERY_SOURCE_HEAD,
81
81
  ),
82
- expectedSourceHead: flag(
83
- rest,
84
- "expected-source-head",
85
- environment.BUILDCHAIN_DEV_DELIVERY_EXPECTED_SOURCE_HEAD,
86
- ),
87
- observedSourceHead: flag(
82
+ sourceRoot: flag(
88
83
  rest,
89
- "observed-source-head",
90
- environment.BUILDCHAIN_DEV_DELIVERY_OBSERVED_SOURCE_HEAD,
84
+ "source-root",
85
+ environment.BUILDCHAIN_WORK_SOURCE_ROOT ||
86
+ environment.BUILDCHAIN_DEV_DELIVERY_SOURCE_ROOT ||
87
+ sourceRootFromGitHubEvent(environment),
91
88
  ),
89
+ // prettier-ignore
90
+ ...{ expectedSourceHead: flag(rest, "expected-source-head", environment.BUILDCHAIN_DEV_DELIVERY_EXPECTED_SOURCE_HEAD), observedSourceHead: flag(rest, "observed-source-head", environment.BUILDCHAIN_DEV_DELIVERY_OBSERVED_SOURCE_HEAD) },
91
+
92
92
  assignmentRoot: flag(
93
93
  rest,
94
94
  "assignment-root",
@@ -291,3 +291,8 @@ export function devDeliveryCliOptions(args = [], environment = process.env) {
291
291
  json: hasFlag(rest, "json"),
292
292
  };
293
293
  }
294
+
295
+ // prettier-ignore
296
+ function sourceRootFromGitHubEvent(environment) {
297
+ try { const event = JSON.parse(fs.readFileSync(environment.GITHUB_EVENT_PATH, "utf8")); return event.client_payload?.candidate?.sourceRoot || JSON.parse(event.inputs?.["native-roots-json"] || "{}").sourceRoot || ""; } catch { return ""; }
298
+ }
@@ -206,8 +206,9 @@ function transitionFor(command, queue, options) {
206
206
  "pullRequestNumber",
207
207
  ),
208
208
  sourceHead: exactSha(options.sourceHead, "sourceHead"),
209
- assignmentRoot: exactRoot(options.assignmentRoot, "assignmentRoot"),
210
- initiativeRoot: exactRoot(options.initiativeRoot, "initiativeRoot"),
209
+ sourceRoot: options.sourceRoot,
210
+ assignmentRoot: options.assignmentRoot,
211
+ initiativeRoot: options.initiativeRoot,
211
212
  sourceIdentityRoot: exactRoot(
212
213
  options.sourceIdentityRoot,
213
214
  "sourceIdentityRoot",
@@ -0,0 +1,31 @@
1
+ import crypto from "node:crypto";
2
+ import fs from "node:fs";
3
+
4
+ function githubOutputRecord(key, value) {
5
+ const normalized = String(value ?? "");
6
+ if (!/[\r\n]/u.test(normalized)) return `${key}=${normalized}\n`;
7
+ const valueLines = normalized.split(/\r\n|\r|\n/u);
8
+ let delimiter = `BUILDCHAIN_OUTPUT_${crypto
9
+ .createHash("sha256")
10
+ .update(`${key}\0${normalized}`)
11
+ .digest("hex")}`;
12
+ while (valueLines.includes(delimiter)) delimiter += "_";
13
+ const separator = normalized.endsWith("\n") ? "" : "\n";
14
+ return `${key}<<${delimiter}\n${normalized}${separator}${delimiter}\n`;
15
+ }
16
+
17
+ export function writeGitHubOutputs(outputs) {
18
+ const outputPath = process.env.GITHUB_OUTPUT;
19
+ if (!outputPath) {
20
+ for (const [key, value] of Object.entries(outputs)) {
21
+ console.log(`${key}=${value}`);
22
+ }
23
+ return;
24
+ }
25
+ fs.appendFileSync(
26
+ outputPath,
27
+ Object.entries(outputs)
28
+ .map(([key, value]) => githubOutputRecord(key, value))
29
+ .join(""),
30
+ );
31
+ }
@@ -263,17 +263,17 @@ export function selectReleaseAssetPaths({
263
263
  `release candidate payload patterns matched no files: ${splitPatterns(patterns).join(", ")}`,
264
264
  );
265
265
  }
266
- const basenames = new Set();
266
+ const selectedByBasename = new Map();
267
+ const digest = (filePath) => digestFileSync(filePath, "sha256", "hex");
267
268
  for (const filePath of files) {
268
269
  const basename = path.basename(filePath);
269
- if (basenames.has(basename)) {
270
- throw new Error(
271
- `release candidate public asset basename is not unique: ${basename}`,
272
- );
273
- }
274
- basenames.add(basename);
270
+ const existing = selectedByBasename.get(basename);
271
+ if (!existing) selectedByBasename.set(basename, filePath);
272
+ else if (digest(existing) !== digest(filePath))
273
+ throw new Error(`release candidate public asset basename is not unique: ${basename}`);
275
274
  }
276
- return files;
275
+ // Repeated paths are safe only when they name the same immutable bytes.
276
+ return [...selectedByBasename.values()];
277
277
  }
278
278
 
279
279
  function packageNameFromArtifactPath(filePath) {
@@ -38,11 +38,8 @@ on:
38
38
  source-patch-root:
39
39
  description: "Semantic patch root"
40
40
  required: true
41
- assignment-root:
42
- description: "Native Assignment root"
43
- required: true
44
- initiative-root:
45
- description: "Parent Initiative root"
41
+ native-roots-json:
42
+ description: "Machine-supplied Work sourceRoot or historical root pair"
46
43
  required: true
47
44
  plan-root:
48
45
  description: "Native qualification plan root"
@@ -117,8 +114,8 @@ jobs:
117
114
  delivery-warrant-mode: required
118
115
  handoff-workflow-id: native-dev-delivery.yml
119
116
  source-workflow-id: ${{ inputs.source-workflow-id || '' }}
120
- assignment-root: ${{ github.event.client_payload.candidate.assignmentRoot || inputs.assignment-root }}
121
- initiative-root: ${{ github.event.client_payload.candidate.initiativeRoot || inputs.initiative-root }}
117
+ assignment-root: ${{ github.event.client_payload.candidate.assignmentRoot || fromJSON(inputs.native-roots-json || '{}').assignmentRoot || '' }}
118
+ initiative-root: ${{ github.event.client_payload.candidate.initiativeRoot || fromJSON(inputs.native-roots-json || '{}').initiativeRoot || '' }}
122
119
  source-identity-root: ${{ github.event.client_payload.candidate.sourceIdentityRoot || inputs.source-identity-root }}
123
120
  source-patch-root: ${{ github.event.client_payload.candidate.sourcePatchRoot || inputs.source-patch-root }}
124
121
  plan-root: ${{ github.event.client_payload.candidate.planRoot || inputs.plan-root }}