feat(core): context compression — Focus Agent, SWE-Pruner/COMI, SideQuest (#1850, #1851, #1885)#1900
Merged
feat(core): context compression — Focus Agent, SWE-Pruner/COMI, SideQuest (#1850, #1851, #1885)#1900
Conversation
…uest (#1850, #1851, #1885) Adds three context compression subsystems behind the `context-compression` feature flag. Focus Agent (#1850): - Native tools `start_focus(scope)` and `complete_focus(summary)` bracket a task window - `complete_focus` truncates history to the UUID-based checkpoint, synthesises a pinned Knowledge block from the summary that survives all compaction (S1, S4 fixes) - `/focus status` slash command; `FocusConfig` in `[agent.focus]` SWE-Pruner / COMI (#1851): - `PruningStrategy` enum: Reactive | TaskAware | Mig | TaskAwareMig - TF-IDF–weighted Jaccard similarity with Rust/shell stop-word list (S2) - MIG = relevance − redundancy; blocks with negative MIG evicted first - Task goal cached by last-user-message hash; re-computed only on hash change (S5) - Configured via `[memory.compression] pruning_strategy` SideQuest (#1885): - `SidequestState` tracks up to `max_cursors` largest tool outputs - Every `interval_turns` user turns a 5-second LLM call selects stale outputs - Eviction capped by `max_eviction_ratio`; guards: focus-active, compaction-cooldown, pinned-message protection, JSON-parse fallback, cursor size/token filters (S3) - `/sidequest status` slash command; `SidequestConfig` in `[memory.sidequest]` Test count: 6027 (+35 new unit tests across sidequest, compaction_strategy, focus modules).
#1900) Correctness: - C1: set compacted_this_turn=true in complete_focus and maybe_sidequest_eviction - C2: reset compacted_this_turn BEFORE sidequest tick so it sees a clean slate - S4: extract prune_tool_outputs_oldest_first() to break infinite recursion in scored fallback - S5: checkpoint message now has focus_pinned=true so compaction cannot destroy it Security: - SEC-CC-01: append_knowledge() enforces max_knowledge_tokens via FIFO eviction - SEC-CC-02: build_eviction_prompt() prefixes untrusted content boundary - SEC-CC-03: focus summary sanitized as WebScrape (ExternalUntrusted) not ToolResult Performance: - PERF-1: maybe_sidequest_eviction() is now non-async, two-phase: apply last turn's JoinHandle result via now_or_never(), spawn next turn's LLM call in background Tests (16 new): - T-CRIT-01/02/03: pinned message skipping, handle_focus_tool, scored pruning - T-HIGH-01/02/03: guard conditions, rebuild_cursors, tf_weighted_similarity scoring - T-MED-01/03: config validation for SidequestConfig/FocusConfig, feature-gate guard - SEC-CC-01/02 tests: token cap eviction, untrusted boundary in prompt Minor: - S1: tracing::warn when sidequest + non-Reactive strategy both enabled - S3: rename weighted_similarity -> tf_weighted_similarity (no IDF component) - default.toml: align commented defaults with FocusConfig field defaults
5 tasks
Owner
Author
|
Code review complete (rust-code-reviewer agent). All validator findings verified in code:
Follow-up issue #1904 created for deferred integration points (CLI flags Ready to merge. |
- Add explicit `use std::collections::HashMap` in compaction_strategy tests so LSP resolves the type without requiring the context-compression feature - Gate FocusState struct, impl, and KNOWLEDGE_BLOCK_PREFIX with cfg_attr(not(feature = "context-compression"), allow(dead_code)) so clippy passes without the feature flag - Gate is_active with allow(clippy::unused_self) since &self is required for API consistency even when the non-feature branch returns a constant - Gate ToolOutputCursor struct and SidequestState struct/impl with the same cfg_attr pattern for the same reason - Add cfg_attr(not(feature = "context-compression"), allow(unused_mut)) on tool_defs binding in native.rs — mut is only needed when the feature is enabled for focus_tool_definitions injection
Owner
Author
|
Fix pushed (460065a): added |
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
start_focus/complete_focustools bracket task windows;complete_focustruncates history to UUID-based checkpoint and pins a Knowledge block that survives all compactionPruningStrategyenum with TF-IDF–weighted Jaccard scoring and MIG (relevance − redundancy) eviction; task goal cached by user-message hashCritic gap fixes
compact_context()andprune_tool_outputs()skipfocus_pinnedmessagescompaction_strategy.rspruning_strategy != Reactivecomplete_focususes UUID marker; returns error to LLM if marker not foundNew files
crates/zeph-core/src/agent/focus.rs— Focus Agent state, tool definitions, Knowledge block managementcrates/zeph-core/src/agent/sidequest.rs— SideQuest cursor tracking and eviction logiccrates/zeph-core/src/agent/compaction_strategy.rs— TF-IDF scoring and MIG pruning (feature-gated)Configuration
Test plan
cargo +nightly fmt --checkpassescargo clippy --workspace --features full -- -D warningspasses (0 warnings)cargo nextest run --workspace --features full --lib --bins— 6027/6027 passed (+35 new unit tests)origin/main(fast-forward, no conflicts)