Harden context token tracking and improve tool result management#40
Merged
Conversation
added 7 commits
June 1, 2026 20:32
- Default MaxInTurnToolPairs to 12 when MaxContextTokens is set; without this, tool results accumulate O(N²) within a turn for budgeted agents that omit explicit in-turn limits - ShouldCompact (window mode) uses Usage.TotalTokens when available so reasoning tokens stripped from Content are counted toward the budget - AccumulateCompactedUsage folds all compacted-turn costs onto the summary message across every compaction path, keeping MaxTotalTokens accurate after resume cycles - TransitionAlreadyFired distinguishes blocked markers from fired ones so an A→B contract failure no longer suppresses the independent A→C signal
- Corrections injected mid-session were silently dropped for Context-spec agents because AssembleForAgentAsync bypasses shared-history replay; ExtractPendingCorrections re-injects any correction messages that appear after the agent's last assistant turn so retries always see the feedback - MaxTailMessages cut by raw position, so earlier corrections on long histories could fall outside the retained window; step 4 now pins correction messages and applies the tail limit only to non-pinned messages, preserving original order - IsCorrectionMessage is public so both paths share the same detection logic (prefix table + [fuseraft:blocked substring)
- Global MaxToolResultChars cut search/grep at the same limit as file reads; ToolResultCharOverrides lets callers raise the cap per tool without relaxing the global default - ToolCallRecord entries were silently lost for compacted turns; AccumulateCompactedToolCalls now wires them into all five summary paths so telemetry and BuildModifiedFilesNote stay accurate
- AgentOrchestrator: add EstimateContextTokens helper and a pre-turn budget guard that aborts before agent.RunAsync when cumulativeTokens + estimated input tokens > MaxTotalTokens, preventing expensive one-turn overshoots. - CompactionConfig: raise AntiThrashWindow default from 3 to 10 so a single productive compaction no longer resets the guard in long sessions. - CorrectionEngine / GraphOrchestrator: add optional turnToolCalls parameter to InjectNoKeywordCorrection; the no-tool-calls gate also checks AgentMessage.ToolCalls so SubAgentPlugin responses are not misclassified as stagnation.
- intent mode silently downgraded when intentLog is null; agents resuming after compaction had no signal the summary was degraded — now prepends a visible COMPACTION WARNING block and emits a startup LogWarning when Compaction.Mode=intent but no IntentLogPath is configured - patch_file / create_directory / delete_directory / set_permissions / copy_file / move_file bypassed sandbox boundary check when no FileSystemPermissions globs were configured; added SandboxedExtendedWriteFunctions so these always route through InspectFileSystem regardless of glob state - verifier post-turn block only fired on EveryNTurns; TriggerOnSuspiciousTransition had no effect outside StateMachineSelectionStrategy — wired HasSuspiciousTransitionSignal to detect ConflictingEvidence/NoProgress corrections injected by SelectAsync and trigger the verifier immediately; pins EVIDENCE INCONSISTENCY / EVIDENCE AUDIT REQUIRED / MISSING ARTIFACT in CorrectionPrefixes so they survive MaxTailMessages trim - expose ReadSessionContextAsync on ContextAssembler and auto-inject session context summary for agents without an explicit Context spec - default IncludeReasoning and IncludeSymbolGraph to true; add MaxReplayChars to ContextWindowConfig with per-agent TruncateAssistantContent step in Apply
- IncludeReasoning and IncludeSymbolGraph now default to true; docs reflected the old false defaults, which would mislead users who expect opt-in behavior - AntiThrashWindow default raised from 3 to 10 to prevent a single productive compaction from prematurely resetting the guard on long sessions - MaxReplayChars and ToolResultCharOverrides are new ContextWindow fields; omitting them from the reference left the per-agent replay-truncation and per-tool cap-override knobs undiscoverable - Security sandbox table was missing the extended write functions (patch_file, create_directory, etc.) whose sandbox enforcement was just fixed to fire even when no FileSystemPermissions globs are configured
- ShouldCompact was summing Usage.TotalTokens (cumulative API call cost per turn, growing quadratically) while TrimToWindow used chars/4; the trigger could fire repeatedly while the trim found nothing to drop, producing a stuck compaction loop in window mode - Both now use chars/4, matching the TokenBudget calibration documented in CompactionConfig and sessions.md
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.
Summary
Type of change
Testing
./build.sh --target=Test)config/examples/updated if config schema changed