poll digest: flag an unreplied human ask, don't bury it 166 lines down (design 006 piece 7, closes #732) nf-m0j7 ← Beads

closed priority 2 task unassigned activesession:poll-unreplied

Twinned from https://github.com/cfsh/ninefold/issues/826 by tools/beads/import_github.py's reconcile pass.

Design 006 (design_docs/006-the-coders-front-door.md) piece 7. Standalone — touches tools/pr/poll.py only, no dependency on any other piece. This is also #732 in full (filing this to give it a chunk-sized owner rather than leaving it in the general backlog) — close #732 when this lands. Landing this alongside [#824](https://github.com/cfsh/ninefold/issues/824) and [#825](https://github.com/cfsh/ninefold/issues/825) clears every remaining prerequisite for piece 8 (dev.py status/review/merge) — §5.2 of the design doc calls this a prerequisite for status, not a nice-to-have: a status built on the current digest logic inherits the bug where a human's ask looks like nothing happened.

The bug, measured on PR #713 (2026-08-07)

@aedanpope reviewed with an empty review body (body_len=0, state=COMMENTED) — the entire ask was in an inline comment on CLAUDE.md, which is a normal way to write a line-specific review, not an edge case. In that tick's digest:

166 lines between the announcement and the payload, and the announcement gives no sign a payload exists. Root causes (poll.py's digest-printing code — grep for the REV/NFR/CMT/INL block; line numbers have shifted since #732 was filed and again since #801 touched this file):

  1. An empty-bodied review renders as a content-free line — nothing says "see the inline comment below."
  2. Print order is fixed as REV → NFR → CMT bodies → INL, so a human's line-specific ask always lands after every comment body, including the session's own bulky replies.
  3. There is no "you owe a human a reply" marker at all. last_reply/unanswered are computed already (used only to raise ⚠ NFR GAPS for *bot* verdicts) but never applied to human reviews/comments/inlines.
What to build — cheapest fix first, in order of value
  1. Reuse the existing unanswered predicate for humans, not just the bot. Any non-bot review/comment/inline newer than last_reply → print ⚠ aedanpope replied and you have not answered: <thread pointer>, with a counter alongside the existing gaps_pointers cadence. This is the fix that makes the other two cosmetic — if you only do one, do this.
  2. Annotate the empty reviewREV … [COMMENTED] (body empty — see INL below) when body == "" and inline comments exist on the same review.
  3. Hoist human inline comments above the CMT block (or print own-comment bodies collapsed to a byte count first) so the payload isn't buried under the session's own prior replies.

⚠️ Do not truncate or summarize a human's text to close the gap. CLAUDE.md's doctrine is the session reads what he wrote, verbatim — fix the ordering and flagging, never the content.

Reference (context, not required reading)

design_docs/006-the-coders-front-door.md §5.2 ("#732 is a prerequisite, not a nice-to-have"), §8.2 row 7. Full original report: #732 (closes on landing). Related but out of scope: #679 (same shape, bot side), #726 (digest volume generally).

Dependencies

None.

Comments

No comments.

Add a comment