Fix Tier-1 regulation citations, ECCN as a Tier-2a shape, and section-rename orphans - #2276
Conversation
The statute forms the extractor was built around ("Section 145 of the DGCL")
use bare integer section numbers introduced by the word "Section". Regulations
do neither: their section numbers are dotted and they are introduced by "§" far
more often than by the spelled-out word. Three shapes were unreachable, and two
of them failed by producing a WRONG key rather than none:
"Section 120.10 of the ITAR" -> nothing (took "120", then wanted " of")
"ITAR Section 120.41" -> itar:120 (the PREFIX — wrong document)
"ITAR § 120.41" -> nothing
"Category XI of the ... List" -> nothing (no Roman-numeral pattern at all)
The second line is the dangerous one: a citation to the definition of
"specially designed" resolved to the Part 120 overview. Every CFR-,
state-admin-code- and municipal-code-style corpus has this citation shape, so
this is not specific to the corpus it was found on.
Adds dotted section numbers, "§"/"§§", part-level citation, and a
Roman-numeral "Category" pattern. All are gated on a registered authority
alias, so "Part 3 of the Agreement" and "Category IV of the Agreement" still
match nothing. The Category divider list is deliberately narrow — widening it
to Title/Article/Chapter would fire against every other authority corpus on an
install for no demonstrated gain.
Measured on a 4,679-section export-control pack: 1 of 12 probed citation
surface forms resolved before, 12 of 12 after.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
"ECCN 3A611" carries no Section/Part/§ token, and the Tier-1 section-number
shape would take "3" and stop at the "A" — so an order-of-review walk that
leaves the USML has no way to cite where it landed.
Placed in the generic grammars rather than the registry extractor, and emitting
a SHAPE-level `eccn:` prefix rather than any pack's own key. The literal "ECCN"
anchors the form, so it is recognisable without knowing whether a Commerce
Control List corpus is installed or what prefix that corpus binds — which is
the same test `usreporter:` and `htsus:` already satisfy.
An earlier revision of this work did the opposite: it put the pattern in the
extractor and emitted `ccl:<code>`, looked up via a hardcoded "ccl" alias
string. That hardcodes one pack's naming convention into core, which is exactly
what the CASE_REPORTER_PREFIX note warns against. A pack carrying the CCL now
maps `eccn:3a611` to its own key with one `equivalences` row.
Anchored on the literal so a bare alphanumeric in prose ("Model 3A611 shipped
in lot 5A002") cannot become a citation. Keys are lowercased, which is required
rather than incidental: ECCNs are conventionally written uppercase and
authority-key matching is case-sensitive on the section part, so an uppercase
key would be unreachable from any real citation.
Seven grammar tests, plus two in the Tier-1 suite that assert the boundary
holds — the tempting "just add it where the other patterns are" fix
reintroduces the leak silently and nothing else would fail.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
`bootstrap_authority_corpus` located the existing document by canonical key, then handed the write to `create_or_update_text_document`, which derives the corpus path from the TITLE. A section whose heading changed between installs was therefore written to a NEW path while the previous document stayed current — both carrying the same `custom_meta.canonical_key`. `find_authority_target` orders by id and takes the first, so the SUPERSEDED document won every lookup and the key silently served stale text. On a real pack rebuild this left all 21 USML categories serving "[STUB — replace with verbatim text]" at IMPLEMENTING weight. The only signal anywhere was "21 created, 0 updated" in the install summary; no check in the installer, the pack validator or a duplicate-key scan could see it. Now routes the write at the existing document's path and renames the new version, so a rename versions up instead of forking. Also fixes an unrelated local-stack papercut found alongside it: the Django setting for the warp-ingest API key defaults to "" while the service defaults to "abc123", so a stock `--profile warp-ingest` stack sent an empty X-API-Key and warp-ingest 401'd every PDF parse. Both sides now resolve from the same variable with the same default. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Companion pack change: Open-Source-Legal/authority-packs#10, which adds the 638 Worth stating explicitly for reviewers: the ECCN half of this PR is a breaking change for any install carrying a Commerce Control List corpus until that pack change lands. Before, core emitted The other two commits (Tier-1 regulation shapes, section-rename orphans) are independent of the pack and safe on their own. |
|
Review Solid, well-scoped fix. Three independent, well-tested defects with clear regression coverage and honest commit messages about what was tried and rejected ( Findings
Things verified and liked
Minor
No security or performance concerns — the new patterns are all linear-time (no nested unbounded quantifiers), and the DB-touching change ( |
ReviewOverall this is a well-scoped, well-tested fix — three independent, clearly-motivated defects, each with regression tests that were confirmed to fail against the unfixed code. The Tier-1 vs Tier-2a boundary reasoning for ECCNs (shape-level One correctness bug found, plus a couple of minor nits. Bug: ECCN paragraph-suffix regex swallows a trailing sentence period
_ECCN_RE = re.compile(
r"\bECCNs?\s+(?P<code>\d[A-E]\d{3}(?:\.[a-z0-9.]+)?)",
re.IGNORECASE,
)The paragraph-suffix group vs. the non-sentence-final case, which is correct: So None of the new tests in Suggested fix: require the char after each internal dot to include at least one non-dot alphanumeric before allowing another dot, e.g. something like Minor nits (non-blocking)
Nice touches worth calling out
|
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
…ces, not one row The comments, changelog fragment and test docstrings claimed a pack folds eccn: shape keys onto its own "with one equivalences row". That mechanism does not exist: AuthorityKeyEquivalence is strictly per-key and pack-declared rewrite_rules are deliberately never loaded, so the real fold is one generated row per ECCN (authority-packs#11 adds the 638 rows to the ear pack, mirroring its existing act:eccn-* rows). State that accurately everywhere the claim appeared. No behavior change.
ReviewRead through all four commits (Tier-1 regulation citations, ECCN Tier-2a grammar, section-rename version-up, warp-ingest local.yml default) plus the new/changed tests. Overall this is a well-scoped, well-documented fix — the commit messages and inline comments do a good job explaining why each pattern/boundary exists, and the regression tests are specific enough to catch the "tempting wrong fix" the comments warn about (e.g. I traced the new regexes ( Possible gap: heading-only renames (unchanged body text) still leave a stale
|
Three defects found while installing an export-control authority pack against a
live instance. Each failed silently, and two produced wrong answers rather
than missing ones.
They are separate commits and can be reviewed independently.
1. Tier-1 could not read a regulation citation
The statute forms the extractor was built around use bare integer section
numbers introduced by the word "Section". Regulations do neither.
Section 120.10 of the ITARitar:120.10ITAR Section 120.41itar:120← wrong documentitar:120.41ITAR § 120.41itar:120.4122 C.F.R. § 126.1itar:126.1Part 122 of the ITARitar:122Category XI of the United States Munitions Listusml:xiRow 2 is the dangerous one: a citation to the definition of "specially
designed" resolved to the Part 120 overview.
This is not corpus-specific — every CFR-, state-admin-code- and
municipal-code-style corpus has these shapes.
All new patterns are gated on a registered authority alias, so
Part 3 of the AgreementandCategory IV of the Agreementstill match nothing. TheCategorydivider list is deliberately narrow; widening it toTitle/Article/Chapter would fire against every other authority corpus for no
demonstrated gain.
2. ECCNs, as a Tier-2a shape
ECCN 3A611carries no Section/Part/§ token and the section-number shape wouldtake
3and stop at theA.Added to
grammars.pyemitting a shape-leveleccn:prefix, not a pack'sown key — the same test
usreporter:andhtsus:satisfy. An earlier revisionof this work put it in
extractor.pyand emittedccl:<code>via a hardcoded"ccl"alias lookup, which bakes one pack's naming convention into core. Apack carrying the CCL maps
eccn:3a611to its own key with oneequivalencesrow.
Two tests in the Tier-1 suite assert that boundary holds, because the tempting
"just add it where the other patterns are" fix reintroduces the leak silently
and nothing else would fail.
3. Renaming a section stranded its document
bootstrap_authority_corpusfound the existing document by canonical key, thenwrote through a helper that derives the corpus path from the title. A
section whose heading changed was written to a new path while the old document
stayed current — both carrying the same
canonical_key.find_authority_targetorders by
idand takes the first, so the superseded document won and thekey silently served stale text.
On a real rebuild this left all 21 USML categories serving
[STUB — replace with verbatim text]at IMPLEMENTING weight. The only signalanywhere was
21 created, 0 updatedin the install summary.Also fixes an unrelated local-stack papercut found alongside it: the Django
setting for the warp-ingest API key defaults to
""while the service defaultsto
abc123, so a stock--profile warp-ingeststack 401'd every PDF parse.Testing
test_enrichment_extractor_regulations,test_authority_section_rename,test_generic_grammars,test_enrichment_extractor,test_customs_trade_grammars,test_llm_citation_extractorfail against the unfixed code
pre-commit rungreen afterpre-commit clean, so the hook envs wererebuilt from scratch rather than resolved from cache
Measured end to end
On a clean install of a 4,679-section export-control domain pack: 1 of 12
probed citation surface forms resolved before, 12 of 12 after. The document
corpus then formed 157 reference edges, 155 resolved (98.7%) across 12
prefixes — the most-cited keys being exactly the dotted forms that previously
yielded nothing or the wrong key.
🤖 Generated with Claude Code