Reading pane: a quiet break before each chapter; v11n counts in a data file #19

Merged
schaefera merged 4 commits from phase1/chapter-separator into phase1/core-layout 2026-10-21 13:11:11 +00:00
Collaborator

Follow-up to #18, stacked on phase1/core-layout (#17). Part of #11.

What

  • A dim, centred "· · ·" (em-spaced so it doesn't read as an ellipsis) above each chapter heading gives the end of one chapter some room before the next. It is not shown above the Bible's first chapter, where nothing comes before. Screen readers skip it.
  • The core marks a versification's first chapter (Heading::first). The glue now passes the heading as three lines (break, book, chapter), each empty where there is none.
  • Sweep after #18 ("apply the typed locale and ini loading to the rest"): the last embedded table in Rust source, the verse counts in sword/src/v11n/data.rs, now lives in sword/src/v11n/systems.ini. It is read by sword::ini::Section, which core's book names now share. tools/v11n/fetch.sh is pinned to the booknames JSword commit (a2c51f3c).

Blast radius

Tier: trunk
Trunk paths touched: sword/src/v11n*, core/src/bible*, qt/src/reading_model.rs, qml/pages/ReadingPane.qml
Gate / rollback: no flag. Revert this merge; there is no data or schema change, and the verse counts are byte-identical to before.
Budgets (docs/07): one more Text per loaded heading (~15). mem-check at the head: peak PSS 146923 kB of 165000 kB, start-up 126 ms. v11n: ~2.4 KB heap per Versification and ~1,200 integers parsed once per module open.

Proof

  • Rust gate: cargo make (SWORD_TEST_REQUIRED=1) at the head: fmt, clippy, tests (sword 18 unit + 7 golden + 3+3, core 39), coverage 94.96%, deny and audit ok.
  • App gate: cargo make app-docker at the head: QML lint, -Werror build, clang-tidy, mem-check (scroll, save within 189 ms, restore after kill -9 matches).
  • Same data: fetch.sh at the pin plus gen.py gives a systems.ini that is cmp-identical to the committed one, with the same counts as the old data.rs.
  • Fails without the change (deliberate breaks, then restored):
    • KJV Gen 1 set to 30 verses makes kjv_ordinals_match_sword_layout fail.
    • German Gen=3x makes reads_every_system_in_the_file and verse_and_ordinal_round_trip fail.
    • Heading::first from .is_some() instead of .is_none() makes reads_kjv and heads_chapters_in_the_module_language fail.
  • UI: Xvfb screenshots in the CI image (540x960, KJV):
    • Fresh start at Gen 1 shows "Genesis / Chapter 1" at the top with no dots.
    • Gen 1:31 → dots → "Chapter 2".
    • Gen 50:26 → dots → "Exodus / Chapter 1", with no overlap.
  • Phone: the arm64 click from the head is installed and running.
  • Sweep: locale literals appear only in tests and FALLBACK; the worker.rs strings are test fixtures; db.rs already loads its SQL with include_str!.

Review

Reviewer, 26ff675..470a584: fresh-context review at high, 5 findings, 1 fixed (screen readers skip the dots), 4 declined:

  • by_name allocates per call: it runs once per module open.
  • A bad verse count isn't reported clearly: the data is built in and the tests parse every system.
  • The pin is unverified: refuted by the cmp proof.
  • Dots above the first chapter: superseded, now fixed in 1815b14.

A medium re-review of the fix found no bugs.
Review-Confidence (that part): 70/100. Not amended onto 470a584, which was already pushed. The audit's deductions were for the accessibility fix and the first-chapter dots, both lacking proof; 1815b14 replaces the latter.

Reviewer, 1815b14 (first chapter, wider dots): fresh-context review at high, 1 low-confidence finding declined: an empty heading string would leave lines[1] undefined. That can't happen, because every row belongs to a chapter span and Span::of always writes three lines.
Review-Confidence: 100/100 (trailer on 1815b14). No missed defect on an independent pass; the glue-to-QML format is covered by screenshots, not an automated test.

Confidence by part

  • v11n data file and shared ini reader: high (byte-identical data, golden tests, deliberate breaks).
  • Heading::first in core: high (unit tests with a deliberate break).
  • Three-line heading format, glue to QML: medium. It's checked only by screenshots; nothing tests it automatically.
  • Accessible.ignored: medium. It's a valid QtQuick 2.15 property, but not checked with a screen reader.

Merge with "Create merge commit".

🤖 Generated with Claude Code

Follow-up to #18, stacked on `phase1/core-layout` (#17). Part of #11. ## What - A dim, centred "· · ·" (em-spaced so it doesn't read as an ellipsis) above each chapter heading gives the end of one chapter some room before the next. It is not shown above the Bible's first chapter, where nothing comes before. Screen readers skip it. - The core marks a versification's first chapter (`Heading::first`). The glue now passes the heading as three lines (break, book, chapter), each empty where there is none. - Sweep after #18 ("apply the typed locale and ini loading to the rest"): the last embedded table in Rust source, the verse counts in `sword/src/v11n/data.rs`, now lives in `sword/src/v11n/systems.ini`. It is read by `sword::ini::Section`, which core's book names now share. `tools/v11n/fetch.sh` is pinned to the booknames JSword commit (a2c51f3c). ## Blast radius **Tier:** trunk **Trunk paths touched:** `sword/src/v11n*`, `core/src/bible*`, `qt/src/reading_model.rs`, `qml/pages/ReadingPane.qml` **Gate / rollback:** no flag. Revert this merge; there is no data or schema change, and the verse counts are byte-identical to before. **Budgets (docs/07):** one more Text per loaded heading (~15). mem-check at the head: peak PSS 146923 kB of 165000 kB, start-up 126 ms. v11n: ~2.4 KB heap per Versification and ~1,200 integers parsed once per module open. ## Proof - Rust gate: `cargo make` (SWORD_TEST_REQUIRED=1) at the head: fmt, clippy, tests (sword 18 unit + 7 golden + 3+3, core 39), coverage 94.96%, deny and audit ok. - App gate: `cargo make app-docker` at the head: QML lint, -Werror build, clang-tidy, mem-check (scroll, save within 189 ms, restore after kill -9 matches). - Same data: fetch.sh at the pin plus gen.py gives a systems.ini that is `cmp`-identical to the committed one, with the same counts as the old data.rs. - Fails without the change (deliberate breaks, then restored): - KJV Gen 1 set to 30 verses makes `kjv_ordinals_match_sword_layout` fail. - German `Gen=3x` makes `reads_every_system_in_the_file` and `verse_and_ordinal_round_trip` fail. - `Heading::first` from `.is_some()` instead of `.is_none()` makes `reads_kjv` and `heads_chapters_in_the_module_language` fail. - UI: Xvfb screenshots in the CI image (540x960, KJV): - Fresh start at Gen 1 shows "Genesis / Chapter 1" at the top with no dots. - Gen 1:31 → dots → "Chapter 2". - Gen 50:26 → dots → "Exodus / Chapter 1", with no overlap. - Phone: the arm64 click from the head is installed and running. - Sweep: locale literals appear only in tests and `FALLBACK`; the worker.rs strings are test fixtures; db.rs already loads its SQL with `include_str!`. ## Review **Reviewer, 26ff675..470a584:** fresh-context review at high, 5 findings, 1 fixed (screen readers skip the dots), 4 declined: - `by_name` allocates per call: it runs once per module open. - A bad verse count isn't reported clearly: the data is built in and the tests parse every system. - The pin is unverified: refuted by the `cmp` proof. - Dots above the first chapter: superseded, now fixed in 1815b14. A medium re-review of the fix found no bugs. **Review-Confidence (that part):** 70/100. Not amended onto 470a584, which was already pushed. The audit's deductions were for the accessibility fix and the first-chapter dots, both lacking proof; 1815b14 replaces the latter. **Reviewer, 1815b14 (first chapter, wider dots):** fresh-context review at high, 1 low-confidence finding declined: an empty heading string would leave `lines[1]` undefined. That can't happen, because every row belongs to a chapter span and `Span::of` always writes three lines. **Review-Confidence:** 100/100 (trailer on 1815b14). No missed defect on an independent pass; the glue-to-QML format is covered by screenshots, not an automated test. ## Confidence by part - v11n data file and shared ini reader: high (byte-identical data, golden tests, deliberate breaks). - `Heading::first` in core: high (unit tests with a deliberate break). - Three-line heading format, glue to QML: medium. It's checked only by screenshots; nothing tests it automatically. - `Accessible.ignored`: medium. It's a valid QtQuick 2.15 property, but not checked with a screen reader. Merge with "Create merge commit". 🤖 Generated with [Claude Code](https://claude.com/claude-code)
sword/src/v11n/systems.ini replaces the generated v11n/data.rs and its
Table type: a [System.OT] and [System.NT] section per system, of
Gen=31,25,... lines. Versification parses a system's counts when it is
built. The ini Section type moves from core's names into sword::ini so
core's book names and sword's v11n read data files the same way.
tools/v11n/fetch.sh is pinned to the JSword commit tools/booknames uses;
gen.py output is the same at that commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A dim, centred row of three dots at the top of every section heading
gives the end of one chapter some room before the next one's heading.
It is on every heading, so a heading item the list reuses never
changes height; the first chapter shown also gets it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ReadingPane: screen readers skip the chapter break
All checks were successful
CI / rust (pull_request) Successful in 2m29s
CI / audit (pull_request) Successful in 12s
CI / app (pull_request) Successful in 1m24s
CI / click (pull_request) Successful in 54s
470a584e58
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Reading pane: no break above the Bible's first chapter; wider dots
All checks were successful
CI / rust (pull_request) Successful in 2m17s
CI / audit (pull_request) Successful in 11s
CI / app (pull_request) Successful in 1m24s
CI / click (pull_request) Successful in 51s
1815b14e8d
The "···" break sat above Genesis 1 too, where no chapter comes before
it. The core now marks a versification's first chapter
(Heading::first), and the glue passes the heading as three lines,
break, book and chapter, each empty where there is none, so the pane
shows the dots only where a chapter ends above. Em spaces between the
dots keep them from reading as an ellipsis, and centre them (letter
spacing left a trailing gap).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review-Confidence: 100
Review-Tier: trunk
schaefera approved these changes 2026-10-21 13:11:06 +00:00
schaefera merged commit c77d170b8b into phase1/core-layout 2026-10-21 13:11:11 +00:00
schaefera deleted branch phase1/chapter-separator 2026-10-21 13:11:11 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
schaefera/utStudyBIble!19
No description provided.