- Zig 100%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| conformance | ||
| corpus/goldens | ||
| demo | ||
| src | ||
| .gitignore | ||
| build.zig | ||
| build.zig.zon | ||
| README.md | ||
mistura
The family's neutral multi-vocabulary host. It is the compiler laranjuice already is, with the vocabulary taken out: no forms of its own, no hooks, no runtime, no editor, no npm package, no plan set, no part numbers, nothing to release. It composes other repositories' vocabularies over one document and produces the pngine document, its sidecars, and the pacer score the timeline exports, the artifacts those vocabularies would have produced separately. It depends on its siblings (canto, laranjuice, pngine, tempura, pacer, SJON) and nothing depends on it; it is never a release gate a vocabulary must pass to ship.
Day one plus the first exported guest, it composes four rows: canto
(canto/text-v1) and the curve vocabulary (curve/graph-v1) as lowered
guests, pngine's own forms as the carrier, and tempura as the first
exported row. tempura's four-manifest bundle (tempura, midi, it, pacer)
arrives live through its own module exports, its forms are stripped from
the carrier, and its timeline leaves the document as <doc>.score.sjon
beside it. pacer takes no row of its own in v0.1: its vocabulary rides
inside tempura's drift-gated bundle and its compiler is linked only into
the conformance checker. The guest table in src/guests.zig is the whole
of a guest, so audzio joining later is a row there, not a design change.
mistura validate <doc.sjon> diagnostics; exit 1 on errors
mistura emit <doc.sjon> -o <dir/> the document, its sidecars, and
the pacer score a timeline exports
mistura compile <doc.sjon> -o <out.png> the PNG stock pngine plays
The pipeline
In order: preload every guest's manifest live from its sibling's own
public export (canto's Schema.canto_src, the curve vocabulary's
Schema.curve_src, pngine's dsl_sjon.Compiler.manifest_src through its
build wiring, tempura's four-manifest Schema.timeline_manifest_srcs);
validate the composed source once to learn which fonts it names and bake
them, which is the discovery step canto's own compile already pays and
the pipeline's first sjon.Host.validateDocument call; between the
discovery and the bake, slice the exported row's roots out of the
discovery forest, walk them through tempura's own fromForest, derive
the timeline and export the pacer score, so a timeline defect gates
before any font work and the document's second artifact is text; append
canto's shared forms through its public augment; make the pipeline's
second sjon.Host.validateDocument call, the lowering pass, over one
source that uses every vocabulary's forms together, with all five hooks
registered — canto/text-v1, curve/graph-v1 and pngine's own three
(pngine.dsl_sjon.hooks, ask P6, landed 2026-10-16) — and canto's
lowering context (its bakes and sidecar route) supplied; print the
lowered tree with the consumed roots stripped (the carrier's own forms
print, except the three sugar heads its hooks consumed — a head-only
strip, so a qualified ordinary (pngine/buffer …) still prints while a
(pngine/init …) goes with its bare spelling; a lowered or exported
row's forms are consumed and stripped whole); union every sidecar into
one out-directory; and compile through pngine's embedded compiler with a
chain resolver over both sidecar tables, the shape
laranjuice/src/host.zig demonstrates. A lowering env is built per call
over the call's own source through pngine's public
buildLoweringEnv, so define-ref sugar expressions (an init's
:workgroups [(ceil (/ NUM 64))]) resolve in the discovery and lowering
passes alike.
That is what replaces the splice: where the mixing document's build ran canto's emit, a sed to widen the perform vector, a cat to append, a cp to gather sidecars and stock pngine, this host does one emit followed by stock validate, render and ls.
What it refuses to be
- A vocabulary: no manifest, no forms, no hooks. Everything lowered here belongs to a sibling.
- A gate: no sibling's release ever waits on this build.
- A vendor: it preloads live build-graph manifests only, never copies, which is what makes its aggregate preload the family's skew alarm (a renamed or conflicting head in a sibling fails this build the day it lands there).
- A sugar host no longer (2026-10-17, ask P6 landed): pngine's three hook
values are public (
pngine.dsl_sjon.hooks), so its sugar lowers in this host's one pass beside the siblings'; before that export the refusal was pinned here as intentional. The contract that remains is the registry's: a form bound to a hook id nobody registers is refused by name (lowering_hook_missing), pinned over a test-local vocabulary.
The P6 capability carries a boundary, and the record names it (2026-10-17).
The mixed-document shape this host supports, the one the gate's own
demo/mix_sugar.sjon pins, is a NAMED (pass-graph …) / (draw-graph …)
beside an authored (frame …). The unnamed spelling, pngine's default,
refuses through this host, and not for want of a registered hook: canto's
augment, which this host always runs, appends its own
(frame :name __canto …) for any document that authors no frame, a
text-free one included (canto/src/emit.zig:254; the frame is written at
:198-213), and pngine's unnamed graph emits (frame :name main …) and
its ownership check refuses the second frame
(pngine/src/dsl_sjon/hooks.zig:287-318). The interaction predates P6: it
is the host boundary the mix exposed, not a missing registration, and P6's
registration and named-graph mix are complete. Nothing here shims it;
unnamed support would be a design change in the owning repository (canto's
synthesis or pngine's ownership rule), so it stands as a named
followup/limitation, recorded here, not filed as an ask.
The rules it obeys
- The pin is the worktree. No cross-repo lockfile, no semver ranges, no
supported-pairs matrix: the aggregate preload is the compatibility
check, and a comptime test in
src/guests.zigasserts each sibling manifest still declares the plugin name and the hook id the guest table records, so a rename is a named build error, not a runtime lookup miss. - Its gate is seven proofs and two commands, run from this root through
obs:zig build testandzig build demo(the lane that rebuilds the committed demo,demo/, and re-checks its recorded output, the carrier record pinned by the dated ruling of 2026-10-05 indemo/README.md, with the timeline's dated 2026-10-06 note and the sugar lane's dated 2026-10-17 block beside it; a difference fails the lane loudly with both sets of numbers and is never absorbed silently). The proofs: the undemonstrated core (two sibling vocabularies lowering over one document, zero diagnostics), the aggregate preload golden, the demo round trip (the unchanged carrier pin with a timeline present, plus the score artifact), determinism by sha256 over two runs in one process (the demo lane checks a separate invocation's pinned record, and the score-check anchor checks the score), pngine's sugar lowering beside the siblings in one pass (gate 5, inverted when ask P6 landed; the missing-hook refusal is re-pinned independently over a test-local vocabulary, and the namespaced strip and the five-hookdemo/mix_sugar.sjonfixture ride the same proof), the compile leg through pngine's embedded compiler, and the two-artifact shape: the emitted score is byte-equal below the header comment to tempura's OWN load path over the document's extracted timeline roots, and pacer's compiler accepts it. - It asks exactly one thing of its siblings: canto's shared-forms
augmentis public. laranjuice and pngine owe nothing and are never edited from here. - Versions it built against are the siblings' own exports (see the guest table); the artifact-metadata row is 04's released form and not invented here.
Zig 0.16; path dependencies on ../canto, ../laranjuice, ../pngine,
../tempura, ../pacer and ../SJON.