fix(chat): multi-select answers commit again — per-key picker walk + free-text Other in multi-select #65

Merged
dominik.polakovics merged 2 commits from lab/20260709-0107 into main 2026-07-09 02:07:02 +02:00

Closes #64

What broke

Any multi-select question answer — flat card or multi-question form, Other or not — posted fine, played its keystrokes, and then the picker just sat there: the walk onto the unnumbered Submit row was batched into ONE send-keys Down Down Down Down call, and the 2.1.198 picker drops bursts like that wholesale (live: cursor moved zero rows; the closing Enters toggled the top option off/on). keyDelay pacing only applied between ops, never inside the batch. Single-select shares the pattern but small indices stay under the drop threshold — which is why only multi-select visibly broke.

What changed

  • One named key per op (compat §7 universal rule, live-pinned 2026-07-09): every Down is its own paced op across all recipes. Compat snapshots updated; live replay of the exact new op sequence committed and recorded {"Which toppings?":"Olives"} where the old sequence hung.
  • Free-text Other in multi-select, end to end (captured live: pasting onto the "Type something" row fills AND checks it): other_text accepted for multi-select answers (flat + per-question), the row's index never rides selected, other_text alone is valid; intent backstop expects the text as one more ", " segment (multiset compare, toggle order is not option order); web card renders the Other toggle + input in both the flat card and the form, Submit gated on non-empty text.
  • Single-line other_text/plan feedback at the door: a pasted newline records as literal \r in the answer (live-observed) — rejected as 400 now.
  • compat.md §7 re-pinned with the 2026-07-09 session evidence (burst-drop rule, paste-fills-and-checks, Space-types-a-space hazard, record shapes).

Verification

  • Live TUI (real 2.1.198 in tmux, transcript ground truth, never pane-scraped): old recipe reproduced the hang; new recipe committed both a plain selection ("Olives") and a toggle+Other round ("Onions, no anchovies").
  • Go: provider/compat/chat/httpapi suites green (internal/tmuxx integration tests fail identically on a clean tree — sandbox can't host their test tmux server, pre-existing).
  • Web: 496/496, tsc and eslint clean; new component flows for Other-in-multi (flat + form + Other-only + empty-text gating).

🤖 Generated with Claude Code

https://claude.ai/code/session_01Li7oLGPiDruWZTkTxEJK5x

Closes #64 ## What broke Any multi-select question answer — flat card or multi-question form, Other or not — posted fine, played its keystrokes, and then the picker just sat there: the walk onto the unnumbered Submit row was batched into ONE `send-keys Down Down Down Down` call, and the 2.1.198 picker drops bursts like that wholesale (live: cursor moved zero rows; the closing Enters toggled the top option off/on). `keyDelay` pacing only applied between ops, never inside the batch. Single-select shares the pattern but small indices stay under the drop threshold — which is why only multi-select visibly broke. ## What changed - **One named key per op** (compat §7 universal rule, live-pinned 2026-07-09): every `Down` is its own paced op across all recipes. Compat snapshots updated; live replay of the exact new op sequence committed and recorded `{"Which toppings?":"Olives"}` where the old sequence hung. - **Free-text Other in multi-select, end to end** (captured live: pasting onto the "Type something" row fills AND checks it): `other_text` accepted for multi-select answers (flat + per-question), the row's index never rides `selected`, `other_text` alone is valid; intent backstop expects the text as one more `", "` segment (multiset compare, toggle order is not option order); web card renders the Other toggle + input in both the flat card and the form, Submit gated on non-empty text. - **Single-line `other_text`/plan feedback at the door**: a pasted newline records as literal `\r` in the answer (live-observed) — rejected as 400 now. - compat.md §7 re-pinned with the 2026-07-09 session evidence (burst-drop rule, paste-fills-and-checks, Space-types-a-space hazard, record shapes). ## Verification - Live TUI (real 2.1.198 in tmux, transcript ground truth, never pane-scraped): old recipe reproduced the hang; new recipe committed both a plain selection ("Olives") and a toggle+Other round ("Onions, no anchovies"). - Go: provider/compat/chat/httpapi suites green (`internal/tmuxx` integration tests fail identically on a clean tree — sandbox can't host their test tmux server, pre-existing). - Web: 496/496, `tsc` and `eslint` clean; new component flows for Other-in-multi (flat + form + Other-only + empty-text gating). 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01Li7oLGPiDruWZTkTxEJK5x
Two live-verified defects on claude-code 2.1.198 (compat §7 re-driven
2026-07-09, five committed rounds against the real picker):

1. The picker DROPS a burst of named keys sent in one tmux send-keys
   call: the recipe's batched walk (`Down Down Down Down`) moved the
   cursor zero rows, so multi-select answers never reached the Submit
   row — the closing Enters just toggled the top option and the dialog
   hung pending forever. keyDelay pacing only ever applied between
   ops. Every recipe now emits ONE named key per op (Down×N becomes N
   paced ops); live replay of the exact new op sequence commits and
   records the intended answer.

2. Other-in-multi-select was rejected as an "uncaptured TUI path" —
   now captured: bracketed-pasting text onto the "Type something" row
   fills AND checks it in one move. other_text is accepted end to end
   (adapter pastes it onto the row — its index never rides selected;
   other_text alone is valid), the intent backstop expects it as one
   more ", " segment, and the web card (flat + form) renders the Other
   toggle with a text input, Submit gated on non-empty text.

Pinned hazards from the live rounds: Space on the free-text row TYPES
a literal space into the field (the paste is the toggle — never Space
first), and a newline in the pasted text records as literal \r —
other_text and plan feedback are single-line at the door now.

Closes #64

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Li7oLGPiDruWZTkTxEJK5x
style(web): prettier-format the multiAnswerReady arrow
All checks were successful
ci / native (pull_request) Successful in 5m13s
5025421880
CI's format:check (prettier) failed on this one line-wrap in RunChat.tsx —
the only red in the native gate.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AU99RURQKTotKpPvunmfPS
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Cloonar/coding-lab!65
No description provided.