A working implementation of STELE, the self-bootstrapping archive format
specified in STELE-SPEC-v2.md.
The one rule. A STELE file must be decodable by a competent person who has never heard of STELE, possesses no software, and has access to nothing but a hex dump of the file itself.
Everything in the format — and in this implementation — is a consequence of that rule. A STELE file carries, inside itself, in this order: a primer that teaches counting and ASCII from a bare hex dump, a plain-English address, the complete specification, a C89 reference decoder, a worked example with a Reed–Solomon test vector, a manifest, and then the payload in checksummed, parity-protected blocks — with the whole assembly repeated periodically so any surviving fragment is self-sufficient.
- docs/STELE-explainer.pdf — a one-page, plain-language overview (what it is and why it exists, no jargon).
- docs/STELE-README.pdf — the technical brief (architecture, geometry, validation).
- STELE-SPEC-v2.md — the normative specification this implements.
All 22 conformance checks pass — builder points 1–12 of spec §14 and the full acceptance-test battery:
P1 byte-0 Rung1 primer, no magic number A1 decode the worked example
P2 Rung 2 character table self-consistent A2 truncated file: recover pre-cut, report rest
P3 spec embedded verbatim, identical copies A3 interior fragment self-sufficient
P4 Address + prose decoder + C89 decoder A4 destroy one block/group -> byte-identical
P5 worked example + output + RS test vector A5 destroy two blocks/group -> byte-identical
P6 assembly head/periodic/tail, true length A6 destroy three -> honest report of loss
P7 block headers 71 bytes, columns, SUM A7 paper: wrong character caught
P8 manifest arithmetic + parity per §8.3/8.4 A8 paper: swapped pair caught
P9 parity-stripped decodes byte-identical A9 paper: dropped line caught
P10 no accidental valid header in assembly
P11 deterministic build
P12 structural byte whitelist
Plus 18/18 C differential/interop checks: the C builder is byte-identical to the Python builder across every config, all build/decode/repair/paper paths cross-validate, the C89 decoder's binary stdin→stdout path works, and every edge case (1-byte, exact-multiple, short-final, 65536-byte blocks) round-trips.
The canonical interleave geometry reproduces the spec's own arithmetic exactly (C = 294, R = 588 for depth 16 × 4096-byte blocks): one destroyed block per group recovers with the parity budget half spent, two recover at exactly zero margin, three are honestly reported as lost — the claims Appendix C says version 1 got wrong.
The 100 MB canonical example of §5 was reproduced end to end: building
104857600 bytes yields exactly block_count=00025600, parity_bytes=000588,
interleave_depth=0016 — matching the spec's own manifest — and decodes
byte-identical (build 14 s, decode 1 s with the C tools).
The spec mandates the embedded reference decoder be strict C89 (§9.2), and explicitly makes repair prose-specified and optional. This implementation is C-first for the durable artifacts, with a complete Python reference kept as a byte-for-byte differential oracle — the format is deterministic (point 11), so the C builder's output must exactly equal the Python builder's, which is a strong, free cross-check. Verified across all build↔decode paths:
C build == Python build (byte-identical, every config)
C build -> C decode (round-trip identical)
Python build -> C decode (identical)
C build -> Python decode (identical)
C repair == Python repair (1 & 2 blocks/group; 3 -> honest loss)
The three decoder conformance levels of §14 are all present in C:
- Level 0 — hand. The prose decoder (Appendix A), carried in every file.
- Level 1 — clean.
stele_decode.c, strict C89,<stdio.h>only, under 300 lines — the required reference (§9.2). - Level 2 — repair.
stele_repair.c: Reed–Solomon erasure recovery over the §8.3 stride geometry (§8.5). Since every missing/suspect block is an erasure at a known position, this needs only erasure decoding.
STELE-SPEC-v2.md the normative specification
stele/ Python reference implementation + oracle
gf256.py GF(2^8) + Reed-Solomon rs255-223 (encode, errors+erasures)
checksums.py Adler-32 (§7.1) and the paper line checksum (§7.2)
ladder.py Rungs 1-3 primer/table/note + the Address (§3)
manifest.py manifest build/parse + wellformed/probe validation (§5)
block.py 71-byte header format + §6.2 validation
parity.py §8.3 stride interleave geometry + §8.5 repair
paper.py §10 paper hex representation (encode/decode)
worked_example.py the reduced-profile miniature + RS test vector (§9.3)
assembly.py assemble.py builder.py file assembly with self-ref assembly_bytes (§2, §5.2)
decoder.py Level 1 (clean) + Level 2 (repair) decoder
bundle.py multi-file bundle convention (Appendix B)
cli.py command line: build/decode/paper/info/verify
data/spec_ascii.txt canonical ASCII fold of the spec (embedded verbatim)
data/stele_decode.c the C89 reference decoder (embedded + compiled)
data/embedded.h generated doc-prefix blob for the C builder
c/stele_build.c C builder (real GF/RS/SHA-256/manifest/assembly logic)
c/stele_repair.c C Level-2 repair (RS erasure recovery, §8.5)
c/stele_paper.c C paper form encode/decode (§10)
tools/fold_spec.py spec -> ASCII fold
tools/gen_embedded.py doc prefix -> embedded.h
tests/conformance.py the §14 conformance + acceptance suite
build.ps1 regenerate artifacts + compile the C tools
.\build.ps1This folds the spec, regenerates embedded.h, and compiles stele_decode.exe
(strict C89, /Za) and stele_build.exe into build/. It finds MSVC via
vswhere and loads vcvars64.bat automatically.
Python CLI:
python -m stele.cli build --in payload.bin --out archive.stele --date 2026-07-19
python -m stele.cli decode --in archive.stele --out recovered.bin # clean
python -m stele.cli decode --in archive.stele --out recovered.bin --repair # Level 2
python -m stele.cli paper encode --in archive.stele --out archive.hex
python -m stele.cli info --in archive.stele
python -m stele.cli verify --in archive.stele
python -m stele.cli bundle build --out multi.stele a.txt b.bin # Appendix B
python -m stele.cli bundle extract --in multi.stele --outdir out/C tools:
build\stele_build.exe payload.bin archive.stele --date 2026-07-19
build\stele_decode.exe archive.stele recovered.bin # Level 1, report to stderr
build\stele_repair.exe damaged.stele recovered.bin # Level 2, RS erasure repair
build\stele_paper.exe encode archive.stele archive.hex # to the paper (hex) form
build\stele_paper.exe decode archive.hex archive.stele # and back
# or, reading a hex dump the way the format intends: stele_decode < archive.stele > outThe C89 decoder reads stdin / writes stdout when given no file arguments; it
accepts file arguments so that raw payload bytes survive on platforms with a
text/binary stream distinction (see the header comment in stele_decode.c).
.\run_all.ps1 # build the C tools, then run every suite
# or individually:
python tests/conformance.py # 22/22 Python conformance + acceptance
python tests/c_differential.py # 18/18 C vs Python differential + interopEnglish above Rung 4; Rung 0 (bytes are numbers) is unearned; SHA-256 is the one deliberate external reference and is optional; hand verification is possible but arduous; overhead is ~21% for canonical parameters. These are stated, not hidden — an honest boundary is worth more than an implied guarantee (axiom A6).