Skip to content

fix(markdown): reject non-text strikeout rules - #253

Merged
abimaelmartell merged 4 commits into
mainfrom
abi/fix-strikeout-false-positives
Aug 4, 2026
Merged

fix(markdown): reject non-text strikeout rules#253
abimaelmartell merged 4 commits into
mainfrom
abi/fix-strikeout-false-positives

Conversation

@abimaelmartell

@abimaelmartell abimaelmartell commented Aug 4, 2026

Copy link
Copy Markdown
Member

Summary

Tightens geometric strikeout detection so a horizontal rule must be snugly owned by a contiguous text row and isolated from connected diagram geometry. This prevents bullets, formula bars, signature lines, chart rules, and schematic connectors from being emitted as deleted text while preserving genuine redline strikeouts.


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.


Summary by cubic

Tightened strikeout detection so only real text strikeouts are marked. Handles split runs, inline scripts, and small baseline drift, and rejects non-text lines like connectors, bullets, chart rules, and thin filled connectors.

  • Bug Fixes
    • Require a strike rule to be “owned” by a contiguous text row within a small em-based pad; ignore bullets.
    • Include adjacent numeric super/subscripts and group slight baseline drift in the owner to keep marks across script merges and split runs.
    • Reject rules connected to vertical/diagonal segments or thin, vertically elongated filled rectangles; skip chart rules that end inside short labels; allow broad fills behind text.
    • Compute ownership once per rule for consistent marking; added tests for connectors (incl. filled rects), short-label chart rules, bullets, split runs, baseline drift, and inline scripts.

Written for commit f729f92. Summary will update on new commits.

Review in cubic

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 1 file

Shadow auto-approve: would not auto-approve because issues were found.

Fix all with cubic | Re-trigger cubic

Comment thread src/extractor/underline.rs Outdated
Comment thread src/extractor/underline.rs Outdated
Comment thread src/extractor/underline.rs Outdated
@abimaelmartell

Copy link
Copy Markdown
Member Author

Addressed all three findings in 1843a29: bare list markers are excluded, ownership is computed once per rule, and inline numeric super/subscripts remain part of genuine strikeouts. Added direct regression coverage for each case.

@cubic-dev-ai please re-review.

@cubic-dev-ai

cubic-dev-ai Bot commented Aug 4, 2026

Copy link
Copy Markdown

Addressed all three findings in 1843a29: bare list markers are excluded, ownership is computed once per rule, and inline numeric super/subscripts remain part of genuine strikeouts. Added direct regression coverage for each case.

@cubic-dev-ai please re-review.

@abimaelmartell I have started the AI code review. It will take a few minutes to complete.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 1 file

Shadow auto-approve: would not auto-approve because issues were found.

Fix all with cubic | Re-trigger cubic

Comment thread src/extractor/underline.rs
@abimaelmartell

Copy link
Copy Markdown
Member Author

Addressed the filled-rectangle connectivity finding in 874919a. Candidate strike rules are now vetoed by connected narrow vertical fills, while broad background fills remain supported. Added coverage for both cases.

@cubic-dev-ai please re-review.

@cubic-dev-ai

cubic-dev-ai Bot commented Aug 4, 2026

Copy link
Copy Markdown

Addressed the filled-rectangle connectivity finding in 874919a. Candidate strike rules are now vetoed by connected narrow vertical fills, while broad background fills remain supported. Added coverage for both cases.

@cubic-dev-ai please re-review.

@abimaelmartell I have started the AI code review. It will take a few minutes to complete.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 1 file

Shadow auto-approve: would not auto-approve because issues were found.

Fix all with cubic | Re-trigger cubic

Comment thread src/extractor/underline.rs
@abimaelmartell

Copy link
Copy Markdown
Member Author

Addressed the baseline-drift finding in f729f92. Strike ownership now shares the extractor’s 5pt row tolerance, with direct coverage for split runs on shifted baselines.

@cubic-dev-ai please re-review.

@cubic-dev-ai

cubic-dev-ai Bot commented Aug 4, 2026

Copy link
Copy Markdown

Addressed the baseline-drift finding in f729f92. Strike ownership now shares the extractor’s 5pt row tolerance, with direct coverage for split runs on shifted baselines.

@cubic-dev-ai please re-review.

@abimaelmartell I have started the AI code review. It will take a few minutes to complete.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 1 file

Shadow auto-approve: would require human review. The diff is truncated, so the full ownership heuristic and its tests are not visible; I cannot verify that tightened strikeout detection preserves genuine redlines while rejecting non-text rules. This tradeoff needs human review.

