T-saur

Logo

T-saur (.tsr): a content-addressed, deterministic archive format built for AI agents. Rust, Apache-2.0 OR MIT.

View the Project on GitHub iulianbondari/t-saur

T-saur Archive Format (.tsr) — Specification v1.0

Status: v1.0, format frozen (2026-09-24; drafted as v0.1 on 2026-09-22). Name: T-saur, file extension .tsr; volume sets .tsrv. Former working name “AIX”. Language: English. License of this document: CC-BY-4.0.

What is frozen and what is not. §3 (file layout), §4 (chunking and identity), §5 (codecs 0–5 and filters 1–2, blob records), §6 (entries, containers, references), §8 (encryption, recipients, signatures), §9 (limits), §10 (pieces, parity, volume sets) and §12 (versioning) describe format version 1 as the reference implementation writes and reads it; the golden archives in tsaur/crates/tsaur-core/tests/golden/ are the executable form of this freeze. Sections that describe reserved codecs, the semantic layer beyond stored canonical views, trust levels, external reference sets, anchoring and the P2P layer beyond volume sets and the TSXP/1 exchange are design intent, marked “reserved” or “future”, and are not promised by v1.0 (docs/V1-CONTRACT.md lists what is). Implementation-status notes inside the text record when a feature landed; “v0.1” in those notes is the name of the first implementation, which v1.0 keeps unchanged at the byte level.

Abstract: this document describes the proposed archive format: a content-addressed container (chunks identified by hash, Merkle tree), layered compression (dedup → dictionaries/references → strong codecs → optional language model), two fidelity modes (bit-exact and canonical/semantic for agents), per-chunk envelope encryption, signatures, trust levels for content, and a P2P distribution layer (verifiable pieces, erasure coding, optional anchoring in transparency logs/DLT). Every decision carries a short rationale. Prototype numbers are in benchmarks/RESULTS.md.


0. Design goals and non-goals

# Goal Why
G1 Agent-native. The archive is a self-describing knowledge container: an AI agent can read the manifest, decide what it needs, fetch only those chunks, and get a canonical (Markdown/JSON) view of documents without ever touching PDF/DOCX parsers. Agents are the intended consumer; bytes are secondary to information.
G2 Information-based compression. Store new information only: deduplicate content-defined chunks, use shared dictionaries and external references (“the receiver already has this”), then apply strong codecs; optionally use a pinned language model as a predictor. This is the only physically valid route to “much smaller than RAR/ZIP”: exploit redundancy and prior knowledge, not magic.
G3 P2P-native. The archive is a Merkle DAG of chunks; any subset of pieces is independently verifiable; missing pieces can be fetched from any peer or reconstructed from erasure-coded parity. BitTorrent v2 / IPFS / iroh lessons; recovery records like RAR/PAR2 but standardised.
G4 Secure by construction. Authenticated encryption per chunk, envelope keys, multi-recipient (hybrid post-quantum), signed manifests, encrypted metadata, resource limits against decompression bombs, no path traversal by design. Every legacy format has at least one of: unauthenticated encryption (7z), weak KDF (WinZip AES), plaintext metadata, Zip Slip.
G5 Honest fidelity. Two explicit modes: bit-exact (lossless bytes, verified by hash) and canonical (semantic-lossless derivative for agents). Never blur the two. Lossy “AI compression” presented as lossless would be a trust failure.
G6 Deterministic and reproducible. Same inputs + same parameters ⇒ byte-identical archive ⇒ same root hash. Enables cross-archive dedup, caching, and audit.
G7 Open. Spec under CC-BY-4.0, reference implementation Apache-2.0 OR MIT (the Apache option carries a patent grant), no proprietary codec. RAR’s proprietary compressor limited its ecosystem; ZIP and zstd won by openness.

Non-goals (v0.1): GUI, Windows shell integration, self-extracting executables, in-place update of archives (append-only journaling is v0.2), compression of already-compressed media beyond container awareness.


