Skip to content

client: a read-only window's ask_user card still offers Submit and Dismiss; the refusal is silent and the card comes back #2283

Closed

Description

@HugoXK

Implementation: FlyBot (ours) — PR follows within 24h. Do not pick up without a pickup-ok comment on this issue.

Written-by: FlyBot Lead
Claimed-by: FlyBot Lead
Claim-Id: 3f59a63ec400476eb45508431b9d53e9
Branch: dev/3-questions-readonly
Base: b451e3b
At: 2026-11-03T06:59:26Z

Implementation: FlyBot (ours) — PR follows within 24h. Do not pick up without a pickup-ok comment.
Written-by: FlyBot Lead

What is wrong

In a read-only window the chat's ask_user card still offers Submit and Dismiss. Both are writes
the host refuses (bot/read-only), and nothing on the card says so:

  • core/src/client/questions.js:167 — answering marks the card answered first and then
    void actions.answerQuestion(...).catch(() => setAnswered(null)): the refusal is swallowed, the
    card silently comes back, and the click looked like it worked.
  • core/src/client/questions.js:169-171 — dismiss sets answered (the card disappears) and
    void actions.dismissQuestion(sessionId) drops the rejected promise entirely: the card hides,
    then returns on the next poll, again with no sentence saying why.

The component has no read-only check at all; roster.readOnly is available where the card is
mounted (cells.js:1112, inside a component that already reads useRoster).

Reproduction (live main b451e3b3)

  • Rendering PendingQuestion with a read-only roster draws ["Dismiss question", "A", "B", "Submit"]; with the choices expanded the answer buttons and Submit are all live.
  • The host answers answer-question and dismiss-question with bot/read-only (measured on a real
    runtime whose lock is held by another dsh; tasks answers normally in the same window).
  • Answering in that window: no error, no notice, the card returns. Dismissing: the card vanishes
    and returns on the next poll.

Expected behaviour

In a read-only window the card keeps the question, its detail and its option labels as text, and
draws none of the ways to answer — the option rows themselves are the write, not only the
footer: on a single-select card a row answers at once and the card has no Submit at all, so a
fix that only removes Submit and the x leaves the card just as pressable. Concretely, in a
read-only window:

  • no option buttons (the rows stay as text: no onClick, no aria-pressed, no aria-keyshortcuts),
  • no own-answer field (textarea),
  • no Skip, no Submit, no x (dismiss),
  • no form and no handler at all on the card (nothing to submit, nothing to swallow),
  • the A/B/C letter shortcuts are off (useOptionKeys(0, ...)),
  • one visible sentence carries the host's own words for roster.readOnly (hostText,
    role="status"), the same hint the other read-only surfaces draw,
  • pressing anything on the card sends no answer-question and no dismiss-question request, so
    neither the swallowed refusal nor the hide-then-return can happen.

A writable window's rendered tree stays byte-identical (same fixture and runtime, normalised tree
compared by sha256), and a blank or missing readOnly stays on the writable path.

Scope

  • core/src/client/questions.js: gate the card's actions and draw the explanation.
  • core/src/client/cells.js: pass the read-only sentence from the roster it already reads.
  • One test file under core/test/ for the red-first and the writable reverse.
  • Generated artifacts (core/client.js, patches/ds-bot/**) are regenerated in the same commit
    and reviewed as generated output.

Duplicate check

Searched open and closed issues for ask_user read-only, question card read-only and
PendingQuestion: no issue covers this card (the read-only family tickets cover the task board,
menus, Settings forms, Memory panel and scheduled-task entries).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions