Gate reuse + quality findings (Low, convergent): is_goal_control checked
_BARE_CONTROL_VERBS plus an inline {"wait", "gate"} literal. Hoist a single
module constant _CONTROL_FIRST_WORDS so the busy-path classifier reads one
verb set next to the dispatcher's. No behaviour change.
Gate quality finding (Low): `arg.startswith("--")` also matched goal text
that starts with a flag-like word, so `/goal --dry-run the migration`
silently set "dry-run the migration". Match only the standalone `--`
token (the documented `/goal -- <text>` form) and reuse the parsed rest,
so flag-like text is kept literally as on main.
Gate quality finding (Medium): _set read mgr.state.goal regardless of status,
so `/goal clear` (or a done goal) followed by `/goal <text>` printed
"(replaced the previous goal) was: ..." about a goal that was already gone.
Use mgr.has_goal() (active/paused) to decide what counts as replaced.
`/goal resume last goal`, `/goal continue` on a paused goal and
`/goal pause for now` fell through to the set path and silently
overwrote a standing goal with that sentence. The non-destructive
control verbs (resume/continue/unpause/pause/status/show/unwait) now win
over goal text and report the ignored words; `/goal -- <text>` sets goal
text that really starts with a control word, and a plain replace names
the goal it replaced. clear/stop/done keep their existing behaviour.
Hand rebuild of the goal_command.py part of #127367 (criteria parsing,
/goal history and the clear/stop refusal are left out).
(cherry picked from commit 9a9731437369138bbf4f84362556ae634ab27d6f)
Keep parsing, contracts, gates and persisted goal mutations in one dispatcher. Adapters retain authorization, rendering and scheduling; TUI drafting resolves the target session profile off the RPC reader. Document ACP as unsupported rather than implying a goal loop exists.