fix(muse): blank rows in the draft no longer lose the composer - #275
Merged
Merged
Conversation
locateTail's walk stopped at the first non-continuation row, so a paragraph break inside the box resolved prompt null: verify read null forever (stuck send), the unread-dialog card drew over the live box, and each two-tap retry appended a full duplicate. The walk now steps over blank rows under the same bound; approval still resolves null at its subject rows. Also lists the rotated /loop placeholder tip as non-draft.
This was referenced Sep 23, 2026
AltanS
added a commit
that referenced
this pull request
Sep 24, 2026
PR #275 lets locateTail step over blank rows, so the rows that still stop the walk carry the safety: the pointer and the column-0 question. The new case takes an approval frame, renames its question to one no detector knows and tears off the pointer, the screen where the walk crosses blanks furthest. It must still find no box, refuse the composer and read no draft, so the unread-dialog card keeps the way out. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
AltanS
added a commit
that referenced
this pull request
Sep 24, 2026
…-built The Muse corpus section promises byte-faithful captures, and the four PRs each added fixtures made by editing one of those captures: the frame is real, the box or dialog rows carry text seen live. Say so, the way the Codex and Pi reconstructions already do, so nobody reads their colours as measured. Doc-only, so no CHANGELOG line (SKIP_VERSION_CHECK=1: the hook counts any file under web/src). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
AltanS
added a commit
that referenced
this pull request
Sep 24, 2026
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Owner
|
Thanks @jpcarranza94, this goes in as it stands, with one test of ours on top. You inverted the pinned unread-dialog test the way its note asked instead of deleting it, and you ran the adapter before and after on the live capture, which saved me the question. Our commit pins where the blank-row walk now stops, the pointer and the column-0 question, so a box-less dialog still gets its card. Your authorship is kept, the changelog credits you, and the PR closes when the branch merges. |
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.
Fixes #274 (which supersedes the #261 bargain).
What broke, live on 1.12.1: any message containing a blank row (a paragraph break) wedged its Muse pane. The first send typed but never submitted (verify reads
nullforever → stuck spinner); from the next poll the unread-dialog card covered the live box and locked the composer; and every two-tap retry appended a full duplicate, because the force path types without the pre-clear sweep. Observed: one message typed six times, no way to clear the box from the phone (Esc no-ops on a live box; Ctrl+C from the terminal cleared it).Root cause:
locateTailwalked up from the bottom rule over continuation rows only, so a blank draft row stopped the walk andpromptresolved null — a healthy box reading as "no composer". Reproduced against the real adapter over the captured screen: before,composerReady=false tail.prompt=null draft=null→ card FIRES; after the fix,composerReady=true tail.prompt=36 draft=<1134 chars folded>→ no card.The fix (
markers.ts): the walk steps over blank rows as part of the draft run, under the sameMAX_DRAFT_ROWSbound. The❯row itself still stops the walk before transcript, and approval still resolves null at its non-continuation subject rows — verified by the unchanged approval/trust/dialog suites.extractInputDraftalready folds blanks out, matching FOLD_SEAM, so verify passes once the prompt binds. Also lists the rotated/loop 10m <prompt> schedules a recurring promptplaceholder tip (seen live the same night) so it stops reading as a ghost draft.The flipped test is maintainer-sanctioned:
unread-dialog.test.tspinned the card-on-blank-draft behavior with the note "When locateTail tolerates a bounded blank run inside the draft, this test must be INVERTED (card null, composerReady true), not deleted." Inverted exactly that way, keeping the construction. The two new fixtures auto-enroll in the pinned corpus, the ready/raw/conformance sweeps, and the per-adapter card set.Verification: web suite 8746 passed / 41 todo / 0 failed, oxlint 0/0, both typechecks clean, vite build green, plus the before/after adapter run over the live capture above.