From civic web to whodunit
Classic Clue is famously motiveless — person, room, weapon, no why. This stack inverts that: it grows a town whose relationships are real enough to read grievances off, then generates murder mysteries whose motives, alibis, witnesses and red herrings are all structure the web already carries. Every case is certified solvable before it ships, and every closed case scars the web the next case grows from. This page documents the whole stack — and because every kernel is deterministic, zero-dependency, client-side JS, the figures below are not screenshots: they are the actual kernels, running in your browser, on the seed in the topbar.
1The stack
Three kernels, each pure and node-tested, each consuming the one below:
scoreSociety scores the whole thing Thriving…Failing. Vendored from hoop/v099/econ, copy-never-fork.The important property is that each kernel adds no facts, only readings. Goss doesn't invent tribes — it finds them by label propagation over the tie graph. Case doesn't invent motives — it promotes one existing grievance to a cause and lets the rest stand as red herrings. Plausibility is inherited, not authored.
2The society underneath
A society is fully determined by (genome, seed). Places are buildings sized by
function; people are laid over them wearing many hats — Jim = mend@chopshop + grow@home +
worship@chapel. The hats are everything downstream: they are the tie generator, the schedule, the
means-access list and the alibi, all at once.
The vitality oracle is the civ-health readout used everywhere in this repo (the same
Thriving…Failing tiers as hoop.mino.mobi/econ and the chunkroller): supply closure ·
thickness (hats/person) · weave (reach) · bridges (weak-tie share) · third places · employment ·
resilience (hub-removal damage), weighted into 0–100.
3The six goss layers
| layer | what it derives | how |
|---|---|---|
| 1 demographics | age, pronouns, household surname, unique given name, kinship (head · partner · child · sibling · kin) | seeded off stable person identity; the engine itself carries none of this. Cast once — deaths never rename anyone. |
| 2 ties | the person↔person weighted graph | projected from co-membership, weighted by how binding the context is: partner 4.0 > household 3.0 > co-work 2.0 > co-worship 1.5 > club/sport 1.2 > weak 0.8. Every tie carries its evidence (the places it happened at). |
| 3 tribes | emergent communities + totem place + name | deterministic label propagation over the tie graph. No faction is assigned at the NPC level anywhere in the engine — tribes are found, not given. |
| 4 romance | established couples + new sparks, flagged cross-tribe / affair-risk / triangle | couples from kinship; sparks are seeded attraction over strong non-household ties, adults only. |
| 5 tension | the two axes: tribalism (polarization, contested places, defectors) and the narcissism of small differences (near-twin tribes stitched at a fraction of what random mixing predicts) | both are functions of (similarity, link) per tribe pair; link uses the configuration-model null. |
| 6 dramas | typed seeds ranked by heat: FEUD · SCHISM · STAR-CROSSED · AFFAIR · TRIANGLE · RIVALS · DEFECTOR · MATCH | instantiated from graph patterns; each carries its evidence (people, places, tribes, the numbers that fired it). |
4Seven webs → one web
Hoop's nave (floor 1) is a commons ringed by six faction wards. The engine scores each ward
alone — seven sealed societies, zero cross-ward ties. The unified reading runs one society
over all seven chunks, hats crossing wards by nearest distance (the game's own commute rule writ
large). Measured across every baked seed (goss/UNIFIED.md): the unified floor wins on civ
health everywhere — mean vitality 69.5 → 85.9 — because the wards are designed specialized,
so a sealed ward is a structurally incomplete economy and a thin society by construction.
For mysteries the unified floor turned out to be a prerequisite, not a preference: a sealed ward is one strong-tie clump, and clump-souls have no independent witnesses — alibis can neither be trusted nor falsified. No unification, no whodunits.
5Anatomy of a case
A case is five samplings and one certification, all deterministic from (seed, case №):
| part | where it comes from |
|---|---|
| motive | grievancesAgainst: dramas involving the victim, rivals (same job, near-identical webs), wronged partners (sparks vs the couple map), household succession. The victim is chosen where the grievance circle is deepest and most diverse; one grievance is promoted to the cause; the rest are red herrings with genuine motive but innocence. |
| time | a six-watch day — dawn · morning · midday · afternoon · evening · night — each soul's hats laid out as a schedule, seeded off stable identity, so a survivor keeps the same routine across every case of a chain. |
| opportunity | the crime happens at the victim's scheduled place on some watch; a suspect's alibi is their own scheduled place on that watch. |
| witnesses | co-scheduled souls — but only independent ones clear a name (tie weight < 1.5, Granovetter's weak ties as evidentiary value). The household swearing to you is worth exactly what kin's word is worth. The culprit is never corroborated. |
| means | items typed by place role — clinic sedative, chopshop spanner, works cable, canteen ration, garden desiccant, exchange weighing-bar — access is a hat query. The planted item is drawn from the culprit's access set among those keeping ≥2 suspects on the board (pacing is a generation constraint); a culprit with no means-role hats gets the cord that narrows nothing. |
| clues | body → rumor → the coroner's finding → the canvass (one alibi per suspect) → sightings (age band · ward colours · trade) → traces (a member's token, a household thread) → grounded last resorts (a passerby whose schedule really crosses the claimed place on the adjoining watch; the reluctant eyewitness whose schedule really brushed the scene). |
6The solvability oracle
The generator's contract: the planted clue list, replayed cold as a deductive closure (eliminations only), must converge on exactly the culprit — never eliminating them along the way. If a watch won't close, the generator tries another; unsolvable cases never leave the kernel. This is the same discipline as hoop's quest-solvability oracle: prove the puzzle before shipping it. Below, this seed's case № 1 with its closure traced clue by clue — this is the real case the viewer opens, spoilers and all:
7The chain — a seed is a casebook
Closing a case removes the victim (buried) and the culprit (taken). The relational layers — ties,
tribes, romance, tension, dramas — re-run over the survivors, while demographics stay
cast-once: nobody is renamed by a death, and every survivor keeps their routine. Case n+1 is
generated from the scarred web: grievances shift, tribes re-knit, the town thins. Same seed ⇒ same
casebook, forever — which is why ?sub=&seed=&case=n is a permalink (prior cases
replay closed with the true culprit).
A cold case (three dismissed accusations) reveals the truth and the chain continues identically — the culprit is taken either way. The tempting fork — a cold case leaving the killer free on the web, eligible to kill again — is deliberately not built: chain state would then depend on play outcomes and permalinks would break. The deterministic casebook is worth more for now.
8Determinism, tests, what's next
Determinism is load-bearing. Every layer is seeded hashing + mulberry32; there
is no Date.now() and no unseeded randomness anywhere in the kernels. That is what makes a
permalink a promise, the bake a byte-identical no-op, and the oracle's certificate meaningful.
| contract | pinned by |
|---|---|
| the goss kernel — determinism, emergent tribes, both tension axes, evidence-bearing dramas, the nave contract (zero cross-ward ties sealed / crossing floor) | tide/goss/test/gossip.selftest.mjs |
| the unified-web findings — sealed vs floor health, the v101 unlock-chain churn, solve-order independence | tide/goss/tools/study-unified.mjs + goss/UNIFIED.md |
| the case kernel — closure ≡ {culprit}, culprit never eliminated, alibi honesty, pacing, cast-once identity, 6-case chains on every baked seed + econ towns (60 cases certified) | tide/case/test/casegen.selftest.mjs |
Where this goes next
hoopy retelling — cases are structured JSON with prose sketch lines, exactly the borges shape: procedural bones, model retelling, frozen per seed route-aware opportunity — schedules currently teleport between watches; pricing hoop's nav routes makes "could they have crossed the floor in time?" a clue axis the other genres — maintenance mysteries over the forge flow web (a planted fault, symptoms propagating through conserved books) and romance arcs (the tie graph run forward): the same machine on different graphs