1. Terminology


2. Layered model

L4  Distribution : pieces, piece hashes, Merkle root of pieces, erasure parity (RaptorQ/RS), peer hints, anchors (Rekor/OpenTimestamps)
L3  Semantic     : canonical derivatives (Markdown/JSON), summaries, embeddings index, knowledge-graph triples, tokens-budget hints
L2  Manifest     : entries, provenance (C2PA/in-toto-style), trust levels, policies, signatures, AI-BOM (CycloneDX ML-BOM)
L1  Objects      : streams (chunk lists), container recipes (zip/pdf/tar), delta references, external references
L0  Bytes        : chunks (CDC), blobs (codec + AEAD), dictionaries / reference sets

Each layer can be consumed independently: a P2P node needs only L4 + blobs; an agent deciding relevance needs only L2 + L3; a byte-exact restore needs L0 + L1.


3. File layout

+--------------------------------------------------------------+
| Header (fixed 32 bytes)                                      |
|   magic "TSR\x1A" (4) | version u16 | flags u16 | header_len u32   |
|   reserved (20 bytes, zero)                                        |
+--------------------------------------------------------------------+
| Section 1: recipients (cleartext CBOR: KDF params, wrapped key)    |  [if encrypted]
| Section 2: dictionary / reference-set stubs               [sealed] |
| Section 3: blobs (body) ... (append-only while packing)            |
| Section 4: chunk index (CBOR, zstd, sealed)                        |
| Section 5: manifest (canonical CBOR, zstd, sealed)                 |
| Section 7: semantic index (optional, zstd, sealed)                 |
| Section 6: signatures (CBOR: alg, public key, signature)           |
| Section table: CBOR array of {t, off, len, h = BLAKE3(section)}    |
| Trailer (24 bytes): table_off u64 | table_len u64 | crc32(table) u32 | "RST\x1A" |
+--------------------------------------------------------------------+

Rules:

  1. Writers stream: header → sections → section table → trailer. Readers open from the trailer (like ZIP’s end-of-central-directory): the table must end exactly where the trailer starts, its CRC must match, every section must lie inside [header_len, table_off) in increasing, non-overlapping order, and every section hash must verify before anything is decoded. There is exactly one source of truth for every value; redundant fields that disagree make the archive corrupt.
  2. Every section has its own BLAKE3 hash in the section table; the signature covers the header and every non-signature table row (type, offset, length, hash), so the whole archive is authenticated.
  3. All multi-byte integers little-endian in fixed headers; all structured data is canonical CBOR (RFC 8949 §4.2, deterministic encoding; struct field order fixed) so archives are reproducible.
  4. Optional sidecars (same base name): .tsr.pieces (piece layer, like a .torrent), .tsr.par (erasure parity), .tsr.sig (detached signatures/attestations), .tsr.idx (semantic index if kept out of the main file).
  5. Sealed sections and blobs use XChaCha20-Poly1305 with a nonce derived from the archive’s nonce key, a label (blob / index / manifest / dictionary) and the blob index; the AAD binds the blob header (codec, uncompressed length, first chunk, chunk count) — see §8. Implementation status: tsaur-core v0.1 implements sections 1–6 exactly as drawn; section 7 is reserved.

4. Layer L0 — chunks, blobs, dictionaries

4.1 Chunking

4.2 Blobs and codecs

