The generalization of #409 (merged path: PR #436), and the core of graff's answer to prime-agent's "context as variables" — without adopting a Python kernel.
Today: .graff/tool-results/ keeps full tool outputs at execution time with a ~2KB preview, and #409 spills at the send-time cap. But the default contract is still "tool output goes into context in full until something truncates it".
Proposal — handles by default: any tool result crossing a size threshold returns, uniformly and at tool time: a bounded preview + a durable handle (path) + byte count + a one-line shape hint (line count, JSON top-level keys). The model slices what it needs via read_file/grep/bash over the handle instead of carrying the whole payload turn after turn. The threshold is a knob; meta-tools and small results are untouched.
Why this beats cap-time spilling alone: the cap only rescues bytes at the moment of overflow; handles-by-default means a big result never occupies context in the first place — the same economics as prime-agent's kernel namespace, using the filesystem as the namespace and bash as the REPL, which graff already has.
Pairs with #411 (post-compaction note should list live handles) and the append-only transcript issue. Prompt guidance for the handle contract belongs in a gated segment per #421's structure.
The generalization of #409 (merged path: PR #436), and the core of graff's answer to prime-agent's "context as variables" — without adopting a Python kernel.
Today:
.graff/tool-results/keeps full tool outputs at execution time with a ~2KB preview, and #409 spills at the send-time cap. But the default contract is still "tool output goes into context in full until something truncates it".Proposal — handles by default: any tool result crossing a size threshold returns, uniformly and at tool time: a bounded preview + a durable handle (path) + byte count + a one-line shape hint (line count, JSON top-level keys). The model slices what it needs via read_file/grep/bash over the handle instead of carrying the whole payload turn after turn. The threshold is a knob; meta-tools and small results are untouched.
Why this beats cap-time spilling alone: the cap only rescues bytes at the moment of overflow; handles-by-default means a big result never occupies context in the first place — the same economics as prime-agent's kernel namespace, using the filesystem as the namespace and bash as the REPL, which graff already has.
Pairs with #411 (post-compaction note should list live handles) and the append-only transcript issue. Prompt guidance for the handle contract belongs in a gated segment per #421's structure.