@kungfu-tech/buildchain 2.14.1 → 2.14.2-alpha.1

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.
@@ -4,10 +4,10 @@
4
4
  "status": "passed",
5
5
  "summary": {
6
6
  "cliCommandCount": 83,
7
- "workflowCount": 47,
7
+ "workflowCount": 48,
8
8
  "actionCount": 4,
9
9
  "sitePageCount": 50,
10
- "docCommandRefCount": 256,
10
+ "docCommandRefCount": 257,
11
11
  "failureCount": 0
12
12
  },
13
13
  "enumerated": {
@@ -1233,6 +1233,7 @@
1233
1233
  "cadence",
1234
1234
  "capabilities",
1235
1235
  "dry-run",
1236
+ "landing-mode",
1236
1237
  "max-actions",
1237
1238
  "merge-method",
1238
1239
  "mode",
@@ -1242,7 +1243,7 @@
1242
1243
  "same-repository-only",
1243
1244
  "target-branch"
1244
1245
  ],
1245
- "inputCount": 15,
1246
+ "inputCount": 16,
1246
1247
  "secrets": [
1247
1248
  "github-token"
1248
1249
  ],
@@ -1327,6 +1328,17 @@
1327
1328
  ],
1328
1329
  "outputCount": 7
1329
1330
  },
1331
+ {
1332
+ "id": "dev-merge-queue-governance",
1333
+ "path": ".github/workflows/dev-merge-queue-governance.yml",
1334
+ "reusable": false,
1335
+ "inputs": [],
1336
+ "inputCount": 0,
1337
+ "secrets": [],
1338
+ "secretCount": 0,
1339
+ "outputs": [],
1340
+ "outputCount": 0
1341
+ },
1330
1342
  {
1331
1343
  "id": "dev-pr-auto-merge",
1332
1344
  "path": ".github/workflows/dev-pr-auto-merge.yml",
@@ -1337,6 +1349,7 @@
1337
1349
  "buildchain-ref",
1338
1350
  "buildchain-repository",
1339
1351
  "dry-run",
1352
+ "landing-mode",
1340
1353
  "max-merges",
1341
1354
  "merge-method",
1342
1355
  "ready-label",
@@ -1345,18 +1358,20 @@
1345
1358
  "same-repository-only",
1346
1359
  "target-branch"
1347
1360
  ],
1348
- "inputCount": 12,
1361
+ "inputCount": 13,
1349
1362
  "secrets": [
1350
1363
  "github-token"
1351
1364
  ],
1352
1365
  "secretCount": 1,
1353
1366
  "outputs": [
1367
+ "action-count",
1368
+ "enqueued-count",
1354
1369
  "evaluated-count",
1355
1370
  "final-base-sha",
1356
1371
  "merged-count",
1357
1372
  "skipped-count"
1358
1373
  ],
1359
- "outputCount": 4
1374
+ "outputCount": 6
1360
1375
  },
1361
1376
  {
1362
1377
  "id": "npm-publish",
@@ -1486,6 +1501,7 @@
1486
1501
  "buildchain-ref",
1487
1502
  "buildchain-repository",
1488
1503
  "dry-run",
1504
+ "landing-mode",
1489
1505
  "max-actions",
1490
1506
  "merge-method",
1491
1507
  "ready-label",
@@ -1494,7 +1510,7 @@
1494
1510
  "same-repository-only",
1495
1511
  "target-branch"
1496
1512
  ],
1497
- "inputCount": 12,
1513
+ "inputCount": 13,
1498
1514
  "secrets": [
1499
1515
  "github-token"
1500
1516
  ],
@@ -2430,6 +2446,11 @@
2430
2446
  "path": "docs/cli.md",
2431
2447
  "command": "buildchain dev merge-queue"
2432
2448
  },
