fix(comments): title=comment_id; route by docket into Rules/Comments/<docket>
Two related fixes for how regulations.gov comment items show up in Zotero. Title was "Comment on <comment_on_id>" — but ``comment_on_id`` is the *parent rule's* document id, so every comment under a single rule appeared with an identical title in the Zotero list view. Use ``comment.id`` instead (the comment's own CMS-DOCKET-XXXX-NNNN id), optionally prefixed with the byline when the commenter populated firstName/lastName/organization. Collection routing put every comment into a flat Rules/Comments folder. With ~164k items that's unusable; route to Rules/Comments/<docket_id> instead. The docket comes from the ``reg-docket:`` tag set by ``cli/bib.py`` when fetching PFS comments (via ``api.resolve_docket``) — not the ``docket:`` tag, which is sourced from regulations.gov's comment-detail attrs.docketId field that's unpopulated for the bulk of submissions. Companion to a one-shot SQL migration that retitled 164,214 existing items in bib + Zotero and moved them out of the flat Rules/Comments into per-docket sub-collections (CMS-2017-0092 … CMS-2025-0304). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -540,10 +540,14 @@ def upsert_comment(
|
||||
extra_tags: list[str] | None = None,
|
||||
) -> str:
|
||||
"""Upsert the comment as a Source item, return bib key."""
|
||||
title = comment.title or f"Comment on {comment.comment_on_id}"
|
||||
# Title = the comment's own CMS-DOCKET-XXXX-NNNN id, optionally
|
||||
# prefixed with the byline (org or first/last name) when the
|
||||
# commenter filled those fields in. The previous "Comment on
|
||||
# <comment_on_id>" form named the *parent rule* instead of the
|
||||
# comment, which made every comment under a single rule look
|
||||
# identical in the Zotero list.
|
||||
byline = _byline(comment)
|
||||
if byline:
|
||||
title = f"{byline}: {title[:120]}"
|
||||
title = f"{byline}: {comment.id}" if byline else comment.id
|
||||
|
||||
url = f"https://www.regulations.gov/comment/{comment.id}"
|
||||
item = Source(title=title, url=url)
|
||||
|
||||
@@ -391,9 +391,20 @@ def _zotero_collection_path(item: Item) -> list[str]:
|
||||
manual = (ej.get("manual_name") or "").strip() or "General"
|
||||
return ["Healthcare Data Platform", "Manuals", manual]
|
||||
if "source:regulations-gov" in item.tags:
|
||||
# Every rulemaking comment lands flat in Rules/Comments. The
|
||||
# rule:<id> and year:<Y> tags on each item carry the
|
||||
# disambiguating citation, so a single bucket is readable.
|
||||
# Each rulemaking gets its own sub-collection under
|
||||
# Rules/Comments/<docket_id> (e.g. CMS-2025-0304). Without this
|
||||
# split, ~164k comments pile into a single Rules/Comments
|
||||
# folder and the Zotero list view becomes unusable.
|
||||
#
|
||||
# Read from `reg-docket:` (set by cli/bib.py via api.resolve_docket),
|
||||
# not `docket:` — the latter is sourced from regulations.gov's
|
||||
# comment-detail attrs.docketId field which is empty for the
|
||||
# bulk of comments.
|
||||
for tag in item.tags:
|
||||
if tag.startswith("reg-docket:"):
|
||||
docket = tag.split(":", 1)[1]
|
||||
if docket:
|
||||
return ["Rules", "Comments", docket]
|
||||
return ["Rules", "Comments"]
|
||||
if "source:email" in item.tags:
|
||||
# IMAP-ingested email lands under Inbox/<Mailbox-Title>.
|
||||
|
||||
Reference in New Issue
Block a user