Keep a wrapped NEEDS-HUMAN bullet whole in SUMMARY section 6 - #554
Merged
Merged
Conversation
When a reviewer or advisory artifact wrote a "- NEEDS-HUMAN" bullet that wrapped onto indented lines, SUMMARY.md section 6 showed only its first line. The person clearing section 6 at sign-off saw a question that stopped mid-sentence, such as "src/x.py:12 (`f`):", and had to open the artifact to learn what was being asked. The bullet parser now takes the first line plus every following line indented deeper than the bullet, and joins them with single spaces into one item. The item ends at a blank line, a line no deeper than the bullet, a new list item at any indent, a heading, a table row, or a code fence. So two bullets in a row stay two items, and an indented NEEDS-HUMAN sub-bullet is still its own item. The joined text never contains a newline. Each item renders as one "- [ ] ..." checkbox line, and sign-off counts open items line by line, so a second physical line would lose its checkbox and escape the open-item check. Single-line bullets, table rows, and "[impl]" classification behave as before. A new offline test, template/tests/test_needs_human_multiline.py, fails before the change and passes after it. Fixes #527 Signed-off-by: eduralph <eduard@ralphovi.net>
eduralph
marked this pull request as ready for review
September 16, 2026 15:42
eduralph
deleted the
fix/527-section6-keeps-whole-needs-human-bullet
branch
September 16, 2026 16:21
This was referenced Sep 18, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
User impact: when a review finding that needs a human decision runs longer than one
line, the sign-off checklist in
SUMMARY.mdshows only its first line. The person signingoff sees a question that stops mid-sentence (for example just
src/x.py:12 (`f`):) and hasto open the review file to find out what they are being asked to decide. This hits anyone
clearing that checklist; reviews in real cycles have produced several such cut-off items.
This PR keeps the whole finding: its wrapped lines are joined into the same single checklist
line.
Reported in #527.
What to look at
The change is in one function, the parser that turns review files into checklist items in
SUMMARY.md. A finding's wrapped lines (indented under it) now join onto it. A blank line,a line back at the same indent, another list item, a heading, a table row, or a code fence
ends the finding. So two findings in a row stay two checklist items.
To try it: write a review file in a bundle whose finding wraps, e.g.
then build the summary. Before this change the checklist item ends at
(`f`):. After it,the item reads the whole sentence through "so it overshoots." on one
- [ ]line, andsign-off counts it as one open item.
Root cause
_needs_humanwalked the review text one line at a time and, for a- NEEDS-HUMANbullet,kept only the stripped current line; the indented lines below it were never joined. Every
file that feeds the checklist goes through this parser (
check-review.md,check-advisory-*.md,plan-advisory-*.md), so all of them were affected.Fix
forloop becomes awhileloop, so a bullet can consume its continuation linesbefore the index moves on (
template/src/pdca_harness/assemble.py:489-522).indented deeper, stopping at a blank line, a line no deeper than the bullet, or a line
that
_ends_needs_human_continuationflags: a list item at any indent (-,*,+,1.), a heading, a table row, or a code fence (assemble.py:60-77).as one
- [ ] …line (assemble.py:603, unchanged), andsignoff.open_needs_humancounts open items per line, so a second physical line would drop out of the open-item
check.
early
continuebecomesif vi is not None:, and its inner index is renamedj→kso itdoes not clash with the new scan index.
The indent rule follows the one
brief._block_foralready uses for wrapped brief fields(
template/src/pdca_harness/brief.py:70-104, #336). That helper is not reused directly: itkeeps a multi-line block and treats blank lines as inside it, while a checklist item must be
one line.
Out of scope: findings split into several paragraphs (a blank line still ends the item), and
the table-row path.
Verification
- NEEDS-HUMANbullet becomes one checklist item holding its fulltext, on one line, counted once at sign-off.
template/src/pdca_harness/assemble.py:494-512(continuation scan andspace join); rendering at
assemble.py:603; line-based count attemplate/src/pdca_harness/signoff.py:102-122onmain.template/tests/test_needs_human_multiline.py:76-100— the item text, therendered
SUMMARY.mdcheckbox line, and theopen_needs_humancount.indented sub-bullet stays its own item, and a blank line, heading, or dedent ends it.
assemble.py:60-77and:501-507(stop conditions).test_needs_human_multiline.py:103-156(ContinuationBoundaries). The otherlist markers (
*,+, numbered), table rows, and both fence styles were also checkeddirectly against the parser during review.
[impl]bullet is still one IMPL itemwith the marker stripped, and single-line bullets give the same text as before.
_IMPL_MARKER_REand_classify_findingare untouched; the table branchat
assemble.py:513-521keeps the same STANDING check against the precomputedverdict-table rows.
test_needs_human_multiline.py:164-175(ClassificationUnchanged).assemble.pychange removed, 9 of the 10 new tests fail withreal assertion errors (e.g.
'overshoots' not found in 'src/x.py:12 (`f`):'); only thesingle-line case passes, as expected. With the change, all 10 pass.
template/,PYTHONPATH=src python3 -m unittest discover -s tests) passes — 1798 tests, 2 skipped(existing skips), including
test_autoiterate.py,test_plan_advisory.py,test_external_dependency_section6.pyandtest_leaf_status.py. Docs lint and siterender also pass.
Fixes #527