| codec id | name | use | |—|—|—| | 0 | store | incompressible data (media, encrypted payloads) | | 1 | zstd (level 3..22) | default; with or without dictionary; --long window for solid blocks | | 2 | zstd + dictionary | granular mode: chunks compressed against a trained dictionary (reference set) | | 3 | xz / LZMA2 | max-ratio option for text where speed is irrelevant | | 4 | PPMd (variant H, 7z range coder; p = [order, mem_size]) | text blocks; beats LZMA2 by 2–4 points on prose | | 5 | zstd + chunk dictionary (“delta”): d lists the chunks (internal or external) whose concatenation is the raw-content dictionary | new versions of documents already held by this archive or by a reference archive (the --patch-from model) | | 6 | brotli | reserved; web-friendly | | 7 | context-mixing (cmix/paq-class) | reserved; small critical text; slow (KB/s), deterministic | | 8 | model-predictive (arithmetic coding with a pinned LM) | reserved tier; requires model_id = hash of weights + tokenizer + runtime spec; deterministic int8 inference, logit quantisation, mismatch-tolerant coding (PMATIC-class) as safety net; text only, languages the model covers (small English LMs lose on non-English text) | | 9 | float-split (ZipNN-style exponent/mantissa separation + entropy coding) | reserved; BF16/FP16/FP32 tensors inside safetensors/GGUF/.pt; ~17–33 % lossless at GB/s |

A blob records {off, clen, ulen, codec, n: [chunk indices…], p: [codec parameters…], f: filter, d: [dictionary chunk indices…]} (the chunk list is explicit so that external/referenced chunks can interleave with stored ones in the chunk table; p, f and d are omitted when empty/zero); the AEAD AAD binds codec, ulen, n[0], len(n). The reader must refuse blobs whose ulen exceeds the manifest-declared limits (anti-bomb, see §9), whose chunk sizes do not add up to ulen, that share a chunk with another blob, or that use an unregistered codec or filter id. Implementation status v0.1: codecs 0 (store), 1 (zstd, window sized to the block), 2 (zstd + trained dictionary, granular mode), 3 (xz/LZMA2 with a block-sized dictionary), 4 (PPMd variant H with the 7z range coder; parameters [order, mem_size] stored in p); --codec best tries zstd and xz per block (and PPMd when the block looks like text) and keeps the smallest. A block that zstd cannot shrink by at least 3 % is treated as incompressible: the slower codecs are skipped and the block is stored.

Delta coding (codec 5): a writer that recognises an entry as a new version of content it already holds — the same path in a reference archive, or a similarly named earlier entry of the same archive (same extension, common name prefix of at least half the name) — compresses that entry’s blocks with zstd using the earlier content as a raw-content dictionary and keeps the result when it is smaller than the best ordinary encoding. The dictionary is described by chunk indices (d): chunks of a reference archive are registered in the chunk table as external (x = 1) even when no entry uses them directly, so the Merkle root covers them and readers resolve them through --ref. Rules: a dictionary chunk is never itself part of a delta blob (no decoding chains), dictionaries are at most 64 MiB (writers use 4 MiB), blocks never mix chunks with different dictionaries, the AEAD binds the codec id. A candidate is confirmed only when at least a quarter of the new bytes are shared with it (judged on 8 KiB content-defined pieces), and it is skipped when the earlier content already sits in the current block with room for the new entry (the codec’s own window covers it then). Measured: corpus B (10 documents + 5 edited versions) 48.1 % → 45.2 % in block mode with 1 MiB random access (solid mode unchanged at 44.3 %), and the incremental archive of B against A’s archive 6.8 % → 2.8 % of the input; unrelated inputs are unaffected.

Pre-filters (f, one byte: low nibble = filter id, high nibble = filter parameter) transform the block before the codec and are inverted after decoding. They are exactly invertible and never change the chunk identities (hashes are taken on the unfiltered bytes):

filter id name parameter use
0 none – default
1 x86 BCJ (E8/E9 branch converter, LZMA SDK x86.c semantics, state reset per block) – x86/x86-64 machine code; tried when a block shows ≥ 0.1 % E8/E9 opcodes followed by a 00/FF most-significant byte
2 ARM64 BCJ (BL / ADRP immediate conversion, XZ Utils arm64.c semantics) byte offset (0–3) of the first aligned instruction word AArch64 machine code; blocks start at arbitrary chunk boundaries, so the writer chooses the alignment with the most near BL calls