2449
+ {
2450
+ "id": "dev",
2451
+ "path": "docs/cli.md",
2452
+ "command": "buildchain dev merge-queue --from-config"
2453
+ },
2433
2454
  {
2434
2455
  "id": "dev",
2435
2456
  "path": "docs/release-governance.md",
@@ -3482,8 +3503,8 @@
3482
3503
  "workflowRegistryPath": "dist/site/workflow-registry.json",
3483
3504
  "pageRegistryPath": "dist/site/page-registry.json",
3484
3505
  "cliRegistryDigest": "b469949f77ed7777f23fe68c54daf6d2c20d3afc97f3bbd5a178a91202a068d0",
3485
- "workflowRegistryDigest": "62b7ca87803c461e1e1436a477c3b6b70103eed84dbf14d855d383e810d7d71e",
3486
- "pageRegistryDigest": "c76ebcc729f2c9922605e02ba369c8e839064d6090735362ec3fc4983a20accb"
3506
+ "workflowRegistryDigest": "2ad4284a9e275cec6fbc6593a470f9d443e26f7aa880bedf9fa0671448369f2f",
3507
+ "pageRegistryDigest": "53c5c0918268a1ea769a3841ad3b5ad553e81b0fcd602c8289dc049e3559ff89"
3487
3508
  },
3488
3509
  "comparison": {
3489
3510
  "missingCliRegistry": [],
@@ -280,6 +280,19 @@
280
280
  "runnerPolicy": "unqualified",
281
281
  "notes": ""
282
282
  },
283
+ {
284
+ "workflowPath": ".github/workflows/dev-merge-queue-governance.yml",
285
+ "authorityClass": "governance-write",
286
+ "publicationCapable": false,
287
+ "capabilityIds": [],
288
+ "credentialMode": "none",
289
+ "publisherWorkflowMode": "fixed",
290
+ "publisherWorkflowPath": ".github/workflows/dev-merge-queue-governance.yml",
291
+ "environment": "",
292
+ "environmentMode": "fixed",
293
+ "runnerPolicy": "unqualified",
294
+ "notes": ""
295
+ },
283
296
  {
284
297
  "workflowPath": ".github/workflows/dev-pr-auto-merge.yml",
285
298
  "authorityClass": "governance-write",
@@ -657,6 +670,11 @@
657
670
  "signals": [],
658
671
  "classified": false
659
672
  },
673
+ {
674
+ "path": ".github/workflows/dev-merge-queue-governance.yml",
675
+ "signals": [],
676
+ "classified": true
677
+ },
660
678
  {
661
679
  "path": ".github/workflows/dev-pr-auto-merge.yml",
662
680
  "signals": [
@@ -774,5 +792,5 @@
774
792
  "classified": false
775
793
  }
776
794
  ],
777
- "registryDigest": "760215fb39e6c85890c925e924c538a766d78abd6319794c8799fb47c23dec3d"
795
+ "registryDigest": "24c7f5210da277b79ce13356c439c14ea49f6c54ba9e083f42ce47fdfdacc55c"
778
796
  }
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
3
  "contract": "kungfu-buildchain-publication-release-registry",
4
- "generatedAt": "2026-07-17T00:55:24.253Z",
5
- "publishedAt": "2026-07-17T00:55:24.253Z",
4
+ "generatedAt": "2026-07-17T06:47:39.218Z",
5
+ "publishedAt": "2026-07-17T06:47:39.218Z",
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": "d962181c3023e587488a5276b10307007cc5a13f",
22
+ "sourceRevision": "4f111d56131695265eaf786eb86cae5202247111",
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": "2.14.1",
35
+ "version": "2.14.2-alpha.1",
36
36
  "versionSource": "package.json#version"
37
37
  },
38
38
  "sourceKind": "package-site-bundle",
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
3
  "contract": "kungfu-buildchain-site-manifest",
4
- "generatedAt": "2026-07-17T00:55:24.253Z",
5
- "publishedAt": "2026-07-17T00:55:24.253Z",
4
+ "generatedAt": "2026-07-17T06:47:39.218Z",
5
+ "publishedAt": "2026-07-17T06:47:39.218Z",
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": "d962181c3023e587488a5276b10307007cc5a13f",
22
+ "sourceRevision": "4f111d56131695265eaf786eb86cae5202247111",
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": "2.14.1",
40
+ "version": "2.14.2-alpha.1",
41
41
  "versionSource": "package.json#version"
42
42
  },
