# v0.38.0: Code Health you can trust

Dead code and unused exports are back on the dashboard, rebuilt on a real analysis engine. Plus: tools stay responsive while your project compiles, `trace_data` moves to the persisted call-graph store, and Pascal joins the language table.

## Dead code and unused exports, rebuilt on oxc

In v0.35.3 we pulled dead-code and unused-export numbers from the sidebar and status displays because they over-reported — barrel re-exports, package entry points, and dynamic imports produced false positives we weren't willing to show. This release replaces the TypeScript/JavaScript analysis with a real module-graph engine built on [oxc](https://oxc.rs): scope-aware export liveness, barrel and re-export chains, `package.json` entry-point resolution, tsconfig-aware module resolution, and dynamic-import handling.

On AFT's own repository the unused-export count dropped 62% — and the survivors check out as genuinely dead when inspected by hand. Both categories are live again in the TUI sidebar, `/aft-status`, `aft_inspect`, and the agent status bar.

Honest framing, per language: TS/JS findings are import-graph verified by the new engine. Findings for other languages still come from the call-graph analyzer, which can over-report dynamic dispatch targets (trait methods, interface implementations) — those upgrades are next on the roadmap, and results remain labeled by language so you can weigh them accordingly.

The engine also reports its own gaps: files it could not parse and files outside the analysis root are listed in `aft_inspect` output instead of being silently skipped.

## Tools stay responsive during builds

Filesystem event processing moved off the bridge's request thread. Previously, a compile writing thousands of files (cargo's `target/`, webpack output) could queue tool calls behind a flood of watcher events — requests timed out at 30 seconds while the bridge chewed through events. Events are now received, filtered, and coalesced on a dedicated thread; the request loop only ever sees the handful of source files that actually changed. Tool calls answer in milliseconds mid-build.

## trace_data on the call-graph store

`aft_callgraph` op=`trace_data` now projects from the persisted call-graph store like the other five ops, instead of re-walking files with the legacy engine. Cross-file value flows resolve through the store's type-aware edges, recursive functions trace correctly, and results come back from an index instead of a parse.

## Pascal support

`.pas`/`.pp`/`.dpr` files now work in `aft_outline`, `aft_zoom`, and the AST tools (`ast_grep_search`/`ast_grep_replace`) — programs, units, classes, procedures, and functions extract with correct ranges. (#109)

## Ctrl-C and shutdown behavior

AFT's signal handling now follows a strict contract: if AFT is the only SIGINT/SIGTERM listener in the host process, it owns termination — cleanup runs with a 5-second cap and the process exits with the conventional signal code. If other plugins or the host also listen, AFT cleans up and defers termination to them — and logs *which* listeners it deferred to, by name, so a hung Ctrl-C is attributable from the log instead of requiring a debugging session.

## Status panel reliability

- The TUI sidebar no longer loses its connection permanently after heavy host load: clients only remove a server's port file when its process is provably dead, and the server re-publishes its port file every 15 seconds if it goes missing. (#110)
- Transient environment problems (a JSON schema fetch timing out, a registry being unreachable) no longer count as code errors in the status bar or `aft_inspect` summaries. They remain visible in detail rows, tagged `[environmental]`.

## Bash output protection: chained commands

The pipe protection that keeps `bun test | grep fail` from hiding failures now handles command chains: `cd pkg && bun test | tail -3 && bun run typecheck | tail -1` gets each segment's noise filter stripped independently, with the same fail-closed rules — comments, redirections, substitutions, and side-effectful filters leave the command untouched.

## Fixes

- **`edit` honors `occurrence: 0`** — the first-match selector was treated as an empty parameter and re-prompted with `ambiguous_match`.
- **Error responses no longer leak status-bar internals** — structured tool errors carried a `status_bar` data block meant for transport, not for the agent.
- **Cloning a repository you already have no longer corrupts the original's call-graph cache** — two checkouts of the same repo now build per-clone stores instead of re-rooting each other's metadata back and forth.
- **Analysis caches distinguish `.ts` from `.tsx`** — identical content parsed under different grammars no longer shares a cache entry.
- **`aft_inspect` scoped to a directory reports scope-accurate language breakdowns** instead of project-wide ones.

---

Questions or feedback? Join us on [Discord](https://discord.gg/DSa65w8wuf).