Writers try the applicable filter and keep the smaller of the filtered and unfiltered encodings, so a filter can never make a block larger. Measured (benchmarks/RESULTS-rust.md; Windows x64 DLLs + exe, 13.5 MB): 32.5 % in block mode and 30.8 % solid with the filter, about one point worse without it (7-Zip BCJ2 29.7 %, WinRAR 33.1 %); ARM64 shared libraries (22.5 MB): 17.8 % block / 16.0 % solid (7-Zip 16.4 % with its automatic ARM64 filter, 15.9 % without, WinRAR 18.5 %). Reserved for a later revision: section-aware filtering driven by PE/ELF/Mach-O headers (filter only the code sections) and BCJ2-style split streams.

Modes:

4.3 Dictionaries and reference sets


5. Layer L1 — objects

5.1 Streams

stream = [chunk_idx, ...] (indices into the chunk table; varint-packed). Total length and BLAKE3 of the whole stream are recorded, so an agent can verify a file without re-hashing chunks individually (the chunk table is itself Merkle-committed).

5.2 Container recipes (container awareness)

Already-compressed containers are opened and their members chunked as plain data, plus a recipe to rebuild them:

5.3 References (external)

{"ref": {"hash": <chunk id>, "size": n, "hints": ["https://…", "magnet:?xt=urn:btmh:…", "ipfs://bafy…", "tsaurref://<set-name>"]}}. Hints are advisory; the hash is the identity.

Implementation status v0.1 (reference archives): a chunk-table row carries x = 1 when the chunk is not stored in this archive but is held by a reference archive; the manifest lists refs: [{root, hint, chunks, bytes}]. pack --ref base.tsr registers every chunk of base.tsr as available and stores only the rest; readers opened with the same --ref resolve external chunks by hash (verified again on read), and report — never silently skip — chunks that no reference provides. On the benchmark corpora, packing the 15-file version set against the 10-file base archive stores only the changed chunks (see README).

5.4 Delta streams

A stream may be expressed as base_stream + patch where base_stream is another entry or external reference. Used for successive versions of the same document.


6. Layer L2 — manifest

Canonical CBOR map (JSON projection shown for readability):

{
  "tsaur": 1, "profile": "documents", "created": "2026-09-22T19:00:00Z",
  "root": "b3:…",                                  // Merkle root of the chunk table
  "chunking": {"algo": "fastcdc", "min": 16384, "avg": 65536, "max": 262144},
  "limits": {"max_total_uncompressed": 4294967296, "max_entry": 1073741824, "max_ratio": 1000},
  "fidelity": "bit-exact | canonical | hybrid",
  "dicts": [{"id": 0, "hash": "b3:…", "size": 112640, "inline": true}],
  "refsets": [{"name": "org-context-2026Q3", "hash": "b3:…", "count": 1200, "hints": ["…"]}],
  "entries": [
    {
      "id": 0, "path": "raport-A.docx", "size": 57739, "hash": "b3:…", "mtime": "…",
      "media_type": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
      "mode": "container:zip", "streams": {"word/document.xml": [12, 13, 14], "…": []},
      "derivatives": [
        {"kind": "canonical/markdown", "stream": [40, 41], "size": 63385, "generator": "tsaur-docx2md@0.1", "fidelity": "semantic"},
        {"kind": "summary", "text": "Raport tehnic despre …", "generator": "model:b3:…", "tokens": 120},
        {"kind": "embedding", "model": "b3:…", "dims": 1024, "dtype": "int8", "stream": [42]}
      ],
      "trust": {"level": "untrusted", "origin": "upload", "signed_by": []},
      "provenance": {"c2pa": "…", "source_uri": "…", "derived_from": []}
    }
  ],
  "policy": {
    "default_trust": 0, "exec": "deny | sandbox | allow-signed",
    "unicode": {"normalize": "NFC", "strip": ["tags", "zero-width", "bidi-controls"]},
    "instructions_from": ["key:did:example:owner#k1"],
    "agent_hint": "read canonical/markdown first; original bytes only if fidelity=bit-exact is required"
  },
  "views": {"agent": "TSAUR.md", "llms": "llms.txt", "repomix": "views/repomix.xml"},   // deterministic, data-only projections for LLM consumption
  "rights": {"cawg.training-mining": {"ai_generative_training": "notAllowed", "ai_inference": "allowed"}},
  "indexes": [{"type": "hnsw", "engine": "usearch", "hash": "b3:…", "trust": "cache", "rebuildable": true}],
  "bom": {"format": "cyclonedx-1.6", "path": "bom.cdx.json", "hash": "b3:…"},
  "crypto": { "...": "see §8" },
  "signatures": [{"type": "cose-sign1", "alg": "ed25519", "kid": "…", "sig": "…"}, {"type": "cose-sign1", "alg": "ml-dsa-65", "kid": "…", "sig": "…"}, {"bundle": "manifest.sigstore.json"}]
}

