Skip to content

v0.56.2

Choose a tag to compare

@github-actions github-actions released this 17 Sep 23:13
· 7350 commits to main since this release

AFT 0.56.2 is a patch release for aft doctor reporting healthy OpenCode installs as broken, for natural-language aft_search stalling on machines where the local embedding model is slow, and for a set of smaller defects found by the new daemon health sentinel while it was being built.

Fixes

  • aft doctor no longer flags a working OpenCode V1 install. It expected a ./server load path that V1 never uses (V1 always loads the package root) and required an exact version pin where @latest is the correct V1 registration; the exact pin now applies to OpenCode 2 hosts only. On a machine where OpenCode is running, doctor also crashed with "host probe changed the operator database": the probe's isolation canary compared the live opencode.db before and after and could not tell the running host's writes from its own. The strict canary is kept for CI; in production the probe proves its isolation positively and tolerates a live host.
  • Natural-language aft_search queries no longer stall when the local embedding model is slow. The query-time budget (3 s, then lexical results with a note) applied to remote embedding backends but not to the bundled ONNX one, so a slow inference held the whole search for as long as it took. The local embed now runs under the same budget on its own worker, a query that exceeds it falls back to lexical search, the late vector is kept for the next identical query, and ONNX worker threads are capped by the container's CPU quota instead of the visible core count. Identifier-shaped queries were unaffected, which is why single-word searches kept working. (#319)
  • Retrying a search after a timeout no longer fails with "re-verification of live memo entry is rejected". The exact-match memo marked a query verified before its verification ran; an abandoned attempt burned the epoch and the identical retry was refused. Verification is single-flight per query: a concurrent request joins it, an abandoned or failed one leaves the query retryable. (#319)
  • Multi-word exact matching skips files that cannot contain the phrase. Every candidate file was scanned for one- to three-line windows even when one of the query's tokens was absent; a 2,000-file corpus went from 1.6 s to 0.33 s warm on that path.
  • read and other tool calls no longer wait behind a long aft_inspect on the standalone bridge. Wrapped tool calls that the bare-command path already deferred (inspect, read, bash, LSP navigation) ran on the request loop when invoked through tool_call, so a 35 s inspect timed out every sibling request and OpenCode killed the bridge. (#317)
  • Embedding builds against llama.cpp survive an oversized chunk. Dense rows the character-to-token estimate undercounted returned HTTP 400 and aborted the whole build; the backend is now the tokenization authority: an overflow reply bisects the batch, shrinks the offending row toward its signature, and skips it with a count if it still does not fit. (#318)
  • glob with a path argument matches a bare filename directly under that path. {path: "src", pattern: "a.rs"} matched against the project-relative src/a.rs and returned nothing; the pattern is now evaluated relative to path on both the indexed and fallback routes, in one path form on Windows.
  • A deleted file no longer blocks dead-code analysis for its project. Its stale callgraph row survived every refresh because nothing re-evaluated a path that no longer existed, and the projection waited on it forever; refresh now retires rows for proven-absent paths and the health report counts what remains.
  • A fresh git worktree excludes target/ and node_modules/ from the file watcher from its first bind. The eight exclusion slots were filled in .gitignore order, so on this repository the first cargo build in every worktree overflowed the event stream; slots are now seeded by expected volume, and the observed ranking is shared across worktrees of one repository. Windows gets its own watcher backend with overflow reporting.
  • A Tier-2 dead-code pass that overruns its deadline releases its build slot even when the scanner ignores cancellation; a pass that ran for 95 minutes on one worktree had starved index builds fleet-wide. Cancellation is also checked at the scanner's file and rollup boundaries so a cooperative pass returns.
  • Background-task garbage collection no longer quarantines a task whose metadata is being rewritten. A metadata file replaced under every open attempt is a live writer, not a damaged layout, and replay now finishes recovering a session before the detached sweep can see it.
  • Stale inspect caches for projects not seen in seven days are swept; they had accumulated without any retention.
  • Governed gh calls that time out after the request was sent report "outcome unknown, check before retrying" with exit status 87 instead of claiming the command was not run; retrying on that claim posted a duplicate comment.

Changes

  • aft_search ranks identifier-shaped tokens inside natural-language queries through the exact lane, puts declarations first for bare identifiers, renders path:line and the matching line on lexical rows, excludes oversized and binary files from exact matching using the indexer's own eligibility rule, and returns one row per file. On the real-query benchmark, mean reciprocal rank rose from 0.154 to 0.188 with exact and concept recall unchanged.
  • aft_search topK is capped at 50. Ranks past 50 were opened in about one percent of searches while producing more than half of all search output tokens; offset pages beyond the first fifty.
  • Old background-task rows in aft.db are pruned in small batches (terminal, delivered, no watches, over 30 days, layout gone).
  • Health reports carry process I/O counters, the cold-build limiter's slot holders, and Tier-2 pass timings; aft profile --memory no longer labels allocator slack as reclaimable.

Internal

  • A launchd health sentinel for the daemon (scripts/sentinel/) with per-detector fingerprints and cooldowns.
  • Content-addressed index views remain opt-in (views.enabled); this release retires the legacy callgraph refresh on views-on roots after first publication and makes materialization incremental.