Skip to content

feat(recommend): pluggable compression candidate planner (MICRO/EPISODE) β€” advisory, executor-parityΒ #166

Description

@ranxianglei

πŸ€– ework agent Β· vllm-qwen/qwen3.8-27b

Problem

The recommend pipeline node emits turn-grouped CompressibleRanges, and the surfaces that display them (nudge-inject, report/acp_status, panel) pair that list with imperative guidance ("compress now", "compress the listed ranges"). Hosts adopting this guidance see over-compression: under nudge pressure (especially at the context limit) the model compresses whole turn-grouped ranges, including reasoning and decisions it still needs. Summaries are lossy, so the agent re-reads files, re-runs commands, or loses task state.

Prior art: opencode-acp PR #341 (feat: add adaptive compression candidates) β€” host-side implementation, under review. The algorithm is host-agnostic and belongs in the kernel.

Proposal

New src/candidates/ module (or extension of recommend.ts):

  • planCandidates({ messages, state, config }) β†’ CandidatePlan { candidates, omitted, truncatedCount }
  • Kinds:
    • micro β€” one large plain message, or one complete tool transaction (reuse tool-pairs.ts pairing for call+result+transitive span closure).
    • episode β€” contiguous historical segment of smaller adjacent units; split at protected units (reuse protected.ts).
  • Structural safety: protected exclusion (protected tools, last user message, recent window), tool-pair closure, minimum size (align with viable.ts VIABLE_RANGE_MIN_TOKENS β€” the kernel's token floor is the right primitive; opencode-acp's char-based minCompressRange maps onto it), deterministic, non-overlapping output, bounded (default cap 12).
  • Pluggability: follow the existing registry pattern (src/search/registry.ts, src/filter/registry.ts) β€” registerCandidatePlanner() / getCandidatePlanner() / listCandidatePlanners(), built-in default micro-episode-v1. Hosts register/replace planners; depend only on the interface.
  • Executor parity: validate each candidate through the same validation path applyCompression runs (the kernel validates the whole batch atomically β€” see the "Summary too short" atomic-rejection incident documented in viable.ts). Guarantee: everything listed is structurally submittable. Planner errors fail closed (surfaces fall back to the current range list).
  • Surfaces: nudge-inject node, report.ts, panel β€” candidates replace/augment the raw range list (supersedes the grouping concern in fix(report): group acp_status uncompressed ranges by conversation turnΒ #165).

Reference implementation

opencode-acp PR #341: lib/messages/inject/candidates.ts (~567 lines) + tests/compression-candidates.test.ts (12 unit tests), tests/compression-candidates-property.test.ts, e2e scenario 13.

Acceptance criteria

  • Deterministic, non-overlapping, bounded; fail-closed on planner errors.
  • Unit + property tests per kernel conventions.
  • No breaking changes: new exports; recommend node unchanged as fallback.

Filed from opencode-acp#341 review (awork bot, on behalf of @Dog).


Mirrored from ework issue #166

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions