Skip to content

0.3.0

Cut on 2026-09-06, hours after 0.2.0. Every component is tagged v0.3.0 in lockstep; the manifest table on the Releases page pins them. coxswain-tools is published to PyPI from that tag, so uv tool install coxswain-tools gets you the cox command.

Status: beta, unchanged. Nothing here breaks a 0.2.0 install.

This release is almost entirely the loop fixing itself. Of the thirty-odd changes below, the harness wrote and reviewed all but a handful, against its own repositories, and a person merged each one. The defects it fixed are the defects that were costing it runs.

The loop stops lying about why a build failed

Three of the day's fixes are the same shape: a run reported a verdict it had not earned.

A stale phase branch is decided before its tasks build, never after. A phase whose branch was behind its base used to build every task against ground that was missing landed work, then rebase at the end and quarantine whatever no longer applied. Twice in one morning a correct diff was discarded that way. The phase is now rebased, or blocked by name, before the first task runs.

A check that could not run is a harness fault, not a failing build. The configured check is pytest -q, and a fresh worktree has no virtualenv, so the command was answering a question about an interpreter that is not the project's. That reached the record as configured checks failed. It now reaches the record as a named fault carrying the command and what the shell said about it.

An approved build that does not land says so. A build the reviewers and the arbiter approved could still fail to reach a branch, and nothing in the run's exit said which task or how to recover it. The exit summary now names each one with the command that re-applies it.

The dispatcher and the decomposer

A failed child dispatch leaves a record naming its intake item, and a decompose runs under the initiative's budget rather than a fixed node cap. initiative-decompose writes initiative.md with phase goals, and its --target-repo flag no longer collides with the harness's own --repo — a collision that made every shell.py invocation die at parser build.

A truncated patch is retried rather than reviewed, and a patch is salvaged from the scratch tree when the model's recollection of it has drifted.

New in cox

  • cox home — one screen as the front door: leader, runs, backlog and attention in bordered panels, ENTER to drill into a run, l to land, i for intake, t for the conversation.
  • cox runs top — columns that line up, a TOKENS column over every token a run spent, and an expansion that opens under the row rather than replacing the table.
  • cox route leader take|beat|release|status — one file says who drives the landing loop, now with --pid naming the durable process that owns it, refused when that process is not alive.
  • cox setup — a Roster tab listing every seat from the resolved cast, with enabled honoured by setup install and reported by the doctor.
  • cox route pull — the first intake adapter, GitHub issues, behind a source interface the other trackers will implement.
  • cox dev release-check — the docs checks that compare the CLI surface, the manifest and the release notes against what actually landed. Known defect: on a clean tree it reports drift that is not there, from a doubled path in the manifest check and a comparison against CLI pages that are generated at docs-build time. Filed; until it is fixed, cox dev release needs --allow-doc-drift.

Install

macOS gets a Homebrew path beside uv:

brew install ppfenning/coxswain/cox
cox setup doctor

The formula installs cox alone; cox install fetches the rest from the manifest. The manifest itself now documents two channels — a component entry carries either tag (release) or ref (edge), never both, because a half-edge install is a configuration nobody tested.

Style is guidance, and a linter proves the half it can

The review seat judges correctness only: a departure from the code style is noted, never a reason to withhold approval. Three of four quarantines on 2026-09-05 were style revises of code the arbiter had itself called correct, each burning four build attempts before the work was discarded. The mechanical half now belongs to ruff, whose rules are declared once in each repository's pyproject.toml and mirrored by pre-commit, and the judgment half belongs to a style_pass seat that runs after approval and makes the edit rather than sending the build back.

Known gap: the cartridge's configured checks still run only pytest, while every component repository runs ruff and pytest in CI. Six pull requests in one day were red on GitHub for a lint rule the harness could not see when it opened them. Filed.

Also

policy.gate ships ticket as the base default, so a first-time installer's harness proposes and a person merges. A cartridge's cast validates enabled as a bool through the resolution chain. resolve_surfaces refuses a work item whose surfaces are not real paths in the checkout, which is what stopped three runs at the plan node in a single day. The decompose, intake-link and release-sync skills state the rules the harness now enforces.