Reported by a user running 3.9.20 (official build, path jail active, doctor green).
Symptom
Outside the project root, ctx_read(mode="signatures") returned the full file
with no indication that no compression had happened. From the caller's side a
lossy summary and a verbatim full read are indistinguishable — you pay full-file
tokens believing you asked for a summary. Same session: ctx_delta reported
"no cached version for diff" immediately after a successful mode=full read.
"A silent fallback to full is the bad failure mode — you pay full tokens
believing you asked for a summary."
Root cause
cap_to_raw (tools/ctx_read/core_logic.rs) enforces the #361 anti-inflation
invariant: if the framed/compressed output is larger than the raw file, the raw
file is returned instead. It returned it bare — no mode label, no note. The
same is true of raw_fallback in render.rs (the monotonic guard).
For a verbatim request (full, raw, lines:N-M) that is correct and silent
is right. For a request that asked for a summary (signatures, map,
aggressive, entropy, task, reference) silence is a lie by omission.
Fix (implemented)
A size-gated honesty banner:
[lean-ctx] no compression applied (mode=signatures): output was not smaller
than the file — returning full content (N tok)
Tests: cap_to_raw_labels_silent_fallback_for_compressed_request,
cap_to_raw_stays_silent_for_verbatim_full_request,
cap_to_raw_notice_never_breaks_the_361_cap.
Still open
The exact trigger for the out-of-root case was not reproduced end to end; a
/tmp vs /private/tmp path-normalization mismatch in the cache key is the
leading hypothesis and would also explain the ctx_delta "no cached version"
right after a successful read. Tracked separately if it recurs.
Reported by a user running 3.9.20 (official build, path jail active, doctor green).
Symptom
Outside the project root,
ctx_read(mode="signatures")returned the full filewith no indication that no compression had happened. From the caller's side a
lossy summary and a verbatim full read are indistinguishable — you pay full-file
tokens believing you asked for a summary. Same session:
ctx_deltareported"no cached version for diff" immediately after a successful
mode=fullread.Root cause
cap_to_raw(tools/ctx_read/core_logic.rs) enforces the #361 anti-inflationinvariant: if the framed/compressed output is larger than the raw file, the raw
file is returned instead. It returned it bare — no mode label, no note. The
same is true of
raw_fallbackinrender.rs(the monotonic guard).For a verbatim request (
full,raw,lines:N-M) that is correct and silentis right. For a request that asked for a summary (
signatures,map,aggressive,entropy,task,reference) silence is a lie by omission.Fix (implemented)
A size-gated honesty banner:
counts_as_compressed().NO_COMPRESSION_BANNER_MIN_TOKENS = 400, so the banner cannever itself push a small read above the raw size — Independent benchmark of lean-ctx on a pi/forge agentic workload — request for review before June 17 publication #361 keeps its guarantee
("a read never costs more than the raw file") exactly where it matters.
cap_to_rawandrender::raw_fallback) so theCLI/in-process path and the MCP path behave identically.
Tests:
cap_to_raw_labels_silent_fallback_for_compressed_request,cap_to_raw_stays_silent_for_verbatim_full_request,cap_to_raw_notice_never_breaks_the_361_cap.Still open
The exact trigger for the out-of-root case was not reproduced end to end; a
/tmpvs/private/tmppath-normalization mismatch in the cache key is theleading hypothesis and would also explain the
ctx_delta"no cached version"right after a successful read. Tracked separately if it recurs.