43
43
  "entrypoint": "buildchain-site.json",
@@ -189,7 +189,7 @@
189
189
  "path": "docs/cli.md",
190
190
  "plane": "use",
191
191
  "exists": true,
192
- "digest": "sha256:9ecf8c220b5ff02ee5719cb877d4b2b159c3d683af288630eae0013d9d906373"
192
+ "digest": "sha256:1733f9377938a16e6de77511546be7de67c5ab8816220d693fd46f55450a5148"
193
193
  },
194
194
  {
195
195
  "id": "build-facts",
@@ -229,7 +229,7 @@
229
229
  "path": "docs/publish-transaction.md",
230
230
  "plane": "verify",
231
231
  "exists": true,
232
- "digest": "sha256:cc2f4c9d2b9988962a237bbc7e8da83385d45585e2b2dd105ff4c4334a74c05d"
232
+ "digest": "sha256:950ca4fb2f7ab0a7d40775593e3864f8bb1229f8543b266b00154af82c619e95"
233
233
  },
234
234
  {
235
235
  "id": "release-governance",
@@ -237,7 +237,7 @@
237
237
  "path": "docs/release-governance.md",
238
238
  "plane": "why",
239
239
  "exists": true,
240
- "digest": "sha256:5cf4bf4332119531f6aaa1c123d7f64e6af4a61611c4e4a33d40bd9fb46448cf"
240
+ "digest": "sha256:e64ffd6183eaa7b73f8c0c133a645ced22212bca70c9609ad5f667cf3830aaae"
241
241
  },
242
242
  {
243
243
  "id": "release-flow",
@@ -245,7 +245,7 @@
245
245
  "path": "docs/release-flow.md",
246
246
  "plane": "verify",
247
247
  "exists": true,
248
- "digest": "sha256:a2f68d42f34acc35940e135285df5ba510d91b15b9d9ede8cabbe8bfa6ab0305"
248
+ "digest": "sha256:fc6495a7b5124c17c880777e16fc98e60ed7766ec9a958abfca3030bdc2c321e"
249
249
  },
250
250
  {
251
251
  "id": "runtime-train-validation",
@@ -261,7 +261,7 @@
261
261
  "path": "docs/versioning.md",
262
262
  "plane": "why",
263
263
  "exists": true,
264
- "digest": "sha256:c3dce313b846fb36c69e4a725d086226ff2e875c376cc10e8554a0aff2f67c93"
264
+ "digest": "sha256:e856ec8aee11ff4bd2760425a8950538a91245cd5624c22c8768af50d6b1a8ce"
265
265
  },
266
266
  {
267
267
  "id": "web-surface-deployments",
@@ -269,7 +269,7 @@
269
269
  "path": "docs/web-surface-deployments.md",
270
270
  "plane": "use",
271
271
  "exists": true,
272
- "digest": "sha256:797d8f0e81974a49125b17256bb8b4a85fc60673e06d6bbecbbf399651163437"
272
+ "digest": "sha256:856a7602cf1c2d3a0a540cdf0d64566914f79dde24417c92089f0466bee25df1"
273
273
  }
274
274
  ],
275
275
  "facts": [
@@ -879,6 +879,7 @@
879
879
  "cadence",
880
880
  "capabilities",
881
881
  "dry-run",
882
+ "landing-mode",
882
883
  "max-actions",
883
884
  "merge-method",
884
885
  "mode",
@@ -888,7 +889,7 @@
888
889
  "same-repository-only",
889
890
  "target-branch"
890
891
  ],
891
- "inputCount": 15,
892
+ "inputCount": 16,
892
893
  "secrets": [
893
894
  "github-token"
894
895
  ],
@@ -991,6 +992,20 @@
991
992
  "capabilityGroup": "api-cli-reference",
992
993
  "status": "active"
993
994
  },
