You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
XML reader drops a section that has only a heading, so the provision after it loses its account and chapter headings #525
When a bill's XML gives a section a heading but no text, and puts the provision that heading names in the next element, DeltaTrack drops the heading. The provision then shows a breadcrumb that stops short, with no account name and no chapter name.
Some background, for anyone new to this:
The XML pipeline. DeltaTrack reads a bill either from its PDF or from the tagged XML that GPO publishes. This issue is in the XML reader, src/deltatrack/bill_tree.py. It turns the bill into a list of nodes, one per piece of provision text.
Breadcrumb (heading path). Each node carries the headings above it. display_path is the breadcrumb a reader sees on change cards, in the sidebar and as headings in the Full bill view, e.g. TITLE VII › Agriculture › Office of the Secretary. match_path is a lower-cased twin that the diff engine uses to pair a provision in one version with the same provision in the other.
Appropriations elements. GPO tags spending text with <appropriations-major>, <appropriations-intermediate> and <appropriations-small>, roughly the department, agency and account (the named fund) levels. "Intermediate" is just the middle tag. The reader keeps one "current major" and one "current intermediate" heading as it walks.
Example
116-hr-133 (Consolidated Appropriations Act, 2021), Division N. Sec. 751 is tagged as a <section> holding only its number and the heading "Office of the Secretary". Its next sibling is an <appropriations-intermediate> with no heading, whose text appropriates $11,187,500,000 "for the Office of the Secretary". The report shows no dollar amounts (#671, which removed financial data from reports); the figure is only how to find the provision.
A synthetic copy of that chapter, run on develop (d3935ee, checked 2026-10-05), with the chapter heading "Agriculture programs":
AI1 header='' display_path=('TITLE VII—NUTRITION AND AGRICULTURE RELIEF', 'Agriculture')
S752 display_path=('TITLE VII—NUTRITION AND AGRICULTURE RELIEF', 'Agriculture', 'sec. 752')
Neither "Office of the Secretary" nor "Agriculture programs" appears in either path, or anywhere in the Full bill view text.
Why it matters
A reader sees the provision under "Agriculture" alone, on its change card and in the Full bill view, and has to read the sentence to learn what it funds. Nothing looks broken, so nobody notices.
CI can't see it. No committed XML file has this shape: of the 58 under tests/corpus/, none has a header-only section, and no subtitle, part or chapter mixes sections with appropriations elements (scanned 2026-10-05).
Cause
Two separate steps in src/deltatrack/bill_tree.py:
The section is dropped. In _process_section_element, a section with no body and no subsections emits no node (if body_text or sub_specs:, line 950). Its heading isn't handed on either: _walk_structural_children clears pending_header on every section (line 1016). The hand-on that An account whose name and money sit in separate elements loses its name and files its money under its parent agency #474 added (a header-only element names the untitled one after it, in _process_appro_element, line 669) works only between appropriations elements. Tagged as an appropriations element instead, the same heading is kept.
The chapter heading is overwritten. The untitled element sets the "current intermediate" heading to an empty string (current_intermediate = header, line 739). That erases the chapter's heading for this node and for every section after it in the chapter.
Done when
A test in tests/test_bill_tree.py builds this chapter shape. It asserts that the appropriations node's header_text is "Office of the Secretary" and that its display_path keeps the chapter heading and ends with the account. It fails on develop.
The Full bill view prints "Office of the Secretary" above the provision's text.
The fast suite and uv run pytest -m slow --deselect tests/test_govinfo_corpus_parity.py pass with no pinned baseline changed. No committed file has this shape, so a moved pin means the fix reached further than intended.
If you can fetch 116-hr-133, run the section-coverage gate with CORPUS_SWEEP=1 (which sweeps every bill you have locally, not just the committed set). Post the output.
Scope
In scope: a header-only section followed by an untitled appropriations element, and the emptied chapter heading.
Test file:tests/test_bill_tree.py, class TestWalkTitle, next to test_header_only_sibling_names_the_untitled_body (~line 700). Repro:
title=ET.fromstring(
'<title id="T1"><enum>VII</enum><header>NUTRITION AND AGRICULTURE RELIEF</header>''<subtitle id="ST"><enum>B</enum><header>Agriculture</header>''<chapter id="CH"><enum>1</enum><header>Agriculture programs</header>''<section id="S751"><enum>751.</enum><header>Office of the Secretary</header></section>''<appropriations-intermediate id="AI1"><text>For the Office of the Secretary, $11,187,500,000.</text>''</appropriations-intermediate>''<section id="S752"><enum>752.</enum><header>X</header><text>Provision.</text></section>''</chapter></subtitle></title>')
walk_title(title, "NUTRITION AND AGRICULTURE RELIEF", NO_DIVISION)
The real bill wasn't re-run today: govinfo wasn't reachable from the checking environment. The original report (2026-08-04, at a20d8b5) found Sec. 751 reaching no node in both the engrossed-amendment and enrolled versions.
The real chapter's heading, and whether its sections 752–756 lose it as the synthetic sec. 752 does.
changed the title [-]An $11.19 billion appropriation loses its account heading when a chapter mixes a section with an appropriations element[/-][+]XML reader drops a section that has only a heading, so the provision after it loses its account and chapter headings[/+]on Oct 5, 2026
What's wrong
When a bill's XML gives a section a heading but no text, and puts the provision that heading names in the next element, DeltaTrack drops the heading. The provision then shows a breadcrumb that stops short, with no account name and no chapter name.
Some background, for anyone new to this:
src/deltatrack/bill_tree.py. It turns the bill into a list of nodes, one per piece of provision text.display_pathis the breadcrumb a reader sees on change cards, in the sidebar and as headings in the Full bill view, e.g.TITLE VII › Agriculture › Office of the Secretary.match_pathis a lower-cased twin that the diff engine uses to pair a provision in one version with the same provision in the other.<appropriations-major>,<appropriations-intermediate>and<appropriations-small>, roughly the department, agency and account (the named fund) levels. "Intermediate" is just the middle tag. The reader keeps one "current major" and one "current intermediate" heading as it walks.Example
116-hr-133 (Consolidated Appropriations Act, 2021), Division N. Sec. 751 is tagged as a
<section>holding only its number and the heading "Office of the Secretary". Its next sibling is an<appropriations-intermediate>with no heading, whose text appropriates $11,187,500,000 "for the Office of the Secretary". The report shows no dollar amounts (#671, which removed financial data from reports); the figure is only how to find the provision.A synthetic copy of that chapter, run on
develop(d3935ee, checked 2026-10-05), with the chapter heading "Agriculture programs":Neither "Office of the Secretary" nor "Agriculture programs" appears in either path, or anywhere in the Full bill view text.
Why it matters
A reader sees the provision under "Agriculture" alone, on its change card and in the Full bill view, and has to read the sentence to learn what it funds. Nothing looks broken, so nobody notices.
CI can't see it. No committed XML file has this shape: of the 58 under
tests/corpus/, none has a header-only section, and no subtitle, part or chapter mixes sections with appropriations elements (scanned 2026-10-05).Cause
Two separate steps in
src/deltatrack/bill_tree.py:_process_section_element, a section with no body and no subsections emits no node (if body_text or sub_specs:, line 950). Its heading isn't handed on either:_walk_structural_childrenclearspending_headeron every section (line 1016). The hand-on that An account whose name and money sit in separate elements loses its name and files its money under its parent agency #474 added (a header-only element names the untitled one after it, in_process_appro_element, line 669) works only between appropriations elements. Tagged as an appropriations element instead, the same heading is kept.current_intermediate = header, line 739). That erases the chapter's heading for this node and for every section after it in the chapter.Done when
tests/test_bill_tree.pybuilds this chapter shape. It asserts that the appropriations node'sheader_textis "Office of the Secretary" and that itsdisplay_pathkeeps the chapter heading and ends with the account. It fails ondevelop.match_path. Reusing the An account whose name and money sit in separate elements loses its name and files its money under its parent agency #474 hand-on as-is would add it: in the control run, sec. 752'smatch_pathgainedoffice of the secretary.uv run pytest -m slow --deselect tests/test_govinfo_corpus_parity.pypass with no pinned baseline changed. No committed file has this shape, so a moved pin means the fix reached further than intended.CORPUS_SWEEP=1(which sweeps every bill you have locally, not just the committed set). Post the output.Scope
<quoted-block>in the same bill.Where to start
bill_tree.py:_walk_structural_children(line 979),_process_section_element(870), and the docstring of_process_appro_element(669), which explains the An account whose name and money sit in separate elements loses its name and files its money under its parent agency #474 hand-on.docs/bill-structure.mdfor the XML tags.Test file:
tests/test_bill_tree.py, classTestWalkTitle, next totest_header_only_sibling_names_the_untitled_body(~line 700). Repro:Related open PR: Show every heading the XML tags in its breadcrumb, and measure the ledger on each kind of bill that appropriates #739, a draft that keeps every heading the XML tags in the breadcrumb. It closes The XML reader leaves headings that carry no text of their own out of the breadcrumb #733 and Headings with no text of their own (provision groups, agency containers) are missing from the XML reader's breadcrumbs #521 and is stacked on Show each version's dollar amounts, typed, in three report views #736 and Recover PDF heading structure for the bill ledger, measured by agreement with the XML twin #734. At its head (
e7229c7, checked 2026-10-05) the repro gives the same output asdevelop, so it doesn't fix this. It rewrites these same functions, so expect conflicts if both proceed.Unverified
a20d8b5) found Sec. 751 reaching no node in both the engrossed-amendment and enrolled versions.