Files
pbakaus_impeccable/browser-bundle
Paul BakausandClaude Fable 5.1 0fea696a7f A snapshot records each line once, a line stops at the gutter, and a design document's directive governs what follows it
The re-review of the first round found four places where the new
measurements reached further than they should.

- The snapshot recorded the rects of every text node *under* each element,
  so a line rendered deep in a page was written down again for every
  ancestor above it. On a deep, text-heavy page that multiplies the
  capture by its depth and can carry it past the byte cap, and a capture
  that fails is a scan that returns nothing at all. Each element records
  only its own text now — one line, one entry — and `text_line_rects`
  assembles an element's lines by walking the tree the capture already
  serialized.

- Merging rects by vertical band alone made two columns that happen to
  sit on the same rows into one page-wide line. A fragment joins a row now
  only when it runs on from it: a horizontal gap no wider than the row's
  own line box. The fragments of a wrapped line are contiguous; a gutter
  is not. An inline image wider than the leading splits its line by the
  same test, which understates a line rather than overstating it, and that
  is the direction this rule should err in.

- In DESIGN.md, where the negative word sits decides what it governs. A
  state ("`.card-old` is deprecated") describes whatever its clause is
  about; a directive ("never use `.x`") condemns what follows it and
  nothing before it. Reading the whole clause for either lost the
  sanctioned half of "Use `.kicker` and never `.tagline`". The headings a
  document uses to retire a set — "Retired components", "Unsupported
  patterns" — are read as negative now, and a heading that names both
  sides ("Dos and Don'ts") heads a section of both, so its subsections are
  what say which is which.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LQBUunp8QttxZqihybNmtL
2026-09-20 19:13:13 -07:00
..

browser-bundle: the page-side JavaScript of the detector

Plain JavaScript that runs inside a page or the extension: the DOM probe the wasm rule core calls back into, the page snapshot producer, the visual-contrast sampling IO, the overlay UI, the scan API and the extension's offscreen document. Measurement and presentation only; every rule decision is a call into the wasm rule core built from crates/core (docs/ENGINE.md).

Two consumers:

  • crates/browser embeds 15-snapshot.js (the snapshot producer the URL engine injects; no WebAssembly runs in the page).
  • crates/bundle (the impeccable-bundle library) embeds every file here with include_str! and concatenates them, in filename order, with the wasm core into the in-page bundle plus the extension's extension/detector/ pieces. cargo xtask bundle is its caller inside this workspace: it writes dist/detect-antipatterns-browser.js, copies that bundle to the tracked crates/live/assets/detect-antipatterns-browser.js the engine embeds, and writes the extension pieces. A downstream crate with its own rule pack calls the library directly (docs/ENGINE.md).

Because the files are embedded, a new one here has to be added to PAGE_JS in crates/bundle/src/lib.rs (and to the order it is concatenated in); a test fails when the two lists disagree.

15-snapshot.js lists the computed-style properties the rules read; the bundle build checks that list against the core's and fails when they drift.