Skip to content

0.23.0

Cut on 2026-09-28. coxswain-graphs and coxswain-tools are tagged v0.23.0. coxswain-cartridges had no changes and stays pinned at v0.21.0; coxswain-crew stays pinned at v0.12.0. coxswain-tools is published to PyPI from its tag. Status: beta. This release lets the fleet run itself, and it carries four headlines.

The store is the board. Work items live in the store (graphs harness.store_queue, migration 0009), intake states agree between the ticket files and the store, and cox route drift compares intake rows as well as tasks. A machine whose profile names a shared Postgres storage_url now reads its board from the store when the store answers, and says work state: files (store unreachable) when it does not; a local SQLite store keeps the ticket files, so local-first stays the default.

A lane host can come and go. A lane whose host has gone quiet and whose own lease heartbeat has stopped is marked lost and relaunched elsewhere; hosts can be drained, and placement weighs hosts and their capabilities. The loop checks each lane host's Claude login every 30 minutes over ssh, records it with the host's beat, and gives a host with a lapsed login no new lanes. A remote run's approvals reach the chair's ticket files when it is fetched, and so do its phase branches.

The chair is resident and has a console. cox chair service --install --host <name> prints or runs the steps that put the chair loop on a lane host as a user service, and --status --host reports it. cox console is one terminal screen of drafts, hosts, lanes, the chair and needs-chair items, whose keys run cox commands after a y/n. Stale work becomes a draft for a person to approve or decline.

One merge to main per phase. The loop lands a completed phase as one squash of its branch onto a fresh main, from its own pr/ branch, and marks every task in it done; a partial phase's branch is carried forward on relaunch with main merged into it, and an approved task of a partial phase waits for its phase instead of landing alone.

Upgrading from 0.22.0. Run the graphs migration (0009) against the store. A lane host needs the tools' postgres extra. To make a machine a resident chair, run cox chair service --install --host <name>, then the two steps it prints for a person (loginctl enable-linger and systemctl --user enable --now).

coxswain-tools

  • Lost lanes: the contract, the drained display, marking a run lost, the recovery rule and the signal reader (tools #1061, #1063, #1065, #1067, #1069); placement facts and weighted, capability-aware fill (tools #1090, #1092). A lane counts as lost only when its own lease heartbeat is quiet too (tools 95616b6).
  • Login watchdog: types, the watch rule, the executor, the facts and the plan (tools #1097, #1099, #1101, #1103, #1105); the loop reads the hosts table for it and the ssh check times out after 60 seconds (tools 249cca8).
  • One merge to main per phase: the carry rule, no lone lands for a partial phase, the land_phase action and its executor, the stranded wiring and the carry merge (tools #1078, #1080, #1082, #1109, #1113, #1115). Phase lands accept approved tasks, squash the phase onto a fresh main from a pr/ branch, close each task's work item, and a remote fetch brings back phase branches (tools #1140, #1142, #1150, #1152). The planner switch (tools #1117) was reverted until a phase land could merge (tools 168c789) and then re-applied (tools #1154); the first phase land under it is tools #1156.
  • Stale work becomes a draft: the executor, the planner, the signal reader and the facts (tools #1074, #1084, #1086, #1095); a ticket with no commit reads its file's modification time, so a fresh ticket is never stale (tools 91a4010); a stale draft names proposed_by and proposed_at (tools 5e736a7).
  • The store as queue: cox route file writes the store first (tools #1088); intake states agree, and drift and import compare intake rows (tools #1136, #1146, #1148); the work-state default reads a shared Postgres store (tools #1156).
  • cox console (tools #1121, #1125, #1127), with drafts, one needs-chair line per item and host login shown (tools 21a6b57).
  • Resident chair: the install steps, --install --host and --status --host (tools #1130, #1138, #1144).
  • Remote runs: every unfetched remote run is found, not only the newest, and a run with no directory is fetched once (tools #1132, #1134); a fetched run's approvals reach the ticket files (tools 936aa2e).
  • The loop: it takes its lease under its own host (tools 6abe8d1), recovery launches stop at the machine's free lanes (tools 2d26c92), and a loop tick under a takeover still moves the record heartbeat (tools #1123).

coxswain-graphs

  • harness.store_queue: migration 0009 adds the work-item queue columns, and the queue verbs read, upsert, claim and release rows (graphs #594, #596); an upsert without a stamp gets the write time and store_queue as author (graphs 980225b).

coxswain

  • Fleet and Chair dashboards: the fleet datasets, the charts and dashboards, the installer creating every listed dashboard, and their docs (coxswain #172, #175, #179, #181).
  • The release branches the tap PR from the fetched remote default, not the local tap checkout (coxswain #177).
  • The 0.22.0 notes name the real pins (coxswain 7a3e274).

Components

coxswain-tools carries most of the release, coxswain-graphs the store queue, and the umbrella the dashboards and the release fix. coxswain-cartridges and coxswain-crew are unchanged.