agent-merge-broker 0.12.0 → 0.13.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.
Files changed (61) hide show
  1. package/CHANGELOG.md +69 -2
  2. package/README.md +219 -77
  3. package/ROADMAP.md +118 -0
  4. package/VISION.md +140 -0
  5. package/dist/broker.d.ts +24 -2
  6. package/dist/broker.d.ts.map +1 -1
  7. package/dist/broker.js +254 -54
  8. package/dist/broker.js.map +1 -1
  9. package/dist/cli.js +167 -21
  10. package/dist/cli.js.map +1 -1
  11. package/dist/config.d.ts +2 -0
  12. package/dist/config.d.ts.map +1 -1
  13. package/dist/config.js +86 -4
  14. package/dist/config.js.map +1 -1
  15. package/dist/gate-authority.d.ts +22 -0
  16. package/dist/gate-authority.d.ts.map +1 -0
  17. package/dist/gate-authority.js +288 -0
  18. package/dist/gate-authority.js.map +1 -0
  19. package/dist/git.d.ts +137 -7
  20. package/dist/git.d.ts.map +1 -1
  21. package/dist/git.js +2106 -51
  22. package/dist/git.js.map +1 -1
  23. package/dist/index.d.ts +2 -2
  24. package/dist/index.d.ts.map +1 -1
  25. package/dist/index.js +2 -2
  26. package/dist/index.js.map +1 -1
  27. package/dist/publisher.js +1 -1
  28. package/dist/publisher.js.map +1 -1
  29. package/dist/serve-log.d.ts +2 -0
  30. package/dist/serve-log.d.ts.map +1 -1
  31. package/dist/serve-log.js +7 -2
  32. package/dist/serve-log.js.map +1 -1
  33. package/dist/status.d.ts.map +1 -1
  34. package/dist/status.js +21 -0
  35. package/dist/status.js.map +1 -1
  36. package/dist/store.d.ts +21 -3
  37. package/dist/store.d.ts.map +1 -1
  38. package/dist/store.js +141 -28
  39. package/dist/store.js.map +1 -1
  40. package/dist/submission.d.ts +30 -0
  41. package/dist/submission.d.ts.map +1 -0
  42. package/dist/submission.js +619 -0
  43. package/dist/submission.js.map +1 -0
  44. package/dist/types.d.ts +127 -2
  45. package/dist/types.d.ts.map +1 -1
  46. package/dist/types.js +2 -0
  47. package/dist/types.js.map +1 -1
  48. package/dist/validation.d.ts +4 -0
  49. package/dist/validation.d.ts.map +1 -1
  50. package/dist/validation.js +178 -12
  51. package/dist/validation.js.map +1 -1
  52. package/docs/ARCHITECTURE.md +301 -25
  53. package/docs/COMPATIBILITY.md +200 -19
  54. package/docs/GETTING_STARTED.md +194 -19
  55. package/docs/PROTOCOL.md +348 -27
  56. package/docs/RELEASING.md +1 -1
  57. package/docs/SECURITY.md +177 -8
  58. package/package.json +8 -3
  59. package/schemas/config.schema.json +16 -4
  60. package/schemas/gate-authority.schema.json +39 -0
  61. package/schemas/submission.schema.json +160 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,71 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.13.0 — 2026-09-04
