Dorabella Decipher

seven phases · run each on its own · the last one runs continuously

Key

what this isThe 24-letter alphabet, shown twice: as Elgar’s clock face (radius = arc count, angle = orientation) and as the snowflake grid you can type into. They are the same object — edit either and both update.

Locks. Type letters you believe you know, press Lock filled, and the solver holds them fixed while it searches everything else. That is how you feed in a crib. Locked cells glow on the dial. Locking every symbol leaves nothing to solve — the tool says so rather than silently doing nothing.

Glyph convention

why this existsA semicircular arc has two features that could carry its direction name: the apex (the tip of the cup) or the opening (the gap). The manuscript never says which, and transcribers legitimately differ — some anchor a quarter-turn off either one. So it is a setting, not a constant.

Does it change the answer? No. Every convention is a global relabelling of the 24 names, and all 16 offset×mirror combinations give bit-identical χ², mirrored pairs, index of coincidence and entropy — asserted in core.test.js. Its real job is letting you hold the drawn legend against the manuscript and confirm you transcribed the glyphs you meant.
Every convention is a global relabelling, so the statistics are provably identical (core.test.js asserts it). Its job is letting you match the drawn glyphs to the manuscript.

Transform settings

the cipher itselfHow the key moves while enciphering. Phase 3 undoes exactly this.

Reading order — which glyph was enciphered first. Not necessarily the order they are written: right-to-left, alternating lines, columns and spiral are all offered.
Advance the key — when it turns. Never (a plain substitution), on a fixed clock, or irregularly, driven by the text itself.
Step / direction — how far it turns, in 45° units.
Reflect — mirror the key across an axis before turning.
Ring op — permute the arc counts. Rotation always preserves the ring, so this is the only operation that can break that.

Changing anything here marks phases 3–5 stale (amber): their output no longer matches these settings.

1 Transcribe

manuscript → machine-readableEach glyph becomes arcs + direction: 2se is a two-arc symbol facing south-east. Three readings ship with the tool:

primary — the raw first-pass transcription.
resolved — nine glyphs were flagged as ambiguous; this picks, for each, the variant that best fits a 1:1 substitution. Validated against a published reading at 82/87 with zero letter collisions, p < 5×10⁻⁵. The default.
corrected — adds five further re-reads inferred from that published solution. Circular: do not use it to test that solution.

The legend shows all 24 glyphs as currently drawn. If the shapes look wrong against your manuscript, change the glyph convention — not the transcription.

2 Sequence

put the glyphs in encipherment orderA pure reordering — no symbol changes, nothing added or lost. It matters only because the order Elgar enciphered in need not be the order the glyphs sit on the page. The output below is the same 87 symbols in their new sequence; with “as written” it is the identity and nothing moves.
—

3 Unwind the key motion

the heart of the ideaIf the key was turning as Elgar wrote, every symbol was encoded with the key in a different position. This turns each one back by however many steps the key had taken by that point — the exact inverse of the encipher side.

Read the χ². A 45° turn preserves the ring, so a per-symbol rotation forces the eight direction counts toward 87/8 ≈ 10.9 whatever the key or fill. Dorabella sits at 26.6 on 7 degrees of freedom — Monte Carlo over 40 000 simulated rotating ciphertexts puts that at p = 0.0003. A regular rotation is ruled out, and no key guess rescues it.

The irregular schedules escape that argument: advancing on a repeated symbol, an arc-count change or a mirrored pair is driven by the text, so the counts are never forced flat. Those are the live options.
—

4 Substitute

geometry → lettersLook each unwound cell up in the key grid and write its letter. The only phase that touches the alphabet; everything before it is pure geometry. A · means that symbol has no letter assigned. The glyph row underneath shows each original manuscript glyph with the letter it produced.
—

5 Score against language

is the output language?English is scored with a blended 3+4-gram model. Other languages get bigram models — the method Hauer et al. (HistoCrypt 2021) used for language identification, which ranked Latin first and English third across 380 languages.

Why calibrate. A raw score means nothing alone. The tool enciphers real English passages with random substitutions and attacks them with this same solver at the same effort, then reports where your text falls in that distribution. Comparing a solved score against unsolved English would be unfair — the solver never quite reaches the true text.

German is a full solving target, not a ranking one: a 3+4-gram model over 2.5 M letters of 19th-century prose (Goethe, Fontane, Mann, Kafka, Nietzsche), with controls drawn from a held-out 15% the model never saw.

Caveat: the remaining language corpora are ~1.7 KB of hand-written prose each. Good enough to rank candidates, not to conclude one.

6 Hunt for the key

sweep the space, solve each candidateA substitution solver absorbs any fixed relabelling of the 24 symbols — so a different grid fill, a once-off rotation, or “orientation is the letter and arcs are a modifier” are all already covered and need no test. Only reading order and scheduled key motion change what the solver sees. That is why this space is small enough to sweep at all.

Dedupe. Many different settings produce the identical unwound stream. Each is hashed and solved once — a measured 50–56% saving on the larger modes. The ≡ column counts how many settings collapsed into that row.
Two stages. Stage A solves every distinct stream cheaply; stage B re-solves only the top N at full effort. A cheap solve is a noisy but adequate filter, so you pay full price only where it can matter.

Watch the live view: the dial fills in with the best key found so far, and the spark line plots every candidate as it is solved, with a dashed marker at the worst real-English score. A genuine solution would sit near the middle of the English band, not scraping the bottom.

7 Continuous auto-solve

what makes this different from phase 6 Phase 6 sweeps once, at a fixed effort, in one language, and forgets everything when it stops. This one is built to be left running.

The space is addressed by index, not built as a list. Combination number 431,905 is decoded arithmetically, so a sweep of any size costs no memory and “resume where I stopped” is exact rather than approximate.
Survey, then refine forever. Every distinct symbol stream gets one cheap solve per language. After that the engine keeps giving candidates more effort, carrying the elite pool forward, so the answer improves the longer you leave it. It chooses by successive halving: bring the whole field to the same number of rounds, cut the bottom half, double the budget, refill the free places from the leaderboard, repeat. Every comparison is between candidates that got equal effort.
This began as a bandit rule and it fixated badly — 267 of 319 rounds on one candidate. A bandit assumes its value estimate is an unbiased mean, but “best score so far” only rises with more rounds, so the exploit term rewards whatever has already been pulled most, purely for having been pulled most. Equal budgets remove the problem instead of tuning around it.
Two languages at once. Raw scores from an English and a German model are not comparable, so nothing ever compares them. Each candidate is placed in standard deviations against its own language's controls, and those z-scores compete.

And the correction, which is the point. Test sixty thousand candidates and the best of them looks impressive by chance alone. So the headline is not the best score. It is the best score measured against this stream shuffled — same symbols, same frequencies, no linguistic order — solved at the same effort, corrected for how many candidates were tried.

Investigation

state that outlives the tab Everything before this was one-shot: set up, run, read a number, lose it. An investigation is a long argument with yourself, so this holds the whole thing — transcription, transform, key with per-cell confidence, your template, the solver's accumulated work, and what you have ruled out — and writes it to one JSON file you can reload later or send to someone.

Template

what you believe the plaintext says A crib asks "does this word fit anywhere?". A template asks the sharper question: if position 34 is D, what does that force? Because this is a substitution, one asserted letter constrains every occurrence of that symbol across all 87 positions — a four-letter guess in the right place can pin a fifth of the key.

Write . for unknown. The template is self-checking: assert two letters for one symbol, or one letter for two symbols, and it says so instead of quietly producing nonsense.

The cost number is the point. Solving with your template pinned will always score no better than solving free. If your guess is right the gap is small; if the gap is large, the guess is wrong — that is a real test, not a vibe.
—
—

Reproducibility

read this before believing anything A plaintext is worth nothing without an exact account of how it was reached. A recipe is that account, and it works at two levels.

Level 1 — deterministic replay. Ciphertext + reading order + key motion + the 24-cell key gives the plaintext by pure arithmetic. No solver, no randomness. Anyone can check it in milliseconds and must get the identical string. This is the level that makes a claim verifiable, and Verify enforces it — including re-scoring, so a quoted score cannot drift from its text. Change one cell of the key and it fails loudly.

Level 2 — search replay. Re-running the annealer from the same seed to rediscover the same key. Useful, but annealing is stochastic and depends on this exact build. A recipe that fails level 1 is not a solution, whatever it scores.

Tools

key-free instruments Three things that do not need you to guess a key first.

Crib. If you think a word appears in the message, this finds every position where it is consistent with the symbol pattern — before any solving. A repeated letter is a powerful constraint: DORABELLA has a double L, and that alone rules it out everywhere in the as-written reading.
Vowel test. Sukhotin's algorithm recovers the vowel set from adjacency structure alone. If the symbols behave like language, the vowels fall out.
Export. Hunt results and the current plaintext, as CSV or plain text.

History

everything you have triedEach phase run and each hunt is recorded with the exact reading order, key motion, glyph convention and key that produced it. Restore puts all of that back and re-runs the phases, so you can return to any earlier state without rebuilding it by hand. Memory only — browser storage is blocked on file:// origins, so use Export JSON to keep a session.
Every run is recorded with the exact settings that produced it. Restore puts those settings (and the key, if the run found one) back into the page. History lives in memory only — browser storage is blocked on file:// origins.

Log

A running trace of what the tool did and when. Hunt results, adopted candidates and restores are highlighted.