nigig-org/REVIEWS/adr
andodeki a82c8f7ff7
Some checks failed
nigig-build (CAD) / supply-chain (push) Has been cancelled
nigig-build (CAD) / cad-module (push) Has been cancelled
nigig-build (CAD) / full-crate-check (push) Has been cancelled
nigig-build (CAD) / cad-engine-coverage (push) Has been cancelled
nigig-build (CAD) / doc-workspace-coverage (push) Has been cancelled
nigig-build (CAD) / cad-widget-coverage (push) Has been cancelled
repo hygiene / hygiene (push) Has been cancelled
spreadsheet / engine-coverage (push) Has been cancelled
spreadsheet / ui-controller-coverage (push) Has been cancelled
doc-engine / engine (push) Has been cancelled
doc-engine / coverage (push) Has been cancelled
sms / robius-sms (push) Has been cancelled
sms / android (push) Has been cancelled
sms / nigig-sms (push) Has been cancelled
sms / supply-chain (push) Has been cancelled
doc-engine / consumer (push) Has been cancelled
email / gates (push) Has been cancelled
email / email-domain (push) Has been cancelled
email / nigig-email (push) Has been cancelled
email / supply-chain (push) Has been cancelled
nigig-map / test (push) Has been cancelled
PDF engine / engine (push) Has been cancelled
PDF engine / makepad-integration (push) Has been cancelled
PDF engine / fuzz (push) Has been cancelled
sms / gates (push) Has been cancelled
feat(pdf): Unicode-aware search and layout-aware reading order
Phase 8 bullets one and two. Probing the existing code first, as the
workflow requires, found five defects rather than the one the plan names:

    SPLIT MATCH 'Hello': 0 hits
      plain_text: "Hello"
    PRECOMPOSED 'café': 0 hits
    COLUMNS plain_text: "LeftTopRightTop\nLeftBotRightBot"
    OUT OF ORDER plain_text: "second\nfirst"

`PageText::find` searched one run at a time and documented that as a known
limitation. It is a limitation from inside the code and a broken feature
from outside it: a writer starts a new run wherever it adjusts kerning, so
an ordinary word arrives as two runs, and the find bar says a word plainly
visible on the page is not there.

`search.rs` indexes the page as one flattened string with a map back to
(run, character), so a cross-run match is found and highlighted with one
rectangle per run — never a merged box, which across a line break covers
half the paragraph.

The separator between two runs is a geometric question with three answers:
abutting runs join with nothing (one word, split by kerning), separated
runs with a space, and a different line or column with a newline. The
newline matters as much as the empty join: joining lines with a space lets
"one Right" match across a column gutter, text that appears nowhere.
Whether two runs share a column is *asked* of the layout analysis rather
than re-derived, or the extracted text and the searched text disagree about
where a column ends — the original defect wearing a different hat.

NFD, never NFC: composition needs the next character, so an NFC fold
applied per character composes nothing and the two spellings of an accent
stay different. That was a real bug in the first draft. And case *folding*,
not lowercasing — Rust lowercases ß to ß, so "Strasse" never found
"Straße".

Columns are detected before lines, because two columns share their
baselines; that is what makes them columns. Bands are separated by a gutter
rather than by bare non-overlap, since two abutting runs on a line do not
overlap either.

Also fixed, found by running the gates rather than by looking: a stream
reader trimmed a trailing CR before `endstream` as if it were the writer's
separator. Binary data ends in CR about one time in 256, and when it did
the reader returned a stream one byte short — no longer AES-block-aligned,
so decryption produced garbage and Flate failed. Roughly one encrypted
document in 250 was silently corrupt on read. The test failed once under
coverage, passed five times in isolation, and failed 2 in 40 when actually
counted. A /Length consistent with the file is now the authority; both
stream readers are fixed and a test reads one file through each.

1477 tests pass (was 1426), coverage 88.37%, all floors met, external
readers pass. 10 mutations across the two modules, all killed.

