Skip to content

Archive Format (.holo)

The .holo format is hologram’s representation for a compiled model. It is a header, a section table, a sequence of payload sections, and a 32-byte BLAKE3 footer over all preceding bytes. hologram-archive is no_std + alloc; the std feature adds file-backed helpers.

┌──────────────────────────────────┐ offset 0
│ Header │ magic + version + flags + section_count
├──────────────────────────────────┤
│ Section table │ one SectionRef per section
├──────────────────────────────────┤
│ Section payloads │ in stable emission order
│ ... │
├──────────────────────────────────┤
│ Footer (32 bytes) │ BLAKE3 fingerprint over all bytes above
└──────────────────────────────────┘

The header is magic (b"HOLO"), format_version (currently 2), flags (u16), and section_count (u16). Each section-table entry (SectionRef) is a kind byte (plus padding), an 8-byte offset, and an 8-byte length pointing into the payload region.

The section kinds (enum SectionKind in format.rs):

IDVariantContent
1KernelCallsTagged KernelCall stream (one variant per op)
2ScheduleTopological schedule (NodeId levels)
3WeightsDeduped weight bodies, BLAKE3-keyed
4ShapeRegistryInterned shape descriptors
5DTypeRegistryDtype registry
6CertificatesPer-node validation/completeness certificates
7TraceOptional trace bytes
8MetadataOptional metadata bytes
9InputsInput PortDescriptors
10OutputsOutput PortDescriptors
11ConstantsInline constant bodies or references into Weights
12ExecPlanPer-level kernel-call indices (executor walks these directly)
13WarmStartConstant-only cone κ-labels (and, at fold depth, materialized results)
14ExtensionOpen, repeatable producer-defined metadata: a length-prefixed string key + arbitrary bytes (tokenizer, generation config, class labels, calibration tables, provenance, …)

A PortDescriptor carries { name: String, slot: u32, element_count: u64, dtype: u8, shape: Vec<u64> } — the runtime uses it to map caller tensors into the workspace’s slot numbering. The semantic name (e.g. "input_ids", "logits") and full shape let multi-input models be addressed by identity rather than position (InferenceSession::input_port_by_name / output_port_by_name).

Extension sections are accessed at runtime via InferenceSession::extension(key) and extension_keys(), and written with Graph::add_extension(key, bytes) (or HoloWriter::add_extension).

Constants over a 4 KiB inline threshold become references (slot + dtype + 32-byte fingerprint) into the deduped Weights pool; smaller literals are inlined. A matmul whose constant B weight is uniquely consumed is pre-packed into the backend’s panel layout (weight-layout monomorphism, zero runtime copy).

HoloWriter is a builder. Set the sections you have, then call finish(), which lays out the header, section table, and payloads, and appends the BLAKE3 footer.

use hologram_archive::HoloWriter;
let mut writer = HoloWriter::new();
writer.set_kernel_calls(kernel_calls);
writer.set_schedule(schedule);
writer.set_weights(weights);
writer.set_shape_registry(shape_registry);
writer.set_constants(constants);
writer.set_inputs(inputs);
writer.set_outputs(outputs);
writer.set_exec_plan(exec_plan);
let archive: Vec<u8> = writer.finish()?;

Setters: set_kernel_calls, set_schedule, set_weights, set_shape_registry, set_certificates, set_trace, set_metadata, set_inputs, set_outputs, set_constants, set_exec_plan. There is no set_graph, no separate compression mode, and no mmap mode.

use hologram_archive::HoloLoader;
let plan = HoloLoader::from_bytes(&bytes)?.into_plan()?;

HoloLoader::from_bytes validates the magic, version, and footer fingerprint; into_plan() produces the LoadedPlan the executor decodes sections from. HoloLoader::fingerprint() returns the 32-byte content fingerprint, and sections() exposes the parsed SectionRef table.

hologram_archive::address derives content addresses (UOR-ADDR κ-labels, 71 bytes):

  • address_ring(&[u8]) -> Result<AddressOutcome<71>, _> — address canonical bytes on the BLAKE3 σ-axis
  • compose_model(&[KappaLabel<71>]) -> Result<KappaLabel<71>, _> — fold part labels into one model identity

compose_model left-folds the CS-G2 commutative product, so the resulting model identity is order-independent — composing the same parts in any order yields the same label. (Computed values inside the graph instead use an ordered, non-commutative derivation, so matmul(A,B) and matmul(B,A) get distinct addresses.)