Docs/Configuration

Configuration

Every setting, its default, and the reasoning behind that default.

rose config with no arguments dumps everything; one argument reads a dotted key; two set it. Any key can be overridden per-run by an environment variable: recall.max_pack_tokensROSE_RECALL_MAX_PACK_TOKENS.

Ablations#

recall.strategy exists so the descent policy can be measured rather than asserted:

rose config recall.strategy stepwise      # baseline: walk children, ignore deltas
rose config recall.strategy delta-jump    # replace apex with the holder node
rose config recall.strategy delta-patch   # default: apex + matched claims only

Every setting#

Generated from rose/config.py when the docs are built, so it cannot drift from the code the way a retyped table does — and did.

SettingDefaultWhat it is for
version1
agentclaudedefault backend: claude | codex | mock
modelnullNone -> backend default
recall.enabledtrue
recall.strategydelta-patchdelta-patch | delta-jump | stepwise
recall.max_pack_tokens1200
recall.max_families3how many lessons to inject per prompt
recall.judge_calls2Model calls the walk may spend descending. The first pass over the top level is not drawn from this — it is sized by how many chunks the apex layer needs, because a chunk skipped there is a lesson that can never be retrieved.
recall.fanout12Lessons shown to the model in one question. Wide levels are split across several; this is about answer quality, not budget.
recall.parallel4Chunks of one level put to the model at the same time. They are independent questions about disjoint sets, and each costs ~15s of which ~5s is process startup, so asking them in turn makes the top level unaffordable exactly as the store grows: six chunks sequentially exceeds the recall timeout and serves nothing. This is what makes covering every lesson possible rather than aspirational.
recall.max_depth2how far down the tree the walk may look
recall.max_expansions3
recall.filter_above3Apexes below which recall serves everything without asking. There used to be no count here, only a token budget, justified as "judgement is only needed under scarcity". That was wrong about cost: measured over 57 prompts on a store that fit the budget, 15,917 of ~17,800 injected tokens went unused, and judging those same sets kept every lesson that mattered while dropping 55% of the noise. Context that fits is not context that is free. It was right about latency, which is the part that cannot be argued away: a routing call costs ~5s of CLI startup alone and ~34s on the model that routes well, in a hook that blocks the user's prompt. So a gate stays — but a small one, sized so that what it lets through is a few lines rather than a page. Three lessons served blind is cheaper than five seconds of waiting; twenty is not.
recall.warm_prefix_above_tokens2000Candidate-list size above which routing seeds a reusable conversation instead of re-sending the list every prompt. Providers serve an identical prefix from cache at roughly a tenth of the price, but only within one conversation — and seeding costs an extra round trip, so below this the trick loses money. It is set for where the design has to work rather than where it is: at 5,000 lessons the list runs to ~225k tokens per prompt and re-sending it is not survivable.
recall.min_cacheable_tokens1200Smallest prefix a provider will open a cache entry for. Below it, seeding writes nothing and every fork misses — so when warming is on, candidate chunks are widened until they clear this. Roughly 1024 for the larger models and 2048 for the smallest; 1200 leaves margin without making the questions much wider than they need to be.
recall.modelnullModel for the routing decision. Null means "same as everything else", and that is the measured right answer despite looking wasteful. Choosing which of two dozen one-line summaries bear on a prompt looks like a classification job a small model should win, and it blocks the user's prompt, so the incentive to downgrade it is strong. rose eval-recall says don't: model precision recall noise tok default 48% 100% 7,146 sonnet 35% 81% 9,781 haiku 35% 75% 8,818 Both small models serve more noise and drop useful lessons. Since serving everything unfiltered has 100% recall by construction, a cheap router is strictly worse than no router at all — it costs latency, loses lessons, and does not even save context. Set this only with an eval run to back it.
recall.stays_fresh_turns8Turns for which an already-injected lesson counts as still present and attended to. Inside it, a repeat is skipped; beyond it, the lesson is refreshed with its one-line gist rather than repeated in full. Context compaction resets this, since compaction may have removed the text.
recall.timeout_s20Bound on the routing call, kept below the hook's own deadline so a slow judgement degrades to "inject nothing" instead of being killed.
recall.selectoragenticHow selection is made. agentic: fork the live session and let it search the store. The only option whose cost does not grow with the number of lessons — the index is grepped, never sent — and the only one that sees the task's tool calls and reasoning rather than just its opening sentence. judge: render the apex layer into one question and walk it. Costs ~55 tokens per apex per prompt, which is ~225k at 5,000 lessons. judge is not dead code: it is the baseline every arm of rose eval-recall is compared against, and the automatic fallback whenever there is no session to fork.
recall.selector_timeout_s60Longer than timeout_s because a search is several tool calls rather than one question, and each costs a round trip. This is the number that decides whether selection is felt as lag, so it is also the first thing to lower if it is. Raised from 45 after a migrated store timed out: a library imported verbatim holds lessons of several thousand tokens, and one whole-file read of one of those can exhaust the window on its own. The prompt now steers toward grep-with-context for that reason; this is the headroom for when it still needs a look.
recall.selector_max_tool_calls6Searches the selector may run before it must answer with what it has. An unbounded search is the failure mode here: there is always another phrasing to try, and the user is waiting the whole time.
routing.enabledtrueSelection lessons: what the reflector learned about where the knowledge was, as opposed to what the knowledge is.
routing.max_tokens800The only part of retrieval that costs tokens on every prompt now that the index is searched rather than sent. It is capped rather than trusted to stay small: the claim that selection lessons stay far fewer than lessons is a bet, and rose status reports the ratio so the bet is visible. When the cap binds, the rules with the worst record of improving a selection are the ones that fall out.
selection.w_judge0.60The model decides which dropped detail explains a failure; the other two terms are evidence (observed rescue rate) and measurement (tokens), not proxies for judgement.
selection.w_prior0.28
selection.w_cost0.12
selection.exploreposteriorposterior | ucb
selection.ucb_c0.7
compaction.enabledtrue
compaction.min_successes1Successful recalls before a compression is attempted. Recall serves about one lesson per prompt, so waiting for a second success can take weeks — and the wait buys little, because the thing that actually protects the lesson is replay against its own episodes, which runs either way. One success is enough of an occasion.
compaction.max_ratio0.75Candidate must be <= this fraction of the parent's tokens. Measured against real compressors, a single step on an already-dense lesson lands around 0.7; a stricter gate simply rejects everything and leaves you at 100%. What matters is compounding, not per-step depth — 0.75 per level is ~32% of the original after four levels.
compaction.threshold1.0required replay pass-rate
compaction.regression_k5episodes replayed per validation
compaction.max_level6
compaction.cooldown_s900
learning.enabledtrue
learning.min_tool_calls8ignore trivial sessions
learning.capture_failurestrue
learning.nudge_enabledtrueReflection needs an occasion, not a verdict. The agent has the judgement to tell a conceptual mistake from a typo, but in flight its attention is on the task — so the harness schedules the look and the agent decides what it sees. These thresholds only ask "did this turn have enough substance to be worth a thought".
learning.nudge_modebackgroundbackground: a detached process reflects on the transcript, and the agent is never interrupted. Costs nothing on the main thread. block: interrupt the agent to reflect in its own context. It has the live sense of what surprised it, but spends a turn and pollutes the working context — a real cost in the middle of a large task. fork: reflect inside a fork of the live session — same context, off the main thread. Costs ~0.1x its tokens thanks to prompt cache reads, but 10% of a large context still exceeds a digest. off: no reflection until session end.
learning.nudge_after_tool_calls12
learning.nudge_after_turns3
learning.min_surprises2failed tool calls also make a turn substantial
learning.nudge_cooldown_s900
learning.nudge_backoff_after3If the agent captures on its own, stop interrupting it. Backs the cooldown off after this many nudges in a row that yielded nothing.
placement.consulttrueask a model how new knowledge relates to old
placement.judge_calls2levels of tree walk when looking for related lessons
placement.max_depth2
placement.surface_conflictstrueraise unresolved contradictions at recall
signals.min_confidence0.5below this an outcome is recorded as 'unknown'
limits.agent_timeout_s180
limits.max_concurrent2
privacy.redacttruescrub secret-shaped strings before anything is stored