# Muse-Choices Deny/Escalate Policy — DECISION RECORD (Final) Topic: add deny/escalate decisions to the `muse-choices` auto-approve daemon (`bin/muse_choice_watcher.py`), which today only approves (top choice per prompt kind). Interviewed 2026-10-06/07 per grill contract; accepted verbatim below, which flipped this record from Draft to Final. ## Standing constraints (settled by user) - All prompts must resolve: no stuck states are acceptable in any outcome. - The full-auto top-choice flow must always exist as a path. - Model review of choices is a FUTURE layer. Deferred out of this interview. ## Settled decisions - D0 (helper form): a checked-in repo rules file informs decisions. Source: user's structured answerquared 2026-10-06 ("Repo rules file (Recommended)" for "which helper should inform approve/deny/hold decisions"). Rationale recorded at selection time: deterministic, versioned, sub-second, unit-testable; no agent round-trip latency. ## Settled during interview - D0b (approve path needs no helper): straightforward prompts resolve locally with top-choice keys (the five matcher kinds, already implemented and live). Helpers (D0 rules file) govern deny/hold judgments only. Source: user direction 2026-10-06 ("the watcher itself should be able to input 1"; "always have the flow for full auto just top choice"). - D1 (rule match dimensions): command pattern first, plus kind and text pattern. Source: user selected option 1, 2026-10-06. Rationale: the observed risk lives in the `$ command` of approval dialogs; kind/text add precision around it. - D2 (deny mechanics): deny exists only for permission kinds -- `muse-approval` dialogs receive `2` + Enter, `y/n` prompts receive `n` + Enter. Question kinds (interview, letter, numbered) always resolve top-choice and are never denied. Source: user selected option 1, 2026-10-06. Rationale: deny is only meaningful where a permission is refused; questions stay total. - D3 (hold mechanics): hold leaves the dialog untouched, suppresses auto-answer, raises a HELD entry in `box muse-choices status` plus an audit record; the operator resolves via a box command, otherwise a SHORT window expires back to top-choice approve. Source: user selected option 1 with "short window", 2026-10-06. Exact duration proposed below (2 minutes, tunable); accepted or amended with the scope text in D5. - D4 (unmatched default): approve top-choice, exactly today's behavior. Source: user selected option 1, 2026-10-06. Rationale: follows from the standing constraints; rules carve out only deny/hold exceptions, so an empty rules file changes nothing. ## Open questions (unresolved) None. All interview questions resolved and the scope accepted. ## Scope contract (ACCEPTED) Artifact boundary, IN: - `docs/MUSE-CHOICES-POLICY.md`: this record (Draft -> Final on acceptance). - New `muse-choices-rules.json` at repo root (beside `keepalive-config.json`): the checked-in deny/hold rules. - `bin/muse_choice_watcher.py`: rule evaluation, deny/hold paths, HELD state with short-window expiry, resolve plumbing. - `bin/super-cli.py`: `box muse-choices resolve` command + HELD display in status. - `tests/test_muse_choice_watcher.py`: rule eval, per-kind deny keys, hold/suppress/expiry, resolve flow. Artifact boundary, OUT (rejected or deferred, each needs its own interview to re-enter): - Model review of choices (deferred future stage). - Peer-agent consultation (rejected in D0). - New matcher shapes (matcher suite's lane). - `box runtime` work (adjacent lane, untouched). - Timer cadence / daemon supervision changes. Done means (all observable): - [ ] This record marked Final with the acceptance quoted. - [ ] Rules file loads; empty rules == today's behavior exactly. - [ ] Deny sends `2`+Enter / `n`+Enter per D2: unit tests + one live scratch proof per permission kind. - [ ] Hold suppresses + shows HELD + resolves via box + expires to approve: unit tests + one live scratch proof of hold and one of expiry. - [ ] Audit records for deny/hold/resolve/expire in `box-ctl.jsonl`. - [ ] Full suite green; fleet reloaded; desired state left as found. Acceptance (quoted verbatim, chat, 2026-10-07T00:19:57Z): "ACCEPT". Accepted as written, including the 2-minute tunable hold window. Per the grill scope contract, later work outside the IN boundary needs explicit owner approval or its own follow-up interview; "go" authorizes only this boundary. No owning issue exists in this workflow, so this record is the lane-coordination evidence. ## Non-goals (accepted with the scope) - Model-based review of choices (deferred future layer). - Peer-agent consultation over sidechat (rejected in favor of D0). - Changes to approval matching shapes (covered by the matcher test suite).