Command Payload Widget Review Appendix¶
Status: reference note from the April 2026 UI handoff package. Canonical contract lives in
docs/src/design/story/INTERACTION_VOCABULARY.mdanddocs/src/design/service/FRAGMENT_STREAM_CONTRACT.md.
The design review proposed a useful compromise for classic interactive-fiction commands: keep the backend authoritative, but let capable clients provide a command bar and partial local affordances over the visible action surface.
The important idea is not “write a parser in the client.” The important idea is that a command bar can be another payload widget over the same choices that a button, menu, CLI prompt, or Ren’Py menu would submit.
Adopt¶
Backend resolves all natural-language commands and validates every payload.
A rich client may use advisory grammar hints for autocomplete, preview, highlighting, and did-you-mean UI.
A plain CLI can submit raw text to the same reserved command choice without implementing grammar or autocomplete.
choice.acceptsshould describe payload shape, not widget class.Explicit payloads stay boring:
{}for pick/button choices{text: "..."}{quantity: 3}{piece_ids: ["..."]}{parts: {role: subpayload}}later for composed forms
Backend failures should return renderable interpretation feedback such as ambiguous, unknown noun, blocked, impossible, or validation failed.
Adjust¶
Keep
ProjectedStateas the durable sidecar for ledgers and status; do not introduceprojected_valueas an in-stream fragment until the backend has a real need for it.Keep
zoneandpiecereferences id-based and renderable. If an open choice references a target zone, that zone must be visible or reachable in the current client shell.Treat grammar as advisory metadata. It must be derived from the visible turn surface and must not contain hidden verbs, nouns, aliases, or target ids.
Prefer backend raw-command fallback whenever the client is unsure. Local resolution is an optimization for ergonomics, not a contract requirement.
Add
composeafter the simpler payload widgets have settled.
CLI Floor¶
The minimum conforming client only needs to reach the gateway API, render text, and read input. It should still be able to provide every interaction:
Render prose and known state as text.
Render zones as labeled lists.
Render choices as numbered rows with locked reasons.
For
accepts.kind="text", prompt for a line and submit{text}.For
accepts.kind="quantity", prompt for an integer and submit{quantity}.For
accepts.kind="pieces", number the visible target-zone entries and submit{piece_ids}.For
accepts.kind="raw_command", prompt for a command line and submit{text}to the reserved interpretation edge.For
compose, ask the parts sequentially once that payload shape is adopted.
Rich clients can compress those prompts into widgets, but cannot require hidden client-side rules to make the turn playable.
Implementation Bias¶
The next implementation should stay narrow:
Make
ChoiceInputViewsupportpick,text,quantity, andpieces.Add canonical fixtures for quantity and sandbox-ish piece/text interactions.
Add
raw_command, grammar preview, andinterpretationrendering in a later slice.Add
composeafter the simple payload shapes are tested.Save browser E2E for after payload widgets and command feedback are stable.