Skip to content

v0.36.0

Choose a tag to compare

@github-actions github-actions released this 07 Jun 18:35
· 2838 commits to main since this release

v0.36.0: Persisted call graph, leaner bash output, and sharper code search

The call graph now lives in a persisted, incremental store instead of being rebuilt from scratch on demand. That removes the file-count limit that capped dead-code analysis on large repositories, makes aft_callgraph queries resolve from disk, and improves edge accuracy across more languages. This release also stops shell pipes from hiding test failures, steers agents toward aft_search for code discovery, and fixes a handful of crashes and papercuts.

Persisted call graph (and the end of the file-count cap)

aft_callgraph and aft_inspect's dead-code analysis used to build a whole-project call graph in memory, re-parsing every file on demand. That build was capped at lsp.max_callgraph_files (5000) to avoid the multi-core CPU spikes reported in #86, which meant dead-code analysis simply turned off above that size.

The call graph is now a persisted SQLite store, built once in the background and updated incrementally as files change. Queries read from disk, so callers/callees/impact/trace return without rebuilding anything, and the cold build reuses the symbol cache instead of re-parsing. On this repo the cold build is ~14s; on a 5,700-file TypeScript repo ~13s, after which updates are incremental.

The lsp.max_callgraph_files cap is gone for the call-graph store. Dead-code analysis runs on large repositories again. The cold-build's parsing pass is bounded to half your cores so it can't monopolize the machine while it runs.

More accurate call edges

The store resolves method calls more precisely. It infers receiver types (for self/Self, parameters, and common bindings in Rust, Java, Kotlin, and C++) to produce exact method-dispatch edges, falls back to name matching when a type can't be resolved, and applies a standard-library denylist so calls like .expect() or .map() don't generate thousands of spurious edges. Call extraction now also covers C, C++, C#, and Zig.

Bash output stops hiding failures

Piping a test or build command through a filter, like bun test | grep fail or cargo test | grep -A3 FAILED, used to strip the output down before AFT's compressor ran, which often threw away the failure detail and summary you actually wanted. When output compression is on, AFT now recognizes that pattern, runs the command without the trailing filter, and lets the compressor keep the failures and summary. This also works through a leading cd <dir> && ... prefix. Pass compressed: false to keep your pipe verbatim.

Sharper code search steering

Agents reach for grep/rg/find in bash out of habit even when AFT's indexed search is faster and better ranked. Workflow guidance and the per-command hints now steer code discovery to aft_search and the other aft_* tools, run in parallel, and when aft_search is available the grep-rewrite footer points there instead of suggesting the grep tool.

Status bar accuracy

The E/W (errors/warnings) counts in the agent status bar are now filtered to the same build membership aft_inspect and tsc use, so files excluded from your tsconfig (test files, build output) no longer inflate the count with diagnostics that your compiler would never report.

Fixes

  • foreground_wait_window_ms had no effect (#102): a small timeout passed to a foreground bash call collapsed the wait window and could kill the command almost immediately. A foreground timeout below the wait window is now ignored (the command runs to the normal window, then promotes to background), while an explicit background: true task still honors a short timeout as a real kill cap.
  • aft_delete and aft_safety checkpoint could crash on a mistyped argument: when a host delivered the files array as a bare string or a JSON-encoded string, the tool threw inputs.map is not a function before doing anything. The argument is now coerced at the boundary, so it works or returns a clear error instead of crashing.
  • Trailing newline is preserved in compressed terminal output instead of being dropped from the last line.
  • Call-graph lookups no longer show as tool errors in the UI when a symbol isn't found or the store is still building; they return a normal result.
  • Semantic index no longer hammers a slow embedding backend with fixed-interval retries; refresh retries back off and trip a circuit breaker.

Thanks to @de-flandres (#102, pinpointing the wait-window override).

Join our Discord