agent-merge-broker 0.10.0 → 0.12.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 (80) hide show
  1. package/CHANGELOG.md +455 -0
  2. package/CODE_OF_CONDUCT.md +28 -0
  3. package/CONTRIBUTING.md +36 -0
  4. package/README.md +102 -42
  5. package/SUPPORT.md +25 -0
  6. package/dist/bootstrap.d.ts.map +1 -1
  7. package/dist/bootstrap.js +128 -33
  8. package/dist/bootstrap.js.map +1 -1
  9. package/dist/broker.d.ts +35 -0
  10. package/dist/broker.d.ts.map +1 -1
  11. package/dist/broker.js +1269 -90
  12. package/dist/broker.js.map +1 -1
  13. package/dist/cli.js +136 -18
  14. package/dist/cli.js.map +1 -1
  15. package/dist/config.d.ts.map +1 -1
  16. package/dist/config.js +27 -2
  17. package/dist/config.js.map +1 -1
  18. package/dist/git.d.ts +23 -1
  19. package/dist/git.d.ts.map +1 -1
  20. package/dist/git.js +171 -7
  21. package/dist/git.js.map +1 -1
  22. package/dist/hooks.d.ts.map +1 -1
  23. package/dist/hooks.js +28 -12
  24. package/dist/hooks.js.map +1 -1
  25. package/dist/index.d.ts +5 -2
  26. package/dist/index.d.ts.map +1 -1
  27. package/dist/index.js +4 -1
  28. package/dist/index.js.map +1 -1
  29. package/dist/mcp-cli.d.ts +3 -0
  30. package/dist/mcp-cli.d.ts.map +1 -0
  31. package/dist/mcp-cli.js +21 -0
  32. package/dist/mcp-cli.js.map +1 -0
  33. package/dist/mcp.d.ts +13 -0
  34. package/dist/mcp.d.ts.map +1 -0
  35. package/dist/mcp.js +373 -0
  36. package/dist/mcp.js.map +1 -0
  37. package/dist/process.d.ts +1 -1
  38. package/dist/process.d.ts.map +1 -1
  39. package/dist/process.js +21 -11
  40. package/dist/process.js.map +1 -1
  41. package/dist/publisher.d.ts +9 -6
  42. package/dist/publisher.d.ts.map +1 -1
  43. package/dist/publisher.js +95 -20
  44. package/dist/publisher.js.map +1 -1
  45. package/dist/serve-log.d.ts +18 -0
  46. package/dist/serve-log.d.ts.map +1 -1
  47. package/dist/serve-log.js +16 -1
  48. package/dist/serve-log.js.map +1 -1
  49. package/dist/service.d.ts +8 -3
  50. package/dist/service.d.ts.map +1 -1
  51. package/dist/service.js +138 -7
  52. package/dist/service.js.map +1 -1
  53. package/dist/status.d.ts +4 -0
  54. package/dist/status.d.ts.map +1 -0
  55. package/dist/status.js +81 -0
  56. package/dist/status.js.map +1 -0
  57. package/dist/store.d.ts +34 -3
  58. package/dist/store.d.ts.map +1 -1
  59. package/dist/store.js +213 -42
  60. package/dist/store.js.map +1 -1
  61. package/dist/support.d.ts +32 -0
  62. package/dist/support.d.ts.map +1 -0
  63. package/dist/support.js +44 -0
  64. package/dist/support.js.map +1 -0
  65. package/dist/types.d.ts +39 -1
  66. package/dist/types.d.ts.map +1 -1
  67. package/dist/validation.d.ts.map +1 -1
  68. package/dist/validation.js +18 -6
  69. package/dist/validation.js.map +1 -1
  70. package/docs/ARCHITECTURE.md +6 -2
  71. package/docs/COMPATIBILITY.md +139 -0
  72. package/docs/GETTING_STARTED.md +72 -9
  73. package/docs/PROTOCOL.md +6 -0
  74. package/docs/RELEASING.md +1 -1
  75. package/docs/SECURITY.md +33 -6
  76. package/examples/two-agents/README.md +4 -1
  77. package/examples/two-agents/run.mjs +146 -0
  78. package/package.json +11 -4
  79. package/schemas/candidate.schema.json +4 -1
  80. package/schemas/config.schema.json +16 -1