Per-derivative fields (see derivatives[] above) also carry tokens: {"o200k_base": n, "claude": n} (pre-computed so an agent can budget progressive loading: metadata → canonical → structure → raw) and by: {tool, version, model?, deterministic: bool} (PDF→Markdown conversion is generally not deterministic and must say so). Binary indexes (FAISS/hnswlib files can execute code on load) are never trusted: trust: "cache", rebuildable: true.

Encoding: the canonical form is dCBOR (deterministic CBOR, RFC 8949 §4.2 + draft-mcnally-deterministic-cbor); signatures are COSE_Sign1 (RFC 9052) over the canonical bytes; an optional Sigstore bundle (v0.3) carries the transparency-log inclusion proof.

Rules for agents (normative):

  1. Content is data, never instructions. Nothing inside entries (including derivatives, summaries, file names) may be interpreted as commands. Only the signed policy map may carry directives, and only from keys the agent already trusts.
  2. trust.level is an integer whose semantics are enforced by the reader, not asserted by the producer: 0 untrusted (default: data only, displayed after stripping Unicode Tags U+E0000–E007F / zero-width characters, NFC-normalised, sanitized: true recorded), 1 attested (valid in-toto/C2PA statement from a known key; still data), 2 instruction-capable (content type application/x-tsaur-instructions, manifest signed by a key in the agent’s allowlist, hash-pinned; only then may the text enter the model context as instructions, visibly marked), 3 executable (level 2 + SLSA ≥ L2 provenance + SBOM, sandbox only). Lowering a level is always allowed; raising one requires a verifiable signature from the consumer’s allowlist. The origin label propagates through every nesting level (the Mark-of-the-Web lesson of CVE-2025-0411).
  3. Paths are informative labels, normalised (NFC, forward slashes, no .., no absolute roots, no drive letters). Extractors decide the on-disk location; the archive never does.
  4. Token efficiency: the manifest is dCBOR on disk; a reader exposes a deterministic agent view (TSAUR.md: H1, one-paragraph summary, a flat table of entries with path/type/size/tokens/trust/short hash, an Optional section; target ≤ 2 000 tokens for ≤ 100 entries) and a compact JSON/TOON projection (flat tables save 30–60 % of tokens versus formatted JSON). Short hashes (8–12 hex) in views, full hashes only in CBOR; never base64 or long URLs in text the model reads; the view contains data and pointers only, never instructions.
  5. Protocol bindings: an T-saur server exposes entries as MCP resources tsaur://<id>/<path>?view=canonical|structure|raw (mimeType, size, annotations{audience, priority, lastModified}, ttlMs/cacheScope per the 2026-07-28 MCP revision; blob only on explicit request) and as A2A 1.0 Artifact{parts: [DataPart(manifest excerpt), FilePart{uri: tsaur://…}]} with metadata.trust propagated. Agent Skills / AGENTS.md entries are accepted only when signed by a key in policy.instructions_from.