995
+ {
996
+ "id": "dev-merge-queue-governance",
997
+ "path": ".github/workflows/dev-merge-queue-governance.yml",
998
+ "reusable": false,
999
+ "inputs": [],
1000
+ "inputCount": 0,
1001
+ "secrets": [],
1002
+ "secretCount": 0,
1003
+ "outputs": [],
1004
+ "outputCount": 0,
1005
+ "surface": "repository-workflow",
1006
+ "capabilityGroup": "api-cli-reference",
1007
+ "status": "active"
1008
+ },
994
1009
  {
995
1010
  "id": "dev-pr-auto-merge",
996
1011
  "path": ".github/workflows/dev-pr-auto-merge.yml",
@@ -1001,6 +1016,7 @@
1001
1016
  "buildchain-ref",
1002
1017
  "buildchain-repository",
1003
1018
  "dry-run",
1019
+ "landing-mode",
1004
1020
  "max-merges",
1005
1021
  "merge-method",
1006
1022
  "ready-label",
@@ -1009,18 +1025,20 @@
1009
1025
  "same-repository-only",
1010
1026
  "target-branch"
1011
1027
  ],
1012
- "inputCount": 12,
1028
+ "inputCount": 13,
1013
1029
  "secrets": [
1014
1030
  "github-token"
1015
1031
  ],
1016
1032
  "secretCount": 1,
1017
1033
  "outputs": [
1034
+ "action-count",
1035
+ "enqueued-count",
1018
1036
  "evaluated-count",
1019
1037
  "final-base-sha",
1020
1038
  "merged-count",
1021
1039
  "skipped-count"
1022
1040
  ],
1023
- "outputCount": 4,
1041
+ "outputCount": 6,
1024
1042
  "surface": "dev-governance",
1025
1043
  "capabilityGroup": "governance-versioning",
1026
1044
  "status": "active"
@@ -1162,6 +1180,7 @@
1162
1180
  "buildchain-ref",
1163
1181
  "buildchain-repository",
1164
1182
  "dry-run",
1183
+ "landing-mode",
1165
1184
  "max-actions",
1166
1185
  "merge-method",
1167
1186
  "ready-label",
@@ -1170,7 +1189,7 @@
1170
1189
  "same-repository-only",
1171
1190
  "target-branch"
1172
1191
  ],
1173
- "inputCount": 12,
1192
+ "inputCount": 13,
1174
1193
  "secrets": [
1175
1194
  "github-token"
1176
1195
  ],
package/docs/cli.md CHANGED
@@ -208,6 +208,31 @@ required status checks from strict to loose, preserves the required check
208
208
  identities, and is safe to repeat. `gh` must be authenticated with repository
209
209
  Administration write permission for apply mode.
210
210
 
211
+ Repositories can make that policy declarative in `buildchain.toml`:
212
+
213
+ ```toml
214
+ [governance.dev.merge_queue]
215
+ mode = "enabled" # enabled, inherit, or disabled
216
+ required_workflows = [".github/workflows/verify.yml"]
217
+ check_response_timeout_minutes = 120
218
+ max_entries_to_build = 1
219
+ bypass_users = ["release-owner"]
220
+ ```
221
+
222
+ Use `buildchain dev merge-queue --from-config` to resolve and reconcile the
223
+ declaration. `enabled` requires an exact queue on the target dev branch;
224
+ `disabled` suppresses automatic queue creation; `inherit` copies the active
225
+ default dev branch's queue parameters and bypass actors. When the table is
226
+ absent, release-line bootstrap uses the backward-compatible `inherit` mode.
227
+ Every inherited or explicitly enabled queue still validates each declared
228
+ required workflow before any mutation. For a legacy repository with no table,
229
+ an already-active exact queue on the current default dev branch is accepted as
230
+ the inheritance evidence; new declarations should list the workflows so future
231
+ changes are revalidated from source.
232
+ The `Dev Merge Queue Governance` workflow runs this reconciliation after
233
+ governance-relevant changes land on a dev branch; its manual dispatch remains
234
+ dry-run by default.
235
+
211
236
  `buildchain release line open` plans or writes the first version-state commit
212
237
  for a new semver minor line. It does not publish anything. The dry-run mode is
213
238
  the default and returns the dev/alpha/release refs, protection contract, default
@@ -224,8 +249,9 @@ buildchain release line open \
224
249
  The write mode only updates local version-state files. The repository workflow
225
250
  `Release Line Bootstrap` wraps this command and, when `apply=true`, commits the
