Skip to content

Keep checked options and the Other answer together on multi-select questions - #4372

Open
ThePharmer wants to merge 1 commit into
getpaseo:mainfrom
ThePharmer:fix/question-card-multiselect-other
Open

Keep checked options and the Other answer together on multi-select questions#4372
ThePharmer wants to merge 1 commit into
getpaseo:mainfrom
ThePharmer:fix/question-card-multiselect-other

Conversation

@ThePharmer

@ThePharmer ThePharmer commented Sep 5, 2026

Copy link
Copy Markdown

Linked issue

Closes #4370

Type of change

  • Bug fix
  • New feature
  • Enhancement
  • Refactor
  • Docs

Reasoning

On a multi-select question card, the Other field and the checked options cannot coexist. Check first and then type, and the boxes clear. Type first and then check, and the card silently drops the typed text on submit: since #3517 the field owns its text and never replays state, so the screen keeps showing a sentence the state has already forgotten. The agent receives the labels alone. Claude Code's own AskUserQuestion UI keeps both and submits "Apple, durian", and the Agent SDK docs describe exactly that shape, so a Paseo user answering from their phone gets a worse answer than they would at the terminal.

This PR makes multi-select keep both inputs and submit the checked labels followed by the trimmed Other text, joined with ", ". Single-select keeps the replace behavior, which also matches Claude Code, but when it clears the Other text it now calls replaceText("") on the field so the screen and the state agree.

Goals

  • Multi-select: checked options survive typing into Other, and Other text survives checking options, in either order.
  • Multi-select: the submitted answer is the checked labels followed by the Other text, comma-joined, so Codex and OpenCode split it into the array their APIs expect and Claude receives the same string its own UI would send.
  • Single-select: picking an option after typing clears the Other field on screen, not just in state.
  • No protocol or daemon change. answers stays Record<string, string>.

Non-goals

QA

Reproduced before the fix (Paseo 0.7.2, Claude Code 2.1.258, web UI and Android app): on a multi-select AskUserQuestion, typed a sentence into Other, checked four options, submitted. The agent received the four labels joined with commas and nothing else. Checking first and typing afterwards visibly cleared the boxes. Recording is attached to #4370.

Tests. packages/app/src/components/question-form-card-core.test.ts gains two cases for the answer builder (multi-select combines, single-select replaces). New packages/app/src/components/question-form-card.browser.test.tsx mounts the real card in headless Chromium through the Vitest browser project, with the real web EditingTextInput and no mocks, and drives both orders through clicks and input events, asserting the answers the card submits and what the field shows. On main without the source change, four of the ten tests fail:

core:    × keeps checked options and appends the other answer for multi-select
           expected { Fruits: 'durian' } to deeply equal { Fruits: 'Apple, Cherry, durian' }
browser: × keeps checked options when the other answer is typed afterwards (multi-select)
         × keeps the typed other answer when options are checked afterwards (multi-select)
           expected { Fruits: 'Apple, Banana' } to deeply equal { Fruits: 'Apple, Banana, durian' }
         × clears the typed other answer on screen when an option is picked afterwards (single-select)
           expected 'OpenCode' to be ''

With the change, all ten pass. oxlint and oxfmt are clean on the four touched files. Typecheck, lint, and format results for the whole repo are from CI.

Platforms tested for the bug: web UI in a browser and the Android app. The fix is in the shared card and has no platform branches. Not re-tested on device after the fix; the browser tests cover the same interaction sequence against the real web input.

Checklist

  • One focused change
  • npm run typecheck passes (CI)
  • npm run lint passes (CI)
  • npm run format passes (CI)
  • QA evidence
  • Tests added or updated where it made sense

@greptile-apps

greptile-apps Bot commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes question-form answer composition so multi-select options coexist with custom “Other” text while preserving single-select replacement behavior.

  • Combines selected multi-select labels with trimmed custom text at submission.
  • Keeps multi-select state intact regardless of interaction order.
  • Explicitly clears the visible custom input when a single-select option replaces it.
  • Replaces the prohibited mocked JSDOM component test with a sanctioned real-Chromium browser test.
  • Removes the unrelated native-headers release workflow introduced before the previous review.

Confidence Score: 5/5

The PR appears safe to merge; the previous question-form test-harness violation is fully addressed and no new actionable defect remains.

The answer builder and component state transitions consistently preserve multi-select labels and custom text, while single-select replacement explicitly synchronizes both React state and the visible input. The two earlier release-workflow findings are no longer present because that workflow was removed, and the previous mocked JSDOM component test was replaced by the repository-sanctioned real-Chromium browser test.

Important Files Changed

Filename Overview
packages/app/src/components/question-form-card.tsx Preserves both input sources for multi-select questions and synchronizes single-select state with the visible editing surface.
packages/app/src/components/question-form-card-core.ts Builds multi-select answers from selected labels plus trimmed custom text while retaining single-select replacement semantics.
packages/app/src/components/question-form-card.browser.test.tsx Covers both interaction orders and single-select replacement through the production component and input in real Chromium.
packages/app/src/components/question-form-card-core.test.ts Adds focused answer-builder coverage for combined multi-select and replacing single-select answers.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[User edits a question] --> B{Multi-select?}
    B -->|Yes| C[Preserve checked options and Other text]
    C --> D[Submit labels followed by trimmed Other text]
    B -->|No| E{Latest input}
    E -->|Other text| F[Clear selected option]
    E -->|Preset option| G[Clear Other state and visible input]
    F --> H[Submit Other text]
    G --> I[Submit selected label]
Loading

Reviews (2): Last reviewed commit: "fix(app): keep checked options and the O..." | Re-trigger Greptile

Comment thread .github/workflows/native-headers-release.yml Outdated
Comment thread .github/workflows/native-headers-release.yml Outdated
Comment thread packages/app/src/components/question-form-card.test.tsx Outdated
…-select questions

On a multi-select question card, typing into Other cleared the checked
options, and checking an option after typing deleted the Other text from
state while the field kept showing it, so submit silently dropped it.

Multi-select now keeps both and submits the checked labels followed by
the trimmed Other text, comma-joined, matching Claude Code's own
AskUserQuestion UI. Single-select keeps the replace behavior and clears
the field through replaceText so the screen matches the state.

Closes getpaseo#4370
@ThePharmer
ThePharmer force-pushed the fix/question-card-multiselect-other branch from 5e30a34 to 1f33b1a Compare September 5, 2026 17:35
@ThePharmer

Copy link
Copy Markdown
Author

Two fixes pushed in response to the review:

  • The branch was cut from my fork's main, which carries a fork-only release workflow, so .github/workflows/native-headers-release.yml leaked into this PR. Rebased onto upstream main; the PR is now the single fix commit and touches only the four question-form files. The two workflow comments do not apply to this PR.
  • The component test was a mocked JSDOM test, which docs/testing.md rules out. Replaced with question-form-card.browser.test.tsx in the Vitest browser project: real Chromium, the real web EditingTextInput, no mocks. Three of its four cases fail on main without the source change, including the silent-drop case (Apple, Banana received instead of Apple, Banana, durian).

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: multi-select question card treats Other and checked options as exclusive, and since #3517 silently drops the typed text

1 participant