package/CHANGELOG.md ADDED
@@ -0,0 +1,455 @@
1
+ # Changelog
2
+
3
+ ## 0.12.0 — 2026-09-04
4
+
5
+ ### Added
6
+
7
+ - Durable journals for publication, auto-merge enablement and revocation, candidate revision, and
8
+ stale-base refresh operations, allowing unattended service restarts to finish interrupted work.
9
+ - Per-batch operation serialization, recoverable lock ownership, and an operator-visible recovery
10
+ path for abandoned dynamic batch locks.
11
+ - Durable Git remote fingerprints and host-qualified forge selectors so publication remains bound
12
+ to the repository and target selected when a batch was assembled.
13
+
14
+ ### Changed
15
+
16
+ - `serve --publish` now reconciles and safely retries prepared batches, partial publication,
17
+ auto-merge hand-offs, policy changes, and stale bases before integrating more work.
18
+ - The exported `ForgePublisher` contract now requires exact pull-request identity and explicit
19
+ observed auto-merge state, including an `undefined` result when the forge cannot prove it.
20
+ - Broker-generated Git commits use a stable broker identity with signing and ambient repository
21
+ hooks disabled, making integration behavior consistent across clean Windows, macOS, and Linux
22
+ hosts.
23
+
24
+ ### Security
25
+
26
+ - Auto-merge authorization remains bound to the exact candidate SHA, base SHA, policy revision,
27
+ required evidence, authorized actor, pull-request target, and durably recorded forge repository.
28
+ - Merge reconciliation proves the accepted fast-forward, squash, two-parent merge, or linear rebase
29
+ topology before releasing dependent tasks.
30
+ - 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.
32
+
33
+ ### Fixed
34
+
35
+ - Publication and refresh failures no longer strand the queue or create duplicate pull requests.
36
+ - Validators can no longer validate bytes different from the retained candidate through worktree
37
+ mutation or ambient Git hooks.
38
+ - Stale bases, policy drift, interrupted refreshes, and approval retries now converge to an
39
+ auditable terminal or retryable state after a process restart.
40
+
41
+ ## 0.11.0 — 2026-09-03
42
+
43
+ ### Added
44
+
45
+ - First-class Windows support: non-profile PowerShell validation, process-tree timeout cleanup,
46
+ per-user Task Scheduler services, a cross-platform Node acceptance demo, and release-gating CI.
47
+ - A stdio MCP adapter with separate worker and operator tool profiles. Worker calls use locally held
48
+ lease tokens without returning them to the model, and merge-authorizing tools exist only in the
49
+ operator profile.
50
+ - Actionable human status, sanitized `doctor --support-bundle` output, and archive-aware audit and
51
+ metrics reads.
52
+ - Conservative Go, Rust, and Python bootstrap detection plus repository-relative validator working
53
+ directories for nested packages.
54
+
55
+ ### Changed
56
+
57
+ - Hook installation composes with repository-local hook directories and preserves unrelated default
58
+ hooks. `install-hooks --print` supports explicit composition when another tool owns `pre-push`.
59
+ - Background-service installation fails early when publication is disabled.
60
+ - Documentation now publishes a platform matrix, Windows operating notes, MCP capability guidance,
61
+ safe support-bundle workflow, release-availability notice, and an explicit list of functionality
62
+ that is not included today.
63
+
64
+ ## 0.10.0 — 2026-09-02
65
+
66
+ ### Added
67
+
68
+ - `init` now detects declared JavaScript and SwiftPM validation entry points, installs a managed
69
+ root `AGENTS.md` contract, reports unresolved project-specific configuration, and returns an
70
+ explicit operational-readiness result.
71
+ - Validators can request native hardware execution on translated macOS processes and receive an
72
+ isolated `MERGE_BROKER_CACHE_DIR` shared across one integration transaction.
73
+
74
+ ### Changed
75
+
76
+ - Initialization is idempotent for existing repositories: it preserves configured validation and
77
+ owner instructions while repairing missing managed files and legacy unsigned provenance.
78
+ - `doctor` distinguishes component health from operational readiness and reports the process and
79
+ native host architectures, validation readiness, and whether the root agent contract is installed
80
+ and committed.
81
+
82
+ ## 0.9.0 — 2026-08-31
83
+
84
+ ### Added
85
+
86
+ - Candidate revision intents make branch publication recoverable across an interrupted state
87
+ finalization, and integration now rejects a task receipt replaced after planning.
88
+ - `ForgePublisher` is an injectable Node API boundary; the GitHub CLI publisher remains built in.
89
+ - `doctor` reports toolchain, remote/base, forge authentication, committed policy, hooks, service,
90
+ locks, provenance, and unfinished transaction readiness.
91
+ - A full getting-started guide, community support/conduct files, and structured issue templates.
92
+
93
+ ### Security
94
+
95
+ - Validator output is memory-bounded while commands run, and timeouts terminate the POSIX process
96
+ group. Runtime directories/files now receive explicit 0700/0600 modes without changing a
97
+ caller-owned custom token directory.
98
+ - Auto-merge defaults off, every auto-merge call carries an exact head SHA, and service installers
99
+ refuse to overwrite or remove unowned supervisor files.
100
+
101
+ ### Fixed
102
+
103
+ - systemd user services now write stdout and stderr to the log path reported by the CLI.
104
+ - The generated config is validated against the published JSON Schema during tests, packaged demos
105
+ are included in npm tarballs, numeric CLI options fail closed, and documentation edit links point
106
+ at their real source files.
107
+
108
+ ## 0.8.1 — 2026-08-30
109
+
110
+ ### Fixed
111
+
112
+ - SHA-bound approval now works with GitHub CLI versions that do not expose `baseRefOid` through
113
+ `gh pr view --json`. The broker detects that specific capability gap, retrieves the exact head
114
+ and base refs through `gh api`, and fails closed if the pull request head changes between the two
115
+ snapshots.
116
+
117
+ ## 0.8.0 — 2026-08-28
118
+
119
+ ### Added
120
+
121
+ - **Exact candidate approval.** Optional approval policy binds required GitHub checks, named manual
122
+ evidence, and explicit authorization to the integrated candidate SHA, base SHA, and policy
123
+ revision. Publishing no longer enables auto-merge before that gate when the policy is required.
124
+ - `batch verify`, `batch approve`, and `batch request-changes` expose verification and authorization
125
+ as separate, auditable capabilities. Approvers can be restricted by configured actor identity.
126
+ - `task candidate` replaces ambiguous completion language while `task submit` remains a compatible
127
+ alias. `task abandon` is the explicit cancellation alias.
128
+ - `task reopen` and `task revise` keep corrective work on the same integration branch and pull
129
+ request. The guarded force update archives the former candidate as `superseded` and starts the new
130
+ revision with no inherited evidence or approval.
131
+ - Candidate state and evidence have a published JSON schema, and human/JSON status surfaces show
132
+ verification progress, exact bindings, approval, and blocking reasons.
133
+
134
+ ### Security
135
+
136
+ - Approval re-reads the live pull request, requires an exact head/base binding, rejects conflicts or
137
+ requested changes, verifies every task remains outside an editing lease, and passes the candidate
138
+ SHA to GitHub's merge head guard. External PR-head mutations block the candidate; an out-of-band
139
+ merge without matching approval is recorded as an invariant violation.
140
+ - Base or candidate changes invalidate all prior verification and approval. Editing leases remain
141
+ enforceable during revision without being kept artificially alive through long CI and review.
142
+
143
+ ### Compatibility
144
+
145
+ - Existing version-one configurations receive `approval.required: false` defaults and retain the
146
+ pre-0.8 publication behavior until they opt into the gate.
147
+
148
+ ## 0.7.1 — 2026-08-28
149
+
150
+ ### Fixed
151
+
152
+ - Closing a pull request without merging now pauses every affected task as `failed` instead of
153
+ automatically re-queueing its unchanged receipt. This prevents eager services from repeatedly
154
+ publishing rejected work; corrected commits can be reclaimed and submitted normally, while
155
+ `task retry` remains the explicit escape hatch for a deliberate unchanged-receipt retry.
156
+
157
+ ## 0.7.0 — 2026-08-28
158
+
159
+ ### Added
160
+
161
+ - **Explicit validation authority.** Repositories can select `validation.authority: required-ci` to
162
+ publish an immutable signed pull-request batch after changed-scope preflight, leaving the complete
163
+ suite to protected required CI checks instead of running it serially twice. The mode fails closed
164
+ unless publication uses pull requests, signed provenance is required, and the local authoritative
165
+ list is empty. Existing configurations default to `broker` and keep their current behavior.
166
+
167
+ ## 0.6.0 — 2026-08-25
168
+
169
+ ### Added
170
+
171
+ - **Authenticated provenance.** New repositories receive an Ed25519 signing identity during `init`.
172
+ The public key is committed as protected-base policy; the mode-0600 private key stays under Git's
173
+ common runtime directory. Remote verification rejects forged, unsigned, or tampered manifests
174
+ when signature policy is required. Existing repositories can migrate with `merge-broker
175
+ provenance setup-signing`, and supervised hosts may supply the key through a file or environment
176
+ secret that validators never inherit.
177
+ - **Abandoned integration recovery.** `serve` and `integrate` now recover a durable `running` batch
178
+ left by a killed process after safely acquiring the integration lock. Its tasks return to
179
+ `submitted` without spending their attempt budget, and broker-owned worktree and branch artifacts
180
+ are cleaned. `merge-broker recover` exposes the same operation explicitly, while `doctor` reports
181
+ incomplete transaction state and missing signing credentials.
182
+ - `merge-broker install-service` runs the integration loop as a per-user background service — a
183
+ launchd agent on macOS, a systemd user unit on Linux. `serve` already did the work, but only
184
+ while somebody kept a terminal open, so a submitted task could sit in `submitted` for as long as
185
+ nobody happened to look. An agent cannot tell that state apart from having its work rejected, and
186
+ the repository this was written against had a verified batch waiting with nothing driving it. The
187
+ service is scoped per repository, because two checkouts of one project sharing a label would
188
+ leave one of them silently unserved. It is a user service on both platforms: a system daemon
189
+ would need root and would publish as a user who holds neither the SSH key nor the forge
190
+ credentials. On macOS the agent carries an explicit `PATH` — a launchd job inherits almost none,
191
+ and without it the loop starts, cannot see `git`, and does nothing, which looks exactly like
192
+ having nothing to do.
193
+ - `serve` now reports what it is doing. It previously wrote only on a merge, a closure, an error, or
194
+ a *completed* integration — so a batch spending minutes in validators produced an empty log, and a
195
+ healthy busy service could not be told apart from a dead one. That was survivable while the loop
196
+ lived in a terminal and fatal once `install-service` moved it into the background, where the log
197
+ file is the only window on it. It now announces startup and its settings, announces a batch
198
+ *before* the work rather than after, reports idleness on a slower clock than the poll so a quiet
199
+ loop still proves it is alive without writing thousands of lines a day, and says it is stopping
200
+ instead of vanishing. Failures and batches returned to the queue go to stderr, progress to stdout,
201
+ and `--json` emits one object per line. `--once` keeps its original single-result output.
202
+
203
+ ### Security
204
+
205
+ - **Post-assembly merge commits are rejected.** The former update-branch allowance compared changed
206
+ paths, which could not detect malicious conflict resolution inside a path the base also changed.
207
+ The provenance commit must now remain the branch head. A stale batch is closed, re-cut from the
208
+ current base, revalidated, and re-signed with `batch refresh`.
209
+ - Remote provenance claims now distinguish cryptographically authenticated manifests from legacy
210
+ structural-only verification. Authenticated enforcement requires a protected-base public key and
211
+ private-key custody outside untrusted worker environments.
212
+
213
+ ### Fixed
214
+
215
+ - The documented composite action now uses the real exact `v0.6.0` release tag, and the action runs
216
+ the matching package version instead of silently defaulting to `0.3.0`.
217
+ - Architecture and protocol documentation now describe the local token vault and signing-key
218
+ custody accurately.
219
+ - Service logs resolve through Git's common directory, so `install-service` works from linked
220
+ worktrees where `.git` is a file rather than a directory.
221
+ - `batch refresh` now refuses to requeue or create a replacement when the superseded pull request
222
+ could not be closed. The previous best-effort close could leave two remotely mergeable copies of
223
+ the same tasks after a forge failure.
224
+ - Runtime dependencies now honor the documented Node 20 minimum instead of installing a Commander
225
+ release whose engine declaration requires Node 22.
226
+
227
+ ## 0.5.0 — 2026-08-17
228
+
229
+ Surviving a bad afternoon at the forge. A GitHub outage interrupted a publication midway, and the
230
+ broker turned a transient 503 into a batch that could not be landed at all.
231
+
232
+ ### Added
233
+
234
+ - `merge-broker batch refresh <id>` re-cuts a batch the base branch moved past, so it can merge
235
+ again. Previously there was no way back: the operator closed the pull request by hand, reconciled
236
+ state by hand, and integrated again. It re-cuts the same tasks from the current tip and
237
+ re-validates them, which is the point — a stale batch was only ever checked against a base nobody
238
+ merges into any more. Re-cutting rather than merging the base into the branch keeps every batch an
239
+ immutable artifact whose manifest describes exactly the base it was assembled on. The superseded
240
+ pull request is closed first, so nobody can still merge the batch being replaced. Attempts are not
241
+ incremented: nothing about the work failed, the world moved, and charging it against
242
+ `maxAttempts` would eventually retire a task for being unlucky about merge order. A batch that is
243
+ already current is a no-op.
244
+
245
+ ### Fixed
246
+
247
+ - **Publication records the pull request before attempting auto-merge.** It used to create the pull
248
+ request and enable auto-merge as one step, so a failure at the second threw away the first: the
249
+ batch stayed `prepared` while its pull request existed on the forge. `batch sync` only reconciles
250
+ `published` batches, so the one command built to notice the merge could not see it. Auto-merge is
251
+ now its own step, and failing it leaves a published batch carrying `publishWarning` — something
252
+ that needs a hand, not a publication that did not happen.
253
+ - **Publication is idempotent.** It looks for the branch's open pull request before opening one, so
254
+ retrying after a partial failure finishes the job instead of opening a duplicate. A lookup that
255
+ *fails* is not treated as "there is none" — publication stops with `PULL_REQUEST_LOOKUP_FAILED`,
256
+ because the response to none is to create one, and that is how retrying during an outage produces
257
+ duplicates. `batch publish` accepts an already-`published` batch so it can be used to retry.
258
+ - **One batch in flight at a time.** `integrate` cut a new batch whenever tasks were queued, even
259
+ with an earlier batch still open. A batch is cut from the base tip so it is born mergeable;
260
+ cutting another while the first is unmerged makes that expire, and whichever merges first strands
261
+ the other behind a base that requires branches to be up to date. Integration now refuses with
262
+ `BATCH_OUTSTANDING` and names the batch to land first. `--force` overrides, and `--dry-run` is
263
+ unaffected — a rehearsal retains nothing, so it can strand nothing.
264
+
265
+ ## 0.4.1 — 2026-08-17
266
+
267
+ Toolchain maintenance. No behaviour changes.
268
+
269
+ ### Fixed
270
+
271
+ - Named the node types explicitly in `tsconfig.json`. TypeScript 7 stopped inferring ambient node
272
+ types from `NodeNext` module resolution alone, so every `node:` import failed to resolve and the
273
+ compiler read the specifiers as bare names. The build would have broken on the compiler upgrade
274
+ whether or not the dependency bump arrived with it.
275
+
276
+ ### Changed
277
+
278
+ - Moved to TypeScript 7.0.2 and `@types/node` 26, the current stable line.
279
+ - Updated `commander` to 15. This is the one runtime dependency, so consumers resolving it
280
+ transitively will see the major change.
281
+
282
+ ## 0.4.0 — 2026-08-15
283
+
284
+ Recovery. Everything here came out of one repository's week of fighting the lifecycle rather than the
285
+ merge: the broker was strict in places where strictness protected nothing, and the way out of an
286
+ ordinary mistake was to rebuild the task.
287
+
288
+ ### Added
289
+
290
+ - `merge-broker validate` runs the configured validators against a working tree, before anything is
291
+ submitted. Integration was previously the only thing that knew what "ready" meant, so adopters
292
+ wrote a cheaper approximation for workers to run first — and an approximation is exactly the thing
293
+ that passes locally and fails at integration. This runs the same validators from the same
294
+ configuration, covers uncommitted and untracked files, writes no state, requires no lease, and
295
+ exits non-zero on failure so a worker script can gate on it. Validators see
296
+ `MERGE_BROKER_BATCH_ID=local`.
297
+
298
+ ### Fixed
299
+
300
+ - `integrate --dry-run` no longer marks tasks `failed` when validation fails. A rehearsal consumed
301
+ the queue: the next integrate found nothing to do and reported `EMPTY_BATCH`, with no indication
302
+ that the dry run had emptied it. The success path already restored `submitted` for this reason;
303
+ the failure path did not.
304
+ - A task may be submitted again while `submitted`, replacing its receipt, until its batch is
305
+ assembled. Nothing downstream has read it yet, so the refusal protected only the worker's own
306
+ earlier list of commits — while making "I need one more commit" unrecoverable, since the sole
307
+ remaining lever was `cancel`, which is final and ends the lease.
308
+ - `task extend` accepts a `failed` task, as `task claim` already did. Fixing what validation caught
309
+ routinely means touching a file the original scope did not cover, and refusing to widen scope at
310
+ exactly that moment left rebuilding the task as the only way forward.
311
+ - Lifecycle refusals name the command that moves the task instead of only reporting its status. The
312
+ state machine is invisible from outside, so `cannot be submitted while batched` was a riddle.
313
+ Submission checks status before the lease for the same reason: batching ends the lease, so the
314
+ honest answer was "its batch is assembled", not "you hold no lease".
315
+
316
+ ## 0.3.0 — 2026-08-15
317
+
318
+ First public release. The versions below are development history and were never published to npm.
319
+
320
+
321
+ The adoption layer. Everything here already existed as bespoke glue around the broker in the
322
+ repository that pilots it; this release moves the generic parts into the tool so a new adopter does
323
+ not have to rebuild them.
324
+
325
+ ### Added
326
+
327
+ - `merge-broker verify-provenance --branch <ref> --head <sha> --base <sha>` proves that a pull
328
+ request head is an unaltered broker batch: assembled on real base history, changing exactly the
329
+ paths its receipts account for, carrying every submitted commit, and validated. It reads only Git,
330
+ so it runs on any forge and before any dependency is installed. It accepts the "update branch"
331
+ merges a protected base produces, and rejects a merge that brings in anything the base does not
332
+ already contain. Verification policy is read from the configuration committed on the base branch,
333
+ never from the change under review.
334
+ - A composite GitHub Action at `verify/action.yml`, so requiring the gate is two lines:
335
+ `uses: WeSpitfire/agent-merge-broker/verify@v1`.
336
+ - `merge-broker task submit --since-base` submits the linear commits made after the base the broker
337
+ handed out. Commits whose change is already upstream are skipped by patch identity, so a rebased
338
+ branch does not resubmit landed work.
339
+ - The broker now holds the lease token for the worker, mode 0600, beside the state it authorizes.
340
+ Lease-aware commands find it automatically; `--token`, `--token-file`, and `MERGE_BROKER_TOKEN`
341
+ still work, and `task claim --no-store-token` opts out. Previously the token was shown once and
342
+ every adopter had to build a credential store, with the obvious implementation putting a live
343
+ token in the working tree where `git add` and validator commands can reach it.
344
+ - `merge-broker install-hooks` installs a pre-push guard that refuses direct pushes of
345
+ implementation branches, with `MERGE_BROKER_ALLOW_DIRECT_PUSH=1` as the deliberate bypass. It
346
+ refuses to run when the repository already has hooks that moving `core.hooksPath` would silently
347
+ disable, and `--uninstall` reverses it.
348
+ - `examples/two-agents` is a runnable demonstration: two workers in parallel worktrees, one refused
349
+ overlapping claim, four commits, one validated branch. It runs in CI as an acceptance test.
350
+ - Batch provenance manifests record the `history` mode used to assemble them, so a verifier knows
351
+ whether submitted commits are traceable in the integrated history. Manifests written before this
352
+ field are treated as `preserve`, which is what they were.
353
+
354
+ ## 0.2.0 — Unreleased
355
+
356
+ Correctness pass ahead of the first public release. Everything below was found by reviewing the
357
+ package as an outside adopter would receive it, rather than as it is used in its home repository.
358
+
359
+ ### Changed
360
+
361
+ - **Validators no longer run under the operator's login shell.** They previously ran under
362
+ `$SHELL -lc`, which made every integration decision depend on whose machine assembled the batch:
363
+ a non-POSIX `$SHELL` such as fish or nushell broke validation outright, and personal login
364
+ profiles could silently reshape the result. Validators now run under `/bin/sh -c`
365
+ (`%ComSpec% /d /s /c` on Windows), configurable with `validation.shell`. The environment still
366
+ comes from the calling process, so PATH and toolchain managers keep working; a validator that
367
+ needs more should set its own `env`.
368
+ - Auto-merge no longer decides by pattern-matching the GitHub CLI's prose. It queries
369
+ `mergeStateStatus` and merges directly only when GitHub reports `CLEAN`. The previous English
370
+ regular expression turned a clean pull request into a hard failure under a different `gh` version
371
+ or locale.
372
+
373
+ ### Added
374
+
375
+ - `merge-broker prune [--older-than <days>] [--dry-run]` retires completed tasks and batches into
376
+ `<state>/archive/`. `state.json` is rewritten in full on every transaction, including heartbeats,
377
+ so an unbounded history made routine operations progressively slower. A completed task that a
378
+ retained task still depends on is never pruned: the scheduler cannot tell a pruned dependency from
379
+ one that has never merged, and the dependent would wait forever.
380
+ - `merge-broker unlock [state|integration] [--force]` releases a lock left by a crashed process.
381
+ A holder on another machine cannot be probed, so integration could previously stall for the full
382
+ 24-hour stale window with no recourse. Without `--force` the lock is released only when its owner
383
+ is provably gone.
384
+ - `doctor` now reports lock state and warns when no validators are configured, which otherwise
385
+ assembles batches without checking anything and says nothing about it.
386
+ - `validation.shell` configuration field and JSON-schema entry.
387
+
388
+ ### Fixed
389
+
390
+ - One truncated line no longer makes the entire audit trail unreadable. `events` skips malformed
391
+ records and reads a bounded tail instead of loading the whole file, and the active audit file is
392
+ rotated into `<state>/archive/` once it grows large. Rotated segments are never deleted.
393
+ - The lease token is no longer passed to validator commands. Repository configuration is trusted to
394
+ run commands, but no validator needs a worker credential that can submit or cancel on its behalf.
395
+ - A task with more commits than `scheduling.maxCommits` now reports that it can never be scheduled
396
+ instead of repeating the same transient-looking deferral on every planning pass.
397
+
398
+ ### Platform support
399
+
400
+ - CI now covers Ubuntu and macOS on Node 20 and 22. Windows runs as an informational job:
401
+ the shell selection and command quoting differ there and are not yet a supported platform.
402
+
403
+ ## 0.1.6 — Unreleased
404
+
405
+ - Added `--force` to `task cancel` and `task release`, so an integration owner can reclaim a lease
406
+ whose one-time token was lost with its worker. Previously such a scope stayed locked until its TTL
407
+ expired. Forced revocation is recorded in the audit stream with the holder it was taken from.
408
+
409
+ - Merged a published pull request directly when GitHub refuses to queue auto-merge because the pull
410
+ request is already mergeable. A "clean" status means the required checks have passed, so the batch
411
+ no longer stalls when checks finish before publication returns.
412
+ - Fixed cross-machine lock recovery. Liveness was probed with a process ID, but the state directory
413
+ is shared across machines while process IDs are not, so one machine could reclaim a lock that
414
+ another machine was actively holding. Owner records now carry a hostname: a crashed holder on this
415
+ machine is reclaimed after a short grace period, and a holder elsewhere waits out the full stale
416
+ timeout. Records written without a hostname keep the previous behaviour.
417
+
418
+ ## 0.1.5 — Unreleased
419
+
420
+ - Added `publish.autoMerge` and `publish.mergeMethod`. The broker now asks GitHub to merge a
421
+ published batch once required checks pass, so integration completes without a human step.
422
+ - Rejected the `publish.autoMerge` + `publish.draft` combination during configuration validation.
423
+ GitHub can never merge a draft pull request, so the previous default silently stalled every batch.
424
+ - Changed the generated default to `publish.draft: false` with `publish.autoMerge: true`.
425
+ Configurations written before this release keep auto-merge off until they opt in.
426
+ - Added `integration.refreshBase`, which fetches the remote base branch before a batch is cut.
427
+ Batches were previously born behind the base branch and became unmergeable under
428
+ "require branches to be up to date" protection.
429
+ - Reconciled pull requests that are closed without merging. The batch becomes `closed` and its tasks
430
+ return to the queue instead of remaining `published` forever, which silently discarded the work.
431
+ - Limited failure blast radius: a cherry-pick or focused-validation failure now fails only the task
432
+ responsible and returns its batch-mates to the queue. Authoritative failures still fail the batch.
433
+ - Added `integration.maxAttempts` to bound automatic re-queueing.
434
+ - Added committed batch-provenance manifests that bind a published integration
435
+ branch to its base SHA, integrated parent, task receipts, and broker validators.
436
+ - Made provenance opt-in compatible for existing version-one configurations and
437
+ enabled it by default for new installations.
438
+ - Added token-authenticated active-lease scope extension for coordinator adapters.
439
+
440
+ ## 0.1.1 — Unreleased
441
+
442
+ - Separated the integration `baseRef` from the forge target `baseBranch` so passive local main branches cannot produce stale batches.
443
+
444
+ ## 0.1.0 — Unreleased
445
+
446
+ - Added versioned repository configuration and generated agent instructions.
447
+ - Added atomic cross-worktree state, expiring leases, heartbeats, and audit events.
448
+ - Added immutable commit receipts with expected/actual path enforcement.
449
+ - Added dependency-aware, conflict-aware bounded batch scheduling.
450
+ - Added transactional Git worktree integration with cherry-pick provenance.
451
+ - Added focused and authoritative repository-defined validation.
452
+ - Added local branch, remote branch, and GitHub pull-request publication.
453
+ - Added explicit merge reconciliation and a polling broker service.
454
+ - Added local throughput, batch, and validation metrics.
455
+ - Added JSON CLI and exported Node API for adapters.
@@ -0,0 +1,28 @@
1
+ # Code of conduct
2
+
3
+ Agent Merge Broker is committed to a respectful, useful, and harassment-free project community.
4
+ Participation includes issues, pull requests, reviews, discussions, release work, and other spaces
5
+ the maintainers represent as part of this project.
6
+
7
+ ## Expected behavior
8
+
9
+ - Be considerate, specific, and constructive.
10
+ - Critique ideas and code without attacking people.
11
+ - Respect differing experience levels, identities, backgrounds, and communication styles.
12
+ - Assume good intent while remaining accountable for impact.
13
+ - Keep private information, credentials, and vulnerability details out of public reports.
14
+ - Accept a maintainer's request to pause, refocus, or leave a discussion.
15
+
16
+ Harassment, discrimination, threats, sexualized attention, deliberate intimidation, repeated
17
+ personal attacks, and publishing another person's private information are not acceptable.
18
+
19
+ ## Enforcement
20
+
21
+ Maintainers may edit or remove contributions, limit participation, or ban a participant when needed
22
+ to protect the community. Enforcement decisions should consider context, severity, repetition, and
23
+ the safety of people affected.
24
+
25
+ Report conduct concerns privately to the repository owner or maintainers. Include links and enough
26
+ context to investigate; do not start a public thread about the people involved. Maintainers will
27
+ limit disclosure to the people needed to respond and will avoid conflicts of interest where
28
+ practical.
@@ -0,0 +1,36 @@
1
+ # Contributing
2
+
3
+ Contributions are welcome. Small bug fixes, recovery fixtures, documentation improvements, and
4
+ adapter work are all useful.
5
+
6
+ Before starting a large protocol or persisted-state change, open a feature request so compatibility
7
+ and migration expectations can be agreed before implementation. Use a security advisory rather
8
+ than a public issue for exploitable findings.
9
+
10
+ ## Development
11
+
12
+ ```bash
13
+ npm install
14
+ npm run verify
15
+ node dist/cli.js --help
16
+ npm run example
17
+ ```
18
+
19
+ Tests use temporary real Git repositories rather than mocks for transaction behavior. Add a regression fixture for changes to leases, receipts, cherry-picking, validation, batching, or lifecycle transitions.
20
+
21
+ ## Pull requests
22
+
23
+ - Keep changes focused and explain any state or protocol compatibility impact.
24
+ - Update JSON schemas and documentation with persisted-format changes.
25
+ - Avoid agent-specific behavior in the core; expose it through an adapter boundary.
26
+ - Preserve the invariant that no branch is retained after failed validation.
27
+ - Include tests for both the successful transaction and its recovery path.
28
+
29
+ Run `npm run verify` before submitting. CI also runs `npm pack --dry-run` to verify the distributable package.
30
+
31
+ See [SUPPORT.md](SUPPORT.md) for usage questions and [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md) for the
32
+ project's participation expectations.
33
+
34
+ ## Compatibility
35
+
36
+ Until version 1.0, breaking changes are allowed but must increment the relevant on-disk `version` field and include a migration or a clear reset procedure. Never silently reinterpret existing state.