4
+
5
+ ### Added
6
+
7
+ - Added validation-only Gate intake for trusted Git refs already present in the broker repository.
8
+ `candidate authority setup` first records a versioned protected-target trust root at a fixed path
9
+ in Git's common directory; `candidate adopt --ref` then pins the exact commit, derives its
10
+ base-relative history and paths, loads committed policy from the registered base, and records a
11
+ standalone, schema-backed submission without manufacturing tasks, leases, receipts, or batches.
12
+ - Added `candidate list` and `candidate show`, plus recovery of interrupted `received` and
13
+ `validating` submissions.
14
+
15
+ ### Changed
16
+
17
+ - Validator environments now expose `MERGE_BROKER_SUBMISSION_ID` during trusted local-ref intake.
18
+ - Validators now receive an owner-readable UTF-8 JSON path list through
19
+ `MERGE_BROKER_FILES_FILE`, `MERGE_BROKER_FILES_FILE_FORMAT=json`, and shell-safe `{filesFile}`.
20
+ Inline input remains the compatibility default but fails closed when either legacy representation
21
+ exceeds 4 KiB; `filesInput: "json"` explicitly selects file-only transport for large path sets.
22
+ - Gate requires Git 2.46 or newer, binds protected-base refresh to the canonical fetch URL (separate
23
+ from any publication `pushurl`), rejects and scrubs Git repository/index/object/history and
24
+ configuration-injection or transport-command overrides, refuses configured URL/transport
25
+ rewrites, proxy/TLS/routing overrides, and exact-locator remote shorthand collisions, physically
26
+ binds local transport paths, rejects URL forms whose Git and web interpretations differ,
27
+ recursively inspects the owned object store, recomputes commit/tree/blob identities,
28
+ applies documented aggregate diff/tree/path ceilings, materializes raw filter-free blob bytes,
29
+ binds state/worktree/cache/hook directories to physical filesystem identities, journals retained-ref
30
+ establishment and later loss, bounds untracked-path diagnostics, and serializes authority
31
+ replacement against adoption and recovery.
32
+
33
+ ### Fixed
34
+
35
+ - Kept exact-target checks compatible with Git for Windows' standard unscoped Schannel TLS backend,
36
+ and made lock release retry transient Windows sharing violations without weakening nonce fencing.
37
+
38
+ ## 0.12.1 — 2026-09-04
39
+
40
+ ### Added
41
+
42
+ - Added a truthful product vision and capability-based roadmap that distinguish today's Coordinate
43
+ mode from planned external-candidate Gate and generalized Verify modes.
44
+
45
+ ### Changed
46
+
47
+ - Reframed the README, package metadata, and website around crash-recoverable exact-candidate
48
+ repository transactions while preserving the current package, CLI, and project identities.
49
+ - Expanded the architecture, protocol, security, compatibility, and operations documentation to
50
+ cover v0.12 locks, durable intents, reconciliation, topology proofs, adapter obligations, upgrade
51
+ boundaries, and actionable error recovery.
52
+
53
+ ### Fixed
54
+
55
+ - Aligned the published configuration schema with runtime support for declaring auto-merge while
56
+ publication remains disabled, while continuing to reject branch-mode and draft auto-merge.
57
+ - Made the documentation site redeploy for every canonical content source and replaced its
58
+ inaccurate source-declaration test count with the supported cross-platform CI matrix.
59
+ - Replaced a historical but copyable nonexistent `verify@v1` reference with an existing immutable
60
+ action tag.
61
+ - Made abandoned-integration cleanup replayable across another process stop, use the persisted
62
+ branch name and expected SHA, remove partial worktree directories, and preserve branches checked
63
+ out for operator inspection.
64
+ - Made JSON CLI usage errors follow the documented machine-readable error envelope and made
65
+ `serve --once --json` return exactly one summary document.
66
+ - Made human refresh output distinguish an already-current batch, terminal reconciliation, and a
67
+ pull request that a reviewer had already closed.
68
+
3
69
  ## 0.12.0 — 2026-09-04
4
70
 
5
71
  ### Added
@@ -28,7 +94,8 @@
28
94
  - Merge reconciliation proves the accepted fast-forward, squash, two-parent merge, or linear rebase
29
95
  topology before releasing dependent tasks.
30
96
  - Revocation, reviewer closure, force-push, reopened pull request, remote retargeting, and
31
- configuration-downgrade races now fail closed without leaving a possibly-live merge queue behind.
97
+ configuration-downgrade races now fail closed without leaving a possibly-live auto-merge request
98
+ behind.
32
99
 
33
100
  ### Fixed
34
101
 
@@ -332,7 +399,7 @@ not have to rebuild them.
332
399
  already contain. Verification policy is read from the configuration committed on the base branch,
333
400
  never from the change under review.
334
401
  - A composite GitHub Action at `verify/action.yml`, so requiring the gate is two lines:
335
- `uses: WeSpitfire/agent-merge-broker/verify@v1`.
402
+ `uses: WeSpitfire/agent-merge-broker/verify@v0.3.0`.
336
403
  - `merge-broker task submit --since-base` submits the linear commits made after the base the broker
337
404
  handed out. Commits whose change is already upstream are skipped by patch identity, so a rebased
338
405
  branch does not resubmit landed work.
package/README.md CHANGED
@@ -1,18 +1,61 @@
1
1
  # Agent Merge Broker
2
2
 
3
- **Four agents just finished at the same time. Who merges first?**
3
+ **Crash-recoverable repository transactions for code-producing agents and humans.**
4
4
 
5
- Agent Merge Broker answers that so your agents never have to. Workers commit their work and stop. The broker decides what can safely go together, cherry-picks it into a disposable worktree, runs your test suite against the combination, and lands one validated branch or pull request.
5
+ Many producers can create code. The repository still needs one contract for deciding what is safe to
6
+ validate, publish, and merge. Agent Merge Broker is a local-first transaction coordinator for that
7
+ boundary: participating workers submit receipts naming immutable commits, while Gate intake can
8
+ submit one retained trusted-local Git ref for validation without fabricated coordination history.
9
+ The complete Coordinate path derives one batch candidate and keeps
10
+ publication bound to the recorded Git and forge target.
6
11
 
