Skip to content

PDF report shows a false "Moved" card when only a heading's line wrap changed #648

Open

Description

@willhea

Re-scoped 2026-10-07 (comment).

What's wrong

In a PDF comparison, the report can say a heading was "Renumbered" when the heading is printed identically in both versions and only its line break moved.

Some background, for anyone new to this:

  • PDF pipeline. DeltaTrack can compare two printed PDFs of a bill. The PDF reader infers headings and sections from the print.
  • Anchors. An anchor is the label the PDF reader records where a section or heading starts, taken from the printed heading text.
  • Change cards and moved cards. The report lists each change as a card. When the two versions' text is matched but sits in a different place, the card is "moved". The card then reads either Moved: <old breadcrumb> → <new breadcrumb> or Renumbered: <old label> → <new label>.
  • Canonical diff. This is the JSON both pipelines produce (schema/canonical-diff.md). There, move.kind is renumbered when "the section's anchor identifier changed", and relocated otherwise.

Example (checked 2026-10-05 on develop, d3935ee)

118-hr-4366 (FY2024 appropriations), Senate calendar print (v3) → Senate amendment (v4). Both print FAMILY HOUSING OPERATION AND MAINTENANCE, NAVY AND MARINE CORPS, wrapped differently:

  • v3, p. 10: FAMILY HOUSING OPERATION AND MAINTENANCE, / NAVY AND MARINE CORPS
  • v4, p. 15: FAMILY HOUSING OPERATION AND MAINTENANCE, NAVY / AND MARINE CORPS

The report says Renumbered: NAVY AND MARINE CORPS → AND MARINE CORPS. The same pair also reports Renumbered: ARMY → FAMILY HOUSING OPERATION AND MAINTENANCE, ARMY.

Reproduce (about 5 seconds):

uv run ./diff_pdf.py tests/corpus/118-hr-4366/3_placed-on-calendar-senate.pdf \
  tests/corpus/118-hr-4366/4_engrossed-amendment-senate.pdf --format json -o out.json

Across the 17 PDF pairs the product accepts, develop produces:

  • 161 moved cards, 153 of them "Renumbered".
  • 130 of those are SEC. n → SEC. m. Not checked one by one; most are likely genuine.
  • 23 are heading labels. Most are fragments of a wrapped heading: FACILITIES → STATE EXTENDED CARE FACILITIES, POWER ADMINISTRATION → ADMINISTRATION, DEBT → FEDERAL DEBT. Three were checked against the printed page lines, and all three are wrap-only.
  • Of those 23, 3 look like genuine heading edits: ENERGY SECURITY → ENERGY SECRUITY, RELATED AGENCY → RELATED AGENCIES and ADMINISTRATIVE PROVISION → PROVISIONS.

Why it matters

A staffer is told that a provision was renamed or renumbered when it wasn't. That is a false statement in the part of the report meant to say what changed, and it looks the same as a real one. The pairs where it happens are re-typeset amendments, which are exactly the comparisons staff run.

Cause

There are two places:

  1. The PDF reader takes a heading from one printed line. A wrapped heading becomes a fragment that depends on where the line broke. This is the same root as In PDFs, a long account name that wraps onto a second line shows up as a fake agency plus a fragment account #524 (a wrapped account heading read as an agency plus an account) and Reading a bill from PDF, headings printed across more than one line get the wrong name or parent #732 (headings spanning more than one printed line are misread). Recover PDF heading structure for the bill ledger, measured by agreement with the XML twin #734 (the open PR that rewrites PDF heading detection) addresses it.
  2. _pdf_move labels any text difference "renumbered". It is in src/deltatrack/formatters/canonical.py:262-274, and _move_info_html (lines 521-536) prints it. It compares raw anchor text: any difference becomes "renumbered", including a heading edit, which is not a renumbering. Recover PDF heading structure for the bill ledger, measured by agreement with the XML twin #734 doesn't touch it.

Where #734 leaves this (checked 2026-10-05, #734 head e3d3926)