7. Layer L3 — semantic layer (optional)

Implementation status: canonical views are generated on demand (read --view canonical: DOCX → Markdown from the document XML, PDF → text) with a provenance header, and stored at pack time with --canonical (see §11, hybrid fidelity); exact token counts (a tokenizer instead of the chars/3.5 estimate) remain future work. The tsaur mcp server exposes the agent operations over the Model Context Protocol (stdio JSON-RPC): tools tsaur_info, tsaur_list, tsaur_stat, tsaur_read, tsaur_grep, tsaur_diff, tsaur_verify, tsaur_unpack, resources tsaur://<archive file name>/<entry path>, archives restricted to declared roots, every tool description labelling archive content as untrusted data; dual-era protocol support (2026-07-28 per-request versioning with server/discover, and the legacy initialize handshake). Citation identifiers are tsaur://<merkle-root-hex>/<entry path> with optional fragments #L<a>-<b> (lines) or #B<start>-<end> (bytes).

The semantic layer is what lets an agent answer “what is in this archive and which 3 chunks do I need?” without downloading the body. It is also where semantic dedup lives (near-duplicate documents referenced instead of stored).


8. Cryptography

Purpose Primitive Parameters Notes
Content hash / Merkle BLAKE3-256 plaintext chunk IDs; in encrypted archives IDs are BLAKE3.keyed_hash(K_content_id, chunk) tree hash, verified streaming (Bao); keyed IDs prevent “confirmation of a file” while keeping dedup inside one key domain
Transport Merkle (verify-cap) BLAKE3 over the ciphertext pieces (16 KiB leaves, BEP 52 layout) root signed in the manifest peers and relays verify and repair without being able to decrypt (Tahoe-LAFS verify-cap)
Header integrity HMAC-SHA-256 or BLAKE3 keyed, key = HKDF(DEK, “tsaur/v1/header”) covers the cleartext header (algorithms, KDF params, recipient stanzas) no cheap password verifier (WinZip 2 B / RAR5 12 B anti-pattern): the password is checked only through this tag after the full KDF
Chunk/blob AEAD XChaCha20-Poly1305 (default) or AES-256-GCM (HW-accelerated option) nonce = HKDF(DEK, “nonce”, blob_index) (24 B), AAD = blob header ‖ manifest root chunked STREAM-style construction (Cryptomator/age model): each blob authenticated, index-bound and archive-bound; final blob flagged
Manifest / index same AEAD, separate derived subkeys AAD = section header metadata (names, sizes) are encrypted
Data key DEK, 256-bit random per archive — never derived from a password directly
Password KDF Argon2id (RFC 9106) default m=256 MiB, t=3, p=4; reader-enforced floor m=64 MiB, t=3; salt 16 B; parameters in header wraps a KEK; the passphrase stanza is exclusive (age rule); PBKDF2 forbidden; scrypt N=2^17 only where Argon2 is unavailable
Recipients X25519 + ML-KEM-768 hybrid KEM (per recipient, age-style stanza x25519mlkem768) secret = KDF(ss_mlkem ‖ ss_x25519 ‖ ek ‖ ct ‖ context) (RFC 10024 / SP 800-227 combiner) “harvest now, decrypt later” defence; multiple recipients per archive; other stanzas: argon2id, fido2-hmac, kms, shamir(t,n)
Signatures composite Ed25519 and ML-DSA-65, over the sections table hash and manifest root — dual signature per NIST IR 8547; SLH-DSA-128s for long-lived root keys; valid only if both verify when strict-pq flag is set
Timestamps / anchoring Rekor (Sigstore) entry or OpenTimestamps proof of root optional “DLT” usage limited to anchoring hashes, never storing data
Padding Padmé-style length padding for blobs and sections when hide-sizes flag set — reduces size leakage
Convergent mode optional, per reference set: key = HKDF(secret, chunk hash) — only for org-internal dedup; documented “confirmation-of-file” risk

