Add The Frontier, a second setting, and a picker to choose between them

Cold Fork is a freight yard: 29 events across two stages, a four-day cycle, and
its own relationship and skill vocabulary. src/engine/ was not touched. Adding it
needed three changes outside the engine: one save slot per pack, app.js holding
the current pack, and turn.js no longer naming the mailroom (DECISIONS #34).
build.js now handles imports wrapped across lines. A conformance suite runs over
every registered pack. DECISIONS #35 records three calls on open questions.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxdJFbLq1rBKsUeticGV1g
This commit is contained in:
JesseMarkowitz
2026-09-12 21:03:50 -04:00
co-authored by Claude Opus 5
parent 4957c24e31
commit 7f20be83e8
25 changed files with 3015 additions and 300 deletions
+5 -1
View File
@@ -79,7 +79,11 @@ async function collect(entryPath, seen = new Map()) {
const source = await readFile(entryPath, 'utf8');
seen.set(entryPath, null); // reserve the slot before recursing
const specifiers = [...source.matchAll(/^[ \t]*import\s.*?from\s*['"]([^'"]+)['"];?[ \t]*$/gm)]
// `[\s\S]*?` rather than `.*?`: a destructured import may be wrapped across
// several lines, and `transform` below already rewrites those — a scan that
// missed them produced a bundle with a __require for a module that was never
// collected, which only failed when the bundled game was run.
const specifiers = [...source.matchAll(/^[ \t]*import\s[\s\S]*?from\s*['"]([^'"]+)['"];?[ \t]*$/gm)]
.map((match) => match[1])
.filter((specifier) => specifier.startsWith('.'));