ADR 0034.
2026-08-19 16:12:12 +00:00
..
0001-payment-scope.md feat(pay): complete Phase 1 and fix M-Pesa store defects B1/B4 2026-07-27 15:23:20 +00:00
0002-payment-crate-ownership.md fix(pay): validate money at the persistence boundary (B6) 2026-07-29 04:48:50 +00:00
0003-pdf-incremental-save.md fix(pdf): fuzz every target, and close two ADR 0004 gaps 2026-07-31 18:34:25 +00:00
0004-pdf-annotation-editing.md fix(pdf): fuzz every target, and close two ADR 0004 gaps 2026-07-31 18:34:25 +00:00
0005-pdf-encryption.md test(pdf): prove the AES-256 path and harden malformed encryption 2026-07-28 17:50:44 +00:00
0006-pdf-advanced-color.md feat(pdf): real colour spaces, ICC profiles and PDF functions 2026-07-28 20:48:55 +00:00
0007-payment-platform-boundary.md feat(pay): coordinator entry point for an externally granted authorization 2026-07-29 04:10:59 +00:00
0008-truthful-payment-states.md feat(pay): Phase 6 truthful payment states, and run UI tests in CI 2026-07-29 02:27:44 +00:00
0009-pdf-transparency.md feat(pdf): transparency, and four operator-parsing bugs it exposed 2026-07-31 18:58:31 +00:00
0010-pdf-signatures.md feat(pdf): read signatures, and fix a third ObjRef-destroying resolve 2026-07-31 20:02:29 +00:00
0011-pdf-structure-tree.md feat(pdf): tagged structure tree, and the BMC bug that turned red green 2026-07-31 22:19:45 +00:00
0012-pdf-acroform-full.md feat(pdf): AcroForm actions and validation; JavaScript refused, not run 2026-07-31 22:41:50 +00:00
0013-pdf-xref-streams.md feat(pdf): read xref streams and object streams (PDF 1.5+) 2026-08-16 17:10:42 +00:00
0014-pdf-type3-fonts-and-streaming.md feat(pdf): Type 3 fonts and streaming interpretation — Phase 2 complete 2026-08-16 17:28:44 +00:00
0015-pdf-filters-and-codecs.md fix(pdf): LZW was broken outright; refuse image codecs instead of faking them 2026-08-16 18:04:07 +00:00
0016-pdf-image-decode-surface.md feat(pdf): a real JPEG decoder — the old one was a stub returning black 2026-08-16 18:33:56 +00:00
0017-pdf-declared-versus-delivered.md test(pdf): assert what a file declares is delivered, and floor the coverage 2026-08-16 19:04:57 +00:00
0018-pdf-destinations.md feat(pdf): internal links that actually go somewhere 2026-08-16 19:34:01 +00:00
0019-pdf-document-creation.md feat(pdf): document creation — outlines, forms, attachments, font subsetting 2026-08-16 21:02:19 +00:00
0020-pdf-bitonal-and-wavelet-codecs.md docs(pdf): the four missing ADRs — codecs, Phase 4 completion, editing, redaction 2026-08-18 05:53:36 +00:00
0021-pdf-phase4-completion.md docs(pdf): the four missing ADRs — codecs, Phase 4 completion, editing, redaction 2026-08-18 05:53:36 +00:00
0022-pdf-editing.md docs(pdf): the four missing ADRs — codecs, Phase 4 completion, editing, redaction 2026-08-18 05:53:36 +00:00
0023-pdf-redaction-and-compaction.md docs(pdf): the four missing ADRs — codecs, Phase 4 completion, editing, redaction 2026-08-18 05:53:36 +00:00
0024-pdf-encryption-on-save.md feat(pdf): encryption on save — AES-128 and AES-256 (Phase 6, part one) 2026-08-18 07:27:45 +00:00
0025-pdf-signing-and-verification.md fix(pdf): security review of the signing code — a forgery verified as valid 2026-08-18 10:39:20 +00:00
0026-pdf-signing-security-review.md fix(pdf): security review of the signing code — a forgery verified as valid 2026-08-18 10:39:20 +00:00
0027-pdf-phase6-completion.md feat(pdf): the five Phase 6 bullets the status line omitted 2026-08-18 12:06:59 +00:00
0028-pdf-shading.md feat(pdf): shadings — the sh operator was parsed and thrown away 2026-08-18 17:30:39 +00:00
0029-pdf-mesh-shadings.md fix(pdf): mesh shadings — three bugs in code that had no fixture 2026-08-18 19:10:49 +00:00
0030-pdf-compositing-and-overprint.md feat(pdf): compositing and overprint — the blend maths had no backdrop 2026-08-18 19:25:15 +00:00
0031-pdf-glyph-outlines.md feat(pdf): glyph outlines from TrueType and CFF, and glyph-aware text runs 2026-08-18 19:44:18 +00:00
0032-pdf-nested-content.md feat(pdf): nested content, the wire codec and tiled rendering — Phase 7 closed 2026-08-18 20:00:18 +00:00
0033-pdf-wire-codec-and-tiling.md feat(pdf): render a form XObject to pixels — the golden caught what the 2026-08-18 20:06:50 +00:00
0034-pdf-text-search-and-layout.md feat(pdf): Unicode-aware search and layout-aware reading order 2026-08-19 16:12:12 +00:00