Skip to content

0.46.0

Cut on 2026-10-18. Status: beta. A hardening release from moving the maintainers' own machines under the coxswain home. cox setup migrate --finish can now finish: a lane host that reports a folder inside a moved checkout counts as migrated, and a second --apply after the move keeps the migration marker and plans no drop-in rewrite. The migration also rewrites the profile's repo_map entries for the moved checkouts. The chair's status line counts lanes across every host, an empty queue with idle lanes pushes one notice, and the loop pulls issues at most every ten minutes, where it had exhausted the GitHub GraphQL limit. Only coxswain-tools changes.

cox setup migrate --finish finishes. A lane host's beat lists coxswain-cartridges/providers among its repositories, and the check for a migrated host wanted every path directly under the installs folder, so --finish answered finish: waiting on host <name> to migrate for every host however long it waited. A path anywhere inside the installs folder now counts. After the move every profile setting names the installs folder, so a second cox setup migrate --apply resolved the old root to the installs folder itself: it overwrote migrate.json with the old root equal to the new one, and it planned the chair unit drop-in rewrite on every run, so the local plan never came down to the single skip that --finish waits for. The marker is now written only while the old root differs from the installs folder, and the unit and drop-in steps are planned only when a folder actually moves.

The migration rewrites repo_map. The profile's repo_map, which maps a repository name to its checkout, kept naming the old checkout folders after a migration and had to be rewritten by hand before --finish removed the compatibility links. A repo_map value that equals an old checkout path, in its absolute or tilde spelling, is now rewritten to the checkout under the installs folder in one rewrite_profile_key step, and every other entry is left as it is. A second run plans nothing for it.

The chair sees the whole fleet. The status line's lanes part reads lanes L/C (here l/c) when there are lane hosts: L and C add every host's live lanes and capacity to the chair's own, which stay in the parenthesis. It had shown only the chair's machine, lanes 0/4 while ten lanes were building elsewhere. An empty queue now pushes one notice, Queue empty, when no initiative has a ready task, no intake is queued, no task is approved, no lane is live on any host and the tick raised no hold; it pushes once until the queue fills again. And the issue pull, which the chair planned on every idle tick for every routed repository, now waits ten minutes after the last one.

coxswain-tools

  • setup migrate: a folder inside a checkout under the installs folder counts as migrated (tools #1801), and a re-run after the move keeps the marker and plans no unit or drop-in rewrite (tools #1802).
  • setup migrate rewrites the moved checkouts' entries in the profile's repo_map (tools #1805).
  • The status line counts lanes across every host (tools #1803).
  • An empty queue with idle lanes pushes one Queue empty notice (tools #1806).
  • The chair plans the issue pull at most every 600 seconds, from a new pull_age_s fact (tools #1804).

Known gaps

The umbrella's development environment declares the tools checkout as ../coxswain-tools. cox setup migrate moves the tools checkout under the home and leaves the umbrella where it is, and --finish removes the compatibility link, so uv run in the umbrella cannot resolve the tools package afterwards. On a maintainer's machine that cuts releases, keep a coxswain-tools link beside the umbrella until the migration moves the umbrella too. The migration does not list operator scripts, launchd jobs or systemd units outside the chair unit that still name an old checkout folder; check them by hand before --finish.

From 0.44.0, still open: the doctor has no lane host paths or migration state row, and profile paths does not check umbrella_dir; the migration emits no beat when it ends, so --finish waits on each host's next beat. From 0.43.0, still open: the empty-decompose hold always says no refusal line was found in the decompose log, cox runs triage takes no --profile or --repo, and nothing sets up the timer for cox chair watchdog.

The gate for 0.46.0 was the hosted rehearsal (run 39099135025), whose fresh, upgrade and migrate jobs passed, and a clean-machine rehearsal in a throwaway Proxmox container, where the fresh install, the upgrade from 0.45.0 and cox setup migrate passed. Both ran on tools 50d302f, graphs 0c138e2, dash b654297, cartridges 8584e34 and crew 80eb36a.

Migrations: none

Components

coxswain-tools changes and is released at 0.46.0. coxswain-graphs has no commits since v0.43.0 and stays pinned there, coxswain-dash has none since v0.42.0 and stays pinned there, coxswain-cartridges has none since v0.40.0 and stays pinned there, and coxswain-crew is unchanged since v0.38.0 and stays pinned there.

Upgrading from 0.45.0. The store schema is unchanged and nothing migrates on its own. Update cox itself first, with uv tool upgrade coxswain-tools or brew upgrade cox, then run cox upgrade. If a cox setup migrate --finish was waiting on hosts, run cox host beat on each host and run it again.