Complete oversized tool-result spill: safe 5k default, error paths, all result paths (#89) - #91
Merged
Merged
Conversation
|
Bugbot is not enabled for your account, so this pull request was not reviewed. Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs. |
…rrors, all paths Completes the f231bbf spill mechanism per issue #89 (motivated by Mythos unintentionally ingesting a ~42k search result: the old default cap was strategy.maxMessageTokens * 4 — often tens of thousands of chars, or NO cap at all when the strategy declares no maxMessageTokens). - House-safe default inline cap: 5000 chars (DEFAULT_TOOL_RESULT_INLINE_MAX_CHARS), applied even when the strategy declares no bound. - Durable FrameworkConfig.toolResultInlineMaxChars (>= 1000): residence-level cap that survives restarts; clamped down to the strategy bound when that is smaller. The ephemeral agent_settings override still wins outright. - Provenance: agent_settings get now reports tool_result_inline_max_chars_effective and _source (agent-settings-override | framework-config | default, with a strategy-clamped marker). - Error results follow the same spill policy as successes — a giant error string spills to the same tool-results/ file with a bounded preview, byte-matched between history and live wire. - Alternate paths covered: the complete-while-waiting guard path now uses the same bounded builder; background-script wake payloads use the resolved cap (override applies; unknown agent gets the bounded default, never unbounded); the direct-Agent-API path is bounded at the house default for successes and errors. - Native image path: image blocks stay byte-intact; an adjacent oversized text block's truncation notice now references the spill file. - No-writable-workspace fallback states explicitly that full content was not retained. - File lifecycle documented: deterministic <date>-<callId>.txt names, overwrite on collision, retained until the workspace owner deletes them. Out of scope (tracked in #89): adapter-level pre-allocation/byte-bounded reads; connectome-host recipe passthrough (separate Host PR after release). Refs #89 (item 5, adapter byte-bounds, stays open) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
antra-tess
force-pushed
the
issue-89/tool-result-spill-completion
branch
from
August 6, 2026 14:56
ef1d0e3 to
b6d96a6
Compare
Collaborator
Author
|
CI note: both OS jobs fail in Type-check on the pre-existing fresh-install dependency drift — the Chronicle |
Review finding on #91 (opus-rev, confirmed by repro): when a writable workspace exists but the spill write fails (mount maxFileSize, storeBlob failure, ...), spillOrTruncate fell through to the no-workspace return — the agent was told 'no writable workspace, full content not retained', teaching them their residence lacks a capability it actually has, and the catch swallowed the error with no observability. Now: a distinct inline notice naming the attempted path and the (bounded) failure reason, a new 'tool:spill_failed' trace event, and a console error. The genuine no-workspace fallback is unchanged. Also pins the strategy-clamp branch (review finding #4): maxMessageTokens 1000 → effective cap 4000, source 'default (strategy-clamped)' — the branch that decides the cap for every resident on a bounded strategy. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
antra-tess
pushed a commit
that referenced
this pull request
Aug 6, 2026
Carries today's merged work: #91 oversized tool-result spill completion, #94 durable resident-owned inline cap (hard-clamped to the strategy bound), #88 refusal-reaction baseline export, #86 removal of the dead context/afterInference surface, #87 MCPL manifest freshness, #98 physical-window projection for continuation rounds. Minor (not patch) because 0.x puts breaking changes in the minor and this release both removes a public method from an exported class (McplServerConnection.sendAfterInference, #86) and changes fleet default behavior (tool results now spill at 5000 chars by default, #91). Dependency floors raised to fix a build that only worked against local symlinks: - chronicle ^0.3.0 — context-manager 0.6.3 requires ^0.3.0, so ^0.2.2 installed TWO chronicles and AF handed a 0.2.x JsStore to APIs wanting the 0.3.x one. Single copy now. - membrane ^0.5.78 — AF consumes the 'retrying' yielding-stream event, which existed only in unpublished membrane commits until 0.5.78. DEPLOY NOTE: chronicle 0.3.0 open-writes a store format 0.2.x cannot reopen. Take cold backups before upgrading any residence. Verified against the real published packages (not local symlinks): single chronicle 0.3.0, cm 0.6.3, membrane 0.5.78; tsc clean; build clean; 539 tests, 538 pass, 0 fail, 1 skipped. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Addresses #89 (Mythos's accidental 42k ingest). Completes the
f231bbfspill mechanism rather than reimplementing it.What changes
Safe durable default. The inline cap is no longer
strategy.maxMessageTokens * 4(frequently tens of thousands of chars, or unbounded when the strategy declares nomaxMessageTokens— the exact hole the incident went through). Cap resolution is now:agent_settings tool_result_inline_max_charshot override — wins outright, ephemeral (unchanged);FrameworkConfig.toolResultInlineMaxChars— durable residence cap, validated>= 1000atcreate();Non-override values are clamped down to the strategy bound when that is smaller (a message must still fit
maxMessageTokens); the explicit override escapes the clamp, as before.Provenance.
agent_settings getnow reportstool_result_inline_max_chars_effectiveand_source(agent-settings-override | framework-config | default, with a(strategy-clamped)marker). Restart drops the override and keeps the configured cap — pinned by test.One policy on all text-bearing paths.
isErrorpreserved; history and live wire byte-identical.'complete'firing duringwaiting_for_tools) uses the same bounded builder (previously unbounded serialize).undefined→ unbounded.Agent.infer'sbuildToolResultMessages, no framework call sites but public) is bounded at the house default for successes and errors.Image safety. Native image blocks are never character-truncated (unchanged); an oversized text block riding alongside an image now points its truncation notice at the spill file.
Explicit no-workspace fallback. The plain-truncation notice now states
no writable workspace, full content not retainedinstead of looking identical to a recoverable truncation.File lifecycle (issue item 7), documented on the config field: deterministic
tool-results/<date>-<callId>.txtnames, overwrite on collision, retained until the workspace owner deletes them — never auto-GC'd, no silent 'temporary'.Behavior change, deliberately
Fleet agents on strategies with large/absent
maxMessageTokenswill start seeing 5000-char previews + spill files where they previously got the full blob inline. That is the house request in #89. Residences that want more settoolResultInlineMaxCharsdurably or lift per-agent viaagent_settings.Out of scope (stays open in #89 discussion)
toolResultInlineMaxCharsthrough recipe composition, after this lands in an AF release (will open dependency-separated, host#48-style).Tests
New
test/tool-result-spill.test.ts(9): default-5000 spill with full-content file recovery, durable-config cap + provenance, override-wins/reset-restores, giant-error spill with byte-identity, success byte-identity, explicit no-workspace fallback, image-intact + spill-file-referencing wire copy, restart semantics, invalid-config rejection.Full suite: 539/540 pass, 0 fail (1 pre-existing skip). The
mcpl-awareness-barriertiming flake surfaced once under full-suite load and passes in isolation and on re-run — pre-existing cluster, unrelated.🤖 Generated with Claude Code