226
251
  initial version state, creates `dev/vX/vX.Y`, `alpha/vX/vX.Y`, and
227
- `release/vX/vX.Y`, applies one-review branch protection, switches the default
228
- branch, and opens the first dev-to-alpha channel PR:
252
+ `release/vX/vX.Y`, applies one-review branch protection, reconciles declared or
253
+ inherited merge-queue governance, switches the default branch only after that
254
+ reconciliation succeeds, and opens the first dev-to-alpha channel PR:
229
255
 
230
256
  ```bash
231
257
  buildchain release line open \
@@ -395,6 +395,20 @@ last transient error seen before a rerun.
395
395
  An exact tag at an unrelated SHA is still a material conflict and blocks
396
396
  recovery.
397
397
 
398
+ Governed retries distinguish unrelated channel advancement from advancement
399
+ made by their own durable transaction. An unrelated descendant remains an
400
+ auditable `superseded-promotion` no-op. When the target ref is exactly the
401
+ recorded `release_sha` for the requested source, target, and expected version,
402
+ Buildchain resumes finalization, restores publish evidence, and emits the
403
+ release-passport paths needed by downstream controller receipts.
404
+
405
+ Publication authority planning applies the same occupied-version rule as the
406
+ later mutation step. If a current alpha transaction already contains published
407
+ material and regenerating version state would create new release material, the
408
+ planner advances to the next alpha before sealing authority. It never seals the
409
+ old published version and then lets the publisher discover a different version
410
+ inside the mutation boundary.
411
+
398
412
  If finalization fails after an exact Git tag is created, the next run reads the
399
413
  durable `finalizing` state, verifies the exact tag points at the recorded
400
414
  release SHA, and retries the remaining floating refs. An exact tag at a
@@ -108,12 +108,17 @@ When the workflow is run with `apply=true`, Buildchain:
108
108
  - applies branch protection with one approving review and the configured
109
109
  required status check; dev starts strict, while alpha and release also require
110
110
  the pair-specific `verify` aggregate without a source-up-to-date ancestry loop;
111
+ - reconciles the new dev branch's explicitly declared merge queue, or inherits
112
+ the exact queue parameters and bypass actors from the current default dev
113
+ branch when the policy is `inherit` or absent;
111
114
  - switches the repository default branch to the new dev line when requested;
112
115
  - opens the first `dev/v2/v2.10 -> alpha/v2/v2.10` channel PR when requested.
113
116
 
114
117
  This makes minor-line creation a single audited operation. The channel PR still
115
118
  goes through the normal verify/review/promotion path before an alpha is
116
- published.
119
+ published. Queue reconciliation runs after branch protection and before the
120
+ default-branch switch, so a failed governance apply leaves the old active line
121
+ in place and the idempotently created new refs can be retried.
117
122
 
118
123
  ## Alpha Promotion
119
124
 
@@ -411,7 +411,8 @@ buildchain dev merge-queue \
411
411
  --repository owner/repository \
412
412
  --branch dev/v4/v4.0 \
413
413
  --workflow .github/workflows/source-acceptance.yml \
414
- --workflow .github/workflows/affected-native-pr.yml
414
+ --workflow .github/workflows/affected-native-pr.yml \
415
+ --bypass-app dedicated-release-app
415
416
  ```
416
417
 
417
418
  After reviewing the plan, repeat with `--apply`. Buildchain creates or updates
@@ -423,6 +424,31 @@ protection. The ruleset uses the first merge method that the repository itself
423
424
  allows, and fails closed when the repository has no enabled merge method.
424
425
  Re-running the command is idempotent.
425
426
 
