# mergetrain full LLM operating guide

mergetrain is a local Git integration train for coding-agent worktrees. It is not a
background job queue, cloud CI provider, deploy provider wrapper, or PR-first
merge queue.

## Contract

Agents should:
1. Work in task-specific branches and worktrees.
2. Commit a clean result before enqueueing.
3. Run `mergetrain doctor --json` before deciding the next queue action.
4. Enqueue with `mergetrain enqueue --task TASK --branch BRANCH --capture-sha`.
5. Never push configured Git refs directly.
6. Leave merge/test/push/verify to one runner or daemon.
7. Use `--auto` only after explicit unattended-deploy approval.

## Status interpretation

- `queued`: waiting for a runner.
- `in_progress`: claimed by a single-job runner.
- `blocked`: merge conflict or user action needed. If `conflict_with` is
  non-empty, this is a semantic conflict found during train bisection: the
  job passes gates alone but fails combined with the comma-separated job IDs
  listed there (partner branches and SHAs are in `note`). Fix by rebasing
  onto the integration branch with the partner's change merged, then enqueue
  a fresh job.
- `failed`: gate or command failure.
- `validated`: validation succeeded without push; the exact train remains deployable after approval.
- `deployed`: deploy push succeeded; inspect `push_status` and `verify_status`
  for the independent push and post-push verification outcomes.
- `needs_reconcile`: a crash left a possibly-landed push; run `reconcile`
  (dry-run) then `reconcile --apply` or `recover`. Every deploy entrypoint is
  refused while any job is in this state.
- `canceled`: user canceled the item.

## Safe commands

```sh
mergetrain status --json
mergetrain doctor --json
mergetrain agent-contract --json
mergetrain inspect JOB_ID --json
mergetrain events --job JOB_ID --after EVENT_ID --follow --jsonl
mergetrain logs JOB_ID --tail 200
mergetrain gc --json
mergetrain reconcile
mergetrain hub list --json
mergetrain hub status --json
```

The hub is a machine-level, read-only aggregate over registered repos. It
owns no queue state: every repo keeps its own SQLite database, runner lock,
and recovery markers, and observing a repo never creates queue data or migrates
anything inside it. `hub status --json` returns one entry per repo with
per-repo errors isolated.

For long runs, prefer `inspect` or scoped `events --follow` over OS process
inspection. JSONL is one object per line: persisted `type=event` rows have the
resume ID, ephemeral `type=heartbeat` rows report lease progress, and the final
`type=stream_end` row reports success, failure, cancellation, lost lease, or
interruption. Reconnect after the last persisted event ID, not a heartbeat.
`logs` explicitly exposes raw local command output and may contain secrets;
structured events do not copy subprocess output.

## Consent-sensitive commands

```sh
mergetrain run-batch --deploy
mergetrain enqueue --auto ...
mergetrain hub daemon
mergetrain reconcile --apply
mergetrain recover
mergetrain unlock --force
mergetrain gc --apply
mergetrain gc --apply --delete-branches
```

Do not infer consent from context. Require explicit user/operator approval for
unattended deploy and deploy execution. `hub daemon` deploys `--auto` jobs
across every registered repo (through each repo's own runner and lock, with a
machine-wide `--concurrency` cap), so it carries the same approval requirement
as `--auto` itself. A repo registered with `hub add REPO --no-daemon` is
excluded from every sweep as policy; do not re-enable it without explicit
operator instruction. Recovery applies (`reconcile --apply`, `recover`,
`unlock --force`) mutate queue state or steal a lock; run the dry-run first.

Repositories may configure `terminology.git_operation: integrate` or `push`.
Human output and the preferred `--integrate`/`--push` alias follow that setting,
but the JSON/SQLite contract remains `status=deployed`, `deploy_sha`, and
`deploy.*`. Completion proves the configured Git refs were atomically updated;
`deploy.verify` reports an independent post-push outcome, and a provider release
remains a separately labeled and authorized action.

After `run-batch --validate-only`, read `status --json.validated_trains` to
identify the approved `train_id`, member branches, and recorded HEADs. A later
`run-batch --deploy` rebuilds that train on the current integration ref and
reruns gates. If several validated trains are pending, pass `--train-id`.
Validated-but-not-deployed branches are never branch-deletion candidates for
`gc --delete-branches`.

Validated-gate reuse is disabled by default. Use an explicit
`deploy.reuse.enabled` policy or `run-batch --deploy --reuse-validated` only
after inspecting `--preview --json`. Reuse requires an unchanged integration
base, task heads, train membership, validation commit/tree, gate policy,
environment fingerprints, and age; otherwise it reruns all gates or fails
closed. The exact reused commit is `reused_validation_sha`. Post-push verify
hooks always run.

Run JSON distinguishes `result=warning` from full success. In particular,
`status=deployed`, `push_status=succeeded`, and `verify_status=failed` means the
remote ref changed successfully but post-push verification still needs
attention; do not report that outcome as a failed push or a full success.