Key hierarchy:

password ──Argon2id──▶ KEK_pw ─┐
recipient X25519+ML-KEM ──────▶ KEK_i ─┼── wraps ──▶ DEK (archive) ──HKDF──▶ K_blob, K_manifest, K_index, K_nonce
hardware key (FIDO2 hmac-secret)▶ KEK_h ┘

Implementation status v0.1: the recipients section is a CBOR list of stanzas, each wrapping the same archive key — argon2id (salt, m, t, p) and x25519mlkem768 (ephemeral X25519 public key, ML-KEM-768 ciphertext; KEK = HKDF-SHA-256(ss_mlkem ‖ ss_x25519, salt = eph ‖ BLAKE3(ct), info “tsaur v1 x25519mlkem768”)); identities are 96 bytes (X25519 secret + ML-KEM seed), recipient keys 1216 bytes. Composite ML-DSA signatures and FIDO2 stanzas are not implemented yet.

Key rotation = re-wrapping the DEK (rewrite of the small recipient block only). Revocation of a recipient requires re-encryption with a new DEK (documented limitation; convergent chunks are not re-encrypted).


9. Safety limits (normative)


10. Layer L4 — distribution and recovery


11. Fidelity modes

mode what is stored restore guarantee intended use
bit-exact original streams (chunked, container-aware with verified recipes) byte-identical, hash-verified archival, legal, code
canonical canonical derivatives only (Markdown/JSON/text) + provenance information-equivalent, NOT byte-identical agent working sets, RAG corpora, memory
hybrid canonical derivatives inline + original streams as (possibly external) references byte-identical if references resolvable default for agent exchange

Implementation status v0.1: pack --canonical produces fidelity hybrid: every original is stored bit-exact as before, and for each DOCX/PDF entry a derived entry .tsaur/views/<path>.md|.txt holds the canonical view generated at pack time, with derived: {from, view, generator, tokens_est} in the manifest (tokens_est = chars / 3.5, a planning estimate). Views are chunked, deduplicated, compressed, encrypted and verified like any entry; read --view canonical serves the stored view (and converts on demand when none is stored); default extraction skips views unless they are selected explicitly; a view that cannot be generated leaves a note on its source entry and never blocks the original. Cost on corpus A: 62.2 % → 65.4 % of the input for 4 views (281 KB of Markdown/text, ≈ 80 k tokens pre-computed). Stored embeddings and summaries remain future work.

Prototype numbers (benchmarks/RESULTS.md, 10 mixed files, 1.54 MB): bit-exact solid 73.1 % of original (7-Zip LZMA2 ultra 73.6 %, WinRAR 7.23 RAR5 solid 74.2–74.4 %, brotli 73.2 %); canonical 11.1 % — the only mode that “breaks” the PDF/DOCX barrier, because it stores information rather than bytes.


12. Versioning and extensibility


13. Open questions (to decide before v0.2)

  1. Name and extension: the former working name (.aix) conflicted with IBM’s live AIX® trademark (class 9) and was taken on PyPI/npm/crates.io/GitHub. Decision (maintainer, 2026-09-22): T-saur, packages tsaur, extension .tsr, magic bytes TSR\x1A (in force since v1). Decision (maintainer, 2026-09-25): no name reservations and no trademark search; the media type application/vnd.tsaur+cbor is not registered.
  2. Default chunk profile for mixed document sets: 64 KiB (P2P dedup) vs 256 KiB (less metadata) — measure on larger corpora.
  3. Whether the semantic index is inline by default (bigger archive) or sidecar (simpler streaming).
  4. Model-predictive codec: which small open model to pin first (RWKV/Qwen-class, ≤ 1 B params, integer inference) and how to guarantee determinism across CPUs.
  5. Hybrid signatures: mandatory ML-DSA from day one, or optional until PQ libraries stabilise.