Skip to content

The inspector learns which two boxes - #83

Merged
omars-lab merged 2 commits into
mainfrom
inspector-word-outline
Aug 7, 2026
Merged

The inspector learns which two boxes#83
omars-lab merged 2 commits into
mainfrom
inspector-word-outline

Conversation

@omars-lab

Copy link
Copy Markdown
Owner

inspector-draws-no-ink was filed as a question, not a defect: the encoding inspector shows identity and never appearance, and that blindness is what its authority rests on. The row said to wait for a caller rather than for an argument. The caller arrived — reading a 2→1 paint block at word 3, the next question is always which two boxes — so section ① now draws them.

What it draws, and what it still refuses to

Word boxes as outlines, from the committed assets/words/hafs-kfqc/<page>.json shards that gate:words already checks re-derive from committed bytes, on the page's own frame out of manifest.viewBox (with viewBoxOverrides honoured for pages 1–2). The rest of the page sits behind the ayah faintly, behind a toggle.

Nothing is read from assets/pages/**. No glyph is drawn. §6.4's principle keeps its force over the half that mattered, and the doc says which half: the line it actually protects is not "draws nothing" but "makes no claim about appearance", and a rectangle out of a gated shard makes none.

Three things settled before anything was drawn

  • from === 1 is asserted, not assumed. True of all 6,236 ayahs — no ayah's boxes are split across two shards — which is what lets print word i be boxes[i - 1] unconditionally. A non-1 from would shift every label by the offset and look entirely correct.
  • Boxes are tinted by host index, not print index. A word the fold dropped gaps on the page exactly as it gaps on the codepoint ruler. That shared parity is why ① and ④ read as one instrument rather than two pictures — and why clicking a box selects the annotation over it and lights the ruler in step.
  • A count disagreement refuses to number. If the box list and the data-hafs word list disagree, the view draws the geometry and warns with both counts, because the failure it would otherwise produce is word 7's box under word 8's label. Measured over the full corpus: 6,236 ayahs outlined, 0 mismatches. The check stays; the number is a result, not a guarantee.

One invisible defect, found by building it

Both halves of the report are text to probe-encodings.mjs and are never imported, so nothing noticed a syntax error in the client: the report generated, weighed its usual 4.9 MB, and opened to a blank page with the whole script dead in the console. It now compiles the exact concatenation the browser will parse (new vm.Script) before writing, and fails at generation time.

Verified

Headless Chromium against the generated report: both themes render with zero console errors; page 2 uses the 235×235 override and page 7 the 345×550 default; clicking each of page 7's 17 boxes selects an annotation for exactly the 7 that carry one, with box 14 lighting 2 — the two-adjacent case the feature exists to answer; the context toggle drops rect.other from 132 to 0; injecting a fake extra box flips all 18 to .untrusted and surfaces the warning. make ci green.

Registers

④ goes to answered, not fixed — same reasoning as drift-label-reads-backwards. The guard catches a syntax error and gate:words keeps the shards honest, but nothing in CI would fail if ① stopped drawing: the report is generated, gitignored and never a gate, which is exactly why it is allowed to be this cheap.

§⑥ item 4 gets the superseded-blind-spot treatment rather than an edit in place, and map.json's extend rule inverts to where the line now sits, so the next person adding a font reads a rule that has already thought about their case.

🤖 Generated with Claude Code

https://claude.ai/code/session_01EuhvbUKjGesE3uMhjCzBGt

omars-lab and others added 2 commits August 7, 2026 07:41
`inspector-draws-no-ink` asked for a caller before spending the work, and the
caller arrived: a maintainer reading a 2→1 paint block at word 3 wants to see
*which two boxes*, and `assets/words/**` has them. Section ① now draws them.

Outlines only, and the line moved by exactly the distance the question proposed.
The boxes come from the committed `assets/words/hafs-kfqc/<page>.json` shards —
`gate:words` checks those re-derive from committed bytes — on the page's own
frame from `manifest.viewBox`, with `viewBoxOverrides` honoured for pages 1–2.
Nothing is read from `assets/pages/**`, no glyph is drawn, and §6.4 keeps its
force over the half that mattered: the principle protects "makes no claim about
appearance", and a rectangle out of a gated shard makes none.

Three things were settled before anything was drawn.

`readBoxes` asserts `from === 1` rather than assuming it. It is true of all
6,236 ayahs today — no ayah's boxes are split across two shards — which is what
makes print word *i* be `boxes[i - 1]` unconditionally. A non-1 `from` would
shift every label by the offset and look entirely correct.

A box is tinted on its **host** index, not its print index, so a word the fold
dropped is a gap on the page exactly as it is a gap on the codepoint ruler. That
shared parity is the whole reason ① and ④ are one instrument rather than two
pictures, and it is why clicking a box selects the annotation over it and lights
the ruler in step.

When the box count and the `data-hafs` word count disagree, the view draws the
geometry and refuses to number it, warning with both counts. The failure it
would otherwise produce is word 7's box under word 8's label, which looks fine.
Measured over the full corpus: 6,236 ayahs outlined, 0 mismatches. The check
stays; the number is a result, not a guarantee.

One invisible defect was found by building it. Both halves of the report are
*text* to `probe-encodings.mjs` and are never imported, so nothing noticed a
syntax error in the client: the report generated, weighed its usual 4.9 MB, and
opened to a blank page with the whole script dead in the console. It now
compiles the exact concatenation the browser will parse (`new vm.Script`) before
writing, and fails at generation time instead.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EuhvbUKjGesE3uMhjCzBGt
`docs/design/encoding-inspector.md` §⑨ ④, `docs/issues.json`, the regenerated
`docs/issues.md` and `docs/map.json`, for the outline in 2220f66.

§⑥ item 4 gets the superseded-blind-spot treatment rather than an edit in
place — "no glyphs, no boxes, no page geometry" becomes "the ink: glyphs and the
page raster only", struck through with the record above it — because the useful
thing about a limitation that turned out to be half wrong is which half, and
deleting the sentence deletes that.

`answered` rather than `fixed`, by this repo's own definition of the stronger
word and the same reasoning `drift-label-reads-backwards` used. The generation
guard catches a syntax error and `gate:words` keeps the shards honest, but
nothing in CI would fail if section ① stopped drawing tomorrow: the report is
generated, gitignored and never a gate, which is exactly why it is allowed to be
this cheap. Claiming a closure with no test behind it would misreport what is
protecting the outline.

`map.json`'s extend rule inverts from "do not teach it to draw the ink" to where
the line actually sits now — outlines from a gated shard in, glyphs and anything
out of `assets/pages/**` still out — so the next person adding a font or a raster
reads a rule that has already thought about their case.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EuhvbUKjGesE3uMhjCzBGt
@omars-lab
omars-lab merged commit 5dc227d into main Aug 7, 2026
6 checks passed
@omars-lab
omars-lab deleted the inspector-word-outline branch August 7, 2026 12:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant