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,
|
extra_tags: list[str] | None = None,
|
||||||
) -> str:
|
) -> str:
|
||||||
"""Upsert the comment as a Source item, return bib key."""
|
"""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)
|
byline = _byline(comment)
|
||||||
if byline:
|
title = f"{byline}: {comment.id}" if byline else comment.id
|
||||||
title = f"{byline}: {title[:120]}"
|
|
||||||
|
|
||||||
url = f"https://www.regulations.gov/comment/{comment.id}"
|
url = f"https://www.regulations.gov/comment/{comment.id}"
|
||||||
item = Source(title=title, url=url)
|
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"
|
manual = (ej.get("manual_name") or "").strip() or "General"
|
||||||
return ["Healthcare Data Platform", "Manuals", manual]
|
return ["Healthcare Data Platform", "Manuals", manual]
|
||||||
if "source:regulations-gov" in item.tags:
|
if "source:regulations-gov" in item.tags:
|
||||||
# Every rulemaking comment lands flat in Rules/Comments. The
|
# Each rulemaking gets its own sub-collection under
|
||||||
# rule:<id> and year:<Y> tags on each item carry the
|
# Rules/Comments/<docket_id> (e.g. CMS-2025-0304). Without this
|
||||||
# disambiguating citation, so a single bucket is readable.
|
# 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"]
|
return ["Rules", "Comments"]
|
||||||
if "source:email" in item.tags:
|
if "source:email" in item.tags:
|
||||||
# IMAP-ingested email lands under Inbox/<Mailbox-Title>.
|
# IMAP-ingested email lands under Inbox/<Mailbox-Title>.
|
||||||
|
|||||||
Reference in New Issue
Block a user