New file internal/plugin/expedition_balance.go — sibling to
dnd_class_balance.go, no dnd_ prefix per feedback_avoid_dnd_naming.
Plan doc: gogobee_expedition_difficulty.md.
Critical de-risk settled: clock-injection seam. The harness does not
run the wall-clock tickers (expeditionBriefingTicker @ 06:00,
expeditionRecapTicker @ 21:00, expedition_ambient @ 3h) and does not
inject a virtual time.Now. Instead, advanceExpeditionOneDay
reimplements the morning→day→night pipeline by calling the math-pure
helpers directly: applyDailyBurn, dailyThreatDrift,
resolveCombatInterrupt, resolveWanderingCheck, simulateCombatWithRNG.
No DB, no goroutines, no clock.
Phase 0 trade-offs (documented in the file header):
- Boss completion deferred; survive-N-days is the proxy.
- Per-region zones, loot/XP, pardon/Sovereign, babysit, temporal
stack effects all skipped — Phase 1+ scope.
- Encounter cadence (harnessHarvestRollsPerDay=4) is a placeholder
to be calibrated against live traces in Phase 1.
Tests:
- TestExpeditionBalance_Phase0_Spike — T2 Crypt Valdris × L5 Fighter,
100 trials, asserts only degenerate sentinels (no 0%/100%, days>0,
days<=cap). Runs in <3s.
- TestExpeditionBalance_Phase0_SeedSpread — confirms the RNG seam is
actually wired by showing two distinct seeds produce different
trials. Full byte-for-byte reproducibility under same seed is not
asserted at Phase 0; surpriseRoundNick + pickWanderingMonster
draw from package-global rand (same caveat as class balance).
Spike numbers (calibration baseline, NOT a target): 1% completion,
99% deaths, median 4 days, ~6 encounters. The headline death rate is
loud but expected — Phase 1's full matrix will diagnose whether it's
HP-carryover punishment, bestiary-vs-abstract-monster delta, or kit
ladder mismatch. Phase 2 is where the centerline gets tuned.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>