Free-model routers often answer with surrounding prose, so a strict whole-
response JSON parse failed and every triage run ended in error. Extract the
first JSON block before parsing, keeping the zod schema gate intact.
Also fix two bugs the tests surfaced in the merged AI implementation:
- agent-tool-call model made approval.summary/expiresAt conditionally required only when an approval subdocument is present, so blocked/error tool calls persist without a fake approval
- agent.repo.createRun coerced empty-string session/user ids to null so autonomous triage runs (no session/user) no longer fail ObjectId casting