Skip to main content

memra_cli/
lib.rs

1use memra_gguf::config::{HfConfig, ModelConfig};
2use memra_gguf::model_packs::{self, Gate, ModelPack, TokenizerSource};
3use memra_gguf::safetensors::{
4    StInfo, StModel, parse_header_json_checked, parse_index_weight_map_json_checked,
5};
6use memra_gguf::tensor_contract::{
7    CheckpointDialect, ContractOptions, FloatType, IntegerType, OutputHead, QuantLayout,
8    StorageLayout, TensorCensusEntry,
9};
10use memra_gguf::{GgmlType, GgufFile};
11use memra_reference::{deterministic_fixture, execute, execute_multimodal, execute_vision};
12use sha2::{Digest, Sha256};
13use std::collections::{BTreeMap, BTreeSet};
14use std::fmt::Write as _;
15use std::io::Write as _;
16use std::path::{Path, PathBuf};
17use std::process::{Command, Output, Stdio};
18
19const MAX_TEXT_BYTES: usize = 100_000_000;
20
21pub struct InspectRequest {
22    pub source: String,
23    pub against: String,
24    pub out_dir: PathBuf,
25}
26
27pub struct InspectSummary {
28    pub family: &'static str,
29    pub tensor_count: usize,
30    pub out_dir: PathBuf,
31}
32
33pub struct ScaffoldRequest {
34    pub family: String,
35    pub out_dir: PathBuf,
36}
37
38#[derive(Debug, Clone, Copy, PartialEq, Eq)]
39pub enum VerifyStage {
40    Config,
41    Tiny,
42    Checkpoint,
43    Rewrite,
44    Serve,
45}
46
47pub struct VerifyRequest {
48    pub stage: VerifyStage,
49    pub source: String,
50    pub against: String,
51    pub out_dir: Option<PathBuf>,
52    pub oracle: Option<PathBuf>,
53    pub native_runner: Option<PathBuf>,
54}
55
56pub struct VerifySummary {
57    pub family: &'static str,
58    pub stage: VerifyStage,
59}
60
61pub fn verify_model(request: VerifyRequest) -> Result<VerifySummary, Box<dyn std::error::Error>> {
62    match request.stage {
63        VerifyStage::Config => {
64            let pack = model_packs::by_alias(&request.against)
65                .ok_or_else(|| format!("unknown model pack {:?}", request.against))?;
66            let config = load_config_only(&request.source)?;
67            pack.compile_plan(&config)?;
68            Ok(VerifySummary {
69                family: pack.family,
70                stage: VerifyStage::Config,
71            })
72        }
73        VerifyStage::Checkpoint => {
74            let pack = model_packs::by_alias(&request.against)
75                .ok_or_else(|| format!("unknown model pack {:?}", request.against))?;
76            let out_dir = request.out_dir.ok_or("verify checkpoint requires --out")?;
77            let summary = inspect_model(InspectRequest {
78                source: request.source.clone(),
79                against: request.against.clone(),
80                out_dir: out_dir.clone(),
81            })?;
82            write_hf_oracle_bundle(&request.source, &out_dir)?;
83            let gate = pack.checkpoint_parity.ok_or_else(|| {
84                format!(
85                    "model pack {} has no checkpoint parity threshold; capture bundle written to {} and no fallback is allowed",
86                    pack.family,
87                    out_dir.display()
88                )
89            })?;
90            let oracle_path = request.oracle.ok_or_else(|| {
91                format!(
92                    "checkpoint tensor contract passed; run {} offline, then repeat with --oracle <hf-oracle.tsv>; no fallback is allowed",
93                    out_dir.join("capture-hf-oracle.py").display()
94                )
95            })?;
96            let runner = request
97                .native_runner
98                .or_else(|| std::env::var_os("MEMRA_NATIVE_CHECKPOINT_RUNNER").map(PathBuf::from))
99                .ok_or("checkpoint parity requires --native-runner or MEMRA_NATIVE_CHECKPOINT_RUNNER; no fallback is allowed")?;
100            let native_path = out_dir.join("native-oracle.tsv");
101            run_native_checkpoint(&runner, &request.source, &native_path)?;
102            let runner_hash = hex_sha256(&std::fs::read(&runner)?);
103            let expected = parse_checkpoint_oracle(&std::fs::read_to_string(&oracle_path)?)?;
104            let actual = parse_checkpoint_oracle(&std::fs::read_to_string(&native_path)?)?;
105            let receipt = match compare_checkpoint_oracles(&expected, &actual, gate) {
106                Ok(receipt) => receipt,
107                Err(error) => {
108                    write_atomic(
109                        &out_dir.join("checkpoint-parity.tsv"),
110                        format!(
111                            "status\tfailed\nerror\t{}\n",
112                            lock_value(&error.to_string())
113                        )
114                        .as_bytes(),
115                    )?;
116                    write_atomic(
117                        &out_dir.join("gates.txt"),
118                        format_gate_results_with_receipts(
119                            pack,
120                            &out_dir,
121                            &[Gate::Config, Gate::TokenizerTemplate, Gate::TensorCensus],
122                            &[Gate::CheckpointParity],
123                        )
124                        .as_bytes(),
125                    )?;
126                    return Err(error);
127                }
128            };
129            let artifact_lock = std::fs::read(out_dir.join("artifact.lock"))?;
130            let receipt = format!(
131                "{receipt}artifact_lock_sha256\t{}\nnative_runner_sha256\t{runner_hash}\n",
132                hex_sha256(&artifact_lock)
133            );
134            write_atomic(&out_dir.join("checkpoint-parity.tsv"), receipt.as_bytes())?;
135            write_atomic(
136                &out_dir.join("gates.txt"),
137                format_gate_results_with_receipts(
138                    pack,
139                    &out_dir,
140                    &[
141                        Gate::Config,
142                        Gate::TokenizerTemplate,
143                        Gate::TensorCensus,
144                        Gate::CheckpointParity,
145                    ],
146                    &[],
147                )
148                .as_bytes(),
149            )?;
150            Ok(VerifySummary {
151                family: summary.family,
152                stage: VerifyStage::Checkpoint,
153            })
154        }
155        VerifyStage::Tiny => {
156            let pack = model_packs::by_alias(&request.against)
157                .ok_or_else(|| format!("unknown model pack {:?}", request.against))?;
158            if pack.support.is_none() {
159                return Err(format!(
160                    "model pack {} is inspect-only and has no native support state",
161                    pack.family
162                )
163                .into());
164            }
165            let out_dir = request.out_dir.ok_or("verify tiny requires --out")?;
166            let plan = pack.compile_tiny_plan()?;
167            let fixture = deterministic_fixture(&plan)?;
168            let first = execute(&plan, &fixture.weights, &fixture.token_ids)?;
169            let second = execute(&plan, &fixture.weights, &fixture.token_ids)?;
170            if first != second {
171                return Err("native reference fixture is not bit-deterministic".into());
172            }
173            let vision = fixture
174                .vision
175                .as_ref()
176                .map(|input| {
177                    let first = execute_vision(&plan, &fixture.weights, input)?;
178                    let second = execute_vision(&plan, &fixture.weights, input)?;
179                    if first != second {
180                        return Err(ReferenceVisionError::Nondeterministic);
181                    }
182                    Ok(first)
183                })
184                .transpose()
185                .map_err(|error| -> Box<dyn std::error::Error> { error.into() })?;
186            let multimodal = match (
187                fixture.multimodal_token_ids.as_ref(),
188                fixture.vision.as_ref(),
189            ) {
190                (Some(token_ids), Some(input)) => {
191                    let first = execute_multimodal(&plan, &fixture.weights, token_ids, input)?;
192                    let second = execute_multimodal(&plan, &fixture.weights, token_ids, input)?;
193                    if first != second {
194                        return Err(
195                            "native multimodal reference fixture is not bit-deterministic".into(),
196                        );
197                    }
198                    Some(first)
199                }
200                (None, None) | (None, Some(_)) if plan.multimodal.is_none() => None,
201                _ => {
202                    return Err(
203                        "multimodal plan is missing its combined tiny fixture inputs".into(),
204                    );
205                }
206            };
207            std::fs::create_dir_all(&out_dir)?;
208            write_atomic(
209                &out_dir.join("tiny-fixture.txt"),
210                format_tiny_fixture(&plan, &fixture).as_bytes(),
211            )?;
212            write_atomic(
213                &out_dir.join("reference-oracle.tsv"),
214                format_reference_oracle(&first).as_bytes(),
215            )?;
216            if let Some(vision) = vision.as_ref() {
217                write_atomic(
218                    &out_dir.join("reference-vision-oracle.tsv"),
219                    format_reference_vision_oracle(vision).as_bytes(),
220                )?;
221            }
222            if let Some(multimodal) = multimodal.as_ref() {
223                write_atomic(
224                    &out_dir.join("reference-multimodal-oracle.tsv"),
225                    format_reference_oracle(&multimodal.language).as_bytes(),
226                )?;
227            }
228            write_atomic(
229                &out_dir.join("tiny-gate.tsv"),
230                format!("status\tpassed\nfamily\t{}\n", pack.family).as_bytes(),
231            )?;
232            write_atomic(
233                &out_dir.join("gates.txt"),
234                format_gate_results_with_receipts(
235                    pack,
236                    &out_dir,
237                    &[Gate::Config, Gate::TinyParity],
238                    &[],
239                )
240                .as_bytes(),
241            )?;
242            Ok(VerifySummary {
243                family: pack.family,
244                stage: VerifyStage::Tiny,
245            })
246        }
247        VerifyStage::Rewrite => {
248            let pack = model_packs::by_alias(&request.against)
249                .ok_or_else(|| format!("unknown model pack {:?}", request.against))?;
250            let out_dir = request
251                .out_dir
252                .ok_or("verify rewrite requires --out; no fallback is allowed")?;
253            verify_rewrite_receipt(pack, Path::new(&request.source), &out_dir)?;
254            Ok(VerifySummary {
255                family: pack.family,
256                stage: VerifyStage::Rewrite,
257            })
258        }
259        VerifyStage::Serve => {
260            let pack = model_packs::by_alias(&request.against)
261                .ok_or_else(|| format!("unknown model pack {:?}", request.against))?;
262            let out_dir = request
263                .out_dir
264                .ok_or("verify serve requires --out; no fallback is allowed")?;
265            let runner = request
266                .native_runner
267                .or_else(|| std::env::var_os("MEMRA_NATIVE_SERVE_RUNNER").map(PathBuf::from))
268                .ok_or("verify serve requires --native-runner or MEMRA_NATIVE_SERVE_RUNNER; no fallback is allowed")?;
269            verify_native_serve(pack, &request.source, &out_dir, &runner)?;
270            Ok(VerifySummary {
271                family: pack.family,
272                stage: VerifyStage::Serve,
273            })
274        }
275    }
276}
277
278fn verify_rewrite_receipt(
279    pack: &ModelPack,
280    receipt_path: &Path,
281    out_dir: &Path,
282) -> Result<(), Box<dyn std::error::Error>> {
283    let artifact_lock = std::fs::read_to_string(out_dir.join("artifact.lock"))?;
284    let artifact_lock_sha256 = hex_sha256(artifact_lock.as_bytes());
285    if !artifact_lock
286        .lines()
287        .any(|line| line == format!("family={}", pack.family))
288    {
289        return Err("rewrite receipt family does not match artifact.lock".into());
290    }
291    let manifest = std::fs::read_to_string(out_dir.join("execution-rewrites.tsv"))?;
292    let receipt = std::fs::read_to_string(receipt_path)?;
293    let mut fields = BTreeMap::new();
294    for line in receipt.lines() {
295        let Some((key, value)) = line.split_once('\t') else {
296            return Err(format!("malformed rewrite receipt line {line:?}").into());
297        };
298        if fields.insert(key, value).is_some() {
299            return Err(format!("duplicate rewrite receipt field {key}").into());
300        }
301    }
302    for (key, expected) in [
303        ("format", "memra-rewrite-parity-v1"),
304        ("status", "passed"),
305        ("first_violation", "none"),
306    ] {
307        if fields.get(key).copied() != Some(expected) {
308            return Err(format!("rewrite receipt requires {key}={expected}").into());
309        }
310    }
311    match fields.get("value_kind").copied() {
312        Some("logits-f32") if fields.get("require_argmax").copied() == Some("true") => {}
313        Some("token-ids-u32") if fields.get("require_argmax").copied() == Some("false") => {}
314        _ => return Err("rewrite receipt has an invalid value_kind/argmax policy".into()),
315    }
316    let rewrite_id = *fields.get("rewrite").ok_or("rewrite receipt has no id")?;
317    let row = manifest
318        .lines()
319        .skip(1)
320        .find(|line| line.split('\t').next() == Some(rewrite_id))
321        .ok_or_else(|| format!("rewrite {rewrite_id} is absent from execution manifest"))?;
322    let columns: Vec<_> = row.split('\t').collect();
323    if columns.len() != 8 || columns[4] != "true" {
324        return Err(format!("rewrite {rewrite_id} is not eligible in this artifact").into());
325    }
326    for (field, expected) in [
327        ("surface", columns[1]),
328        ("implementation", columns[2]),
329        ("plan_sha256", columns[3]),
330    ] {
331        if fields.get(field).copied() != Some(expected) {
332            return Err(format!("rewrite receipt {field} does not match manifest").into());
333        }
334    }
335    if fields.get("artifact_lock_sha256").copied() != Some(artifact_lock_sha256.as_str()) {
336        return Err("rewrite receipt does not match artifact.lock".into());
337    }
338    let reference = fields
339        .get("reference_sha256")
340        .ok_or("rewrite receipt has no reference hash")?;
341    let candidate = fields
342        .get("candidate_sha256")
343        .ok_or("rewrite receipt has no candidate hash")?;
344    let parse_nonnegative = |field: &str| -> Result<f32, Box<dyn std::error::Error>> {
345        let value = fields
346            .get(field)
347            .ok_or_else(|| format!("rewrite receipt has no {field}"))?
348            .parse::<f32>()?;
349        if !value.is_finite() || value < 0.0 {
350            return Err(format!("rewrite receipt {field} is not finite and nonnegative").into());
351        }
352        Ok(value)
353    };
354    let atol = parse_nonnegative("atol")?;
355    let rtol = parse_nonnegative("rtol")?;
356    let max_abs = parse_nonnegative("max_abs")?;
357    let _max_rel = parse_nonnegative("max_rel")?;
358    if atol == 0.0 && rtol == 0.0 && (max_abs != 0.0 || reference != candidate) {
359        return Err("exact rewrite receipt has nonzero error or different stream hashes".into());
360    }
361    for field in [
362        "implementation_sha256",
363        "reference_sha256",
364        "candidate_sha256",
365    ] {
366        let value = fields[field];
367        if value.len() != 64
368            || !value
369                .bytes()
370                .all(|byte| byte.is_ascii_digit() || (b'a'..=b'f').contains(&byte))
371        {
372            return Err(format!("rewrite receipt {field} is not a lowercase SHA-256").into());
373        }
374    }
375    if fields
376        .get("values")
377        .and_then(|value| value.parse::<usize>().ok())
378        .is_none_or(|values| values == 0)
379    {
380        return Err("rewrite receipt compared no values".into());
381    }
382    let receipt_hash = hex_sha256(receipt.as_bytes());
383    let receipt_dir = out_dir.join("rewrite-receipts");
384    std::fs::create_dir_all(&receipt_dir)?;
385    write_atomic(
386        &receipt_dir.join(format!("{rewrite_id}.tsv")),
387        receipt.as_bytes(),
388    )?;
389    let index_path = out_dir.join("rewrite-receipts.tsv");
390    let mut index = BTreeMap::new();
391    if let Ok(existing) = std::fs::read_to_string(&index_path) {
392        for line in existing.lines().skip(1) {
393            let columns: Vec<_> = line.split('\t').collect();
394            if columns.len() == 4 {
395                index.insert(
396                    columns[0].to_string(),
397                    (
398                        columns[1].to_string(),
399                        columns[2].to_string(),
400                        columns[3].to_string(),
401                    ),
402                );
403            }
404        }
405    }
406    index.insert(
407        rewrite_id.to_string(),
408        (columns[3].to_string(), receipt_hash, "passed".to_string()),
409    );
410    let mut index_text = String::from("rewrite\tplan_sha256\treceipt_sha256\tstatus\n");
411    for (rewrite, (plan, hash, status)) in index {
412        writeln!(index_text, "{rewrite}\t{plan}\t{hash}\t{status}").unwrap();
413    }
414    write_atomic(&index_path, index_text.as_bytes())?;
415    write_atomic(
416        &out_dir.join("gates.txt"),
417        format_gate_results_with_receipts(pack, out_dir, &[], &[]).as_bytes(),
418    )?;
419    Ok(())
420}
421
422fn verify_native_serve(
423    pack: &ModelPack,
424    source: &str,
425    out_dir: &Path,
426    runner: &Path,
427) -> Result<(), Box<dyn std::error::Error>> {
428    if !Path::new(source).exists() {
429        return Err("verify serve requires a local model artifact; no fallback is allowed".into());
430    }
431    let checkpoint_receipt = out_dir.join("checkpoint-parity.tsv");
432    let artifact_lock_path = out_dir.join("artifact.lock");
433    let artifact_lock = std::fs::read_to_string(&artifact_lock_path).map_err(|error| {
434        format!(
435            "verify serve requires {} from inspect/checkpoint first: {error}; no fallback is allowed",
436            artifact_lock_path.display()
437        )
438    })?;
439    if !artifact_lock
440        .lines()
441        .any(|line| line == format!("source={}", lock_value(source)))
442        || !artifact_lock.lines().any(|line| line == "binding=passed")
443        || !artifact_lock.lines().any(|line| line == "tokenizer=passed")
444    {
445        return Err(
446            "verify serve artifact.lock does not match this source with binding/tokenizer passed; no fallback is allowed"
447                .into(),
448        );
449    }
450    let checkpoint = std::fs::read_to_string(&checkpoint_receipt).map_err(|error| {
451        format!(
452            "verify serve requires a passed {} first: {error}; no fallback is allowed",
453            checkpoint_receipt.display()
454        )
455    })?;
456    if !checkpoint.lines().any(|line| line == "status\tpassed") {
457        return Err(
458            "verify serve requires status=passed checkpoint parity; no fallback is allowed".into(),
459        );
460    }
461    let lock_hash = hex_sha256(artifact_lock.as_bytes());
462    if !checkpoint
463        .lines()
464        .any(|line| line == format!("artifact_lock_sha256\t{lock_hash}"))
465    {
466        return Err(
467            "verify serve checkpoint receipt does not match artifact.lock; no fallback is allowed"
468                .into(),
469        );
470    }
471    std::fs::create_dir_all(out_dir)?;
472    let listener = std::net::TcpListener::bind("127.0.0.1:0")?;
473    let port = listener.local_addr()?.port();
474    drop(listener);
475    let address = format!("127.0.0.1:{port}");
476    let api_key = "memra-onboarding-verify";
477    let log_path = out_dir.join("serve.log");
478    let log = std::fs::File::create(&log_path)?;
479    let mut child = Command::new(runner)
480        .env("MEMRA_MODELS", format!("verify={source}"))
481        .env("MEMRA_REWRITE_BUNDLE", out_dir)
482        .env("MEMRA_ADDR", &address)
483        .env("MEMRA_API_KEY", api_key)
484        .stdin(Stdio::null())
485        .stdout(Stdio::from(log.try_clone()?))
486        .stderr(Stdio::from(log))
487        .spawn()?;
488    let result = (|| -> Result<String, Box<dyn std::error::Error>> {
489        let timeout = std::env::var("MEMRA_SERVE_VERIFY_TIMEOUT_S")
490            .ok()
491            .and_then(|value| value.parse::<u64>().ok())
492            .unwrap_or(180);
493        let started = std::time::Instant::now();
494        loop {
495            if let Some(status) = child.try_wait()? {
496                return Err(format!(
497                    "native server exited before readiness with {status}; inspect {}",
498                    log_path.display()
499                )
500                .into());
501            }
502            let ready = Command::new("curl")
503                .args([
504                    "--fail",
505                    "--silent",
506                    "--output",
507                    "/dev/null",
508                    &format!("http://{address}/readyz"),
509                ])
510                .status();
511            if ready.is_ok_and(|status| status.success()) {
512                break;
513            }
514            if started.elapsed() >= std::time::Duration::from_secs(timeout) {
515                return Err(format!(
516                    "native server did not become ready within {timeout}s; inspect {}",
517                    log_path.display()
518                )
519                .into());
520            }
521            std::thread::sleep(std::time::Duration::from_millis(250));
522        }
523        let response = Command::new("curl")
524            .args([
525                "--fail",
526                "--silent",
527                "--show-error",
528                "--header",
529                &format!("Authorization: Bearer {api_key}"),
530                "--header",
531                "Content-Type: application/json",
532                "--data",
533                r#"{"model":"verify","prompt":"Hello","max_tokens":1,"temperature":0}"#,
534                &format!("http://{address}/v1/completions"),
535            ])
536            .output()?;
537        if !response.status.success() {
538            return Err(format!(
539                "native completion failed with {}: {}",
540                response.status,
541                String::from_utf8_lossy(&response.stderr)
542            )
543            .into());
544        }
545        let response = String::from_utf8(response.stdout)?;
546        if !response.contains("\"choices\"") || response.contains("\"error\"") {
547            return Err(format!("native completion response is not successful: {response}").into());
548        }
549        Ok(response)
550    })();
551    let _ = child.kill();
552    let _ = child.wait();
553    let response = result?;
554    let runner_hash = hex_sha256(&std::fs::read(runner)?);
555    write_atomic(&out_dir.join("serve-response.json"), response.as_bytes())?;
556    write_atomic(
557        &out_dir.join("serve-gate.tsv"),
558        format!(
559            "status\tpassed\nfamily\t{}\nmodel\tverify\nendpoint\t/v1/completions\nartifact_lock_sha256\t{lock_hash}\nnative_runner_sha256\t{runner_hash}\n",
560            pack.family,
561        )
562        .as_bytes(),
563    )?;
564    write_atomic(
565        &out_dir.join("gates.txt"),
566        format_gate_results_with_receipts(
567            pack,
568            out_dir,
569            &[
570                Gate::Config,
571                Gate::TokenizerTemplate,
572                Gate::TensorCensus,
573                Gate::CheckpointParity,
574                Gate::Serve,
575            ],
576            &[],
577        )
578        .as_bytes(),
579    )?;
580    Ok(())
581}
582
583#[derive(Debug, Clone, PartialEq)]
584struct CheckpointOracle {
585    engine: String,
586    numeric_class: String,
587    tokens: Vec<u32>,
588    vocab: usize,
589    logits: Vec<f32>,
590}
591
592fn write_hf_oracle_bundle(source: &str, out_dir: &Path) -> Result<(), Box<dyn std::error::Error>> {
593    let tokens = [1u32, 2, 3, 4];
594    let (model, revision) = if Path::new(source).exists() {
595        (source.to_string(), None)
596    } else {
597        let (model, revision) = parse_pinned_hf_source(source)?;
598        (model.to_string(), Some(revision.to_string()))
599    };
600    let request = format!(
601        "format\tmemra-checkpoint-request-v1\nsource\t{}\nrevision\t{}\nnumeric_class\tsource-weights-float32-accumulation\ntokens\t{}\n",
602        lock_value(&model),
603        revision.as_deref().unwrap_or("local"),
604        tokens
605            .iter()
606            .map(u32::to_string)
607            .collect::<Vec<_>>()
608            .join(",")
609    );
610    write_atomic(&out_dir.join("oracle-request.tsv"), request.as_bytes())?;
611    let model_literal = format!("{model:?}");
612    let revision_literal = revision
613        .as_ref()
614        .map(|revision| format!("{revision:?}"))
615        .unwrap_or_else(|| "None".to_string());
616    let script = format!(
617        r#"#!/usr/bin/env python3
618import argparse
619import struct
620import torch
621import transformers
622from transformers import AutoModelForCausalLM
623
624MODEL = {model_literal}
625REVISION = {revision_literal}
626TOKENS = [1, 2, 3, 4]
627
628parser = argparse.ArgumentParser(description="Offline HF correctness oracle for Memra onboarding")
629parser.add_argument("--out", default="hf-oracle.tsv")
630args = parser.parse_args()
631
632model = AutoModelForCausalLM.from_pretrained(
633    MODEL,
634    revision=REVISION,
635    dtype=torch.float32,
636    trust_remote_code=False,
637)
638device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
639model = model.to(device).eval()
640with torch.no_grad():
641    logits = model(input_ids=torch.tensor([TOKENS], device=device)).logits[0, -1].float().cpu()
642
643with open(args.out, "w", encoding="utf-8") as f:
644    f.write("format\tmemra-checkpoint-oracle-v1\n")
645    f.write("engine\thf-transformers-fp32\n")
646    f.write("numeric_class\tsource-weights-float32-accumulation\n")
647    f.write(f"transformers_version\t{{transformers.__version__}}\n")
648    f.write(f"torch_version\t{{torch.__version__}}\n")
649    f.write("tokens\t" + ",".join(map(str, TOKENS)) + "\n")
650    f.write(f"vocab\t{{logits.numel()}}\n")
651    for index, value in enumerate(logits.tolist()):
652        bits = struct.unpack("<I", struct.pack("<f", value))[0]
653        f.write(f"logit\t{{index}}\t{{bits:08x}}\n")
654"#
655    );
656    write_atomic(&out_dir.join("capture-hf-oracle.py"), script.as_bytes())?;
657    Ok(())
658}
659
660fn run_native_checkpoint(
661    runner: &Path,
662    source: &str,
663    output: &Path,
664) -> Result<(), Box<dyn std::error::Error>> {
665    if !Path::new(source).is_dir() {
666        return Err(
667            "native checkpoint parity requires a local safetensors directory; inspect may use a pinned remote header, execution may not"
668                .into(),
669        );
670    }
671    let result = Command::new(runner)
672        .arg(source)
673        .args(["1", "2", "3", "4"])
674        .env("MEMRA_FULL_PREC", "1")
675        .env("MEMRA_ORACLE_OUT", output)
676        .output()?;
677    if !result.status.success() {
678        return Err(format!(
679            "native checkpoint runner failed ({}): stdout={} stderr={}",
680            result.status,
681            String::from_utf8_lossy(&result.stdout),
682            String::from_utf8_lossy(&result.stderr)
683        )
684        .into());
685    }
686    if !output.is_file() {
687        return Err(format!(
688            "native checkpoint runner did not create {}",
689            output.display()
690        )
691        .into());
692    }
693    Ok(())
694}
695
696fn parse_checkpoint_oracle(text: &str) -> Result<CheckpointOracle, Box<dyn std::error::Error>> {
697    let mut format_ok = false;
698    let mut engine = None;
699    let mut numeric_class = None;
700    let mut tokens = None;
701    let mut vocab = None;
702    let mut logits = BTreeMap::new();
703    for line in text.lines() {
704        let fields: Vec<_> = line.split('\t').collect();
705        match fields.as_slice() {
706            ["format", "memra-checkpoint-oracle-v1"] => format_ok = true,
707            ["engine", value] => engine = Some((*value).to_string()),
708            ["numeric_class", value] => numeric_class = Some((*value).to_string()),
709            ["tokens", value] => {
710                tokens = Some(
711                    value
712                        .split(',')
713                        .map(str::parse)
714                        .collect::<Result<Vec<u32>, _>>()?,
715                )
716            }
717            ["vocab", value] => vocab = Some(value.parse::<usize>()?),
718            ["logit", index, bits] => {
719                let index = index.parse::<usize>()?;
720                let bits = u32::from_str_radix(bits, 16)?;
721                if logits.insert(index, f32::from_bits(bits)).is_some() {
722                    return Err(format!("duplicate oracle logit index {index}").into());
723                }
724            }
725            _ => {}
726        }
727    }
728    if !format_ok {
729        return Err("oracle is missing format=memra-checkpoint-oracle-v1".into());
730    }
731    let vocab = vocab.ok_or("oracle is missing vocab")?;
732    if logits.len() != vocab || (0..vocab).any(|index| !logits.contains_key(&index)) {
733        return Err(format!(
734            "oracle has {} logits, expected contiguous {vocab}",
735            logits.len()
736        )
737        .into());
738    }
739    Ok(CheckpointOracle {
740        engine: engine.ok_or("oracle is missing engine")?,
741        numeric_class: numeric_class.ok_or("oracle is missing numeric_class")?,
742        tokens: tokens.ok_or("oracle is missing tokens")?,
743        vocab,
744        logits: (0..vocab).map(|index| logits[&index]).collect(),
745    })
746}
747
748fn compare_checkpoint_oracles(
749    expected: &CheckpointOracle,
750    actual: &CheckpointOracle,
751    gate: model_packs::CheckpointParityGate,
752) -> Result<String, Box<dyn std::error::Error>> {
753    if expected.numeric_class != actual.numeric_class {
754        return Err(format!(
755            "oracle numeric class mismatch: expected={} native={}",
756            expected.numeric_class, actual.numeric_class
757        )
758        .into());
759    }
760    if expected.tokens != actual.tokens || expected.vocab != actual.vocab {
761        return Err(format!(
762            "oracle identity mismatch: expected tokens={:?} vocab={}, native tokens={:?} vocab={}",
763            expected.tokens, expected.vocab, actual.tokens, actual.vocab
764        )
765        .into());
766    }
767    let mut max_abs = 0.0f32;
768    let mut max_rel = 0.0f32;
769    let mut worst = 0usize;
770    let mut first_violation = None;
771    for (index, (&reference, &native)) in expected.logits.iter().zip(&actual.logits).enumerate() {
772        if !reference.is_finite() || !native.is_finite() {
773            return Err(format!("non-finite checkpoint logit at token {index}").into());
774        }
775        let absolute = (reference - native).abs();
776        let relative = absolute / reference.abs().max(1e-6);
777        if absolute > max_abs {
778            max_abs = absolute;
779            worst = index;
780        }
781        max_rel = max_rel.max(relative);
782        let allowed = gate.max_abs + gate.max_rel * reference.abs();
783        if absolute > allowed && first_violation.is_none() {
784            first_violation = Some((index, absolute, allowed));
785        }
786    }
787    let reference_argmax = stable_argmax(&expected.logits);
788    let native_argmax = stable_argmax(&actual.logits);
789    if let Some((index, absolute, allowed)) = first_violation {
790        return Err(format!(
791            "checkpoint parity failed at token {index}: abs={absolute} exceeds atol+rtol*abs(reference)={allowed}; observed max_abs={max_abs} at token {worst}, max_rel={max_rel}"
792        )
793        .into());
794    }
795    if gate.require_argmax && reference_argmax != native_argmax {
796        return Err(format!(
797            "checkpoint parity argmax mismatch: reference={reference_argmax} native={native_argmax}"
798        )
799        .into());
800    }
801    Ok(format!(
802        "status\tpassed\nreference_engine\t{}\nnative_engine\t{}\nnumeric_class\t{}\ntokens\t{}\nvocab\t{}\nmax_abs\t{max_abs}\nmax_rel\t{max_rel}\nreference_argmax\t{reference_argmax}\nnative_argmax\t{native_argmax}\n",
803        expected.engine,
804        actual.engine,
805        expected.numeric_class,
806        expected
807            .tokens
808            .iter()
809            .map(u32::to_string)
810            .collect::<Vec<_>>()
811            .join(","),
812        expected.vocab,
813    ))
814}
815
816fn stable_argmax(values: &[f32]) -> usize {
817    values
818        .iter()
819        .enumerate()
820        .max_by(|(left_index, left), (right_index, right)| {
821            left.total_cmp(right)
822                .then_with(|| right_index.cmp(left_index))
823        })
824        .map(|(index, _)| index)
825        .unwrap_or(0)
826}
827
828#[derive(Debug)]
829enum ReferenceVisionError {
830    Reference(memra_reference::ReferenceError),
831    Nondeterministic,
832}
833
834impl std::fmt::Display for ReferenceVisionError {
835    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
836        match self {
837            Self::Reference(error) => error.fmt(f),
838            Self::Nondeterministic => write!(
839                f,
840                "native vision reference fixture is not bit-deterministic"
841            ),
842        }
843    }
844}
845
846impl std::error::Error for ReferenceVisionError {}
847
848impl From<memra_reference::ReferenceError> for ReferenceVisionError {
849    fn from(value: memra_reference::ReferenceError) -> Self {
850        Self::Reference(value)
851    }
852}
853
854pub fn scaffold_model_pack(request: ScaffoldRequest) -> Result<(), Box<dyn std::error::Error>> {
855    validate_family_name(&request.family)?;
856    if request.out_dir.exists() && request.out_dir.read_dir()?.next().is_some() {
857        return Err(format!(
858            "refusing to scaffold into non-empty directory {}",
859            request.out_dir.display()
860        )
861        .into());
862    }
863    std::fs::create_dir_all(&request.out_dir)?;
864    write_atomic(
865        &request.out_dir.join("pack.toml"),
866        format!(
867            "family = {:?}\nconfig_layout = \"pending\"\nsupport = \"pending\"\n\n[checkpoint_parity]\nmax_abs = \"pending\"\nmax_rel = \"pending\"\nrequire_argmax = true\n",
868            request.family
869        )
870        .as_bytes(),
871    )?;
872    write_atomic(
873        &request.out_dir.join("aliases.txt"),
874        format!("{}\n", request.family).as_bytes(),
875    )?;
876    write_atomic(
877        &request.out_dir.join("config-normalization.txt"),
878        b"# source field\tcanonical field\ttransform\n",
879    )?;
880    write_atomic(
881        &request.out_dir.join("tensor-schema.tsv"),
882        b"semantic_id\tcheckpoint_pattern\tshape\townership\ttransform\tquant_layout\n",
883    )?;
884    write_atomic(
885        &request.out_dir.join("tokenizer-template.txt"),
886        b"tokenizer_source=pending\ntemplate=artifact-required\n",
887    )?;
888    write_atomic(
889        &request.out_dir.join("gates.txt"),
890        format_gates(&[
891            Gate::Config,
892            Gate::TokenizerTemplate,
893            Gate::TensorCensus,
894            Gate::TinyParity,
895            Gate::CheckpointParity,
896            Gate::RewriteParity,
897            Gate::Serve,
898        ])
899        .as_bytes(),
900    )?;
901    Ok(())
902}
903
904struct SourceData {
905    label: String,
906    revision: String,
907    dialect: CheckpointDialect,
908    config: ModelConfig,
909    config_bytes: Vec<u8>,
910    tensors: Vec<CensusRow>,
911    shards: Vec<String>,
912    tokenizer: Result<TokenizerEvidence, String>,
913}
914
915struct TokenizerEvidence {
916    source: TokenizerSource,
917    tokenizer_sha256: String,
918    template_sha256: String,
919    template_bytes: usize,
920}
921
922#[derive(Clone)]
923struct CensusRow {
924    physical_name: String,
925    entry: TensorCensusEntry,
926    dtype: String,
927}
928
929pub fn inspect_model(
930    request: InspectRequest,
931) -> Result<InspectSummary, Box<dyn std::error::Error>> {
932    let pack = model_packs::by_alias(&request.against)
933        .ok_or_else(|| format!("unknown model pack {:?}", request.against))?;
934    let source = load_source(&request.source)?;
935    let plan = pack.compile_plan(&source.config)?;
936    let output_head = if source
937        .tensors
938        .iter()
939        .any(|row| row.entry.name == "lm_head.weight" || row.entry.name == "output.weight")
940    {
941        OutputHead::Separate
942    } else {
943        OutputHead::TiedToEmbedding
944    };
945    let entries: Vec<_> = source.tensors.iter().map(|row| row.entry.clone()).collect();
946    std::fs::create_dir_all(&request.out_dir)?;
947    let config_hash = hex_sha256(&source.config_bytes);
948    let census = format_census(&source.tensors);
949    let census_hash = hex_sha256(census.as_bytes());
950    let plan_text = format!("{plan:#?}\n");
951    let plan_hash = hex_sha256(plan_text.as_bytes());
952    let rewrites = memra_gguf::execution_manifest::execution_rewrites(&plan);
953    debug_assert!(
954        rewrites
955            .iter()
956            .all(|rewrite| rewrite.plan_sha256 == plan_hash)
957    );
958    let rewrite_manifest = format_execution_rewrites(&rewrites);
959    let rewrite_hash = hex_sha256(rewrite_manifest.as_bytes());
960    write_atomic(
961        &request.out_dir.join("tensor-census.tsv"),
962        census.as_bytes(),
963    )?;
964    write_atomic(
965        &request.out_dir.join("model-plan.txt"),
966        plan_text.as_bytes(),
967    )?;
968    write_atomic(
969        &request.out_dir.join("execution-rewrites.tsv"),
970        rewrite_manifest.as_bytes(),
971    )?;
972    let binding_error = match pack.compile_tensor_contract(
973        &source.config,
974        &plan,
975        source.dialect,
976        ContractOptions { output_head },
977    ) {
978        Ok(contract) => contract.bind(&entries).err().map(|error| error.to_string()),
979        Err(error) => Some(error.to_string()),
980    };
981    let tokenizer_error = match &source.tokenizer {
982        Ok(evidence) if pack.tokenizer_sources.contains(&evidence.source) => None,
983        Ok(evidence) => Some(format!(
984            "model pack {} does not accept tokenizer source {:?}",
985            pack.family, evidence.source
986        )),
987        Err(error) => Some(error.clone()),
988    };
989    if let Ok(evidence) = &source.tokenizer {
990        write_atomic(
991            &request.out_dir.join("tokenizer-contract.tsv"),
992            format!(
993                "status\tpassed\nsource\t{:?}\ntokenizer_sha256\t{}\ntemplate_sha256\t{}\ntemplate_bytes\t{}\n",
994                evidence.source,
995                evidence.tokenizer_sha256,
996                evidence.template_sha256,
997                evidence.template_bytes,
998            )
999            .as_bytes(),
1000        )?;
1001    }
1002    write_atomic(
1003        &request.out_dir.join("artifact.lock"),
1004        format_lock(
1005            pack,
1006            &source,
1007            &config_hash,
1008            &census_hash,
1009            &plan_hash,
1010            &rewrite_hash,
1011            if binding_error.is_some() {
1012                "failed"
1013            } else {
1014                "passed"
1015            },
1016        )
1017        .as_bytes(),
1018    )?;
1019    let error_path = request.out_dir.join("contract-error.txt");
1020    let tokenizer_error_path = request.out_dir.join("tokenizer-error.txt");
1021    let mut passed = vec![Gate::Config];
1022    let mut failed = Vec::new();
1023    if tokenizer_error.is_some() {
1024        failed.push(Gate::TokenizerTemplate);
1025    } else {
1026        passed.push(Gate::TokenizerTemplate);
1027    }
1028    if binding_error.is_some() {
1029        failed.push(Gate::TensorCensus);
1030    } else {
1031        passed.push(Gate::TensorCensus);
1032    }
1033    write_atomic(
1034        &request.out_dir.join("gates.txt"),
1035        format_gate_results_with_receipts(pack, &request.out_dir, &passed, &failed).as_bytes(),
1036    )?;
1037    if let Some(error) = binding_error.as_ref() {
1038        write_atomic(&error_path, format!("{error}\n").as_bytes())?;
1039    } else {
1040        match std::fs::remove_file(&error_path) {
1041            Ok(()) => {}
1042            Err(error) if error.kind() == std::io::ErrorKind::NotFound => {}
1043            Err(error) => return Err(error.into()),
1044        }
1045    }
1046    if let Some(error) = tokenizer_error.as_ref() {
1047        write_atomic(&tokenizer_error_path, format!("{error}\n").as_bytes())?;
1048    } else {
1049        match std::fs::remove_file(&tokenizer_error_path) {
1050            Ok(()) => {}
1051            Err(error) if error.kind() == std::io::ErrorKind::NotFound => {}
1052            Err(error) => return Err(error.into()),
1053        }
1054    }
1055    match (binding_error, tokenizer_error) {
1056        (Some(binding), Some(tokenizer)) => {
1057            return Err(
1058                format!("tensor contract: {binding}; tokenizer contract: {tokenizer}").into(),
1059            );
1060        }
1061        (Some(error), None) | (None, Some(error)) => return Err(error.into()),
1062        (None, None) => {}
1063    }
1064
1065    Ok(InspectSummary {
1066        family: pack.family,
1067        tensor_count: source.tensors.len(),
1068        out_dir: request.out_dir,
1069    })
1070}
1071
1072fn load_source(source: &str) -> Result<SourceData, Box<dyn std::error::Error>> {
1073    let path = Path::new(source);
1074    if path.exists() {
1075        return load_local(path);
1076    }
1077    let (repo, revision) = parse_pinned_hf_source(source)?;
1078    load_remote(repo, revision)
1079}
1080
1081fn load_config_only(source: &str) -> Result<ModelConfig, Box<dyn std::error::Error>> {
1082    let path = Path::new(source);
1083    if path.is_file() {
1084        return Ok(ModelConfig::from_gguf(&GgufFile::open(path)?));
1085    }
1086    if path.is_dir() {
1087        let bytes = std::fs::read(path.join("config.json"))?;
1088        return Ok(ModelConfig::from_hf(&HfConfig::parse(std::str::from_utf8(
1089            &bytes,
1090        )?)));
1091    }
1092    let (repo, revision) = parse_pinned_hf_source(source)?;
1093    let url = format!("https://huggingface.co/{repo}/resolve/{revision}/config.json");
1094    let config = http_text(&url)?.ok_or("pinned model has no config.json")?;
1095    Ok(ModelConfig::from_hf(&HfConfig::parse(&config)))
1096}
1097
1098fn load_local(path: &Path) -> Result<SourceData, Box<dyn std::error::Error>> {
1099    if path.is_file() {
1100        let gguf = GgufFile::open(path)?;
1101        let tokenizer = inspect_gguf_tokenizer(&gguf);
1102        let config = ModelConfig::from_gguf(&gguf);
1103        let tensors = gguf
1104            .tensors
1105            .iter()
1106            .map(|tensor| CensusRow {
1107                physical_name: tensor.name.clone(),
1108                entry: TensorCensusEntry {
1109                    name: tensor.name.clone(),
1110                    shape: tensor.ne.clone(),
1111                    storage: ggml_storage(tensor.ggml_type),
1112                },
1113                dtype: format!("{:?}", tensor.ggml_type),
1114            })
1115            .collect();
1116        let config_bytes = format!("{config:#?}").into_bytes();
1117        return Ok(SourceData {
1118            label: path.display().to_string(),
1119            revision: "local".to_string(),
1120            dialect: CheckpointDialect::Gguf,
1121            config,
1122            config_bytes,
1123            tensors,
1124            shards: (0..gguf.n_shards())
1125                .map(|index| gguf.shard_path(index).display().to_string())
1126                .collect(),
1127            tokenizer,
1128        });
1129    }
1130
1131    let config_bytes = std::fs::read(path.join("config.json"))?;
1132    let config_text = std::str::from_utf8(&config_bytes)?;
1133    let config = ModelConfig::from_hf(&HfConfig::parse(config_text));
1134    let tokenizer = inspect_hf_tokenizer_dir(path);
1135    let model = StModel::open(path)?;
1136    let shards = local_shards(path)?;
1137    let revision = local_hf_revision(path, &shards).unwrap_or_else(|| "local".to_string());
1138    let headers = model
1139        .names()
1140        .map(|name| {
1141            let (info, _) = model.raw(name).expect("StModel name must resolve");
1142            (name.clone(), info.clone())
1143        })
1144        .collect();
1145    Ok(SourceData {
1146        label: path.display().to_string(),
1147        revision,
1148        dialect: CheckpointDialect::HfSafetensors,
1149        config,
1150        config_bytes,
1151        tensors: census_from_headers(headers)?,
1152        shards,
1153        tokenizer,
1154    })
1155}
1156
1157fn load_remote(repo: &str, revision: &str) -> Result<SourceData, Box<dyn std::error::Error>> {
1158    let base = format!("https://huggingface.co/{repo}/resolve/{revision}");
1159    let config_bytes = http_text(&format!("{base}/config.json"))?
1160        .ok_or("pinned model has no config.json")?
1161        .into_bytes();
1162    let config = ModelConfig::from_hf(&HfConfig::parse(std::str::from_utf8(&config_bytes)?));
1163    let tokenizer = inspect_remote_hf_tokenizer(&base);
1164    let index = http_text(&format!("{base}/model.safetensors.index.json"))?;
1165    let shards: Vec<String> = if let Some(index) = index {
1166        let mut files: Vec<_> = parse_index_json(&index)?.into_values().collect();
1167        files.sort();
1168        files.dedup();
1169        files
1170    } else {
1171        vec!["model.safetensors".to_string()]
1172    };
1173    let mut headers = BTreeMap::new();
1174    for shard in &shards {
1175        validate_remote_filename(shard)?;
1176        let url = format!("{base}/{shard}");
1177        let prefix = http_range(&url, 0, 7)?;
1178        if prefix.len() != 8 {
1179            return Err(format!("{shard}: expected 8-byte safetensors prefix").into());
1180        }
1181        let header_len = u64::from_le_bytes(prefix.try_into().unwrap()) as usize;
1182        if header_len == 0 || header_len > MAX_TEXT_BYTES {
1183            return Err(format!("{shard}: invalid safetensors header length {header_len}").into());
1184        }
1185        let bytes = http_range(&url, 8, 7 + header_len)?;
1186        if bytes.len() != header_len {
1187            return Err(format!(
1188                "{shard}: range returned {} header bytes, expected {header_len}",
1189                bytes.len()
1190            )
1191            .into());
1192        }
1193        let parsed = parse_header(std::str::from_utf8(&bytes)?)?;
1194        for (name, info) in parsed {
1195            if headers.insert(name.clone(), info).is_some() {
1196                return Err(format!("tensor {name} occurs in multiple safetensors shards").into());
1197            }
1198        }
1199    }
1200    Ok(SourceData {
1201        label: repo.to_string(),
1202        revision: revision.to_string(),
1203        dialect: CheckpointDialect::HfSafetensors,
1204        config,
1205        config_bytes,
1206        tensors: census_from_headers(headers)?,
1207        shards,
1208        tokenizer,
1209    })
1210}
1211
1212fn inspect_gguf_tokenizer(gguf: &GgufFile) -> Result<TokenizerEvidence, String> {
1213    let model = gguf
1214        .metadata
1215        .get("tokenizer.ggml.model")
1216        .and_then(|value| value.as_str())
1217        .ok_or_else(|| "GGUF is missing tokenizer.ggml.model".to_string())?;
1218    let tokens = gguf
1219        .metadata
1220        .get("tokenizer.ggml.tokens")
1221        .and_then(|value| value.as_str_array())
1222        .ok_or_else(|| "GGUF is missing tokenizer.ggml.tokens".to_string())?;
1223    if tokens.is_empty() {
1224        return Err("GGUF tokenizer.ggml.tokens is empty".to_string());
1225    }
1226    let template = gguf
1227        .metadata
1228        .get("tokenizer.chat_template")
1229        .and_then(|value| value.as_str())
1230        .filter(|template| !template.trim().is_empty())
1231        .ok_or_else(|| "GGUF is missing tokenizer.chat_template".to_string())?;
1232    let mut hasher = Sha256::new();
1233    hasher.update(model.as_bytes());
1234    if let Some(pre) = gguf
1235        .metadata
1236        .get("tokenizer.ggml.pre")
1237        .and_then(|value| value.as_str())
1238    {
1239        hasher.update([0]);
1240        hasher.update(pre.as_bytes());
1241    }
1242    for token in tokens {
1243        hasher.update([0]);
1244        hasher.update(token.as_bytes());
1245    }
1246    Ok(TokenizerEvidence {
1247        source: TokenizerSource::GgufMetadata,
1248        tokenizer_sha256: hasher
1249            .finalize()
1250            .iter()
1251            .map(|byte| format!("{byte:02x}"))
1252            .collect(),
1253        template_sha256: hex_sha256(template.as_bytes()),
1254        template_bytes: template.len(),
1255    })
1256}
1257
1258fn inspect_hf_tokenizer_dir(path: &Path) -> Result<TokenizerEvidence, String> {
1259    let tokenizer_path = path.join("tokenizer.json");
1260    let tokenizer = std::fs::read(&tokenizer_path)
1261        .map_err(|error| format!("read {}: {error}", tokenizer_path.display()))?;
1262    let template = local_hf_template(path)?;
1263    Ok(TokenizerEvidence {
1264        source: TokenizerSource::TokenizerJson,
1265        tokenizer_sha256: hex_sha256(&tokenizer),
1266        template_sha256: hex_sha256(template.as_bytes()),
1267        template_bytes: template.len(),
1268    })
1269}
1270
1271fn local_hf_template(path: &Path) -> Result<String, String> {
1272    let config_path = path.join("tokenizer_config.json");
1273    if let Ok(config) = std::fs::read_to_string(&config_path)
1274        && let Some(template) = template_from_tokenizer_config(&config)
1275    {
1276        return Ok(template);
1277    }
1278    let template_path = path.join("chat_template.jinja");
1279    std::fs::read_to_string(&template_path)
1280        .map_err(|error| format!("read {}: {error}", template_path.display()))
1281        .and_then(nonempty_template)
1282}
1283
1284fn inspect_remote_hf_tokenizer(base: &str) -> Result<TokenizerEvidence, String> {
1285    let tokenizer = http_text(&format!("{base}/tokenizer.json"))
1286        .map_err(|error| error.to_string())?
1287        .ok_or_else(|| "pinned HF model has no tokenizer.json".to_string())?;
1288    let config =
1289        http_text(&format!("{base}/tokenizer_config.json")).map_err(|error| error.to_string())?;
1290    let template = config
1291        .as_deref()
1292        .and_then(template_from_tokenizer_config)
1293        .or_else(|| {
1294            http_text(&format!("{base}/chat_template.jinja"))
1295                .ok()
1296                .flatten()
1297        })
1298        .ok_or_else(|| {
1299            "pinned HF model has neither tokenizer_config chat_template nor chat_template.jinja"
1300                .to_string()
1301        })
1302        .and_then(nonempty_template)?;
1303    Ok(TokenizerEvidence {
1304        source: TokenizerSource::TokenizerJson,
1305        tokenizer_sha256: hex_sha256(tokenizer.as_bytes()),
1306        template_sha256: hex_sha256(template.as_bytes()),
1307        template_bytes: template.len(),
1308    })
1309}
1310
1311fn template_from_tokenizer_config(config: &str) -> Option<String> {
1312    let config = memra_gguf::config::JsonObj::parse(config);
1313    config
1314        .string("chat_template")
1315        .filter(|value| !value.trim().is_empty())
1316}
1317
1318fn nonempty_template(template: String) -> Result<String, String> {
1319    if template.trim().is_empty() {
1320        Err("chat template is empty".to_string())
1321    } else {
1322        Ok(template)
1323    }
1324}
1325
1326fn census_from_headers(
1327    headers: BTreeMap<String, StInfo>,
1328) -> Result<Vec<CensusRow>, Box<dyn std::error::Error>> {
1329    let mut auxiliary_names = BTreeSet::new();
1330    let mut rows = Vec::new();
1331    for (physical_name, info) in &headers {
1332        if auxiliary_names.contains(physical_name) || is_quant_auxiliary(physical_name, &headers) {
1333            continue;
1334        }
1335        let stem = physical_name.strip_suffix(".weight");
1336        let auxiliaries: Vec<String> = stem
1337            .map(|stem| {
1338                [
1339                    format!("{stem}.weight_scale"),
1340                    format!("{stem}.weight_scale_inv"),
1341                    format!("{stem}.weight_scale_2"),
1342                    format!("{stem}.input_scale"),
1343                    format!("{stem}.scale"),
1344                ]
1345                .into_iter()
1346                .filter(|name| headers.contains_key(name))
1347                .collect()
1348            })
1349            .unwrap_or_default();
1350        auxiliary_names.extend(auxiliaries.iter().cloned());
1351        let (shape, storage) = st_storage(info, &auxiliaries)?;
1352        rows.push(CensusRow {
1353            physical_name: physical_name.clone(),
1354            entry: TensorCensusEntry {
1355                name: canonical_hf_name(physical_name),
1356                shape,
1357                storage: match storage {
1358                    StorageLayout::Quantized(mut layout) => {
1359                        layout.auxiliaries = auxiliaries
1360                            .iter()
1361                            .map(|name| canonical_hf_name(name))
1362                            .collect();
1363                        StorageLayout::Quantized(layout)
1364                    }
1365                    other => other,
1366                },
1367            },
1368            dtype: info.dtype.clone(),
1369        });
1370    }
1371    rows.sort_by(|left, right| left.entry.name.cmp(&right.entry.name));
1372    let mut names = BTreeSet::new();
1373    for row in &rows {
1374        if !names.insert(&row.entry.name) {
1375            return Err(
1376                format!("multiple physical tensors normalize to {}", row.entry.name).into(),
1377            );
1378        }
1379    }
1380    Ok(rows)
1381}
1382
1383fn st_storage(
1384    info: &StInfo,
1385    auxiliaries: &[String],
1386) -> Result<(Vec<u64>, StorageLayout), Box<dyn std::error::Error>> {
1387    let float = match info.dtype.as_str() {
1388        "F32" => Some(FloatType::F32),
1389        "F16" => Some(FloatType::F16),
1390        "BF16" => Some(FloatType::Bf16),
1391        "F8_E4M3" if auxiliaries.is_empty() => Some(FloatType::Fp8E4m3),
1392        _ => None,
1393    };
1394    if let Some(float) = float {
1395        return Ok((info.shape.clone(), StorageLayout::Float(float)));
1396    }
1397    if info.dtype == "I64" && auxiliaries.is_empty() {
1398        return Ok((info.shape.clone(), StorageLayout::Integer(IntegerType::I64)));
1399    }
1400    if auxiliaries.is_empty() {
1401        return Err(format!("unsupported standalone safetensors dtype {}", info.dtype).into());
1402    }
1403    let mut shape = info.shape.clone();
1404    let (format, block_shape) = match info.dtype.as_str() {
1405        "U8" => {
1406            let last = shape
1407                .last_mut()
1408                .ok_or("packed U8 weight has no dimensions")?;
1409            *last *= 2;
1410            ("NVFP4", vec![16])
1411        }
1412        "I8" => {
1413            let last = shape
1414                .last_mut()
1415                .ok_or("packed I8 weight has no dimensions")?;
1416            *last *= 2;
1417            ("MXFP4", vec![32])
1418        }
1419        "F8_E4M3" => ("FP8_E4M3", vec![128, 128]),
1420        other => return Err(format!("unsupported quantized weight dtype {other}").into()),
1421    };
1422    Ok((
1423        shape,
1424        StorageLayout::Quantized(QuantLayout {
1425            format: format.to_string(),
1426            block_shape,
1427            auxiliaries: Vec::new(),
1428        }),
1429    ))
1430}
1431
1432fn is_quant_auxiliary(name: &str, headers: &BTreeMap<String, StInfo>) -> bool {
1433    for suffix in [
1434        ".weight_scale",
1435        ".weight_scale_inv",
1436        ".weight_scale_2",
1437        ".input_scale",
1438        ".scale",
1439    ] {
1440        if let Some(stem) = name.strip_suffix(suffix) {
1441            if headers.contains_key(&format!("{stem}.weight")) {
1442                return true;
1443            }
1444        }
1445    }
1446    false
1447}
1448
1449fn canonical_hf_name(name: &str) -> String {
1450    if let Some(suffix) = name.strip_prefix("model.language_model.") {
1451        return format!("model.{suffix}");
1452    }
1453    if let Some(suffix) = name.strip_prefix("language_model.model.") {
1454        return format!("model.{suffix}");
1455    }
1456    if let Some(suffix) = name.strip_prefix("language_model.lm_head.") {
1457        return format!("lm_head.{suffix}");
1458    }
1459    name.to_string()
1460}
1461
1462fn ggml_storage(kind: GgmlType) -> StorageLayout {
1463    match kind {
1464        GgmlType::F32 => StorageLayout::Float(FloatType::F32),
1465        GgmlType::F16 => StorageLayout::Float(FloatType::F16),
1466        GgmlType::BF16 => StorageLayout::Float(FloatType::Bf16),
1467        GgmlType::I64 => StorageLayout::Integer(IntegerType::I64),
1468        other => {
1469            let (block, _) = other.block_and_type_size();
1470            StorageLayout::Quantized(QuantLayout {
1471                format: format!("{other:?}"),
1472                block_shape: vec![block as u32],
1473                auxiliaries: Vec::new(),
1474            })
1475        }
1476    }
1477}
1478
1479fn parse_pinned_hf_source(source: &str) -> Result<(&str, &str), Box<dyn std::error::Error>> {
1480    let (repo, revision) = source
1481        .rsplit_once('@')
1482        .ok_or("remote sources must be pinned as hf-id@40-char-sha")?;
1483    if repo.split('/').count() != 2
1484        || repo.split('/').any(|part| part.is_empty())
1485        || !repo
1486            .bytes()
1487            .all(|byte| byte.is_ascii_alphanumeric() || matches!(byte, b'/' | b'-' | b'_' | b'.'))
1488        || repo.contains("..")
1489    {
1490        return Err("HF model id must be namespace/repository".into());
1491    }
1492    if revision.len() != 40 || !revision.bytes().all(|byte| byte.is_ascii_hexdigit()) {
1493        return Err("HF revision must be a full 40-character commit SHA".into());
1494    }
1495    Ok((repo, revision))
1496}
1497
1498fn validate_family_name(family: &str) -> Result<(), Box<dyn std::error::Error>> {
1499    if family.is_empty()
1500        || !family
1501            .bytes()
1502            .all(|byte| byte.is_ascii_lowercase() || byte.is_ascii_digit() || byte == b'_')
1503    {
1504        return Err(
1505            "family must contain only lowercase ASCII letters, digits, and underscores".into(),
1506        );
1507    }
1508    Ok(())
1509}
1510
1511fn validate_remote_filename(name: &str) -> Result<(), Box<dyn std::error::Error>> {
1512    if name.is_empty()
1513        || name.starts_with('/')
1514        || name.split('/').any(|part| part.is_empty() || part == "..")
1515        || !name
1516            .bytes()
1517            .all(|byte| byte.is_ascii_alphanumeric() || matches!(byte, b'/' | b'-' | b'_' | b'.'))
1518    {
1519        return Err(format!("unsafe shard filename {name:?}").into());
1520    }
1521    Ok(())
1522}
1523
1524fn http_text(url: &str) -> Result<Option<String>, Box<dyn std::error::Error>> {
1525    let mut command = curl_command();
1526    command.args([
1527        "--silent",
1528        "--show-error",
1529        "--location",
1530        "--max-filesize",
1531        &MAX_TEXT_BYTES.to_string(),
1532        "--write-out",
1533        "\n%{http_code}",
1534        url,
1535    ]);
1536    let output = curl_output(command)?;
1537    if !output.status.success() {
1538        return Err(format!(
1539            "curl failed for {url}: {}",
1540            String::from_utf8_lossy(&output.stderr)
1541        )
1542        .into());
1543    }
1544    let split = output
1545        .stdout
1546        .iter()
1547        .rposition(|byte| *byte == b'\n')
1548        .ok_or("curl response omitted HTTP status")?;
1549    let status = std::str::from_utf8(&output.stdout[split + 1..])?.trim();
1550    match status {
1551        "200" => Ok(Some(String::from_utf8(output.stdout[..split].to_vec())?)),
1552        "404" => Ok(None),
1553        other => Err(format!("HTTP {other} for {url}").into()),
1554    }
1555}
1556
1557fn http_range(url: &str, start: usize, end: usize) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
1558    let mut command = curl_command();
1559    command.args([
1560        "--fail",
1561        "--silent",
1562        "--show-error",
1563        "--location",
1564        "--max-filesize",
1565        &MAX_TEXT_BYTES.to_string(),
1566        "--range",
1567        &format!("{start}-{end}"),
1568        url,
1569    ]);
1570    let output = curl_output(command)?;
1571    if !output.status.success() {
1572        return Err(format!(
1573            "range request failed for {url}: {}",
1574            String::from_utf8_lossy(&output.stderr)
1575        )
1576        .into());
1577    }
1578    Ok(output.stdout)
1579}
1580
1581fn curl_command() -> Command {
1582    Command::new("curl")
1583}
1584
1585fn curl_output(mut command: Command) -> std::io::Result<Output> {
1586    let token = std::env::var("HF_TOKEN").ok();
1587    if token.is_none() {
1588        return command.output();
1589    }
1590    command
1591        .args(["--header", "@-"])
1592        .stdin(Stdio::piped())
1593        .stdout(Stdio::piped())
1594        .stderr(Stdio::piped());
1595    let mut child = command.spawn()?;
1596    let mut stdin = child.stdin.take().expect("piped curl stdin");
1597    writeln!(stdin, "Authorization: Bearer {}", token.unwrap())?;
1598    drop(stdin);
1599    child.wait_with_output()
1600}
1601
1602fn local_shards(path: &Path) -> Result<Vec<String>, Box<dyn std::error::Error>> {
1603    let index = path.join("model.safetensors.index.json");
1604    if index.exists() {
1605        let mut shards: Vec<_> = parse_index_json(&std::fs::read_to_string(index)?)?
1606            .into_values()
1607            .collect();
1608        shards.sort();
1609        shards.dedup();
1610        Ok(shards)
1611    } else {
1612        Ok(vec!["model.safetensors".to_string()])
1613    }
1614}
1615
1616fn local_hf_revision(path: &Path, shards: &[String]) -> Option<String> {
1617    let metadata = path.join(".cache/huggingface/download");
1618    let mut files = Vec::with_capacity(shards.len() + 1);
1619    files.push("config.json");
1620    files.extend(shards.iter().map(String::as_str));
1621    let revisions: Option<Vec<_>> = files
1622        .into_iter()
1623        .map(|file| {
1624            let text = std::fs::read_to_string(metadata.join(format!("{file}.metadata"))).ok()?;
1625            let revision = text.lines().next()?;
1626            (revision.len() == 40 && revision.bytes().all(|byte| byte.is_ascii_hexdigit()))
1627                .then(|| revision.to_ascii_lowercase())
1628        })
1629        .collect();
1630    let revisions = revisions?;
1631    let first = revisions.first()?;
1632    revisions
1633        .iter()
1634        .all(|revision| revision == first)
1635        .then(|| first.clone())
1636}
1637
1638fn format_census(rows: &[CensusRow]) -> String {
1639    let mut output = String::from("semantic_name\tphysical_name\tdtype\tshape\tstorage\n");
1640    for row in rows {
1641        writeln!(
1642            output,
1643            "{}\t{}\t{}\t{:?}\t{:?}",
1644            row.entry.name, row.physical_name, row.dtype, row.entry.shape, row.entry.storage
1645        )
1646        .unwrap();
1647    }
1648    output
1649}
1650
1651fn format_execution_rewrites(
1652    rewrites: &[memra_gguf::execution_manifest::ExecutionRewrite],
1653) -> String {
1654    let mut output = String::from(
1655        "rewrite\tsurface\timplementation\tplan_sha256\teligible\tblockers\toperations\treceipt\n",
1656    );
1657    for rewrite in rewrites {
1658        let blockers = rewrite
1659            .blockers
1660            .iter()
1661            .map(|operation| format!("{operation:?}"))
1662            .collect::<Vec<_>>()
1663            .join(",");
1664        let mut unique_operations = Vec::new();
1665        for operation in &rewrite.canonical_operations {
1666            if !unique_operations.contains(operation) {
1667                unique_operations.push(*operation);
1668            }
1669        }
1670        let operations = unique_operations
1671            .iter()
1672            .map(|operation| format!("{operation:?}"))
1673            .collect::<Vec<_>>()
1674            .join(",");
1675        writeln!(
1676            output,
1677            "{}\t{}\t{}\t{}\t{}\t{}\t{}\tpending",
1678            rewrite.id,
1679            rewrite.surface.as_str(),
1680            rewrite.implementation,
1681            rewrite.plan_sha256,
1682            rewrite.eligible(),
1683            blockers,
1684            operations,
1685        )
1686        .unwrap();
1687    }
1688    output
1689}
1690
1691fn format_lock(
1692    pack: &ModelPack,
1693    source: &SourceData,
1694    config: &str,
1695    census: &str,
1696    plan: &str,
1697    rewrites: &str,
1698    binding: &str,
1699) -> String {
1700    let mut output = String::from("format_version=2\n");
1701    writeln!(output, "source={}", lock_value(&source.label)).unwrap();
1702    writeln!(output, "revision={}", lock_value(&source.revision)).unwrap();
1703    writeln!(output, "family={}", pack.family).unwrap();
1704    match pack.support {
1705        Some(support) => writeln!(output, "support={support:?}").unwrap(),
1706        None => writeln!(output, "support=unsupported").unwrap(),
1707    }
1708    if let Some(gate) = pack.checkpoint_parity {
1709        writeln!(output, "checkpoint_atol={}", gate.max_abs).unwrap();
1710        writeln!(output, "checkpoint_rtol={}", gate.max_rel).unwrap();
1711        writeln!(output, "checkpoint_require_argmax={}", gate.require_argmax).unwrap();
1712    }
1713    writeln!(output, "config_sha256={config}").unwrap();
1714    writeln!(output, "census_sha256={census}").unwrap();
1715    writeln!(output, "plan_sha256={plan}").unwrap();
1716    writeln!(output, "rewrite_manifest_sha256={rewrites}").unwrap();
1717    writeln!(output, "binding={binding}").unwrap();
1718    match &source.tokenizer {
1719        Ok(evidence) if pack.tokenizer_sources.contains(&evidence.source) => {
1720            writeln!(output, "tokenizer=passed").unwrap();
1721            writeln!(output, "tokenizer_source={:?}", evidence.source).unwrap();
1722            writeln!(output, "tokenizer_sha256={}", evidence.tokenizer_sha256).unwrap();
1723            writeln!(output, "template_sha256={}", evidence.template_sha256).unwrap();
1724        }
1725        Ok(_) | Err(_) => writeln!(output, "tokenizer=failed").unwrap(),
1726    }
1727    writeln!(output, "tensor_count={}", source.tensors.len()).unwrap();
1728    for shard in &source.shards {
1729        writeln!(output, "shard={}", lock_value(shard)).unwrap();
1730    }
1731    output
1732}
1733
1734fn parse_header(
1735    json: &str,
1736) -> Result<std::collections::HashMap<String, StInfo>, Box<dyn std::error::Error>> {
1737    parse_header_json_checked(json).map_err(Into::into)
1738}
1739
1740fn parse_index_json(
1741    json: &str,
1742) -> Result<std::collections::HashMap<String, String>, Box<dyn std::error::Error>> {
1743    parse_index_weight_map_json_checked(json).map_err(Into::into)
1744}
1745
1746fn lock_value(value: &str) -> String {
1747    value
1748        .replace('\\', "\\\\")
1749        .replace('\n', "\\n")
1750        .replace('\r', "\\r")
1751}
1752
1753fn format_gates(gates: &[Gate]) -> String {
1754    format_gate_results(gates, &[], &[])
1755}
1756
1757fn format_gate_results(gates: &[Gate], passed: &[Gate], failed: &[Gate]) -> String {
1758    let mut output = String::new();
1759    for gate in gates {
1760        let status = if passed.contains(gate) {
1761            "passed"
1762        } else if failed.contains(gate) {
1763            "failed"
1764        } else {
1765            "pending"
1766        };
1767        writeln!(output, "{gate:?}={status}").unwrap();
1768    }
1769    output
1770}
1771
1772fn all_eligible_rewrites_have_receipts(out_dir: &Path) -> bool {
1773    let Ok(manifest) = std::fs::read_to_string(out_dir.join("execution-rewrites.tsv")) else {
1774        return false;
1775    };
1776    let Ok(index_text) = std::fs::read_to_string(out_dir.join("rewrite-receipts.tsv")) else {
1777        return false;
1778    };
1779    let mut index = BTreeMap::new();
1780    for line in index_text.lines().skip(1) {
1781        let columns: Vec<_> = line.split('\t').collect();
1782        if columns.len() != 4 || columns[3] != "passed" {
1783            return false;
1784        }
1785        index.insert(columns[0], (columns[1], columns[2]));
1786    }
1787    let mut eligible = 0usize;
1788    for line in manifest.lines().skip(1) {
1789        let columns: Vec<_> = line.split('\t').collect();
1790        if columns.len() != 8 {
1791            return false;
1792        }
1793        if columns[4] != "true" {
1794            continue;
1795        }
1796        eligible += 1;
1797        let Some(&(plan, receipt_hash)) = index.get(columns[0]) else {
1798            return false;
1799        };
1800        if plan != columns[3] {
1801            return false;
1802        }
1803        let Ok(receipt) = std::fs::read(
1804            out_dir
1805                .join("rewrite-receipts")
1806                .join(format!("{}.tsv", columns[0])),
1807        ) else {
1808            return false;
1809        };
1810        if hex_sha256(&receipt) != receipt_hash {
1811            return false;
1812        }
1813    }
1814    eligible > 0
1815}
1816
1817fn format_gate_results_with_receipts(
1818    pack: &ModelPack,
1819    out_dir: &Path,
1820    passed: &[Gate],
1821    failed: &[Gate],
1822) -> String {
1823    let mut passed = passed.to_vec();
1824    let artifact_lock = std::fs::read(out_dir.join("artifact.lock")).ok();
1825    let lock_hash = artifact_lock.as_ref().map(|bytes| hex_sha256(bytes));
1826    if let Some(lock) = artifact_lock
1827        .as_deref()
1828        .and_then(|bytes| std::str::from_utf8(bytes).ok())
1829        .filter(|lock| {
1830            lock.lines().any(|line| line == "format_version=2")
1831                && lock
1832                    .lines()
1833                    .any(|line| line == format!("family={}", pack.family))
1834        })
1835    {
1836        for (gate, evidence) in [
1837            (Gate::Config, None),
1838            (Gate::TokenizerTemplate, Some("tokenizer=passed")),
1839            (Gate::TensorCensus, Some("binding=passed")),
1840        ] {
1841            if evidence.is_none_or(|line| lock.lines().any(|candidate| candidate == line))
1842                && !passed.contains(&gate)
1843                && !failed.contains(&gate)
1844            {
1845                passed.push(gate);
1846            }
1847        }
1848    }
1849    let receipt_passes = |name: &str, family_bound: bool, lock_bound: bool| {
1850        let Ok(receipt) = std::fs::read_to_string(out_dir.join(name)) else {
1851            return false;
1852        };
1853        if !receipt.lines().any(|line| line == "status\tpassed") {
1854            return false;
1855        }
1856        if family_bound
1857            && !receipt
1858                .lines()
1859                .any(|line| line == format!("family\t{}", pack.family))
1860        {
1861            return false;
1862        }
1863        if lock_bound
1864            && !lock_hash.as_ref().is_some_and(|hash| {
1865                receipt
1866                    .lines()
1867                    .any(|line| line == format!("artifact_lock_sha256\t{hash}"))
1868            })
1869        {
1870            return false;
1871        }
1872        true
1873    };
1874    for (gate, name, family_bound, lock_bound) in [
1875        (Gate::TinyParity, "tiny-gate.tsv", true, false),
1876        (Gate::CheckpointParity, "checkpoint-parity.tsv", false, true),
1877        (Gate::Serve, "serve-gate.tsv", true, true),
1878    ] {
1879        if receipt_passes(name, family_bound, lock_bound)
1880            && !passed.contains(&gate)
1881            && !failed.contains(&gate)
1882        {
1883            passed.push(gate);
1884        }
1885    }
1886    if all_eligible_rewrites_have_receipts(out_dir)
1887        && !passed.contains(&Gate::RewriteParity)
1888        && !failed.contains(&Gate::RewriteParity)
1889    {
1890        passed.push(Gate::RewriteParity);
1891    }
1892    format_gate_results(pack.gates, &passed, failed)
1893}
1894
1895fn format_tiny_fixture(
1896    plan: &memra_gguf::model_plan::ModelPlan,
1897    fixture: &memra_reference::ReferenceFixture,
1898) -> String {
1899    let mut output = format!("tokens={:?}\nplan={plan:#?}\n", fixture.token_ids);
1900    for (id, tensor) in &fixture.weights {
1901        let mut bytes = Vec::with_capacity(tensor.data.len() * 4);
1902        for value in &tensor.data {
1903            bytes.extend_from_slice(&value.to_bits().to_le_bytes());
1904        }
1905        writeln!(
1906            output,
1907            "tensor={id:?}\tshape={:?}\tsha256={}",
1908            tensor.shape,
1909            hex_sha256(&bytes)
1910        )
1911        .unwrap();
1912    }
1913    if let Some(vision) = fixture.vision.as_ref() {
1914        let mut bytes = Vec::with_capacity(vision.patches.data.len() * 4);
1915        for value in &vision.patches.data {
1916            bytes.extend_from_slice(&value.to_bits().to_le_bytes());
1917        }
1918        writeln!(
1919            output,
1920            "vision_patches={:?}\tsha256={}\tpositions={:?}\toutput_tokens={}",
1921            vision.patches.shape,
1922            hex_sha256(&bytes),
1923            vision.positions,
1924            vision.output_tokens,
1925        )
1926        .unwrap();
1927    }
1928    if let Some(token_ids) = fixture.multimodal_token_ids.as_ref() {
1929        writeln!(output, "multimodal_tokens={token_ids:?}").unwrap();
1930    }
1931    output
1932}
1933
1934fn format_reference_oracle(output: &memra_reference::ReferenceOutput) -> String {
1935    let mut text = String::from("stream\tposition\ttoken\tlogit_f32_bits\n");
1936    append_oracle_rows(
1937        &mut text,
1938        "main",
1939        &output.logits,
1940        output.tokens,
1941        output.vocab,
1942    );
1943    for mtp in &output.mtp {
1944        append_oracle_rows(
1945            &mut text,
1946            &format!("mtp:{}", mtp.depth),
1947            &mtp.logits,
1948            output.tokens,
1949            output.vocab,
1950        );
1951    }
1952    if let Some(draft) = output.draft.as_ref() {
1953        append_oracle_rows(
1954            &mut text,
1955            "dspark",
1956            &draft.logits,
1957            draft.block_size,
1958            output.vocab,
1959        );
1960        for (position, (&token, &confidence)) in draft
1961            .output_ids
1962            .iter()
1963            .skip(1)
1964            .zip(&draft.confidence)
1965            .enumerate()
1966        {
1967            writeln!(
1968                text,
1969                "dspark-confidence\t{position}\t{token}\t{:08x}",
1970                confidence.to_bits()
1971            )
1972            .unwrap();
1973        }
1974    }
1975    text
1976}
1977
1978fn append_oracle_rows(
1979    text: &mut String,
1980    stream: &str,
1981    logits: &[f32],
1982    tokens: usize,
1983    vocab: usize,
1984) {
1985    for position in 0..tokens {
1986        for token in 0..vocab {
1987            writeln!(
1988                text,
1989                "{stream}\t{position}\t{token}\t{:08x}",
1990                logits[position * vocab + token].to_bits()
1991            )
1992            .unwrap();
1993        }
1994    }
1995}
1996
1997fn format_reference_vision_oracle(output: &memra_reference::ReferenceVisionOutput) -> String {
1998    let mut text = String::from("stream\tposition\tchannel\tf32_bits\n");
1999    for (stream, values, rows, width) in [
2000        (
2001            "vision-encoder",
2002            output.encoder_hidden.as_slice(),
2003            output.patch_count,
2004            output.hidden_size,
2005        ),
2006        (
2007            "vision-pooled",
2008            output.pooled_hidden.as_slice(),
2009            output.output_tokens,
2010            output.hidden_size,
2011        ),
2012        (
2013            "vision-projected",
2014            output.projected_hidden.as_slice(),
2015            output.output_tokens,
2016            output.projection_size,
2017        ),
2018    ] {
2019        for position in 0..rows {
2020            for channel in 0..width {
2021                writeln!(
2022                    text,
2023                    "{stream}\t{position}\t{channel}\t{:08x}",
2024                    values[position * width + channel].to_bits()
2025                )
2026                .unwrap();
2027            }
2028        }
2029    }
2030    text
2031}
2032
2033fn hex_sha256(bytes: &[u8]) -> String {
2034    let digest = Sha256::digest(bytes);
2035    digest.iter().map(|byte| format!("{byte:02x}")).collect()
2036}
2037
2038fn write_atomic(path: &Path, bytes: &[u8]) -> std::io::Result<()> {
2039    let temporary = path.with_extension(format!("tmp-{}", std::process::id()));
2040    std::fs::write(&temporary, bytes)?;
2041    std::fs::rename(temporary, path)
2042}
2043
2044#[cfg(test)]
2045mod tests {
2046    use super::*;
2047
2048    #[test]
2049    fn local_glm_fixture_generates_deterministic_onboarding_artifacts() {
2050        let root = std::env::temp_dir().join(format!("memra-cli-inspect-{}", std::process::id()));
2051        let model = root.join("model.gguf");
2052        let output = root.join("out");
2053        std::fs::create_dir_all(&root).unwrap();
2054        memra_gguf::micro_gguf::write_glm_dsa_micro(&model, 0x434c_4901).unwrap();
2055        let verified = verify_model(VerifyRequest {
2056            stage: VerifyStage::Config,
2057            source: model.display().to_string(),
2058            against: "glm_dsa".to_string(),
2059            out_dir: None,
2060            oracle: None,
2061            native_runner: None,
2062        })
2063        .unwrap();
2064        assert_eq!(verified.stage, VerifyStage::Config);
2065        let first = inspect_model(InspectRequest {
2066            source: model.display().to_string(),
2067            against: "glm_dsa".to_string(),
2068            out_dir: output.clone(),
2069        })
2070        .unwrap();
2071        assert_eq!(first.family, "glm_dsa");
2072        assert!(first.tensor_count > 0);
2073        let lock = std::fs::read(output.join("artifact.lock")).unwrap();
2074        inspect_model(InspectRequest {
2075            source: model.display().to_string(),
2076            against: "glm_dsa".to_string(),
2077            out_dir: output.clone(),
2078        })
2079        .unwrap();
2080        assert_eq!(std::fs::read(output.join("artifact.lock")).unwrap(), lock);
2081        for artifact in [
2082            "artifact.lock",
2083            "tensor-census.tsv",
2084            "model-plan.txt",
2085            "execution-rewrites.tsv",
2086            "gates.txt",
2087        ] {
2088            assert!(output.join(artifact).is_file(), "missing {artifact}");
2089        }
2090        std::fs::remove_dir_all(root).unwrap();
2091    }
2092
2093    #[test]
2094    fn pinned_source_and_wrapper_normalization_fail_closed() {
2095        assert!(parse_pinned_hf_source("org/model@main").is_err());
2096        let sha = "a".repeat(40);
2097        assert_eq!(
2098            parse_pinned_hf_source(&format!("org/model@{sha}")).unwrap(),
2099            ("org/model", sha.as_str())
2100        );
2101        assert_eq!(
2102            canonical_hf_name("model.language_model.layers.1.self_attn.q_proj.weight"),
2103            "model.layers.1.self_attn.q_proj.weight"
2104        );
2105    }
2106
2107    #[test]
2108    fn scaffold_is_deterministic_and_refuses_non_empty_targets() {
2109        let root = std::env::temp_dir().join(format!("memra-cli-scaffold-{}", std::process::id()));
2110        scaffold_model_pack(ScaffoldRequest {
2111            family: "new_family".to_string(),
2112            out_dir: root.clone(),
2113        })
2114        .unwrap();
2115        for artifact in [
2116            "pack.toml",
2117            "aliases.txt",
2118            "config-normalization.txt",
2119            "tensor-schema.tsv",
2120            "tokenizer-template.txt",
2121            "gates.txt",
2122        ] {
2123            assert!(root.join(artifact).is_file(), "missing {artifact}");
2124        }
2125        assert!(
2126            scaffold_model_pack(ScaffoldRequest {
2127                family: "new_family".to_string(),
2128                out_dir: root.clone(),
2129            })
2130            .is_err()
2131        );
2132        assert!(validate_family_name("Bad-Family").is_err());
2133        std::fs::remove_dir_all(root).unwrap();
2134    }
2135
2136    #[test]
2137    fn unimplemented_verify_stages_refuse_without_fallback() {
2138        for stage in [VerifyStage::Serve] {
2139            let error = verify_model(VerifyRequest {
2140                stage,
2141                source: "unused".to_string(),
2142                against: "qwen3".to_string(),
2143                out_dir: None,
2144                oracle: None,
2145                native_runner: None,
2146            })
2147            .err()
2148            .unwrap()
2149            .to_string();
2150            assert!(error.contains("no fallback is allowed"));
2151        }
2152    }
2153
2154    #[test]
2155    fn supported_packs_write_deterministic_native_oracles() {
2156        let root = std::env::temp_dir().join(format!("memra-cli-tiny-{}", std::process::id()));
2157        let request = || VerifyRequest {
2158            stage: VerifyStage::Tiny,
2159            source: "unused".to_string(),
2160            against: "qwen3".to_string(),
2161            out_dir: Some(root.clone()),
2162            oracle: None,
2163            native_runner: None,
2164        };
2165        verify_model(request()).unwrap();
2166        let fixture = std::fs::read(root.join("tiny-fixture.txt")).unwrap();
2167        let oracle = std::fs::read(root.join("reference-oracle.tsv")).unwrap();
2168        verify_model(request()).unwrap();
2169        assert_eq!(
2170            std::fs::read(root.join("tiny-fixture.txt")).unwrap(),
2171            fixture
2172        );
2173        assert_eq!(
2174            std::fs::read(root.join("reference-oracle.tsv")).unwrap(),
2175            oracle
2176        );
2177        for pack in model_packs::PACKS {
2178            if pack.family == "qwen3" {
2179                continue;
2180            }
2181            let result = verify_model(VerifyRequest {
2182                stage: VerifyStage::Tiny,
2183                source: "unused".to_string(),
2184                against: pack.family.to_string(),
2185                out_dir: Some(root.join(pack.family)),
2186                oracle: None,
2187                native_runner: None,
2188            });
2189            if pack.support.is_some() {
2190                result.unwrap();
2191                assert!(
2192                    root.join(pack.family)
2193                        .join("reference-oracle.tsv")
2194                        .is_file()
2195                );
2196                if pack.family.starts_with("gemma4") {
2197                    assert!(
2198                        root.join(pack.family)
2199                            .join("reference-vision-oracle.tsv")
2200                            .is_file()
2201                    );
2202                    assert!(
2203                        root.join(pack.family)
2204                            .join("reference-multimodal-oracle.tsv")
2205                            .is_file()
2206                    );
2207                }
2208            } else {
2209                assert!(result.is_err());
2210            }
2211        }
2212        std::fs::remove_dir_all(root).unwrap();
2213    }
2214
2215    #[test]
2216    fn checkpoint_oracle_bundle_is_pinned_and_parity_is_fail_closed() {
2217        let root = std::env::temp_dir().join(format!(
2218            "memra-cli-checkpoint-oracle-{}",
2219            std::process::id()
2220        ));
2221        std::fs::create_dir_all(&root).unwrap();
2222        let sha = "0123456789abcdef0123456789abcdef01234567";
2223        write_hf_oracle_bundle(&format!("org/model@{sha}"), &root).unwrap();
2224        let request = std::fs::read_to_string(root.join("oracle-request.tsv")).unwrap();
2225        let script = std::fs::read_to_string(root.join("capture-hf-oracle.py")).unwrap();
2226        assert!(request.contains(&format!("revision\t{sha}")));
2227        assert!(script.contains(&format!("REVISION = \"{sha}\"")));
2228        assert!(script.contains("trust_remote_code=False"));
2229        assert!(script.contains("dtype=torch.float32"));
2230        assert!(script.contains("source-weights-float32-accumulation"));
2231
2232        let oracle = |engine: &str, values: &[f32]| {
2233            let mut text = format!(
2234                "format\tmemra-checkpoint-oracle-v1\nengine\t{engine}\nnumeric_class\tsource-weights-float32-accumulation\ntokens\t1,2,3,4\nvocab\t{}\n",
2235                values.len()
2236            );
2237            for (index, value) in values.iter().enumerate() {
2238                writeln!(text, "logit\t{index}\t{:08x}", value.to_bits()).unwrap();
2239            }
2240            parse_checkpoint_oracle(&text).unwrap()
2241        };
2242        let reference = oracle("hf-transformers", &[0.0, 1.0, -1.0]);
2243        let native = oracle("memra-native", &[0.0, 1.001, -1.001]);
2244        let gate = model_packs::CheckpointParityGate {
2245            max_abs: 0.01,
2246            max_rel: 2.0,
2247            require_argmax: true,
2248        };
2249        assert!(compare_checkpoint_oracles(&reference, &native, gate).is_ok());
2250        let failing = oracle("memra-native", &[2.0, 1.0, -1.0]);
2251        assert!(compare_checkpoint_oracles(&reference, &failing, gate).is_err());
2252        std::fs::remove_dir_all(root).unwrap();
2253    }
2254
2255    #[test]
2256    fn rewrite_verifier_binds_manifest_plan_and_exact_streams() {
2257        let root =
2258            std::env::temp_dir().join(format!("memra-cli-rewrite-receipt-{}", std::process::id()));
2259        std::fs::create_dir_all(&root).unwrap();
2260        let config = ModelConfig::from_hf(&HfConfig::parse(
2261            r#"{"model_type":"qwen3","num_hidden_layers":2,"hidden_size":64,
2262            "num_attention_heads":2,"num_key_value_heads":1,"head_dim":32,
2263            "intermediate_size":128,"vocab_size":16,"max_position_embeddings":128}"#,
2264        ));
2265        let plan = memra_gguf::model_plan::ModelPlan::compile(&config).unwrap();
2266        let rewrites = memra_gguf::execution_manifest::execution_rewrites(&plan);
2267        let rewrite = rewrites
2268            .iter()
2269            .find(|rewrite| {
2270                rewrite.surface == memra_gguf::execution_manifest::RewriteSurface::DecodeBatch
2271            })
2272            .unwrap();
2273        let artifact_lock = b"format_version=2\nfamily=qwen3\n";
2274        std::fs::write(root.join("artifact.lock"), artifact_lock).unwrap();
2275        std::fs::write(
2276            root.join("execution-rewrites.tsv"),
2277            format_execution_rewrites(&rewrites),
2278        )
2279        .unwrap();
2280        let receipt = rewrite
2281            .verify_logits(
2282                &"00".repeat(32),
2283                &[0.0, 1.0, -1.0],
2284                &[0.0, 1.0, -1.0],
2285                memra_gguf::execution_manifest::RewriteParityPolicy {
2286                    max_abs: 0.0,
2287                    max_rel: 0.0,
2288                    require_argmax: true,
2289                },
2290            )
2291            .unwrap()
2292            .bind_artifact_lock(artifact_lock)
2293            .to_tsv();
2294        let receipt_path = root.join("receipt.tsv");
2295        std::fs::write(&receipt_path, &receipt).unwrap();
2296        verify_rewrite_receipt(
2297            model_packs::by_alias("qwen3").unwrap(),
2298            &receipt_path,
2299            &root,
2300        )
2301        .unwrap();
2302        assert!(
2303            std::fs::read_to_string(root.join("rewrite-receipts.tsv"))
2304                .unwrap()
2305                .contains("decode-batch.v1")
2306        );
2307
2308        let wrong = receipt.replace(&rewrite.plan_sha256, &"11".repeat(32));
2309        std::fs::write(&receipt_path, wrong).unwrap();
2310        assert!(
2311            verify_rewrite_receipt(
2312                model_packs::by_alias("qwen3").unwrap(),
2313                &receipt_path,
2314                &root,
2315            )
2316            .is_err()
2317        );
2318        std::fs::remove_dir_all(root).unwrap();
2319    }
2320
2321    #[cfg(unix)]
2322    #[test]
2323    fn native_serve_gate_launches_readiness_and_completion_on_real_http() {
2324        use std::os::unix::fs::PermissionsExt;
2325
2326        let root =
2327            std::env::temp_dir().join(format!("memra-cli-serve-gate-{}", std::process::id()));
2328        let model = root.join("model");
2329        std::fs::create_dir_all(&model).unwrap();
2330        let artifact_lock = format!(
2331            "source={}\nbinding=passed\ntokenizer=passed\n",
2332            lock_value(model.to_str().unwrap())
2333        );
2334        std::fs::write(root.join("artifact.lock"), &artifact_lock).unwrap();
2335        std::fs::write(
2336            root.join("checkpoint-parity.tsv"),
2337            format!(
2338                "status\tpassed\nartifact_lock_sha256\t{}\n",
2339                hex_sha256(artifact_lock.as_bytes())
2340            ),
2341        )
2342        .unwrap();
2343        let runner = root.join("fake-memra-server.py");
2344        std::fs::write(
2345            &runner,
2346            r#"#!/usr/bin/env python3
2347import json, os
2348from http.server import BaseHTTPRequestHandler, HTTPServer
2349host, port = os.environ["MEMRA_ADDR"].rsplit(":", 1)
2350class Handler(BaseHTTPRequestHandler):
2351    def log_message(self, *args): pass
2352    def do_GET(self):
2353        self.send_response(200 if self.path == "/readyz" else 404)
2354        self.end_headers()
2355        self.wfile.write(b"ready")
2356    def do_POST(self):
2357        length = int(self.headers.get("content-length", "0"))
2358        self.rfile.read(length)
2359        body = json.dumps({"choices":[{"text":"ok"}]}).encode()
2360        self.send_response(200)
2361        self.send_header("content-type", "application/json")
2362        self.send_header("content-length", str(len(body)))
2363        self.end_headers()
2364        self.wfile.write(body)
2365HTTPServer((host, int(port)), Handler).serve_forever()
2366"#,
2367        )
2368        .unwrap();
2369        let mut permissions = std::fs::metadata(&runner).unwrap().permissions();
2370        permissions.set_mode(0o755);
2371        std::fs::set_permissions(&runner, permissions).unwrap();
2372        verify_native_serve(
2373            model_packs::by_alias("qwen3").unwrap(),
2374            model.to_str().unwrap(),
2375            &root,
2376            &runner,
2377        )
2378        .unwrap();
2379        assert!(root.join("serve-response.json").is_file());
2380        assert!(
2381            std::fs::read_to_string(root.join("gates.txt"))
2382                .unwrap()
2383                .contains("Serve=passed")
2384        );
2385        std::fs::remove_dir_all(root).unwrap();
2386    }
2387}