Skip to content

[bug] text typed during a turn is lost when the agent completes - #41

Merged
mike-diff merged 4 commits into
mainfrom
dispatch/issue-33
Aug 20, 2026
Merged

[bug] text typed during a turn is lost when the agent completes#41
mike-diff merged 4 commits into
mainfrom
dispatch/issue-33

Conversation

@sesh-dispatch

@sesh-dispatch sesh-dispatch Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Closes #33

Problem

Text typed into the message bar while the agent was working was discarded when the turn completed. The live editor kept the draft in its buffer through the turn (the errTurnOver return path does not clear it), but the between-turns prompt re-opened the editor through beginInput, which unconditionally zeroed the buffer, throwing away whatever the user had been mid-typing.

Changes

  • harness/tui.go, beginInput: when re-opening the editor, carry an existing non-empty buffer (and its cursor position, snippets, and images) into the next prompt instead of zeroing it. The submit, steer, and /stop paths all clear the buffer before they return, so a non-empty buffer here uniquely identifies the carry-over from a turn that ended mid-draft. A buffer left masked (a secret prompt) never carries, so a secret cannot leak into an ordinary prompt; the guard keys on the prior mask rather than the new one so that holds in both directions.

How to test

Reproduce the original bug and the fix headless through the editor:

go test ./harness/ -run 'TestBeginInput' -v
  • TestBeginInputPreservesDraftAcrossTurnEnd types a steering draft during a turn, ends the turn, then confirms the next prompt returns the carried draft. Without the fix (revert beginInput to t.buf = nil unconditionally) it fails with line = "".
  • TestBeginInputDropsMaskedDraftForOrdinaryPrompt seeds a masked, non-empty buffer and confirms an ordinary prompt clears it. Drop the !t.mask guard and it fails with buf = "hush".

Verification

go build ./... && go vet ./... && go test ./... pass.

sesh-dispatch Bot and others added 3 commits August 20, 2026 16:49
A steering message typed while the agent worked was discarded when the
turn completed. beginInput unconditionally zeroed the editor buffer when
the between-turns prompt re-opened the editor, destroying a draft that
survived the turn in the live editor's buffer.

Carry an existing non-empty buffer (with its cursor, snippets, and
images) into the next prompt. Submit, steer, and /stop all clear the
buffer before returning, so a non-empty buffer here uniquely identifies
the carry-over. A masked (secret) buffer never carries, keyed on the
prior mask so it holds in both directions.
@mike-diff

Copy link
Copy Markdown
Owner

Reviewed, validated, and amended on this branch.

Issue #33 is valid, reproduced independently

Drove the real console rather than taking the report on trust:

buffer right after the turn ends:  "half-typed thought"
buffer after the prompt reopens:   ""

The issue's own diagnosis of the location is also correct.

The fix is sound

The claim it rests on holds. Verified every path that can leave a buffer behind:

Path Clears buf?
submit (Enter) yes, via endInput
steer (Enter mid-turn) yes
/stop yes
Select (pickers) never writes buf
ReadKey (approval gate) never writes buf

So a non-empty buffer really does uniquely identify the carry-over, across the
whole console surface. Both breakers named in the PR body were confirmed to fail
without the change.

Two things amended

1. TASK.md was committed. Removed here. It is not this PR's fault: the
workflow strips PR_BODY.md but not TASK.md, so every dispatch PR carries it.
Fixed at the source in #45.

2. The mask guard was one-directional. The comment claimed it held "either
way", but only one direction was gated:

secret   -> ordinary : buf=""              guarded
ordinary -> secret   : buf="my draft text" carried into a MASKED field

In that direction the draft renders as dots and Enter would submit it as the
key. No current path reaches a secret prompt with a draft pending (every route
goes through a submitted line, which clears the buffer), so this was a latent
hazard rather than a live bug. Now !t.mask && !mask, the comment says what the
code does, and TestBeginInputDropsDraftForSecretPrompt covers the direction
that had no test.

Rebased, because the base could not validate

The branch was based on 30a3e43, which predates the e2e rig, so
harness/e2e_test.go did not exist here and -run TestE2E matched nothing. Its
CI also never ran -race, which is now part of the bar. Rebased onto current
main; the whole bar passes:

gofmt clean · vet clean · go test -race ./... green · SESH_E2E=1 green

All three TestBeginInput* tests were re-checked against their breakers:

unconditional t.buf = nil (kills the fix)    -> fails
drop !t.mask (secret -> ordinary leak)       -> fails
drop !mask (draft -> secret field)           -> fails

Force-push is the documented behavior for a dispatch branch, so the rebase is
safe here.

Nit, not addressed: a whitespace-only Enter during a turn hits neither the
/stop nor the steer branch, so a whitespace draft carries. Harmless, and
arguably correct.

@mike-diff
mike-diff merged commit f0973f9 into main Aug 20, 2026
2 checks passed
@mike-diff
mike-diff deleted the dispatch/issue-33 branch August 20, 2026 23:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[bug] text typed during a turn is lost when the agent completes

1 participant