Mechanical `gofmt -w ./internal ./cmd`. Mostly struct-field realignment that
had drifted, plus a few trailing-newline fixes. No behaviour change — gofmt is
semantics-preserving, and build/vet/test are green either side.
Split out from the code-review fixes that follow so those stay reviewable
instead of hiding inside a wall of realignment.
- Harvest tables (expedition + standalone) now keyed by node_id; legacy
room-idx entries auto-migrate via read-fallback + drop-on-save.
- Narration salts swapped from run.CurrentRoom to narrationCadence(run)
(= len(visited_nodes)-1) so flavor pickers survive G9 column drop.
- !zone map renders the graph (BFS by PosX/PosY) when the gate is on:
✓/▶/· status, ╳ for locked-only edges, secrets hidden until visited.
- Region-boundary hook in graph advance/!zone go updates expedition
CurrentRegion + visited list when from/to nodes differ — without
burning supplies or retiring runs (the graph IS the run state).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Wires the §3 zone-note interactions that were called out across the
resource doc but left for the polish pass.
Harvest gates (dnd_expedition_harvest.go):
- zoneConditionHarvestBlock — Underforge Heat 10 blocks !mine, Dragon's
Lair infernax_awake blocks all harvesting, Abyss Instability 81+
blocks all harvesting.
- zoneConditionHarvestDCMod — Underforge Heat 7-9 → +3 !mine DC,
Dragon's Lair Awareness Pulse 3+ (day 9+) → +4 all DCs, Abyss 61-80
→ +5 all DCs, Feywild Double-Day → -3 !forage DC. Delta + reason
shown inline on the dice line.
- restoreHarvestNodesInRoom — Time Loop hook (in-memory only; cycle
flow persists downstream).
- Manor !scavenge: 10% Cursed Trinket secondary drop with one-time
TwinBee warning gated by RegionState["manor_cursed_warned"].
Time Loop wiring (dnd_expedition_temporal.go):
- feywildTemporalPostRollover Loop branch now restores nodes in the
current room and appends a re-emergence narration line.
Drow Poison Blade recipe (dnd_economy.go):
- ThomCraftRecipe gains BladeWeaponCount; pickBladeWeapons matches
Type=="weapon" + blade keyword (sword/dagger/blade/scimitar/etc.).
- !craft list shows the blade slot with current inventory count.
- Recipe consumes 1× Drow Poison + 1× any blade weapon → Drow Poison
Blade (sleep-on-crit for 3 combats, effect TODO).
Tests (dnd_zone_conditions_test.go, all DB-free): block branches per
zone, DC delta tables, manor cursed-trinket gate at 10% boundary,
restoreHarvestNodesInRoom in-memory roundtrip, isBladeWeapon /
pickBladeWeapons coverage + shortfall + exclude-already-consumed,
drow_poison_blade recipe shape.
Flavor reuse only — no new flavor file. Reasons-strings on the dice
line and the cursed-trinket warning are inline (Thom/TwinBee voices
in existing pools didn't fit harvest-blocking or warding contexts).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Voluntary !extract burns 1 day, flips status to 'extracting', keeps
all rewards, resumable for 7 real days. Forced extraction (Abyss
collapse, future HP-0/supply-0 hooks) flips to 'abandoned' and applies
the §10.2 20% coin tax via the cycle layer's euro handle. !resume
within the 7-day window repurchases supplies and restores threat &
temporal stacks as-is; expired rows demote to failed.
getActiveExpedition / briefing / recap loaders narrow to status='active'
so 'extracting' rows don't get phantom day rollovers. Reuses
flavor.ExtractionVoluntary, ExtractionForced, ExpeditionResume from
twinbee_expedition_flavor.go.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
§7.6 instability accumulator: +5/day (cap 100), persisted via
TemporalStack. Bands:
• 0–20 normal
• 21–40 mild (-1 WIS)
• 41–60 reality warps (rooms shift order)
• 61–80 demon surges (12h wandering)
• 81–99 unraveling — forces 2× supply burn override + -2 all rolls
• 100 collapse — forced extraction (status = failed)
Pre-burn override fires at 81–99 so the supply doubling lands the same
day the band activates. Collapse at 100 calls completeExpedition
with ExpeditionStatusFailed and emits the AbyssPortalCollapse line.
Adds ReduceAbyssInstability(e, n) for the §7.6 -10 per major story
objective; combat-link wires the call when objectives complete.
Combat-side knobs (WIS/all-roll penalties, room-shift, surge cadence)
are exposed via AbyssInstabilityBandFor — combat-link reads on tick.
Reuses flavor.AbyssPortalDestabilizationMid / Critical / Collapse per
feedback_reuse_existing_flavor.
Closes Phase 12 E3 (Zone Temporal Events). Next session = E4
(Multi-Region Zones).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
§7.5 awareness pulses on Day 3, 6, 9, 12, ... apply +10 threat at
briefing rollover and log a temporal entry (DragonsLairAwarenessPulse
flavor). Day-14 awakening sets RegionState["infernax_awake"]=true
once, with the §7.5 awakening narration; the pulse line is suppressed
that day so the awakening narration carries the moment alone.
Combat-side knobs (kobold patrols +1 enemy per active room, 6h
wandering cadence, dragon-encounter weighting in the wandering table,
forced extraction pressure once awake) are exposed via the
infernax_awake region flag — combat-link phase reads it to switch
behavior. Boss-defeated suppresses entirely.
Reuses flavor.DragonsLairAwarenessPulse / DragonsLairAwakenWarning per
feedback_reuse_existing_flavor.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
§7.4 daily 1d6 distortion roll fires at briefing time:
• 1–2 normal day (no override)
• 3–4 half-day → 0.5× burn multiplier override
• 5 double-day → 2.0× burn + extra wandering check at recap
• 6 time loop → narration only; combat-link reads on next room
Refactors applyZoneTemporalPreBurn to return TemporalBurnOverride
(Multiplier-based) instead of a force-double bool. Sunken Temple's
Day-6 tidal piggybacks on the same override pipeline (2.0×) instead
of the siege-flag hack.
Persists the day's distortion bucket to RegionState["feywild_today"]
so the recap path can fire the §7.4 extra wandering check on
double-day.
Reuses flavor.FeywildTimeDistortionHalf / Double / Loop per
feedback_reuse_existing_flavor.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
§7.3 heat stacks: +1/day in the Underforge (cap 10), persisted via
new updateTemporalStack helper. Band thresholds:
• 1–3 ambient (no narration)
• 4–6 warning band (combat fire damage applies, narration logged)
• 7–9 supply band (forces harsh-conditions burn = +50%, narration)
• 10 critical (exhaustion narration, log entry)
Fortified/base camp long rest in the Underforge drops heat by 2
(updates briefing's "Fortified rest" summary line), per §7.3.
Replaces the placeholder `TemporalStack > 0 → harsh` predicate in
deliverBriefing with zoneTemporalHarsh(), which is now per-zone aware
— Heat 1–3 in the Underforge is correctly flavor-only and no longer
prematurely doubles supply burn from Day 1.
Combat-side knobs (+1d4 fire round-start damage at heat 4–6, dis CON
saves at 7–9, -2 to all rolls at 10) are exposed via heat band but
not yet applied — combat-link phase reads heat band off the active
expedition.
Reuses flavor.UnderforgHeapWarning / UnderforgHeapCritical per
feedback_reuse_existing_flavor.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
§7.2 cycle: every 3rd day's morning briefing in Blackspire fires the
"manor reset" temporal log — non-boss rooms respawn one enemy each.
Boss-defeated suppresses. Wrong-zone is a no-op.
Exposes ManorReset(e, day) bool for the combat-link phase to read at
!advance time when applying the actual respawn (per the deferral
pattern from E2b's wandering-encounter combat).
Reuses flavor.HauntedManorResetMorning per feedback_reuse_existing_flavor.
Deferred: Night-2 quiet warning narration on the recap path — needs
a new hook in deliverRecap; not load-bearing for the reset itself.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds the §7.1 tidal event hook: warnings on Days 4 and 5, peak event
on Day 6 with forced 2× supply burn (overrides tier-2 HarshMod 1.5×),
silenced if the boss has been defeated.
Wires zone-temporal events into deliverBriefing as two new hook points
— pre-burn (mutates burn multiplier) and post-rollover (appends
flavor-bearing log entries). Future E3b–E3f layer onto the same hooks.
Reuses the prewritten flavor.SunkenTempleTidalWarning / TidalEvent
pools per feedback_reuse_existing_flavor.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>