The 0.10.4 requirement only reaches an installing GM through the release
manifest, so it needs a release to take effect.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The manifest asked for VANITY 0.10.0, but the Forge seams only landed in
0.10.4. Below that floor the seams are absent and every delve emits the 9
chat cards and 3 folders the spike measured — the exact failure the seams
exist to prevent. The README said 0.10.5, which was safe but wrong; both
now say 0.10.4 and say why.
DESIGN.md still described the tool as an unreleased core with one theme.
It now matches what shipped: seams merged and released, the Foundry slice
at v0.6.0, 16 themes across 5 geometries, 39 tests, the pack validator and
the authoring layer. The features pool is motif-scoped now, so the "last
piece of generic furniture" is gone.
Open questions gain the one that matters: DELVE has never been run at a
live table, and no amount of desk validation will close that.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Five wild-kernel themes, each 4 motifs:
cave dark · deep · echo · keeping (cave geometry)
mountain ascent · cold · pass · weight (cave)
river crossing · current · course · drowned (fen)
lake stillness · mirror · sunken · rising (fen)
valley ridges · shelter · bottom · weather (forest)
Two rendering fixes surfaced by the new claimants, both in skeleton.mjs:
- `{conscript}'s` rendered "the climbers's"; conscripts are plural noun
phrases, so fill() now collapses s's to s'.
- claimants carrying their own article rendered "The The Grey"; named()
only prefixes when one is absent.
All 16 themes validate; 39 tests pass. Module → 0.6.0.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Barrow and Castle share a kernel — a dead claimant whose appetite outlived them.
A market or a river has no corpse in it, so the other two families needed the
kernel to generalise, and it does: something wanted a thing, and something was
done to keep it that way. Only who "something" is changes.
TOWN, on village geometry. The appetite belongs to the place and the claimants
are offices — a Corporation, a Watch Committee, a Guild of Mercers. It wants to
be prosperous, respectable, safe or necessary, and it priced people out,
chartered them away or struck them from the rolls to stay that way. Motifs:
ledger, appearances, vigilance, thoroughfare.
FOREST, on forest geometry. The appetite belongs to the wood, and the claimants
are its own names for itself. It wants to be entered, fed, spread or left
uncounted, and it took people, grew through them, or let them wander. Motifs:
paths, tithe, reclaiming, trackless.
Settlements also needed their own naming rule. A barrow is named for its
occupant; a town is not — it has a name and the claimant merely runs it. Packs
declare placeNameStyle, so "The Town of Watch Committee" is now Cold Harrow, run
by the Watch Committee.
Three of fifteen requested themes are done. The remaining twelve are the same
job repeated rather than a design question, since all three kernels now exist.
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>
Installing by manifest URL failed on a remote server:
[Module.vanity-delve] validation errors: relationships: systems:
ArrayField 0: type: requires is not a valid choice
The relationship entry used type: "requires". In Foundry's schema `type` is the
PACKAGE type — module, system or world — and the relationship kind is expressed
by which array the entry sits in. So the correct value is "system".
The entry now also carries VANITY's manifest URL, so Foundry can offer to
install the system rather than just refusing.
This was never caught because the module had only ever been installed by copying
files into Data/modules by hand. The validator that rejected it only runs on the
manifest-install path, so every local test passed while the published artifact
could not be installed at all — the same shape as the scene-control hook bug,
where testing the layer below the interface hid a failure in the interface.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The repo went public with no LICENSE, which means default copyright — nobody
could legally reuse any of it. MIT throughout, covering the generator and the
VANITY prose alike.
Also adds a README, since the front page was previously a design document that
opened mid-argument, and sets module.json's license field so Foundry shows it.
Module to 0.1.2 so the released zip carries LICENSE too.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Eleven files carried "Private VANITY development material — not for sale or
distribution", which contradicted the repo the moment it went public.
Two replacements, because the files do two different jobs. core/render.mjs
*emits* its footer into every generated delve, so that one now says where the
document came from rather than restricting what can be done with it — a
generated dungeon belongs to whoever generated it. The project's own documents
— DESIGN.md, the paper delve, both playtests, the spike report — read as
development notes in a public repo.
Samples regenerated so they carry the new line. The worksheet and play sheet
never had a footer and still do not; they are the GM's own working documents.
Module to 0.1.1: the v0.1.0 zip vendors the old render.mjs and would stamp the
stale footer on everything it generated. Cutting a version rather than swapping
assets under the existing one.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
What was on git could not be installed. foundry-module/ referenced core/ rather
than containing it, so an installed copy had no generator at all — it only ever
worked here because the live module directory had core/ copied in by hand.
core/ is now vendored into foundry-module/module/core/, minus cli.mjs and
test.mjs which are desk tools. module.json points manifest and download at
release assets, the way mapwright distributes, so a remote server can install by
URL without reaching into the repo tree.
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>