# aid Roadmap
Updated 2026-10-09 after the third-party capability evidence work (unreleased).
This document owns execution order and acceptance gates; [CHANGELOG](../CHANGELOG.md)
owns release history. The [takeover inventory](project-status-2026-09-22.md) records
source evidence and verification limits. Release validation is recorded separately from historical audit results.
`ai-board` remains the work-item tracker (`ai-board item list --project ai-dispatch`).
Existing `wi-*` IDs are retained for reconciliation; source implementation status below
does not assert board closure. New slices need board IDs before implementation.
## Current baseline
- The current release is **v10.51.0** (2026-10-08): quota, cost and isolation fixes from
[the magpie comparison](investigation-magpie-absorption.md); see the section below.
The release candidate passed the full `--bin aid` suite on the build box (2,982 passed,
0 failed, 11 ignored), `aid_guide_e2e`/`init_e2e`, and `scripts/release.sh --dry-run`.
- v10.50.0 (2026-09-30) carried the first rounds of the
structural refactor program below, `--read-only` enforcement, and the command-surface
consolidation (removed `kill`, `output`, top-level `summary`/`finding`/`broadcast`,
`config add-agent`, `watch --wait`).
- The release candidate passed the full workspace suite on the build box
(34 test binaries, 3,038 passed, 0 failed) and `scripts/release.sh --dry-run`.
A recursive `--help` dump (126 pages, default features) was identical before and after
the CLI module reorganisation. Web-feature help and the live API/Swift gates were not
re-run for this release.
- Earlier baseline notes (v10.47.x custody and budget work) remain below for reconciliation.
## Third-party capability evidence (unreleased)
aid assigns no capability scores of its own. The per-CLI capability matrix, the
hand-written `capability` field of catalog rows and the complexity bonus are removed.
Model capability comes from third-party leaderboards served by the price relay at
`/v1/scores.json` (Terminal-Bench 4.0, Epoch ECI and SWE-bench Verified, LMArena
webdev/agent), keyed by the same ids as `/v1/prices.json`. One source per task category,
never blended; a Terminal-Bench row applies only to its exact CLI and effort. A route
with no evidence scores a neutral 6.0 and is never excluded by the capability floor.
Known limits found by review:
- Sources use different 0-10 rescales (Terminal-Bench fixed 0-100, ECI min-max over the
current snapshot), so the lowest-ECI model rescales to 0 and routes rated by different
sources are not strictly comparable.
- `harness: measured` is reported whenever a Terminal-Bench row exists, even when the
task category scored from another source.
- Effort strings must match exactly; a mismatch falls back to the model-level source.
- A model the relay lists under two price ids (e.g. `claude-opus-5-5` and
`anthropic/claude-opus-5.5`) scores only under the one the scores feed uses.
- Feed refresh (`src/feed_refresh.rs`): the detached `sh` is not reaped, so a
long-running aid process keeps up to two defunct children until it exits; `.ready`
is validated then renamed by path (claiming it under a per-process name first would
close a narrow swap window); the script's `mv` takes no `--` and curl has no
`--max-filesize`.
## Quota, cost and isolation (v10.51.0)
### Landed
| Claude quota | Rejected `rate_limit_event` and error results hold the claude route until the stated reset (≤ 8 days); quota evidence for Claude is envelope text only (`Attributable::quota_text`); plain lines still reach auth markers |
| Quota ranking | Headroom penalty reads only windows that cover the requested model; expired windows and sub-24h windows resetting within 60 minutes do not penalise |
| Cost | Codex/Claude completions priced by component (uncached input, cached input, output, cache writes at 1.25× input) when recorded; Claude `total_cost_usd` stays authoritative |
| Usage | OpenCode-format parsers (OpenCode, Kilo, MiMo Code, custom delegates) sum `step_finish` usage; the recorded model is the dominant `modelUsage`/Gemini entry |
| Isolation | Inherited per-CLI config redirect variables (`CONFIG_REDIRECT_VARS`) are removed from host and PTY launches; batch `env_forward` values resolve at launch; job specs are `0600` |
| Tooling | `scripts/remote-test.sh` exits 66 when a filter matches no tests |
### Next (from the same study; none started)
| Salvage commit identity | `failure_salvage` WIP commits carry the repository's configured identity inside an isolated HOME; a test fails when it falls back to `user@host` |
| Idle timeout during box waits | A verify or agent blocked on the build-box lock is not killed as idle; queue wait does not count toward the verify timeout |
| Model id normalisation | One `canonical_model_id` (case, vendor prefix, date suffix, `[1m]`, `.`≡`-`) used by rating, gate, pricing and probes; Codex probe drops hidden models |
| Context overflow | An overflow failure writes no hold and continues on a model with a larger context instead of a same-model retry |
| Early failure cascade | A non-quota failure in under 30 s with no work cascades without consuming `--retry`; an all-held error lists every route and its reset |
| Vendor signatures | Agent-independent credit refusals (`余额不足`, `insufficient_quota`) and Codex JSON `resets_at` |
| Cost settlement | A Codex ceiling is not failed on a provisional model price; reports prefer the persisted task cost |
| Quota snapshot fields | `credits`, `held`, `span_secs` read from aidbar snapshots |
## Structural refactor program (in progress)
Source: a three-lane audit of the 109 non-merge commits before v10.48.0 (execution
lifecycle, agent/model layer, command surface). Each slice must remove code or a concept;
no new layer. Behaviour-preserving moves and semantic fixes land separately.
### Landed in v10.50.0
| Run configuration | CLI args convert once into `cmd::run::RunArgs` (positional 49-argument bridge deleted); workers rebuild from saved dispatch args; every retry path starts from `RunArgs::for_retry` |
| Command surface | Duplicate/hidden verbs removed; subcommand enums defined once; CLI args grouped in domain-named files; one exhaustive dispatch `match` |
| Agent layer | One bounded probe runner for identity, help, version, model listing and preflight; native OpenCode served by the shared overlay; agy `--model` checked at preflight |
| Routing | `advise` is the ranker for hints; quota terms use the resolved model's group; only installed, enabled, non-excluded routes are recommended; Gemini is excluded when agy is installed |
| Pricing | One price function (override, subscription, catalog figure, vendor-CLI feed, unknown); displays read the enforced price |
| Worktree | One git-status porcelain parser for every reader |
| Read-only | Post-run snapshot comparison of the Git run directory |
| Tests | Guide tests check facts generated from code plus a safety-invariant table; gated-verifier settlement E2E harness |
### Next slices (execution order)
| 1 (complete locally) | Route: best-of races advise's launchable candidates | No uninstalled or held route races; each racer's resolved model equals the advised model; plan cycling kept |
| 2 (complete locally) | Route: cascade fallback from advise | Fallback is the first launchable advise candidate other than the exhausted agent; Claude and superseded Gemini never selected; a peer below the capability floor is not selected |
| 3 (complete locally) | Pricing: budget scoring uses the price function | Subscription and unknown prices are not "paid"; overrides apply both ways |
| 4 | Run configuration: job file holds runtime state only | Nine runtime fields; old job files still load so running workers can be waited on, stopped and reaped |
| 5 | Read-only snapshot scope | Snapshot from the repository top level; the run repository's HEAD and refs compared; repositories without commits and special files recorded instead of failing |
| 6 | Read-only report location | Auto audit reports written under the task directory for host launches; explicit `--result-file` unchanged |
| 7 | Worktree observation | One capture per settlement step; comparisons computed only where read; per-consumer filters unchanged |
| 8 | Task settlement | Terminal status published once after verification, preservation and continuation selection; see [task settlement design](design/task-settlement.md) |
**Exit per slice:** full remote suite green, an independent audit with test evidence,
guide updated for any contract change, and net production lines not increased.
2026-10-03 progress: slice 1 (`wi-843a`) is complete locally. Production lines
decrease by 35; both full remote suites and strict default/Web lint pass, and
independent review returns SHIP. Slice 2 (`wi-7aad`) is also complete locally: automatic cascades preserve
advice's exact model and declared profile through resolver, quota continuation
and batch handoffs. Production Rust decreases by 10 physical lines; 3,098 default
and 3,130 Web tests pass, with zero failed and 14 existing ignored per suite.
Strict default/Web production lint and independent review pass. [Cascade validation](validation-advised-cascade-2026-10-03.md)
records the source and completed jobs. Slice 3 (`wi-739e`) is complete locally:
budget scoring uses resolved prices and exact overrides, with production Rust
reduced by 2 lines. The final pricing source passes 3,102 default and 3,134 Web
tests, zero failed and 14 existing ignored per suite, strict default/Web lint,
guide validation and independent SHIP. [Pricing validation](validation-resolved-price-scoring-2026-10-03.md)
records the exact source and jobs. Slice 4, runtime-only job state, remains open.
Read-only report preservation (`wi-562b`) and the remote verifier's absolute
launch/wait deadline (`wi-8b23`) also pass their before/after regressions and
independent review. The final candidate passed 3,066 default and 3,098 Web tests,
zero failed and 14 existing ignored per suite. [Validation and audit evidence](validation-route-settlement-2026-10-03.md)
records the exact source, commands, job IDs and limits. Issue #118 retains three
separate source-only configuration/prelaunch gaps; live Drive and M0 API/Swift
gates remain open. These changes do not constitute a release.
### Known limits of the current code
- `--read-only` compares only files under the run directory (from a repository
subdirectory, that subtree); the run repository's own HEAD, branches and tags are not
compared; an embedded repository without commits fails the snapshot.
- Batch dependencies and `aid accept` can act on a task whose verification is still
running; the settlement harness records these as ignored scenarios.
- Retry children of an agent failure (`prepare_retry`) inherit the saved `on_done` hook
and do not overlay the worker's runtime environment.
## Reconcile the previous queue
| `wi-4c47`: agy terminal errors | Implemented; v10.38.0 changelog and buffered watcher fixtures | Retain regression coverage; reconcile board |
| `wi-7b8e`: live probe process ownership | Implemented in `scripts/probe-client-api.sh`; v10.38.0 notes | Re-run with current API baseline |
| `wi-8ffc`: target-project dispatch | Implemented; v10.38.0 notes, further prompt-context fix in v10.47.0 | Protect existing coverage; audit budget path separately |
| `wi-dc6a`: custody without worktrees | Shared-checkout recovery committed in `d7dc85ef` and remotely tested | Review and reconcile board; see evidence below |
| `wi-29bd`: project budget | Target identity enforcement/reporting committed in `d7dc85ef` and remotely tested; init/sync contract remains | Next budget work is slice 3 below |
| `wi-e1a0`: merge conflict attribution | Distinct stash-restore result, durable stash identity, regression tests exist | Acceptance recheck; not an unimplemented feature |
| `wi-5eef`: truthful release dry-run | Recorded in v10.47.0 and covered by release hygiene tests | Remove from implementation queue; keep release gate |
| #152: module-tree migration | run/show/batch subdirectories landed (v10.46.0) | Continue only remaining clusters |
## M0 — Restore a reproducible baseline (P0, next)
1. Reconcile retained IDs and stale active initiatives in ai-board. Do not carry forward
an active status solely because the August roadmap called it active.
2. Restore the approved rbox test environment and a Python 3.10+ tooling environment.
Re-run default and Web-enabled Rust suites on the same candidate SHA.
3. Default/Web CI coverage, strict production lint and the background wait race
are fixed in this patch. Next make the client API probe use a controlled fixture
rather than relying on an operator's task history.
4. Establish an approved macOS build runner for XcodeGen, both client schemes, and Swift tests.
Record source SHA, toolchain, commands, exit codes, and log locations.
**Exit:** a reproducible result for every required surface, with failures assigned to
bounded work items. A historical audit or a skipped probe is not a pass.
Baseline-environment work can proceed alongside the two correctness slices in M1.
## M1 — Close dispatch and artifact boundaries (P0/P1)
| 1 / P0 | Non-worktree artifact custody (`wi-dc6a`) | Rescue preserves recoverable results without committing/amending the principal's active branch or absorbing unrelated staged work. Cover no-HEAD, tagged HEAD, pre-existing dirty files, failure, retry and normal worktree cases. |
| 2 / P0 | Target-project budget identity (`wi-29bd`) | Dispatch A → B uses B's resolved identity for budget checks; A's cap cannot block B and B's cap cannot be bypassed by cwd. Cover no-config targets, linked worktrees, batch and retry. |
| 3 / P1 | Project budget source contract (`wi-29bd`) | Specify precedence and whether edits require sync; test cost/token/window limits and cap removal. Keep declared model-budget preference distinct from enforced spend limits. |
| 4 / P1 | Merge recovery acceptance (`wi-e1a0`) | Branch conflict and stash-restore failure remain distinguishable; recovery identifies the exact retained stash and does not discard local files, including a competing stash. |
**Exit:** each slice has a reproducer, regression coverage, guide updates for any public
contract change, and tests on the reviewed candidate. Infrastructure refusal must remain
separate from agent failure; terminal task status must not imply permission to GC.
### Custody and budget implementation committed — 2026-09-23
The non-worktree settlement slice of `wi-dc6a` is implemented: shared-checkout settlement uses a private-index
recovery ref rather than committing/amending the principal branch. Regression cases
cover real-index preservation, unborn/tagged HEAD, repeated snapshots, renames,
publication failure, and task status. All 12 new regressions and both default/Web
Rust suites pass on the remote builder. [Validation evidence](validation-custody-2026-09-23.md)
records counts, job IDs, and limitations. The 15 strict clippy diagnostics are
resolved by this patch. Live API/Swift gates and board closure
remain outstanding. The local rbox fleet is configured outside the repository.
The target-project identity slice of `wi-29bd` is also implemented. Budget checks,
stored usage aggregation and reporting use the target's persisted project identity.
All 10 new CLI regressions pass; default tests pass and Web tests pass on an unchanged
rerun. The first Web attempt exposed an intermittent background delivery failure,
reproduced and fixed by this patch. [Budget validation](validation-budget-2026-09-23.md)
records both attempts. Next budget work is slice 3: project configuration/sync precedence
and cap removal. Concurrent spend reservation is outside the completed slice.
## M2 — Make client/server delivery routine (P1)
- Decide and document whether release binaries include `web` or ship a separate variant;
current release builds use default features. Document the matching client setup path.
- Preserve authentication, action-conflict responses, SSE reconnect/restart behavior,
state/outcome consistency, and latency acceptance across server and Swift client.
- Require the default suite, Web suite, live API probe, both client builds and Swift tests
on one candidate when the release includes client/API changes.
- Keep dry-run hygiene and exact stash/worktree recovery diagnostics under regression checks.
**Exit:** a clean checkout can build and validate the intended distribution without
personal task history or undocumented local tooling. No release number is promised here.
## M3 — Reduce remaining maintenance cost (P2)
- Continue #152 with rate-limit, worker/PTY and Store mutation boundaries; the
lifecycle boundary is tracked in the structural refactor program above.
Keep behavior-preserving extraction separate from semantic fixes.
- #160 adapter consolidation: OpenCode native/overlay and CLI probing are shared as of
v10.50.0; reassess further sharing against captured protocol fixtures.
- Re-triage [historical UX debt](ux-debt.md): batch dependency lineage (`wi-f4bf`),
content-hash resume (`wi-1479`), and resource lifecycle (`wi-7804`) remain separate programs.
Start each with a current reproduction and a narrow acceptance contract.
- Audit remaining blanket lint exceptions, stale knowledge references and tracked
generated reports; archive useful evidence before deleting artifacts.
**Exit per slice:** fewer duplicated owners/parsers, preserved external behavior, and
scenario coverage. File movement or a lower line count alone is not completion.
## Verification and release process
Rust compilation/tests run through the configured build box, per [CLAUDE.md](../CLAUDE.md).
Do not fall back to local compilation on the operator's Mac.
```bash
# Requires an operator-configured AID_BUILD_BOX and rbox on PATH.
scripts/remote-test.sh --dry-run -- --locked
scripts/remote-test.sh -- --locked
scripts/remote-test.sh -- --locked --features web
# With Python 3.10+, no remote contact or Cargo compilation:
python3 scripts/remote-test-test.py
bash .github/scripts/check-changelog.sh
```
The live probe requires `AID_BIN` pointing to the reviewed Web-enabled binary and
`AID_SRC_DB` pointing to a suitable controlled database. Swift schemes are declared in
[`client/project.yml`](../client/project.yml). These gates require their respective runners;
the custody slice did not run the live probe or Swift targets.
Use `scripts/release.sh` for version/changelog/release commit/tag/push; run its dry-run
first and set `AID_RELEASE_TEST_CMD='scripts/remote-test.sh'`. Do not manually bump or
publish as part of roadmap maintenance. The [August handoff](audit-handoff-2026-08-23.md)
is historical evidence, not the next release candidate definition.