7
- No agent pushes. No agent rebases. No agent quietly clobbers another agent's `package-lock.json`.
12
+ In Coordinate mode, exact-candidate approval ties evidence and authorization to the candidate SHA,
13
+ base SHA, and policy revision. Durable operation state lets the broker reconcile a crash or lost
14
+ forge response before it releases dependent work.
8
15
 
9
- ## The problem
16
+ It does not spawn agents, decide policy with AI, or replace CI, review, protected branches, or a
17
+ native forge queue. The forge remains the final branch authority.
10
18
 
11
- Put four coding agents on one repository and the bottleneck stops being code. It becomes Git.
19
+ ## What ships today
12
20
 
13
- Two agents edit the same file and find out at merge time. A third rebases onto a branch that moved twenty minutes ago. Everyone regenerates the lockfile. CI runs four times to test four things that were never once tested *together*. And the pull request that has been sitting there since lunch is now so far behind `main` that nothing can merge it at all.
21
+ ### Coordinate mode
14
22
 
15
- The work is parallel. Integration is not. Every worker doing its own integration turns a coordination problem into a coordination disaster.
23
+ The current workflow coordinates workers that participate through the broker's claim and receipt
24
+ protocol:
25
+
26
+ ```text
27
+ claim → lease → commit → nominate → batch → validate → publish → reconcile
28
+ ```
29
+
30
+ - Expiring, cross-worktree leases prevent predictable collisions before editing.
31
+ - Commit receipts separate implementation from integration authority.
32
+ - A deterministic conflict/dependency scheduler forms bounded batches.
33
+ - Every batch is tested through real cherry-picks in a disposable worktree.
34
+ - Focused checks run after each task; the complete gate runs either in the broker or as required CI.
35
+ - Successful work becomes one local branch, remote branch, or GitHub pull request.
36
+ - Optional exact-candidate policy separates nomination, verification, approval, and mechanical merge.
37
+ - Published branches can carry a signed provenance manifest for remote policy checks.
38
+ - Target fingerprints, durable intents, and forge observation make interrupted publication recoverable.
39
+ - Automatic completion waits until the accepted Git history proves that the batch merged.
40
+
41
+ ### Gate intake for trusted local refs
42
+
43
+ Version `0.13.0` adds a first Gate slice for a Git ref whose objects are already available in the
44
+ broker's local repository. An explicit `candidate authority setup` ceremony records the reviewed
45
+ protected-target locator outside candidate commits. `candidate adopt` then resolves and retains the
46
+ exact commit, independently resolves that registered base, loads committed policy from the base,
47
+ derives the raw commit chain and changed paths, and runs focused plus authoritative broker validators
48
+ over filter-free materialized bytes. The resulting `SubmissionRecord` is validation evidence only:
49
+ this slice does not create a task, lease, receipt, batch, approval candidate, provenance statement,
50
+ branch, pull request, or merge authority.
51
+
52
+ ### A concrete coordination problem
53
+
54
+ Four coding agents finish at once. Two touched the same file, a third started from a base that has
55
+ already moved, and each produced a lockfile. Testing four branches independently never proves that
56
+ their combined result works. Coordinate mode orders that work, rejects overlapping claims early,
57
+ validates compatible commits together, and retains one candidate without giving workers merge
58
+ authority.
16
59
 
17
60
  ## Try it in one minute
18
61
 
@@ -25,39 +68,61 @@ Two workers race on a throwaway repository, a third gets turned away for claimin
25
68
 
26
69
  It is also this project's acceptance test in CI — so if the demo ever stops telling the truth, the build goes red.
27
70
 
28
- ## How it works
29
-
30
- One integration authority; implementation stays distributed:
31
-
32
- - Expiring, cross-worktree leases prevent predictable collisions before editing.
33
- - Commit receipts separate implementation from integration authority.
34
- - A deterministic conflict/dependency scheduler forms bounded batches.
35
- - Every batch is tested through real cherry-picks in a disposable worktree.
36
- - Focused checks run after each task; the complete gate runs either in the broker or as required CI.
37
- - Successful work becomes one local branch, remote branch, or GitHub pull request.
38
- - Optional exact-candidate policy separates nomination, verification, approval, and mechanical merge.
39
- - Published branches can carry a committed provenance manifest for fast remote policy checks.
40
- - Tasks are dependency-complete only after their batch is actually merged.
41
- - An append-only audit stream records lifecycle decisions and validation results.
71
+ ## How Coordinate mode works
42
72
 
43
- It is deliberately **not** an agent framework and **not** a replacement for protected branches. Codex, Claude, Cursor, custom agents, CI jobs, and humans all speak the same small commit-receipt protocol, and your forge keeps the final say on what merges.
73
+ Implementation stays distributed while one broker owns ordering, batching, validation, publication,
74
+ and recovery. Codex, Claude, Cursor, custom agents, CI jobs, and humans can use the same small
75
+ commit-receipt protocol. An append-only audit stream records lifecycle decisions and validation
76
+ results, while the forge keeps the final say on what merges.
44
77
 
