Prose map for campaign weksa-lowering, written by Imagination for the Eureka-area Self (session self-2026-10-29-eureka). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
11 KiB
Map: interlingua lowering (campaign weksa-lowering)
Prose map for the campaign whose target is
interlingua-lowering.md. Rulings, questions,
follow-ups and cut specs live in the Eureka mind under weksa-lowering:; this
page is the model page and the cut sequence, and cites them by label. Written
by Imagination for the Eureka-area Self, 2026-10-29.
The design in one paragraph
The interlingua spec has two layers. The schema is Rust types: packet
families, node ids, role slots, value kinds. It changes rarely and by commit.
The inventory is data in CultCache: the concepts, frames, roles, relation
types, speech acts and nuance features (hedge, certainty, warmth, irony and
whatever the loop finds missing) that the schema's slots name by id. Every
open slot in a packet is an inventory id, never free text, so a packet carries
no target-language wording (no-surface-leak). The golf loop improves the spec
mostly by growing and refining the inventory, which is fast; schema changes are
the slow path. Concepts are open-class and grow forever; the other families are
closed-class, and convergence is measured on them
(weksa-lowering:ruling:convergence-test). This split is
weksa-lowering:ruling:spec-is-schema-plus-inventory.
Model page
Every persistent kind, what names it, its life, and who decides. "Derived" means no store holds it and nothing writes it.
| Kind | What names it | Lifecycle | Who decides |
|---|---|---|---|
| Packet | Key packet:<item-id>:r<inventory-rev>:<encoder-digest>; CultCache type weksa.interlingua_packet, carrying schema_version and inventory_rev |
Minted by an encoder for one corpus item under one spec version; immutable; a new spec version means a new packet, never an edit. Admitted only through the validator | The encoder writes; the validator refuses malformed packets at the door (typed-packet); nothing else writes packets |
| Schema version | weksa.interlingua_packet.v<N> constant in crates/weksa; published JSON Schema at schemas/cultnet/ |
Bumped by a commit that changes the Rust types; the published schema is regenerated in the same commit and a test fails on drift | A cut (Hands, under a spec); never the loop |
| Inventory entry | Key <family>:<n> (families: concept, frame, role, relation, speech_act, feature); type weksa.inventory_entry, with gloss, value kind, introduced_rev, optional retired_rev |
Added or retired by an inventory revision; never edited in place (a changed meaning is a retire plus an add); a retired id still resolves for packets of earlier revisions | The loop's accepted rounds; Self on merge to main |
| Inventory revision | Key rev:<n>, type weksa.inventory_revision, with parent, change list and frozen |
Appended per accepted round; exactly one revision is ever marked frozen, by the convergence test | The loop's accept rule appends; the convergence test freezes; Self records the freeze as a ruling |
| Target profile | Locale or language-project id (en-US, ja-JP, a conlang's slug) plus a revision |
Authored, revised by commit or by an accepted round that changed the lowering; each lowering names the revision it used | Profile authors and accepted rounds (profile-owns-register); never the lowerer's defaults |
| Corpus item | Key item:<source-slug>:<n>; type weksa.corpus_item with text, language, speaker, split group, prior turns, source |
Admitted once; the text is immutable (a correction is a new item that supersedes the old); withdrawn, never deleted, so old scores stay explainable |
Importers and weksa corpus add, under corpus-cast-plus-public-domain; the source enum has no variant for Discord or any training-forbidden source (corpus-clean) |
| Split assignment | Derived: split(scheme, item.group) |
Fixed for a scheme; a new scheme is a new constant, never a reassignment. Model-written items never land in test | The hash function. Nobody assigns by hand, so there is no writer to forbid |
| Loop round | Key run:<label>:round:<n>; type weksa.loop_round with spec version, profile revisions, model ids and prompt digests, sampled train items, proposed change, validation scores before and after, outcome |
Opened, scored, closed accepted or rejected; immutable once closed. Lives in the run store on Yggdrasil | The loop driver's accept rule (validation composite improves past the measured noise floor and no metric regresses past tolerance) |
| Score | Key <lowering-key>:<metric>@<metric-version>; type weksa.score |
Immutable; a new metric version scores again under a new key | The scorer, deterministic given the metric version and the embedder's model id |
| Lowering trace | Key lowering:<packet-key>:<profile>@<rev>:<lowerer-digest>:<sample>; type weksa.lowering holding the surface text and its trace together |
Immutable. A surface text cannot exist without its trace, because they are one record (lowering-traced) |
The lowerer emits; the lowerer sees the packet without its trace (the input type has no such field), never the corpus item |
| Conlang lexicon entry | Key lex:<language>:<concept-id>; root form, morphology class |
Root placed at its concept's embedding when the concept first needs a form in that language; stable once accepted; diachrony derives later forms, it does not overwrite | The language project's owner: the operator for her settings' languages, the loop proposing roots for her review |
| Conlang grammar and phonology data | <language>/grammar, <language>/phonology documents per language project |
Revised by commit; every lowering names the revision | The language project's owner |
| Training pair (later) | Key pair:<frozen-rev>:<item-id>:<profile> |
Created only by re-encoding the whole corpus under the frozen inventory revision; never before the freeze (staged-distill-every-language-equal); split inherited from the item |
The re-encode job, which can only be constructed from a frozen revision |
Authority map (the packet boundary)
- Owner: the validator in
crates/weksaowns whether a packet exists. - Inputs: the packet, the inventory at the packet's revision.
- Outputs: an admitted packet, or a typed refusal naming the rule.
- Derived state: split assignment (from the item's group); the lowering view of a packet (the packet minus its trace).
- Forbidden writers: the Node daemon's
decomposeThoughtIntoInterlinguaandnormalizeInterlinguaPacket(parked, cutpark-node-body); the Metame harness's packet-like YAML (parked); any loop step that writes a packet without the validator. - Shared paths: the loop's encoder, the CLI, tests and the future live
lowering all admit packets through the same
validatecall. - Deletion line: the Node body goes before the crate lands, so no second packet shape survives on main.
Scoring (golf-metric-automatic, conlang-scoring, meaning-metric-embedding-cosine)
- English against its corpus item: chrF (character n-gram F-score, beta 2; a 20-line implementation matched sacrebleu 2.4.3 exactly on four probe pairs) and meaning cosine (sentence embeddings from qwen3-embedding:0.6b, already served by Ollama on Yggdrasil). Probe on one reference: hedged paraphrase 0.948, flattened claim 0.643, register-shifted 0.720, negation 0.496. BERTScore proper needs per-token transformer embeddings and a torch stack; it is deferred, not adopted.
- Every language by the same meaning cosine: the embedder reads the output directly when it can (natural languages, since the embedder is multilingual); for a conlang it reads the deterministic gloss made from the language's own lexicon (Weksa owns the lexicon, so reading it back needs no model). Plus lexicon adherence for a conlang: the share of tokens that parse against its lexicon and morphology.
- A style axis follows as its own cut, behind the same scorer port.
- Leak check: an inventory entry minted in a round is refused if its gloss shares a word 3-gram with the corpus item it was minted for. The packet's only free text is proper names and the trace, so the gloss is the channel to guard.
Where things live and run (rust-single-crate, loop-runs-on-yggdrasil)
- Code: one Cargo workspace at the repo root, one package
crates/weksa(a library and theweksabinary). CultCache throughcultcache-rspinned by git rev, as Huginn pins it. No daemon: the loop is a batch command. A daemon is earned later only by the live lowering service, if isolation protects a named invariant there. - Stores:
data/interlingua/inventory.ccanddata/corpus/corpus.ccin the repo (small, reviewed withweksa dump); run stores (rounds, lowerings, scores) on Yggdrasil under the loop's state root, not in git. - The loop runs on Yggdrasil as a detached unit with a log and a status record.
Starfire runs none of it. Model calls go through a
ModelPort; its first adapter drivesclaude -pon the operator's subscription. Never OpenAI (eureka-body:ruling:no-return-to-openai-supplier), never Discord data (gamecult-chat:ruling:discord-taints-training).
Convergence (convergence-test)
The spec has converged when, on a panel of en-US, ja-JP and the first conlang, for 20 consecutive rounds no accepted change to a closed-class inventory family or the schema raised the validation composite past the noise floor, and at that checkpoint the test-split composite is within the noise floor of validation. The test split is read only at checkpoints. Self then records the freeze, and the training set is the whole corpus re-encoded under the frozen revision.
Cut sequence
One line per cut; only the first two have specs.
park-node-body: park the Node daemon, MiMo command, RUDP shims, launchers and the Discord-sourced Metame harness at tagparked/weksa-node-body; README front door tells the truth. Waits on nothing. (spec)packet-store: Rust crate with packet, inventory and corpus types, the validator, the derived split, the stores and theweksaCLI; the standard reconciled to the types. Waits on nothing; sibling of 1. (spec)scorer: chrF, meaning cosine behind anEmbedderport (Ollama on Yggdrasil), the leak check wired,weksa score. Waits on 2.pd-importer: public-domain play and fiction dialogue into the corpus with speaker, scene group and edition provenance. Waits on 2 and follow-upgutenberg-terms.golf-loop-en: the loop driver,ModelPortwith theclaude -padapter, encoder and lowerer prompts, round records, the accept rule, the detached unit on Yggdrasil. Waits on 3, 4 and follow-upclaude-on-yggdrasil.style-axis: a style-embedding score behind the scorer port. Waits on 3.ja-panel: ja-JP into the loop's panel. Waits on 5.conlang-lexicon: the first conlang's lexicon placed at concept embeddings, its morphology data and the gloss reader. Waits on 3 and questionfirst-conlang.convergence-freeze: the convergence test, the freeze, the re-encode into training pairs. Waits on 5, 7 and 8.distil: fine-tune a lowerer on the frozen training set. Waits on 9 and a host question asked then.live-lowering: agents emit packets and Weksa lowers them for the reader. Waits on 9.