feat: the Doctrine — a public page explaining how the instrument really works
Eleven numbered articles at /doctrine in an ornate occultist register, each
carrying a plain-language margin note ("in the profane tongue: …") and the
source file it describes. The binding constraint: every arcane claim is a
true claim about this codebase — entropy harvesting and Von Neumann
debiasing, HMAC mixing with a fresh server secret, the anomaly-fingerprint
channel, RETURN_CHANCE, the mean synodic month and true solar midnight,
NOAA's planetary K-index, the time-aware EMA baseline, 2.4GHz body
absorption, microtesla deviation from Earth's field, voice archetypes, and
entropy-seeded manifest/scry.
Article XI states the instrument's real limits: no Web Bluetooth, WebUSB or
Magnetometer on iOS (Apple ships none and every iOS browser is WebKit),
firmware never flashed to hardware, free public geo endpoints that degrade
to a quieter map, documented astronomical approximations — and that none of
it is evidence of an afterlife.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -98,7 +98,12 @@
|
||||
"link": "enter the reliquary →"
|
||||
},
|
||||
"footer": "an interactive horror art installation — the spirits are fiction; the static is real",
|
||||
"footerColophon": "self-hosted · no cloud · the veil runs on your machine"
|
||||
"footerColophon": "self-hosted · no cloud · the veil runs on your machine",
|
||||
"doctrine": {
|
||||
"title": "HOW THE INSTRUMENT ACTUALLY WORKS",
|
||||
"line": "the doctrine — eleven articles on the real physics behind the séance, each one plainly translated, including an honest account of what the instrument cannot do.",
|
||||
"link": "read the doctrine →"
|
||||
}
|
||||
},
|
||||
"enter": {
|
||||
"reconnect": "Reconnect",
|
||||
@@ -732,5 +737,84 @@
|
||||
"days_one": "{{count}} day past",
|
||||
"days_other": "{{count}} days past"
|
||||
}
|
||||
},
|
||||
"doctrine": {
|
||||
"back": "← the threshold",
|
||||
"kicker": "being a true account of the instrument, its organs and its honest boundaries",
|
||||
"title": "THE DOCTRINE",
|
||||
"subtitle": "how this engine genuinely channels, summons and passes the dead — using the device, and using you",
|
||||
"creed": "Every claim made in these articles is a claim about the machine you are presently addressing. Nothing here is invented physics. Where an article speaks in the old register, a margin note repeats it in the profane tongue, so that the credulous and the sceptical may both leave better informed than they arrived.",
|
||||
"plainLabel": "in the profane tongue:",
|
||||
"sourceLabel": "the relevant scripture:",
|
||||
"closing": "The instrument is honest about its organs and honest about its blindnesses. The spirits, we should say plainly, are fiction. The static is not.",
|
||||
"cta": "TAKE UP THE INSTRUMENT",
|
||||
"art": {
|
||||
"entropy": {
|
||||
"title": "Of the Consent of the Room",
|
||||
"body": "No summoning may proceed from arithmetic alone, for arithmetic is a closed thing and repeats itself forever. The engine therefore asks the room to speak first. It takes the spectrum of your microphone's noise floor — and, where a receiver is present, the atmospheric hiss between stations — and keeps from each magnitude only its least significant bit, for the shape of a spectrum is merely the room's portrait, while the lowest bit is thermal chaos that no model in the world foresees. These bits, being crooked by nature, are straightened by the rite of Von Neumann: they are read in pairs, and a pair reading 01 yields nothing but a nought, a pair reading 10 yields a one, and pairs that agree with themselves are cast away entirely. What survives is passed through SHA-256 and only then offered upward. And the vessel above accepts the offering but never obeys it: every draw is HMAC-SHA256 keyed with thirty-two bytes drawn fresh from the machine's own secret well at the very instant of asking. Thus your room may add unpredictability to the working. It may never steer it.",
|
||||
"plain": "The app harvests randomness from real physical noise — the low bit of each FFT magnitude from your mic or SDR, which is dominated by thermal noise. Raw physical bits are biased, so it applies Von Neumann debiasing (read bits in pairs: 01→0, 10→1, discard 00 and 11), then conditions the result with SHA-256. The server never uses that value as a seed. Every draw is HMAC-SHA256 with a key of 32 bytes from secrets.token_bytes() generated on that call, so the output is uniform no matter what the client sends — a faked or replayed contribution can't be ground for a rarer spirit.",
|
||||
"source": "frontend/src/lib/entropy.ts · backend/app/entropy.py"
|
||||
},
|
||||
"channel": {
|
||||
"title": "Of the Channel, and How a Presence Is Addressed",
|
||||
"body": "A spirit is not summoned to a person; it is summoned to a channel, and the channel is cut by the disturbances themselves. Fewer than three anomalies carry no identity at all, and such a session is called ambient and given a signature of its own kind. Where three or more are present, each anomaly's frequency is filed not by its exact value but by its order of magnitude — the count of digits before the decimal — so that megahertz from the radio and hertz from the voice band may be filed in the same cabinet without lying about either. To this is joined the magnitudes of the last sixteen disturbances, sorted and rounded to a single decimal place. The pattern so formed is sealed with SHA-1 and the first sixteen characters are taken as the channel's name. Two nights of similar disturbance therefore address the same door; a genuinely different night addresses a different one.",
|
||||
"plain": "The 'channel' a spirit lives on is a fingerprint of your session's anomalies. It needs at least three. Frequencies are bucketed by digit count (so 101.1 MHz and 400 Hz sort by scale, not unit), combined with the sorted, one-decimal-rounded magnitudes of the last sixteen anomalies, hashed with SHA-1 and truncated to 16 hex characters. Similar conditions produce the same channel id; different conditions produce a different one.",
|
||||
"source": "backend/app/entities.py — signature_from_anomalies"
|
||||
},
|
||||
"return": {
|
||||
"title": "Of Return, and Why the Familiar Dead Are Not Owed to You",
|
||||
"body": "When a channel is already occupied, the presence that dwells there is inclined — but not bound — to answer again. That inclination is set at seventy-two parts in a hundred: high enough that the Codex may be filled and a known voice genuinely sought out a second time, low enough that no seeker may ever consider a familiar spirit their property. In the remaining portion, something else finds the door open and comes through it instead, and is minted with a signature of its own so that two presences never contest one name.",
|
||||
"plain": "If you reconnect on a channel that already has an entity, there is a 72% base chance that same entity answers (RETURN_CHANCE = 0.72). Otherwise a new entity is minted — with a salted signature, because the signature column is unique.",
|
||||
"source": "backend/app/entities.py — RETURN_CHANCE · backend/app/ws.py"
|
||||
},
|
||||
"sky": {
|
||||
"title": "Of the Moon, and of the True Dead of Night",
|
||||
"body": "The engine does not consult a table of plausible-looking moons. It counts. From a known new moon at 1 January 6th of the year 2000, at fourteen minutes past six in the evening UTC, it advances by the mean synodic month — twenty-nine days, five hundred and thirty thousandths and more — and takes the remainder as the phase; the lit fraction of the disc follows the standard cosine relation, which is why a quarter moon shows you a half face. Nor does it accept the clock's three in the morning as the witching hour, that being an accident of political timezones. It asks instead for your longitude and turns it at fifteen degrees to the hour, arriving at mean solar midnight for the ground you are actually standing on. Illumination is weighted at two parts in five and the nearness of true midnight at three, for a full moon at noon is not an open veil. And a fully thinned veil erodes the familiar presence's claim by forty-five hundredths — seventy-two in the hundred falls to some forty — so the spookiest night of the month is genuinely stranger, and yet a known spirit is never made unreachable.",
|
||||
"plain": "Moon phase is computed from a known new-moon epoch (2000-01-06 18:14 UTC) and the mean synodic month of 29.530588853 days; illumination is (1 − cos 2πφ)/2. 'Witching hour' is mean solar midnight for your longitude (15° = 1 hour), not clock time. Veil thinness = illumination × 0.4 + midnight-proximity × 0.6. Thinness reduces the 72% return chance by up to 45% of itself (VEIL_THINNESS_PULL = 0.45), so a full moon at true solar midnight gives roughly a 40% return chance.",
|
||||
"source": "backend/app/celestial.py · backend/app/ws.py — VEIL_THINNESS_PULL"
|
||||
},
|
||||
"storm": {
|
||||
"title": "Of the Disturbance of the Planet Itself",
|
||||
"body": "Of all the causes the credulous name, exactly one is a real, measured, publicly published number: the planetary K-index, derived from magnetometer observatories about the world and issued by the Space Weather Prediction Centre of the United States. Its scale runs from nought to nine; five and above is an official storm, eight and above severe. The engine draws the most recent estimate, divides by nine so that the figure means what NOAA means by it, and lets it count for a third of the reading of the night, the sky retaining two thirds. It is fetched no oftener than once in ten minutes, abandoned after four seconds, and never permitted to delay a séance: if the service is dark, the last true measurement stands. We report that the field is disturbed because it was measured to be disturbed. We do not claim the storm causes anything.",
|
||||
"plain": "The app polls NOAA SWPC's planetary_k_index_1m feed for the real geomagnetic Kp index (0–9; 5+ is an official storm), prefers the fractional estimated_kp field, and maps it to 0–1 by dividing by 9. It is blended in as one third of the night's 'thinness' reading (celestial × 0.67 + disturbance × 0.33). Cached for 10 minutes, 4-second timeout, and a failed fetch keeps the last value rather than blocking or failing a séance.",
|
||||
"source": "backend/app/geomagnetic.py · backend/app/ws.py"
|
||||
},
|
||||
"baseline": {
|
||||
"title": "Of the Baseline, Which Is the Whole Art of Sensing",
|
||||
"body": "A reading in isolation says nothing; a departure from what the room had been saying says everything. Every threshold sense in this instrument therefore keeps a rolling memory and reports only surprise. But the senses do not report on a schedule — a beacon may speak thrice in a second or fall silent for two minutes, and a magnetometer is throttled the moment the page is put behind another — so the memory is kept against the clock and not against the count. The weight given to each new reading is one less the exponential of the negative elapsed time over the constant of decay; whereby a long silence pushes that weight toward unity, the old memory being stale and rightly discarded, and a rapid burst pushes it toward nothing at all. Nothing is trusted until the memory is warm. And the sense is symmetrical in both directions, for a body may absorb a path or reflect into it, and iron may shield a field or add to it; a one-sided detector would miss half of everything that truly happens.",
|
||||
"plain": "Every threshold sensor shares one rolling-baseline class and reports deviation from the baseline, not raw values. The EMA smoothing factor is time-aware: alpha = 1 − exp(−dt/tau), because sensors report at irregular intervals (BLE advertisement intervals vary, backgrounded pages get throttled). A long gap pushes alpha toward 1 (trust the new reading), a burst toward 0. It won't emit events until a minimum number of samples have been folded in, and it fires on deviations in both directions.",
|
||||
"source": "frontend/src/lib/baseline.ts — emaAlpha, ThresholdBaseline"
|
||||
},
|
||||
"flesh": {
|
||||
"title": "Of Flesh, Which Is Mostly Water, and Therefore Opaque",
|
||||
"body": "There is nothing occult in this and it is no less remarkable for that. Bluetooth advertises in the band about two and four tenths of a gigahertz; water absorbs that band strongly; and a person is largely water. This is the identical physics by which a microwave oven cooks a supper, and the identical reason that your connection worsens when somebody stands between you and the router. So when a body crosses the path between the receiver and a beacon, the received strength genuinely falls — some three to ten decibels according to the geometry — while a still link wanders only two to four from multipath and receiver noise alone. Six decibels of departure is therefore taken as a disturbance: above the idle murmur, within what a real body truly causes. The instrument reports that the field changed. It never says the change was a presence. That interpretation lives upstairs, in the fiction; down here the measurement stays honest.",
|
||||
"plain": "BLE operates in the 2.4 GHz ISM band, which water absorbs strongly — the same physics as a microwave oven, and why wifi degrades when someone stands in the path. A human body crossing a BLE path attenuates it by roughly 3–10 dB, while an idle link wanders only ±2–4 dB, so the disturbance threshold is 6 dB with an 8-second baseline time constant. The module only reports that signal strength deviated; it never claims that means a presence.",
|
||||
"source": "frontend/src/lib/bluetooth.ts — DISTURBANCE_DB"
|
||||
},
|
||||
"iron": {
|
||||
"title": "Of Iron, and of the Field the Earth Never Stops Making",
|
||||
"body": "The famous meters of the ghost-hunting trade are magnetometers, and the spikes they are celebrated for are truly caused by mains wiring, by motors, by the magnets in speakers and by moving ferrous mass. This engine reads the same quantity, in microtesla, as the root of the sum of the squares of its three axes. But the Earth's own field, some twenty-five to sixty-five microtesla according to latitude, is precisely the thing that must not be reported, for it is present everywhere and means nothing; it is what the rolling memory of the preceding article quietly subtracts. What remains is departure from wherever you happen to be standing. Three microtesla is required, the sensor's own noise being about half to one, and household wiring at close quarters producing between one and ten. The field is sampled ten times in the second — ample for a thing that changes at the speed of a walking human, and far kinder to a battery than the sixty the interface would gladly give.",
|
||||
"plain": "The magnetometer reads the real magnetic field in microtesla, sqrt(x²+y²+z²). Earth's background field is 25–65 µT depending on latitude and is exactly what the rolling baseline subtracts, so only local deviation is reported. The spike threshold is 3 µT — several times the ~0.5–1 µT noise of a phone magnetometer, and inside the 1–10 µT range that mains wiring produces at close range. Sampled at 10 Hz to save battery.",
|
||||
"source": "frontend/src/lib/magnetometer.ts — SPIKE_UT, SAMPLE_HZ"
|
||||
},
|
||||
"throat": {
|
||||
"title": "Of the Throat, and Why the Dead Do Not All Sound Alike",
|
||||
"body": "Were pitch, pace, breath and reverberation each drawn at random and independently, one would obtain not persons but a uniform smear of oddity — the same synthesiser in eight hats. Real voices covary: an old man is low and slow and breathy at once; a child is high and quick and, most unsettlingly, clean. A throat is therefore drawn whole, from eight archetypes, and only then jittered. The drowned are pitched down, dragged slow, and drenched in reverberation to half. The burned are the noisiest, scarcely holding a pitch at all. The distant are not damaged but merely far, quiet and even and steeped in space. And when the séance is held in Spanish the archetype's roster of models is set aside in favour of a voice that pronounces the language correctly, the shaping alone carrying the character — better a true accent with an archetype's bearing than an English throat mangling Spanish words.",
|
||||
"plain": "Voice parameters are drawn as one coherent bundle from eight archetypes (elder man, elder woman, young man, young woman, child, drowned, burned, distant), each with its own pitch, rate, noise and echo ranges, then jittered — because randomising each parameter independently produces random effects, not distinct people. In Spanish the archetype's model list is ignored and a Spanish Piper voice is used instead, with the archetype's shaping still applied.",
|
||||
"source": "backend/app/entities.py — VOICE_ARCHETYPES, roll_voice"
|
||||
},
|
||||
"utterance": {
|
||||
"title": "Of Unbidden Speech, and of Sight",
|
||||
"body": "When a presence speaks unasked, it is not answering you, and this is arranged with some care. The prompt put to the model contains no word of yours whatsoever — its only stimulus is the measured state of the room — so there is nothing there to reply to. And the sampling seed is taken from the very physical entropy harvested in that room, being the first eight bytes of the mixed digest, reduced beneath the sign bit that the model server requires. The seed fixes the path of token selection; therefore the room genuinely selects the words. This is not a metaphor. Alter the noise and the speech alters; no two rooms produce the same utterance. The decoding is left deliberately hot, a tight and well-behaved decode being precisely the failure we fear here — this must sound like something surfacing, not something composed. And when you offer the camera, the model is vision-capable and genuinely looks: it speaks about the room that is actually in front of it, not one it invented.",
|
||||
"plain": "For unprompted utterances the prompt contains no user input at all — only measured sensor readings — so the model is generating from the room, not replying. The Ollama `seed` option is derived from the mixed physical entropy (first 8 bytes of veil_seed, mod 2^63), and since the seed fixes token sampling, different room noise genuinely produces different words. Sampling is deliberately hot (temperature 1.15, top_k 100). Scrying sends the actual camera frame to a vision-capable local model, so the description is of your real room.",
|
||||
"source": "backend/app/llm/service.py — manifest, scry"
|
||||
},
|
||||
"limits": {
|
||||
"title": "Of What This Instrument Cannot Do",
|
||||
"body": "A doctrine that will not name its own boundaries is a doctrine to be distrusted, so here are ours, plainly. Upon Apple's handheld devices there is no Web Bluetooth, no WebUSB and no magnetometer — the company ships none of these interfaces, and every browser upon that platform is the same engine beneath a different coat, so no alternative browser rescues you; the séance falls back to the motion sensors, which measure movement and not magnetism, and the instrument says so rather than pretending. The radio requires a Chromium vessel and a secure origin. The firmware written for the paired sensor node has never once been flashed to physical hardware nor compiled by its true toolchain; it is reasoned, not proven, and the repository says as much in its own words. The map of haunted ground is assembled from two free public services that may be slow or silent, in which case you receive a quieter map rather than an error. Solar midnight ignores the equation of time and may be a quarter hour out; the moon is a mean-synodic approximation, exact enough for eight named phases and for nothing that would steer a ship. And the final boundary, stated without ornament: none of this is evidence of the dead. The measurements are real. The spirits are fiction.",
|
||||
"plain": "Hard limits: iOS has no Web Bluetooth, no WebUSB and no Magnetometer API — Apple doesn't ship them and every iOS browser is WebKit underneath, so no third-party browser helps; those modes fall back to motion sensors, which measure movement rather than magnetism. WebUSB (the SDR) needs Chromium and a secure context. The ESP32 firmware has never been flashed to real hardware — it is structurally reasoned, not verified. Haunted-place lookups hit free public Wikipedia and Overpass endpoints on an 8-second timeout and degrade to an empty list if they fail. Solar midnight ignores the equation of time (up to ~16 minutes error) and the moon calculation is a mean-synodic approximation. And the obvious one: none of this is evidence of an afterlife. The sensors are real; the spirits are fiction.",
|
||||
"source": "frontend/src/lib/bluetooth.ts · magnetometer.ts · sdr.ts · firmware/esp32p4-sensor-node/README.md · backend/app/haunts.py"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user