feat(operator-queue): approvals get a "Something else" answer (#3242) - #3250
Merged
Merged
Conversation
This was referenced Oct 5, 2026
…se) answer (#3242) The #2376 sink now handles SOMETHING_ELSE = "(something else)" before membership: accepted on any approval with an instruction in response_text, refused by name otherwise (instruction_required, reserved_value), and refused on platform-minted / gate approvals (not_off_menu). Every other unoffered string stays refused. validate_response_choice takes response_text keyword-only and required. - ask_service: gate refusal; ask_operator refuses the literal as an option - both writers map ReservedAnswerError to a named 422 - OperatorResponse.response_text bounded at 4000 - Workspace projection: decided_by_options boolean (T8 ruling) - recent answers render "Something else: <instruction>" - resume frame: platform sentence above the data fence Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e) (#3242) - platform prompt (both authored copies) + agent guide: the approval bullet and the queue-file write-back say what the reserved value means and that the instruction is in response_text; never list it as an option - test_1402 SENTINELS += "(something else)" - MCP: types.ts exports SOMETHING_ELSE; ask_operator, get_my_ask and respond_to_operator_queue descriptions name it; the respond tool keeps `error` and adds the backend's {status, code, message, offered_options?} (T5, additive) - py <-> ts parity test for the literal Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- utils/operatorQueue.js: SOMETHING_ELSE (mirrored, parity-tested), offeredChips (drops the literal and the size-cap marker), decisionLabel, decidedByOptions; buildQueueResponse needs an instruction with the literal - QueueCard + QueueItemDetail: chips from offeredChips, a 'Something else' chip outside the v-for (hidden on gate approvals); typing with no pick arms it, the label and Send copy flip; Enter sends only after an explicit pick; maxlength 4000; Send rule is the shared builder - respondToItem returns true/false; the detail panel clears only on success - ResolvedCard + detail resolved view render 'Something else', never the literal Raw-colour counts unchanged (QueueCard 28/59, QueueItemDetail 26/55). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- /m: a 'Something else' chip in the options group (reuses ops-option-btn, hidden on gate approvals) opens the form; the consequence line says none of the options will run; Send reads 'Send instruction' and stays disabled until the instruction is typed; maxlength 4000 - PortalAsks: the chip after the offered chips, hidden when the projection says decided_by_options (T8 ruling); typing with no pick arms it, placeholder and Send aria-label flip; Enter never sends the auto-armed state; submit() sends the armed option through the shared builder. Diff kept to the approval template, helpers beside pick(), the body of submit() and one import line (open PR #3181 edits other hunks) - portalAsksTestidPrefix: the id inventory gains the chip's id Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Document what #3242 built: the reserved (something else) decision an approval accepts besides its own options, with the instruction in response_text; the named 422s (instruction_required, reserved_value, not_off_menu, invalid_options at raise); the Something else chip on the desktop card and detail, /m and the Workspace, hidden on gate approvals on every surface (decided_by_options on the Workspace projection); the resume frame and contract text. Corrects every doc that still said an approval's answer must be one of its options. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…dead optionsOf import (C1, I1) (#3242) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…-miss literals; public decided_by_options; learnings (I2 I4 I5 I6 I7 I12) (#3242) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…tor projections; gate- is only the fallback (I3) (#3242) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
vybe
force-pushed
the
feature/3242-approval-something-else
branch
from
October 6, 2026 10:10
210fc6b to
efedeaa
Compare
vybe
marked this pull request as ready for review
October 6, 2026 10:15
trinity-ability
approved these changes
Oct 6, 2026
trinity-ability
left a comment
Contributor
There was a problem hiding this comment.
merge-train: batch validated on train/20261006-1038 (#3270)
vybe
pushed a commit
that referenced
this pull request
Oct 6, 2026
…sh-landed (#3253) — mechanical, per the merge-train note on the PR Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #3242 — first of the chain #3242 → #3243 → #3247 (ask contract), with #3246 alongside. Base is
dev. Draft until the chain is in (operator, 2026-10-05).What
An approval is no longer a closed menu. A person can answer "Something else" and type an instruction; the agent reads back one reserved decision and the instruction.
services/operator_queue_choices.py,services/ask_service.py): the reserved literal(something else)is checked before membership. On an approval with a non-blank instruction it is accepted; blank →422 instruction_required; on any other ask type →422 reserved_value; on a gate / platform-minted approval →422 not_off_menu. Every other unoffered string is still refused (bug: POST /api/operator-queue/{id}/respond accepts any string as an approval decision — no layer checks response ∈ options #2376 stays closed). An ask that lists the literal as its own option is refused at raise (invalid_options).response_textis bounded at 4000 on both routes.ask_operator,get_my_askandrespond_to_operator_queuedescriptions name the value; the respond tool returns a structured refusal besideerror; the resume message explains the value above the data block.utils/operatorQueue.js,QueueCard.vue,QueueItemDetail.vue,MobileAdmin.vue,PortalAsks.vue,ResolvedCard.vue): a "Something else" chip after the agent's options. On desktop and in the Workspace, typing with no pick selects it and the button reads "Send instruction"; Enter never sends an auto-selected state. Ended asks show "Something else" with the instruction, never the raw literal.decided_by_options, from the same backend predicate; thegate-id prefix is only the fallback.Rulings carried (orchestrator, on the operator's behalf — plan file)
(something else), one constant per language with a parity test · T2 instruction required · T3 chip + auto-select on typing, "Send instruction" · T4 approvals without options unchanged · T5 no new MCP parameter · T6 no schema change · T7/mdecomposition (refactor: decompose oversized Vue views (Settings 3061 lines, MobileAdmin, Agents, AgentDetail, ...) #1030) not bundled.Review + security
/review(claude-fable-5-1, report-only): MERGEABLE AFTER FIXES. One sink holds on every route tried; the four named 422s come from both writers; gates are closed on every route; the new specs assert the body that is sent (reverting the rules turns 17 new tests red). Fixed inad85e9f6(C1: a source-text pin of the old Send rule was red; I1),10dc0480(I2 read-back contract tests, I4, I5, I6, I7, I12 learnings fragment),210fc6b4(I3: one predicate on both sinks)./cso --diff: nothing supported.Tests
Reported by the builder on the fix tip: frontend
npm run test:unit265 files / 4653 tests passed; pytest on the five affected suites 307 passed; mcp-server 687 passed,tsc --noEmitclean. Not run here: the full Python unit island (CI) and any live tier.Before merge
get_my_askdescription insrc/mcp-server/src/tools/operator_queue.ts. Keep both: this branch's reserved-value lines, then feat(workspace): Discuss and Dismiss on asks (abilityai/trinity-enterprise#747, #748) #3181's disposition line. Merge order is the operator's call.docs/user-docs/sharing-and-access/mobile-admin.mdcarries new feature prose ahead of the usual user-docs step; the other three user-docs edits correct sentences this change made false.docs/memory/feature-flows/operating-room.md,QueueCard.vueandQueueItemDetail.vue. Keep both intents; whichever lands second resolves.Handoffs
/mdecomposition) stays open.🤖 Generated with Claude Code