Repository navigation
Generator shortfall explainer: say why a run built fewer teams than requested - #149
Conversation
…eams silently A synced-roster run that comes back with fewer than 5 teams now says why. diagnoseTeamShortfall (src/teamcalc.ts, sim-free, unit-tested) names what the leftover pool ran out of, mirroring the search's own legality rules: Burst I/II coverage (one ≤20s caster or an alternating ≤40s pair), the two-Burst-III minimum, the slot-fit case, the boss-weakness element rule, and the healer requirement (relaxing when no healer is eligible, exactly like buildGenCalc). The Roster Generator renders the reasons under the run button and, when turning on "Include Non-OL Units" would supply every missing role, says so with example units it adds. Driven by a user report (openid 29080-…96007): 27 OL'd generator-eligible units built only 2 of 5 teams — the leftover pool held one lone 40s Burst I (Moran) and zero Fire units, both invisible in the UI. The replayed diagnosis reports exactly those two gaps and that the non-OL toggle clears them. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The same silent failure existed in both other generators: the Team Generator
returns null with no explanation when the pool can't field one team, and the
Union Raid loop breaks on the first row that can't build. Both now set the
shared shortfall state — the union row diagnoses against its OWN boss's
weakness and its own pool (units consumed by earlier rows + reserved for later
ones). The panel is extracted into one shortfallNote helper rendered on all
three tabs; the info carries its source generator so a note from one never
shows on another's tab. Reason copy reworded to per-team form ("A team
needs…") so it reads correctly for per-boss union rows.
Closes the QUEUE.md follow-up recorded in c622b37.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… counterfactual follow-up Cross-family code review (kimi-code/k3) returned CLEAN with 2 FOLLOW-UPs + 1 NOTE (scratchpad/gates/2026-08-25-roster-shortfall/result.json). Applied the reviewer's suggested fixes for two: the nonOlFix example picker now names only ≤20s Burst I/II casters for a 'fit' shortfall (the only units that break the 2+2+2>5 bind — a 40s caster or third Burst III named there was misleading), and the shortfallOpts comment credits makeCalc's requiredAny availability filter instead of buildGenCalc. The third (offer the non-OL hint when the diagnosis returns no named reason) is filed in docs/handoffs/QUEUE.md item 5. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…'t activate User report: on a synced 27-unit pool, Include Healer produced a team whose only healer-tagged unit was anis-star — but her heal is formation-gated on a SECOND Burst I ally (`formation: hasB1`), a shape the search never builds (double-B1 is excluded from enumeration), so the toggle reported success while delivering zero healing. delta-ninja-thief has the same problem (heal needs a Defender ally; requiredAny is static and can't express the conditional). The healer tag itself is prose-derived (build-archetype-tags.ts, regenerated on sync) and condition-blind, so the fix lives at the consumer: HEALER_SLUGS moves to web/src/healerSlugs.ts (vite-free so tests import the REAL list under the root tsconfig) and drops the two condition-dormant healers. genCalc re-exports it; the constraint, the shortfall diagnosis, and its example picker all share the filtered list. mint stays: her solo-mode heal is off only when the mint+prika together-rule guarantees prika, an unconditional duet healer. Test: scripts/tests/generators/healer-constraint.test.ts pins the exclusions (with a completeness check: tagged healer = listed or named exclusion) and re-runs the reporting pool through the search — every team now fields a healer that can actually heal. Replaces the in-session scratch probes. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…der block Both NOTEs from the kimi-code/k3 increment review (CLEAN verdict, scratchpad/gates/2026-08-25-healer-fix/result.json): the healerSlugs comment no longer overstates "never fields double Burst I" (reachable via explicit user locks, where anis-star could heal but still won't satisfy the toggle — worst case a redundant second healer), and genCalc's HEALER_SLUGS import joins the header import block with the re-export staying beside its comment. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Added: "Include Healer" fix (user-reported)The toggle could be satisfied by a healer-tagged unit whose heal cannot activate in any team the generator builds. On the reporting pool, team 1's only tagged healer was anis-star, whose heal is formation-gated on a second Burst I ally (
Updated draft patch note (still needs owner approval before publishing)
🤖 Generated with Claude Code |
…clusions Doc-maintenance pass for the session: the settled WHY behind both PR #149 changes goes to the changelog doc — the explainer's contract (names what the pool ran out of, never promises a team exists) and the condition-dormant healer exclusions (anis-star formation-gated, delta-ninja-thief Defender-gated, mint kept via the prika together-rule), with the evidence tier (literal kit facts + two kimi-code/k3 CLEAN reviews, per the 2026-08-11 gate-moves ruling) and where the tests live. No STATE.md change (web UI surface, not engine state); QUEUE already carries the one open follow-up; no handoffs to close; no U-questions touched. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
What
All three web generators (Team Generator, solo Roster Generator, Union Raid) previously failed silently: fewer teams than requested (or
null) with no explanation. Now a sim-free diagnosis (diagnoseTeamShortfall,src/teamcalc.ts) inspects the leftover candidate pool and the UI names exactly what ran out:With a synced roster on "Ignore Non-OL Units", it also detects when toggling Include Non-OL Units would supply every missing role, and says so with example units that cover the specific gaps.
Why
User report (openid
29080-…96007): 27 OL'd generator-eligible units built only 2 of 5 teams. Root cause was invisible in the UI: the leftover pool held one lone 40s Burst I (Moran, who can't sustain the stage alone) and zero Fire units (all three consumed by teams 1–2). The replayed diagnosis on that account's stored roster reports exactly those two gaps and that the non-OL toggle clears them.How it mirrors the search
The diagnosis re-states the search's own legality rules (
isLegal/stageCovered/canFormLegalTeam,elementOk, therequiredAnyavailability filter) per-dimension. An empty result deliberately does NOT promise a team exists (cross-dimension binds fall through to a generic message — follow-up filed in QUEUE.md item 5). Union rows diagnose against their own boss weakness and their own pool (consumed + later-reserved units excluded). The shared panel is tagged by source generator so a note never renders on the wrong tab.Review
Cross-family
/code-review(Claude-authored → kimi-code/k3): CLEAN, model stamp verified. 2 FOLLOW-UPs + 1 NOTE; the reviewer's suggested fixes for the fit-case example picker and a comment attribution were applied in52a4c14b, the third (offer the non-OL hint on undiagnosed shortfalls) is filed indocs/handoffs/QUEUE.md. Packet + verdict JSON retained atscratchpad/gates/2026-08-25-roster-shortfall/(gitignored audit trail).Testing
scripts/tests/generators/shortfall-diagnosis.test.ts— 10 cases incl. pool preconditions (roster drift fails loudly, not silently)bash scripts/verify.shgreen (typecheck, regression, web build + smoke)Proposed patch note (needs owner approval before publishing to the Dev page)
🤖 Generated with Claude Code