Repository navigation
anthrex 0.3.0
Pre-releaseThe protocol version is now 26 (22 for milestone 9.13's OrchestratorInfo.untrusted,
23 for milestone 9.14's build admission, 24 for milestone 9.15's lessons, 25 for
milestone 9.16's brakes: RunRequest::Hold, RunReply::Held, RunsSnapshot.brakes,
RunInfo.handoff, a routing decision's failover, the settings document's brakes;
26 for milestone 9.17's plan and review quality: a finding's target, the brief
task note kind, RunInfo.plan_frame, PlannerInfo.frame, TaskInfo.replaces and
replaced_by, add_task's replaces, a task record's replaces and
brief_findings, and HistoryStats.replaced): a client needs a daemon of the same
release. Stop the old daemon (anthrex daemon stop) after upgrading.
Downgrading. run.json is now format 7 (milestone 9.15: a run's frozen lessons,
its discard reason, a task's lessons shown and risk note, and the distill and
risk-note ops; milestone 9.16: a run's failovers and its context handoff; milestone
9.17: a run's plan frames, an epic's frame, the approved spec's Non-goals, a task's
replaces, a finding's target and the brief notes; milestone 9.19: each design
agent's raw token usage). A 0.2.0 daemon skips a run
this release wrote (run format 7; this one reads up to 1) and
leaves it as it is, as does any daemon that reads an older format. The hold lives in
brakes.json in the data directory, which older releases ignore: an older daemon
does not hold dispatch. Releases before
0.2.0 have no such guard and can drop this release's new run fields when they save
(the untrusted-read record, the orchestrator's retry count, the pinned gate files, a
pending override proposal and an override count's protected list): finish or discard
your runs before downgrading below 0.2.0.
Added
-
Reviewers see what the run is for (milestone 9.17). Every reviewer prompt now
has the run goal as its second line (Run goal: …, the same line the worker gets),
and, before the brief, the plan's out-of-scope list (Out of scope for this run …)
or, in a design-flow run, the approved spec's Non-goals. -
brieffindings. A reviewer that thinks the brief itself is wrong (wrong for the
goal, out of scope, or missing something the goal needs) files a finding with
target: brief. It never sends the worker back and never blocks the merge; it
becomes abrieftask note that wakes the orchestrator (t1's reviewer says the brief is wrong: …). A run without an orchestrator, such as a plan file, shows it to
you as a sticky attention line inanthrex run status(t1: the reviewer says the brief is wrong (1 notes); read them in the task's notes). The inspector, the report
((brief, from the reviewer)) and history (brief_findings) show them apart from
the code findings. -
Decided for you · Out of scope. The orchestrator's plan submit, and each
sub-planner'ssubmit_epic, now carrydecided(each question the goal left open,
with the answer chosen) andout_of_scope(what the run will not do); a submit
without them is refused, with the reason. At the plan gate the review opens on
the frame (frame 2 decided for you · 1 out of scope · f shows them, orframe none statedin the attention colour), andfflips the detail between the frame
and the selected task.anthrex run statusprintsdecided for you: <question> → <answer>andout of scope: <item>after the goal while the plan awaits you, and
the run report has aPlan framesection. Plan files, your ownrun edit --submit
and design-flow runs need no frame. -
replaces. An orchestrator'sadd_taskcan name the cancelled or blocked tasks
it takes over (replaces: ["t1"]); a blocked one is cancelled (cancelled: replaced by t2), andsplit_taskrecords it for its children. The inspector showsreplaces
andreplaced by, the reportcancelled (replaced by t2), and the history record
names what it replaces.anthrex run statsand the TUI's stats page judge the work
by the replacement: replaced records leave the class rows (replaced 1 (judged by their replacements)). -
Shared sequences. The orchestrator's and sub-planners' contracts now say that a
task taking the next number of a shared sequence (a migration number, a version
constant, a registry entry) owns the file that holds it, so two such tasks never run
at once. -
A dispatch hold (milestone 9.16).
C-b H(with a confirm) oranthrex hold on
stops every new agent session daemon-wide; sessions already running finish their
work, are reviewed and merge. The status bar showsHELD, an alert and every
run's attention line say so, and new goals are refused withdispatch is held daemon-wide · anthrex hold off; queued goals wait. The hold survives a daemon
restart (brakes.json, written atomically; a corrupt file holds).C-b Hagain or
anthrex hold offreleases it and says how many queued goals start;anthrex hold statusshows the hold and the quota. -
A subscription quota brake. anthrex reads each CLI's own rate-limit readings,
Claude'srate_limit_eventand thetoken_countlines of Codex's session rollout
under$CODEX_HOME/sessions, with no credentials and no vendor request. While a
runtime's 5-hour window is at 90 % or its 7-day window at 95 %, no new session of
that runtime starts until the window resets; in-flight work still finishes. A
runtime with no recent reading is never braked, and the run log says so once.
[orchestrator.brakes](quota_brake,quota_pause_5h_percent,
quota_pause_7d_percent,quota_fresh_secs) sets it, also from the Settings
screen;anthrex run statusprints the brake lines while something is held. -
Cross-runtime failover. A fresh session whose runtime is braked starts on its
role row's "if it struggles" fallback when that is on the other runtime:claude braked: t2 started on codex (fallback). A reviewer never gets its author's model,
overlapping work never splits runtimes, and the hold stops failover too. A row whose
fallback is on the same runtime waits instead. -
The orchestrator's context handoff. When a goal is continued on a chain whose
orchestrator session is 80 % of its context window or 300,000 tokens full
([orchestrator] handoff_at_percent,handoff_at_tokens,context_window_tokens),
a fresh orchestrator session starts with the summary and recent history, the old
window is renamed<h4>/orchestrator (handed off), and the run's inspector shows
where it came from. A live orchestrator at 90 % gets an attention line. -
Lessons (milestone 9.15). anthrex now learns from its own runs in a repository.
Each failed check or proof records a failure signature on the task's history record,
and a signature seen in two runs within 14 days becomes a known failure. After a
recovered, blocked or blocking-review task, or a failed or discarded run, a
background distiller (one decider call, off the run, at most 20 a day per
repository, on a redacted dossier) proposes lessons: episodic ones go on trial at
once, procedural and semantic ones wait for your approval. A run freezes the active
lessons at its start, and each worker's first turn gets the best few for its files
underNotes from earlier runs in this repository. …, its reviewer the same under
Known pitfalls in this repository; a lesson earns credit when the tasks shown it
merge. A reviewer can also get a short risk note written from the brief alone. The
new[lessons]table turns each part on or off and sizes it. -
anthrex lessons list | approve | reject | forget. List the repository's lessons
with their status, layer andgreen/outcomes(--all,--json), approve or reject
proposed ones, and forget a lesson or dismiss a known failure (y/Nper id unless
--yes). -
The Lessons page and the knowledge graph page. On the Profile screen (
C-b P),
llists the lessons (aapprove,rreject,dforget,tall) and its hint
counts those waiting for review;gthere draws them as a graph of module hubs and
lesson dots, with selection by arrows, an inspect panel, search, zoom and pan. -
A discard reason.
anthrex run discard <run> --reason "<text>", and a reason
field in the TUI's discard form, record why a run was thrown away on its history
record and in its distill dossier. -
Files that run outside the sandbox are protected. CI, git-hook, cargo and
toolchain files join the protected paths:.github/workflows/**,
.github/actions/**,.gitlab-ci.yml,.circleci/**,.buildkite/**,
Jenkinsfile,azure-pipelines.yml,.githooks/**,.husky/**,
.pre-commit-config.yaml,**/.cargo/**(the directory itself too, so a.cargo
committed as a symbolic link is caught),**/rust-toolchainand
**/rust-toolchain.toml(21 built-in paths in all). A task
whose branch changes one without itsownsnaming it exactly is bounced at
task_donewith a line that says why (… runs outside the run's sandbox (CI, git hooks, cargo or toolchain config); this task may change it only if its owns names it exactly). A task whoseownsnames a protected file is noted at the plan gate
(owns names protected <path>; the user approves this grant with the plan). -
The gate's own scripts are pinned. At run start anthrex reads which tracked
files the profile's commands name (check,setup,single_test, the tier
commands;make,just,toxandnoxadd their own files) and protects them.
Before every gate command it compares them in the checkout with the base commit; if
the run changed one, the command never runs and the run halts for you (the gate's script <path> differs from the base commit's; the run changed what measures it).
Only you can resume it. A task may change a gate script when itsownsnames it
exactly and you approve that with the plan. -
An orchestrator retry cap. After the orchestrator has retried one task twice,
that task's next block is yours (· the orchestrator retried it 2 times; the user decides); your ownrun retrygives it its two retries back. -
Untrusted text is tracked. Once the orchestrator has read text from outside the
run (a pull-request comment, or a review or CI fix task's block, note or result),
itsoverrideandaccept_redbecome anorchestrator asksquestion to you (do it/leave it), and itsapprove_holdis refused, for the rest of the run and any
next goal it continues.anthrex run statusprintsuntrusted text read: <source> at <HH:MM>; override, accept_red and approve_hold go to the user, and the run view's
inspector shows anuntrustedrow. A fix task's wake-up no longer carries its
worker's text (read it with run_status).
Changed
- The orchestrator cannot merge or grant protected changes on its own. Its
overrideof a task whose branch changes a protected file the task'sownsdoes
not name is refused and the task's block becomes yours; it cannot approve a hold
whose tasks name a protected file, nor add such a task outside a hold after the plan
gate. Your ownrun overridestill goes through and lists the protected paths it
changes; for a pinned gate script the reply adds that itstays pinned until a task's owns names it (run edit), so the next gate command halts until you add a task whose
ownsnames it. brieffindings leave the code-review counts (milestone 9.17). A history
record'sreviews_rejectedno longer counts a round whose only findings are about
the brief, the orchestrator's digest shows them apart in a task's review text (r1 changes (1 brief)), and an integration review whose findings are all about the
brief approves its epic.- Tokens are billed tokens everywhere, and a run's total counts its design agents
(milestone 9.19). A brainstormer's and a document reviewer's tokens no longer count
cache reads (input, cache writes and output, as every other role's), and the run's
usage now credits them underbrainstormeranddoc_reviewer, so its total covers
every role.history.jsonllines are now written atv6: fromv6 aphase
line's agent tokens are billed tokens and arunline's usage includes the design
roles; the design budget refit takes its token samples fromv6 lines only. A run
designed before the upgrade keeps no split of its design agents' tokens, so its total
leaves them out (an undercount, never a cache-read overcount). The run spend row
readstokens 1.8M (all roles) · cache hits 71% of input · worker tool calls 412
(tokens ≥… (tasks only)from a daemon without run usage),REPORT.mdand the
inspector print tokens as750kand1.2M, andrun statsleaves a merged task with
no recorded tokens out of its token median (-when none are left). - Every number has one meaning, label and format (milestone 9.19), written down in
docs/numbers.md, which?help (anumbersgroup) and the README link to. The
protocol stays 26;run.jsonis format 7 andhistory.jsonllines arev6 (both
from the token change above). - Clock times name their zone. The TUI and the CLI show local time with its offset
(14:30 +02:00,Thu 14:30 +02:00within six days, else the date); text the daemon
writes (attention lines, prompts, the proposal file, theREFITcolumn) stays UTC and
saysUTC. On Linux, a change of the system time zone mid-session is picked up only
after a restart (DST changes are picked up at once). After the upgrade the
orchestrator digest'satvalues read2026-09-21 11:40 UTC, not11:40
(cosmetic: the times are the same). - One duration and one age format:
42s,41m 12s,1h 05m,3d 04h, floored;
just nowunder 10 s, else<duration> ago. Fixed-width cells (the sidebar, graph
boxes, the alerts list) show the largest unit only. - One progress count and one stage position.
3/5 mergedleaves out cancelled,
reported and replaced tasks everywhere, a run still being designed shows its design
word instead of0/0 merged, and every position readsstage 2 of 3. - Unknown is not zero. A missing value reads
unknown(-in a table cell): a
sub-agent with no end time, a check that never ran (✗ never ran), a doc gate still
loading, an age before the first snapshot. - Context fill never reads
450%:context 91% full (183k / 200k),context over 100% (450k / 200k window), orcontext 183k (window unknown). - Ages freeze when the daemon link is lost. Timers and ages stop counting, and the
badge readsDISCONNECTED · as of <ago>; the model picker's age is the catalog's own
fetch age. anthrex hold statustells the truth:(read 3m 10s ago),(stale: read 1h 35m ago)for a stale reading, the brake text the TUI shows for a braked runtime, and the
hold's age (on since Thu 14:30 +02:00 (2h 05m ago)).anthrex treelabels its numbers:#1 id 7(the positionC-b <n>uses and the
idls,killandattachtake),claude 2 · codex 1 · shell 1, andrunning 3m 10s,ran 12sordone -for a sub-agent.anthrex run statslabels its aggregates:MED LINES,MED CALLS,MED TOKENS,
MED WORK(a floored duration, was rounded minutes) andBOUNCES (ALL), a footer
saying what the medians are over, androunds: 3 ended · 1 run iterated. The TUI's
stats page uses the same words and shows the rounds line.
Fixed
- A host sleep no longer stalls an open turn or delivers into it. Across a laptop
sleep the wall clock jumped, so the stall watchdog interrupted an open worker turn
and the outbox delivered a message mid-turn (against decision 42), and the minutes
budget charged the sleep. The daemon now measures each sleep (wall time against the
awake clock) and excuses it from an agent session's stall clock, its waits (rate
limit, delivery and count retries, the interrupt's grace, a failed turn's continue)
and its minutes budget, and from a design phase's budget, a design agent's session
seconds and a stopped racer's exit wait; budgets count awake time. Orchestrator
notices and the GitHub-facing delivery polls still run on wall time. Records of what
happened stay wall times. - A wall clock set back now moves every session clock back with it. A clock set
ahead by mistake and then corrected looked like a sleep and then like nothing, so
every open turn's stall clock and every running wait stayed out by the mistake:
a turn set a year ahead and back never stalled. The daemon now also detects a wall
clock that falls behind the awake clock and gives each stall clock, wait, budget,
orchestrator-stall wait and writer-cap recovery the awake time it had left.
Backlog hardening (milestone 9.18), no new features. The protocol (26) and the run
format (6) are unchanged.
- More secrets are redacted from provider prompts and the Lessons page: Stripe
sk_live_andsk_test_keys, AWS secret access keys (after their key name, or on
the line of anAKIAorASIAkey id),Basiccredentials, and URL passwords
spelled%3A%2F%2F…%40or:\/\/…@. timeout 600 cargo testwaits for its build slot like a barecargo test, and so
dostdbufandcargo llvm-cov,cargo miri,cargo hackandcargo insta test.- A cached green is not reused after a
CARGO_PROFILE_*change.CARGO_PROFILE_*,
CARGO_TARGET_<triple>_RUSTFLAGS,CARGO_BUILD_RUSTFLAGSandCARGO_INCREMENTALare
now part of the tier cache key. If you set any of them, your next tier run misses the
cache once. - A task's own
[task.budget]raises its size ceiling. The budget ladder's next-size
check now uses, per axis, the larger of the task's budget and its class's, so a task
given more room is not stopped at its class's limit. Token totals no longer overflow. - A wheel scroll no longer holds the orchestrator's wake-up. Mouse reports sent
while a wake-up is pasted no longer count as typing, so the wake-up is submitted. - Dialogs wrap in display columns, so a path with CJK characters or emoji no longer
breaks the force-remove prompt's box. - A failed tool call shows as failed at once in the conversation view, from Claude's
PostToolUseFailurehook, instead of staying pending until the transcript is read. - Lessons requests never hang.
anthrex lessons(list,graph,approve,
reject,forget) refuses a store or history that is not a regular file, such as a
FIFO, instead of blocking on it, and gives up after 30 s on a file system that stops
answering. A stuckapprove,rejectorforgetno longer holds the store's lock,
so later changes and the lesson distiller still write. A FIFO athistory.jsonlno
longer holds a run start's tuning orrun statseither: it is refused unread. lessons.jsonlis compacted. Once it reaches 1 MiB, the lines no reader needs
(a closed lesson's day-old attempts, and records a later line replaces) are dropped.
Only the newest three moved-asidetuning.toml.bad-*files are kept.
Install: see docs/install.md.
The binaries are unsigned; on macOS, clear the quarantine flag as described there.