Fix caller lineup never loading and add Wellspring cult callers

The lineup fix and the new characters both land in main.py, so they share a
commit rather than being split artificially.

Lineup fix — populate_backgrounds() was reachable only through
POST /api/session/reset, so taking calls without hitting reset left
session.caller_backgrounds empty for a whole show. Every caller got a hollow
prompt, collapsed into generic relationship filler, and Silas lost his lore.
Now start_call populates on demand, get_caller_prompt raises
EmptyCallerBackgroundError instead of emitting an empty prompt, /api/callers
reports lineup readiness to a header badge, and cross-episode topic dedup
widened from 2 shows to 10.

Wellspring callers — Doyle as the anchor defector plus a six-member pool,
grouped by new frontmatter fields (group, group_lead, group_weight, register,
explicitness). A faction is capped at one caller per show, with a 15% roll for
two pairing the lead with one other member. group_weight lets an anchor carrying
an arc get slots faster than texture characters.

Also detects model refusals, which arrive as ordinary 200s and previously
reached air as broken-character text or dead silence.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-15 03:33:08 -05:00
co-authored by Claude Opus 5
parent 9071ed36d3
commit b85e1c6ea7
15 changed files with 856 additions and 21 deletions
+16 -1
View File
@@ -621,7 +621,22 @@ async function loadCallers() {
sessionEl.textContent = `(${data.session_id})`;
}
console.log('Loaded', data.callers.length, 'callers, session:', data.session_id);
// Lineup readiness — an empty lineup means callers have no identity and
// every call collapses into generic filler, so make it visible pre-show.
const lineupEl = document.getElementById('lineup-status');
if (lineupEl) {
if (data.lineup_ready) {
lineupEl.textContent = `${data.lineup_count} ready`;
lineupEl.className = 'lineup-status ready';
lineupEl.title = 'Caller identities are loaded';
} else {
lineupEl.textContent = 'no lineup';
lineupEl.className = 'lineup-status empty';
lineupEl.title = 'No caller identities loaded — hit Reset Session before going live';
}
}
console.log('Loaded', data.callers.length, 'callers, session:', data.session_id, 'lineup:', data.lineup_count);
} catch (err) {
console.error('loadCallers error:', err);
}