Adv 2.0 D&D Phase 12 E5: Extraction & Resume

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>
This commit is contained in:
prosolis
2026-05-08 16:36:05 -07:00
parent a199efd773
commit d179ca27a7
8 changed files with 461 additions and 9 deletions

View File

@@ -520,11 +520,17 @@ func abyssPortalTemporalPostRollover(e *Expedition) []string {
return []string{line}
case "collapse":
line := flavor.Pick(flavor.AbyssPortalCollapse)
forced := flavor.Pick(flavor.ExtractionForced)
_ = appendExpeditionLog(e.ID, e.CurrentDay, "temporal",
"portal collapsed — expedition forcibly extracted", line)
// Forced extraction: spec §7.6 marks the run failed.
_ = completeExpedition(e.ID, ExpeditionStatusFailed)
return []string{line}
// §10.2: forced extraction → abandoned. Coin tax is applied by
// the cycle layer (which holds the euro handle) once it sees
// the row flipped to 'abandoned'.
_, _, _ = forcedExtractExpedition(e.ID, "abyss portal collapse")
e.Status = ExpeditionStatusAbandoned
_ = appendExpeditionLog(e.ID, e.CurrentDay, "narrative",
"forced extraction", forced)
return []string{line, forced}
}
return nil
}