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}