427
+ The repository policy can be declared once instead of repeated as CLI flags:
428
+
429
+ ```toml
430
+ [governance.dev.merge_queue]
431
+ mode = "inherit"
432
+ required_workflows = [".github/workflows/verify.yml"]
433
+ ```
434
+
435
+ `enabled` explicitly requires Buildchain to create or update an exact-branch
436
+ queue; `inherit` copies queue parameters and bypass actors from the repository's
437
+ current default dev branch; `disabled` prevents automatic queue creation. An
438
+ absent declaration behaves as `inherit` during release-line bootstrap so a new
439
+ major or minor line does not silently lose governance already active on the
440
+ previous line. Required status-check identities still come from the new
441
+ branch's own classic protection rather than being copied from the old branch.
442
+
443
+ Merge-queue rules also reject generated post-publish version-state ref updates.
444
+ When the sealed promotion workflow uses a dedicated GitHub App, user, or team
445
+ already declared by release governance, repeat `--bypass-app`, `--bypass-user`,
446
+ or `--bypass-team` to project that exact actor into the ruleset. Bypass actors
447
+ are never inferred and broad repository or organization roles are not accepted.
448
+ This keeps ordinary feature PRs on the predecessor-aligned queue path while the
449
+ sealed publication authority can finish its machine-verified bookkeeping. The
450
+ dry-run receipt exposes the exact actor IDs before `--apply` changes GitHub.
451
+
426
452
  Buildchain provides the reusable
427
453
  `.github/workflows/dev-pr-auto-merge.yml` workflow for repositories that want a
428
454
  scheduled or manual "merge ready dev PRs" pass. The consumer repository owns
@@ -435,9 +461,21 @@ The workflow defaults are conservative. A PR is skipped unless it targets the
435
461
  configured dev line, is not a draft, has the ready label, has no block label,
436
462
  comes from the same repository, uses an allowed work-branch prefix, has a
437
463
  current approval, is mergeable, and has the configured required checks passing.
438
- After each merge, the next PR is re-evaluated before it can move the protected
439
- dev branch. This prevents one merge from silently making the next candidate
440
- stale or conflicting.
464
+ `landing-mode: auto` reads the target branch's native merge-queue state. When a
465
+ queue exists, Buildchain never calls the direct merge endpoint: it admits at
466
+ most one PR against the observed target-branch SHA and immutable PR head, then
467
+ calls GraphQL `enqueuePullRequest` with `expectedHeadOid`. GitHub's
468
+ `merge_group` checks remain the final authority for the projected merge.
469
+
470
+ The admission receipt records the expected and observed base/head SHAs, policy
471
+ checks, decision, reason, and active predecessor. Buildchain re-reads the base,
472
+ head, mergeability, and native queue immediately before enqueueing. Base or
473
+ head drift fails closed, an active queue entry blocks admission, and a rejected
474
+ ready predecessor leaves its PR open while later PRs receive
475
+ `blocked-by-predecessor`. Workflow concurrency serializes Buildchain-owned
476
+ admission runs; GitHub still owns the atomic queue and protected-ref update.
477
+ Repositories may explicitly select `landing-mode: direct` only when the target
478
+ branch has no native queue. Queue presence always disables the direct path.
441
479
 
442
480
  The canonical consumer required check context is `check / check`, matching the
443
481
  reusable workflow call plus its `check` job. Buildchain's own `Verify` workflow
@@ -497,6 +535,7 @@ jobs:
497
535
  ready-label: ready
498
536
  block-labels: blocked,do-not-merge
499
537
  max-merges: 1
538
+ landing-mode: auto
500
539
  dry-run: ${{ inputs.dry-run || false }}
