Skip to content

Generator shortfall explainer: say why a run built fewer teams than requested - #149

Merged
Infernal-Crack-LED merged 9 commits into
mainfrom
worktree-roster-shortfall-explainer
Aug 25, 2026
Merged

Infernal-Crack-LED merged 9 commits into
mainfrom
worktree-roster-shortfall-explainer

Conversation

@Infernal-Crack-LED

Copy link
Copy Markdown
Owner

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:

  • Burst I / Burst II cooldown coverage (one ≤20s caster, or two ≤40s alternating)
  • the two-Burst-III minimum
  • the slot-fit case (both stages only coverable by 40s pairs → 2+2+2 > 5)
  • the boss-weakness element rule (per-boss for Union rows)
  • the healer requirement (relaxing when no healer is eligible, mirroring the search)

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, the requiredAny availability 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 in 52a4c14b, the third (offer the non-OL hint on undiagnosed shortfalls) is filed in docs/handoffs/QUEUE.md. Packet + verdict JSON retained at scratchpad/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.sh green (typecheck, regression, web build + smoke)
  • Panel visually verified at desktop + mobile widths
  • End-to-end replay of the reporting account's stored roster reproduces the report

Proposed patch note (needs owner approval before publishing to the Dev page)

Team generators now explain themselves. When the Team Generator, Roster Generator, or Union Raid generator can't build every team, it now tells you why — which burst role, element, or healer your remaining units ran out of — and points out when "Include Non-OL Units" would fix it.

🤖 Generated with Claude Code

Infernal-Crack-LED and others added 7 commits August 25, 2026 14:46
…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>
@Infernal-Crack-LED

Copy link
Copy Markdown
Owner Author

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 (formation: hasB1) — a shape the search never produces from enumeration. delta-ninja-thief (heal requires a Defender ally) has the same defect.

  • HEALER_SLUGS moved to web/src/healerSlugs.ts (vite-free so tests import the real list under the root tsconfig), excluding the two condition-dormant healers; the constraint, the shortfall diagnosis, and its example picker all share the filtered list. The prose-derived tag itself is untouched — the sustain/buffer boards keep it, correctly (anis-star does heal in double-B1 comps).
  • New regression: scripts/tests/generators/healer-constraint.test.ts — pins the exclusions (with a completeness check) and re-runs the reporting account's 27-unit pool through the search: every team now fields a healer that can actually heal.
  • Cross-family review of the increment (kimi-code/k3): CLEAN, 2 NOTEs, both applied (f19780af). Verdict at scratchpad/gates/2026-08-25-healer-fix/result.json.
  • verify.sh green.

Updated draft patch note (still needs owner approval before publishing)

Team generators now explain themselves. When the Team Generator, Roster Generator, or Union Raid generator can't build every team, it now tells you why — which burst role, element, or healer your remaining units ran out of — and points out when "Include Non-OL Units" would fix it.

"Include Healer" now guarantees a working healer. Units whose healing only activates under conditions a generated team can't meet (like Anis: Star's, which needs a second Burst I ally) no longer count as the team's healer.

🤖 Generated with Claude Code

Infernal-Crack-LED and others added 2 commits August 25, 2026 16:08
…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>
@Infernal-Crack-LED
Infernal-Crack-LED merged commit 43308bd into main Aug 25, 2026
1 check passed
@Infernal-Crack-LED
Infernal-Crack-LED deleted the worktree-roster-shortfall-explainer branch August 25, 2026 23:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant