Skip to content

Releases: ryanlitalien/aida

v1.15.0

Choose a tag to compare

@github-actions github-actions released this 30 Sep 23:41
bd7e5a5
  • README: new "Picking the lane: the arbiter" section after the autonomous loop, covering how a task's data class and ~/.aida/lanes.yaml pick 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 copied examples/lanes.yaml to an overnight wave. The Commands block gains an arbiter and capacity group.

v1.14.0

Choose a tag to compare

@github-actions github-actions released this 30 Sep 15:17
39bdeb6
  • New internal/arbiter package: 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 via lanes.path; copy examples/lanes.yaml), one entry per lane with the CLI it runs (claude, codex exec, agy, or the metered aida --agent path), its allowed data classes, and its model. arbiter.Pick combines the burn-down capacity view (models.yaml plus burndown.yaml headroom 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 are butterstack, project:plt and other game tags are games, everything else is personal, 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 sets allow_unprobed: true. When no lane is eligible the arbiter waits and logs why; it never picks new spend on its own.
  • New internal/taskstate package holding the per-task state an unattended run needs. Each task gets a STATE.json in the brain repo (phase, host, attempt count, lane history, and an acceptance block of --check commands plus named ## Deliverables parsed from the task body) and a model-authored HANDOFF.md written 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 with git push --force-with-lease so 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 --arbiter and aida serve --loop-arbiter turn 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 from HANDOFF.md on the next lane. A missing or invalid lanes.yaml fails loudly at startup rather than silently spawning on the metered path. The gate is the run's --check commands 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-metered aida --agent path. The arbiter path cuts worktrees through loopOpts.setupTaskWorktree, so it uses the same resolved base remote and ref as the rest of the loop.
  • aida serve --arbiter hosts 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-check and 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 arbiter subcommands: lanes (list the roster, --lint to 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), signal and signals (mark a lane empty by hand, or list current signals), handoff (read or check a task's HANDOFF.md, including check and show for a task ref), ledger (the per-attempt record of lane, model, and outcome), and status (the live view the dashboard also reads). aida loop --dry-run stops before any claim, so it never pushes a lease ref, writes STATE.json, or spawns an agent.
  • The /dashboard gains an Arbiter card backed by a new GET /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_OrphanGrandchildTimeout in internal/execx, which hung in containers with no init reaper: a killed grandchild is reparented to PID 1 and never reaped, so kill(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 the kill(0) result alone on macOS and other systems without /proc.

v1.13.0

Choose a tag to compare

@github-actions github-actions released this 25 Sep 14:22
903e5b7
  • The models roster (~/.aida/models.yaml, internal/models/roster.go) gains an optional per-provider retired: 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's models_cache.json via unlistedCodexModels, agy's agy models via agyModelsUnlisted, including -high/-medium/-low effort-suffix stripping), so dropping a superseded version from the active roster doesn't make aida models start 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.Models never contains them, so Resolve never attaches a nickname to one, and they never appear in aida models, aida models --json's models arrays, or the dashboard's Models panel. examples/models.yaml documents the shape.
  • The /dashboard Models 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's extra_usage, spend, and seven_day_breakdown fields and surfaces two new lines under each Claude provider, in aida models, --json, and the dashboard's Models panel: a usage credits line reporting whether Anthropic's purchasable usage credits (there is no free reset, unlike Codex's reset_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 a 7-day by surface line 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

Choose a tag to compare

@github-actions github-actions released this 22 Sep 21:19
e3b58d3
  • 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

Choose a tag to compare

@github-actions github-actions released this 21 Sep 21:55
1e2e5f1
  • The autonomous loop no longer hardcodes origin as the remote a project lives on. At the start of a --worktree / --pr run it now asks git which remote the --base branch tracks (worktree.ResolveUpstream, reading branch.<base>.remote and branch.<base>.merge) and resolves that once into the loop options, so worktree creation (internal/cli/loop.go), the --pr push (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 --base never reached worktree creation at all (even --base release branched off origin/main), the PR push went to a literal origin and then gh pr create failed on a branch GitHub had never seen, and the review panel diffed against origin/<base> regardless of what the base branch tracks. A base branch with no upstream, or a repo with no remotes, falls back to origin / 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.Create now pre-fetches whichever configured remote the base ref names (checked against git remote) rather than only when the ref starts with origin/, so a worktree cut off public/main or upstream/release starts from the fresh remote tip too. The fetch stays best-effort and an offline failure still falls back to the local ref.
  • aida loop --pr now 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 --pr is not supported there yet; use --commit or push the auto/ branch to the mirror by hand. Opening the PR on the mirror is a separate feature.
  • Running aida loop --worktree outside a git repository now fails the run up front instead of parking every task on hold one at a time.

v1.10.0

Choose a tag to compare

@github-actions github-actions released this 21 Sep 17:04
2753271
  • Bumped go.opentelemetry.io/otel/sdk from 1.43.0 to 1.45.0, which carries otel, otel/trace, and otel/metric to 1.45.0 alongside it, plus the indirect github.com/go-logr/logr 1.4.4 and golang.org/x/sys 0.47.0 that those modules require. No API surface aida uses changed, and the full test suite passes unmodified.

v1.9.0

Choose a tag to compare

@github-actions github-actions released this 21 Sep 16:43
3fdf875
  • 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: the aida fleet start --cwd default, 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, so brain_search could never return them. Every *.md page in that directory, both generated source profiles and hand-written prose pages with no Keywords: line, now lands in a new knowledge_pages table plus a knowledge:<slug> row in the shared FTS corpus (doc type knowledge:domain), indexed incrementally by mtime with best-effort embeddings, pruned when a file disappears, and re-embedded by aida brain reembed alongside the other tables. The domains figure 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_search tool and aida brain search now return matching knowledge pages (a new ## Knowledge Pages section with the page body), and the agent's multi-channel SearchMulti gains a knowledge vector channel next to wiki, with keyword hits arriving through the shared FTS corpus.
  • The brain staleness check now watches knowledge/domains/ rather than all of knowledge/, so editing knowledge/routing/ or knowledge/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

Choose a tag to compare

@github-actions github-actions released this 18 Sep 14:20
9f82377
  • Removed the last references to a specific third-party Claude Code hook manager from the repo. The additive-merge behavior is unchanged - aida setup still merges its harvest hooks into ~/.codex/hooks.json and ~/.gemini/settings.json so anything another tool already wrote survives byte-for-byte, and still refuses to write ~/.claude/settings.json at 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

Choose a tag to compare

@github-actions github-actions released this 17 Sep 18:16
005579f
  • 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, the wiki.path config key, and the aida wiki index / aida wiki lint commands, 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 --help now names the wiki.path config key instead of presenting its default as the path, and the wiki plan doc is scrubbed of owner-specific references and renamed to docs/plan-wiki-integration.md. Help strings and comments only; no behavior change.

v1.6.0

Choose a tag to compare

@github-actions github-actions released this 16 Sep 17:14
e79a9d2
  • Roster subagent entries can now pin the Claude model their claude --print transport runs on via a new subagent.model field, passed through verbatim as --model <value> (an alias like sonnet/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.