Chat: multi-select question answers never commit (batched picker keys dropped); no free-text Other in multi-select #64
Labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Cloonar/coding-lab#64
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Symptoms (field report, 2026-07-09)
On any multi-select AskUserQuestion card — flat or inside a multi-question form, with or without Other involved:
Root cause 1 — the picker drops batched key bursts (the "submit does nothing")
multiSelectOpspacked the walk onto the unnumbered Submit row into ONE tmux call:send-keys Down Down Down Down. Driven live on 2.1.198: a 4-key burst in one send-keys call moves the picker cursor zero rows (a 2-key burst landed once — the drop is burst-size/timing dependent). The recipe'skeyDelaypacing only ever applied BETWEEN ops, so the walk never reached the Submit row and the closing Enters merely toggled the top option off/on — the dialog hung unanswered. Single-select recipes share the pattern but typical indices (0–2) stay under the drop threshold, which is why only multi-select visibly broke.Live disproof and fix proof (real 2.1.198 TUI, tmux, transcript ground truth):
[Space][Down×4 batched][Enter][Enter]→ cursor frozen, picker hung;[Space][Down][Down][Down][Down][Enter][Enter](one key per op, paced) → committed, recorded{"Which toppings?":"Olives"}.Root cause 2 — Other-in-multi-select was rejected on a stale "uncaptured path" premise
normSelected409'd any answer toggling the Other row ("uncaptured TUI path"), and the SPA rendered the row as a bare toggle with no input — so even the error path read as "nothing happens" (the 409 only surfaced in the top-of-page banner). Captured live 2026-07-09: bracketed-pasting text onto the "Type something" row fills it AND checks it in one move — recorded"Onions, no anchovies". (Two hazards pinned: Space on that row types a literal leading space into the field; a newline in the pasted text records as literal\r.)Fix
keyDelaypaces every key (compat §7 universal rule, snapshots updated);other_textend-to-end: adapter fills the free-text row via paste (its index never ridesselected), intent backstop expects the text as one more", "segment, web card (flat + form) renders the Other toggle + input with Submit gated on non-empty text;other_textalone is a valid answer;other_text/plan-feedback validated single-line at the door (the\rcorruption above).Compat §7 re-pinned with the 2026-07-09 live session (five committed rounds).
Land-PR audit for PR #65 (
fix(chat): multi-select answers commit again — per-key picker walk + free-text Other in multi-select)Verdict: PASS (after one mechanical fix pushed to the head branch).
What was checked:
60df8f3failed the requiredci / nativecheck in 53s — root cause wasprettier --checkonweb/src/routes/RunChat.tsx(a single line-wrap of themultiAnswerReadyarrow). Fixed withprettier --write, pushed as5025421(style(web): prettier-format the multiAnswerReady arrow). CI on the new head: success — that green vouches for eslint, prettier, vitest, vite build,go build/go test -tags ui, and golangci-lint.go build -tags uiOK,go test -tags ui ./...exit 0 across all 30 packages (tmuxx integration tests included).downOps) across all picker recipes;other_textaccepted for multi-select (flat + per-question) with the Other row's index barred fromselected;other_text-alone valid; single-line validation at the door (validateOtherText) used consistently by both the keystroke and intent paths (question Other, plan feedback);sameAnswermultiset compare degrades identically on both sides for text containing", ". Web card + form gate Submit on non-empty Other text and strip the Other index from the payload. Compat snapshots pin the new recipes with the 2026-07-09 live evidence.Closes #64, merge intomainis conflict-free (verified viagit merge-treeagainst2b2e935).No blockers remain. Merge awaits the human's free-text go-ahead.