Repository navigation
Releases: ryanlitalien/aida
Releases · ryanlitalien/aida
Release list
v1.15.0
- README: new "Picking the lane: the arbiter" section after the autonomous loop, covering how a task's data class and
~/.aida/lanes.yamlpick the lane, where headroom comes from (aida models,aida burndown capacity), what happens when a lane runs dry (HANDOFF.md at 90 percent, fail-open limit signals, the git-ref lease), and the five commands to go from a copiedexamples/lanes.yamlto an overnight wave. The Commands block gains an arbiter and capacity group.
v1.14.0
- New
internal/arbiterpackage: a lane picker that decides which credential and which CLI a task runs on, cheapest eligible lane first. The lane roster lives in~/.aida/lanes.yaml(config.Config.LanesPath, override vialanes.path; copyexamples/lanes.yaml), one entry per lane with the CLI it runs (claude,codex exec,agy, or the meteredaida --agentpath), its allowed data classes, and its model.arbiter.Pickcombines the burn-down capacity view (models.yamlplusburndown.yamlheadroom per window) with per-lane rate-limit signals from~/.aida/arbiter/lane-state.json, and returns a lane, a model, a near-exhaustion flag, and a reason string per rejected lane. A task's tags map to a data class (ADR-0003): ButterStack tags arebutterstack,project:pltand other game tags aregames, everything else ispersonal, and a lane only accepts the classes it lists, so company work never lands on the personal Max or Codex login and personal work never lands on the company seat. A lane with no capacity rows is ineligible unless it setsallow_unprobed: true. When no lane is eligible the arbiter waits and logs why; it never picks new spend on its own. - New
internal/taskstatepackage holding the per-task state an unattended run needs. Each task gets aSTATE.jsonin the brain repo (phase, host, attempt count, lane history, and an acceptance block of--checkcommands plus named## Deliverablesparsed from the task body) and a model-authoredHANDOFF.mdwritten at attempt boundaries (ADR-0004), so when a lane runs dry mid-task the next lane resumes from the handoff instead of starting cold. A run claims a task with a lease that is a git ref,refs/leases/<slug>on the brain remote, taken withgit push --force-with-leaseso N claimers produce exactly one winner and a rejected push is the collision signal (ADR-0001); an expired lease can be taken over and a held one renewed. aida loop --arbiterandaida serve --loop-arbiterturn on lane enforcement, and both are on by default (ADR-0002, reversed 2026-09-25 from an opt-in): every attempt asks the picker for a lane and runs that lane's own CLI, and if a run reports a usage limit the lane is marked empty and the next attempt resumes fromHANDOFF.mdon the next lane. A missing or invalidlanes.yamlfails loudly at startup rather than silently spawning on the metered path. The gate is the run's--checkcommands plus any named deliverables; a passing task takes the same tail as the plain loop (marked done, or a PR under--pr), a failing one is parked on hold, and every attempt appends a line to~/.aida/arbiter/ledger.ndjson.--arbiter=false(or--loop-arbiter=false) reverts a single invocation to the old always-meteredaida --agentpath. The arbiter path cuts worktrees throughloopOpts.setupTaskWorktree, so it uses the same resolved base remote and ref as the rest of the loop.aida serve --arbiterhosts an overnight scheduler in the daemon (HTTP mode only, mutually exclusive with--loop). It wakes at a fixed nightly time and whenever a 7-day window is about to reset with headroom left to drain, runs a lane-1 preflight turn before each wave, and skips any task with no machine verifier (no--arbiter-checkand no## Deliverables) unless told otherwise. Tuning flags:--arbiter-tag,--arbiter-check,--arbiter-nightly-at,--arbiter-weekly-drain,--arbiter-require-verifier,--arbiter-worktree,--arbiter-pr,--arbiter-reviewer,--arbiter-concurrency,--arbiter-preflight-timeout.- New
aida arbitersubcommands:lanes(list the roster,--lintto validate it),plan(a read-only table of what the arbiter would do with each open task: class, lane, model, near-exhaustion, reason; it runs nothing),signalandsignals(mark a lane empty by hand, or list current signals),handoff(read or check a task'sHANDOFF.md, includingcheckandshowfor a task ref),ledger(the per-attempt record of lane, model, and outcome), andstatus(the live view the dashboard also reads).aida loop --dry-runstops before any claim, so it never pushes a lease ref, writes STATE.json, or spawns an agent. - The
/dashboardgains an Arbiter card backed by a newGET /api/arbiter: scheduler state and reason, next wake, the last wave's task, passed and held counts, and any lanes currently marked empty (until when, from which source, and whether the signal was ambiguous). The endpoint reads the scheduler's state files only, no live capacity probe, so the 30-second poll stays cheap, and it returns a 200 with zero-value fields on a box where the scheduler has never run rather than failing the page. - Fixed
TestRun_OrphanGrandchildTimeoutininternal/execx, which hung in containers with no init reaper: a killed grandchild is reparented to PID 1 and never reaped, sokill(pid, 0)kept succeeding on the zombie even though the kill had worked. The test now treats a zombie as gone by reading the process state from/proc/<pid>/stat, and falls back to thekill(0)result alone on macOS and other systems without/proc.
v1.13.0
- The models roster (
~/.aida/models.yaml,internal/models/roster.go) gains an optional per-providerretired:list of model ids. A retired id still counts as known for every unlisted-model diff a probe runs against a local tool cache (Codex'smodels_cache.jsonviaunlistedCodexModels, agy'sagy modelsviaagyModelsUnlisted, including-high/-medium/-loweffort-suffix stripping), so dropping a superseded version from the active roster doesn't makeaida modelsstart flagging it as "unlisted locally, not in roster" every time a warm local cache still lists it. Retired ids are otherwise invisible everywhere else:Provider.Modelsnever contains them, soResolvenever attaches a nickname to one, and they never appear inaida models,aida models --json'smodelsarrays, or the dashboard's Models panel.examples/models.yamldocuments the shape. - The
/dashboardModels panel now draws every usage bar as a bullet bar instead of a thin accent-colored progress bar: a flat track with a shaded 90%+ zone at the far end, a thin fill in a hue fixed per provider (roster order, never cycled), six labeled day ticks (d1..d6) on any 7-day window, and a pace marker at how far through the window the clock is, so fill left of the marker reads as under pace at a glance; the marker now draws on every bar that has a real reset time and window length, not just ones with a computed pace verdict, so 5-hour bars and idle 7-day bars (e.g. a 0%-used Gemini week) show the clock position too. The meta column is a bold used% (red at 90%+) followed by the reset as a short local absolute time ("resets Fri 2:00pm", or "idle" for a zero reset time); the ratio/IDLE verdict and its detail moved into the track's tooltip. LiteLLM spend rows use the same track with spend/budget as the fill and "$x / $y" in the meta. A 0-100% scale row and a one-line key sit under the provider cards. Both themes carry their own series and track inks. - The Anthropic OAuth usage probe (
internal/models/probe_claude.go) now parses the usage payload'sextra_usage,spend, andseven_day_breakdownfields and surfaces two new lines under each Claude provider, inaida models,--json, and the dashboard's Models panel: ausage creditsline reporting whether Anthropic's purchasable usage credits (there is no free reset, unlike Codex'sreset_credits) are on with a dollar amount and monthly cap, off by choice, or never enabled, plus a(can buy)suffix and balance/spend-limit detail where applicable; and a7-day by surfaceline breaking the account's 7-day usage down by Claude Code / Chats / Cowork / Other. Both are omitted entirely when the payload doesn't carry the corresponding field.
v1.12.0
- README gained a "The shape around it" section: a table naming the five kinds of private repo that sit around the public core (config, memory, knowledge, fleet, clients), what each holds, why each stays private, and which aida surface reaches it. The point is the separation rather than the author's particular repos, so a reader can see how to keep their own machines, data and credentials out of anything they publish while still running the same binary.
v1.11.0
- The autonomous loop no longer hardcodes
originas the remote a project lives on. At the start of a--worktree/--prrun it now asks git which remote the--basebranch tracks (worktree.ResolveUpstream, readingbranch.<base>.remoteandbranch.<base>.merge) and resolves that once into the loop options, so worktree creation (internal/cli/loop.go), the--prpush (internal/cli/pr.go), and the review-panel diff all use the same remote and remote-tracking ref (e.g.public/public/main) and cannot drift. Previously--basenever reached worktree creation at all (even--base releasebranched offorigin/main), the PR push went to a literaloriginand thengh pr createfailed on a branch GitHub had never seen, and the review panel diffed againstorigin/<base>regardless of what the base branch tracks. A base branch with no upstream, or a repo with no remotes, falls back toorigin/origin/<base>, so any single-remote project behaves exactly as before; a base tracking a local branch (.remote) cuts from that branch and refuses to push. worktree.Createnow pre-fetches whichever configured remote the base ref names (checked againstgit remote) rather than only when the ref starts withorigin/, so a worktree cut offpublic/mainorupstream/releasestarts from the fresh remote tip too. The fetch stays best-effort and an offline failure still falls back to the local ref.aida loop --prnow fails fast, before any push, in a repo whose base branch tracks a public GitHub remote while some other remote is a non-GitHub mirror (a review-on-the-forge-first layout). The error names both remotes and their URLs and says--pris not supported there yet; use--commitor push theauto/branch to the mirror by hand. Opening the PR on the mirror is a separate feature.- Running
aida loop --worktreeoutside a git repository now fails the run up front instead of parking every task on hold one at a time.
v1.10.0
- Bumped
go.opentelemetry.io/otel/sdkfrom 1.43.0 to 1.45.0, which carriesotel,otel/trace, andotel/metricto 1.45.0 alongside it, plus the indirectgithub.com/go-logr/logr1.4.4 andgolang.org/x/sys0.47.0 that those modules require. No API surface aida uses changed, and the full test suite passes unmodified.
v1.9.0
- Scrubbed the personal and private nouns that test fixtures, testdata, doc examples, prompt examples, and code comments had been using as stand-ins: a real campground business is now the fictional Pine Hollow Campground (slug
pine-hollow), a real company and its GitHub org/repo are now the Acme Widgets family (acme-widgets,acme_widgets,acmewidgets), and a real first name is now Ralph. Fixtures that exercise slug splitting, token compaction, and artifact-id matching keep the same two-word hyphenated shape so those tests still cover what they did. No behavior change: theaida fleet start--cwddefault, the whisper vocabulary prompt, and the live golden query suite are untouched because they must match the machine they run on. - Curated knowledge pages under
brain/knowledge/domains/are now part of the searchable corpus.aida brain index(and the staleness-triggered background rebuild) used to only count those files for its summary line without reading, embedding, or inserting a single one, sobrain_searchcould never return them. Every*.mdpage in that directory, both generated source profiles and hand-written prose pages with noKeywords:line, now lands in a newknowledge_pagestable plus aknowledge:<slug>row in the shared FTS corpus (doc typeknowledge:domain), indexed incrementally by mtime with best-effort embeddings, pruned when a file disappears, and re-embedded byaida brain reembedalongside the other tables. Thedomainsfigure in the index summary now reports what was actually indexed. The planner's keyword-routing read of the same files is unchanged. - The MCP
brain_searchtool andaida brain searchnow return matching knowledge pages (a new## Knowledge Pagessection with the page body), and the agent's multi-channelSearchMultigains aknowledgevector channel next towiki, with keyword hits arriving through the shared FTS corpus. - The brain staleness check now watches
knowledge/domains/rather than all ofknowledge/, so editingknowledge/routing/orknowledge/patterns/(which the index never reads) no longer triggers a full multi-minute re-embed, while a batch of new domain pages still does, and that rebuild now picks them up.
v1.8.0
- Removed the last references to a specific third-party Claude Code hook manager from the repo. The additive-merge behavior is unchanged -
aida setupstill merges its harvest hooks into~/.codex/hooks.jsonand~/.gemini/settings.jsonso anything another tool already wrote survives byte-for-byte, and still refuses to write~/.claude/settings.jsonat all - but the comments, docs, and test fixtures now describe that tool generically instead of by name, and the merge tests simulate a fictional "othertool" rather than a real product.
v1.7.0
- Documented the memory stack's L4 tier, which the docs had reduced to one table row reading "Planned": the README's memory section now shows a path per tier, corrects the L4 row (the consolidation pass shipped as
aida brain consolidate), and explains why the wiki is a separate repo rather than another directory under~/.aida/brain/- it carries raw archive corpora and human-reviewed prose, and material graduates into it only once it stops changing - along with the OKF v0.1 format, thewiki.pathconfig key, and theaida wiki index/aida wiki lintcommands, which the Commands block had never listed. - INSTALL.md's backup section now covers the wiki as a third optional directory and says plainly that a private git remote is the lowest-friction route rather than a requirement: an rsync to a local server or NAS, or a Time Machine target, backs up a directory of plain files just as well. The privacy warning extends to the wiki, which holds the same class of material as the brain.
aida wiki --helpnow names thewiki.pathconfig key instead of presenting its default as the path, and the wiki plan doc is scrubbed of owner-specific references and renamed todocs/plan-wiki-integration.md. Help strings and comments only; no behavior change.
v1.6.0
- Roster
subagententries can now pin the Claude model theirclaude --printtransport runs on via a newsubagent.modelfield, passed through verbatim as--model <value>(an alias likesonnet/opus/haiku/fable, or a full model id), so cheap reporting personas can run on a lighter model instead of inheriting Claude Code's configured default; leaving it unset keeps the old inherit-the-default behavior.