feat(bib): --docket scope for backfill-comments; drop ocr stub from refarm
All checks were successful
CI / lint (push) Successful in 34s
CI / notebooks-smoke (push) Successful in 1m28s
Deploy / notebooks (push) Has been skipped
Deploy / zotero (push) Has been skipped
Deploy / docs (push) Has been skipped
Deploy / api (push) Has been skipped
Deploy / llm (push) Has been skipped
Deploy / mc (push) Has been skipped
Infra CI / notebooks (push) Successful in 3m33s
Infra CI / zotero (push) Successful in 23s
Infra CI / docs (push) Successful in 1m34s
Infra CI / api (push) Successful in 1m5s
Infra CI / llm (push) Successful in 49s
Infra CI / mc (push) Successful in 13s
Deploy / report (push) Successful in 15s
CI / test (push) Successful in 17m10s
Harden / build-scan-report (push) Successful in 18m38s
Notebooks Integration / notebooks-integration (push) Successful in 7m29s
Renovate / renovate (push) Successful in 18s
Zotero Sync / zotero-sync (push) Successful in 1m13s
Package Supply Chain / pkg-supply-chain (push) Successful in 1m0s
All checks were successful
CI / lint (push) Successful in 34s
CI / notebooks-smoke (push) Successful in 1m28s
Deploy / notebooks (push) Has been skipped
Deploy / zotero (push) Has been skipped
Deploy / docs (push) Has been skipped
Deploy / api (push) Has been skipped
Deploy / llm (push) Has been skipped
Deploy / mc (push) Has been skipped
Infra CI / notebooks (push) Successful in 3m33s
Infra CI / zotero (push) Successful in 23s
Infra CI / docs (push) Successful in 1m34s
Infra CI / api (push) Successful in 1m5s
Infra CI / llm (push) Successful in 49s
Infra CI / mc (push) Successful in 13s
Deploy / report (push) Successful in 15s
CI / test (push) Successful in 17m10s
Harden / build-scan-report (push) Successful in 18m38s
Notebooks Integration / notebooks-integration (push) Successful in 7m29s
Renovate / renovate (push) Successful in 18s
Zotero Sync / zotero-sync (push) Successful in 1m13s
Package Supply Chain / pkg-supply-chain (push) Successful in 1m0s
An unscoped 'bib backfill-comments' walks every un-enriched reg.gov stub in the store (~167k) at the 970/hr rate cap — a week-long crawl that buried the freshly farmed CMS-2026-2377 comments (highest item ids, ORDER BY i.id) at the back of the queue and blocked the P37 extract/index chain behind it. backfill_details now takes docket=, filtering on the store's reg-docket:<id> tag, and the CLI forwards --docket. The September refarm script uses it, and no longer calls comments extract-ocr, a phase-2 stub that always exits 2 (#253) and would have logged a spurious failed step every run. refs #615
This commit is contained in:
@@ -17,9 +17,10 @@ echo "=== re-farm run $(date -Is) ==="
|
||||
FAILURES=0
|
||||
|
||||
uv run stack bib fetch-pfs-comments || { echo "WARN: fetch-pfs-comments rc=$?"; FAILURES=$((FAILURES+1)); }
|
||||
uv run stack bib backfill-comments || { echo "WARN: backfill rc=$?"; FAILURES=$((FAILURES+1)); }
|
||||
uv run stack bib backfill-comments --docket CMS-2026-2377 || { echo "WARN: backfill rc=$?"; FAILURES=$((FAILURES+1)); }
|
||||
uv run stack comments extract --docket CMS-2026-2377 || { echo "WARN: extract rc=$?"; FAILURES=$((FAILURES+1)); }
|
||||
uv run stack comments extract-ocr --docket CMS-2026-2377 || { echo "WARN: ocr rc=$?"; FAILURES=$((FAILURES+1)); }
|
||||
# extract-ocr is a phase-2 stub (always exits 2, no --docket) — see #253.
|
||||
# ocr_needed attachments stay flagged in combined.md frontmatter for now.
|
||||
uv run stack llm index --collection comments --docket CMS-2026-2377 \
|
||||
|| { echo "WARN: index rc=$?"; FAILURES=$((FAILURES+1)); }
|
||||
|
||||
|
||||
@@ -377,6 +377,7 @@ def backfill_details(
|
||||
store: Store,
|
||||
client: Client,
|
||||
*,
|
||||
docket: str = "",
|
||||
limit: int | None = None,
|
||||
log_path: Path | None = None,
|
||||
commit_every: int = 25,
|
||||
@@ -403,6 +404,19 @@ def backfill_details(
|
||||
# Using a tag (not just the abstract) lets us handle "see attached"
|
||||
# comments with near-empty body AND still drives distinct retry
|
||||
# states (``enriched:gone`` for 404s, untagged for transient fails).
|
||||
docket_clause = ""
|
||||
params: list[str] = []
|
||||
if docket:
|
||||
# Scope to one docket so a fresh farm enriches in hours, not the
|
||||
# multi-day full-store crawl (reg.gov's 1000/hr cap is binding).
|
||||
# ``reg-docket:`` is the store's docket tag (``docket:`` is the
|
||||
# empty-valued wart — see llm/source.py).
|
||||
docket_clause = """
|
||||
AND i.id IN (
|
||||
SELECT item_id FROM item_tags
|
||||
WHERE tag_id IN (SELECT id FROM tags WHERE name = ?)
|
||||
)"""
|
||||
params.append(f"reg-docket:{docket}")
|
||||
rows = con.execute(
|
||||
"""
|
||||
SELECT i.id, i.key, i.url
|
||||
@@ -415,9 +429,11 @@ def backfill_details(
|
||||
SELECT item_id FROM item_tags
|
||||
WHERE tag_id IN (SELECT id FROM tags WHERE name IN ('enriched:ok','enriched:gone'))
|
||||
)
|
||||
ORDER BY i.id
|
||||
"""
|
||||
+ (f" LIMIT {int(limit)}" if limit else "")
|
||||
+ docket_clause
|
||||
+ " ORDER BY i.id"
|
||||
+ (f" LIMIT {int(limit)}" if limit else ""),
|
||||
params,
|
||||
).fetchall()
|
||||
|
||||
stats = {
|
||||
|
||||
@@ -338,6 +338,13 @@ def ingest_mail(
|
||||
|
||||
@app.command(name="backfill-comments")
|
||||
def backfill_comments(
|
||||
docket: str = typer.Option(
|
||||
"",
|
||||
"--docket",
|
||||
help="Limit to one docket (e.g. CMS-2026-2377). Without it the "
|
||||
"walk covers every un-enriched stub in the store — a multi-day "
|
||||
"crawl at the reg.gov rate cap.",
|
||||
),
|
||||
limit: int = typer.Option(
|
||||
0,
|
||||
"--limit",
|
||||
@@ -374,6 +381,7 @@ def backfill_comments(
|
||||
stats = backfill_details(
|
||||
store,
|
||||
api,
|
||||
docket=docket,
|
||||
limit=limit or None,
|
||||
log_path=log_path,
|
||||
)
|
||||
|
||||
@@ -144,6 +144,43 @@ class TestUpsertComment:
|
||||
|
||||
|
||||
class TestBackfillDetails:
|
||||
def test_docket_scope_limits_candidates(self, tmp_path):
|
||||
"""docket= restricts the walk to that docket's stubs, so a
|
||||
freshly farmed docket enriches without a full-store crawl."""
|
||||
from bib.item import Item
|
||||
from bib.store import Store
|
||||
|
||||
store = Store(str(tmp_path / "bib.sqlite"), storage_dir=tmp_path / "storage")
|
||||
for docket, cid in [
|
||||
("CMS-2026-2377", "CMS-2026-2377-0001"),
|
||||
("CMS-2025-0304", "CMS-2025-0304-0001"),
|
||||
]:
|
||||
store.create(
|
||||
Item(
|
||||
item_type="source",
|
||||
title=f"comment {cid}",
|
||||
url=f"https://www.regulations.gov/comment/{cid}",
|
||||
tags=["source:regulations-gov", f"reg-docket:{docket}"],
|
||||
)
|
||||
)
|
||||
|
||||
api = MagicMock()
|
||||
api.get_comment_detail.return_value = {
|
||||
"data": {"attributes": {"comment": "Body", "organization": "Org"}},
|
||||
"included": [],
|
||||
}
|
||||
stats = backfill_details(
|
||||
store,
|
||||
api,
|
||||
docket="CMS-2026-2377",
|
||||
log_path=tmp_path / "log.txt",
|
||||
scratch_root=tmp_path / "scratch",
|
||||
)
|
||||
store.close()
|
||||
|
||||
assert stats["enriched"] == 1
|
||||
api.get_comment_detail.assert_called_once_with("CMS-2026-2377-0001")
|
||||
|
||||
def test_basic_enrichment(self, tmp_path):
|
||||
store = MagicMock()
|
||||
con = MagicMock()
|
||||
|
||||
@@ -343,6 +343,22 @@ class TestBackfillComments:
|
||||
assert result.exit_code == 0
|
||||
assert "enriched" in result.output
|
||||
|
||||
@patch("bib.connect")
|
||||
@patch("bib.regulations_gov.Client")
|
||||
@patch("bib.regulations_gov.backfill_details", return_value={"enriched": 1})
|
||||
def test_docket_forwarded(self, mc_backfill, mc_client_cls, mc_connect):
|
||||
store = MagicMock()
|
||||
mc_connect.return_value = store
|
||||
|
||||
api = MagicMock()
|
||||
api.__enter__ = MagicMock(return_value=api)
|
||||
api.__exit__ = MagicMock(return_value=False)
|
||||
mc_client_cls.return_value = api
|
||||
|
||||
result = runner.invoke(app, ["backfill-comments", "--docket", "CMS-2026-2377"])
|
||||
assert result.exit_code == 0
|
||||
assert mc_backfill.call_args.kwargs["docket"] == "CMS-2026-2377"
|
||||
|
||||
|
||||
class TestIngestIom:
|
||||
@patch("bib.connect")
|
||||
|
||||
Reference in New Issue
Block a user