fabro/lib/components
Bryan Helmkamp b17b8aeaed
fix(agent): refuse to truncate history on a degenerate compaction summary
When the summarization LLM call returned an empty completion, compaction
truncated the conversation anyway. `history.compact_from` discarded the
summarized turns irreversibly, `CompactionCompleted` was emitted as if
nothing had gone wrong, and the replacement system turn contained only the
handoff preamble: "A different assistant began this task and produced the
following summary" followed by nothing.

The agent then continued with zero context while having been explicitly
told a handoff summary existed. It presents to a user as the agent
suddenly forgetting everything, and the only trace was a `debug!` line
that is off by default, so there was nothing in production logs to
correlate against.

This is provider-independent. Any completion that comes back empty
triggers it: a truncated stream, a reasoning model that spends its whole
token budget on reasoning, or a rate-limit edge.

Validate the summary before mutating history. A summary that is empty,
whitespace-only, or shorter than 32 bytes after trimming is refused: the
history is left fully intact and an error is returned instead. The
threshold is deliberately far below any genuine summary — 32 bytes is
shorter than a single source file path — because this guards against
degenerate responses, not summary quality, and a false refusal would let
the context keep growing. Structure is not validated, since a model may
legitimately vary the requested section format.

Returning `Err` is sufficient to surface the failure. `compact_if_needed`
already converts it into an `AgentEvent::Error`, which lands in the run
event stream and logs at ERROR via `AgentEvent::trace`, and the session
continues rather than dying — behavior already covered by
`compaction_failure_is_non_fatal`.

The canned summary in `compaction_includes_structured_prompt_and_file_tracking`
was 26 bytes, which the new guard rejects. That test verifies the
summarization request prompt and file tracking, not minimum summary
length, so its fixture is now a realistic summary.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-24 19:10:13 -04:00
..
fabro-acp refactor: organize crates into three layers 2026-07-23 17:59:34 -04:00
fabro-agent fix(agent): refuse to truncate history on a degenerate compaction summary 2026-07-24 19:10:13 -04:00
fabro-automation refactor: organize crates into three layers 2026-07-23 17:59:34 -04:00
fabro-checkpoint refactor: organize crates into three layers 2026-07-23 17:59:34 -04:00
fabro-dump Merge branch 'main' into feat/shared-checkout-parallel 2026-07-24 06:29:57 -04:00
fabro-environment refactor: organize crates into three layers 2026-07-23 17:59:34 -04:00
fabro-github refactor: organize crates into three layers 2026-07-23 17:59:34 -04:00
fabro-graphviz refactor: organize crates into three layers 2026-07-23 17:59:34 -04:00
fabro-hooks refactor: centralize agent profile tool configuration 2026-07-24 14:06:29 -04:00
fabro-install refactor: organize crates into three layers 2026-07-23 17:59:34 -04:00
fabro-interview refactor: organize crates into three layers 2026-07-23 17:59:34 -04:00
fabro-llm Merge pull request #627 from fabro-sh/fix/openai-compatible-stream-usage 2026-07-24 17:53:45 -04:00
fabro-manifest refactor: organize crates into three layers 2026-07-23 17:59:34 -04:00
fabro-mcp refactor: organize crates into three layers 2026-07-23 17:59:34 -04:00
fabro-mcp-store refactor: organize crates into three layers 2026-07-23 17:59:34 -04:00
fabro-sandbox Merge branch 'main' into feat/shared-checkout-parallel 2026-07-24 06:29:57 -04:00
fabro-slack refactor: organize crates into three layers 2026-07-23 17:59:34 -04:00
fabro-store feat(reasoning): capture provider reasoning in agent.message 2026-07-24 14:21:15 -04:00
fabro-tool refactor: organize crates into three layers 2026-07-23 17:59:34 -04:00
fabro-tracker refactor: organize crates into three layers 2026-07-23 17:59:34 -04:00
fabro-validate Merge branch 'main' into feat/shared-checkout-parallel 2026-07-24 06:29:57 -04:00
fabro-variable refactor: organize crates into three layers 2026-07-23 17:59:34 -04:00
fabro-workflow Merge pull request #626 from fabro-sh/feat/passive-reasoning-capture 2026-07-24 17:49:46 -04:00