Gas City v1.5.0
v1.5.0 is the new stable release and supersedes v1.4.2. It is tagged from
release/v1.5.0 at f66474617d, which differs from v1.5.0-rc1 only by the
CHANGELOG release commit. Install it with brew install gascity /
brew upgrade gascity or from the release assets (see Install). The
biggest change is underneath the work ledger: Beads (bd), not Gas City,
now owns the Dolt process of every new city. Every maintenance order reaches
the ledger through gc bd, and v1.5.0 requires bd v1.3.1. Existing cities
keep running on gc-managed Dolt until you migrate them.
The Dolt ownership change
New cities run on a bd-owned proxied Dolt store, and Gas City no longer
starts a Dolt server of its own for them (#6273). Existing cities are not
converted automatically. They keep their gc-managed Dolt server until you run
gc beads city migrate-proxied (see
Migrating an existing city).
What changed
- bd owns the Dolt process lifecycle. A fresh
gc initorgc rig add
runs bd's own proxied-server init. bd starts abd db-proxy-child, which
runs adolt sql-serverrooted at<scope>/.beads/dolt.gc stopasks bd to
stop each scope (bd dolt stop, last, after agents and sessions), and stop
is re-runnable. gc writes no Dolt runtime state, allocates no Dolt port and
starts no Dolt server for these scopes. - bd is the topology authority.
.beads/metadata.jsondolt_mode: proxied-serveris the persisted truth. gc keeps only
.gc/scope-ownership.json, a crash-safe journal of its init intent. - Each scope has its own store. The city and every rig created by
gc rig addget their own proxy and their own Dolt server. A legacy city
ran one gc-owned server for the city and all its rigs. - The proxy stays resident. gc initialises its scopes with bd's idle
timeout set to never (idle_timeout: -1in
.beads/proxied_server_client_info.json), so commands do not pay a proxy
and Dolt cold start after a quiet period. - Maintenance goes through
gc bdon every topology (#6751).reaper,
jsonl-exportandmol-dog-backupreach each scope withgc bdand use
bd's own export, backup and purge, so proxied, gc-managed and mixed cities
are all maintained. The dolt pack's managed-server orders are typed no-ops on
a bd-owned scope. Details are in the Upgrading Notes. - Do not run
bd dolt startorbd dolt statuson a proxied scope.
Neither is proxied-aware, andstartlaunches a second, unmanaged
sql-serverover the same data directory. Any ordinary bd command restarts
a stopped proxy by itself. - Escape hatch:
gc init --beads-transport direct --beads-target local
still gives a bd-owned server-mode store (one bd-starteddolt sql-server
per scope, with.beads/dolt-server.pid/.port). It is not the legacy
gc-managed server, which only an existing city reaches.
Why
Two programs managing one Dolt process was a steady source of lifecycle bugs.
For example, bd cannot see a server Gas City started, so bd's own commands
could start a second server over the same data, or migrate a store under a
running server (#1374, and the hazard migrate-proxied fences below). With
bd owning the process, there is one owner for start, stop, backup and
migration, and gc reaches the store only through bd.
Migrating an existing city
Existing cities are not migrated automatically. A city initialised before
v1.5.0 keeps its gc-managed Dolt server and keeps working on v1.5.0.
gc beads city migrate-proxied moves it to bd's proxied topology. It runs
bd's own bd migrate from-server-to-proxied-server on each scope, city first,
and handles the gc-side residue bd cannot see. There is no reverse
migration, so take a backup first.
Before you start:
- Upgrade bd to v1.3.1 (
bd version), and upgrade gc to v1.5.0. - Stop the city:
gc stop <city-dir>. This is required. bd cannot see a
server gc started, and migrating under a live one commits the mode flip and
leaves the scope unusable until that server dies. The command refuses while
gc's server state, Dolt store lock or Dolt port is still live, and
--dry-runrefuses too, so stop first.gc stopalso unregisters the city
from the supervisor, so name the city by its directory until
gc start <city-dir>registers it again. - Back up the stopped city's stores: copy
<city-dir>/.beads(it holds
the shared Dolt data dir,<city-dir>/.beads/dolt) and every rig's.beads
directory, for example withtar.
Run it from the city directory (or add --city <city-dir> to the
gc beads and gc doctor commands):
gc stop <city-dir>
gc beads city migrate-proxied --dry-run # per-scope plan, nothing written
gc beads city migrate-proxied # add --json for scripts
gc start <city-dir>
gc doctor --fix
gc doctor--rig NAME (repeatable) migrates only the named rigs. The city is always
included, because rigs that share its data dir cannot move while it is still
gc-managed. The command prints a per-scope table and exits non-zero if any
scope failed.
Verify it:
pgrep -af 'db-proxy-child|dolt sql-server' # bd's proxy and its Dolt child
cat <city-dir>/.beads/metadata.json # "dolt_mode": "proxied-server"
cat <rig>/.beads/metadata.json # "dolt_data_dir": "../../.beads/dolt" (relative)
gc bd list
gc statusgc start must not start a dolt sql-server of its own or recreate
<city-dir>/.gc/runtime/packs/dolt/dolt-state.json. A migrated city keeps one
proxy for the city and its rigs, so it runs one proxy plus one Dolt server,
where it used to run one Dolt server. Running bd dolt stop inside a migrated
rig stops the city's proxy too.
What it refuses. Every scope it will not touch is refused by name:
- a scope that tracks an external Dolt endpoint (
gc.endpoint_originexternal
or a pinneddolt.host): leave it external, or move it with
gc beads city use-managedfirst; - an embedded Dolt scope or a DoltLite scope, which have no server to migrate;
- a scope already handed to bd by the ownership handoff, or one recorded in
.gc/scope-ownership.json(a store that was created proxied); - a rig with both its own Dolt store and a database in the city's data dir,
a rig gc cannot place, and a city data dir that holds other databases but
not the city's own; - a city whose beads provider is not bd.
An already-proxied scope reports already-migrated and is skipped, so the
command is safe to rerun.
If it fails:
- One scope failed and the rest succeeded. Completed scopes stay migrated.
Fix what the message names and rerun the command. Rigs that share the city's
data dir are skipped, not attempted, when the city's own turn fails. - bd died mid-migration. Rerun the command. It resumes bd's interrupted
migration from bd's journal (.beads/dolt-mode-migration.json). - The migration committed but bd cannot open the store. A legacy server
is almost always still running. Rungc stop <city-dir>, thenbd pingin
the scope. gc doctorreportsdolt runtime state unavailable. A stale
dolt.mode: serverinconfig.yamlis shadowingmetadata.json. Rerun
gc beads city migrate-proxiedto rewrite it.- Going back. There is no reverse migration. Restore the backup.
The full procedure is in the
migration runbook.
Highlights
- New cities hand their Dolt process to bd (#6273). Gas City no longer
starts a Dolt server for a new city or rig. Existing cities keep gc-managed
Dolt until you rungc beads city migrate-proxied. See
The Dolt ownership change. - Preview: an opt-in SQLite ledger for infrastructure beads, with
130–250× faster infrastructure reads (#5070, #5071). New in v1.5.0. A
city can move its execution graph, sessions, messaging, orders and nudge
queue off the work ledger onto a dedicated SQLite bead engine. On a
production-scale city that measured 130–250× lower latency for
infrastructure-class reads. It is off by default and experimental in this
release; see
Preview: the SQLite infrastructure ledger. - Maintenance works on every topology (#6751).
reaper,jsonl-export
andmol-dog-backupnow reach the city and every rig throughgc bd, so
bd-owned proxied, gc-managed and mixed cities are all reaped, archived and
backed up. A new typedorder.skippedevent reports any work an order could
not do. gc doctorno longer starts a stopped store, and it checks backup
coverage (#6817, #6814). Running doctor on a stopped city leaves it
stopped. The newproxied-backup-coveragecheck asks bd whether each live
proxied scope has a recent backup.- Sessions and pools are harder to break. Claim and close now use the
same identity, and pool workers are named<template>-<beadID>again. The
orphan sweep, the corpse cleaner andgc session killno longer kill or
close live or resumable sessions. Claude's workspace-trust dialog is
confirmed in a closed loop. - The Dolt compactor protects adopted and shared history (#5958, #6554).
It never flattens a database that has a remote, and it only squashes
commits after a first-sightgc-compact-basetag. - The Gas City pack binds as
gc(#4508, #6683).gc initwrites
[imports.gc], andgc doctor --fixoffers to rename an existing
[imports.gascity].
Preview: the SQLite infrastructure ledger
A pre-release feature, opt-in only, and new in v1.5.0. A city with no
[storage] section in city.toml is untouched by it: nothing is resolved,
opened or migrated.
Every city stores six classes of state. The work ledger holds what people
and agents reason about: tasks, epics, bugs and convoys. The other five are
infrastructure: the execution graph, session lifecycle, messaging, orders
and the nudge queue. By default all six share the work ledger. A [storage]
split keeps work where it is and moves the five infrastructure classes to a
dedicated SQLite bead engine under .gc/store.
On a production-scale city, infrastructure-class reads measured 130–250×
lower latency from the SQLite ledger than from the work ledger, because the
controller's constant session, graph and nudge traffic stops competing with
the work ledger's own load (#5071). Closed session beads in the SQLite ledger
are pruned after GC_INFRA_SESSION_PURGE_AGE (default 72h) once wisp_ttl is
set (#6689), so the ledger stays small.
It is experimental in this release. Try it on a new or throwaway
city, not on a production city. The
split storage runbook
describes the configuration.
Upgrading Notes
-
Upgrade Beads (
bd) to v1.3.1 before you upgrade a city. v1.5.0 pins
and tests against bd v1.3.1, in bothdeps.envBD_VERSIONand the go.mod
library. v1.3.1 is a stable release and keeps bd v1.3.0's schema. To get
it, runbrew install beads(orbrew upgrade beads), download it from the
v1.3.1 release assets,
or rungo install github.com/steveyegge/beads/cmd/bd@v1.3.1. A city that
stays on bd v1.3.0 keeps working through the bd CLI, with two losses:- gc refuses that bd for its native store, because it is older than the
linked library; mol-dog-backup's proxiedbd backupand thereaper's closed-wisp
bd purgeare reported as skipped every run.
Read beads'
v1.3.1 upgrade notes
before you upgrade scripts that call bd directly. Do not move a city to a
newer bd until a gc release pins it. - gc refuses that bd for its native store, because it is older than the
-
New cities default to a bd-owned proxied Dolt store; existing cities are
not converted (#6273). Only a scope with no persisted Beads identity gets
the new default, fromgc initorgc rig add. A scope that already has a
server, embedded, DoltLite or external binding keeps its lifecycle. See
The Dolt ownership change for the escape hatch
and for migrating an existing city. -
New cities import the Gas City pack as
[imports.gc]; rename the key on
existing cities before moving past pack 0.1.6 (#4508, #6683).
gc init(the default, or--template gascity) used to write
[imports.gascity]. The pack's skill is nowgc.mayorinstead of
gascity.mayor. Existing cities are not rewritten and keep working at the
pinned 0.1.6. Newer Gas City pack role prompts rungc gc claim, which
fails under the old key.gc doctor --fixrenames the key in place and
leavespacks.lockunchanged. Do not add a secondgcimport next to the
old key, because that imports the pack twice. -
The
reaper,jsonl-exportand doltmol-dog-backuporders now run
throughgc bdon every topology (#6751). Each bead scope (the city and
every rig) is reached withgc bd, and the orders no longer dial Dolt
themselves. Both orders run with a 900s timeout.- Unbound databases are no longer maintained. A database on a
gc-managed Dolt server that no city or rig binds is no longer reaped,
exported or backed up. Drop orphaned databases, or bind them to a rig. - The JSONL archive switches to
bd exportformat. Each line holds one
issue, with its labels, dependencies and comments, and the file restores
withbd import <file>. On its first run, the order moves each database's
old{"rows":[...]}snapshot files into<db>/legacy/withgit mv.
Nothing is deleted. - Backups use
bd backup. When a scope has no backup destination,
mol-dog-backupregisters<city>/.dolt-backup/<db>as its destination,
then runsbd backup sync. The reaper's session-prune backup gate reads
bd backup status. A bd older than v1.3.1 refuses backup on proxied
scopes. Those scopes are reported as skipped, and their session-bead
prune waits for a backup it can see. - Closed-wisp purge uses
bd purge --wisps-planein bounded batches.
A backlog is cleared across runs withinGC_REAPER_PURGE_BUDGET_SECS
(default 300s). A run that uses upGC_REAPER_RUN_BUDGET_SECS(default
780s) reports a partial outcome, and the next run continues.
- Unbound databases are no longer maintained. A database on a
-
Treat
gc storage migrateas experimental. The command is new in
v1.5.0 and still has open correctness issues on split cities (#5987,
#6015, #5974, #6129, #6242, #6348). Rungc storage preflightfirst, back
up every store involved, and do not migrate a production city you cannot
restore. -
Run
gc doctorafter upgrading a city whose beads store gc does not own
(#6495). On start, gc registers its required bead types (including the
newstartup-health-episode) for gc-managed and provider-owned stores. It
never writes to external Dolt servers, complete storage bindings, hosted
gateways or legacy proxied opt-in scopes. On those, rungc doctor, and if
custom-typesfails, rungc doctor --fix. -
Unaliased pool and ephemeral sessions now act as their session bead id
(#5716).GC_AGENTandBEADS_ACTOR(and the event actor and telemetry
gc.agent) are now the session bead id instead of the session name.
Restart running sessions to pick this up. Whengc hook --claimadopts a
bead still held under the old spelling, it re-stamps it. If that re-stamp
fails, it prints the exactbd update <id> --if-assignee <old> --if-status in_progress --assignee <new>recovery command. -
A failed pool start can now stall its slot instead of leaking a runtime
(#6549). When a pool worker fails to start, gc stops its runtime before
the slot retries. If that stop fails, the slot stalls and logs
holding pool session <id> openinstead of starting another box. Open
pool rows created by an RC or main build with the namesclaudeor
claude-N-poolkeep those names until they close. -
The Dolt compactor never flattens a database that has a Dolt remote
(#5958). Such databases (including bdrefs/dolt/dataand backup-only
file://remotes) get a bareCALL DOLT_GC(), so their history grows. A
leftovercompact-pending-pushmarker is held for review instead of being
pushed.- First-sight tag. The first time the compactor sees a database, it
tags itgc-compact-base. The tag goes at the root if the database was
already flattened or is marked.compact-full-history, and at HEAD
otherwise. Only commits after the tag are squashed. - Flattening on purpose. Announce a window to every clone, then run
GC_DOLT_COMPACT_ALLOW_FEDERATED=1 gc dolt compact --only-db <db>. - After a rollback. If you roll a database back to before its tag,
compaction fails with instructions until you delete the tag:
CALL DOLT_TAG('-d', 'gc-compact-base').
- First-sight tag. The first time the compactor sees a database, it
-
secrets.envkeys must be shell identifiers (#5982, #6022). Any other
key (optionally afterexport) is rejected asline N: invalid key. An
unclosed quote skips through its closing line as one block, reported by key
and line range. The rest of the file still applies. Check the supervisor's
stderr aftergc startfor skipped lines. -
Child processes now see
BD_BIN=(empty) when no bd pin is configured
(#6550). Previously they inherited the ambient value. A relative or
non-executable ambientBD_BINis ignored with a warning. ABD_BINpinned
inworkspace.envstill fails closed. -
Formula steps and the agent-script
notes:key now append to work-bead
notes (#6412). They runbd update --append-notesinstead of replacing
the notes. A retried step can append the same text twice. -
A retry step's own counter moved to
gc.retry_attempt(#6548). Inside
a ralph or review loop,gc.attemptagain names the loop iteration on
every bead of the iteration body, as in v1.4.2.gc.retry_attemptcounts a
step's retries from 1 in each iteration. Packs that readgc.attemptas a
retry counter should readgc.retry_attemptand fall back togc.attempt.
Beads created before the upgrade have nogc.retry_attempt. -
Publishing a pack under a bare (unscoped) name now requires
--allow-unscoped-name(#5394). Registry names are<github-owner>/<pack>.
New packs must set[pack].name = "<github-owner>/<pack>"inpack.toml.
--namecan only restate the name thatpack.tomlalready declares. -
gc bd new --metadata @file.jsonnow exits 1.gc bdchecks
rig-qualified metadata before it writes, and it cannot read that metadata
from a file. Pass the JSON inline, for example
--metadata '{"routed_to": "rig/agent"}'. -
Main and nightly builds only: the seat-claim and named-seat execution
backstops were removed (#6524). Named always-on seats again have no
controller claim or execution backstop. An agent must claim its work at
startup or be nudged. The pool-slot backstop stays, without #6287's
changes. Theexecution.claim_stalledevent type is gone.
Added
- An
order.skippedevent reports work an exec order could not do
(#6751). An order can exit 0 and still miss part of its work, for example
when a bead scope is unreachable or a safety gate holds a step back. The
controller now records a typedorder.skippedevent next to
order.completed. The event carries the outcome (skippedorpartial)
and the scopes that did not run, andgc order runprints the same
declaration. gc doctorchecks proxied backup coverage (#6814). For each live
proxied scope,proxied-backup-coveragerunsbd backup status. It warns,
at advisory severity, when a scope has no backup destination, has never
synced, or has not synced in 24 hours. The fix hint is
gc order run mol-dog-backup. It never asks bd about a stopped scope.gc doctorcatches proxied stores pulled into bd's host-wide shared
server (#6697). Theproxied-shared-servercheck reports and fixes
gc-owned scopes that are unpinned or bound to bd's shared server.gc doctoroffers to rebind the Gas City pack import asgc(#6683).
Thegascity-pack-bindingcheck warns when a city imports the public Gas
City pack under another key, andgc doctor --fixrenames the key to
[imports.gc]. The fix refuses, and explains why, in three cases:gcis
already bound to a different pack, the pack is imported twice with
different settings, orpack.tomlorcity.tomlstill reference
gascity.-qualified names.gc beads city migrate-proxiedmoves a legacy gc-managed city onto
bd's proxied-server topology (#6273).--dry-runprints the per-scope
plan, and--jsonoutput has a schema. See
Migrating an existing city.gc storage preflightreports everything the infra-class cutover would
refuse, from outside the migration window (#5597). It runs the same
checks asgc storage migrate --from-workagainst a live city, and it
copies nothing, takes no guard, and publishes no event.- Storage-binding events say more (#5597).
storage.binding.not_configured
makes "this city has no split" a visible verdict. Every
storage.binding.*event now carriesproven_beads, the size of the
proven-copy manifest behind a serving verdict.
Changed
- Closed session beads in a SQLite infra ledger are purged after
GC_INFRA_SESSION_PURGE_AGE(default 72h) (#6689). This applies only
when a city relocates sessions to a SQLite infra ledger andwisp_ttlis
greater than zero. An invalid value logs one warning and falls back to 72h.
A named session closed for more than 3 days loses its bead and reopens
fresh. The Dolt reaper keepsGC_REAPER_SESSION_PURGE_AGE(default 720h). gc pack registry publishchecks the pack name locally before it sends
anything (#5394). An unscoped name, or a scope that is not the lowercased
GitHub owner of the source repository, is refused with the exact
[pack].nameedit that fixes it. Before, such a request was parked in the
review queue as a pending row that could never be approved.gc bdon a split city decides ownership by where a bead lives, not by
its id prefix (#5634). A reserved-prefix id that the class binding does
not hold now falls through to the work ledger instead of being refused.
That includescreate --depsand--parent. A binding that cannot answer
is still a hard error and is never read as an absence.gc bd newgets the same--metadatavalidation ascreateand
update.modelandeffortpins are open options for every provider (#5658).
Before, a model id the builtin catalog did not know produced no--model
flag at all, so the agent silently ran on the CLI's default. Any value is
now rendered through the option's flag template, and the provider CLI
accepts or rejects it. grok gainedgrok-4.6andgrok-4.7. codex accepts
effort = "max", and antigravity accepts"xhigh"and"max". cursor
gained a model option. A pin that still cannot be honored prints a loud
startup warning naming the agent, the value, and the valid set.- Due condition-triggered orders now fire on the tick that sees them,
outside the per-tick dispatch budget (#5990). Before, cooldown sweeps
could use uporders.max_dispatches_per_tickon every tick, and one merge
queue went 11 hours without a dispatch. Cooldown, cron and event orders
keep the budget. A tick that spends its budget logs one line naming the
orders it did not reach. gc statusno longer scans the whole event log to showLast GC:
(#4418). The lookup reads back a bounded 8 MiB of the active
events.jsonlonly, so on a busy city the field may be absent even though
maintenance has run. For durable history, query the event log for
store.maintenance.*.
Fixed
Beads, Dolt and maintenance
gc doctornever starts a stopped proxied store (#6817). On a stopped
bd-owned proxied city, a fullgc doctororgc doctor --fixused to
start a proxy and adolt sql-serverthat never exited. Doctor now asks
gc's own endpoint inspection whether a scope is running, without calling
bd or dialing. If a scope is stopped, its store-reading checks keep their
names and reportnot checked: store not running. That result is OK on a
stopped city, and a warning with a fix hint if the controller is up.
Checks that do not read the store run unchanged.gc initworks again below a directory that holds a bd workspace
(#6701). Creating a city, or agc rig addrig that is not a git repo,
under a beads repo or a home with~/.beadsused to fail with
workspace already initialized as database "ws00". gc now pins bd to the
new scope's own.beadsbeforebd init.- gc-owned proxied stores no longer move into bd's host-wide shared server
(#6697). When the user-level bd config setdolt.shared-server: true,
gc-owned proxied stores were silently moved into
~/.beads/shared-server, which could merge two cities'hqdatabases. gc
now pins the mode off for every bd it spawns, for agent sessions, and in
each gc-owned scope's.beads/config.yaml. Beads that a scope wrote while
bound to the shared server stay there and are not migrated, and
gc doctorwarns while that database exists. gc bd show --watchworks on proxied cities (#6681). bd v1.3.0 refuses
watch mode under the proxied transport. gc now serves
gc bd show <id> --watch(alsoviewand--current) itself: it polls
the bead every 2 seconds and redraws it when it changes.- gc reads bd 1.3.1's nested config keys (#6814). bd 1.3.1 writes
dolt.host,dolt.portanddolt.modein nested YAML form. gc read only
the flat form, so its repair paths on direct and external scopes failed
closed. gc's readers, the bd and dolt pack scripts, and the dashboard
sampler now read both forms, flat first, and the canonical config writer
leaves one value per key. - The reaper's stale-issue auto-close works again when an open bead
depends on a wisp or external bead (#6751). A NULL in that dependency
emptied the exclusion list, so no stale issue in the store was ever closed. - The Dolt compactor no longer rewrites adopted or shared history
(#5958, #6554). The default-onmol-dog-compactorflattened any managed
database over 2000 commits back to its root, and if the database had a
remote, it force-pushed the result. See the Upgrading Notes and "History
protection" indocs/troubleshooting/dolt-bloat-recovery.md. - Native Dolt metadata writes no longer silently undo concurrent updates
(#6222, #6221, #6233).SetMetadataandSetMetadataBatchnow
compare-and-swap on the row version. Under sustained contention they
return an error wrappingbeads.ErrVersionMismatchinstead of overwriting
the other writer. Route recovery now skips fenced beads and sets
gc.routed_towith a key-level compare-and-set. Readyon a remote native Dolt store is fast again (#6491, #6497). A
pre-release regression made controller ticks take minutes. The blocker
check is now one batched read.- Upgraded cities register
startup-health-episodeagain, so crash-loop
protection works (#6495, #6557). gc now merges its required types into
both bd's config row and itscustom_typestable without removing custom
types.gc doctor --fixkeeps types that exist only in the table. - Managed Dolt is no longer killed about 15 seconds after the session that
restarted it closes (#6316, #6546). Managed Dolt and the detached
supervisor no longer inherit session identity, and the orphan sweep skips
city infrastructure. - A nudge no longer closes the shared store on a city that relocates the
nudgesclass (#5979, #5980). Before, every later class read failed with
sqlite store: bead store closeduntil restart. One outage lasted 7.6
hours. - The stale-issue reaper no longer closes active Slack room groups (#6380,
#6385). - Wisp GC now reaps closed, rootless, leaf plain-task wisps (#3780,
#4927). Before, they piled up in the wisp tier forever. - The dolt pack's
run_boundedpython3 fallback sends SIGTERM before
SIGKILL (#4823, #4875). On stock macOS, a SIGKILL during
dolt backup synccould leave a backup archive permanently unreferenced. gc bdadds a corrective hint when bd suggestsbd dolt startagainst
a gc-managed endpoint (#1374, #4898). The hint points atgc startor
gc dolt restart. Following bd's suggestion would start a second,
unmanaged Dolt server.
Sessions, pools and runtimes
- Claude sessions in untrusted directories start again (#6531, #5796,
#6121, #6547). Current Claude Code builds put the cursor on "No, exit",
and v1.4.2 confirmed that choice with a bare Enter. gc now moves the
cursor and presses Enter only after two consecutive frames show
"Yes, I trust this folder". If it cannot get there, it leaves the dialog
up and warns. - Unaliased pool workers no longer loop on claim and close (#5716, #6324,
#6597, #6632, #6640). Claim, close and the runtime actor now agree on the
session bead id. - Unaliased pool workers are named
<template>-<beadID>again (#6549).
The Kubernetes pod-leak fix is kept: a failed create stops its runtime
before its bead closes. - Session-bead cleanup no longer stops a running session (#6596).
- The orphan sweep no longer kills a live worker after one transient read
(#6649). A kill now needs the store and the tick's session snapshot to
agree.BdStore.Getreports not-found only for real bead-level misses. - A new pool worker that holds a live claim is no longer drained as
orphaned (#6665, #6666). - The controller no longer crashes on a tmux state-cache race (#6735).
- A pending create whose command drifted no longer holds its alias forever
(#6744). The row is rolled back asfailed-createand recreated.
gc session resetrolls back a stuck create, and--jsonreports
mode: restart|rollback. - A codex prompt swallowed during a large paste is submitted again
(#6739). gc re-sends the submit at most 8 times, only while the staged
draft is still visible and the pane is idle. It never sends into an
attached session. gc session killno longer races the reconciler (#6749). While a fresh
kill-pending marker exists, the reconciler and the corpse cleaner leave the
row alone, and attach and send return HTTP 409.- Killed and dormant sessions are no longer closed as
dead-runtime
(#6752). - A
lifecycle=one_shotpool session that exits cleanly no longer blocks
its own runtime name (#5594). Rig-scoped one_shot retry attempts also
keep their rig qualifier and drop stale session pinning (#5609). - A named session no longer replays a trigger stamp for a work bead that
was parked (#4373, #5033). - Secret session metadata no longer appears in process argv (#6537). On
tmux, secret values go through a private 0600 command file. On ssh, they
are staged over stdin. If staging fails, the write is refused. - A single bad line in
secrets.envno longer drops every credential
(#5982, #6022, #6043). - A stale or relative ambient
BD_BINno longer takes everygc bd
offline (#6550). - ACP activity is visible across process boundaries (#4612). This
enables timed idle policies and the opt-inprogress_stall_timeoutfor
ACP sessions. gc initprovider readiness finds Nix-installed CLIs (#3962, #4926).
Formulas, orders and workflows
- Retries inside ralph and review loops get the right attempt numbers and
a full retry budget in every iteration (#6548). The new
{retry_attempt}placeholder names a step's own retry. In-flight
molecules keep working across the upgrade. - Retry attempts that pass no longer abort their scope or fail their
workflow (#6534). - Formula steps no longer erase notes on the work bead (#6412).
GET /runs/{id}/stepsreturns steps in pipeline order (#4699, #4876).- The dashboard's dependency graph keeps the relation type on inverse
edges (#4365, #5032). gc doctor'sorder-firing-currentcheck reports a lookup timeout as
advisory, not blocking (#4895, #4946).
Split storage (class bindings)
- The one-live-workflow-per-source-bead guard reads the graph binding
(#5993). Before, a split city admitted a second live workflow for the
same source bead. A closed binding row also supersedes its retained frozen
twin, so a converged city no longer refuses a valid sling (#6312). - The work-record close gate asks the repository that the bead's owner
points at (#6138). It also resolvesgc.work_branchagainst its
remote-tracking ref (#5037, #5055). - The infra-class cutover carries dependency-edge payloads (#5597). This
does not repair a city that already cut over. See Known Issues. gc workflow delete-sourceandreopen-sourcewrite the copy that the
residency contract owns (#5992).- A control bead served by a class binding is routed to the dispatcher its
gc.root_store_refnames (#5918). This fixes #5547 and #5587.
CLI, packs and docs
gc import addof a local in-git pack locks to HEAD, not the repo's
latest tag (#3659, #4925).- Mail archive and delete expand whitespace-joined message IDs (#4923).
gc stop --helpandgc stop --jsonsay that stopping a
supervisor-managed city unregisters it (#4366, #4899).gc formula cook --attachhelp describes theblocksrelationship it
actually creates (#2392, #4900).- The workspace-identity deprecation warning cautions that following it
can break packs pinned to an older revision (#3887, #4947). - The tutorials and quickstart show
[imports.gc](#6676). check-core-boundary.shscans tracked files only (#4479, #4877).
Known Issues
gc import add --version <semver>fails for registry packs. gc
resolves a semver against git tags, and gascity-packs has no per-pack tags.
So the "Exactly this version" command printed bygc pack registry show
fails, for example for Gas City pack 0.1.6 and the new 0.1.1 releases. Until
a v1.5.x patch release fixes it, pin by commit: rungc pack registry show <pack>, then
gc import add <source> --version sha:<commit>with that release's commit.gc storage migratehas open correctness issues on split cities
(#5987, #6015, #5974, #6129, #6242, #6348). See the Upgrading Notes.- A split city that cut over before this release still has payloadless
dependency edges in its binding. No command detects or repairs them yet.
See "If this city cut over before edge payloads were carried" in
docs/runbooks/split-storage-classes.md. - A hot session bead can briefly be marked awake or draining with no
runtime. Two reconciler writes ignore their error after stopping a
runtime. With the metadata compare-and-swap (#6233), this happens more
often, and a later tick repairs it. gc startcan time out probing Dolt on a heavily loaded host. The
Dolt identity probe at startup allows 2 seconds and stopsgc startwith
"dolt config probe timed out after 2s" if the host cannot answer in time.
It was seen once during RC validation, at load around 130. Re-run
gc startonce the host is less busy.
Troubleshooting (upgrading to v1.5.0)
Upgrade bd first (bd version should report 1.3.1). Then run this once per
existing city:
gc doctor --fix
| Symptom | Cause | Fix |
|---|---|---|
Every reaper / mol-dog-backup run fires order.skipped (bd-purge-unsupported, or backup refused on a proxied scope)
| bd is older than v1.3.1 | brew upgrade beads, or install bd v1.3.1 from its release assets
|
gc doctor reports store checks as not checked: store not running
| The city or rig is stopped. Doctor no longer wakes it (#6817) | Expected on a stopped city. gc start, then rerun gc doctor
|
proxied-backup-coverage warns on a fresh proxied city
| No mol-dog-backup run has registered a destination and synced yet
| gc order run mol-dog-backup, or wait for the order
|
Role workers fail with gc: unknown command "gc" after bumping the Gas City pack past 0.1.6
| The city still imports the pack as [imports.gascity]
| gc doctor --fix (the gascity-pack-binding check)
|
gc import add ... --version 0.1.1 fails for a registry pack
| Known issue: no per-pack git tags | --version sha:<commit>, using the commit from gc pack registry show <pack>
|
invalid issue type: startup-health-episode, or custom-types fails on an external or hosted store
| gc does not write stores it does not own | gc doctor --fix
|
proxied-shared-server warns
| A gc-owned scope is unpinned or was bound to ~/.beads/shared-server
| gc doctor --fix. Beads written to the shared server stay there
|
Old JSONL archive files are gone from <db>/
| First run of the new bd export format
| They were moved, not deleted: look in <db>/legacy/
|
| A database on the gc-managed server is no longer reaped, exported or backed up | No city or rig binds it | Bind it to a rig, or drop it |
gc dolt compact fails after a database rollback
| The database is behind its gc-compact-base tag
| CALL DOLT_TAG('-d', 'gc-compact-base')
|
A pool slot logs holding pool session <id> open
| gc could not stop a failed start's runtime | Stop the runtime by hand; the slot then retries |
Lines are skipped from secrets.env
| The key is not a shell identifier, or a quote is unclosed | Fix the reported line or key range |
Validation
- RC Gate 8 passed on the v1.5.0-rc1 commit with no reruns. Run
36817987389onrelease/v1.5.0at5cc547ede3: 151 jobs succeeded and
0 failed. 3 jobs were skipped, as in every RC Gate, because the gate runs
its own integration tier. The run covered:- CI parity, including Beads topology acceptance on bd 1.3.1
(TestBeadsProxiedDefault14/14, the shared-server test, and the init
topology matrix); - proxied-native acceptance, contracts, and the Windows process tree;
- Ubuntu acceptance A, B and C 1–5 with real inference;
- all 29 Ubuntu integration shards and tutorial goldens 1–6;
- every macOS regression job;
- the goreleaser snapshot.
- CI parity, including Beads topology acceptance on bd 1.3.1
- gascity-packs inference suites ran against the RC. These runs used RC
heade0cb0c5e4fwith bd v1.3.1-rc.2 and gascity-packs390cac1, on a
Claude pool at medium effort. The tagged head adds only a test-fixture fix
and the promotion of bd rc.2 to v1.3.1, which has no code change, so the
suites were not rerun.- Passed on the first try: superpowers-all, compound-all and bmad-all.
- Also passed: gastown-all and all 5 pack smokes.
- gstack-all did not pass, and gstack was accepted on evidence. The
first attempt failed atgc starton a heavily loaded host, before any
inference. The retry hit its 9000s build deadline while the model was
still iterating in release readiness. Every closed step had passed, and
every artifact it produced validated. The release owner accepted gstack
on that evidence. - Maintenance orders and doctor were checked on a proxied fixture.
reaper,jsonl-exportandmol-dog-backupexited 0 on a proxied city
plus a rig, with no direct Dolt access.gc doctorleft the stopped
city stopped.
- Pack releases are locked in. gstack, compound-engineering, bmad and
superpowers 0.1.1 are published in the gascity-packs registry at390cac1. - Beads v1.3.1 is a stable release. It is tag
v1.3.1on
c1c4b642ac1c. Its code is identical to v1.3.1-rc.2, and Homebrew core
beadsis 1.3.1. - The stable tag differs from v1.5.0-rc1 only by the CHANGELOG commit.
v1.5.0(f66474617d) isv1.5.0-rc1(5cc547ede3) plus
chore: release v1.5.0(#7043), which moves[Unreleased]to[1.5.0]in
CHANGELOG.mdand touches no other file.
Install
Upgrade bd to v1.3.1 first (see the Upgrading Notes), then install or upgrade
Gas City with Homebrew:
brew update
brew install gascity # new install
brew upgrade gascity # existing install
gc version # 1.5.0brew install gascity resolves to the homebrew-core formula, which picks up
v1.5.0 through Homebrew's automatic version bump, usually within a few hours of
the release. Until brew info gascity shows 1.5.0, use the
gastownhall/gascity tap formula (brew install gastownhall/gascity/gascity),
which already installs v1.5.0, or download the archive below.
Or download the archive for your platform (linux or darwin, amd64 or
arm64) from this release and verify it:
gh release download v1.5.0 -R gastownhall/gascity \
-p 'gascity_1.5.0_linux_amd64.tar.gz' \
-p 'gascity_1.5.0_checksums.txt'
sha256sum --ignore-missing -c gascity_1.5.0_checksums.txt # macOS: shasum -a 256 --ignore-missing -c
tar -xzf gascity_1.5.0_linux_amd64.tar.gz gc
./gc versionThen let gc start restart the supervisor on the new binary. The release
archives carry GitHub artifact attestations and an SPDX SBOM
(gh attestation verify <archive> -R gastownhall/gascity). To build from
source, check out the v1.5.0 tag and run make install.
Contributors
Thanks to everyone who contributed to v1.5.0 (between v1.4.2 and
v1.5.0):
@24601, @A3Ackerman, @AJBcoding, @AlexBelous, @allenday, @amir-rezaei,
@aphexcx, @atbrace, @austinborn, @aytheo-bit, @boshu2, @bourgois,
@brandonmartin, @caseymatt, @chris-sanders, @ckumar1, @cmc-veup,
@csauer02-personal-user, @csells, @dlarsen5, @donnabox, @duncan4123,
@edwarddavison, @elmpp, @eudaimos, @figgeous, @GEMISIS, @graham-a11y,
@haddad-daniel, @hexsprite, @iwata-1116, @jacobhausler, @jamelt, @jeffora,
@jm2, @johnzook, @julianknutsen, @justakeyboardbetweenus, @kaushikNaarayan,
@loucmane, @m-u-xyz, @masonjames, @McKean, @mike-reese, @mk-imagine,
@pranaypratyush, @pzxy, @quad341, @rbriski, @remuscazacu, @rjgeng, @Rome-1,
@sarendipitee, @shahshrey, @sjarmak, @swedeinasia-flow, @tdupu,
@TheChrisOneil, @Toady00, @tobasummandal, @tudorsaitoc, @vbtcl,
@vishnujayvel, @wbern, @wonkothesanest, @wynged
New Contributors
- @justakeyboardbetweenus made their first contribution in #3693
- @kaushikNaarayan made their first contribution in #4514
- @eudaimos made their first contribution in #4570
- @GEMISIS made their first contribution in #4588
- @amir-rezaei made their first contribution in #4593
- @figgeous made their first contribution in #4693
- @chris-sanders made their first contribution in #4716
- @vishnujayvel made their first contribution in #4792
- @24601 made their first contribution in #4838
- @tdupu made their first contribution in #4865
- @wonkothesanest made their first contribution in #4893
- @edwarddavison made their first contribution in #4913
- @loucmane made their first contribution in #4944
- @masonjames made their first contribution in #4983
- @rbriski made their first contribution in #4984
- @haddad-daniel made their first contribution in #5031
- @Toady00 made their first contribution in #5154
- @tobasummandal made their first contribution in #5200
- @pranaypratyush made their first contribution in #5227
- @caseymatt made their first contribution in #5283
- @shahshrey made their first contribution in #5369
- @aphexcx made their first contribution in #5417
- @jamelt made their first contribution in #5474
- @aytheo-bit made their first contribution in #5516
- @pzxy made their first contribution in #5538
- @allenday made their first contribution in #5657
- @AlexBelous made their first contribution in #5777
- @dlarsen5 made their first contribution in #5905
- @TheChrisOneil made their first contribution in #5924
- @ckumar1 made their first contribution in #6233
- @graham-a11y made their first contribution in #6412
Recommended Reading
- Installation guide
- Troubleshooting guide
- Migrating a legacy gc-managed city to proxied-server
- Dolt bloat recovery and history protection
- Split storage classes runbook
- Understanding packs
- CLI reference
- Config reference
- Beads v1.3.1 upgrade notes
Full Changelog: v1.4.2...v1.5.0