Re-trigger cubic

@abimaelmartell
abimaelmartell merged commit 7747b3a into main Aug 4, 2026
8 checks passed
abimaelmartell added a commit that referenced this pull request Aug 4, 2026
CI checks out a merge of the PR head with main, and main advanced 8
commits since this branch was cut — including #201 (contextual digit
runs), #240 and #253 (markdown fixes). Those change extraction output,
so a snapshot generated on the unmerged branch could not match; the
Test job failed on the merge commit while passing on the branch itself.

The merged behaviour is better: the footnote marker '2' before
'Hartley, R. V. L.' is now recovered instead of dropped.

950 tests pass on the merged tree, clippy clean.
abimaelmartell added a commit that referenced this pull request Aug 5, 2026
#241)

* fix(extractor): supply built-in metrics for non-embedded base-14 fonts

PDFs may legally omit /Widths for non-embedded standard fonts (Times,
Helvetica, Courier, Symbol, ZapfDingbats) — the spec requires the reader
to supply the metrics. We returned None, so every glyph advanced 0 and
each text item got width 0, silently breaking every gap-based heuristic
downstream: space synthesis, sub/superscript detection, table column
detection, heading merging.

- src/extractor/base14.rs: Adobe Core-14 AFM width tables keyed by
  Unicode char, plus the standard Symbol/ZapfDingbats encoding vectors
  (their glyphs sit at byte positions unrelated to Latin text, so widths
  must resolve through the built-in encoding, not cp1252)
- Width resolution order: Differences -> built-in encoding -> the same
  cp1252-style fallback the text decoder uses, so a code's advance always
  matches the character we emit for it
- Type3 visual sizing: PK bitmap fonts (dvips) use FontMatrix
  [1 0 0 -1 0 0] with nominal sizes like 0.12pt; scale by FontBBox height
  x |matrix_y|. Applied in the page-stream and Form XObject paths.
  Indirect numeric array elements are resolved before use.

Effect on Shannon's 'A Mathematical Theory of Communication' (1998
dvips/Distiller, the reported case): glued sentences 95 -> 5. Corpus
impact: 12 of 184 eval documents, e.g. Data-Processing-Agreement
recovers a paragraph that a phantom table had shredded into cells.

Layout heuristics tuned on the same document (indent-based paragraph
breaks, heading reclassification, table script filtering) are held back
for a separate PR — they change ~98 further documents and need to be
justified against the corpus, not against one PDF.

* review: narrow Type3 rescaling to self-inconsistent fonts; dedup + test all width tables

Addresses cubic review on #241, plus a follow-up from a local cubic run.

- Type3 visual scaling was applied to every Type3 font whose FontBBox
  height x |matrix_y| deviated >5% from 1.0. FontBBox is the glyph box,
  not the em box, so a conventional 1/1000-matrix font with a
  descender..ascender bbox (~700 units) computed 0.7 and had every
  reported size shrunk by 30% — corrupting the drop-cap, heading-tier,
  sub/superscript and table heuristics this is meant to fix.

  First attempt gated on the matrix being unit-scale, but a local cubic
  run pointed out that wrongly excludes valid non-standard matrices (a
  0.005 matrix with a full-em bbox legitimately needs a 5x scale). The
  product is the right discriminator, not the matrix: a self-consistent
  font lands near 1.0 because the matrix is the reciprocal of the
  glyph-space em, so only a wildly inconsistent one (dvips/PK bitmap
  fonts sit at ~159) is renormalized. Band widened to [0.25, 4.0].

  Corpus effect: 12 -> 7 documents change. The 5 that drop out were
  being wrongly rescaled — including Data-Processing-Agreement, whose
  phantom-table fix turned out to come from this bug rather than from
  the width fallback, so it is correctly given up.

- base14: all 14 width tables now covered by the sort-invariant test via
  an ALL_TABLES registry, not a hand-picked subset.
- base14: identical tables share one static (all four Courier variants
  are monospace 600; the oblique Helvetica variants match their upright
  forms), removing 5 duplicate copies.

* test: refresh Shannon snapshot after merging main

CI checks out a merge of the PR head with main, and main advanced 8
commits since this branch was cut — including #201 (contextual digit
runs), #240 and #253 (markdown fixes). Those change extraction output,
so a snapshot generated on the unmerged branch could not match; the
Test job failed on the merge commit while passing on the branch itself.

The merged behaviour is better: the footnote marker '2' before
'Hartley, R. V. L.' is now recovered instead of dropped.

950 tests pass on the merged tree, clippy clean.
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