fix(cmux-next): validate replies from immutable question inputs

TE
7d ago
+417-0

Question-card Other answers need validation against the exact immutable native request before the trusted renderer proof can be spent. This prerequisite validates and canonicalizes a captured reply; it creates no person authority.

The standalone immutable Input contains sessionId, permissionId, requestJSON, and requestDigest. Validation checks the exact digest, current unique allow-once option, complete harness-specific answers, choice-only labels, duplicate JSON keys, original Claude AskUserQuestion previews, notes, and annotation absence/null semantics. Session and permission identity are never taken from the renderer reply. Omitted/null allowsOther defaults to true, matching AgentQuestion.Item and the web decoder; explicit false remains choice-only and malformed flags are refused. Both allowsOther and multiSelect require a JSON Boolean when present; numeric zero/one cannot coerce into flags. Omitted/null multiSelect defaults to false.

This pure helper has no ledger, connection, generation, nonce, person-proof, gesture-ticket, or renderer-binding APIs. The later integration must construct Input only from a captured native live Question and recheck that Question after renderer redemption and at ticket consumption. It does not repair Other Enter by itself.

Lawrence, via Leo:

leo i think this ui can be better / also needs to be keyboard navigable (i didnt check yet) / leo this needs to work with keyboard shortcuts like up arrow ctrl n/p etc / clicking enter doesnt work

Base: feat-cmux-next 8424d05bf9324f6f60a8f0c7c40b01f8a3e085b9.
Head: 0812231ec3dae1b370726bbd530fb4a5b0f73b8a.
Diff: 355 added lines in two files.

Validation:

  • git diff --check and python3 scripts/cmux-next/prepush-gate.py pass at this exact head.
  • Omission/null regressions were committed first as 028cb98a0cfead717bd2fb180cdc6a3581f286b8 and cover Claude/Chief/Codex with options present and exact answer preservation.
  • Numeric Other-flag and strict multiSelect regression sources were committed before their fixes as 54859174875 and 6669d37407b.
  • Original regression source was committed first as 0c7a29e9891; native compilation and tests are UNVERIFIED under the coordinator's Swift HOLD26809. No executed red/green result is claimed.
  • Intended fleet command after release: swift test --package-path Packages/macOS/CmuxNext --filter AgentPaneQuestionReplyTests.

The question_other_answer lane owns final verification with the root coordinator. This remains draft pending independent exact-head review and required native verification. No merge is requested.

Changelog

none

No capture: no UI change; this PR adds a pure Swift validator and its tests, with no rendered surface.

Agent session: agent session