Deterministic checks with stable codes

Programmers have compilers that read code and point at the line that breaks. Asten does the same for a story’s facts, with deterministic rules, stable codes, and evidence for every mark.

Two men in blue and orange tunics swing flails over a sheaf of grain, painted in the margin of a medieval manuscript.

In short

Asten’s compiler is a deterministic rule engine written in Rust. It reads your settled facts, your timeline, and the page itself, and emits diagnostics with stable codes (CANON-E013 to E601, NAME-W001 to W004, PLOT-I001, and optional CRAFT hints) at four severities: error, warning, information, and hint. Each mark explains itself in a numbered chain and offers repairs. It runs entirely on your machine and never changes your text.

Deterministic

Same project, same marks. No model, no randomness, no “it depends on the prompt”.

Stable codes

CANON-E013 always means an attribute contradiction. Search it, discuss it, suppress it.

Four severities

Errors for confirmed against confirmed, warnings for the page against a confirmed fact, information for clashes that are only possible, hints for confusable names and optional craft notes.

Evidence attached

Every mark points at a span in a document, reads as a numbered chain (①②③), and names the statement most likely at fault.

Repairs you own

Add an event, mark the scene a memory, retire a fact, silence the mark, or keep your sentence. Bisect finds the edit that raised a mark.

Append-only history

Document operations are recorded, and named snapshots restore a revision on your own disk.

Stable block ids

Paragraphs carry identities, so a mark can follow its sentence when you edit around it.

Which rules ship today?

CodePackWhat it noticesDefault
CANON-E013ScribeTwo values for a one-valued attribute at the same story time in the same context, with no change event between themAlways on
CANON-E014 / E015ScribeAn immutable attribute (a birthplace) changed; an attribute on the wrong kind of thingAlways on
CANON-E101 / E102 / E103LifecycleActing after a settled death; appearing before birth; an item used after it was destroyedOn
CANON-E201 / E202 / E203ClocksStory time stepping backward inside a continuous run; dates that cannot all be true; an effect before its causeOn
CANON-E301AtlasA journey that does not fit the time between two scenes. Two places at one story time is marked E013.On
CANON-E401KnowledgeA character using knowledge no event has given them yetOn
CANON-E501 / E502 / E503RelationsTheir own ancestor; two of an exclusive relation at once; a parent too youngOn
CANON-E601InvariantsA rule you wrote in the invariants panel fails on the scene traceOn
NAME-W001 to W004ScribeA name not in the cast; named before being introduced; confusable names; a fact pointing at a removed entityAlways on
PLOT-I001InvariantsA setup you marked for payoff has not been paid off yetOn
CANON-E302, CANON-E602, PLOT-I002ReservedCodes the catalogue holds for later; no rule raises them yetNot raised
CRAFT-H001 / H002Diction watchFilter words such as “very” and “really”, as optional notesOff

Why rules and not an AI model?

Because a mark you can’t trust trains you to ignore all of them. Deterministic rules can be explained, tested, and argued with. They also run instantly on a laptop with no network. AI may later help propose facts, but the compiler that judges contradictions stays rule-based and inspectable. See our AI stance.

What’s under the hood?

For the curious: the engine is a set of Rust crates. A story IR holds entities, facts, events, scenes, and contexts; a block model gives every paragraph a stable id and a hash-chained history so marks follow their sentence through edits; perception reads the page with Unicode folding and dictionary matching, no model; the analyses are an event calculus, a lifecycle typestate, a temporal network, shortest routes, and a small temporal-logic checker for your own rules. Storage is SQLite. An Axum server exposes a local API on 127.0.0.1:4317 that answers only to paired clients. The interface is React and TypeScript; the Tauri desktop shell embeds the same API. More in For AI tinkerers.

About the compiler

Is the Asten compiler an AI?
No. The Asten compiler is a deterministic rule engine. It produces the same marks for the same project every time, and it runs entirely on your computer.
What do Asten’s diagnostic codes mean?
CANON-E0xx codes are attribute clashes, E1xx lifecycle, E2xx the two clocks, E3xx travel and place, E4xx knowledge, E5xx relations and genealogy, E6xx your own rules. NAME-W codes are name hygiene, PLOT-I codes are setup ledgers, and CRAFT-H codes are optional diction hints. The glossary defines the common ones.

Try the pre-alpha

Open the workbench in your browser on a sample novel, or download release 0.0.1b for Windows or Linux.