mainline stops parallel coding agents and worktrees from clobbering protected
main by turning local branch landing into a serialized, durable,
machine-readable queue.
mainline is a local coordinator for a protected Git branch.
It owns:
- submission of work to a durable queue
- serialized integration onto the protected branch
- publish coordination to the remote
- queue state, events, retries, operator controls, and health reporting
It does not own:
- arbitrary Git authoring workflows
- CI systems
- hosted merge queues
- semantic conflict resolution
- every Git operation a factory might perform outside protected-branch landing
- keep the root checkout of
mainclean - do feature work in topic worktrees
- land through
mq, not through manual merge/push onmain
- give each agent a worktree
- let agents submit completed work without touching protected
main - keep queue state durable and inspectable
- submit work from worktrees or durable refs
- wait on structured lifecycle outcomes
- inspect machine-readable status, events, health, and logs
- let one daemon own integration and publish for many repos
If mainline becomes a library, the supported use case is:
- embedding coordinator semantics inside a larger Go system
- using typed
Submit,Wait,Status,Events,Retry,Cancel, andDoctorflows - avoiding subprocess boundaries for Go-based factory supervisors
That library use case is about orchestration. It is not about replacing Git itself.
The durable model is:
- one protected branch per repo
- one integration queue per repo
- one publish queue per repo
- one repo-local SQLite state store
- per-repo advisory locking
- one canonical root checkout that humans inspect
- many disposable feature worktrees where changes are authored
Submission writes queue state first. Draining is opportunistic:
mq submitrecords the submission durablymq submitmay try to drain if no worker currently holds the lock- otherwise an existing worker or
mainlineddrains it later
This keeps submit cheap and reliable while still giving low latency when the queue is idle.
- protected
mainmust stay clean before and after anymainlineaction mainlinemust not create commits on protectedmain- conflicts belong to the submitted worktree or submitted ref, not protected
main - only one integration runs per repo at a time
- only one publish runs per repo at a time
- newer publish requests supersede older stale ones
- machine-readable output must remain versioned and documented
- the root checkout must be trustworthy enough for humans, wrappers, and supervisors to inspect
From a feature worktree:
mq submit --check-only --json
mq submit --wait --timeout 15m --jsonOr:
mq submit --json
mq wait --submission <id> --for landed --json --timeout 30mmq land --json --timeout 30mmq land is a blocking land command. When [repo].RemoteName names a remote,
it must publish and fail before queueing if that remote is missing from the
protected worktree. Local-only repositories with [repo].RemoteName = "" may
use mq land, mq submit --wait --for landed, or mq wait --for landed; a
verified protected-branch integration is the terminal landed state because no
remote publish target exists.
If a publish request fails because remote main advanced first, the supported
operator recovery path is:
mq retry --repo /path/to/protected-worktree --publish <id>Before retrying the push, mq may fetch upstream and rebase the protected
branch onto the updated upstream tip when unpublished local commits replay
cleanly. When local branch tracking is not configured, mq compares the
protected branch against the protected remote branch configured in
mainline.toml.
mainlined --all --jsonWith repo-local observation:
mq events --repo /path/to/root --follow --json --lifecycleThe public automation contract is:
mqandmainlined- the JSON shapes documented in
docs/JSON_CONTRACTS.md
The public automation contract is not:
- internal Go structs
internal/packages- undocumented CLI fields
Compatibility expectations:
- additive JSON fields are allowed within a schema version
- removals, renames, or semantic breaks require a schema-version change
- tests must enforce the documented contract
These are current design constraints, not hidden bugs:
- one protected branch per repo
- CLI/daemon first; stable Go library surface is not yet committed
- native
gitremains the write path for workflow-critical operations such as rebase and push - factories should currently integrate through the CLI/daemon contract, not by
importing
internal/ - queued or blocked submissions whose
source_shais already reachable from protectedmainare obsolete and may be auto-superseded even if their original source worktree has been deleted - status and doctor report when protected
mainhas committed work that is ahead of the latest known published tip; that state should be published or reconciled, not reset as disposable drift
The next productization work is:
- stabilize the factory-facing JSON API further
- reduce dependence on live source worktrees for unattended flows
- add publish circuit breaking and better recovery tooling
- improve supervisor metrics and readiness
- harden the machine-global daemon model
- decide whether to expose a supported
pkg/Go library surface
The forward execution plan for that work lives in PLAN.md.