Summary
While the Tuval chat window's view slot shows a subagent, the composer is disabled and the reason
lives in the field's placeholder. A disabled textarea is not focusable and not in the tab order, so
that placeholder is visual-only — a screen-reader operator reaches nothing where the composer was
and is told nothing about why, or where prompts go instead.
What I was doing
Reviewing PR #8629 (the review-code verdict on issue #8466) at head
89f7ce562b38431598eb097f678b17106c87c898. The PR passes on its stated criteria; this is a gap the
criteria did not ask about.
What I observed
apps/tuval/src/shell/chat/ChatWindow.tsx passes disabled={viewing !== null} to
AgentChatInput, and swaps the DesignTranslationProvider's translate so the placeholder reads
subagentViewPlaceholder from apps/tuval/src/shell/chat/copy.ts:
"Prompts go to the main agent — go back to its transcript to send (the row above, or Escape)."
packages/design/src/AgentChatInput.tsx puts a real disabled attribute on the textarea and on the
submit button, so both leave the tab order. The window's one live region — the
role="status" paragraph in ChatWindow.tsx (around line 993) — announces only the transcript
swap: "Showing the reviewer subagent's transcript. Still running." It says nothing about the
composer being off, and nothing about where a prompt would go.
So the whole explanation of the disabled state is carried by an accessible name a screen-reader user
cannot reach.
Why it matters
The point of the founder's ruling on #8466 was to stop a prompt landing in a transcript nobody is
reading, and to tell the operator where it should go instead. A screen-reader operator gets the
first half and not the second: the composer silently vanishes from the tab order with no
explanation. Might read as the app breaking rather than as a deliberate state. Cost of leaving it is
bounded — one operator class, one window — but this is the surface where a "why is it gone" question
is most expensive to answer without sight.
Pointers
Suggested next step (non-binding)
A guess, two shapes. Either fold the composer's state into the existing status announcement, so the
swap announces both the transcript and where prompts now go; or switch to aria-disabled plus a
no-op submit, keeping the field focusable so its accessible description can carry the hint. The
second matches what #8466's own criterion 1 offered as the alternative.
Filed by an agent · session 425cb3d4-b7c2-4bc3-b562-0776c88e7787 · 2026-09-08T21:12:15Z
Summary
While the Tuval chat window's view slot shows a subagent, the composer is disabled and the reason
lives in the field's placeholder. A disabled textarea is not focusable and not in the tab order, so
that placeholder is visual-only — a screen-reader operator reaches nothing where the composer was
and is told nothing about why, or where prompts go instead.
What I was doing
Reviewing PR #8629 (the
review-codeverdict on issue #8466) at head89f7ce562b38431598eb097f678b17106c87c898. The PR passes on its stated criteria; this is a gap thecriteria did not ask about.
What I observed
apps/tuval/src/shell/chat/ChatWindow.tsxpassesdisabled={viewing !== null}toAgentChatInput, and swaps theDesignTranslationProvider's translate so the placeholder readssubagentViewPlaceholderfromapps/tuval/src/shell/chat/copy.ts:packages/design/src/AgentChatInput.tsxputs a realdisabledattribute on the textarea and on thesubmit button, so both leave the tab order. The window's one live region — the
role="status"paragraph inChatWindow.tsx(around line 993) — announces only the transcriptswap: "Showing the reviewer subagent's transcript. Still running." It says nothing about the
composer being off, and nothing about where a prompt would go.
So the whole explanation of the disabled state is carried by an accessible name a screen-reader user
cannot reach.
Why it matters
The point of the founder's ruling on #8466 was to stop a prompt landing in a transcript nobody is
reading, and to tell the operator where it should go instead. A screen-reader operator gets the
first half and not the second: the composer silently vanishes from the tab order with no
explanation. Might read as the app breaking rather than as a deliberate state. Cost of leaving it is
bounded — one operator class, one window — but this is the surface where a "why is it gone" question
is most expensive to answer without sight.
Pointers
apps/tuval/src/shell/chat/ChatWindow.tsx— thedisabledprop, and therole="status"regionapps/tuval/src/shell/chat/copy.ts—subagentViewPlaceholder,tuvalSubagentViewTranslatepackages/design/src/AgentChatInput.tsx— wheredisabledreaches the textarea and submit buttonSuggested next step (non-binding)
A guess, two shapes. Either fold the composer's state into the existing status announcement, so the
swap announces both the transcript and where prompts now go; or switch to
aria-disabledplus ano-op submit, keeping the field focusable so its accessible description can carry the hint. The
second matches what #8466's own criterion 1 offered as the alternative.
Filed by an agent · session
425cb3d4-b7c2-4bc3-b562-0776c88e7787· 2026-09-08T21:12:15Z