Truncating a large tool result to a head+tail preview loses the middle,
which may hold the one line that matters (a buried match, a stack frame, a
credential). Instead of dropping it, persist the full output and let the
agent page back to it on demand.
- output_store.py: bound_and_store() writes the complete output to a
per-scan store and embeds an output_id in the truncation notice;
read_stored_output() serves it back in validated, paginated chunks
(output_id is a 32-char hex token, guarding against path traversal).
- read_tool_output tool: lets the agent retrieve any elided output by id,
paging via offset/limit.
- factory.py: bounded tool results now spill via bound_and_store; the new
tool is registered for every scan agent.
- runner.py: point the store at the run's .state/tool-output directory so
spilled output lives beside the rest of the scan state.
Falls back to a plain head+tail preview if the spill write fails.