tokitai-operator 0.1.0

Verified DL kernel compiler: formally-checked GEMM, p-adic, sheaf, contract-carrying ops. Paper-artifact grade.
Documentation
//! Topology fingerprint.
//!
//! Computes a stable SHA-256 hash of the topology (depth, width,
//! expert count, top-k, per-expert MLP shape). The fingerprint
//! is independent of the parameter values; it is the "what
//! model is this" identifier.
//!
// Stable short hash of a `ModelArch`, intended for cache keys, model
// registry lookups, and the patent disclosure's reproducibility
// appendix. NOT a cryptographic commitment — just a deterministic
// 16-hex-char (64-bit) digest of the canonical arch JSON.
//
// We hash the canonical JSON (sorted keys, compact form) so the
// fingerprint is stable across:
//   - pretty-printed vs. compact JSON,
//   - Rust struct field reordering in future versions of `ModelArch`,
//   - the choice of `MoESize` representation (`"Tiny"` vs. `0`).
//
// Only fields that affect what `build` produces are part of the
// hash. We re-serialize the arch through serde_json (which is
// deterministic for our flat struct) and then SHA-256 it.

use sha2::{Digest, Sha256};

use super::arch::ModelArch;

/// Return a 16-hex-char (64-bit) fingerprint of `arch`. Two arches
/// that would build to structurally identical models (same size,
/// dims, expert count, top_k, depth, and seed) hash to the same
/// string, even if the originating `ModelArch` instances are
/// distinct.
pub fn arch_fingerprint(arch: &ModelArch) -> String {
    // Compact JSON gives a deterministic, whitespace-insensitive
    // canonical form for our flat struct.
    let bytes = serde_json::to_vec(arch).expect("ModelArch is always serializable");
    let mut hasher = Sha256::new();
    hasher.update(&bytes);
    let digest = hasher.finalize();
    // First 8 bytes (16 hex chars) — 64 bits of collision space is
    // plenty for a model-registry key and stays short.
    let mut out = String::with_capacity(16);
    for b in &digest[..8] {
        out.push_str(&format!("{:02x}", b));
    }
    out
}