Skip to content

Mimi codec: token-exact Moshi parity, q8 variant, explicit guard-validated modeling (codex review round 2)#90

Merged
gabewillen merged 133 commits into
mainfrom
worktree-arch64
Jul 4, 2026
Merged

Mimi codec: token-exact Moshi parity, q8 variant, explicit guard-validated modeling (codex review round 2)#90
gabewillen merged 133 commits into
mainfrom
worktree-arch64

Conversation

@gabewillen

@gabewillen gabewillen commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Summary

Branch line for the Moshi/PersonaPlex M2 milestone (Mimi codec) plus the resolution of the second-pass codex architecture review, and a merge of worktree-dataloader (streaming weights phases).

Mimi codec (M2)

  • EMEL-owned Mimi streaming codec (src/emel/speech/codec/mimi/**): SEANet encoder/decoder (compile-time topology unroll), codec transformers with exact ggml numerics (bf16 KV rings, physical-order softmax, fp16 GELU), split-RVQ quantizer.
  • Token-exact encode parity vs pinned moshi.cpp on the real Mimi artifact: 37/37 frames (592/592 codes) on the chirp+noise torture signal, decode PSNR 80.7 dB, gated via scripts/bench_mimi_compare.sh --require-token-exact.
  • Three bound operand classes selected by explicit guard rows: f32 canonical, reference f16 convs, converter-quantized q8_0 projections (tools/bench/moshi_gguf_convert.py --quantize q8_0, 347→199 MB).
  • Throughput: ~65 ms/frame single-threaded vs the 80 ms real-time budget; ~20-35% fewer CPU cycles than multi-threaded moshi.cpp for identical output.

Codex review round 2 resolution (this HEAD commit)

  1. No action-written outcome routing: pure validation guards run BEFORE non-failing compute actions. The bind contract is validated by a compile-time dry-run instantiation of the same walk that binds (cannot drift); decode code-range is the only data-dependent per-frame check and is a pure guard. Distinct bind_failed / arena_capacity / request_shape / code_range error routes.
  2. decode_wavefront outcome-slot race: parallel dispatch now requires pairwise-distinct accepted slots; aliased slots take the serial path. Reproduced first with a failing test (misreported failed_lane).
  3. No fallback branching in actions: new total thread_pool_scheduler_ref::submit_or_run primitive (placement is scheduler-internal capacity handling); wavefront action and generator sliced-matmul are straight-line.
  4. Public sizing surface: bench/parity tools use mimi::*_arena_floats from any.hpp, never mimi::detail.

Coverage

New committed operand-class fixtures mimi-tiny-f16.gguf / mimi-tiny-q8.gguf (deterministic, generator reproduces base fixture bit-identically) drive the f16/q8 guard rows and compute paths: mimi component coverage 66% → ~90%.

Merge + host fixes

  • Merged worktree-dataloader (streaming weight window machine, RAM-aware build clamp, weight_streaming bench suite).
  • Bench registry array 34→35; speech_codec_mimi reference-lane placeholder records (sortformer recorded pattern) so the full compare gate pairs lanes 1:1.
  • gcc -Werror=class-memaccess sweep in tests (memset on the now-non-trivial model::data::vocab → value-init; encoder-test vocab_builder reproduces its all-zero contract explicitly).

Verification

  • Full suite: 1185/1185 (39,313 assertions).
  • Token-exact mimi parity re-verified post-refactor; bench_snapshot (speech_codec_mimi) and paritychecker lanes green.
  • Scoped quality_gates.sh final run in flight at draft time (coverage lane ~30 min on this host); will update here when it lands.

Open items (need maintainer decision)

  • decode_wavefront bench baselines: the suite's 5 entries have no committed baselines (pre-existing); committing them is a snapshot update requiring explicit consent, so the bench lane here is scoped to speech_codec_mimi.
  • stage_ok-style action-recorded outcome channels still exist in whisper/sortformer/gguf-loader (out of this review's scope; likely the next review target).
  • EMEL_QUALITY_GATES_SCOPE=full reserved for M2 milestone closeout.

Handoff (resume protocol)

Where: worktree /shared/stateforward/emel.cpp/.claude/worktrees/arch64, branch worktree-arch64. HEAD = 2a69575 (review-round-2 resolution) on top of merge 12dff0a (worktree-dataloader). Durable session notes live in the agent memory file moshi-personaplex-progress.md (memory index under ~/.claude/projects/-shared-stateforward-emel-cpp/memory/).

Exact current state (updated at handoff time): bench_snapshot (speech_codec_mimi) ✅, paritychecker ✅, fuzz skipped, all 13 coverage ctest shards ✅. The coverage gate scored changed-line 88.0% vs the required 90% on the previous run; commit ce9c514 added direct child-actor validation tests (unbound-runtime / request-shape / buffer-capacity / code-range routes on encoder::sm / decoder::sm / quantizer::sm) which raise the mimi component to 92.3% lines locally. A full gate re-run is in flight at handoff time — check for the freshest result before assuming state; if it still lands under 90%, the residual uncovered lines are per-tensor contract-reject branches in detail.cpp's plan/bind walk (reachable only with corrupt-model fixtures).

Next step: confirm the in-flight gate run is green, then update this PR (lane status + mark ready if appropriate).

How to run the gate on this host (5950X box gotchas):

# one-time per session: clang-format/gcovr venv shim
python3 -m venv /tmp/emel-clang-format-venv && /tmp/emel-clang-format-venv/bin/pip install clang-format gcovr

PATH="/tmp/emel-clang-format-venv/bin:$PATH" \
EMEL_QUALITY_GATES_TIMEOUT=5400s \
EMEL_QUALITY_GATES_BENCH_SUITE=speech_codec_mimi \
EMEL_QUALITY_GATES_CHANGED_FILES="<comma-separated list; commas only, never spaces>" \
scripts/quality_gates.sh
  • The script self-wraps in timeout 1800s by default; the coverage lane alone takes ~29 min here, so EMEL_QUALITY_GATES_TIMEOUT=5400s is required.
  • Run it detached via atmux exec --detach --shared --timeout 0 -- bash <wrapper.sh> — plain setsid/nohup children get reaped between agent tool calls, and the 10-min tool timeout kills foreground runs.
  • Bench lane is scoped to speech_codec_mimi because the decode_wavefront suite has no committed baselines (pre-existing; consent-gated, see Open items). Touching tools/bench/bench_runner*.cpp maps to "all suites" and will fan out ~30 per-suite llama.cpp clones — always pass EMEL_QUALITY_GATES_BENCH_SUITE.

Verification commands:

  • Token-exact parity gate: scripts/bench_mimi_compare.sh (expects "token_exact": true, decode PSNR ~80 dB; needs build/moshi_reference/ artifacts from scripts/setup_moshi_cpp_reference.sh).
  • Full tests: cmake --build build/zig --target emel_tests_bin --parallel 8 && ./build/zig/emel_tests_bin (1185 cases green at HEAD).
  • Fixture regeneration (bit-identical, incl. the new f16/q8 variants): python3 tools/bench/moshi_make_tiny_fixture.py --output-dir tests/models.

After gates are green: update this PR (mark ready or note lane status), then next roadmap work is M3 (temporal transformer + depformer under src/emel/speech/lm/moshi/**) per the approved plan (~/.claude/plans/pull-in-moshi-cpp-as-lazy-perlis.md); optional M2 follow-ups: fork/join conv-GEMM lane parallelism (generator compute_mul_mat_sliced_parallel pattern; per-head attention needs per-lane scratch), quantized convs (per-layer class design), ARM NEON exactness ports.


Note

Low Risk
Documentation-only changes under .planning/architecture/ with no executable code paths modified.

Overview
Updates .planning/architecture/ Mermaid diagrams and transition tables so they match the current sm.hpp state machines (no runtime code in this diff).

graph.md now documents the compute_reserved_graph path: valid reserved compute jumps reservedexecuting (skipping assemble), with matching execute/completion handling and reserved-specific compute-error dispatch back to reserved.

io_mmap.md adds the full advise_mapping_runtime flow from state_ready: handle/range/platform/kind validation, sequential/willneed/dontneed attempts, and done/error callback branches.

kernel_aarch64.md reflects new or refined dispatch guards on the ready state—e.g. dtype/mode-specific mark_done routes for add/mul, get_rows, rope, im2col, conv transpose; f16 mul_mat SIMD path; and unary tanh/elu/gelu/silu rows.

Reviewed by Cursor Bugbot for commit 140738f. Bugbot is set up for automated code reviews on this repo. Configure here.

gabewillen added 30 commits July 2, 2026 07:24
…shi GGUF model binding

Registers the "moshi" architecture (Kyutai Moshi / NVIDIA PersonaPlex family)
and wires Codes4Fun/moshi.cpp in as the pinned reference implementation,
following the llama.cpp/whisper.cpp reference patterns.

Model binding (src/emel/model/moshi/):
- component-discriminated contract (moshi.component = lm | mimi | voice)
  with required moshi.* hparams; load_hparams maps into generic params
  (temporal transformer dims, depformer dims, delays, mimi codec shape)
- execution-contract validation per component: family views (lm.*, mimi.*,
  voice.*), hparam-derived tensor shape checks (text_emb/text_linear/emb
  embeddings, RVQ codebooks), per-layer block presence for both fused
  (in_proj_weight) and pre-split (in_projs.N) attention layouts
- raw metadata-less moshi.cpp GGUF caches are rejected explicitly (no
  general.architecture -> loader error); conversion is required

Converter + fixtures (tools/bench/):
- moshi_gguf_convert.py: raw moshi.cpp GGUF -> emel-enriched GGUF; restores
  CRC-mangled tensor names (>=64 chars, moshi.cpp loader.h tensor_name zlib
  crc32 low-nibble scheme), attaches moshi.* hparams from
  personaplex-config.json / pinned presets with tensor-shape cross-checks,
  embeds the SentencePiece text tokenizer as tokenizer.ggml.* (stdlib-only
  ModelProto wire parser), streams tensor payloads through byte-identically.
  Verified against the real HF artifacts: mimi-e351c8d8-125.gguf (all 64
  mangled names restored, data region sha-identical) and voices/NATF0.gguf.
- moshi_make_tiny_fixture.py: deterministic tiny fixtures generated through
  the maintained converter path; committed under tests/models (LFS) with
  provenance in tests/models/README.md

Reference wiring:
- tools/bench/moshi_reference_ref.txt pins moshi.cpp @ f1fabbd14a50
- EMEL_BENCH_NEEDS_MOSHI FetchContent gate in tools/bench/CMakeLists.txt
  (source-only populate; reference driver targets land with milestone 2)
- scripts/setup_moshi_cpp_reference.sh: clone+pin moshi.cpp, sha256-pinned
  downloads (PersonaPlex-7B q4_k, mimi codec, tokenizer, voice prompt,
  config), deterministic 24 kHz WAV fixture, auto-runs the converter for
  the EMEL-lane enriched GGUFs
- scripts/check_domain_boundaries.sh: forbidden moshi/mimi runtime roots +
  generic-recognizer leak checks

Tests: tests/model/moshi/binding_tests.cpp (registry, enriched lm/mimi/voice
fixture loading incl. embedded-vocab SPM tokenizer, raw-cache rejection,
hparam contract negatives, validation negatives); fixture manifest checks.
Full suite 1132/1132 passing; coverage lane passed; lint snapshot updated
with consent (fixture_manifest_tests.cpp now format-clean).

Known pre-existing gate failures (unrelated, documented): paritychecker
generation baselines for LFM2.5-230M-Q8_0 missing on this lineage;
bench_snapshot missing aarch64 entries on x86 host plus uncommitted
decode_wavefront/flash-attention baselines from earlier branch work.
… + silu/elu/gelu/tanh (Moshi M2 step 1)

Lands real scalar compute for the kernel ops the Mimi codec and Moshi LM
need; all were previously enumerated in EMEL_KERNEL_OP_EVENT_LIST and wired
into both backend machines but silently uncomputed.

Every dtype/mode variant is modeled as an explicit guard-selected transition
row (op_unary pattern) - no runtime variant branches inside actions/detail:
- op_get_rows: six variant rows per backend (f32/f16/bf16/q4_0/q8_0/q4_k
  sources; row dequant via the existing quant helpers, index-validated in
  the guard path, unsupported dtypes reject explicitly)
- op_rope: norm/neox pairing rows (ggml op_params layout, ext_factor==0,
  positions i32; freq_base/freq_scale/attn_factor honored)
- op_im2col: f32/f16 destination rows (1D, ggml operand contract; conv1d =
  im2col + existing mul_mat)
- op_conv_transpose_1d: f32/f16 weight rows (ggml contract: p0==0, d0==1)
- op_rms_norm / op_norm: generic scalar path (single algorithm; eps from
  op_params, double accumulation like the reference)
- op_unary: new tanh/elu/gelu/silu subop rows in both backends (gelu uses
  the ggml tanh-approximation constants)

detail additions: dtype_i32/dtype_bf16 codes + sizes, bf16->f32 conversion,
ggml-layout op_param readers, valid_variant_guard combiner, per-variant
compile-time exec functors shared by both backends.

Tests: per-op positive/negative cases in tests/kernel/x86_64_tests.cpp
(gather f32+q8_0 with out-of-range index rejection, rms/layer norm math,
rope norm+neox rotations, im2col columns, conv_transpose_1d accumulation);
unary subop coverage in both backend test files now asserts the new subops
compute and uses sigmoid as the still-unsupported reject probe.
Full suite: 1136/1136 passing. Lint dirty-list shrinkage (6 files now
format-clean) applied with explicit consent.

ggml parity cases in tools/paritychecker land next with the mimi codec
parity lane.
Adds paritychecker kernel-engine cases comparing the emel backend machines
against ggml for: unary tanh/elu/silu (tight tolerance) and gelu (dedicated
fp16-table slack), rms_norm, norm, get_rows over f32 tables and over
q8_0/q4_0/q4_k blocks quantized by ggml itself (identical block bytes in
both lanes), rope norm+neox (ggml_rope_ext params), im2col (1D), and
conv_transpose_1d (shared f16 kernel taps).

Two defects the new cases caught, now fixed:
- has_required_src0 rejected sub-byte quantized get_rows sources because the
  generic layout check truncates q4 per-element sizes to zero; op_get_rows
  now shares the native-quantized row-layout contract with mul_mat.
- conv_transpose_1d's f16 variant now rounds input samples through fp16
  before the tap multiplies, matching the reference f16 operand pipeline
  exactly.

scripts/paritychecker.sh --runner=kernel: kernel parity ok (both backends).
Full unit suite: 1136/1136 passing.
…M2 step 2)

Lands the complete Mimi codec numeric pipeline as kernel-dispatched compute
under src/emel/speech/codec/mimi/ (detail layer; the codec actors and facade
land next):

- plan/size/bind: fixed mimi_v0_1 SEANet topology tables cross-checked
  against tensor shapes; one-time weight canonicalization (f16->f32,
  prepare-time transposes so no runtime GEMM transposes); RVQ nearest-search
  tables with the -|c|^2/2 bias column folded in; streaming-state arena
  carved with per-layer offsets; caller-owned arenas sized by required_*
  functions (allocation-free dispatch).
- compute helpers (all numeric work as kernel op events, generator pattern):
  streaming causal conv (left-context state, im2col + mul_mat + broadcast
  bias), streaming transposed conv with overlap-add tail state (full and
  explicit depthwise variants - the caller picks the variant, no shape
  sniffing), SEANet stacks with resnet residuals and ELU, per-token codec
  transformer (fused-QKV, rope, ring-buffer KV with two-segment windowed
  attention, softmax scale param, layer scales, GELU MLP), split-RVQ encode
  (mul_mat_argmax + get_rows + sub residual) and decode (get_rows sums +
  output projections).
- new kernel variant: op_add/op_mul BROADCAST-ROW (src1 = one dst row),
  modeled as explicit guard-selected transition rows in both backend
  machines; elementwise SIMD guards now claim only equally-sized operands
  (scoped to add/mul so mul_mat routing is untouched). Unit tested including
  the mismatched-row rejection.
- tests/speech/codec/mimi_detail_tests.cpp: full encode chain (1920-sample
  frame -> seanet -> 25 Hz transformer -> downsample -> 4 RVQ codes) with
  streaming-state advance and exact reset determinism, full decode chain
  (codes -> depthwise upsample -> transformer -> seanet -> 1920 finite
  samples), out-of-range code rejection.
- tests/models/mimi-tiny.gguf regenerated with the full tiny-scale topology
  (README hash + provenance updated; deterministic generator).

Full suite: 1139/1139 passing. Lint clean; domain boundaries clean.
Adds the stateforward.SML actor layer over the verified Mimi compute
pipeline, completing the codec component per the approved plan:

- emel::speech::codec::mimi::encoder::sm - one 80 ms PCM frame -> one
  12.5 Hz latent column through explicit frontend/transformer/downsample
  stage states; validation (runtime bound, request shape, buffer capacity)
  and stage outcomes are guard-routed decision states over the per-dispatch
  runtime ctx, whisper-encoder pattern.
- emel::speech::codec::mimi::quantizer::sm - split-RVQ latent <-> codes with
  separate explicit encode/decode state chains.
- emel::speech::codec::mimi::decoder::sm - latent -> PCM through depthwise
  upsample / transformer / SEANet backend stage states (the depthwise
  transposed-conv variant is selected by the transition, not sniffed).
- emel::speech::codec::mimi::sm facade - owns the bound runtime, streaming
  state, and the three child machines (child data owned by parent context,
  cross-machine communication only via process_event); sequences
  encode_frame (frontend -> quantize) and decode_frame (dequantize ->
  backend), handles initialize/reset_stream, and answers pre-initialization
  requests with explicit not_initialized errors. Caller owns all arenas
  (initialize event spans, sized by the detail required_* functions), so the
  actors allocate nothing during dispatch.
- emel::MimiCodec alias in machines.hpp; public facade header any.hpp.

tests/speech/codec/mimi_lifecycle_tests.cpp drives the public facade against
tests/models/mimi-tiny.gguf: initialize -> encode_frame -> decode_frame with
state inspection (session_ready via is()/visit_current_states), reset_stream
code-replay determinism, not-initialized rejection, and undersized-arena
bind failure landing back in uninitialized.

Full suite: 1142/1142 passing. Lint and domain boundaries clean.
…M2 step 4a)

- tools/bench/speech/mimi_emel_parity_runner.cpp: EMEL-lane runner (links
  only emel; the reference lane stays a separate executable per the
  reference policy). Loads an enriched mimi GGUF, streams a 24 kHz mono s16
  WAV through emel::speech::codec::mimi::sm one 80 ms frame at a time,
  emits `frame=<n> codes=...` lines, and optionally decodes the code stream
  back to raw f32 PCM (--decode-out). Registered in tools/bench CMake.
- codec bind fix for real GGUFs: GGUF collapses trailing size-1 dims (the
  decoder's final 64->1 conv stores as [3, 64]), so the plan walk now
  threads the running channel count through both chains and derives out
  channels from element counts; every layer's geometry is plan-resolved and
  cross-checked (encoder must land on mimi.dim, decoder on 1 channel).
- paritychecker: op_add/op_mul broadcast-row cases vs ggml repeat-broadcast
  semantics (kernel parity lane green on both backends).

Verified against the real converted mimi-e351c8d8-125 model: a 1 s 440 Hz
tone encodes to 12 frames x 16 code streams with the semantic stream stable
in steady state, and decoding the codes reconstructs a 440 Hz tone at
matching RMS with ~17 dB steady-state SNR - functionally correct end to end
on real weights (scalar throughput ~250 ms/frame; performance work is the
bench suite's follow-up).

Full suite: 1142/1142 passing. Lint clean.
…uite (Moshi M2 step 4b)

Reference lane:
- tools/bench/speech/moshi_reference_driver.cpp: pinned moshi.cpp + ggml +
  SentencePiece driver with deterministic frame-level encode/decode
  subcommands emitting the same `frame=<n> codes=...` format as the EMEL
  runner. Builds against the llama.cpp-pinned ggml (no API skew); C++20;
  SentencePiece v0.2.0 via FetchContent, reference lane only.
- tools/bench CMake: speech_codec_mimi added to the NEEDS_LLAMA list (ggml
  only) and the driver target gated on EMEL_BENCH_NEEDS_MOSHI.

Comparison surface (mimi_compare/v1):
- tools/bench/mimi_compare.py runs both lanes as separate subprocesses
  (two-lane isolation) and reports per-frame code match, token_exact, and
  decode-vs-decode PSNR; reference_backends/moshi_cpp_mimi.json manifest;
  scripts/bench_mimi_compare.sh wrapper (--build-only/--run-only), and
  setup_moshi_cpp_reference.sh --build-only now delegates to it.

Bench suite:
- speech_codec_mimi (tools/bench/speech/codec_mimi_bench.cpp, registry
  33->34): facade frame latency on the tiny fixture - encode 2.53 ms,
  decode 2.97 ms, roundtrip 5.48 ms per 80 ms frame budget. Baseline
  snapshots deferred pending consent.
- dependency manifest records for the suite (txt + cpp table).

Honest parity status, embedded in the compare report and backend manifest:
the reference executes ggml's f16 conv pipeline (moshi.cpp requires f16
conv weights and aborts on an f32 model; attention KV cast to bf16) while
the EMEL lane computes in f32 after lossless f16->f32 canonicalization.
Different effective operand classes, so results are reported as similarity
(25.5% code match, 21.3 dB decode PSNR on the 1 s tone), NOT kernel parity.
Token-exact parity requires the EMEL codec to consume the f16 operand
class end to end - tracked as the next M2 work item.
The reference-lane driver tools/bench/speech/moshi_reference_driver.cpp is
legitimate (reference naming is confined to tools/bench per policy); the
boundary check must forbid the speech/moshi/ runtime DIRECTORY root without
matching that filename. speech::moshi namespace remains forbidden.
Tiny-fixture facade frame latency on this host: encode 2.53 ms, decode
2.97 ms, roundtrip 5.48 ms per 80 ms frame.
…step 1)

First piece of the user-approved f16 operand-class pipeline for token-exact
Mimi encode parity:

- kernel detail: can_run_mul_mat_f16 / run_mul_mat_f16 with ggml's layout
  (src0 f16 [k,m], src1 f16 [k,n] both k-fastest, dst f32 [m,n]) and
  vec_dot_f16_ggml - an exact port of the pinned ggml_vec_dot_f16 x86
  AVX2+F16C+FMA path: four 8-lane f32 accumulators over 32-element steps,
  pairwise reduce (0+=2, 1+=3, 0+=1, 128-lane add, two hadds), and a
  double-precision scalar tail; scalar fallback matches ggml's no-SIMD path.
- both backend machines: explicit guard-selected transition row
  (valid_op_mul_mat_f16 -> exec_scalar_op_mul_mat_f16) ahead of the generic
  mul_mat row; generic f32/quantized guards unchanged.
- paritychecker: f16xf16 mul_mat case vs ggml_mul_mat requiring BIT-EXACT
  equality (k=70 exercises the 32-wide loop plus tail) - green on both
  backends.

Full suite: 1142/1142. Next: rebind mimi conv/proj weights as raw f16 with
f16 im2col dispatch, then bf16 KV rounding, then rerun mimi_compare
expecting code match -> 100%.
- SML pin -> external-completion branch (stateforward/sml.cpp PR #16)
- emel aliases + sm_external_completion_tests (9 cases green)
- io/mmap advise_mapping surface (sequential/willneed/dontneed, guard-routed
  kinds, 6 cases green)
- model/tensor/window machine WIP (detail/errors/events/context/guards/actions)
- bench regressions warn by default (EMEL_BENCH_STRICT_REGRESSION=1 for strict)
- LFM2.5-230M fixture graduated to current_publication + 4 parity baselines
- SYSTEM include for sml dep + pedantic pragma guards (g++ coverage lane)
…16 parity step 2)

Rewires the Mimi codec onto the reference f16 operand class for models that
store f16 conv weights (the real Mimi model):

- plan/bind: operand class detected on the first encoder conv and recorded
  as the bound property codec_runtime::conv_f16; raw f16 taps and quantizer
  conv1x1 projections are kept alongside the f32 canonical copies
  (prepare_raw_f16, arena sized for both); every conv in an f16 model must
  itself be f16 or bind fails.
- compute: compute_seanet_stack / compute_streaming_conv / compute_rvq_
  encode / compute_rvq_decode are now template<bool conv_f16>. The f16 path
  reproduces ggml_conv_1d exactly: f16 im2col (input rounded RNE) followed
  by the bit-exact f16 mul_mat over the raw f16 weight rows (the ggml
  reshape layout equals the GGUF layout, so weights are consumed verbatim);
  quantizer projections round their input through f16 and use the same
  matmul (ggml conv1x1 semantics).
- actors: operand-class selection is modeled explicitly - new variant
  decision states + guard_conv_f32/guard_conv_f16 rows in the encoder
  (frontend, downsample), decoder (backend), and quantizer (encode, decode)
  machines; effects are templates instantiated per row.
- codec transformer: K/V ring values round through bf16 (ggml
  fp32_to_bf16 RNE port, new in kernel detail) matching the reference's
  CACHE_BF16 cache.

Real-model evidence (440 Hz tone vs moshi.cpp reference): frame 0 code
match 15/16 (was 11/16 on the f32 pipeline); the remaining divergence is
attention numerics (reference converts q and the softmaxed weights to bf16
and dots in physical slot order) plus ggml's fp16-LUT GELU - both mapped
and queued as the next steps toward token-exact.

Full suite: 1142/1142. Lint clean.
# Conflicts:
#	snapshots/quality_gates/timing.txt
# Conflicts:
#	snapshots/quality_gates/timing.txt
#	src/emel/kernel/x86_64/actions.hpp
#	src/emel/kernel/x86_64/guards.hpp
Tensor-owned residency for models larger than RAM: whole-file mmap source,
budget-guarded passthrough vs streaming decision, ring of pre-allocated layer
slots filled by a 2-lane I/O pool via staged_read (one actor per slot for
single-writer under concurrent loads), and coroutine suspension on slot loads
through the external-completion co_sm policy.

Acquire is a three-dispatch protocol (resolve/settle/publish) driven
unconditionally by the typed wrapper: resolve joins a slot still mid-load for
a different layer (non-sequential access), settle decides
resident/loading/unscheduled and submits+requires the target, publish routes
on the committed residency, publishes the slot view, and advances the
prefetch ring. The prefetch guard never targets the just-published slot (the
pass wrap can alias them when layer_count % slot_count != 0) and willneed/
dontneed advise flows ahead of and behind the window.

Tests: lifecycle (bind validation, passthrough, rebind rejection, not_bound/
not_streaming legs, allocation-free acquire) and streaming (content integrity
across ring eviction, cold jumps joining busy slots, unbind draining
in-flight loads).
…y step 3)

Completes the exact reference-numerics port. Encode is now token-exact
against the pinned moshi.cpp reference on the real Mimi model: 192/192
codes on a 1 s tone and 592/592 codes on a 3 s chirp+noise+silence torture
signal (37 frames), with lane-vs-lane decode PSNR of 78 dB. The official
compare gate (scripts/bench_mimi_compare.sh -> mimi_compare.py) now runs
with --require-token-exact, and the backend manifest's operand-class
caveats are replaced with the token-exact parity statement.

Exact ports added to the kernel detail layer (all validated in the parity
checker or end-to-end):
- vec_dot_f32_ggml / vec_dot_bf16_ggml: ggml's AVX2 accumulator layouts
  and reduce orders (f32: 4x fmadd + pairwise/hadd reduce, float tail;
  bf16: 4x mul+add with <<16 lane loads, movehl/movehdup reduce, double
  tail).
- v_expf_ggml + soft_max_row_ggml: ggml's vectorized expf polynomial and
  row softmax (per-8 horizontal reduce into a double sum, libm expf tail,
  1/sum in double).
- norm_row_ggml: ggml_compute_forward_norm's row math (float mean from a
  double sum, AVX2 centered-variance blocks, double variance sum).
- GELU now replicates GGML_GELU_FP16 exactly (fp16-quantized input/output
  around the tanh approximation with +-10 saturation); the gelu parity
  case is tightened from 2e-3 slack to bit-exact and passes.

Codec transformer rewritten on those primitives:
- reference rope: timestep-embedding angles (expf(-logf(mp)*j/half)) with
  adjacent-pair rotation and moshi's half-split output layout (the layout
  changes vec_dot accumulation order, so it is part of the contract).
- reference attention: K/V rings hold raw bf16 (ggml CACHE_BF16); q and
  the softmaxed weights round to bf16; scores run over the full ring in
  physical slot order with -inf masking; the V pass materializes the
  transposed bf16 value cache exactly like ggml's cont(transpose(v)).
- transformer projections consume raw row-major weights via the ggml f32
  dot (prepare_matrix_raw replaces the transposed packing).

Throughput snapshot (37-frame real-model encode): EMEL 3.20 s wall /
2.61 s user single-threaded (~86 ms/frame) vs reference 1.23 s wall /
3.24 s user multi-threaded - EMEL already spends ~20% fewer total CPU
cycles for identical output; parallelization is the next lever. Tiny
fixture bench improved slightly (encode 2.40 ms vs 2.53 ms baseline).

Full suite: 1154/1154. Kernel parity green. Lint and boundaries clean.
…step 1)

Profiling the real-model encode showed the top cost was not compute but
the staging copies routed through generic strided kernel views (per-element
tensor_offset_bytes/is_dense_contiguous calls dominated the profile). The
conv/convtr staging, ring/overlap state saves, and resnet residual copy are
pure moves with no arithmetic, so they now use direct loops and memcpy in
the codec detail layer.

37-frame real-model encode: 3.17 s -> 2.69 s wall (-15%), 2.59 s -> 2.11 s
user, single-threaded ~73 ms/frame (80 ms real-time budget). Token-exact
parity vs the moshi.cpp reference re-verified after the change (592/592
codes on the torture signal). For contrast the reference burns 3.24 s user
for the same output; the next throughput lever is fork/join lane
parallelism reusing the generator's view-sliced pattern.

Full suite: 1154/1154. Lint clean.
One engagement guard (guard_decode_stream_window_ready, mirroring the
lane-pool capability gate) composed onto the scalar kernel and
native_quantized flash decode routes; streamed rows sit above their
resident/parallel siblings and dispatch window_mode::streamed kernel
instantiations. run_layer's streamed prologue acquires the layer's slot view
from the tensor window (suspending on in-flight loads via the
external-completion drain) and rebases the block's matmul weight records
onto the slot in canonical role order; prefill stays resident through the
always-valid mmap source views (v1 streams decode only).

Owner-side wiring: generator ctor overload takes the bound window actor and
its bind-reported streaming_active; the initializer re-attaches both after
prepare() reconstructs the backend and records the pristine per-layer weight
records the rebase clones from (branch-free bookkeeping).

Tests: streamed-vs-resident argmax token parity through the public generator
path (2 slots over 4 layers), slot-byte consumption proof (model B's file
streamed under model A's records), passthrough disengagement.
…erand class

moshi.cpp cannot run a quantized Mimi at all (its conv path requires f16
weights), so this is an emel-owned operand class.

Converter (tools/bench/moshi_gguf_convert.py --quantize q8_0, needs numpy):
- quantizes the transformer projections (in/out_proj, linear1/2) and RVQ
  input/output projections to q8_0 row blocks matching the emel/ggml
  encoder semantics (per-32 block, fp16 scale, round-half-away); conv1x1
  projections stored [1, in, out] reshape to [in, out] so the quantized
  row length is the real contraction length. Norms, biases, layer scales,
  codebooks, convs, and convtrs keep their float dtypes.
- 347 MB -> 199 MB (-43%), 68 tensors quantized, quantization recorded in
  moshi.mimi.quantization metadata.

Codec: two new independent bound operand properties, each selected by
explicit guard rows per the behavior-modeling directive (never helper
branches): proj_q8 (transformer projections; encoder/decoder gain a
transformer variant decision state with guard_proj_f32/guard_proj_q8 rows)
and rvq_q8 (quantizer projections; the quantizer's variant decision states
now carry three mutually exclusive class rows: f32 / reference-f16 / q8).
Pre-quantized weights bind once into the arena (prepare_raw_q8_0) and the
hot path dispatches the existing AVX2/NEON quantized mat-vec kernels - no
packing or weight conversion in the frame loop.

Real-model quality vs the f16 token-exact reference (37-frame torture
signal): 87% code match, semantic stream 35/37, decode PSNR ~31 dB; an
RVQ-projections-in-fp variant measured identical code match, confirming
the flips come from transformer-latent perturbation inherent to
quantization. The f16 lane keeps its token-exact gate; the q8 artifact is
a size/bandwidth option with these measured bars.

Full suite: 1154/1154. Lint clean.
topology unroll, event-payload observation)

Addresses tmp/codex.review.md:

- HIGH kernel_kind: codec_runtime::kernel_kind now defaults to
  emel::kernel::detect_host_kind() (aarch64 hosts route to the aarch64
  kernel actor) and the bound kind is applied to the nested kernel machine
  exactly once at bind; the five per-helper set_kind calls are gone, so no
  backend selection happens inside compute helpers.

- HIGH seanet block-kind branching: compute_seanet_stack's runtime
  layer.kind dispatch is replaced by a compile-time unroll of the constexpr
  topology tables - compute_stack_step<conv_f16, kind> is instantiated per
  table slot (kind is a template parameter resolved from
  k_encoder_topology/k_decoder_topology at compile time), and the public
  entries are compute_seanet_encoder/compute_seanet_decoder chosen by the
  already-distinct actor effects. Only compile-time conditionals remain in
  the stack. Token-exact parity re-verified after the change (37/37 frames
  vs the moshi.cpp reference).

- MEDIUM context-reading wrapper accessors: removed frame_samples()/n_q()/
  frames_encoded()/frames_decoded()/frames_quantized()/frames_dequantized().
  Callers observe the modeled events instead: initialize_done already
  carries frame_samples and n_q, and the done callbacks count completed
  frames (runner, bench suite, and lifecycle tests updated). The child
  actors keep no persistent state, so their contexts are now empty structs
  per the context rules.

- HIGH stage_ok routing: kept, with the pattern now documented at the ctx
  definition - it is the repository's sanctioned per-dispatch outcome
  channel (identical to gguf loader actions writing ctx.err from
  detail::probe_requirements and guards routing on it, and to the whisper
  encoder's runtime ctx). Actions record outcomes of already-executed work
  without branching; guards - pure predicates of the runtime event - route
  the explicit success/error transitions; the mark_*_failed effects assign
  typed errors on the explicit error transitions.

Full suite: 1154/1154. Lint, boundaries clean. Token-exact gate green.
New opt-in suite (EMEL_BENCH_WEIGHT_STREAMING=1, set by
scripts/bench.sh --suite=weight_streaming) comparing three lanes on the
LFM2.5-230M-Q8_0 fixture at max_tokens 32 with separate first_token rows:
emel window (streamed decode via the tensor window), emel mmap (passthrough
whole-file mapping, OS demand paging), and a llama.cpp mmap reference at
matched threads. EMEL lanes are EMEL-owned end to end; the reference lane
never shares objects. Note fields record bytes_read and major_faults.

scripts/bench.sh gains --memory-max=<bytes|NNpct|none> (weight_streaming
only): systemd-run user-scope wrapper with MemoryMax + MemorySwapMax=0,
probe with hard fail when delegation is missing, NNpct derived from the
fixture size, run-only mode reusing the default bench build dir.

Known limits recorded in the bench source: EMEL session arenas size to the
model's advertised context_length (3.57GB RSS on this fixture), so honest
capped runs need a larger fixture or a session context cap; reference rows
pair by case name so the llama measurement appears under both lane names.
Every build script used bare 'cmake --build --parallel' (one job per core).
The SML template TUs cost 2-4GB of compiler RSS each, so 30 jobs on a 58GB
host oversubscribes memory ~2x and swaps the machine - worst under the
coverage lane's g++ -O0 --coverage rebuild inside quality gates.

scripts/build_jobs.sh computes jobs = min(cores, MemAvailable / 4GB)
(override: EMEL_BUILD_JOBS) and exports CMAKE_BUILD_PARALLEL_LEVEL; sourced
by build_with_zig, bench, test_with_coverage, and quality_gates so the
gate's inner builds are bounded too. AGENTS.md records the rule plus the
no-concurrent-jobs invariant for shared hosts.
Measured compiler RSS is ~3-4GB per template TU under zig -O3 but ~7-8GB
under g++ -O0 --coverage, so the flat 4GB budget still let the coverage lane
reach the memory ceiling at 8 jobs. The clamp now takes a per-job budget
(EMEL_BUILD_JOB_MEM_GB, default 6) and the coverage build recomputes its own
bound at 8GB/job (override: EMEL_COVERAGE_BUILD_JOBS).
# Conflicts:
#	tools/bench/CMakeLists.txt
…actions, wavefront outcome-slot guard, total submit_or_run, public mimi sizing

Finding 1 (stage_ok routing): every success/error route in the mimi facade
and encoder/decoder/quantizer children is now decided by pure validation
guards BEFORE the corresponding action runs; compute actions are non-failing
by contract and chain unconditionally. detail gains validate_codec_contract
(compile-time dry-run instantiation of the same bind walk, so the validator
cannot drift from the bind it authorizes), validate_codes_in_range (the only
data-dependent per-frame failure), void compute entries, and O(1) bound
sizing (runtime.workspace_floats/frame_floats replace a per-frame model
re-plan in capacity guards). Bind splits into contract -> capacity -> bind
states with distinct bind_failed / arena_capacity errors; frame requests
route explicit request_shape / code_range errors.

Finding 2 (shared outcome slot race): parallel wavefront dispatch now
requires pairwise-distinct caller-owned accepted slots
(all_lane_outcomes_distinct); aliased slots route through the serial path.
Reproduced first with a failing test (misreported failed_lane).

Finding 3 (fallback selection in action): new total fork primitive
thread_pool_scheduler_ref::submit_or_run executes each task exactly once
inside the join window (worker or calling thread - scheduler-internal
capacity handling, not a behavior choice); decode_wavefront action and the
generator sliced-matmul helper are straight-line now.

Finding 4 (detail reach-in): public arena-sizing contract in mimi any.hpp
(prepared/state/workspace/frame_arena_floats); bench + parity runner
migrated off mimi::detail.

Coverage debt closed: new committed operand-class fixtures
mimi-tiny-f16.gguf (f16 convs + RVQ projections) and mimi-tiny-q8.gguf
(dim-32, converter-quantized q8_0 projections) drive the guard_conv_f16 /
guard_proj_q8 / guard_class_q8 rows and their compute paths in tests
(mimi component coverage 66% -> ~90%, detail.cpp 92%).

Also: merge fallout fixes (bench registry 34->35, speech_codec_mimi
reference-lane placeholder records via the sortformer recorded pattern,
per-lane case dump on count mismatch), benchmark markers on the new mimi
sm.hpp files, gcc -Werror class-memaccess sweep in tests (memset on the
non-trivial model::data::vocab replaced with value-init; the encoder test
vocab_builder now reproduces its all-zero contract explicitly).

Verification: full suite 1185/1185; token-exact mimi encode parity vs
moshi.cpp re-verified post-refactor (37/37 frames, decode PSNR 80.7 dB);
bench_snapshot (speech_codec_mimi) and paritychecker lanes green.
The facade pre-validates child requests, so the children's explicit
runtime_unbound / request_shape / buffer_capacity / code_range transitions
only execute when the actors are dispatched directly. Covers the remaining
changed-line clusters flagged by the coverage gate (88.0% -> above the 90%
threshold on the mimi component).
pointwise_conv_hwc and standard_conv_hwc_rect gained a leading
emel::kernel::sm parameter, but the aarch64-only #else blocks in
vision_embedding_lane_tests.cpp still used the old signatures; x86_64
hosts preprocess those blocks away, so the break only shows on arm64.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5ba7093bd7

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/emel/model/moshi/detail.cpp Outdated
Comment thread tools/bench/moshi_gguf_convert.py
bind_rvq_split prepares raw f16 projection copies (prepare_raw_f16)
whenever the f16 conv operand class is selected and the split is not q8,
so an f16-class model with f32 RVQ projections passed the contract's
f32-or-f16 float class and then failed codec initialization. The RVQ
projection probes now require f16 in that configuration. Reproduced
first as a failing test: a fixture with every non-transposed conv
flipped to f16 (selecting the class) and untouched f32 projections
validated pre-fix and now rejects.
Mirrors the contract fix: when the first encoder conv selects the f16
operand class and the RVQ split is not q8, the converter now requires
raw f16 RVQ input/output projections, matching bind_rvq_split's
prepare_raw_f16 requirement. The pinned mimi source still converts in
both classes.

@gabewillen gabewillen left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No actionable findings on the new head commit 447b25160e76c5f1ef5b3659c295c7967167f00b.

Reviewed the range c14ea43ea607cda5d34cfac9ce7747047abb6e65..447b25160e76c5f1ef5b3659c295c7967167f00b after reading AGENTS.md and docs/rules/sml.rules.md. I focused on the new Mimi/Moshi contract probes, converter parity checks, generator streamed-route/raw-record classification, tensor-window completion guards, kernel guard bounds, changed tests, and bench dependency/setup wiring.

Verification performed locally on the PR head:

  • git diff --check c14ea43ea607cda5d34cfac9ce7747047abb6e65..HEAD
  • scripts/check_domain_boundaries.sh

Residual risk: I did not run a fresh compile or targeted test suite in this automation worktree because it has no existing build/ directory; the conclusion is based on source inspection plus the static checks above.

bench_suite_build_dir() returns the unfiltered default tree whenever its
bench_runner is already built: the default binary contains every suite and
run_bench_runner already selects at run time via EMEL_BENCH_SUITE, so
per-suite trees (each cloning and compiling a private llama.cpp reference)
are only justified as a cold-start path on fresh checkouts.
configure_bench_build() never applies a suite filter to the default tree,
which also fixes a latent thrash where a scoped run could filter-reconfigure
the shared tree.
POSIX advisory calls require page-aligned addresses, but the streaming
window advises arbitrary weight extents: on platforms that enforce the
alignment (Linux returns EINVAL) every unaligned hint silently failed.
Read hints (sequential/willneed) now expand outward to page boundaries -
prefetching a little extra is harmless - and the cache-release hint
shrinks inward so only fully covered pages drop and neighbours still in
use never fault (degrading to a successful no-op when no full page is
covered). macOS tolerates unaligned advisory addresses, so the new
unaligned-extent test pins the contract rather than reproducing a
failure on this host.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6cc3afb886

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread tools/bench/moshi_gguf_convert.py Outdated
Comment thread tools/bench/bench_dependency_manifest.cpp
Comment thread tools/bench/bench_dependency_manifest.cpp
gabewillen and others added 3 commits July 4, 2026 09:41
…vq projections

cross_check_mimi runs before quantize_mimi_tensors, and the RVQ
projections are in the quantizable set: with --quantize q8_0 the
source-side f16-RVQ requirement rejected an f16-conv raw file whose
projections are f32 even though the published artifact carries q8_0
projections, a class bind_rvq_split accepts without the raw-f16 copies.
The f16 requirement now applies only when no projection quantization is
pending.
…e codec runtime

The weight-streaming bench constructs emel::io::mmap::sm directly for
its baseline and streaming lanes, and the PersonaPlex-MLX comparison
exercises the maintained codec runtime through the EMEL parity runner:
mmap-only and codec-only changes could each skip the suite that
exercises them. Added src/emel/io/mmap to weight_streaming and the codec
runtime plus mimi_emel_parity_runner.cpp to speech_codec_mimi_mlx (with
the manifest baseline synced).
… on Apple Silicon) (#93)

* kernel: add NEON f16 mul_mat and f32 conv_transpose variants to the aarch64 lane

The aarch64 lane's f16 mul_mat previously fell through to the shared scalar
route (vec_dot_f16_ggml compiles its AVX2 path out on arm64), which was both
the dominant mimi profile cost and the reason the f16 parity case could not
match arm64-built ggml. The new simd_op_mul_mat_f16_vector row ports the
pinned ggml_vec_dot_f16 NEON fp16-arithmetic path exactly (float16x8_t
vfmaq_f16 accumulators, pairwise reduce, f32-product tail into double), so
the route is bit-exact against live ggml on fp16-capable aarch64 hosts.

The f32 conv_transpose_1d scatter kernel (decode upsampling, 39% of the
post-mul-mat mimi profile) gains a NEON variant that is bit-identical to the
shared scalar route as compiled: same per-element accumulation order, fused
multiply-add matching the toolchains' -ffp-contract=on scalar codegen, with
the route test asserting exact equality.

Both variants are explicit guard-routed transition rows with dispatch-count
observability (context counters, sm and kernel::any accessors); the shared
scalar rows keep guard-level mutual exclusion so the route choice is decided
by guards, never row order. Capability-absent hosts keep the scalar routes.

Measured on the real Mimi artifact (Apple Silicon, single-threaded):
encode 183.3 -> 65.0 ms/frame, decode 139.2 -> 71.8 ms/frame; both stages
now meet the 80 ms real-time budget the x86 lane already met.

* parity: scope the f16 mul_mat bit-exact case to the host kernel lane

f16 mul_mat accumulation order is ISA-class-specific (x86 lane: AVX2 f32
accumulators; aarch64 lane: NEON fp16 accumulators) while the live ggml
oracle always computes the host's numerics, so cross-lane runs of this case
compare two implementations that are correct to different contracts and can
never match bit-for-bit. The kernel runner now executes the f16 case only
for the lane matching detect_host_kind() and prints an explicit skip notice
for the foreign lane. With the aarch64 NEON f16 port in place this makes the
kernel parity gate green on arm64 hosts: previously both lanes failed there;
the host lane now matches ggml exactly and the foreign lane is out of the
case's contract on either host type.

* docs: regenerate kernel aarch64 machine docs

Picks up the simd_op_mul_mat_f16_vector and simd_op_conv_transpose_1d_f32
rows; the shared f16/f32 rows now render their named guards instead of
anonymized variant-template placeholders.

* revert: drop quality-gate timing snapshot churn from this branch

Snapshot files are not updated without explicit consent (review feedback);
the gate's local rewrites stay uncommitted.

* review: guard-owned route predicates and machine-driven route tests

- can_use_neon_mul_mat_f16_vector and can_use_neon_conv_transpose_1d_f32
  move from aarch64/actions.hpp into guards.hpp guard::detail (the home of
  route/capability predicates, alongside the packed q4/q6 request
  predicates); the capability probe stays with its dotprod/i8mm siblings
  and the kernels remain in actions.
- the f16 route tests no longer call kernel::detail::run_mul_mat_f16
  directly: the shared-route reference is produced by a second aarch64_sm
  dispatch with a no-NEON context, so the scalar row, guard mutual
  exclusion, and wrapper are exercised on both sides of every comparison.

* kernel: SVE exclusion for the f16 route; compile probe for the conv route

- neon_f16_vector_supported() now rejects __ARM_FEATURE_SVE builds: the
  pinned ggml_vec_dot_f16 selects its SVE branch ahead of the NEON fp16
  branch on such hosts, so this NEON port would not match the reference's
  accumulation order there; the scalar route keeps those hosts correct.
- can_use_neon_conv_transpose_1d_f32 gains a compile-time capability probe
  (neon_conv_transpose_f32_supported): on non-NEON builds a forced
  neon_available context could previously select the route whose kernel
  compiles to a no-op, silently leaving the output zero-filled.

Kernel parity and the full suite re-verified green on this host.

* kernel/parity: mirror the SVE exclusion in test gates and the parity skip

The f16 route test expectations and the host-scoped parity case now key on
the same condition as the production probe: the test #if gates add
!defined(__ARM_FEATURE_SVE), and the parity kernel runner skips the aarch64
f16 case (with an explicit notice) when neon_f16_vector_supported() reports
the route disabled - on SVE builds ggml selects its SVE f16 branch, which
EMEL intentionally does not serve until an SVE port exists.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4edf280e77

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/emel/model/tensor/window/actions.hpp
# Conflicts:
#	snapshots/parity/generation_lfm2_5_230m_q8_0_prompt_hello_max_tokens_1.txt
#	src/emel/kernel/aarch64/guards.hpp
#	tests/kernel/aarch64_tests.cpp

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ad6b803edd

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread scripts/quality_gates.sh
Comment thread tools/bench/mimi_compare.py
The pass decision only checked encode code-match thresholds, so a
decoder returning silence or wrong PCM with the right length passed the
Moshi/MLX comparison on encode tokens alone. --min-decode-psnr-db now
fails the run below a floor when --compare-decode measured a PSNR, with
per-backend defaults calibrated against live healthy lanes on this host:
30 dB for the token-exact moshi.cpp lane (measured 37.0 dB even with the
standing token divergence) and 10 dB for the cross-implementation MLX
lane (measured 21.8 dB, lane passes end-to-end); both are
env-overridable.
A speech_codec_mimi selection fell through to the generic bench path,
which runs codec_mimi_bench with placeholder reference rows only - real
Mimi parity regressions could pass the scoped gate. The suite now routes
through bench_mimi_compare.sh --reference=moshi_cpp like the MLX branch.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 44ea202f5d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/emel/speech/codec/mimi/detail.cpp
Comment thread src/emel/kernel/detail.hpp
Comment thread tools/bench/bench_dependency_manifest.cpp
… at the plan

A q8 projection whose aggregate element count is 32-aligned but whose
contraction width is not (dim, MLP width, or codebook width) bound
successfully and then failed inside the compute loops, which have no
error channel back to the frame publisher - the codec kept publishing
frames. plan_codec now rejects q8 operand classes whose dim, transformer
MLP widths, or codebook width are not QK8_0-aligned. Reproduced first as
a failing test: the dim=16 fixture with every projection flipped to q8_0
initialized successfully pre-fix and now routes bind_failed.
The q8 matvec kernels require block-aligned contraction widths; the
contract now rejects a q8 projection class when dim, a family MLP width,
or codebook_dim is not 32-aligned, mirroring the codec plan gate.
Reproduced first as a failing test on the dim=16 fixture.
can_run_conv_transpose_1d and can_run_im2col accepted metadata-only
destinations; through the modeled dispatch the accepting row's
backend-validity guard already rejected them, but the op guards are now
self-contained for any caller and the null-destination rejections are
pinned by machine-driven tests.
The parity runner loads the enriched artifact through the Moshi
hparam/contract path before codec initialization, so
src/emel/model/moshi changes now select both mimi compare suites
(manifest baseline synced).

@gabewillen gabewillen left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No actionable findings in the new 447b25160e76c5f1ef5b3659c295c7967167f00b..140738f264d6210d071f7b7d9f1e7ec14adf2b5e delta.

Review scope:

  • Read AGENTS.md and docs/rules/sml.rules.md before judging SML/model changes.
  • Inspected the new aarch64 kernel guard/action routes, f16 and conv-transpose optimized rows, matrix-x4 lane guards, mmap advise page-window handling, Moshi/Mimi q8 alignment contracts, Mimi compare gating, quality-gate benchmark routing, and related tests.
  • Verified git diff --check 447b25160e76c5f1ef5b3659c295c7967167f00b..origin/pr/90.
  • Verified scripts/check_domain_boundaries.sh.

Residual risk: I did not run the full build/test/bench suite in this watcher pass, so numeric regressions outside the inspected delta would still need CI/bench coverage.

@gabewillen gabewillen merged commit 627402b into main Jul 4, 2026
1 check passed
@gabewillen gabewillen deleted the worktree-arch64 branch July 4, 2026 23:30
@gabewillen gabewillen restored the worktree-arch64 branch July 4, 2026 23:34
@gabewillen gabewillen deleted the worktree-arch64 branch July 4, 2026 23:34
gabewillen added a commit that referenced this pull request Jul 5, 2026
* docs(roadmap): add v1.27 gap closure phases

Reopen the cooperative async milestone for scheduler error semantics, loader resumability, evidence consistency, and constrained-RAM profiling.

Co-authored-by: Cursor <cursoragent@cursor.com>

* chore(lint): add PR #89/#90/#92 files to clang-format baseline

Regenerated with scripts/lint_snapshot.sh --update (clang-format 21.1.8,
matching the pinned dev-host results). Add-only: 26 new entries, 0 removals.

* docs(planning): define v1.28 Memory-Owned KV Block Addressing Cutover

Source-backed audit: memory::hybrid does real block accounting on the
generate path, but physical K/V addressing is generator-local linear
position math; the captured snapshot is never dereferenced in src/;
sequence_recurrent_slot is unused. v1.28 cuts physical addressing over
to the block map (phases 245-250) with bit-exact single-sequence parity
and component-level multi-sequence proof.

* feat(memory,generator): Phase 245 — memory-owned KV block geometry contract

KVM-01: shared geometry contract in emel::memory::view (DEFAULT_BLOCK_TOKENS,
MAX_BLOCKS, blocks_for_tokens, positions_capacity_for); kv machine constants
and duplicated blocks_for_length collapse onto it; generator backend derives
kv_block_tokens/kv_positions_capacity at prepare and sizes/strides the
physical cache from the block-padded capacity (bit-identical when n_ctx is
block-divisible). Free stack now hands out ascending contiguous block ids so
contiguous logical growth maps to contiguous physical spans (Phase 248
flash-contiguity prerequisite).

KVM-02: new pure guard guard_memory_geometry_fits_backend rejects reserve
pools larger than physical capacity before dispatch (under-provisioned pools
stay valid; exhaustion remains the modeled allocate_slots out_of_memory
route). paritychecker/bench/window-streaming tools now reserve whole blocks
capped at model n_ctx instead of passing token budgets as block counts.

Validation: emel_tests 14/14 (1811 cases), coverage and paritychecker gate
lanes pass; bench_snapshot lane fails due to pre-existing main breakage
(reference-lane ggml SIGBUS + PR #89 suites missing baselines), reproduced on
pristine origin/main — see 245-VALIDATION.md.

* feat(generator): Phase 246 — snapshot addressing coherence guards

KVM-03: the per-step captured memory::view::snapshot is now validated as the
addressing truth before compute phases. guard_snapshot_geometry_coherent and
guard_snapshot_covers_tokens fold into guard_prefill_request_ready
(prompt_token_count) and guard_decode_request_ready (kv_tokens + 1); geometry
drift, inactive sequence, length drift, or missing block mapping fail the
ready predicates and route through the existing explicit invalid transitions.
No parallel token accounting enters machine context.

Validation: emel_tests 14/14 first-run, coverage and parity lanes pass;
bench lane blocked by the pre-existing reference SIGBUS (standing
disposition, 245-VALIDATION.md).

* feat(generator): Phase 247 — block-mapped KV write and scalar-read cutover

KVW-01/KVR-01: physical KV addressing now derives from the captured
memory::view::snapshot. A backend-resident logical->physical position map
(kv_physical_positions, identity after prepare) is rebound per compute
dispatch in bind_guarded_inputs from the snapshot the graph events already
carried; layer_cache_offset and flash_layer_cache_head_position_offset
consume it, cutting over store_attention_kv_cache (both layouts) and the
scalar attention read path in one move. validate_guarded_compute /
validate_guarded_preselected_argmax enforce the snapshot contract (present,
geometry-coherent, active primary sequence) through the processor's modeled
validate-failed routing.

Bit-exact for contiguous single-sequence mappings (identity map); a
reversed-block detail test proves stores and offsets follow the snapshot
rather than the logical position. Hand-built test backends keep the flat
layout via the bounded identity fallback, mirroring the existing offset-table
fallback pattern.

Validation: emel_tests 14/14, paritychecker lane PASS (real-model LFM2.5
generation through the mapped path); bench lane blocked by the pre-existing
reference SIGBUS (standing disposition).

* docs(planning): Phase 247 complete; committed-state gate evidence

* feat(generator): Phase 248 — flash route KV map identity guards

KVR-02: flash attention consumes contiguous strided views rooted at each
layer's cache base, so flash eligibility now additionally requires the
snapshot block map to be the identity over the tokens it reads
(guard_flash_kv_map_identity, pure bounded predicate). Folded into
decode_flash_runtime_supported and prefill flash_runtime_supported; permuted
or offset mappings route to the scalar span-walking path through the existing
explicit non-flash transitions (their complements). No helper-return route
selection. Guard tests cover identity, permuted, and restored mappings for
both routes.

* feat(generator): Phase 249 — recurrent state via snapshot slot

KVS-01: shortconv recurrent state is addressed through the snapshot-resolved
recurrent slot (kv_recurrent_slot, rebound per compute dispatch alongside the
physical map; validate_kv_map_contract requires an assigned slot for the
primary sequence). Slot 0 preserves the flat single-sequence layout
bit-exactly; the cache holds max_sequences (currently 1) slots. Detail tests
cover slot binding, offset shift, and the unassigned-slot validate rejection.

* test(memory,generator): Phase 250 KVP-01 — interleaved multi-sequence proof

Machine-level: interleaved two-sequence growth with disjoint block sets and
distinct recurrent slots; free/reallocate recycles ids LIFO without
disturbing the survivor. Helper-level: two sequences bound from one real
hybrid snapshot yield disjoint physical position sets; reused mappings are
non-identity (the Phase 248 flash guard is load-bearing) and remain disjoint.

KVE-01/KVD-01 closeout remains blocked on the pre-existing bench-lane
breakage (reference ggml SIGBUS + missing PR #89 baselines, chip
task_48a05fc3); see 250-VALIDATION.md.

* docs(planning): v1.28 state — phases 245-249 + KVP-01 done, closeout blocked on bench repair

* fix(gates): guarantee lane evidence on timeout without capping verification

The parallel quality group previously had only the global timeout: a wedged
or starved lane burned the entire budget and the run died with zero lane
logs flushed (observed: a 30-minute silent run with no lane verdicts).

Each lane now runs under timeout(1) via a single-lane re-exec of this script
(EMEL_QUALITY_GATES_LANE) so the whole lane process group can be signalled.
The lane budget is an EVIDENCE GUARANTEE, not a work cap: it is the remaining
global budget minus a 180s flush margin, so no lane ever gets less
verification time than the global timeout already allows — it just fails
loudly (status 124, 'lane timeout' marker, log flushed) instead of being
killed silently, and the surviving lanes still report. Raise
EMEL_QUALITY_GATES_TIMEOUT for legitimately longer runs.

EMEL_QUALITY_GATES_LANE_TIMEOUT exists for hang triage only; it can make the
gate fail faster, never pass with less verification. Lane logs are seeded
with a 'lane start name=... budget=...' line so every lane always reports.

Validated: single-lane dispatch runs parity alone and passes; a 60s triage
override kills bench/coverage at budget with markers and full flush (73s
wall, exit 124); default budgets are the full remaining window (1617s) and a
light run passes identically.

* chore(gates): restore timing.txt to baseline

Five phase commits (245-249) accidentally captured gate-written run
telemetry in snapshots/quality_gates/timing.txt. Per the standing rule
that file is gate-written and must stay uncommitted. Restore it to the
origin/main baseline so this PR is net-zero on it. Branch is already
pushed, so a history rewrite/force-push is avoided in favor of a
forward cleanup commit.

* fix(memory): harden KV block geometry helpers

* fix(text): harden KV snapshot dispatch contracts

* fix(text): preserve KV reuse contracts across reinit

* fix(graph): harden KV execute addressing contracts

* docs(planning): refresh v1.28 closeout handoff

* bench: refresh PR 94 performance snapshots

* bench: clarify snapshot provenance

* fix: resolve PR 94 review feedback

* fix: address PR 94 review comments

* Fix PR 94 KV review regressions

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants