← Back to the playgroundtechnical paper · working draft

Jankrish: An Unambiguous, Order-Independent Language for Deterministic Meaning-to-Target Compilation

Mohit Mishra


Abstract

We present Jankrish, a constructed language engineered so that each word carries its own grammatical role as an in-band morphological tag, making surface word order semantically inert. This single property lets a sentence be parsed by a total, deterministic, permutation-invariant function into a canonical role-routed structure, and compiled — with no statistical model — into downstream targets (SQL, wire payloads, parse graphs, retrieval capsules, a card game's move semantics). We give (1) a formal specification of the morphology as a concatenative slot grammar, (2) a semantic model in which meaning is a role-labeled multiset invariant under reordering, (3) the deterministic segmentation-based parsing algorithm and its complexity, (4) proofs of determinism, permutation-invariance (over the flat fragment), and an identifier-soundness grounding invariant for the flagship English→SQL compiler, (5) benchmarks against the standard LLM-based text-to-SQL approach, and (6) an explicit account of what the system intentionally rejects. All claims are cross-referenced to the reference implementation and its 123-test property suite.


1. Formal grammar

1.1 Design principle

Natural languages such as English encode grammatical role positionally: the dog bit the manthe man bit the dog. Recovering "who did what to whom" therefore requires inferring structure from order and function words — an ambiguous, probabilistic task. Jankrish encodes role morphologically and in-band: every content word is a self-contained block whose affixes name its role, number, and tense. Order carries no information, so nothing is left to infer.

The language is built from three donor systems, each supplying one layer:

LayerDonorContribution
Lexical rootEnglishmeaning: cook, drive, build
InflectionSanskritnumber, tense, derivation (dhātu)
Role tagJapaneseinvariant case particles, modular stamps

The grammar tables below are the single source of truth in the implementation; the parser, encoder, and tokenizer all import them.

1.2 Alphabet and tokens

Let Σ be the alphabet (Latin letters plus the Sanskrit long vowel ā). A stream is a whitespace-delimited sequence of packets (word blocks). Each packet is classified into exactly one syntactic category. We specify each category as a concatenative (affixal) grammar; there are no intra-block separators — morphemes are juxtaposed and glued by a vowel-sandhi rule (§1.5).

1.3 Noun blocks

A noun block welds a lexical root to an optional derivational suffix, an optional number, and a mandatory role particle:

NounBlock   ::= Root Dhatu? Number? Particle ListMarker? Index?
Root        ::= Letter{≥2} | Digit+                (* a numeric literal may be one digit *)
Dhatu       ::= "asthal" | "ana" | "tr" | "ti"
Number      ::= "as" | "am" | "au" | "ās"          (* am ≡ singular alias, §6.4 *)
Genitive    ::= "asya"                              (* occupies the Number slot; *)
                                                    (* requires Particle = "no"  *)
Particle    ::= "ga" | "ni" | "de" | "wa" | "no" | "o"
ListMarker  ::= "to"
Index       ::= Digit+                             (* optional agreement co-index, §2.4 *)

Particle → role (the case system):

ParticleRoleJapanese analogue
gasubject (nominative)
oobject (accusative)
nirecipient / direction (dative)
deinstrument / means
watopic
nopossessor / genitive

Dhātu (derivation) turns a root into a role-of-thing: -tr agent/actor, -ana instrument/tool, -asthal location, -ti abstract/state.

Number: -as singular, -au dual, -ās plural; genitive stem asya.

Worked example — cooktrasga:

cook · tr · as · ga  =  cook + agent + singular + subject
                     =  "the (one) chef, as the grammatical subject"

1.4 Verb blocks

A verb block is a chain of optional modifiers around a root and a mandatory tense/person ending. Written in surface (left-to-right) order:

VerbBlock ::= Neg? Past? Root Passive? Intent? Aspect? Polite? Tense Tail? Question?
Neg       ::= "na"                 (* negation; only if the remaining root ≥ 2 chars *)
Past      ::= "a"                  (* past prefix; ONLY valid with a Past tense ending *)
Passive   ::= "rare"
Intent    ::= "nakereba" | "tai" | "eru"      (* obligation | desire | potential *)
Aspect    ::= "shita" | "te"                  (* habitual | continuous *)
Polite    ::= "mas"
Tense     ::= (see table)
Tail      ::= ClauseStamp | Connective        (* mutually exclusive slot *)
ClauseStamp ::= "tara" | "kara" | "tu"        (* conditional | causal | contrast *)
Connective  ::= "te"
Question    ::= "ka"

Tense/person endings (12). The system is triangular: the -sy- infix marks future, the a-…-at bracket marks past.

1sg2sg3sg3pl
Futuresyāmisyasisyatisyanti
Presentāmiasiatianti
Pastamasatan

Worked example — nadrivemassyāmi:

na · drive · mas · syāmi = neg + drive + polite + future-1sg
                         = "I will not drive (polite)"

1.5 Vowel sandhi

At the dhātu|number boundary a simplified Sanskrit sandhi applies: if the stem ends in a/ā and the suffix begins with a vowel a/ā/e, the stem vowel elides.

coalesce(a,b) = a[:-1]·b   if a ends in {a,ā} and b starts in {a,ā,e}
              = a·b        otherwise

Thus ana (tool) + au (dual) → anau (surface learnanau), while tr + astras (consonant-final, clean concatenation). Sandhi is the only context sensitivity in block formation, and it is confined to one boundary; the parser inverts it by enumeration (§3.2).

1.6 Closed-class lexemes

Three categories are fixed, non-decomposable lexemes matched by table lookup:

kasga (who-sg-subj), kimo (what-obj), kutra (where), kadā (when), katham (why), kena (how), kati (how-many), … (12 words).

(inside), uparini (above), adhasni (under).

ablative ātkara, comparative suffix yori, superlative prefix ichiban.

1.7 JQL — a domain grammar layered on the core

The core grammar (logs 1–8) defines no database semantics. JQL (the Jankrish Query Layer) is a controlled sublanguage built on top of it in which each SQL construct is one self-contained, scramble-safe block:

FROM t        ::= t "āswa"                (* topic block  *)
SELECT c      ::= c "o"                   (* object block *)
aggregate     ::= ("count"|"sum"|"average"|"max"|"min") "ati"
WHERE         ::= c Op v "ni"             (* fused filter *)
HAVING        ::= c Op v "hi"             (* post-aggregate filter *)
GROUP BY c    ::= "prati" c
ORDER BY c    ::= c ("vriddhi" | "hrasa") (* ASC | DESC *)
LIMIT n       ::= "sima" n
JOIN t        ::= t "asyano"              (* genitive → FK t_id *)
DISTINCT      ::= "bhinna"
subquery      ::= "upa" … "upanta" with "sub" placeholder
UNION         ::= q1 "sandhi" q2
window        ::= f "ati" + "vibhaga" c   (* RANK/ROW_NUMBER/DENSE_RANK OVER … *)
PIVOT         ::= "pivot" d "mulya"v1 "mulya"v2 …
recursive CTE ::= "shreni" n              (* WITH RECURSIVE seq(n) 1..N *)
Op            ::= "sama"(=) | "adhika"(>) | "nyuna"(<)
                 | "adhikasama"(≥) | "nyunasama"(≤) | "madhye"(IN)

Most constructs are single fused blocks, so within one flat query the tokens scramble freely and compile byte-identically (§4.2 makes this precise). Two constructs are the deliberate exception: the subquery upa … upanta is a delimited span and sandhi is a binary infix separating two operands. These are order-bearing by design — membership in the span, and which side of sandhi an operand sits on, depend on position. Permutation-invariance therefore holds over the flat fragment, not across a nesting or union boundary; §4.5 and §6.5 make this scope explicit, and lifting order-inertness to nested clauses (label-tagged subqueries) is flagged there as future work.


2. Semantic model

2.1 Meaning as a role-labeled multiset

Let a stream s tokenize to a multiset of packets ⟦s⟧ = {p₁, …, pₙ}. Define a per-packet classification function

class : Packet → (Bucket × Record)

that maps each packet to one of eleven role buckets and a structured record of its decoded tags (implemented as _classify). The buckets are:

actor/subject · object · recipient/direction · instrument/means
possessor/genitive · topic · interrogatives · spatial · comparison
floating_markers · actions

The meaning of a stream is the map from buckets to the multiset of records routed there:

M(s) : Bucket → Multiset(Record),   M(s)[b] = { r : class(pᵢ) = (b, r) }

Crucially, M(s) depends only on the multiset ⟦s⟧, never on the order of the pᵢ, because class is a pure function of a single packet and each record is appended to its bucket independently. This is the formal content of "word order does not matter." Two streams are meaning-equivalent iff M(s₁) = M(s₂).

2.2 Canonical form

To obtain a canonical representative the implementation sorts each bucket by a fixed total order on records (_sort_key over (root, token, particle, number, timeline, person)). Writing sort for this per-bucket canonicalization, the canonical parse is

D(s) = sort ∘ M(s)

D is a function into an ordered structure (a Python dict of sorted lists) and is the object the rest of the platform consumes. Since a multiset has a unique sorted representative, D(s) is a canonical form for the meaning-equivalence class of s (Proposition 4.2).

2.3 Compositional target semantics

A downstream application is a partial function ⟦·⟧_A: D → Artifact ∪ {⊥} that interprets a canonical parse in a target domain, returning (refuse) when the parse cannot be grounded. The flagship instances:

operators — topic block → FROM, object blocks → projection, verb root → aggregate, fused …ni block → selection, prati → grouping, asyano → a single equi-join on a foreign key — composed into one SELECT statement.

content word to a real schema element before emitting (§4.4).

wire message, a depth-1 semantic graph, a set of tag-matched bindings, and a combat frame, respectively.

most fully exercises the language's three distinctive properties at once. An agent emits a Jankrish instruction; the human-audited gloss reading(D(s)) and the executed action ground(D(s)) are both projections of the same D(s), so the record cannot diverge from what ran (§4.5 order-independence + one-parse provenance); the decision fingerprint is a hash over the canonical D(s), so scramble-twin instructions share it and replays are suppressed (Thm 4.3); and every term must ground or the instruction is refused (Thm 4.4, applied to actions). Entries are HMAC-signed and hash-chained; verify() re-derives the gloss and fingerprint from the stored instruction, making non-divergence machine-checkable.

is the platform's safety gate (§4.7) turned around — it consumes arbitrary SQL from an external LLM and applies the same read-only + identifier-grounding discipline as a standalone verifier, allowing a statement or refusing it with a named reason. It shares the gate's code but sits outside the Jankrish-parse pipeline.

Because D is order-independent and each ⟦·⟧_A is a deterministic function of D, every artifact is itself order-independent: scramble the input, get the identical output (Theorem 4.5).

2.4 Cross-packet binding and its uniqueness precondition

The multiset model of §2.1 is exact for role assignment but deliberately flat: because class is a function of a single packet, no relation between packets is stored in M(s). Modifier–head binding is therefore not represented directly. The language expresses it by agreement: an adjective is a noun block that mirrors its head's number and particle (the "adjective copy" rule), so the pair shares a tag signature (case, particle). Binding is then recovered downstream by grouping a bucket's records by signature — the mechanism rag_anchor uses (binding_map).

This recovery is well-defined only under a uniqueness precondition: within a role bucket, each intended head must have a distinct tag signature. When two heads collide on the same signature, the group holds several heads and several modifiers with nothing in M(s) to pair them. Concretely, "the clever chef and the busy chef" renders both heads as cooktras·ga and both adjectives as cleveras·ga, busyas·ga; the subject bucket then holds four Singular/ga records and the clever↔chef vs. busy↔chef binding is genuinely underdetermined. The original case study avoided this only because its two subject groups happened to differ in number (singular vs. dual), an accidental discriminator.

The language resolves this with an agreement index (§1.3): a co-index welded after the particle, so a modifier and its head share (case, particle, index) and two same-signature heads take different indices and stay distinct. With it, "the clever chef and the busy chef" is expressible without collision — cleverasga1 chefasga1 busyasga2 chefasga2 — and binding_map groups by the full signature including the index, recovering each binding uniquely. When the index is omitted and a signature would bind the same head twice, binding_map refuses (naming the index as the fix) rather than silently merge — the same ground-or-refuse stance the rest of the system takes. Signature-uniqueness thus becomes something the author can always establish (by indexing) rather than a silent precondition; Proposition 4.6 states the guarantee and its ground-or-refuse behaviour precisely.

2.5 Lexicon independence and localization

The classification class treats a root as an opaque string: it strips the welded affixes and returns whatever remains, never inspecting the root's language (the reference implementation already grounds non-word roots — identifiers, location codes, bare numerals). Consequently every property proved here — determinism, permutation invariance (Thm 4.3), identifier soundness (Thm 4.4), and the downstream signing/chaining/non-divergence of the action ledger — is independent of the lexicon: the role-marking machinery is instantiable with any root vocabulary while the guarantees are unchanged. The reusable object is the grammatical protocol; the vocabulary is configuration.

A useful consequence is localization outside the trust boundary. The human-audited gloss is a pure function of the parse (§2.3), which the verifier re-derives; making the authoritative signature cover the canonical parse rather than the gloss (the implementation exposes both a full-entry signature and a parse-only content signature) yields one signed record with many language-renderings, none of which can alter it.

This is a property of the machinery, and it comes with three honest preconditions before a lexicon swap is more than mechanical:

  1. Unicode-correct segmentation. The ≥2-character root floor (§1.3) is a

code-point count, so a single-glyph CJK root is wrongly rejected, and scripts with combining marks (e.g. Devanagari) need a grapheme count. A root whose orthography ends in a reserved affix (atlas ends in the number affix -as) is mis-segmented — a pre-existing hazard the ASCII demo vocabulary merely avoids. These are fixable but must be fixed, not assumed.

  1. Cross-language equivalence needs a concept layer, and is often unwanted.

Because the root is part of the canonical parse, differently-lexed instructions hash differently. Unifying them across languages requires mapping roots to shared concept identifiers — tractable only for a bounded action vocabulary, and for audit frequently a misfeature: a refund in one jurisdiction under one policy is not the same action as another, and collapsing their fingerprints destroys information a regulator wants.

  1. Keep any concept map outside the signed artifact. A hand-maintained

ontology inside the trust boundary makes every mapping decision auditor- challengeable; it should unify renderings, not fingerprints.

So the shippable claim is narrow and strong — the accountability guarantee is independent of the vocabulary; localization is a gloss outside the trust boundary — and the multilingual vocabulary itself is a scoped direction, not a demonstrated capability.


3. The deterministic parsing algorithm

3.1 Overview

Parsing is segmentation-based: rather than one large regular expression, each block is decoded by peeling affixes from its edges using fixed longest-match tables. This design choice fixes two real bugs in the original prototype (a past prefix that never fired because it expected a literal hyphen; and whole post-log-2 subsystems that were unhandled) —.

The top-level parse:

parse(s, canonical=True):
    db ← empty buckets
    for packet in normalize_punctuation(s).split():
        classify(packet, db)               # exactly one bucket gets one record
    if canonical:
        for bucket in db: bucket.sort(_sort_key)
    return db

3.2 Classification and segmentation

classify tries categories in a fixed priority: (1) fixed question words, (2) spatial words, (3) comparative/superlative markers, (4) verb segmentation, (5) noun segmentation, (6) otherwise a floating marker. Ordering verb before noun is sound because a verb block ends in a tense/stamp/-ka and never in a role particle, so the two segmenters have disjoint acceptance on well-formed blocks.

Verb segmentation (segment_verb) peels right-to-left — ka → stamp/tetense (required)mas → aspect → intent → rare — then left-to-right prefixes na, then a (the past prefix is stripped only when the tense ending is Past, which is exactly what prevents eating the leading a of a present verb like askati). If no tense ending is found, the token is not a verb and any speculative peel is discarded (returns None).

Noun segmentation (segment_noun): first find the trailing role particle (longest-match over PARTICLE_MATCH_ORDER, so multi-char ni/de/no beat single-char o). Then jointly peel the optional dhātu and optional number: because sandhi couples the two, the algorithm enumerates every (dhātu, number) pair, reconstructs the fused tail via coalesce, and keeps the longest valid tail leaving a root of ≥2 characters — or a single-digit numeric literal, e.g. an amount of 5 (with the constraint that the genitive stem asya is only well-formed under particle no). This joint search inverts sandhi exactly without backtracking ambiguity, because "longest valid tail" is a well-defined maximum.

3.3 Complexity

Let n be the number of packets and L the maximum block length. Verb segmentation does a bounded number of suffix/prefix tests (constant table sizes), each O(L); noun segmentation enumerates |Dhātu|·|Number| = 5·6 = 30 fixed combinations, each an O(L) suffix test. Classification is therefore O(L) per packet, and

parse (non-canonical)  =  O(n · L)
parse (canonical)      =  O(n · L + n log n)     (per-bucket sort)

with no backtracking, no dynamic programming, and no model inference. There is no randomness and no wall-clock dependence anywhere in the path ( makes even scramble seeded), which is what makes the function reproducible (§4.1).


4. Correctness properties and proofs

We state the properties the system is built to guarantee and give proof sketches against the code invariants. These are rigorous arguments about a deterministic program, empirically corroborated by the property tests in (123 passing, pytest tests/ -q); they are not machine-checked formal proofs, and §6 is explicit about the boundary.

4.1 Proposition (Totality and determinism)

parse: Σ* → D is a total function: every input yields exactly one output, and identical inputs always yield identical outputs.

Proof. parse performs a single pass over packets; classify assigns each packet to exactly one bucket (the six cases are tried in order and the sixth, floating marker, is a catch-all, so classification never fails and never double-counts). Every table lookup uses a fixed longest-first match order (*_MATCH_ORDER), so ties are resolved deterministically. No branch consults a random source or the clock. Hence the output is a single, input-determined value. ∎

4.2 Proposition (Canonical form of meaning)

sort is injective on finite multisets, so D is a canonical form for meaning-equivalence: D(s₁) = D(s₂) ⟺ M(s₁) = M(s₂). In particular ⟦s₁⟧ = ⟦s₂⟧ (equal packet multisets) ⟹ D(s₁) = D(s₂).

Proof. M(s) routes each packet's record into a bucket by a function of that packet alone; thus M(s) is determined by the multiset ⟦s⟧, and equal multisets give equal per-bucket record multisets. sort maps a finite multiset to its unique ascending sequence under the total order _sort_key, so it is injective; hence D = sort ∘ M is equal iff M is equal. ∎

Remark (one-way at the surface). The reverse implication D(s₁) = D(s₂) ⟹ ⟦s₁⟧ = ⟦s₂⟧ does not hold, and by design: class is deliberately non-injective, because the parser normalises the -am/-as singular alias (§6.4) to one record. Two streams differing only by that surface variant have equal meaning M but distinct packet multisets. This is normalisation, not a defect — it is why D is a canonical form rather than a mere re-encoding.

4.3 Theorem (Permutation invariance / order-independence)

For any stream s and any permutation π of its packets, D(π(s)) = D(s).

Proof. Permuting packets does not change the multiset ⟦s⟧; apply Proposition 4.2. ∎

This is the machine-checkable form of the language's central claim. It is exercised directly: the parser test scrambles a stream with the seeded scramble and asserts the canonical parse is unchanged; the interactive playground's Scramble & verify control does the same live; and each application ships a scramble_invariant predicate checked in its eval suite.

4.4 Theorem (Identifier-soundness grounding invariant, English→SQL)

Let a schema be 𝒮 = (Tables, Columns, FKs, Values). If SchemaLinker.link returns SQL q (rather than raising EncodeError), then every table, column, and literal-value identifier occurring in q is an element of 𝒮.

Proof (sketch). The linker emits an identifier only after binding it to a schema element: the table must be identified (else "no table identified"); each projected/filtered column must resolve uniquely in scope (else "column … not uniquely in scope"); each filter value must ground via the value index (else "value … not uniquely groundable"); a join is only formed on a declared foreign key (else "two tables with no direct foreign key"). Any content word that remains unbound after this pass triggers "ungrounded word(s): …". Thus emission is reached only in the state where the bound identifier set ⊆ 𝒮; the SQL is assembled solely from those bound identifiers. ∎

Corollary (Ground-or-refuse totality). For every English input the linker either returns fully-grounded SQL or raises EncodeError; there is no third outcome, and in particular it never returns SQL containing an invented identifier. The same discipline holds for pure JQL compilation, where compile_text raises CompileError on any out-of-grammar token rather than guess.

Scope — what is proved vs. what is measured. Theorem 4.4 establishes identifier soundness: the SQL references only real schema elements. It does not establish semantic correctness — that the query has the intended join direction, aggregate, and filter polarity. These are distinct failure modes, and the second is the more insidious one: a hallucinated column raises a database error and is self-announcing, whereas a well-formed query with the wrong join returns a plausible number that no one flags. Identifier soundness is what the grounding discipline proves; semantic correctness on the covered fragment is what §5.3 measures (20/20 emitted answers correct, 0 silent-wrong, on the 30-table pressure suite). We keep the two claims separate throughout and never present the empirical result as a theorem.

4.5 Theorem (Artifact order-independence, for applications that are functions of D)

For every application A whose interpretation ⟦·⟧_A is a function of D(s) alone, and every permutation π: ⟦D(π(s))⟧_A = ⟦D(s)⟧_A.

Proof. By Theorem 4.3, D(π(s)) = D(s); ⟦·⟧_A is a function of D. ∎

Scope (the hypothesis is real, not decorative). The theorem holds exactly for applications that consume the canonical parse D, which is every one of them except two JQL constructs: the subquery span upa … upanta and the union infix sandhi are resolved from the token sequence (the compiler locates the delimiters and the infix by position), so for a query using them the compiler is a function of the token order, not of D, and this theorem does not apply across that boundary. Everything inside each flat sub-query remains order-inert; only the nesting/union layer is order-bearing. Making that layer order-inert too — by tagging a subquery with a label that binds regardless of position, the same trick the language uses for roles — would restore an unconditional theorem and is the most interesting open extension (§6.5).

4.6 Proposition (Binding well-definedness, with the agreement index)

Fix a role bucket b of D(s), where the binding signature is (case, particle, index) and index may be (absent). (i) If every intended head in b has a distinct signature, binding_map recovers each modifier→head binding uniquely. (ii) The agreement index makes this achievable for any scene: co-indexing each head with its modifiers gives every head a distinct signature. (iii) If a signature nonetheless binds the same head twice, binding_map raises Refuse rather than return an underdetermined map.

Proof. binding_map partitions b by full signature. Under (i) each part holds exactly one head and its agreeing modifiers, so the head is the unique non-modifier element and every modifier binds to it. For (ii), distinct indices give distinct signatures by construction, so any two heads can be separated. For (iii), a repeated root within one part is a head that appears twice indistinguishably; the pairing would not be a function of D(s) (§2.4), so the implementation refuses, naming the index as the remedy. ∎

The index is shipped in the grammar, parser, and encoder, and binding_map implements the refusal; §6.5 records the one part that remains genuinely undecidable (distinct-root same-signature heads with no index), which the author resolves by indexing.

4.7 System-level safety at the LLM boundary

When a query is refused and routed to the optional LLM fallback, the model's SQL is not trusted. Two independent, deterministic gates stand between the model and the database, and a write must defeat both:

  1. String gate_read_only

requires the statement to open as SELECT/WITH, forbids statement stacking (any interior ;), and rejects any write/DDL keyword matched at a word boundary — so a write cannot hide by hugging a paren in a data-modifying CTE (WITH x AS (DELETE …)) or behind a comment, the failure modes a prefix/space-padded check misses.

  1. Engine gateverify_sql

prepares the statement against the real schema under PRAGMA query_only=ON, so the database rejects both hallucinated identifiers and any write before execution, flagging the answer confirmed=False. Execution of the returned SQL is itself performed on a query_only connection, closing the gap between "verified" and "run". (PRAGMA query_only=ON is SQLite-specific; on PostgreSQL/MySQL the engine gate is the equivalent primitive — a READ ONLY transaction or a read-only role — so the invariant is engine-portable even though the pragma name is not.)

Combined with Theorem 4.4, the system invariant is: no SQL that references a non-existent identifier, and no statement that writes, ever reaches — or survives — execution, whether it came from the deterministic path or the model tail. This is the "SAFE rate" the benchmarks measure.


5. Benchmarks

All numbers are produced by the reference implementation and are reproducible via the noted endpoint/script. The core engine, all applications, and the 123 tests require no ML dependencies.

5.1 Determinism vs. the standard approach

The mainstream way to turn language into SQL is to prompt an LLM. The following compares the properties that matter in production analytics:

PropertyLLM text-to-SQLJankrish (deterministic path)
Same input → same outputnear-deterministic at temp 0, not guaranteedprovably one parse ⇒ one SQL
Hallucinated identifierspossibleimpossible by construction (Thm 4.4)
Wrong-but-fluent answerssilentrefused on the uncovered tail (ground-or-refuse)
Latency10²–10³ ms + network~0.03 ms, pure Python
Marginal costper-token billing$0
Auditabilityopaque weightsevery rule in, inspectable
Data egressships to model APInone (on-prem)

Two honesty notes on this table. First, temperature-0 decoding is near deterministic in practice, so the real distinction is provable determinism plus auditability, not "the LLM is random" — that is the stronger and more defensible claim. Second, the "impossible by construction" cell is scoped to identifier hallucination (Thm 4.4); wrong-join / wrong-aggregate correctness on the covered fragment is an empirical result (§5.3), not a proof.

5.2 Flagship compiler KPIs (GET /benchmark)

KPIResultHonest reading
Compile + SQLite execution100%a regression guard, not an accuracy result: on the inputs the grammar covers, compilation is by construction executable — the number exists to catch regressions, and is close to tautological on a self-defined suite
Round-trip latency~0.03 msparse + compile, no model in the path
Query-grammar coverage (GET /coverage)87.5% (21/24)the 3 refused (lateral join, full-text, MERGE) route to fallback

5.3 The honest number — a realistic 30-table schema (python bench/pressure_test.py)

A toy schema flatters any encoder; a Spider-style schema with ambiguous shared columns exposes the truth. This is the experiment that motivated the grounded linker:

MetricNaive encoderSchema-grounded linker
SAFE rate (correct or correctly-deferred)50%100%
Silent-wrong answers14 / 280
Correct answers1220
Coverage attempted93% ⚠️71% (honest)

The naive encoder attempts more but is confidently wrong half the time; the grounded linker refuses what it cannot ground, so coverage is lower but every emitted answer is correct — the trustworthy operating point, and a direct empirical instance of Theorem 4.4.

5.4 Token footprint — real GPT-2 tokenizer ()

Tokenized corpusTokensvs. English
English (stock GPT-2)25,334
Jankrish (stock GPT-2)36,810+45.3% (inflation)
Jankrish (GPT-2 + 104 fused tokens)12,000−52.6%

Adding 104 vocabulary items flips a +45% penalty into a −53% saving. Two caveats. First, this only helps self-hosted models — you cannot change a frontier API's tokenizer (§6.5). Second, the baseline is stock-GPT-2 English; the strictly controlled comparison would grant English 104 domain-specific merges too. We expect Jankrish still to win (its savings come from welding multi-token roles into single blocks, a structural gain the vocabulary only cashes out), but the honest headline is "−52.6% with a matched vocabulary budget on the Jankrish side," and the controlled-baseline run is future work.

5.5 Per-application SAFE reports (GET /apps/{name}/eval)

Every application inherits the same SAFE-rate harness; all score 100% SAFE, 0 silent-wrong on their eval suites.

ApplicationHeadline result
text_to_sql (JUST)100% SAFE, 0 silent-wrong on the 30-table schema
serialize−54.7% payload bytes vs JSON; scramble-safe decode
star_graphparse depth 1 (vs ~7 for the English AST); O(1) role routing
rag_anchormodifier→noun binding invariant under scrambling; 0 drift — same-signature heads separated by an agreement index, ambiguous collisions refused (§2.4)
syntax_clash24 word-orders → 0 meaning drift; ~0.006 ms/resolve
sql_guardrail5/5 unsafe SQL denied, 0 silent-allow; verification is prepare-only (0 statements executed)
agent_ledger100% grounding SAFE; scramble twins → identical decision fingerprint (replay-suppressed); a tampered audit line is detected on the exact field (provable non-divergence)

The syntax_clash figure is a small, exhaustive instance of Theorem 4.3: for each answerable sentence, all 3! = 6 permutations of its tokens are resolved and yield the identical reading, with illegal proclamations refused.

Baseline caveat for serialize: JSON is a lenient baseline (it stores field names as repeated strings). Against a compact binary format — MessagePack or CBOR — the byte margin narrows and is not the interesting claim; the durable properties are in-band structure (no out-of-band punctuation to lose) and order-independent, partial-loss-tolerant decode, which schemaless binary formats do not provide. The honest framing is "structurally robust and smaller than JSON," not "smallest possible encoding."


6. Limitations and intentionally rejected cases

Jankrish trades coverage for safety on purpose. The following are not bugs; they are inputs the system is designed to refuse rather than guess. Every refusal carries a machine-readable reason that names exactly what is missing.

6.1 Shapes the English→SQL linker refuses (EncodeError)

From:

not supported)"`).

("column … not uniquely in scope").

"revenue" — any content word that does not ground to a real column, filter, or aggregate → "ungrounded word(s)". A named/derived-metric semantic layer can promote such a term to grounded by one line of config; until then it is refused, not approximated.

6.2 Constructs the JQL compiler rejects (CompileError)

From: an aggregate with no measure column, an unsupported action root, a malformed/unclosed subquery span, a HAVING without an aggregate, a window/pivot missing its required parts, and any out-of-grammar token.

6.3 Deliberately out of scope

analytics, and are intentionally excluded (they account for the difference between 87.5% coverage and 100%).

6.4 Handled morphological ambiguity

The source logs use both -as and -am for the singular object; the parser accepts -am as a singular alias while the builder always emits canonical -as. This is safe because a noun is identified by its trailing role particle, so the singular -am can never be confused with the verb 1sg-past ending -am (which occupies a different slot and never precedes a particle). This is a designed disambiguation, not an accident.

6.5 Boundaries of the claims

share a (case, particle) signature — "the clever chef and the busy chef", both cooktras·ga — would collide if binding were signature-only. This is now handled by the agreement index (shipped in grammar/parser/encoder): index each head and its modifiers (chefasga1/cleverasga1 vs chefasga2/busyasga2) and the bindings are unique. binding_map groups by the full signature and refuses an unindexed scene that would bind the same head twice, naming the index as the fix — the ground-or-refuse resolution of the old hole. The one residue that stays undecidable is distinct-root same-signature heads with no index (chef and waiter, both ·ga, no index): the two roots differ, so nothing flags them, yet a modifier could attach to either. This is deliberately not auto-refused (it would reject legitimate multi-modifier phrases, since a modifier and its head legitimately share a signature); the author separates them by indexing. In short: the mechanism to express any scene unambiguously now exists, the sharpest ambiguity (a repeated head) is refused, and the remaining gap is an authoring choice rather than a silent-wrong.

span upa … upanta and the union infix sandhi are order-bearing by design — the compiler resolves them from token position — so permutation-invariance does not extend across a nesting or union boundary. The most interesting open extension is to lift the principle one level up: give a subquery a positional- independent label (the same welding trick the language uses for roles) so nested clauses bind by tag rather than by delimiter position, restoring an unconditional invariance theorem. "We lift order-inertness from words to clauses" would be a stronger result than the flat case alone.

evaluation sets written for this project; §5.3 is "Spider-style," not Spider. This is adequate for a reference-implementation report but not for an external claim of competitiveness. A standard-benchmark run (Spider / BIRD dev) is the clear next step; we expect low coverage at zero silent-wrong — e.g. answering a minority of Spider dev with no confidently-wrong answers, versus LLM baselines at high execution accuracy with unquantified silent-wrong — which is a distinct and, we argue, valuable operating point rather than a head-to-head accuracy win.

frontier API's fixed tokenizer inflates (+45%, §5.4), and the −52.6% figure is against an unextended English baseline (§5.4).

schema is ~71% coverage at 100% correctness — "answer the bounded majority, defer the tail," not "answer anything."

backed by a 123-test property suite (including scramble-invariance and ground-or-refuse assertions), not by a proof assistant. Permutation-invariance (Thm 4.3) and the grounding invariant (Thm 4.4) are the two properties most heavily exercised.

(§5.5) is demonstrated on single-clause, transaction-style streams; deeply nested natural discourse still has structure. Jankrish flattens the role-routing case that dominates machine-to-machine payloads, which is the case it targets.

6.6 Design philosophy

The invariant that governs every extension: coverage rises only when a pattern fully grounds; everything else defers — and silent-wrong stays at zero. A system that is sometimes-wrong-but-broad is, for audited analytics, worse than one that is narrow-but-honest, because the reader of a board deck cannot tell which 5% is the lie. Jankrish makes "I don't know" a first-class, machine-checkable output.


7. Related work and positioning

Jankrish sits at the intersection of three older lines of work; the contribution is their combination, not any single ingredient.

Non-configurational natural languages. The closest analogue of all is a natural phenomenon: non-configurational languages, where rich case marking permits substantially free constituent order because grammatical role is carried morphologically rather than positionally. Warlpiri is the canonical case (Hale 1983), alongside Latin, Sanskrit, Finnish, and Russian. Jankrish is, in effect, an engineered, maximally non-configurational language: it takes the case-marking strategy those languages use partially (with residual positional defaults and agreement complications) and makes it total and exceptionless — every role is marked, every marker is fused into the word, and there is no positional fallback. The honest framing is not "order-inertness is novel" but "natural languages approach it asymptotically; Jankrish completes it," which is precisely what licenses an unconditional permutation-invariance theorem (Thm 4.3) rather than a property of well-marked sentences.

Unambiguous constructed languages — Loglan and Lojban. The nearest conlang prior art is Lojban (and its predecessor Loglan), engineered for syntactic unambiguity with a machine-parseable formal grammar. Importantly, Lojban already supports order-inert argument marking: its FA cmavo (fa fe fi fo fu) tag a sumti with its explicit place number (x1…x5), so a fully FA-tagged bridi's arguments may be written in any order and denote the same relation. (The conversion operators se te ve xe are a different mechanism and not the relevant comparison.) The delta is therefore narrower but genuine, and two-part: in Lojban place tagging is optional — untagged sumti fall back to positional defaults, so order carries information by default — and the tags are separate words. In Jankrish role marking is mandatory and morphologically fused into the content word, so there is no positional-fallback mode at all; that totality is what turns "invariance holds for well-tagged sentences" into an unconditional theorem over the whole language. Jankrish is also not a general human-language project: it is a substrate for compilation to domain targets under a ground-or-refuse gate. (FA-cmavo semantics are stated from the standard reference, Cowan, The Complete Lojban Language*; a reader should verify the place-structure chapter before relying on the comparison.)*

Controlled natural languages (CNLs). Systems such as Attempto Controlled English (ACE) restrict English to a subset with a deterministic mapping to logic. Jankrish shares the "restrict the language to make interpretation a function" philosophy, but differs in mechanism: a CNL keeps English's positional syntax and constrains which sentences are legal, whereas Jankrish changes the word forms so that order stops carrying information at all.

Natural-language interfaces to databases (NLIDB). "Language → database query" is a 50-year-old programme — LUNAR, CHAT-80, and the modern self-serve BI generation (Snowflake Cortex Analyst, Databricks Genie, Vanna.ai). Jankrish's text-to-SQL is one deterministic point in that lineage; its specific new move is the ground-or-refuse contract with a proved identifier-soundness invariant, positioned as the safe front-half of a hybrid router rather than an end-to-end NL-to-SQL solver.

Semantic layers. The grounding step — binding a business term to a concrete column/metric or refusing — is essentially what commercial semantic layers (LookML, dbt metrics, Cube) do by hand-authored config. Jankrish's contribution relative to these is to make grounding a language-level, checkable operation whose failure is an explicit, reasoned refusal, and to reuse the same discipline across multiple targets (SQL, wire, graph, retrieval) rather than SQL alone.

Summary of the delta. Non-configurational languages make order-inertness partial; Lojban makes it optional (via FA tags); CNLs constrain English while keeping it positional; NLIDB and semantic layers map language to queries, usually without a safety guarantee. Jankrish's specific claim is the conjunction: total, mandatory, morphological order-inertness (an unconditional permutation- invariance theorem over the flat fragment) plus a compile-to-many-targets platform plus a ground-or-refuse safety invariant. Each piece has precedent; the combination, at that totality, is the point.