Repository navigation
feat(app): a Repeat reads switch in the main window and a Repeat reads card on the Optimizer tab - #59
Merged
Merged
Conversation
…art from the savings totals Served answers (unchanged and delta, from smart_read and recall_file) are not in LUMEN_ROUTES, so the token totals, by-tool, by-channel and net value never included them and still do not. The report now carries their own counts under repeatReads: unchanged and delta answers, tokens not re-sent against reading the whole file again (measured rows only), fresh=true requests, and reads that could not be tied to a conversation.
…in the settings file get_repeat_reads_setting reports what the file and the default say, never the server's effective mode, since a LUMEN_REPEAT_READS value in a Claude Code MCP config outranks the file and the app cannot see it. set_repeat_reads_setting writes the choice and returns the file read back, so a write that did not take is visible instead of assumed. A corrupt file reads as off with the reason, and switching on rewrites it.
…aved in the settings file The switch shows the settings file and the default, and says so: a LUMEN_REPEAT_READS value in an MCP config takes priority and is not visible here. A file that cannot be read shows why, that repeat reads are off, and that switching on rewrites it. A failed read claims neither state and offers Retry; a failed write puts the switch back and shows the error. Reads and writes run one after another so a read never overtakes the write before it.
…eat reads switch in the app
… switch, which now exists The writer's doc comment said nothing in the app calls it, and the file-problem message and its test said there was no switch to go back to. The Home window has one now, and choosing a setting there rewrites a file that cannot be used. A bad environment value is still not something the switch can fix, so that message keeps not mentioning it.
…ext tab of the main window The docs and the tab bar say "main window" and "Context"; "Home" is only the component's name, so a message sending someone to the Home window sent them to nothing they can see.
…from every total A card after the not-optimized block shows the answers served short (unchanged notes, deltas), the tokens not re-sent counted against reading the whole file again, how many full results were asked for again, and the reads Lumen could not place in a conversation. It states that these are in none of the token totals, the by-tool and by-channel breakdowns or the net value, and it says when the settings file turns repeat reads off. It never words a figure as a saving and shows no dollars or percentage; a backend older than 1.8.0 sends no figures and then there is no card.
… the card's baseline README: the switch as a third way to turn repeat reads off, what it can and cannot show (the settings file and the default, never the environment), and the Repeat reads card: what each figure counts, that its tokens are counted against the whole file and so are not a saving over having repeat reads off, and that its answers are in none of the totals while the provenance counts still include their rows. CHANGELOG: one entry under Unreleased.
…s, so its styles stay under the build budget With the card's own rules optimizer.css was 8.80 kB, over the 8 kB component-style error budget, and `pnpm build` failed. The card now shares the breakdown card, title, rows, value and amber-note rules and inherits its text style from the card: the file is 7.83 kB. The existing rules render as before; in the card, rows are 0.5rem apart and names are 0.74rem.
frontend_styling requires every class a template uses to be styled in its component. The card's paragraphs, names and lead now take their text style from the card instead of from classes of their own, so the template no longer names them; the one modifier left is repeat-card__problem. No spec, e2e or other file used those classes.
The switch is no longer disabled during a write, which dropped the focus it held; it is marked aria-disabled and a second click is ignored until the first write settles. The Optimizer card says "1 delta", not "1 deltas". New tests, each shown to fail without its fix: a reader holding the settings file open still sees the whole old one after a write (the rename is atomic); every command the window invokes is registered in the Tauri handler list; a failed write names the file and the operating-system cause.
The window sends set_repeat_reads_setting its argument as { on } and the handler takes `on`, and nothing compared the two: renaming either end compiled and passed every test. A test now reads the argument keys from tauri-bridge.ts and the parameters from the handlers in lib.rs and requires them to match, for both commands, and a second test pins the scan itself.
The test that served answers stay out of every total seeded two of the four served routes, so adding smart_read_delta or recall_file_unchanged to any of the six route lists in lumen-stats passed it. It now seeds all four.
Each is proved to fail without it: the old test passed under all 12 additions of the two unseeded routes and the new one fails under all 24 single additions; the new pair fails with the key sent as { enabled: on }, with a key sent to the get command, with the handler parameter renamed, and with the scan keeping the spaces around a key.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Repeat reads are on by default in 1.8.0, and until now the only way to turn them off was an environment variable or a hand-edited JSON file, with nothing in the app showing what they had done. This adds a switch to the main window and a card to the Optimizer tab.
Nothing the MCP server sends changes (no tool output,
tools/listor hook), and nothing is added to the hook path. Inlumen-coreonly the unusable-settings-file message changes: it now names the switch.The switch
lumen_settings.json(atomically, readable by its owner only, the other keys of a valid file kept). The server reads that file on every tool call, so a change applies to the next Lumen read in every running Claude Code session, with no restart, and survives a restart. The window says so.LUMEN_REPEAT_READSin the MCP config Claude Code gives the server (which outranks the file), nor aLUMEN_DBthere that points the server at another ledger. Its text says both.aria-disabled) and ignores a second flip, so a keyboard user does not lose their place. A setting that cannot be read shows neither state and offers Retry. A change that cannot be saved puts the switch back and says why.lumen doctorand the unusable-file message name the switch as the repair.The card
On the Optimizer tab, below every total: unchanged answers served, edits served as a delta, tokens not re-sent, and how often the full result was asked for again with
fresh=true(n of m, labelled as re-requests). It is counted apart from every total (token totals, by-tool and by-channel breakdowns, net value) and shows no dollar figure and no percentage. The token figure covers only answers whose count was measured: the card says how many when that is fewer than all, and shows a dash when none. It says when the settings file turns repeat reads off, and counts the reads answered in full because Lumen could not tell the conversation, with a link to Setup. An empty ledger says "No repeat read has been answered short yet." with no figure. A backend that does not send the figures gets no card.lumen-stats: the optimizer report gainsrepeatReads; no schema change. Tauri: two commands read and write the setting throughlumen_core::settings.Styles
The card shares the Optimizer page's existing card, title, row-list, figure and note rules by adding its selectors to them, instead of repeating their declarations. With its own copies the page's stylesheet was 8.80 kB, over the 8 kB build budget; it is 7.83 kB now (main: 7.13 kB, limit 8 kB). home.css is at 7.93 kB of 8 kB: the next rule on either page has to share, or the budget has to move. The existing blocks render as before; the card takes their values (rows 0.5rem apart, figures 0.84rem). The template has no class without a rule; a guard in
lumen-coreenforces it.One wording decision, yours to change
The brief says "tokens saved". The card says "tokens not re-sent", counted against reading the whole file again: with repeat reads off a read returns the outline, usually far smaller, so a saving against the whole file would overstate what repeat reads add. The card and the README name the baseline.
Tests
lumen-statsfor the new aggregate, one of which seeds all four served routes and checks that none reaches any of the six totals; 17 for the Tauri commands (every file state, a failed write names the file and the operating system's reason, the variable not read, every command the window invokes is registered, and the argument keys the window sends are the parameters each handler takes); 1 in doctor; the settings message test updated; inlumen-coreone test that a reader holding the file open still sees the whole old file after a write.Gate
Local gate green on
31772f8(446 s): fmt, clippy-D warnings(workspace and Tauri crate), workspace tests withRUSTFLAGS=-D warnings, frontend build under the style budgets and tests with the coverage thresholds, e2e, Tauri crate and hook e2e tests, MSRV 1.94.0, install verify, debug app build. Run withLUMEN_RANKED_TIME_BUDGET_MS=60000: the lumen-core ranked-outline budget test is wall-clock bound and flakes on a loaded machine; nothing here touches it.Each new test was proved to fail without its fix: the settings write done in place, the handler removed from the list, the operating system's reason dropped from the message, the switch disabled while writing, the plural, the argument sent as
{ enabled: on }, the handler's parameter renamed, and any one of the four served routes added to any of the six route lists inlumen-stats(24 changes; the test before this seeded two routes and passed 12 of them).Not run locally: the tauri-driver app e2e, which runs on CI Linux (
GUI build + test). No e2e touches the switch, and the argument test compares the two sources rather than running the Tauri runtime.CRLF clone (
core.autocrlf=true): thelumen-core,lumen-statsandlumen-clitests and the new Tauri tests, none failed.