501
540
  ```
502
541
 
@@ -61,6 +61,7 @@ repository changes are patch".
61
61
 
62
62
  | Date | Action | Line | Faces | Class | Rationale | PR |
63
63
  | --- | --- | --- | --- | --- | --- | --- |
64
+ | 2026-07-17 | extend-minor | `v2.14` | merge-queue-config, release-line-governance-inheritance | additive | Buildchain config can explicitly enable, inherit, or disable exact dev-channel merge queues, and release-line bootstrap reconciles the declared or inherited policy before moving the repository default branch. | |
64
65
  | 2026-07-16 | open-minor | `v2.14` | dev-merge-queue-governance | additive | The public CLI adds a dry-run-first, idempotent merge-queue governance command that verifies required workflow event compatibility before applying an exact dev-channel ruleset and removing the strict up-to-date race. | |
65
66
  | 2026-07-15 | open-minor | `v2.13` | artifact-verification-envelope, package-subpaths | additive | The public envelope seals exact artifact, provenance, identity, lifecycle, revocation, and existing KFD assessment roots into one consumer-ready KFX admission input, with a dedicated Node API export and fail-closed verifier. | |
66
67
  | 2026-07-11 | open-minor | `v2.12` | channel-build-router, channel-selection-protocol | additive | The public `build.yml` reusable workflow lets consumers declare one build job while Buildchain selects generic major alpha for development/prerelease intent and stable major for production release intent, with explicit overrides, separate locks, and fail-closed ambiguity handling. | |
@@ -745,7 +745,10 @@ When enabled, Buildchain owns the full release apply state machine:
745
745
  operator can verify staging from the PR page and use merge as the approval
746
746
  action. Consumers do not need to hand-write `gh pr create` or production
747
747
  release-intent glue.
748
- - Production runs when `production-apply` is true and either:
748
+ - `production-apply=true` enables the production capability; it does not request
749
+ production for every event. Ordinary `main` pushes remain staging-only and
750
+ can create or update a release PR. Production runs only when the capability
751
+ is enabled and either:
749
752
  - a `workflow_dispatch` passes `production-approved=true` and the triggering
750
753
  actor currently has `write`, `maintain`, or `admin` permission; or
751
754
  - `production-release-on-main=true` and the `main` push commit is associated
@@ -794,7 +797,7 @@ jobs:
794
797
  build-command: npm run build
795
798
  verify-command: npm run check
796
799
  artifact-path: dist
797
- production-apply: ${{ github.event_name == 'push' && github.ref_name == 'main' }}
800
+ production-apply: true
798
801
  production-release-on-main: true
799
802
  production-release-label: buildchain-release
800
803
  production-release-head-prefix: release/
@@ -804,6 +807,13 @@ jobs:
804
807
  production-environment: production
805
808
  ```
806
809
 
810
+ Keep `production-apply` enabled in the caller when the repository supports
811
+ production. Buildchain derives whether the current event may use that
812
+ capability: an ordinary `main` push plans and applies staging, a matching
813
+ reviewed release PR merge authorizes production, and an approved trusted manual
814
+ dispatch authorizes production. Inputs from an untrusted event cannot turn that
815
+ decision on.
816
+
807
817
  `production-release-pr-mode` controls the post-staging handoff:
808
818
 
809
819
  | Mode | Behavior |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kungfu-tech/buildchain",
3
- "version": "2.14.1",
3
+ "version": "2.14.2-alpha.1",
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,6 +20,7 @@ const SUPPORTED_PUBLISH_AUTH = new Set(["trusted-publishing", "npm-token"]);
20
20
  const SUPPORTED_PUBLISH_KINDS = new Set(["npm-package", "npm-paper-package"]);
21
21
  const SUPPORTED_PACKAGE_SET_ORDER = new Set(["as-provided", "platforms-first-main-last"]);
22
22
  const SUPPORTED_STABLE_RELEASE_STRATEGIES = new Set(["manual", "latest-qualified-alpha"]);
23
+ const SUPPORTED_MERGE_QUEUE_MODES = new Set(["inherit", "enabled", "disabled"]);
23
24
  const SUPPORTED_NATIVE_COMPILER_CACHE = new Set(["auto", "ccache", "sccache", "none"]);
24
25
  const WEB_SURFACE_CHANNELS = ["preview", "staging", "production"];
25
26
  const SUPPORTED_CHANNEL_VISIBILITY = new Set(["ephemeral", "protected", "public", "internal"]);
@@ -184,6 +185,9 @@ export function normalizeBuildchainConfig(config) {
184
185
  if (normalized.release !== undefined) {
185
186
  normalized.release = normalizeReleaseSection(normalized.release);
186
187
  }
188
+ if (normalized.governance !== undefined) {
189
+ normalized.governance = normalizeGovernanceSection(normalized.governance);
190
+ }
187
191
  if (normalized.channels !== undefined) {
188
192
  normalized.channels = normalizeChannelsSection(normalized.channels, normalized.project);
189
193
  }
@@ -219,6 +223,53 @@ export function normalizeBuildchainConfig(config) {
219
223
  return normalized;
220
224
  }
221
225
 
226
+ function normalizeGovernanceSection(governance) {
227
+ assertPlainObject(governance, "governance");
228
+ const normalized = { ...governance };
229
+ if (governance.dev !== undefined) {
230
+ assertPlainObject(governance.dev, "governance.dev");
231
+ normalized.dev = { ...governance.dev };
232
+ if (governance.dev.merge_queue !== undefined) {
233
+ const mergeQueue = assertPlainObject(governance.dev.merge_queue, "governance.dev.merge_queue");
234
+ const mode = mergeQueue.mode === undefined
235
+ ? "inherit"
236
+ : assertString(mergeQueue.mode, "governance.dev.merge_queue.mode");
237
+ if (!SUPPORTED_MERGE_QUEUE_MODES.has(mode)) {
238
+ throw new Error("governance.dev.merge_queue.mode must be one of inherit, enabled, or disabled");
239
+ }
240
+ const checkResponseTimeoutMinutes = mergeQueue.check_response_timeout_minutes === undefined
241
+ ? 120
242
+ : Number(mergeQueue.check_response_timeout_minutes);
243
+ const maxEntriesToBuild = mergeQueue.max_entries_to_build === undefined
244
+ ? 1
245
+ : Number(mergeQueue.max_entries_to_build);
246
+ if (!Number.isInteger(checkResponseTimeoutMinutes) || checkResponseTimeoutMinutes < 1) {
247
+ throw new Error("governance.dev.merge_queue.check_response_timeout_minutes must be a positive integer");
248
+ }
249
+ if (!Number.isInteger(maxEntriesToBuild) || maxEntriesToBuild < 1) {
250
+ throw new Error("governance.dev.merge_queue.max_entries_to_build must be a positive integer");
251
+ }
252
+ normalized.dev = {
253
+ ...governance.dev,
254
+ mergeQueue: {
255
+ mode,
256
+ requiredWorkflows: normalizeStringArray(
257
+ mergeQueue.required_workflows,
258
+ "governance.dev.merge_queue.required_workflows",
259
+ ),
260
+ checkResponseTimeoutMinutes,
261
+ maxEntriesToBuild,
262
+ bypassApps: normalizeStringArray(mergeQueue.bypass_apps, "governance.dev.merge_queue.bypass_apps"),
263
+ bypassUsers: normalizeStringArray(mergeQueue.bypass_users, "governance.dev.merge_queue.bypass_users"),
264
+ bypassTeams: normalizeStringArray(mergeQueue.bypass_teams, "governance.dev.merge_queue.bypass_teams"),
265
+ },
266
+ };
267
+ delete normalized.dev.merge_queue;
268
+ }
269
+ }
270
+ return normalized;
271
+ }
272
+
222
273
  function normalizeReleaseSection(release) {
223
274
  assertPlainObject(release, "release");
224
275
  const normalized = { ...release };
@@ -1451,6 +1502,7 @@ export function validateBuildchainConfig(
1451
1502
  lifecycleStages,
1452
1503
  publish: loadedConfig.config.publish,
1453
1504
  release: loadedConfig.config.release,
1505
+ governance: loadedConfig.config.governance,
1454
1506
  facts: loadedConfig.config.facts,
1455
1507
  publication: loadedConfig.config.publication,
1456
1508
  };
@@ -25,6 +25,7 @@ const DESCRIPTORS = Object.freeze([
25
25
  [".github/workflows/buildchain-patrol.yml", "governance-write"],
26
26
  [".github/workflows/buildchain-ref-promotion.yml", "governance-write"],
27
27
  [".github/workflows/buildchain-stable-candidate-patrol.yml", "governance-write"],
28
+ [".github/workflows/dev-merge-queue-governance.yml", "governance-write"],
28
29
  [".github/workflows/dev-pr-auto-merge.yml", "governance-write"],
29
30
  [".github/workflows/npm-publish.yml", "dry-run-only"],
30
31
  [".github/workflows/paper-release-sealed.yml", "product-publication", true, ["npm-publish", "github-release"], "trusted-publishing", "none", "fixed", "caller-bound"],