Weksa/docs/targets/interlingua-lowering-map.md
Eureka 2583fb91c3 Map: interlingua lowering model page, scoring, convergence and cut sequence
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>
2026-10-29 10:10:21 +01:00

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/weksa owns 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 decomposeThoughtIntoInterlingua and normalizeInterlinguaPacket (parked, cut park-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 validate call.
  • 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 the weksa binary). CultCache through cultcache-rs pinned 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.cc and data/corpus/corpus.cc in the repo (small, reviewed with weksa 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 drives claude -p on 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.

  1. park-node-body: park the Node daemon, MiMo command, RUDP shims, launchers and the Discord-sourced Metame harness at tag parked/weksa-node-body; README front door tells the truth. Waits on nothing. (spec)
  2. packet-store: Rust crate with packet, inventory and corpus types, the validator, the derived split, the stores and the weksa CLI; the standard reconciled to the types. Waits on nothing; sibling of 1. (spec)
  3. scorer: chrF, meaning cosine behind an Embedder port (Ollama on Yggdrasil), the leak check wired, weksa score. Waits on 2.
  4. pd-importer: public-domain play and fiction dialogue into the corpus with speaker, scene group and edition provenance. Waits on 2 and follow-up gutenberg-terms.
  5. golf-loop-en: the loop driver, ModelPort with the claude -p adapter, encoder and lowerer prompts, round records, the accept rule, the detached unit on Yggdrasil. Waits on 3, 4 and follow-up claude-on-yggdrasil.
  6. style-axis: a style-embedding score behind the scorer port. Waits on 3.
  7. ja-panel: ja-JP into the loop's panel. Waits on 5.
  8. conlang-lexicon: the first conlang's lexicon placed at concept embeddings, its morphology data and the gloss reader. Waits on 3 and question first-conlang.
  9. convergence-freeze: the convergence test, the freeze, the re-encode into training pairs. Waits on 5, 7 and 8.
  10. distil: fine-tune a lowerer on the frozen training set. Waits on 9 and a host question asked then.
  11. live-lowering: agents emit packets and Weksa lowers them for the reader. Waits on 9.