Fix combat advisor "AI unavailable (parse)" — coerce numeric counts

The encounter-balance schema was the only AI schema with a numeric field.
LLMs routinely emit numbers as JSON strings ("count": "2"), which z.number()
rejects, failing the whole safeParse and falling back to deterministic with a
"parse" error. The all-string NPC/session/quest schemas never hit this.

- Coerce monster counts (z.coerce.number) and widen the upper bound 8->12 so a
  string or slightly over-eager count is accepted, not rejected. min(1) stays.
- Tell the model in the prompt that count is a plain integer and reasoning /
  targetDifficulty are required.
- Surface the real failure message in the advisor instead of the opaque kind.
- Add a regression test that string counts coerce to numbers.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-08 23:43:03 +02:00
parent 740cf20b93
commit 9a81c04199
3 changed files with 15 additions and 4 deletions
@@ -137,7 +137,7 @@ export function useEncounterAdvisor(campaign: Campaign, encounter: Encounter) {
return;
}
} else if (!res.ok) {
setMessage(`AI unavailable (${res.error}); showing a deterministic pick.`);
setMessage(`AI unavailable: ${res.message} Showing a deterministic pick.`);
}
}