Skip to content

coxswain 0.38.0

Choose a tag to compare

@ppfenning ppfenning released this 12 Oct 21:14
· 2027 commits to main since this release

0.38.0

Cut on 2026-10-12. Status: beta. Coxswain now ships with no personal references: no person's name, host,
home path or private address in any shipped repository, and the release refuses a component whose tree names one.
Personal setup lives in two places outside the shipped code: a team cartridge, kept in a repository of its own,
and the provider profile. The human that the courier and decisions address is now a profile setting, operator,
not a name compiled into cox. The release also unsticks the loop: a phase with a quarantined task still lands
its approved tasks, a hand edit to a ticket reaches the store instead of being reverted by the next export, and
the loop's store calls cannot hang a tick.

Nothing personal ships. The release runs the clean check, .github/check_clean.py, on every tree it would
tag, a pinned component at its tag, and refuses before it cuts. The check refuses home paths, .lan hosts,
tailnet and 192.168 addresses, and tracker and platform vendors, and it reads the names to refuse from the
COXSWAIN_CLEAN_DENY secret, so the names themselves are never committed. The install guide has a section on
where personal setup goes, and the providers page describes the operator.

Lands that keep moving. The chair lands the approved tasks of a phase that also holds a quarantined task, one
task at a time, keeps the sibling branches each land would remove, and skips a task another machine has already
landed. A land renews its repository lease while it waits on checks. A store-mode fetch of a run with nothing
approved succeeds.

The queue says what it means. Route priority can put an initiative on top of or below every other open
initiative, measured against open work only. A ticket edited by hand is not overwritten by the export, and
cox route edit writes a task ticket to the store first.

A tick that cannot hang. The loop's store connections carry connect, keepalive and statement timeouts. The
facts stage has a wall-clock bound; a tick that overruns it is abandoned, and cox chair run exits for its
supervisor after three overruns in a row.

A red main from a job that never started is rerun. When main goes red because a CI job never started, the
loop reruns it instead of reverting the land that preceded it; a real test failure is still reverted.

Deferred to 0.39.0. The reach allow-list, home-relative repository paths, and an epic land that closes its
tasks' review pull requests (the forge call and the selection core land here; the land does not call them yet).

Upgrading from 0.37.0. The store schema is unchanged. Courier rows and decisions are addressed to the
profile's operator, which defaults to operator. An install whose courier rows were addressed to a person's
name sets operator: <name> in its provider profile, then restarts the chair loop. cox settings get --json
reports operator_only and, for this release only, the old pat_only field with the same value; the dashboard
reads either. A fork that runs the clean check in CI sets its own COXSWAIN_CLEAN_DENY secret; without it the
names rule is skipped and the other rules still run. coxswain-crew rejoins lockstep and is tagged v0.38.0.

