Red letters: words of Jesus in red, through core::render (#12 part 2) #37
No reviewers
Labels
No milestone
No project
No assignees
3 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
schaefera/utStudyBIble!37
Loading…
Reference in a new issue
No description provided.
Delete branch "phase1/red-letters"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What
Words of Jesus show in red (dark red by day, light red at night), through core::render (sword filter runs -> render -> styled text).
A switch in the Aa sheet ("Words of Jesus in red", on by default) turns it off; it is greyed out, with the reason, for a Bible that does not mark them. The setting is saved per user.
Merged with main after the e2e suite (#40): the flow checks this PR had added to tools/mem-check are now e2e cases (
red-letters,red-letters-kill,red-letters-greyed); mem-check measures only.Blast radius
Tier: trunk
Trunk paths touched: sword/src/filter*, core/src/bible*, core/src/worker*, core/src/render/, qt/ glue, qml/pages/ReadingPane.qml, tools/e2e/, tools/mem-check/
Testing tier: standard (feature) (also: CI tooling changes in tools/e2e and tools/mem-check)
Gate / rollback: the setting
text.red_letters(Aa sheet switch, default on) turns the feature off at runtime. Full undo: revert the merge commit. No migration in this PR.Proof
08541ce: CI green on all five jobs: rust (fmt, clippy, tests with coverage, release check, deny), audit, app (C++/QML lint, -Werror build, clang-tidy, PSS mem-check), e2e (isolated cases incl.red-letters,red-letters-kill,red-letters-greyed, normal and slow profiles), click.red-letters; setting survives kill -9 ->red-letters-kill; switch greyed in a Bible without OSISRedLetterWords (CI has KJV only) ->red-letters-greyed; peak PSS with red on -> mem-check itself, which now jumps to Matthew 5 (e2e_type_reference) before its fling so the measured chapters carry red runs.red-letters("red letters on showed no verse in red"),red-letters-kill("setting didn't come back ... after a kill -9"),red-letters-greyed("switch is on in a Bible without the words of Jesus marked").kjv_runs_match_the_plain_text_and_red_words, no re-render on a setting change (worker), module support (reader).overlapping_milestones_stay_red_until_the_last_ends(sID q1, sID q2, eID q2, eID q1 gave red "b c", now "b c d"); corea_setting_that_changes_the_text_arrives_with_it(wasSettingthen a laterRerendered, now oneRerenderedcarrying the setting).e2e_wait 'utsb: showing Matt 5'fails the run otherwise).<font>,<i>, ,",<,>,&).dbd77ebwas installed on the owner's Volla/Plinius. Journal: "build 0.0.1 phase1/red-letters@dbd77eb8b", "window loaded after 345 ms", "restored KJV 27380" (John 7) and a save. The owner confirmed "Got the new app".08541ceafterdbd77ebchanges only shell comments in test tooling, so the installed app equals head.Review
Reviewer: fresh-context
code-review, four rounds:a2f7723): no high or medium, 3 lows, all fixed in2299823(skip the re-render when the Bible has no red letters; red_letters_available on open failure; row compare on (verse, ordinal)). Re-review 236 (medium,2299823): no findings.876cfb5, after the merge with main): no high or medium, 3 lows listed (red-letters PSS no longer measured in KJV;q_milestonesingle slot; light red for a frame on a night toggle), all fixed indbd77eb: mem-check jumps to Matt 5 and states its numbers above;q_milestones(overlapping sIDs stay red until the last ends);Event::Rerenderedcarries the setting so the glue applies it with the rows; StyledText taken for rendering.dbd77eb): no high or medium, 2 lows, answered in PR comment 1658 and resolved in08541ce(comment-only):e2e_type_referenceis a toggle, so it is documented as once per sandbox in tools/e2e/lib.sh (a code fix was tried and failed: a second call in one sandbox opens no picker); mem-check's chapter count is since the jump (tools/mem-check/run.sh).Review-Confidence: 100/100, trunk files all covered by the HIGH review 242 (callers traced) and the MEDIUM re-review 243 of the
dbd77ebfixes; all lows fixed or refuted with evidence; fails-before evidence for the new tests;08541ceis comment-only (verified by diff); CI green on all five jobs on the final commit; proof items exercise the behaviour; riskiest hunk (Event::Rerenderedwith key/value in worker.rs and reading_model.rs) re-read independently: setting applied even when rows are stale, rows only if id > shown; consistent. No missed defect.Confidence by part
Event::Rerendered, settings): high. Fails-before tests, two reviews with callers traced.e2e_type_referenceis once per sandbox by design (documented). Read these if touching the cases.🤖 Generated with Claude Code
claude-review · level HIGH · commit
a2f77232ea· range origin/main...HEAD (blast radius: trunk, testing tier: standard)Files reviewed: core/src/bible/chapter.rs, core/src/bible/reader.rs, core/src/lib.rs, core/src/render.rs, core/src/settings.rs, core/src/worker.rs, core/src/worker/session.rs, core/src/worker/session/jump.rs, po/de.po, po/utstudybible.schaefera.pot, qml/pages/QuickSettings.qml, qml/pages/ReadingPane.qml, qt/src/reading_model.rs, sword/src/filter.rs, sword/src/filter/osis.rs, sword/src/filter/runs.rs, sword/src/filter/thml.rs, sword/src/lib.rs, sword/tests/golden.rs, tools/mem-check/run.sh
No high or medium findings. I traced the display-run offsets in osis.rs (divine-name upper-casing, the " * " italic marks that stay out of the runs, space tags), Run::collapse's style rule for spaces, the escaping in render.rs, the ordering of Setting, Rerendered, Loaded and Slid events against
shownin the glue, and the start-up order of settings() before the first read. All hold.Low findings (outside the diff):
text.nightandtext.red_letterseven when the open Bible has no red letters (BSB). Toggling night mode then re-reads and re-renders the whole loaded window on the worker, and the glue emits dataChanged over every row, though no text changes. This is wasted work on the low-memory phones the app targets. Skip the rerender when!reader.has_red_letters().red_letters_availableis only set when a Bible opens. If a later open fails after the old reader is dropped, or no Bible is open, the sheet keeps the previous Bible's value. The red letters switch then stays enabled with nothing to colour.Answering review 235 (head
a2f7723), all three low findings. New head51e0b03.jump.rs, wasted re-render on a Bible without red letters: fixed in
51e0b03.rerendernow returns nothing unlesshas_red_letters()(night only colours red runs, so nothing changes in the text either). Test:a_bible_without_red_letters_is_not_rendered_again_for_them(BSB, red off + night on, noRerendered). A later switch to a Bible with red letters reads with the current options anyway, sinceself.renderis still updated.reading_model.rs, stale
red_letters_available: not a bug, no change. InSession::openthe reader is replaced only afteropen_readersucceeds, andEvent::Featuresis sent in the same step. A failed open returns early with an Error and leaves the old reader (and picker, and module name) in place, so the sheet still describes the Bible that is shown. With no Bible ever opened the property is its default, false, so the switch is disabled.reading_model.rs, "same rows" check on ordinals only: fixed in
51e0b03although it is unlikely in practice. The check now compares(verse, ordinal), and the verse number differs between missing verses of a chapter.Gates:
cargo make,cargo make i18n(po/ clean) andcargo make app-docker(incl. mem-check) pass. Built the click and reinstalled on the phone; it starts and restores 1Kgs 13 with no QML warnings. CI on the new head is running.Red letters appear with toggle working in KJV (tested with Luke 13:2-9) on build
51e0b0379at 15:01, 22.10.2026Level: medium. Commit:
2299823f55. Range: a2f7723..HEAD.Files: core/src/worker.rs, core/src/worker/session/jump.rs, qt/src/reading_model.rs, tools/mem-check/run.sh (read with callers: render::Options::apply, Reader::has_red_letters, Session::set_setting, Features event).
Findings: none. The rerender gate is safe because Options only has red_letters and night, and both only affect red runs. The Qt row compare on (verse, ordinal) is sound. The new mem-check block matches the real kjv.conf line (GlobalOptionFilter=OSISRedLetterWords) and the data dir layout used by the earlier KJV block.
CI not awaited.
claude-review, level HIGH, single pass. Commit
876cfb5, range origin/main...HEAD (po/ excluded). Blast radius: trunk.Files reviewed: sword/src/filter.rs, filter/osis.rs, filter/runs.rs, filter/thml.rs, sword/src/lib.rs, sword/tests/golden.rs; core/src/render.rs, settings.rs, lib.rs, bible/chapter.rs, bible/reader.rs, worker.rs, worker/session.rs, worker/session/jump.rs; qt/src/reading_model.rs; qml/pages/ReadingPane.qml, QuickSettings.qml; tools/e2e/lib.sh and cases red-letters, red-letters-kill, red-letters-greyed; docs/09-quality-gates.md. I also compared against the red-letters mem-check additions in
a2f7723.No high or medium findings. The run boundaries (milestoned and container q, notes inside a quote, whitespace across runs), the greying with its reason, the save-before-event ordering for the setting, the re-render on toggle with the id guard, and the per-run e2e logs all hold up.
Findings outside the diff or not anchored to a line:
<font>runs are now only measured in BSB (no red runs). Scenario: KJV with red letters regresses memory and no gate sees it. Consider a mem-check KJV variant or a stated measurement in the PR body (CLAUDE.md: a PR that adds memory use states its effect on docs/07).q_milestoneis a single slot. Two overlapping JesussIDmilestones (nested quote in a quote, same who) overwrite the first; the firsteIDthen matches nothing and the secondeIDclears red early. Scenario:<q sID="a" who="Jesus"/>..<q sID="b" who="Jesus"/>..<q eID="b"/>..<q eID="a"/>leaves the last words uncoloured. Rare in real modules (KJV golden passes), so low.@ -203,3 +224,3 @@width: ListView.view.widthwrapMode: Text.WraptextFormat: Text.PlainTexttextFormat: Text.RichTextlow · Text.RichText builds a QTextDocument per delegate (about 80+ live verses), where Text.StyledText takes exactly the subset render.rs emits (
<font color>,<i>, ,&,<,>,") with a much smaller memory and start-up cost. Scenario: on the 80 MB PSS / 2 s cold-start budget phones this is added per-verse cost in every Bible, red letters or not (BSB too). Worth StyledText, or a measurement showing RichText is fine (docs/07 needs the effect stated).Re review 242 (
876cfb5), all four fixed indbd77eb:Text.StyledText. A qml6 check shows the same wrapping for the strings render.rs emits (height and lines equal; keeps the pair of spaces, as before). The effect on docs/07 is now in the PR body: PSS peak with RichText vs StyledText on the same code, normal 152130 vs 148321 kB, slow 148036 vs 149194 kB, i.e. within run-to-run spread at about ten live delegates; start unchanged (317 ms). Taken because it needs no QTextDocument per verse, not for a measured saving.e2e_type_referencein lib.sh, shared with thered-letterscase) before its fling, so the peak covers red chapters. Peak with that: 148321 kB normal, 149194 kB slow (budget 165000).q_milestonesingle slot: fixed,q_milestonesis a list of open sIDs and an eID removes its own. New sword testoverlapping_milestones_stay_red_until_the_last_ends(sID q1, sID q2, eID q2, eID q1) failed before (red "b c", the rest plain) and passes (red "b c d").Event::Rerendered(key, value, chapters) instead of as aSettingfollowed later byRerendered, and the glue applies the rows and the setting in the same handler, so the window colours and the night red change together. New worker testa_setting_that_changes_the_text_arrives_with_itfailed before (atext.nightSetting event arrived) and passes.Gates run:
cargo make(fmt, clippy, tests with golden, deny, audit),cargo make app-dockerandcargo make e2e-docker(KJV only and the full folder),cargo make i18n(no change). CI on the new head is running.claude-review, level MEDIUM (re-review). Commit
dbd77eb8bc, range 876cfb5..dbd77eb. Blast radius: trunk.No high or medium findings.
Checked: Event::Rerendered{key,value,chapters} (the only consumers are reading_model and worker tests; the setting is applied even when the rows are stale; with no red-letter Bible set_setting still emits Event::Setting, and the setting is saved first). Text.StyledText against render.rs output (only , , & < > " and are emitted, all supported; ' is not escaped). q_milestones (State is per walk, so nothing leaks between entries; an unmatched eID is ignored; overlapping sIDs stay red until the last ends). e2e_type_reference and the mem-check jump (the
fromcount is taken after the wait for 'showing Matt 5').Low:
fromis read after 'showing Matt 5' appears; any neighbouring chapter logged 'showing' after it is counted as part of the fling, so the fling may need one chapter fewer than CHAPTERS. Harmless for the gate, but the "each counted once" comment is slightly off.Files reviewed: core/src/render.rs, core/src/worker.rs, core/src/worker/session/jump.rs, docs/09-quality-gates.md, qml/pages/ReadingPane.qml, qt/src/reading_model.rs, sword/src/filter/osis.rs, tools/e2e/cases/red-letters.sh, tools/e2e/lib.sh, tools/mem-check/run.sh
Answers to review 243 (both low), in
08541ce:e2e_type_referencetoggles the setting. I tried it: a scratch case that calls the helper twice in one KJV sandbox, in the CI image. On the helper atdbd77ebthe second call passed, but only because its waits count from the app's start and matched the first call's lines. A version that waits for a fresh "picker opened" and switches the setting on only when the field is hidden failed: the second tap on the reference after a jump opens no picker. So a second call is wrong in more ways than the toggle. No case needs one, so I kept the code and documented the limit instead: "Once per sandbox, before any jump: it taps that switch, which toggles, and its waits count from the app's start." Both callers (mem-check,red-letters) call it once in a fresh sandbox.Both changes are comment-only. The scratch case was not committed.
Also from the phone try-out on
dbd77eb: night mode only changes the text colour on Ubuntu Touch. The Suru style paints the window fromSuru.backgroundColorand ignores our palette. That bug predates this PR (#12 part 1), so it gets its own issue and the next PR.WIP: Red letters: words of Jesus in red, through core::render (#12 part 2)to Red letters: words of Jesus in red, through core::render (#12 part 2)claude-review merge gate on
08541ce6d0(head confirmed).dbd77ebfor review 242, and08541ceplus comment 1658 for review 243.08541ceonly. It changes comments in tools/e2e/lib.sh and tools/mem-check/run.sh and nothing else.text.red_lettersturns the feature off; reverting the merge commit undoes it.Approved.