0.47.0
Cut on 2026-10-18. Status: beta. A hardening release that closes the known gaps 0.43.0 to 0.46.0 left open around the coxswain home and the chair loop. The migration now moves the umbrella and 0.40-style installs, lists operator scripts it cannot rewrite and beats when it ends. The doctor gains the rows the home design promised. The chair holds an approved task's files until it lands and resolves appended test conflicts at land. Several commands now refuse input that used to be accepted and then fail later. Only coxswain-tools changes.
The migration finishes on every layout. cox setup migrate now moves the umbrella checkout (coxswain) under the
installs folder with a compatibility link when it is present, so its ../coxswain-tools dependency resolves after
--finish. A host without an umbrella plans nothing for it. An install from 0.40.0 that keeps bare-named checkouts
behind coxswain-<name> links was refused; the plan now moves the link's target and relinks the old path. A successful
--apply lists every operator script that still names an old checkout folder, as migrate: <file> still names <old
path>; edit it by hand, and ends with a host beat, so --finish no longer waits for the next beat.
The doctor checks what the migration touches. profile paths now checks umbrella_dir when it is set, and a new
lane host paths row fails when a lane host still beats a checkout path outside the installs folder. The home paths
row accepts a provider profile kept in the team's workspace, which no migration moves. The forge row asks the GitHub
API for the login (gh api user) instead of gh auth status, which rejected a working GH_TOKEN after a rate-limit
episode.
The chair keeps parallel work from colliding. An initiative whose tasks are approved but not yet landed now holds
its files against new launches, as a running one does; a second initiative had built on the same function four times
and conflicted at land each time. When a phase squash conflicts only in test files where both sides append new lines at
the end, the land keeps both sides instead of stopping. An empty decompose now holds with the lint refusal from its log
instead of refusal line not found.
Commands refuse what they cannot do. cox route file refuses a --repo, or a repo: in the intake's frontmatter,
that is not a git checkout on this machine, with route file: refusing, <repo> is not a git checkout on this machine
and exit 2; such intakes used to file and then fail every launch. cox host beat <name> refuses a name other than this
machine's, since the beat records this machine's facts. cox runs triage takes --profile and --repo, so it reads
the profile's store and a named repository from any folder. cox chair watchdog --install writes the five-minute timer
the watchdog was meant for (a launchd job on macOS, a systemd user timer on Linux), --uninstall removes it, and
--interval-minutes changes the period.
coxswain-tools
- An approved task not yet landed holds its surfaces against other launches (tools #1808).
- A phase squash whose only conflicts are appended test lines lands with both sides (tools #1815, #1818).
- The empty-decompose hold names the lint refusal from the decompose log (tools #1809, #1812).
setup migrate --applylists scripts naming old checkouts and ends with a beat (tools #1813, #1817), run through the installedcox host beatso a reinstall during the apply cannot break it (tools #1827).- The doctor
forgerow asksgh api user(tools #1811). - The doctor checks
umbrella_dirand adds alane host pathsrow (tools #1821). cox chair watchdog --install,--uninstalland--interval-minutes(tools #1810, #1814).cox runs triagetakes--profileand--repo(tools #1825).cox host beatrefuses another host's name (tools #1822).cox route filerefuses a repository that is not a checkout (tools #1824).setup migratemoves the umbrella checkout (tools #1819, #1826).- The
home pathsrow accepts a provider profile kept in the workspace (tools #1823). setup migratemoves a 0.40 install whosecoxswain-<name>paths are links (tools #1816, #1820).
Known gaps
The migration lists operator scripts that name an old checkout but does not rewrite them, and it does not read launchd
jobs or systemd units other than the chair unit. An intake row is not linked to its initiative when the intake
decomposes, so it stays queued in the store after its work lands; the empty-queue notice counts those rows and stays
silent until they are closed by hand.
The gate for 0.47.0 was the hosted rehearsal (run 39131292779), 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.46.0 and
cox setup migrate passed. Both ran on tools b11d3d6, graphs 0c138e2, dash b654297, cartridges 8584e34 and crew
80eb36a.
Migrations: none
Components
coxswain-tools changes and is released at 0.47.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.46.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. A host whose cox setup migrate
--finish waited on home paths because its provider profile lives in the workspace can now run it again.