pub struct ReductionPolicy {Show 28 fields
pub tool_output_keep_bytes: usize,
pub tool_output_trigger_bytes: usize,
pub protect_last_n_tool_results: usize,
pub elide_stale_reads: bool,
pub redact_images: bool,
pub image_redact_min_bytes: usize,
pub clear_turns_older_than: Option<usize>,
pub read_freshness: ReadFreshness,
pub diff_rereads: bool,
pub diff_max_percent: u32,
pub protect_imported_prefix: Option<usize>,
pub elide_tool_inputs: bool,
pub tool_input_trigger_bytes: usize,
pub tool_input_elidable_fields: HashMap<String, String>,
pub normalize_terminal_output: bool,
pub terminal_output_min_savings: usize,
pub duplicate_output_min_bytes: usize,
pub deduplicate_outputs: bool,
pub supersede_enabled: bool,
pub supersede_protect_last_n: usize,
pub supersede_min_bytes: usize,
pub supersede_command_fields: HashMap<String, String>,
pub prune_errored_inputs: bool,
pub errored_input_prune_after_turns: usize,
pub summarize_cleared_turns: bool,
pub expected_summary_bytes: usize,
pub summary_cost_floor_multiple: usize,
pub cleared_turns_summary: Option<PreparedClearSummary>,
}Expand description
Knobs controlling project_messages. Defaults match SPEC.md A5/A7, stacked per
D14 with the levers that don’t need an external I/O probe to be safe
on-by-default (redact_images; contrast elide_stale_reads, below).
elide_stale_reads (A8) and clear_turns_older_than (A10) are plumbed
through the struct but inert by default — elide_stale_reads needs a
freshness probe (probe_read_freshness) to mean anything, and
clear_turns_older_than is populated per-agent from
compact_after_messages (Agent::maybe_compact), not from this default.
Fields§
§tool_output_keep_bytes: usizeBytes kept from the front of an oversized tool result (A7). Default
4096.
tool_output_trigger_bytes: usizeOnly tool results strictly larger than this are truncation candidates
(A7). Default 8192.
protect_last_n_tool_results: usizeNever reduce the newest N tool results (#1 “keep”). Default 3.
elide_stale_reads: boolA8 — gate for stale-file-read elision. Consults
Self::read_freshness for the actual per-message verdicts; setting
this without ever populating read_freshness (via
probe_read_freshness) elides nothing, since the empty default
freshness map treats every read as not-yet-verified.
redact_images: boolA9 — gate for data: URL image redaction. Default true (D14:
reduced mode stacks every lossless lever on together) — unlike
elide_stale_reads, this rule is a pure function of the message
content already in view, so it carries none of A8’s “meaningless
without a probe” caveat and can safely default on.
image_redact_min_bytes: usizeA9 — minimum byte length of a candidate image_url part’s url
string for it to become a redaction candidate; inert unless
redact_images is set. Default 8192 (mirrors
tool_output_trigger_bytes’s scale: small inline icons stay in view,
real screenshots/photos get redacted).
clear_turns_older_than: Option<usize>A10 — inert until turn-clearing lands.
read_freshness: ReadFreshnessA8 — the disk-probe pre-pass’s output (probe_read_freshness),
consulted by project_messages only when Self::elide_stale_reads
is set. This is data, not a config knob: it is meant to be
recomputed by the caller before every project/project_messages
call (disk state can change turn to turn) — project_messages itself
never performs the I/O; that happens once, up front, in
probe_read_freshness. Default: empty (fails closed — nothing is
considered fresh without an accompanying probe).
diff_rereads: boolTR-3 (T26) — gate for diff-only re-read representation
(ReductionKind::FileReadDiffed). Like redact_images (and unlike
elide_stale_reads), this rule is a pure function of the message
content already in view — a re-read’s content compared against the
prior read of the same path recorded in log.read_log — with no
disk-probe caveat, so it can safely default on. Default true.
diff_max_percent: u32TR-3 — a candidate diff must be no more than this percentage of the
full re-read’s size to replace it; otherwise the full re-read stays
untouched (SPEC.md TR-3 dev/03’s “large-change guard”). An integer
percentage (rather than a float) so ReductionPolicy keeps its
Eq derive (f64 has none). Default 50 (“diff ≤ 50% of full
content”).
protect_imported_prefix: Option<usize>B7 coordination clamp: when an imported-prefix cache plan is
active, the count of leading messages (of the slice passed to
project_messages) that make up the imported session prefix. A10
turn-clearing must never establish a clear range that dips into them,
since doing so would bust the prefix’s cache breakpoint (and its
fidelity). None (the default) applies no clamp, matching today’s
behavior for callers that never set a cache plan. Set by a runtime
agent from its own imported_prefix_len, not a
user-facing knob.
elide_tool_inputs: boolTR-10 — gate for tool-INPUT elision (ReductionKind::ToolInputElided).
Default true. Unlike elide_stale_reads, the candidate rule
(executed successfully + oversized payload + a disk-persisting tool)
is a pure function of the view plus Self::tool_input_elidable_fields
— no external disk probe is needed to decide elision itself (a probe
only matters later, for the freshness-matrix ESCALATION decision, see
probe_tool_input_fresh) — so, like redact_images, this can
safely default on (D14: reduced mode stacks every lossless lever
together).
tool_input_trigger_bytes: usizeTR-10 — only a candidate tool_call’s payload field whose value
exceeds this many bytes becomes an elision candidate. Default 8192
(mirrors A7/A9’s scale).
tool_input_elidable_fields: HashMap<String, String>TR-10 — table of tool name -> its elidable (disk-persisted) payload
argument field. Defaults to the built-in write-family tools
(write_file -> content, see default_tool_input_elidable_fields);
an MCP tool opts in by inserting its own (name, field) entry
(SPEC.md TR-10: “per-MCP-tool opt-in”).
normalize_terminal_output: boolT30/TR-4 — gate for ReductionKind::OutputNormalized (ANSI/redraw
collapse over terminal tool output). Default true: like
redact_images, this is a pure function of already-in-view content
(no I/O probe needed) and content-lossless (rendered CONTENT is fully
preserved, only presentation bytes are removed), so it stacks on by
default per D14.
terminal_output_min_savings: usizeT30/TR-4 — minimum byte savings (original_bytes - normalized_bytes)
for a candidate to actually become an
ReductionKind::OutputNormalized reduction; below this floor the
output is left untouched rather than raced through the reduction
machinery for a few bytes (SPEC.md TR-4’s “savings floor” knob).
Default normalize::DEFAULT_MIN_SAVINGS.
duplicate_output_min_bytes: usizeTR-2 — minimum byte length of a duplicate tool-result candidate’s
content for it to become a ReductionKind::DuplicateOutput
candidate. Below this, both the canonical and the would-be duplicate
are left alone: a stub’s own bytes are not free, so deduping a tiny
output would spend more than it saves (the “savings floor”). Default
256.
deduplicate_outputs: boolTR-2 — gate for ReductionKind::DuplicateOutput. Default true:
duplicate detection is a pure function of the recorded tool outputs,
so it stacks on in ordinary reduced mode. Composable capability
profiles can disable it without changing the savings-floor knob.
supersede_enabled: boolTR-6 (T16) — gate for ReductionKind::Superseded (same tool + same
canonicalized arguments, keep only the newest result). Default
true: like redact_images/elide_tool_inputs, the candidate rule
is a pure function of the view plus Self::supersede_command_fields
— no external disk probe needed — so it stacks on by default (D14).
supersede_protect_last_n: usizeTR-6 — protected recency zone (opencode’s PRUNE_PROTECT spirit): the
newest N tool RESULT messages (by position, mirrors
Self::protect_last_n_tool_results’s own construction) are never a
new Superseded candidate, regardless of how many older same-key
occurrences exist. A DEDICATED knob rather than reusing
protect_last_n_tool_results — TR-6.md’s spec calls this out as its
own independently tunable “protected recency zone,” and the two
passes run at different points in the pipeline (Superseded runs
before A7 truncation ever computes its own candidates). Default 3
(mirrors protect_last_n_tool_results’s own default).
supersede_min_bytes: usizeTR-6 — minimum byte length of a superseded-candidate’s OWN content for
it to become a ReductionKind::Superseded candidate (the “savings
floor,” mirrors Self::duplicate_output_min_bytes). Below this the
older result is left untouched — a stub’s own bytes are not free.
Default 256.
supersede_command_fields: HashMap<String, String>TR-6 — table of tool name -> its command-bearing argument field (e.g.
bash/shell/exec_command -> "command"), consulted by
supersede::canonical_key to canonicalize (trim + collapse internal
whitespace) just that one field’s value rather than the whole
arguments string. A tool absent from this table still participates in
supersession — its whole (trimmed-only) arguments string becomes the
key — this table only controls whitespace-collapse scope, not
eligibility. Defaults to supersede::default_command_fields.
prune_errored_inputs: boolTR-6 — gate for errored-call input pruning: a FAILED tool call’s
oversized payload argument (Self::tool_input_elidable_fields,
shared with TR-10) becomes a ReductionKind::ToolInputElided
candidate once Self::errored_input_prune_after_turns assistant
turns have elapsed since the failed call — the disjoint, FAILURE-side
complement of TR-10’s elide_tool_inputs (which only ever considers
SUCCESSFUL calls; see detect_tool_inputs’s own doc comment for the
success/failure boundary). The failed call’s own error-result message
is never touched by this — only the assistant-side input argument —
so the error itself stays visible exactly as TR-6.md requires. Default
true (pure function of the view + the age clock, no I/O probe
needed, D14).
errored_input_prune_after_turns: usizeTR-6 — how many LATER Role::Assistant messages must appear after a
failed call’s own message before its oversized input becomes a
pruning candidate (the “N turns” aging clock in TR-6.md’s errored-call
case) — a message-count proxy for “turns elapsed,” the same
convention Self::clear_turns_older_than (A10) already uses (this
codebase has no other structural definition of a conversational
turn). Default 3.
summarize_cleared_turns: boolTR-7 (T20) — the summaries: on|off config knob: gate for rendering
an established ReductionKind::TurnsCleared span’s placeholder as
an LLM-generated summary paragraph instead of the deterministic
[turns cleared] stub. Default false — SPEC.md TR-7 dev/01:
with this off, the A10 stub must stay byte-identical to pre-TR-7
behavior, so project_messages never even looks at
Self::cleared_turns_summary while this is unset, regardless of
what a caller precomputed. Turning this on with no matching
Self::cleared_turns_summary entry (e.g. the side-call was never
run, or failed) is exactly as safe: the deterministic stub is still
what gets rendered (dev/03’s failure-fallback guarantee).
expected_summary_bytes: usizeTR-7 — cost-guard floor (dev/05): a candidate cleared span’s ORIGINAL
byte size (the same range_bytes the deterministic stub’s own
summary clause already reports) must exceed
expected_summary_bytes * summary_cost_floor_multiple before
prepare_cleared_turns_summary ever calls the injected
summarize::SpanSummarizer — below the floor, a summarization
side-call would be negative-ROI (the stub it replaces is already
small) and is skipped outright, never attempted. Default 400
(a rough paragraph-sized estimate).
summary_cost_floor_multiple: usizeTR-7 — see Self::expected_summary_bytes; the floor multiplier.
Default 4 (the span must be at least ~4 summaries’ worth of bytes).
cleared_turns_summary: Option<PreparedClearSummary>TR-7 — the side-call preparer’s output
(prepare_cleared_turns_summary), consulted by
project_messages only when Self::summarize_cleared_turns is
set AND the prepared entry’s (first, last) matches EXACTLY the
range project_messages independently (re)computes for this call —
any other prepared entry (stale, wrong range, or simply absent) is
silently ignored and the deterministic stub is rendered instead. This
is data, not a config knob (mirrors Self::read_freshness):
recomputed by the caller (via prepare_cleared_turns_summary, the
one place TR-7’s side-call happens) before every
project/project_messages call that might establish a NEW
TurnsCleared range. Default: None.
Trait Implementations§
Source§impl Clone for ReductionPolicy
impl Clone for ReductionPolicy
Source§fn clone(&self) -> ReductionPolicy
fn clone(&self) -> ReductionPolicy
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for ReductionPolicy
impl Debug for ReductionPolicy
Source§impl Default for ReductionPolicy
impl Default for ReductionPolicy
Source§fn default() -> ReductionPolicy
fn default() -> ReductionPolicy
impl Eq for ReductionPolicy
Source§impl PartialEq for ReductionPolicy
impl PartialEq for ReductionPolicy
impl StructuralPartialEq for ReductionPolicy
Auto Trait Implementations§
impl Freeze for ReductionPolicy
impl RefUnwindSafe for ReductionPolicy
impl Send for ReductionPolicy
impl Sync for ReductionPolicy
impl Unpin for ReductionPolicy
impl UnsafeUnpin for ReductionPolicy
impl UnwindSafe for ReductionPolicy
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.