45
78
  ## Status
46
79
 
47
80
  `0.3.0` was the first public release: the local broker core, the GitHub CLI publishing adapter with auto-merge, and the remote provenance verifier.
48
81
 
49
- `0.12.0` is the current release. It makes pull-request auto-merge crash-recoverable and
50
- target-bound, adds unattended publication and stale-base recovery, and closes approval, refresh,
51
- revision, remote-retargeting, and reopened-pull-request races. It also retains the first-class
52
- Windows support, permission-separated MCP servers, diagnostics, and bootstrap detection added in
53
- `0.11.0`.
82
+ `0.13.0` is the current release. It adds validation-only Gate intake for trusted repository-local
83
+ Git refs, with an explicit protected-target authority, exact retained artifact identity,
84
+ filter-free validation, and crash-safe recovery. It builds on the `0.12.1` documentation and
85
+ machine-readable CLI consolidation around the `0.12.0` core. That core made
86
+ pull-request auto-merge crash-recoverable and target-bound, added unattended publication and
87
+ stale-base recovery, and closed approval, refresh, revision, remote-retargeting, and reopened-PR
88
+ races, while retaining the first-class Windows support, permission-separated MCP servers,
89
+ diagnostics, and bootstrap detection added in `0.11.0`.
90
+
91
+ The on-disk state, receipt, submission, candidate, and provenance formats are versioned, but
92
+ compatibility is not guaranteed until `1.0.0`. Expect format migrations before then.
93
+
94
+ ## Product direction
95
+
96
+ Coordinate mode remains the complete repository-transaction workflow in `0.13.0`. The release also
97
+ ships a deliberately narrower local-ref Gate validation intake; Gate merge authority and Verify mode
98
+ remain planned.
99
+
100
+ ### Gate mode — validation intake in 0.13.0
101
+
102
+ `merge-broker candidate adopt --ref <git-ref>` accepts a completed candidate from a producer that did
103
+ not use path leases while coding. Before adoption, an operator must run `candidate authority setup`
104
+ from a reviewed protected checkout. This first slice is trusted-source and validation-only. The ref
105
+ must already be available in the local repository, descend linearly from the registered base, and fit
106
+ both `scheduling.maxCommits` and Gate's 1,000-commit hard ceiling; the protected base must contain
107
+ matching committed broker policy with
108
+ `validation.authority: "broker"`. Approval, provenance, publication, merge reconciliation,
109
+ pull-request intake, bundles, and remote submission for these records are not implemented yet.
54
110
 
55
- The on-disk state, receipt, and provenance formats are versioned, but compatibility is not guaranteed until `1.0.0`. Expect format migrations before then.
111
+ ### Verify mode — planned
112
+
113
+ Verify mode will be a lightweight admission check for policy and attestations produced through a
114
+ wider set of workflows. Today's `verify-provenance` command is intentionally narrower: it verifies
115
+ provenance created by the current broker workflow, not arbitrary external candidates.
116
+
117
+ See [Vision](VISION.md) for the durable product boundary and
118
+ [Roadmap](ROADMAP.md) for the capability-based sequence. Planned work is labeled explicitly and
119
+ is not part of npm until a release says otherwise.
56
120
 
57
121
  ## Requirements
58
122
 
59
123
  - Node.js 20.12 or newer
60
124
  - Git 2.31 or newer with worktree support
125
+ - Git 2.46 or newer specifically for trusted local-ref Gate intake
61
126
  - GitHub CLI only when `publish.mode` is `pull-request`
62
127
 
63
128
  Windows, macOS, and Linux are supported and release-gating in CI. Windows validation defaults to
@@ -99,9 +164,10 @@ and owner-written `AGENTS.md` content. Use `--no-detect` or `--no-agent-contract
99
164
  installer or repository template owns those concerns itself.
100
165
 
101
166
  It also creates an Ed25519 provenance private key, mode `0600`, under Git's common runtime directory.
102
- Only its public key is written to the committed configuration. Runtime state, receipt records,
103
- manifests, keys, locks, and integration worktrees therefore stay outside commits while every linked
104
- worktree sees the same broker authority.
167
+ Only its public key is written to the committed configuration. Runtime state, receipt, batch, and
168
+ Gate submission records, keys, locks, and disposable worktrees therefore stay outside commits while
169
+ every linked worktree sees the same broker authority. When provenance is enabled, a separate signed
170
+ or unsigned provenance manifest is deliberately committed as a Coordinate-mode branch head.
105
171
 
106
172
  ## Quick start
107
173
 
@@ -116,9 +182,9 @@ git add .merge-broker AGENTS.md && git commit -m 'Configure authenticated merge
116
182
  merge-broker doctor
117
183
  ```
118
184
 
119
- `merge-broker status` now includes the safe next command for each active task and batch. For a bug
120
- report, `merge-broker doctor --support-bundle` emits diagnostics and recent audit events with paths,
121
- URLs, and secret-bearing fields redacted; review the JSON before sharing it.
185
+ `merge-broker status` includes the safe next command for each active task, batch, and retained Gate
186
+ submission. For a bug report, `merge-broker doctor --support-bundle` emits diagnostics and recent
187
+ audit events with paths, URLs, and secret-bearing fields redacted; review the JSON before sharing it.
122
188
 
123
189
  An orchestrator or worker claims a narrowly scoped task:
124
190
 
@@ -139,16 +205,17 @@ merge-broker task heartbeat CRM-142
139
205
  Pass `--token`, `--token-file`, or `MERGE_BROKER_TOKEN` when the worker runs somewhere else, or
140
206
  claim with `--no-store-token` to handle custody yourself.
141
207
 
142
- Before handing anything over, the worker can check its own work against the same validators
143
- integration will run:
208
+ Before handing anything over, the worker can run a local preflight using the same validator
209
+ definitions integration will use:
144
210
 
145
211
  ```bash
146
212
  merge-broker validate
147
213
  ```
148
214
 
149
- This is the answer integration would give, not an approximation of it, because it reads the same
150
- `validation` configuration. It includes uncommitted and untracked files, writes no state, needs no
151
- lease, and exits non-zero when a validator fails — so a worker script can gate on it.
215
+ This checks the caller's current working tree, including uncommitted and untracked files, writes no
216
+ state, needs no lease, and exits non-zero when a validator fails. It does not reproduce integration's
217
+ per-task focused sequencing or its unchanged-`HEAD` and clean-worktree postconditions, so the retained
218
+ integration transaction remains authoritative.
152
219
 
153
220
  The worker commits its change and nominates a candidate receipt. It does not merge or push:
154
221
 
@@ -179,7 +246,57 @@ merge-broker integrate --publish
179
246
  merge-broker batch sync <batch-id>
180
247
  ```
181
248
 
182
- `batch sync` checks the GitHub PR when available. For branch-only publication it fetches the configured base and verifies ancestry. `batch complete` exists as an explicit manual escape hatch for squash/rebase workflows that cannot be reconciled automatically.
249
+ `batch sync` checks the GitHub PR when available. For branch-only publication it fetches the batch's
250
+ fingerprint-bound recorded target and verifies exact-head ancestry. GitHub fast-forward, squash,
251
+ two-parent merge, and linear-rebase outcomes are reconciled automatically when their topology can be
252
+ proved. `batch complete` remains an explicit manual authority fallback for workflows that expose no
253
+ sufficient automatic proof.
254
+
255
+ ## Validate a trusted local Git candidate
256
+
257
+ When another trusted local workflow has already assembled a linear candidate, retain and validate
258
+ its exact commit without manufacturing Coordinate-mode history:
259
+
260
+ ```bash
261
+ merge-broker candidate authority setup
262
+ merge-broker candidate authority show
263
+ merge-broker candidate adopt --ref refs/heads/external-candidate
264
+ merge-broker candidate list
265
+ merge-broker candidate show <submission-id>
266
+ ```
267
+
268
+ Run setup from a reviewed protected checkout after committing `.merge-broker/config.json`. The
269
+ config-independent record binds the base locator, refresh behavior, state directory, and, when
270
+ available, the canonical fetch-URL fingerprint without storing the URL. A changed target requires
271
+ explicit `--replace`. There is intentionally no caller-supplied `--base` or path list. Adoption
272
+ rejects an empty, unrelated, merged-history, or over-limit candidate (the smaller of
273
+ `scheduling.maxCommits` and Gate's 1,000-commit ceiling) and currently requires
274
+ `validation.authority: "broker"`. It pins the resolved commit under
275
+ `refs/merge-broker/adopted/<submission-id>`, derives raw paths and history, materializes filter-free
276
+ blob bytes in a disposable worktree, recomputes retained commit/tree/blob IDs, and verifies the
277
+ retained identity after validation. It durably records successful ref establishment before any
278
+ validator and journals any later ref loss before create-only repair, so recovery cannot forget a
279
+ retention violation. If a
280
+ validator rejects the candidate and the final artifact identity remains provable, the durable record
281
+ and results are returned but the command exits nonzero. An irreproducible object identity or
282
+ wrong/symbolic retained ref stays `validating` for fail-closed recovery instead of producing an
283
+ unretained terminal claim.
284
+
285
+ When refresh is enabled and the configured ref denotes the base branch, setup requires a configured
286
+ fetch URL and will not fall back to a stale local ref. Set `integration.refreshBase` to false for an
287
+ intentionally offline/local Gate target.
288
+
289
+ Gate also rejects ambient or protected-validator Git repository/index/object/history and
290
+ configuration-injection or transport-command overrides, rejects configured URL/transport rewrites
291
+ and exact-locator remote shorthand collisions, recursively inspects the repository-owned object store, binds the
292
+ disposable worktree's Git administration identity, and bounds its untracked-path diagnostic. See
293
+ [Compatibility and current limits](docs/COMPATIBILITY.md) for the exact deny-list and ceilings.
294
+
295
+ This is not an integration shortcut. A `validated` submission is not approved, published,
296
+ provenanced, or authorized to merge, and cannot be passed to `batch publish`. Use Coordinate mode
297
+ for the current end-to-end merge workflow. If adoption is interrupted after its durable record is
298
+ written, `merge-broker recover` replays `received` or `validating` submissions from the retained
299
+ identity.
183
300
 
184
301
  ## See it work
185
302
 
@@ -234,7 +351,7 @@ installing dependencies:
234
351
  with:
235
352
  ref: ${{ github.event.pull_request.head.sha }}
236
353
  fetch-depth: 0
237
- - uses: WeSpitfire/agent-merge-broker/verify@v0.12.0
354
+ - uses: WeSpitfire/agent-merge-broker/verify@v0.13.0
238
355
  ```
239
356
 
240
357
  The check verifies the Ed25519 signature, branch and batch identity, real base history, one-file
@@ -300,11 +417,12 @@ to be current. Approval also rechecks the open PR head, target base, task state,
300
417
  and configured GitHub checks. Approval becomes merge-authorizing only after it is durable and the
301
418
  broker observes that exact PR still open; the final `gh pr merge` uses GitHub's head-SHA guard.
302
419
 
303
- Protect the target branch with either “require branches to be up to date before merging” or a merge
304
- queue, and restrict bypass permission. GitHub's merge API can guard the head SHA but cannot
305
- atomically guard a base SHA. The broker rechecks the base immediately before queueing and proves the
306
- merged Git history afterward, but branch protection prevents an out-of-band base update in that
307
- final remote interval.
420
+ Protect the target branch with “require branches to be up to date before merging” and restrict
421
+ bypass permission. GitHub's merge API can guard the head SHA but cannot atomically guard a base SHA.
422
+ The broker rechecks the base immediately before queueing and proves the merged Git history afterward,
423
+ while branch protection prevents an out-of-band base update in that final remote interval. Native
424
+ merge-queue and `merge_group` verification are planned; the current topology proof does not treat a
425
+ combined merge-group artifact as the authorized candidate.
308
426
 
309
427
  If verification finds a problem, keep the task and PR:
310
428
 
@@ -331,11 +449,13 @@ Two configuration combinations cannot work and are rejected at load time rather
331
449
 
332
450
  Auto-merge requires the setting to be enabled on the GitHub repository. Configurations written before this feature existed default to `autoMerge: false`, so upgrading never starts landing work on its own.
333
451
 
334
- The broker resolves and records the exact Git push URL locator and GitHub `HOST/OWNER/REPO` when it
335
- assembles a batch. Later changes to the named Git remote or to `gh repo set-default` cannot redirect
336
- publication. Standard GitHub and GitHub Enterprise remote URLs are derived automatically. If the
337
- Git remote is a local mirror or proxy, set `publish.repository` explicitly; otherwise pull-request
338
- mode fails closed rather than guessing a GitHub repository.
452
+ The broker records the selected Git remote and a SHA-256 fingerprint of its canonical push URL when
453
+ it assembles a publishable batch; the raw URL is not persisted because it may contain credentials.
454
+ Pull-request batches also record a host-qualified GitHub `HOST/OWNER/REPO`. Later changes to the
455
+ named remote or to `gh repo set-default` cannot redirect publication. Standard GitHub and GitHub
456
+ Enterprise remote URLs are derived automatically. If the Git remote is a local mirror or proxy, set
457
+ `publish.repository` explicitly; otherwise pull-request mode fails closed rather than guessing a
458
+ GitHub repository.
339
459
 
340
460
  Running `merge-broker serve --publish` reconciles checks, finishes interrupted publication or
341
461
  auto-merge hand-offs, re-cuts stale batches, and only then integrates the next batch. With exact
@@ -365,10 +485,12 @@ deliberately instead.
365
485
  `integrate --dry-run` is a rehearsal in both directions: it retains no branch when it succeeds, and
366
486
  returns every task to the queue when it fails, so verifying costs nothing.
367
487
 
