mergetrain 0.1.0__tar.gz

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 (68) hide show
  1. mergetrain-0.1.0/.gitignore +34 -0
  2. mergetrain-0.1.0/AGENTS.md +32 -0
  3. mergetrain-0.1.0/CHANGELOG.md +27 -0
  4. mergetrain-0.1.0/LICENSE +21 -0
  5. mergetrain-0.1.0/PKG-INFO +207 -0
  6. mergetrain-0.1.0/README.md +172 -0
  7. mergetrain-0.1.0/dashboard/AGENTS.md +15 -0
  8. mergetrain-0.1.0/dashboard/index.html +15 -0
  9. mergetrain-0.1.0/dashboard/package-lock.json +1740 -0
  10. mergetrain-0.1.0/dashboard/package.json +20 -0
  11. mergetrain-0.1.0/dashboard/public/favicon.svg +1 -0
  12. mergetrain-0.1.0/dashboard/scripts/generate-favicon.mjs +15 -0
  13. mergetrain-0.1.0/dashboard/src/App.jsx +486 -0
  14. mergetrain-0.1.0/dashboard/src/main.jsx +12 -0
  15. mergetrain-0.1.0/dashboard/src/styles.css +408 -0
  16. mergetrain-0.1.0/dashboard/vite.config.mjs +22 -0
  17. mergetrain-0.1.0/docs/adapter-pattern.md +20 -0
  18. mergetrain-0.1.0/docs/agent-contract.md +43 -0
  19. mergetrain-0.1.0/docs/cli.md +218 -0
  20. mergetrain-0.1.0/docs/config.md +143 -0
  21. mergetrain-0.1.0/docs/daemon.md +39 -0
  22. mergetrain-0.1.0/docs/design.md +259 -0
  23. mergetrain-0.1.0/docs/development.md +93 -0
  24. mergetrain-0.1.0/docs/failure-modes.md +103 -0
  25. mergetrain-0.1.0/docs/install.md +39 -0
  26. mergetrain-0.1.0/docs/mobile.md +74 -0
  27. mergetrain-0.1.0/docs/quickstart.md +65 -0
  28. mergetrain-0.1.0/docs/release.md +121 -0
  29. mergetrain-0.1.0/docs/security.md +40 -0
  30. mergetrain-0.1.0/examples/example.mergetrain.yaml +31 -0
  31. mergetrain-0.1.0/examples/mergetrain.agent.yaml +14 -0
  32. mergetrain-0.1.0/llms-full.txt +54 -0
  33. mergetrain-0.1.0/llms.txt +21 -0
  34. mergetrain-0.1.0/pyproject.toml +62 -0
  35. mergetrain-0.1.0/src/mergetrain/__init__.py +5 -0
  36. mergetrain-0.1.0/src/mergetrain/__main__.py +4 -0
  37. mergetrain-0.1.0/src/mergetrain/cli.py +628 -0
  38. mergetrain-0.1.0/src/mergetrain/config.py +438 -0
  39. mergetrain-0.1.0/src/mergetrain/daemon.py +80 -0
  40. mergetrain-0.1.0/src/mergetrain/dashboard.py +188 -0
  41. mergetrain-0.1.0/src/mergetrain/dashboard_dist/assets/index-BKsW0WDL.js +49 -0
  42. mergetrain-0.1.0/src/mergetrain/dashboard_dist/assets/index-dvMrfMz1.css +1 -0
  43. mergetrain-0.1.0/src/mergetrain/dashboard_dist/assets/inter-cyrillic-ext-wght-normal-BOeWTOD4.woff2 +0 -0
  44. mergetrain-0.1.0/src/mergetrain/dashboard_dist/assets/inter-cyrillic-wght-normal-DqGufNeO.woff2 +0 -0
  45. mergetrain-0.1.0/src/mergetrain/dashboard_dist/assets/inter-greek-ext-wght-normal-DlzME5K_.woff2 +0 -0
  46. mergetrain-0.1.0/src/mergetrain/dashboard_dist/assets/inter-greek-wght-normal-CkhJZR-_.woff2 +0 -0
  47. mergetrain-0.1.0/src/mergetrain/dashboard_dist/assets/inter-latin-ext-wght-normal-DO1Apj_S.woff2 +0 -0
  48. mergetrain-0.1.0/src/mergetrain/dashboard_dist/assets/inter-latin-wght-normal-Dx4kXJAl.woff2 +0 -0
  49. mergetrain-0.1.0/src/mergetrain/dashboard_dist/assets/inter-vietnamese-wght-normal-CBcvBZtf.woff2 +0 -0
  50. mergetrain-0.1.0/src/mergetrain/dashboard_dist/assets/jetbrains-mono-cyrillic-ext-wght-normal-EocZY2iu.woff2 +0 -0
  51. mergetrain-0.1.0/src/mergetrain/dashboard_dist/assets/jetbrains-mono-cyrillic-wght-normal-D73BlboJ.woff2 +0 -0
  52. mergetrain-0.1.0/src/mergetrain/dashboard_dist/assets/jetbrains-mono-greek-wght-normal-Bw9x6K1M.woff2 +0 -0
  53. mergetrain-0.1.0/src/mergetrain/dashboard_dist/assets/jetbrains-mono-latin-ext-wght-normal-DBQx-q_a.woff2 +0 -0
  54. mergetrain-0.1.0/src/mergetrain/dashboard_dist/assets/jetbrains-mono-latin-wght-normal-B9CIFXIH.woff2 +0 -0
  55. mergetrain-0.1.0/src/mergetrain/dashboard_dist/assets/jetbrains-mono-vietnamese-wght-normal-Bt-aOZkq.woff2 +0 -0
  56. mergetrain-0.1.0/src/mergetrain/dashboard_dist/favicon.svg +1 -0
  57. mergetrain-0.1.0/src/mergetrain/dashboard_dist/index.html +16 -0
  58. mergetrain-0.1.0/src/mergetrain/errors.py +56 -0
  59. mergetrain-0.1.0/src/mergetrain/git_runner.py +1183 -0
  60. mergetrain-0.1.0/src/mergetrain/models.py +133 -0
  61. mergetrain-0.1.0/src/mergetrain/snapshot.py +241 -0
  62. mergetrain-0.1.0/src/mergetrain/store.py +893 -0
  63. mergetrain-0.1.0/tests/test_cli.py +100 -0
  64. mergetrain-0.1.0/tests/test_config.py +75 -0
  65. mergetrain-0.1.0/tests/test_daemon.py +43 -0
  66. mergetrain-0.1.0/tests/test_dashboard.py +148 -0
  67. mergetrain-0.1.0/tests/test_git_runner.py +273 -0
  68. mergetrain-0.1.0/tests/test_store.py +294 -0
