Two bugs, both of them the adapter drifting from what the core says.
PACK was a module global set once at boot to barrow. load() never
switched it and enter() read PACK.forgeStageType, so a port delve
authored at the desk staged barrow geometry — the fiction said quayside
and the map was a burial chamber. Fifteen of the sixteen themes, silently
wrong, on the path the module documents as its intended entry point. It
now resolves per call from d.params.theme, which is written from pack.id
at generation and so is always present and always right. Per call rather
than once at load, because a page reload resets the global while the
staged delve in world state survives; and before the folder is created,
so a bad theme fails without leaving anything behind.
The pack roster describes the encounter DELVE planned. The Forge takes no
cast — it rolls its own monsters from the heat — so the roster and the
actors in the world were never the same list, and both surfaces printed
the roster's stats as though they were. In several themes the roster also
carries "blessed, silvered or magical weapons ONLY", naming a Wraith that
was never created; the journal told the GM to say so before initiative.
Both surfaces now run off the actors that exist, read from the documents
themselves, and the plan is kept but labelled as the plan. The chat card
drops the immunity line entirely — it is the live surface and a false
immunity is worst there; the journal keeps it captioned, since a GM at
the desk may choose to cast the fight by hand.
Adds one core test for the contract the fix rests on: every delve records
the pack it came from, across all sixteen. The adapter itself has no test
harness — see the note in the commit for the release.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Groundwork for many themes, plus the first new one.
A pack validator enforces every structural rule this project learned the hard
way: situations that render as broken English, decisions that gate progress with
no alternative, motifs too thin to fill six areas without repeating, rosters
that do not say what harms them. Fifteen packs cannot be hand-checked; this
checks them in a second.
Themes are now discovered from content/index.json rather than hardcoded, so the
CLI takes --theme and --themes, the Foundry dropdown fills itself, and packs
load on demand instead of all at once.
Castle: four appetites — to be feared, never to give ground, to be obeyed at
once, the name to go on — over barrow geometry, since a keep is rooms and
corridors. 168 kernels from its own claimants and accommodations.
Fixed a bug the second theme exposed: the question the bottom problem asks was
hardcoded against barrow's appetite ids, so every other theme fell through to a
generic "Well?". It lives on the appetite in the pack now, and the validator
requires it.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Two bugs the first real button-press exposed.
The ⛏ never appeared. getSceneControlButtons was written for the old array
shape, but v13+ passes a record keyed by name and the token group is `tokens`,
plural — so the hook silently added nothing. Every earlier test had gone through
the API, which masked it completely. It now handles both shapes.
Area names were picked per-area from a small per-role list, so two areas sharing
a role could collide: a generated dungeon shipped with two scenes both called
"The Lesser Vault". Names are now dealt globally without replacement, falling
back to other roles' lists before ever repeating. This is the same bug already
fixed for features, decisions, temptations and situations — missed for names
because names were assigned in beat.mjs rather than dealt in delve.mjs.
A test now generates 180 delves at 6, 9 and 12 areas and asserts no two areas
in one delve share a name. Tests 38 -> 39.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The brief was a tool in Foundry that generates everything on a click and injects
it as a new dungeon. Previously the module could only stage a delve authored at
the desk, and the only way in was a console command — an API with a button glued
on, which is why it looked like nothing was there.
The ⛏ button now opens a form (theme, areas, depth, heroes, deadliness, density,
greed, clock, ending, seed, and whether to build maps and roll encounters), and
Raise the dungeon builds the lot in about five seconds:
• a folder per document type, named for the dungeon
• one scene per area, walls and lighting placed, via the VANITY Forge
• encounter actors, foldered rather than scattered across the world
• a JournalEntry — GM truth, a page per area, the ending — which is the
adventure, and is written to be read cold
The journal is the deliverable. Scenes without it are a pile of maps.
Generating is cheap, so removing had to be. Every document DELVE creates is
stamped with a dungeonId, and a 🗑 button lists what it built and deletes one
dungeon entirely — confirming with exact counts first, and never deleting the
scene the GM is standing in. Colour is not an identifier: it is a Color object,
and a GM may recolour a folder.
Verified live: two dungeons raised from the form and the API, then one removed
cleanly at -3 scenes, -10 actors, -1 journal, -3 folders with nothing else
touched.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
DELVE is an authoring system now, so the module's job changed: it no longer
generates at the table, it stages what the GM finished at the desk.
game.delve.loadFile('name') reads a finished working file from the world's
delves/ folder; load() takes an object; draft() still generates in-world but
announces itself as unfinished. outstanding() and ready() report what is
missing, and an unfinished delve says so on load rather than pretending.
The important change is two audiences. The read-aloud is what players are
there for, so it is posted publicly, spoken by the area's name. The truth,
the numbers, the situation and the leverage point stay whispered to the GM.
Everything used to be whispered, which meant the one thing written for the
table never reached it.
Verified live in the-vain-crown: a finished five-area delve loaded, reported
zero outstanding, and staged in 5.8s — six public read-alouds, six GM whispers,
nine actors in one delve folder, zero loose Encounter folders. Test debris
swept afterwards; the world is back to its original 8 scenes and 30 actors.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>