57cf6f09f4
A stage's allowedTools only shaped which tool definitions were offered to the model; the dispatch path resolved returned tool calls straight from the full registry and executed them without checking stage membership. A hallucinated, jailbroken, or edited-transcript tool call for any registered tool would run unchecked (violating invariant #5 / policy-is-absolute). dispatchToolCalls now rejects any tool call whose name is not in the stage's allowedTools (STAGE_COMPLETE_TOOL exempt), emitting ToolExecutionRejectedEvent and feeding an error ContextEntry back to the model instead of executing. Empty allowedTools means deny-all domain tools, consistent with offering only STAGE_COMPLETE_TOOL at inference time.