Repository navigation
fix: triage prompt carries the questions, not the whole report - #164
Merged
Merged
Conversation
The morning triage injected the entire report through --append-system-prompt (~25KB on 2026-10-26) and launched with the literal prompt 'go'. A report body narrating a night of firmware work (sdb, root status, dlopen) made every launch read as an offensive-security engagement: Opus 5.5 answered 'safeguards flagged this session ... Details: [cyber]' before the first reply, and 'claude -p' with the same argv reproduced it. The same report's '## Open questions for the user' section passes. - inline only that section (12KB cap) and point at the report path - replace 'go' with a real one-line instruction - a section-less report still launches, with an empty block - tests/review-prompt.sh pins all of it; wired into run-all and CI
- cap with awk on a whole-question boundary into a second mktemp file, so a cut never splits a question and never lands in a 0644 file created by a shell redirect - mark the block truncated="1" and say the rest is in the report, instead of claiming the questions are quoted in full - extract with fence tracking and an exact heading match: a fenced example heading no longer starts the section, a fenced heading inside a question no longer ends it, and a longer heading is a different section - fail loudly when mktemp/awk/mv fail instead of launching with partial questions - remove the questions temp file before exec; the trap names every temp file tests/review-prompt.sh covers each one (24 assertions).
- fence detection covers ~~~ as well as ```, tracking which char opened the fence, so a tilde-fenced example heading does not start the section and a tilde-fenced heading inside a question does not end it - the cap works in whole questions: a top-level list item plus every line under it is kept or dropped as a unit, so a question heading can no longer survive without the decision context beneath it
Round 2's patches left two markdown edge cases, both from the same approximation: extraction and the cap each decided for themselves where a question began. Now a single awk pass owns both. - a fence opens on >=3 backticks or tildes and closes only on the same char at >= the opening length, so a 3-backtick line inside a 4-backtick block is content, not a close - a question starts at a top-level list item only outside a fence, so a `- option` inside a fenced example cannot start or end one - questions are kept or dropped whole, including their fenced blocks - the truncated flag comes from the same pass that applied the cap tests/review-prompt.sh: 37 assertions, including four-backtick nesting and a fenced list item at the cap boundary.
A fence line may carry an info string (a language label after the fence run). Only the leading run counts, and only a bare run closes a fence, so a labelled block inside a question neither ends the section nor starts a question, and a labelled example before the section is not the section.
Five review rounds on review.sh alone kept finding new markdown edge cases (fenced example heading, tilde fences, fence length, fence info strings) because four consumers each had their own idea of where the section ends. Replacing that with the producer's own boundary: - PROMPT.md: L2 wraps the section in AUTODREAM_QUESTIONS_BEGIN/END - report-format.sh: report_questions + report_has_questions_block, the one reader; the old heading read is the legacy fallback inside it - notify.sh, question-streaks.sh, review.sh: call the reader, stop parsing - run.sh: a report from AUTODREAM_QUESTIONS_EPOCH on is truncated when its block is missing or unclosed, so a bad block is rebuilt, not guessed at; the empty-day stub emits the block - review.sh: no markdown parsing at all, and the 12KB cap is all-or-nothing tests: report-format.sh gains the block matrix; review-prompt.sh is rewritten around the contract (23 assertions).
- the block reader takes the LAST end sentinel, so a question that quotes the sentinel in a code example cannot cut the block short - the legacy fallback keeps fence tracking: a heading inside a code example is not the end of the section - an oversized LEGACY report is sent to its heading section in the prompt, not to sentinels that report does not contain - one completeness predicate, report_finishes(report, date), used by the live gate, the abandoned-date sweep and the pin sweep, so a report rejected by the block gate cannot be accepted by a recovery path
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.
Why
The morning triage session was refused every time it launched. Session
9fdd76e2(2026-10-27) and two earlier ones:The prompt was the literal word
go. The payload was this launcher:The 2026-10-26 report narrates a night of TV firmware work (
sdb, root status,dlopen, W^X by mount). Reading that report is what gets refused, not the triage task:Read .../dreams/2026-10-26.mdRead .../dreams/2026-10-26.md(questions section alone)Read .../dreams/2026-10-25.md(report with no such body)gowith the report in--append-system-promptgowith nothing appendedWhat changed
--append-system-promptcarries the## Open questions for the usersection only (2.2KB on that report), capped at 12KB, plus the report path for a question that needs one number from it.Start the triage: restate the first open question and recommend one action.instead ofgo.tests/review-prompt.shpins all five properties (questions inlined, findings body and other sections absent, noRead the reportinstruction, real launch prompt, section-less fallback, cap). Registered intests/run-all.shand the CI matrix; CHANGELOG, CLAUDE.md and the codemap say why.Tests
Verified end to end against the real report: the request captured from a stubbed launch (4,815-byte system prompt) now answers instead of refusing.