@@ -0,0 +1,34 @@
1
+ # mergetrain runtime state (queue DB, logs, temporary worktrees)
2
+ .mergetrain/
3
+
4
+ # Python
5
+ __pycache__/
6
+ *.py[cod]
7
+ *.egg
8
+ *.egg-info/
9
+ .eggs/
10
+ build/
11
+ dist/
12
+
13
+ # Virtual environments
14
+ .venv/
15
+ venv/
16
+ env/
17
+
18
+ # Test / type / lint caches
19
+ .pytest_cache/
20
+ .mypy_cache/
21
+ .ruff_cache/
22
+ .coverage
23
+ htmlcov/
24
+
25
+ # Dashboard authoring dependencies and cache
26
+ dashboard/node_modules/
27
+ dashboard/.npm-cache/
28
+
29
+ # IDE / editor
30
+ .idea/
31
+ .vscode/
32
+
33
+ # OS
34
+ .DS_Store
@@ -0,0 +1,32 @@
1
+ # AGENTS.md
2
+
3
+ This repository contains `mergetrain`, a local deploy train for coding-agent
4
+ worktrees.
5
+
6
+ ## Agent operating rules
7
+
8
+ 1. Work on a task-specific branch and worktree.
9
+ 2. Commit all changes before enqueueing.
10
+ 3. Do not push deploy refs directly.
11
+ 4. Read `mergetrain doctor --json` or `mergetrain status --json` before deciding
12
+ the next action.
13
+ 5. Use `--auto` only after explicit unattended-deploy approval.
14
+ 6. Let one runner or daemon own merge, test, push, and verify.
15
+ 7. Fix blocked or failed work in the owning branch, commit a clean result, then
16
+ enqueue a new job.
17
+
18
+ ## Useful commands
19
+
20
+ ```sh
21
+ PYTHONPATH=src python -m unittest discover -s tests
22
+ PYTHONPATH=src python -m mergetrain agent-contract --json
23
+ PYTHONPATH=src python -m mergetrain init --project demo
24
+ ```
25
+
26
+ ## Boundaries
27
+
28
+ - Never add provider-specific credentials to examples or tests.
29
+ - Keep core provider-neutral; adapters belong under `integrations/` or in a
30
+ separate service repository.
31
+ - Gate and verify commands run through `/bin/sh`; document new shell execution
32
+ behavior clearly.
@@ -0,0 +1,27 @@
1
+ # Changelog
2
+
3
+ ## Unreleased
4
+
5
+ ## 0.1.0 - 2026-07-17
6
+
7
+ First public alpha release.
8
+
9
+ - Preserve exact validated train identity for a later approval-gated deploy.
10
+ - Rebuild validated trains on the current integration ref and reject changed task HEADs.
11
+ - Exclude validated-but-not-deployed branches from destructive GC.
12
+ - Fence batch claims and state transitions with unique lease tokens.
13
+ - Heartbeat, cancel, and time out long-running Git and shell subprocesses.
14
+ - Reject explicitly empty deploy refs and invalid queue timing at config load.
15
+ - Return truthful JSON outcomes and non-zero exit codes for blocked/failed jobs.
16
+ - Version SQLite migrations with `PRAGMA user_version`.
17
+ - Add a loopback-first, read-only live dashboard with SSE and polling fallback.
18
+ - Distinguish browser connectivity from runner activity and explain the current gate, command, scope, and Activity milestones.
19
+ - Record structured runner phases and explicit lock heartbeat timestamps.
20
+ - Redact lease tokens and local filesystem paths from dashboard payloads.
21
+ - SQLite-backed local deploy queue.
22
+ - Runner lock with PID liveness checks.
23
+ - Git worktree merge train execution.
24
+ - Configurable pre-push gates and post-push verify hooks.
25
+ - Atomic push refs.
26
+ - Auto-only daemon boundary.
27
+ - JSON-first agent contract, status, doctor, and GC output.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 mergetrain contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,207 @@
1
+ Metadata-Version: 2.4
2
+ Name: mergetrain
3
+ Version: 0.1.0
4
+ Summary: A local-first merge-and-deploy queue for coding-agent worktrees
5
+ Project-URL: Homepage, https://github.com/yongjip/mergetrain
6
+ Project-URL: Documentation, https://github.com/yongjip/mergetrain/tree/main/docs
7
+ Project-URL: Issues, https://github.com/yongjip/mergetrain/issues
8
+ Project-URL: Changelog, https://github.com/yongjip/mergetrain/blob/main/CHANGELOG.md
9
+ Author: mergetrain contributors
10
+ License: MIT
11
+ License-File: LICENSE
12
+ Keywords: ai-agent,deploy,git,llm,merge-train,sqlite,worktree
13
+ Classifier: Development Status :: 3 - Alpha
14
+ Classifier: Environment :: Console
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: License :: OSI Approved :: MIT License
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3 :: Only
19
+ Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Programming Language :: Python :: 3.13
23
+ Classifier: Programming Language :: Python :: 3.14
24
+ Classifier: Topic :: Software Development :: Build Tools
25
+ Classifier: Topic :: Software Development :: Version Control :: Git
26
+ Requires-Python: >=3.10
27
+ Provides-Extra: dev
28
+ Requires-Dist: build>=1.0; extra == 'dev'
29
+ Requires-Dist: hatchling>=1.21; extra == 'dev'
30
+ Requires-Dist: pytest>=7; extra == 'dev'
31
+ Requires-Dist: pyyaml>=6.0; extra == 'dev'
32
+ Provides-Extra: yaml
33
+ Requires-Dist: pyyaml>=6.0; extra == 'yaml'
34
+ Description-Content-Type: text/markdown
35
+
36
+ # mergetrain
37
+
38
+ **A local-first merge-and-deploy queue for coding-agent worktrees.**
39
+
40
+ mergetrain keeps its queue, coordination, merge assembly, and gate execution on
41
+ your machine. Coding agents commit in separate worktrees; one local runner
42
+ serializes their branches, validates the exact train, and pushes only after
43
+ explicit approval. No hosted merge-queue service or CI provider is required.
44
+
45
+ > **Local-first, not local-only.** Queue state, locking, train assembly, and
46
+ > gates stay local. Configured Git remotes and post-deploy verification may
47
+ > still use external services.
48
+
49
+ > Status: alpha (`v0.1.0`). The core is implemented and tested; interfaces may still change. Built to scratch my own itch first — published in case it scratches yours too.
50
+
51
+ ---
52
+
53
+ ## The problem
54
+
55
+ When several Codex/Claude/LLM sessions work on the same repo at the same time, each in its own worktree and branch, a few things break down:
56
+
57
+ - It's unclear what order branches should land on the deploy branch.
58
+ - If an agent runs `git push` itself, sessions overwrite each other or ship unverified combinations.
59
+ - Each branch passes its own tests, but the *merge of several branches in sequence* can still be broken.
60
+ - Conflicts, stale locks, duplicate enqueues, and "is the daemon allowed to deploy this?" all become judgment calls — and you do not want an LLM guessing at those.
61
+
62
+ Hosted merge queues (GitHub Merge Queue, GitLab Merge Trains, Mergify, Aviator, bors) solve a related problem, but they are PR-first, remote-CI-first, and platform-first. mergetrain is for the other workflow: **local-agent, worktree-first, deploy-branch-first.**
63
+
64
+ ## How it works
65
+
66
+ ```
67
+ agent A ─┐
68
+ agent B ─┼─▶ mergetrain queue (SQLite) ─▶ one runner (lock)
69
+ agent C ─┘ │
70
+
71
+ fresh integration worktree @ origin/main
72
+ merge A → B → C (the train)
73
+
74
+ gates (diff-check, tests, scans…)
75
+
76
+ git push --atomic → deploy refs
77
+
78
+ post-push verify hooks
79
+ ```
80
+
81
+ Agents commit their work and **enqueue** a branch. They never push deploy refs themselves. A single **runner** (or unattended **daemon**) claims the queue, builds a throwaway integration worktree on top of your integration branch, merges the queued branches in FIFO order, runs your gates once over the whole train, and only then pushes — atomically — to your deploy refs. Every important state is readable as JSON so an agent can follow the result instead of inferring it.
82
+
83
+ ## Quickstart
84
+
85
+ ```bash
86
+ # Install the public alpha
87
+ python -m pip install mergetrain
88
+
89
+ # 1. Scaffold config + agent docs in your repo
90
+ mergetrain init --project my-app --write
91
+
92
+ # 2. An agent finishes work, commits, and enqueues its branch
93
+ mergetrain enqueue --task "add health check" --branch agent/health --capture-sha
94
+
95
+ # 3. See the queue and lock state (machine-readable)
96
+ mergetrain status --json
97
+
98
+ # 4. Watch the queue and runner locally (read-only)
99
+ mergetrain dashboard
100
+
101
+ # 5. Validate the whole train without shipping
102
+ mergetrain run-batch --validate-only
103
+
104
+ # 6. Ship — explicit, never implicit
105
+ mergetrain run-batch --deploy
106
+ ```
107
+
108
+ For an unreleased source checkout, use `python -m pip install -e .` instead.
109
+
110
+ The dashboard is served at `http://127.0.0.1:8765/`. It streams structured
111
+ runner phases, heartbeat freshness, job order, blocked reasons, recent activity,
112
+ the exact current gate and command template, and the next safe action. `CONNECTED`
113
+ describes the browser's data stream; `RUNNER ACTIVE` separately describes the
114
+ process that owns the train. It has no mutation endpoints or deploy controls.
115
+
116
+ Validation records an exact train identity, including every task HEAD and the
117
+ integration base used for the check. The later deploy reassembles that same
118
+ train on the current integration ref, reruns all gates, and refuses changed
119
+ task branches. Newly queued work is not silently added to the approved train.
120
+
121
+ Every agent-facing command is non-interactive and requires explicit intent: `--validate-only` or `--deploy`, never a bare `run-batch`.
122
+
123
+ ## Core concepts
124
+
125
+ - **Job** — one task branch waiting in the queue, with the SHAs captured at enqueue time.
126
+ - **Validated train** — an exact, deployable group of jobs that passed gates together and is waiting for explicit deploy approval.
127
+ - **Runner lock** — gives every claim a unique lease token, heartbeats through long-running commands, and prevents a stale runner from overwriting a newer owner.
128
+ - **Integration worktree** — a disposable, detached Git worktree built on your integration ref. The runner merges here, so agents never checkout or push the deploy branch.
129
+ - **Gate** — a verification command (diff-check, tests, secret-scan…) run once over the assembled train *before* push. A gate failure means nothing ships.
130
+ - **Verify hook** — a command run *after* push to confirm the deploy is live.
131
+ - **Auto job** — a job enqueued with `--auto`, the only kind the unattended daemon will touch. Manual jobs are left for a human-initiated runner.
132
+
133
+ Full reference in [docs/design.md](./docs/design.md) and the [CLI reference](./docs/cli.md).
134
+
135
+ ## When to use mergetrain
136
+
137
+ | Your workflow is… | Use |
138
+ |---|---|
139
+ | PR-first, remote-CI-first, hosted platform | GitHub / GitLab merge queue, Mergify, Aviator |
140
+ | Local agents in worktrees shipping to a deploy branch | **mergetrain** |
141
+
142
+ mergetrain is **not** a general-purpose job queue (it won't replace Celery/RQ/Sidekiq), a CI provider, or a deploy provider. The core is provider-neutral: your push targets, test commands, and deploy checks live in config, not in mergetrain.
143
+
144
+ ## Configuration
145
+
146
+ A single `.mergetrain.yaml` at your repo root holds all policy. The core stays neutral; you bring the commands.
147
+
148
+ ```yaml
149
+ project:
150
+ name: my-app
151
+
152
+ git:
153
+ remote: origin
154
+ integration_branch: main
155
+ push_refs: [main] # atomic push targets on deploy
156
+
157
+ queue:
158
+ lock_ttl_minutes: 30
159
+ heartbeat_interval_seconds: 10
160
+ command_timeout_seconds: 3600
161
+
162
+ gates:
163
+ - name: diff-check
164
+ run: git diff --check ${integration_ref}..HEAD
165
+ - name: tests
166
+ run: python -m pytest
167
+
168
+ deploy:
169
+ verify:
170
+ - name: live-health
171
+ run: curl -fsS https://example.invalid/health
172
+ ```
173
+
174
+ See the [config reference](./docs/config.md) for the full schema, placeholders, and environment variables.
175
+
176
+ ## For AI agents
177
+
178
+ mergetrain is designed so an agent can operate it from a short contract and JSON output, without guessing:
179
+
180
+ 1. Work on a task-specific branch in its own worktree.
181
+ 2. Commit before enqueuing.
182
+ 3. Never push deploy refs directly.
183
+ 4. Read `mergetrain doctor --json` / `status --json` before acting.
184
+ 5. Use `--auto` only after explicit human approval for unattended deploys.
185
+ 6. Let one runner or daemon own merge → test → push → verify.
186
+ 7. Fix `blocked`/`failed` work on the owning branch and enqueue a fresh clean job.
187
+
188
+ `mergetrain init` writes `AGENTS.mergetrain.md` / `CLAUDE.mergetrain.md` so your agents pick this up automatically.
189
+
190
+ ## Documentation
191
+
192
+ - [Quickstart](./docs/quickstart.md) · [Install](./docs/install.md)
193
+ - [CLI reference](./docs/cli.md) — every command and flag
194
+ - [Config reference](./docs/config.md) — `.mergetrain.yaml` schema, placeholders, env vars
195
+ - [Design & architecture](./docs/design.md) — the model, data model, and safety guarantees
196
+ - [Daemon](./docs/daemon.md) · [Failure modes](./docs/failure-modes.md) — operating it day to day
197
+ - [Manage from your phone](./docs/mobile.md) — drive mergetrain via Cowork Dispatch
198
+ - [Agent contract](./docs/agent-contract.md) — the rules agents follow
199
+ - [Security](./docs/security.md) · [Adapter pattern](./docs/adapter-pattern.md) · [Development](./docs/development.md) · [Release](./docs/release.md)
200
+
201
+ ## Status
202
+
203
+ `v0.1.0`, alpha. The core — queue, runner lock, merge train, gates, atomic push, auto-only daemon, JSON `doctor`/`status`, and the local read-only dashboard — is implemented with a passing test suite. Built for my own multi-agent workflow first; issues and ideas welcome. Review your config trust boundary, gate commands, and secret handling before enabling unattended deploys — see [security](./docs/security.md).
204
+
205
+ ## License
206
+
207
+ Released under the [MIT License](./LICENSE).
@@ -0,0 +1,172 @@
1
+ # mergetrain
2
+
3
+ **A local-first merge-and-deploy queue for coding-agent worktrees.**
4
+
5
+ mergetrain keeps its queue, coordination, merge assembly, and gate execution on
6
+ your machine. Coding agents commit in separate worktrees; one local runner
7
+ serializes their branches, validates the exact train, and pushes only after
8
+ explicit approval. No hosted merge-queue service or CI provider is required.
9
+
10
+ > **Local-first, not local-only.** Queue state, locking, train assembly, and
11
+ > gates stay local. Configured Git remotes and post-deploy verification may
12
+ > still use external services.
13
+
14
+ > Status: alpha (`v0.1.0`). The core is implemented and tested; interfaces may still change. Built to scratch my own itch first — published in case it scratches yours too.
15
+
16
+ ---
17
+
18
+ ## The problem
19
+
20
+ When several Codex/Claude/LLM sessions work on the same repo at the same time, each in its own worktree and branch, a few things break down:
21
+
22
+ - It's unclear what order branches should land on the deploy branch.
23
+ - If an agent runs `git push` itself, sessions overwrite each other or ship unverified combinations.
24
+ - Each branch passes its own tests, but the *merge of several branches in sequence* can still be broken.
25
+ - Conflicts, stale locks, duplicate enqueues, and "is the daemon allowed to deploy this?" all become judgment calls — and you do not want an LLM guessing at those.
26
+
27
+ Hosted merge queues (GitHub Merge Queue, GitLab Merge Trains, Mergify, Aviator, bors) solve a related problem, but they are PR-first, remote-CI-first, and platform-first. mergetrain is for the other workflow: **local-agent, worktree-first, deploy-branch-first.**
28
+
29
+ ## How it works
30
+
31
+ ```
32
+ agent A ─┐
33
+ agent B ─┼─▶ mergetrain queue (SQLite) ─▶ one runner (lock)
34
+ agent C ─┘ │
35
+
36
+ fresh integration worktree @ origin/main
37
+ merge A → B → C (the train)
38
+
39
+ gates (diff-check, tests, scans…)
40
+
41
+ git push --atomic → deploy refs
42
+
43
+ post-push verify hooks
44
+ ```
45
+
46
+ Agents commit their work and **enqueue** a branch. They never push deploy refs themselves. A single **runner** (or unattended **daemon**) claims the queue, builds a throwaway integration worktree on top of your integration branch, merges the queued branches in FIFO order, runs your gates once over the whole train, and only then pushes — atomically — to your deploy refs. Every important state is readable as JSON so an agent can follow the result instead of inferring it.
47
+
48
+ ## Quickstart
49
+
50
+ ```bash
51
+ # Install the public alpha
52
+ python -m pip install mergetrain
53
+
54
+ # 1. Scaffold config + agent docs in your repo
55
+ mergetrain init --project my-app --write
56
+
57
+ # 2. An agent finishes work, commits, and enqueues its branch
58
+ mergetrain enqueue --task "add health check" --branch agent/health --capture-sha
59
+
60
+ # 3. See the queue and lock state (machine-readable)
61
+ mergetrain status --json
62
+
63
+ # 4. Watch the queue and runner locally (read-only)
64
+ mergetrain dashboard
65
+
66
+ # 5. Validate the whole train without shipping
67
+ mergetrain run-batch --validate-only
68
+
69
+ # 6. Ship — explicit, never implicit
70
+ mergetrain run-batch --deploy
71
+ ```
72
+
73
+ For an unreleased source checkout, use `python -m pip install -e .` instead.
74
+
75
+ The dashboard is served at `http://127.0.0.1:8765/`. It streams structured
76
+ runner phases, heartbeat freshness, job order, blocked reasons, recent activity,
77
+ the exact current gate and command template, and the next safe action. `CONNECTED`
78
+ describes the browser's data stream; `RUNNER ACTIVE` separately describes the
79
+ process that owns the train. It has no mutation endpoints or deploy controls.
80
+
81
+ Validation records an exact train identity, including every task HEAD and the
82
+ integration base used for the check. The later deploy reassembles that same
83
+ train on the current integration ref, reruns all gates, and refuses changed
84
+ task branches. Newly queued work is not silently added to the approved train.
85
+
86
+ Every agent-facing command is non-interactive and requires explicit intent: `--validate-only` or `--deploy`, never a bare `run-batch`.
87
+
88
+ ## Core concepts
89
+
90
+ - **Job** — one task branch waiting in the queue, with the SHAs captured at enqueue time.
91
+ - **Validated train** — an exact, deployable group of jobs that passed gates together and is waiting for explicit deploy approval.
92
+ - **Runner lock** — gives every claim a unique lease token, heartbeats through long-running commands, and prevents a stale runner from overwriting a newer owner.
93
+ - **Integration worktree** — a disposable, detached Git worktree built on your integration ref. The runner merges here, so agents never checkout or push the deploy branch.
94
+ - **Gate** — a verification command (diff-check, tests, secret-scan…) run once over the assembled train *before* push. A gate failure means nothing ships.
95
+ - **Verify hook** — a command run *after* push to confirm the deploy is live.
96
+ - **Auto job** — a job enqueued with `--auto`, the only kind the unattended daemon will touch. Manual jobs are left for a human-initiated runner.
97
+
98
+ Full reference in [docs/design.md](./docs/design.md) and the [CLI reference](./docs/cli.md).
99
+
100
+ ## When to use mergetrain
101
+
102
+ | Your workflow is… | Use |
103
+ |---|---|
104
+ | PR-first, remote-CI-first, hosted platform | GitHub / GitLab merge queue, Mergify, Aviator |
105
+ | Local agents in worktrees shipping to a deploy branch | **mergetrain** |
106
+
107
+ mergetrain is **not** a general-purpose job queue (it won't replace Celery/RQ/Sidekiq), a CI provider, or a deploy provider. The core is provider-neutral: your push targets, test commands, and deploy checks live in config, not in mergetrain.
108
+
109
+ ## Configuration
110
+
111
+ A single `.mergetrain.yaml` at your repo root holds all policy. The core stays neutral; you bring the commands.
112
+
113
+ ```yaml
114
+ project:
115
+ name: my-app
116
+
117
+ git:
118
+ remote: origin
119
+ integration_branch: main
120
+ push_refs: [main] # atomic push targets on deploy
121
+
122
+ queue:
123
+ lock_ttl_minutes: 30
124
+ heartbeat_interval_seconds: 10
125
+ command_timeout_seconds: 3600
126
+
127
+ gates:
128
+ - name: diff-check
129
+ run: git diff --check ${integration_ref}..HEAD
130
+ - name: tests
131
+ run: python -m pytest
132
+
133
+ deploy:
134
+ verify:
135
+ - name: live-health
136
+ run: curl -fsS https://example.invalid/health
137
+ ```
138
+
139
+ See the [config reference](./docs/config.md) for the full schema, placeholders, and environment variables.
140
+
141
+ ## For AI agents
142
+
143
+ mergetrain is designed so an agent can operate it from a short contract and JSON output, without guessing:
144
+
145
+ 1. Work on a task-specific branch in its own worktree.
146
+ 2. Commit before enqueuing.
147
+ 3. Never push deploy refs directly.
148
+ 4. Read `mergetrain doctor --json` / `status --json` before acting.
149
+ 5. Use `--auto` only after explicit human approval for unattended deploys.
150
+ 6. Let one runner or daemon own merge → test → push → verify.
151
+ 7. Fix `blocked`/`failed` work on the owning branch and enqueue a fresh clean job.
152
+
153
+ `mergetrain init` writes `AGENTS.mergetrain.md` / `CLAUDE.mergetrain.md` so your agents pick this up automatically.
154
+
155
+ ## Documentation
156
+
157
+ - [Quickstart](./docs/quickstart.md) · [Install](./docs/install.md)
158
+ - [CLI reference](./docs/cli.md) — every command and flag
159
+ - [Config reference](./docs/config.md) — `.mergetrain.yaml` schema, placeholders, env vars
160
+ - [Design & architecture](./docs/design.md) — the model, data model, and safety guarantees
161
+ - [Daemon](./docs/daemon.md) · [Failure modes](./docs/failure-modes.md) — operating it day to day
162
+ - [Manage from your phone](./docs/mobile.md) — drive mergetrain via Cowork Dispatch
163
+ - [Agent contract](./docs/agent-contract.md) — the rules agents follow
164
+ - [Security](./docs/security.md) · [Adapter pattern](./docs/adapter-pattern.md) · [Development](./docs/development.md) · [Release](./docs/release.md)
165
+
166
+ ## Status
167
+
168
+ `v0.1.0`, alpha. The core — queue, runner lock, merge train, gates, atomic push, auto-only daemon, JSON `doctor`/`status`, and the local read-only dashboard — is implemented with a passing test suite. Built for my own multi-agent workflow first; issues and ideas welcome. Review your config trust boundary, gate commands, and secret handling before enabling unattended deploys — see [security](./docs/security.md).
169
+
170
+ ## License
171
+
172
+ Released under the [MIT License](./LICENSE).
@@ -0,0 +1,15 @@
1
+ # Prototype Instructions
2
+
3
+ Run the local server yourself and open the preview in the browser available to this environment. Do not give the user server-start instructions when you can run it.
4
+
5
+ Before making substantial visual changes, use the Product Design plugin's `get-context` skill when the visual source is unclear or no longer matches the current goal. When the user gives durable prototype-specific design feedback, preferences, or decisions, record them in `AGENTS.md`.
6
+
7
+ When implementing from a selected generated mock, treat that image as the source of truth for layout, component anatomy, density, spacing, color, typography, visible content, and hierarchy.
8
+
9
+ ## Selected direction
10
+
11
+ - Use the approved hybrid: Live Track hierarchy (direction 3) with Signal Board clarity (direction 1).
12
+ - Keep the interface read-only, single-repository, desktop-first, and local-only for v0.1.
13
+ - Show actual runner phases, heartbeat freshness, blocked reason, activity, and the next safe action.
14
+ - Use a warm off-white canvas, dark ink, blue active state, green success, amber attention, red failure, thin borders, and restrained radii.
15
+ - Avoid literal train illustrations and action controls; the track is an information model, not decoration.
@@ -0,0 +1,15 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <meta name="theme-color" content="#fbfaf7" />
7
+ <meta name="description" content="Live, read-only local mergetrain status" />
8
+ <link rel="icon" href="/favicon.svg" type="image/svg+xml" />
9
+ <title>mergetrain · live local status</title>
10
+ </head>
11
+ <body>
12
+ <div id="root"></div>
13
+ <script type="module" src="/src/main.jsx"></script>
14
+ </body>
15
+ </html>