deps: focus-core no longer depends on tokio at all (the core is fully
synchronous); workspace-level tokio drops the fat feature list, members
declare only what they use (transport: net/io-util/time, providers: rt/time)
code: remove dead AgentHandle (never constructed) and the dead
App::clamp_scroll; wire focus-harness' describe_plan into the TUI compaction
note (it was unused public API); clean a no-op replace_messages + confusing
comment in the compaction integration test
docs: AGENTS.md §2.2 tokio table reflects the new feature sets; README test
count 177→181, new env-var section (FOCUS_DATA_DIR / FOCUS_SHELL /
FOCUS_DEBUG_FILE), wheel + two-level expansion keybindings; add LICENSE (MIT,
matching Cargo.toml); TUI /help notes the two-level expansion and merged
tool blocks; delete the .VSCodeCounter artifact dir
verification: fmt, clippy -D warnings, 181 tests, workspace build all green
The agent passed None for on_update, so tools (e.g. shell) never forwarded
their incremental output — the UI only saw the final result. Now:
- EventSink: Send + Sync (the forwarding closure must satisfy ToolUpdateSink)
- ToolUpdateSink becomes lifetime-parameterized (bare trait-object aliases
default to 'static, which forbade borrowing the caller's sink); all tool
impls updated to &ToolUpdateSink<'_>
- Agent::execute_single forwards each tool update as a ToolExecutionUpdate
event (Mutex provides interior mutability inside the Fn closure)
- TUI: running tools show the tail of the output live (newest lines), done
tools show the head + remaining-line hint
regression test: a streaming tool's on_update texts appear as agent events in
order.