coxswain-cartridges

  • The local cartridge lists no inline repositories; a team cartridge lists its own. Skills, provider profiles
    and design docs say "the operator" instead of a name (cartridges #204).
  • docs/PROVENANCE.md is removed (cartridges #203).

coxswain-crew

  • liam, alice and the model steward address the operator, not a name, and alice names the role, not a host
    (crew #13).
  • CI runs the canonical clean check from the tools repository, with names from the COXSWAIN_CLEAN_DENY secret
    (crew #14); the ruff comment keeps its reason without a name or date (crew #12).

coxswain-dash

  • The settings frame marks a setting "operator-only" and reads operator_only from cox settings get --json,
    falling back to pat_only (dash #126, dash #127).
  • Actions, forms, inline tests and fixtures use neutral host and repository names (dash #125, dash #127).
  • The runs view selects the line it draws, so a selected run far down a long list stays in view (dash #124).

coxswain-graphs

  • No operator, host or personal path ships: comments keep their reason without a name or date, design docs name
    the approver by role, and examples and fixtures use neutral hosts and paths (graphs #759). The README drops
    the link to the removed provenance page (graphs #758).
  • store_cli host login records a host's login state without touching its beat time (graphs #750, graphs #752).
  • The claude runner kills its whole process group on a timeout (graphs #753).
  • Every quarantine records its cause, and a crash in a later phase keeps the earlier phases' approvals
    (graphs #755).
  • Decompose names the build grant and the repository bound in its prompt and never writes a ticket that route
    lint refuses (graphs #756, graphs #757).

coxswain-tools

  • The provider profile's operator key, default operator, names the human the courier and decisions address.
    cox settings get --json reports operator_only in place of pat_only, and keeps pat_only as an alias for
    one release (tools #1558).
  • Tests and fixtures use neutral names, and .github/check_clean.py refuses home paths, .lan hosts, tailnet
    and 192.168 addresses, vendors, and the names in the COXSWAIN_CLEAN_DENY secret (tools #1554). It takes
    --skip RULE and never scans target/ (tools #1557).
  • A phase with a quarantined task still lands its approved tasks: the chair plans a partial land, lands each
    approved task in order while it backs up and restores the sibling branches, and the status line names it as
    partial-land (tools #1529, tools #1543, tools #1544, tools #1545). A task land adopts an open pull request
    (tools #1545), and a partial land skips a task another machine already landed (tools #1556).
  • The loop's store calls cannot hang a tick: its store connections carry connect, keepalive and statement
    timeouts (tools #1549), the facts stage has a wall-clock bound (tools #1546), and cox chair run exits 3
    after --max-overruns overruns in a row, three by default (tools #1551).
  • Ticket edits reach the store: the export refuses to overwrite a hand-edited ticket, the status line has an item
    for a ticket file ahead of the store, and cox route edit accepts a task ticket id (tools #1522, tools #1523,
    tools #1540).
  • cox route priority --top and --bottom place an initiative one above or one below every other open
    initiative, measured against open work only, and a queued intake takes a priority as well (tools #1524,
    tools #1527, tools #1531). Decomposed tasks inherit their intake's priority (tools #1547).
  • A red main from a CI job that never started is rerun instead of reverted: the job classifier, the rules, a
    per-commit read of main's CI, the green-since reader, the facts, the executor's rerun port, and a revert that
    replaces its own leftover branch (tools #1520, tools #1521, tools #1534, tools #1538, tools #1539, tools #1541,
    tools #1542). The loop wires the green-since reader and the rerun port, and a pending watch resolves once main
    goes green at or after its commit (tools #1559); an end-to-end test covers the rerun, the revert and no
    walk-back (tools #1560).
  • Clearing branches before a relaunch ignores another initiative's lands in the same repository, so a relaunch
    is not starved by them (tools #1561).
  • The forge can close pull requests, and a pure core picks an epic land's task review pull requests to close
    (tools #1548).
  • A land renews its repository lease while it waits on checks (tools #1535).
  • A store-mode fetch of a run with nothing approved succeeds, and a failed fetch keeps cox's verdict ahead of
    git's output in the reason (tools #1532).
  • The login check reads claude auth status from stdout only, renews an expired access token once before it
    counts a failure, and blocks a host only on its second failure in a row; cox host doctor runs directly on the
    loop's own host (tools #1528, tools #1530).
  • cox setup doctor checks the chair service unit's PATH: every entry absolute, and cox and pytest reachable
    (tools #1526). It warns when a model tier is not its family's newest, or the vendor has a newer model than the
    catalog (tools #1552).
  • Route lint's grant rule flags only the commands a ticket asks the seat to run (tools #1553).
  • The verdict the chair's launch gate will use to launch an initiative only when it has a runnable task
    (tools #1533).
  • Read-only store connections autocommit, so a read never holds a transaction open, and the notifier backs off and
    reconnects after a store error instead of exiting (tools #1525).
  • The lake doctor reports a dangling metadata pointer, and housekeeping skips the prune when traces live in object
    storage and keeps a failed step's last exception line (tools #1536, tools #1537, tools #1555).
  • The load-sensitive CLI startup tests run only when COX_RUN_LOAD_TESTS=1, so a busy host no longer fails a
    land at random (tools #1550).

coxswain (umbrella)

  • The release refuses a component whose tree names a person, host or home path: it runs coxswain's
    .github/check_clean.py on each tree it would tag, a pinned component at its manifest tag, and never prints
    the matched text (coxswain #287). The umbrella's tests drop their last personal names (coxswain #289).
  • The docs use neutral names (coxswain #283, coxswain #284, coxswain #285, coxswain #286). The install guide has
    a section on where personal setup goes, a team cartridge or the provider profile (coxswain #282), and
    docs/customize/providers.md has a section on the operator (coxswain #288).
  • The release fetches before it tags and refuses a checkout that is not at origin (coxswain #276), and checks
    each component in a fresh virtual environment (coxswain #277).
  • The install proof's Linux job installs a python3 for its checker, and its negative control goes green when
    both platforms fail as expected (coxswain #275, coxswain #278).
  • A release drafts its own notes: python -m devtools notes-draft <version> writes the page from the pull
    requests merged since each bumped component's last tag and registers it in the index and nav, and
    --cheap-opener fills the opener with a short model draft (coxswain #279, coxswain #281).

Components

coxswain-cartridges, coxswain-crew, coxswain-dash, coxswain-graphs and coxswain-tools all change; coxswain-crew
rejoins lockstep from v0.32.0.