Files
buzz/crates
Michael Neale 15f6fd57f8 refactor(buzz-agent): express the _Stop veto as a goose Operation
Step 2 of PLANS/BUZZ_OPERATIONS_MIGRATION.md. Behaviour is unchanged:
the existing stop_hook and real_dev_mcp integration tests pass without
modification, which is the point of this step.

BuzzStopVetoOperation replaces the inline stop_veto() branch. The loop
now runs the gate a second time when a round wants to end, which is
where the operation applies -- it declines unless the last message ends
the turn, so the top-of-round call is a no-op for it.

Two things move rather than change:

- The block cap was a loop-local u32 in run_turn; objections now carry
  a metadata note and the cap counts them since kickoff. run_turn is
  per session/prompt, so both are turn-scoped -- same three-strikes
  behaviour, but now a pure function of the conversation, which is why
  goose tags its own denials the same way.
- MAX_STOP_BLOCKS was declared in both loop_drive and hooks with the
  same value. Dropped the loop_drive copy.

Deliberately not goose's StopHookOperation: it drives goose's private
HookManager plugin system, while buzz's hook is an MCP tool that can
see buzz-dev-mcp's in-process todo state. It also emits a user-facing
notification per denial, which in buzz would post 'stop hook blocked
ending this turn' into a channel every time an agent had an open todo.
The objection reaches the model, not the room.

65 unit + 21 integration green, handtest --all 18/18.

Signed-off-by: Michael Neale <michael.neale@gmail.com>
Co-authored-by: Michael Neale <michael.neale@gmail.com>
2026-08-12 14:06:03 +10:00
..