The same census gives 144 moved cards and 137 "Renumbered": the same 130 SEC. cards and 7 heading labels.

  • Gone: every wrap-only fragment above, including NAVY AND MARINE CORPS. The 2026-09-28 comment on this issue said that case was not fixed; it predates Recover PDF heading structure for the bill ledger, measured by agreement with the XML twin #734's last commits.
  • Kept, correctly: the 4 genuine renumberings in 115-hr-5895 (SEC. 103 → SEC. 102, 104 → 103, 105 → 104, 107 → 105), and the 3 heading edits above.
  • Still doubtful, and not about wrapping:
    • ELECTRICITY DELIVERY → NUCLEAR ENERGY and SEC. 5 → PROHIBITION ON USE OF FUNDS, both also on develop. They look like two different sections paired together.
    • a new crossed pair in 115-hr-5895: DEPARTMENT OF DEFENSE FAMILY HOUSING IMPROVEMENT FUND → MILITARY UNACCOMPANIED HOUSING IMPROVEMENT FUND, and the reverse.

Done when

  • On 115-hr-5895 and 118-hr-4366, no "Renumbered" card appears for a heading whose printed text is the same in both versions. (Holds since Decide a move's kind in the differ, by one rule on both pipelines #820. Now: no moved card at all for such a heading.)
  • The genuine SEC. renumberings in 115-hr-5895 are still reported.
  • The genuine heading edits (SECRUITY, AGENCY → AGENCIES) are still reported as changes.
  • A test pins these cases. The suite passes today with the defect present, so a passing suite is not proof.
  • The PDF canonical baseline (tests/data/pdf_canonical_baseline.json) is regenerated on purpose, and its diff is reviewed row by row.

Scope

Where to start

Unverified

  • Whether the 130 SEC. renumberings are all genuine.
  • Whether wrapping also affects the table of contents or the Full bill view. Only change cards were measured.
  • Bills outside the committed corpus.

History

The first measurement, at d5a1ad0, found 156 of 165 moved cards reading "Renumbered". The 2026-09-28 comment on this issue measured #734 at 156 → 143 against develop at c636448. The 2026-10-05 counts above were taken before #820; the 2026-10-07 comment has the counts after it.

Activity

  1. mattzamora commented on Sep 28, 2026

    @mattzamora
    Contributor

    #734 fixes wrapped-heading assembly in the parser (#732, a PDF heading whose structure spans more than one printed line is misread). As this issue asks, here is the consequence checked rather than assumed, over the 17 production-accepted adjacent pairs of the committed corpus, develop at c636448 against the branch:

    • Moved cards that render Renumbered: X -> Y: 156 → 143.
    • Fixed, among others: GINIA.— -> WEST VIRGINIA.—, ARMY -> FAMILY HOUSING OPERATION AND MAINTENANCE, ARMY, TRATION -> MAINTENANCE, WESTERN AREA POWER ADMINISTRATION, DEBT -> FEDERAL DEBT, FACILITIES -> STATE EXTENDED CARE FACILITIES.
    • Still reported, as the verification section requires: the genuine renumberings in 115-hr-5895 (SEC. 103 -> SEC. 102, SEC. 104 -> SEC. 103, SEC. 105 -> SEC. 104, SEC. 107 -> SEC. 105) and the heading edit where the new version is misspelled (…ENERGY SECURITY… -> …ENERGY SECRUITY…).
    • Not fixed: FAMILY HOUSING OPERATION AND MAINTENANCE, NAVY AND MARINE CORPS, in both 115-hr-5895 and 118-hr-4366. The old side now reads the whole name, but the Senate strike-all print still yields AND MARINE CORPS on its own, so the card now reads FAMILY HOUSING OPERATION AND MAINTENANCE, NAVY AND MARINE CORPS -> AND MARINE CORPS.
    • Some cards now compare two whole names that the two versions joined differently (SECURITY INVESTMENT PROGRAM -> NORTH ATLANTIC TREATY ORGANIZATION SECURITY INVESTMENT PROGRAM): the same root cause in a milder form.
    • The second site named above, formatters/canonical._pdf_move, is untouched.

    So #734 advances this issue rather than closing it.

  2. added a commit that references this issue on Oct 4, 2026
  3. changed the title [-]PDF diff reports sections as renamed when only the line wrapping changed[/-] [+]PDF report says a heading was "Renumbered" when only its line wrap changed[/+] on Oct 5, 2026
  4. willhea commented on Oct 7, 2026

    @willhea
    CollaboratorAuthor

    Update after #820 (move kind decided by the differ, merged 2026-10-07), and re-scope. Measured on develop at 7076771, over the 17 PDF pairs production accepts.

    Cause 2 is fixed. _pdf_move's raw-text comparison is gone. move.kind now comes from the differ (move_kind.py), which calls a move renumbered only when a section number changed.

    • 161 moved cards: 113 renumbered, 17 relocated_and_renumbered, 31 relocated.
    • No card whose label is not SEC. n is renumbered any more (was 23). So no card reads "Renumbered: NAVY AND MARINE CORPS → AND MARINE CORPS".

    Cause 1 is not, and it now shows up as a false "Moved" card. The wrap fragments are relocated instead of renumbered. The card still says a provision moved when it was only printed with a different line break. 30 moved cards have a label that is not SEC. n on at least one side:

    What Cards Examples
    Wrap fragment (the heading is the same; only where its line broke differs) 18 NAVY AND MARINE CORPS → AND MARINE CORPS and ARMY → FAMILY HOUSING OPERATION AND MAINTENANCE, ARMY (both in 115-hr-5895 and 118-hr-4366 v3→v4), DEBT → FEDERAL DEBT, POWER ADMINISTRATION → ADMINISTRATION, FACILITIES → STATE EXTENDED CARE FACILITIES, HOUSING IMPROVEMENT FUND → FUND, ACTIVITIES → LEGAL ACTIVITIES
    Genuine heading edit 3 ENERGY SECURITY → ENERGY SECRUITY, RELATED AGENCY → RELATED AGENCIES, ADMINISTRATIVE PROVISION → PROVISIONS
    Same label, different place 7 (a) IN GENERAL ×3, SALARIES AND EXPENSES, DEPARTMENTAL ADMINISTRATION, CAPITAL CONSTRUCTION AND OPERATIONS, STATE OF MISSISSIPPI.—
    Doubtful pairing, not about wrapping 2 ELECTRICITY DELIVERY → NUCLEAR ENERGY, SEC. 5 → PROHIBITION ON USE OF FUNDS

    The 18 fragments are the reading of a heading from one printed line, which #734 rewrites. It measured every wrap-only fragment gone on 2026-10-05 (its head e3d3926), apart from the strike-all print's AND MARINE CORPS, per the comment above. #734 still awaits re-review, and its base (c636448) is behind develop by #800–#827.

    Re-scope. Title changed to name what's left: a false "Moved" card from a wrapped heading. What changes in the "Done when" list:

    • "No 'Renumbered' card for an unchanged heading" holds now. It becomes no moved card at all for a heading whose printed text is the same in both versions.
    • The _pdf_move half of "In scope" is done.
    • The rest stands: the SEC. renumberings in 115-hr-5895 stay reported, the 3 heading edits stay reported, and there's a test and a reviewed PDF-baseline regeneration.

    This stays blocked on #734. The 2 doubtful pairings remain out of scope here.

    To reproduce the table: run compare_pdfs over the accepted keys of tests/data/pdf_canonical_baseline.json, and list the changes with a move whose last path label on either side doesn't start with SEC.


    Generated by Claude Code

  5. changed the title [-]PDF report says a heading was "Renumbered" when only its line wrap changed[/-] [+]PDF report shows a false "Moved" card when only a heading's line wrap changed[/+] on Oct 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions