Goal: see the actual physical machine before simplifying it. "What connects to what" at the file/module level, where the complexity piled up, and where it can be cut. Source:
airframeworkspace clone atsideline/v0.2.8-base, branchspike/206-…. This is a MAP only — no changes yet.
┌──────────────────────────────────────────────────────────────────────────┐
│ BINARIES src/bin/* │
│ shimmy_server_gpu (+server_inference) · shimmy_eval · layer_dump_gpu · │
│ quant_verify · frontier_compare · cert_check · probe_tokens · │
│ vault_generator · vault_seed · window_boundary_probe │
└───────────────┬───────────────────────────────┬───────────────────────────┘
│ server drives pipeline DIRECT │ other bins call GpuRuntime
▼ ▼
┌────────────────────────────┐ ┌──────────────────────────────────────┐
│ backend/bindless/pipeline/* │◄───────│ runtime/gpu.rs (GpuRuntime) │
│ dequant · inference · layer│ uses │ load() · generate() · generate_isf() │
│ · matmul · mod(layouts) │ pipeline│ runtime/engine.rs (Engine facade) │
│ run_full_model_…_with_state│ └───────────────┬──────────────────────┘
└───────────────┬────────────┘ │ (generate_isf only)
│ binds ▼
┌────────────────────────────┐ ┌──────────────────────────────────────┐
│ BindlessModel (loader.rs) │ │ airframe_observe crate │
│ ONE gpu_buffer + N sub- │ │ isf = Inference Saturation Fabric │
│ range blob bindings │ │ facts · observer · output · plan · │
│ + BindlessMetadata │ │ session · internal/tdr │
└───────────────┬────────────┘ └──────────────────────────────────────┘
│ reads GGUF
▼
┌─────────────────┐ ┌──────────────────┐ ┌──────────────┐ ┌──────────────┐
│ core/model.rs │ │ core/dequant/* │ │ core/spec.rs │ │ core/ggml_ │
│ GgufTensorInfo │ │ q4_0 q4_k q5_0 │ │ ModelSpec │ │ types.rs │
│ core/weight_id │ │ q5_k q6_k q8_0 │ │ │ │ core/tensor │
└─────────────────┘ └──────────────────┘ └──────────────┘ └──────────────┘
CONTROL PLANE (per-token intervention) — control.rs defines the trait:
InferenceControl trait + InferenceEvent + ControlDecision
├─ fse_control.rs → libfse Aho-Corasick scan (uses libfse crate)
├─ math_bypass_control.rs→ arithmetic bypass
└─ schoolmarm_control.rs → grammar constraint (uses schoolmarm)
TWO FABRICS (different things — easy to conflate):
• libfse crate = low-level FSE trie / DFA scanner (TEXT rules)
• airframe_observe::isf = Inference Saturation Fabric (reactive inference graph)
TWO VERIFICATION SUBSYSTEMS:
• validation/* (artifacts · errors · evidence · projection · slice_validator)
• conformance/* (diff · fixtures)
OBSERVE ("rank the numbers"): airframe_observe — facts/observer/output/plan/session
GGUF file on disk
│ BindlessMetadata::new() reads tensor offsets / data_start
▼
BindlessModel::load_from_disk()
│ device.create_buffer(ONE gpu_buffer = full file size)
│ + N sub-range blob bindings (blob_0..blob_N) ← THE 206 BUG LIVES HERE
▼
GpuRuntime::load()
│ builds KVCache, dequants output head → output_head_f32, tokenizer, ModelSpec
│
├─ generate() [imperative loop]
│ embed dequant → prefill chunked → decode loop → sampling
│ └─ each step: InferenceControl.intervene(event) ← fse / math / schoolmarm
│
└─ generate_isf() [reactive]
ISFState + InferenceFacts → airframe_observe::isf::InferenceSaturationFabric
.run_to_fixpoint() (wraps the SAME pipeline calls as generate)
SHIMMY SERVER (the live product path) BYPASSES GpuRuntime entirely:
server_inference.rs → pipeline.run_full_model_prefill_chunked_with_cache_state() DIRECT
+ libfse metrics / text scan
(no GpuRuntime, no generate_isf — it drives the bindless pipeline straight)
| # | Duplication / pile-up | Where | Note |
|---|---|---|---|
| 1 | Two inference orchestrators in the facade | gpu.rs::generate (imperative) vs gpu.rs::generate_isf (reactive) |
same pipeline, two control styles stacked |
| 2 | Server bypasses the facade | server_inference.rs calls pipeline.* directly, not GpuRuntime |
3rd live entry path (facade / engine / direct) |
| 3 | Two "fabric" libraries | libfse (text DFA) vs airframe_observe::isf (inference graph) |
confusable names; different jobs, but both called "fabric" |
| 4 | Two verification subsystems | validation/* vs conformance/* |
overlapping intent, separate trees |
| 5 | backend top-level vs backend/bindless | backend/pipeline.rs, backend/wgpu.rs, backend/tdr.rs sit beside backend/bindless/ |
likely legacy/alt path beside the real bindless engine — needs confirmation |
| 6 | Four control modules | control.rs (trait) + 3 impls |
trait is clean; spread across 4 files |
| 7 | Many diagnostic binaries | 9+ src/bin/* tools |
overlapping verification intent (layer_dump, quant_verify, frontier_compare, cert_check…) |
| 8 | The blob hack (206) | loader.rs 3 hardcoded sub-range bindings, remainder dumped in blob_2 |
the symptom this whole spike started from |
control.rsInferenceControl trait — a genuine, small control-plane abstraction. Plug-inInferenceControlimplementors (fse_control,math_bypass,schoolmarm) intervene per token. This is the "deliberate control plane" idea, realized as a trait.airframe_observe— the "rank the numbers from the GGUF" crate:facts+observerisfseparation is coherent; it is the verification/observability layer done right.
core/dequant/*— one module per quant type, no cross-talk. Clean.- Single data model: tensors are absolute byte offsets in ONE buffer; chunking is a binding-layer concern only, so metadata/spec never move. (This is why the multi-buffer strategy from the spike discussion is low-risk to the data model.)
-
Unify the inference entry point. Make
shimmy_server_gpugo throughGpuRuntime(or makeGpuRuntimethe only facade) instead of drivingpipeline.*directly. Kills duplication #2 and collapses #1 toward one path. Biggest single win. -
Disambiguate the two fabrics by role, not name.
libfse= text/rule scanning DFA → keep forfse_control+ server text scan.airframe_observe::isf= inference orchestration graph → keep forgenerate_isf. Document the boundary so future work stops conflating them. (No code move needed yet — just a Written-Down contract.)
-
Resolve the blob design at the load layer (the earlier "multiple real buffers" strategy): split the model into N independent
wgpu::Buffers atload_from_disk, each ≤effective_chunk. Removes the single-buffermax_buffer_sizerisk AND the tail-alignment fragility. Supersedes the sub-range hack cleanly. -
Confirm & prune
backend/*top-level vsbackend/bindless/*. If the top-levelpipeline.rs/wgpu.rs/tdr.rsare dead/legacy, retire them so there is ONE engine. -
Consolidate
validation/*+conformance/*if their intent overlaps (verify first). One verification tree, not two. -
The "control plane for reading GGUFs" you remember may never have been built. What exists is
BindlessMetadata/loader.rs(read+upload) — no higher-level strategy layer for load/chunk decisions. If you want a deliberate load-strategy module (probe adapter → decide chunking → load), that is a NEW small module, not a refactor of what's there. The multi-buffer strategy (#3) is the first cut of it.
Q1: Is generate_isf wired?
Answer: NO. Zero callers found. generate_isf() is defined in gpu.rs but never invoked by any bin or server. It is currently ORPHANED code despite being declared "production path" in public changelog. This is a critical gap.
Q2: Are top-level backend/pipeline.rs, backend/wgpu.rs, backend/tdr.rs live?
Answer: LEGACY/TEST ONLY. Only referenced in backend/tests.rs (LogitMaskPipeline, WgpuContext). Not used by production bindless path. Safe to retire or fold into test utilities.
Q3: What is runtime/engine.rs role?
Answer: CPU inference engine facade. Used by shimmy_eval.rs (benchmarks evals against CPU vs GPU). Contains Engine::new(model) + tests. Separate from GpuRuntime. Role: CPU reference implementation for parity testing. Keep, but don't promote as primary facade.
Q4: Do validation/* and conformance/* overlap?
Answer: Both active, different purposes. validation/* used by core/error.rs, runtime/multi_token_engine.rs, validation/artifacts.rs, slice_validator.rs. conformance/* used by diff.rs, fixtures.rs. Validation = error/evidence/projection; Conformance = diff/fixtures/parity. They complement rather than duplicate. Defer consolidation.
A second independent review confirms the map and adds a dependency-ordered execution plan:
-
Fix the load layer first (the 206 root)
Make multi-buffer strategy real atBindlessModel::load_from_disk. Split into N independentwgpu::Buffers, each ≤ effective chunk size. Removes single-buffermax_buffer_sizerisk + tail-alignment fragility. This is the highest-leverage structural change. -
Unify inference entry points (kill the three-path Rube Goldberg)
Force product path through the facade:- Make
GpuRuntimethe only public way to run inference. - Change
server_inference.rsto go throughgenerate_isf(not direct pipeline calls). - Since
generate_isfis currently ORPHANED (Q1), wire it up first, prove parity, then retire imperativegenerate.
- Make
-
Disambiguate the two fabrics permanently
Write a one-page boundary contract doc:libfse= low-level text/rule DFA scanner (keep forfse_control+ server text scan).airframe_observe::isf= Inference Saturation Fabric (reactive graph). Keep forgenerate_isf. No code move needed yet — just stop the name collision.
-
Confirm and prune obvious dead/legacy surface
- Retire top-level
backend/pipeline.rs,backend/wgpu.rs,backend/tdr.rs(Q2 confirmed legacy). - Leave
runtime/engine.rsalone (Q3 confirmed: CPU reference, keep for parity testing). - DO NOT touch
validation/*+conformance/*yet (Q4: they complement; deleting verification early creates ghosts). - Leave diagnostic binary zoo alone until core paths unified.
- Retire top-level
-
Only after the above
- Consolidate verification trees if overlap is proven.
- Thin the 9+ diagnostic binaries.
- The "control plane for reading GGUFs" can emerge as a small load-strategy module on top of the now-clean multi-buffer loader.
Why this order: Load → orchestration → product integration → cleanup respects the dependency graph. You attack accumulation (three entry points + blob hack) before polishing clean parts. Resulting shape: clean data model + one load strategy + one inference facade + explicit control plane + explicit observe fabric. Lowest long-term debt surface.
The machine is not uniformly garbage — the control trait, the observe crate, and the dequant tree are deliberate and clean. The Rube Goldberg-ness is accumulation: three inference entry paths, two fabrics with confusingly similar names, two verification subtrees, a likely-legacy backend layer, and a 3-binding blob hack bolted onto a single giant buffer. The highest-leverage simplifications are (1) one inference entry point and (2) moving the chunk decision up into the load layer as N real buffers. Both shrink the surface area without touching the clean parts.