368
- Only one batch is in flight at a time. A batch is cut from the base branch tip so it is born
369
- mergeable, and cutting a second while the first is still open makes that expire — whichever merges
370
- first leaves the other behind a base that requires branches to be up to date. `integrate` refuses
371
- with `BATCH_OUTSTANDING` and names the batch to land first; `--force` overrides it.
488
+ Only one batch is in flight at a time. In the default production shape—`baseRef` identifies the
489
+ remote target and `integration.refreshBase` is enabled—a batch is cut from the fetched base-branch
490
+ tip so it is born mergeable. A deliberately different `baseRef`, or disabling refresh, uses the
491
+ configured construction revision instead. Cutting a second batch while the first is still open can
492
+ leave either one stale, so `integrate` refuses with `BATCH_OUTSTANDING` and names the batch to land
493
+ first; `--force` overrides it.
372
494
 
373
495
  When a batch does end up behind — something landed on the base by another route, or `--force` was
374
496
  used — re-cut it:
@@ -377,9 +499,10 @@ used — re-cut it:
377
499
  merge-broker batch refresh <batch-id>
378
500
  ```
379
501
 
380
- That closes the superseded pull request, returns the tasks to the queue without spending their retry
381
- budget, and integrates them again from the current tip, re-validating against the base that is
382
- actually being merged into. A batch already cut from the current tip is left alone.
502
+ For PR publication, that closes the superseded pull request; branch-only publication has no PR to
503
+ close. It returns the tasks to the queue without spending their retry budget and integrates them
504
+ again from the current recorded target tip, re-validating against the base that is actually being
505
+ merged into. A batch already cut from that tip is left alone.
383
506
 
384
507
  Publication is safe to retry. The pull request is recorded before auto-merge is attempted, and a
385
508
  durable intent is recorded before the remote queue is changed. A forge that fails halfway therefore
@@ -390,12 +513,13 @@ create anything new.
390
513
 
391
514
  A process that dies mid-integration can leave both a lock and durable `running` state. A holder on
392
515
  this machine is reclaimed automatically once its process is proven gone. A holder on another machine
393
- cannot be probed and is never stolen merely because it is old; after confirming that process is
394
- gone, inspect or release it explicitly with `unlock batch:<batch-id> --force` (or `state` /
395
- `integration`). Once the integration lock is safely acquired, `serve` and `integrate` automatically
396
- mark abandoned work failed, clean its broker-owned worktree and branch, and return its tasks to
397
- `submitted` without spending their attempt budget. `merge-broker recover` performs that
398
- reconciliation explicitly.
516
+ cannot be probed and is never stolen merely because it is old. Inspect the locks with `doctor`; for
517
+ an abandoned `running` integration, confirm the old authority is gone and release
518
+ `unlock integration --force` (and `state` or `gate-authority` only if `doctor` shows it held). Dynamic
519
+ `batch:<batch-id>` locks apply to interrupted operations after integration. Once the integration lock
520
+ is safely acquired, `serve` and `integrate` automatically mark abandoned work failed, clean its
521
+ broker-owned worktree and branch, and return its tasks to `submitted` without spending their attempt
522
+ budget. `merge-broker recover` performs that reconciliation explicitly.
399
523
 
400
524
  Candidate revisions also carry a durable intent before the broker moves their branch. If a process
401
525
  stops after the branch update but before state finalization, `recover` compares the real PR/local
@@ -497,22 +621,32 @@ while broker credentials stay out of repository-defined commands.
497
621
  Validators receive these environment variables:
498
622
 
499
623
  - `MERGE_BROKER_TASK_ID`
500
- - `MERGE_BROKER_FILES`, newline-separated
624
+ - `MERGE_BROKER_FILES_FILE`, the path to an owner-readable UTF-8 JSON array of validator-relative paths
625
+ - `MERGE_BROKER_FILES_FILE_FORMAT=json`
626
+ - `MERGE_BROKER_FILES`, the newline-separated form for the default `filesInput: "inline"`; empty in JSON mode
501
627
  - `MERGE_BROKER_BASE_SHA`
502
628
  - `MERGE_BROKER_HEAD_SHA`
503
629
  - `MERGE_BROKER_BATCH_ID`
630
+ - `MERGE_BROKER_SUBMISSION_ID`, nonempty only for trusted local-ref adoption
504
631
  - `MERGE_BROKER_CACHE_DIR`, an isolated cache shared by validators in one integration transaction
505
632
 
506
- Commands may also use the shell-safe placeholders `{taskId}`, `{files}`, and
507
- `{validatorCacheDir}` (a stable validator-specific directory inside the transaction cache). `workingDirectory` can
508
- place a validator in a repository-relative package directory; file placeholders and environment
509
- paths are then relative to that directory. Validator output is captured with a fixed memory bound
510
- and retained in state with that cap. A timeout terminates the validator process tree.
511
-
512
- `merge-broker validate` runs these same broker-side validators against a working tree, so a worker
513
- can get the local integration answer before submitting rather than a weaker approximation of it. It reports
514
- `MERGE_BROKER_BATCH_ID=local`, which a validator can branch on if it needs to behave differently
515
- outside a batch.
633
+ Commands may also use the shell-safe placeholders `{taskId}`, `{filesFile}`, `{files}`, and
634
+ `{validatorCacheDir}` (a stable validator-specific directory inside the transaction cache).
635
+ `{filesFile}` expands to `MERGE_BROKER_FILES_FILE`. Validators default to `filesInput: "inline"`,
636
+ which supplies both the shell-quoted `{files}` arguments and newline `MERGE_BROKER_FILES` only when
637
+ both representations fit within 4 KiB. If either is larger, validation fails closed with
638
+ `VALIDATION_FAILED` before the validator starts, even when its command does not contain `{files}`.
639
+ For potentially large path sets, set `filesInput: "json"` and parse the UTF-8 JSON array through
640
+ `{filesFile}` or `MERGE_BROKER_FILES_FILE`; JSON mode leaves `MERGE_BROKER_FILES` empty and rejects a
641
+ command that still contains `{files}`.
642
+ `workingDirectory` can place a validator in a repository-relative package directory; paths in every
643
+ file-list form are then relative to that directory. Validator output is captured with a fixed memory
644
+ bound and retained in state with that cap. A timeout terminates the validator process tree.
645
+
646
+ `merge-broker validate` is a preflight that runs the same broker-side validator definitions against
647
+ the caller's working tree. It does not reproduce per-task focused sequencing or integration's
648
+ post-validator candidate-preservation checks. It reports `MERGE_BROKER_BATCH_ID=local`, which a
649
+ validator can branch on if it needs to behave differently outside a batch.
516
650
 
517
651
  A validator may set `"executionArchitecture": "native"` to run under the hardware architecture on
518
652
  macOS when Node itself is translated by Rosetta. Detected SwiftPM validators use this mode and put
@@ -520,7 +654,8 @@ their scratch build under `{validatorCacheDir}`, preventing Intel and Apple Sili
520
654
  from contaminating each other without rebuilding between the focused and authoritative stages of
521
655
  the same integration transaction.
522
656
 
523
- The JSON schemas in [`schemas/`](schemas/) can be used by editors, adapters, and independent receipt producers.
657
+ The JSON schemas in [`schemas/`](schemas/) cover configuration, task receipts, exact approval
658
+ candidates, batch provenance, and Gate authority/submission records.
524
659
 
525
660
  ### One authoritative CI pass
526
661
 
@@ -564,6 +699,11 @@ merge-broker install-hooks [--force] [--uninstall] [--print]
564
699
  merge-broker install-service [--uninstall] [--interval <seconds>] [--no-eager]
565
700
  merge-broker verify-provenance --branch <ref> --head <sha> --base <sha>
566
701
  merge-broker validate [--task <id>] [--scope focused|authoritative|all] [--base <ref>] [--cwd <path>]
702
+ merge-broker candidate authority setup [--replace]
703
+ merge-broker candidate authority show
704
+ merge-broker candidate list
705
+ merge-broker candidate adopt --ref <revision>
706
+ merge-broker candidate show <submission-id>
567
707
  merge-broker task register|claim|extend|heartbeat|candidate|submit|reopen|revise|retry|release|cancel|abandon|show
568
708
  merge-broker status
569
709
  merge-broker plan
@@ -573,7 +713,7 @@ merge-broker audit
573
713
  merge-broker metrics
574
714
  merge-broker events
575
715
  merge-broker prune [--older-than <days>] [--dry-run]
576
- merge-broker unlock [state|integration|batch:<batch-id>] [--force]
716
+ merge-broker unlock [state|integration|gate-authority|batch:<batch-id>] [--force]
577
717
  merge-broker recover
578
718
  merge-broker serve [--publish] [--eager] [--log-file <path>]
579
719
  merge-broker-mcp -C <directory> [--profile worker|operator]
@@ -600,6 +740,8 @@ resolve conflicts automatically. The complete supported/unsupported boundary is
600
740
 
601
741
  ## Documentation
602
742
 
743
+ - [`VISION.md`](VISION.md) — durable product boundary and design principles
744
+ - [`ROADMAP.md`](ROADMAP.md) — current, next, and later capability horizons
603
745
  - [`docs/GETTING_STARTED.md`](docs/GETTING_STARTED.md) — installation and production rollout
604
746
  - [`docs/COMPATIBILITY.md`](docs/COMPATIBILITY.md) — platform matrix, Windows notes, and current limits
605
747
  - [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) — invariants, state model, scheduling, and transactions