1jehuang / 1jehuang/jcode

Auto-compaction never fires on large-context models (80% of a 1M window = 800k trigger)

Open
#644 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

autonomous: no bug priority: high triage: needs-decision
Dominant language
Rust
Stars
19.9k
Forks
2.3k
Avg merge
2d 7h
Merged PRs (30d)
30

Description

Auto-compaction is unreachable on large-context models: token_budget is the model's full context window, so the 80% trigger sits at 800k on a 1M-context model. A session then never compacts and resends its whole transcript on every provider call.

Mechanism

token_budget is set straight from the provider's context window — crates/jcode-app-core/src/agent.rs:458, agent.rs:622, agent/compaction.rs:213, plus conversation_state.rs:249,312 and model_context.rs:656.

Every trigger is then expressed as a fraction of that budget:

// crates/jcode-compaction-core/src/lib.rs:9
pub const COMPACTION_THRESHOLD: f32 = 0.80;

// crates/jcode-base/src/compaction.rs — reactive
self.context_usage_with(all_messages) >= COMPACTION_THRESHOLD

// crates/jcode-base/src/compaction.rs — proactive
let threshold = COMPACTION_THRESHOLD as f64 * budget;
  • 200k window → trigger at 160k → compacts normally.
  • 1M window → trigger at 800k. Sessions that plateau below that never compact at all.

mode = "proactive" does not help: should_compact_proactively measures against the same 0.80 * token_budget, so it only fires earlier relative to an unreachable ceiling.

There is no config escape hatch. [compaction] has no budget key, and NamedProviderModelConfig::context_window applies only to custom named providers, not the built-in ones.

Impact

This is quiet and expensive. Because each tool call re-sends the full transcript, cost is (context size) x (number of calls) — compaction is what bounds the first term. When it never fires, an agentic session degrades into resending a huge context on every call.

Measured over roughly one day on 0.61.x, same machine, same kind of work:

session model provider calls compactions cache-read tokens
A Opus (1M window) 622 0 124,224,904
B 200k window 559 6 49,796,153

Session A peaked at ~395k context — real usage, but only 40% of a 1M window, so it sat under the 80% trigger for its entire life and compacted zero times. Day total across sessions: 168,106,320 cache-read tokens, 97% on the 1M-window model.

Session B is the control: same codebase, comparable call count, auto-compaction working normally (all outcomes grew=false, e.g. pre_tokens=168790 post_tokens=31107 tokens_saved=137683). Compaction itself is healthy — it just never gets invoked on the large-context model.

Suggested fix

Cap the budget rather than change the threshold, so the trigger stays reachable without misrepresenting the model's real window. A [compaction] max_token_budget: Option<usize> clamped inside set_budget()/with_budget() covers all call sites at one choke point, and None preserves today's behaviour exactly.

fn clamp_budget(&self, budget: usize) -> usize {
    match self.compaction_config.max_token_budget {
        Some(max) if max > 0 && budget > max => max,
        _ => budget,
    }
}

I'm running this locally against be15ad68 with tests (default-uncapped, clamping, under-cap untouched, Some(0) ignored, with_budget parity, a TOML key-binding test, and a behavioural one asserting 400k reads as under-threshold at 1M but over-threshold at a 200k cap). Happy to open a PR if you'd like it in this shape — or if you'd rather derive the cap automatically rather than have users configure it, that seems reasonable too.

Environment

  • jcode v0.61.2-dev (be15ad68), macOS 27.0 arm64
  • [compaction] mode = "reactive" (defaults otherwise)

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the compaction budget call sites in crates/jcode-app-core/src/agent.rs, agent/compaction.rs, conversation_state.rs, and model_context.rs, then inspect set_budget/with_budget and the compaction configuration. Run the mentioned default, clamping, TOML binding, parity, and behavioral tests; done means the cap is optional, clamps large budgets, leaves smaller budgets unchanged, and keeps existing behavior when unset.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
ai, cli
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
65/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.