axm-embodied seals robot sensor streams using the same Genesis shard format as every other AXM spoke. The difference is REQ 5: the binary frame sequence in cam_latents.bin must be gap-free and monotone. Any discontinuity is a cryptographic failure.
An embodied system that selects which sensor frames to record is not trustworthy. The value of a verifiable record depends entirely on its completeness. A record that contains only the moments the system chose to preserve is worthless as evidence.
axm-embodied enforces this at the protocol level. The verifier does not ask whether the stream looks complete. It reads every frame_id in sequence and rejects on the first gap.
Record everything, then seal. The hot buffer appends AXLR frames at sensor rate with no cryptographic overhead. When the session ends — or a power-safe threshold fires — Forge compiles the buffer into a sealed shard. Genesis signs it. Nothing is selected.
A gap is a failure, not an omission. E_BUFFER_DISCONTINUITY is not a warning. It is a hard verification failure. The same exit code as a bad cryptographic signature. A robot that drops frames is not conformant. The stream format does not accommodate gaps.
Offline verification, no infrastructure. axm-verify reads cam_latents.bin directly. It checks AXLF magic, then scans every AXLR record. The check is deterministic and stateless. It runs on the same machine that sealed the shard or any other machine with the publisher key.
Document shards pass silently. If cam_latents.bin is absent, REQ 5 does not apply. axm-chat, axm-show, and any document spoke are not affected. REQ 5 is a conditional requirement — it fires only when the file is present.
cam_latents.bin is a simple binary container. The file begins with an AXLF header block. The remainder of the file is a sequence of AXLR records in frame_id ascending order. No index. No random access. Scanned linearly by axm-verify.
# Hot buffer write path — no crypto overhead, nanosecond appends import struct, time AXLF_MAGIC = b"AXLF" AXLR_MAGIC = b"AXLR" class HotBufferWriter: def __init__(self, path: str, session_ts: int = None): self._f = open(path, "wb", buffering=0) # O_DIRECT writes self._frame_id = 0 ts = session_ts or int(time.time() * 1_000_000) # Write AXLF header self._f.write(AXLF_MAGIC) self._f.write(struct.pack("<BII", 1, 0, ts)) def append(self, payload: bytes) -> int: ts = int(time.time() * 1_000_000) self._f.write(AXLR_MAGIC) self._f.write(struct.pack("<BII", 1, self._frame_id, len(payload))) self._f.write(payload) fid = self._frame_id self._frame_id += 1 return fid def close(self): self._f.flush(); self._f.close() # Usage: one append per sensor tick. No batching. No buffering in userspace. # On session end, call axm-embodied seal → Forge → Genesis signs.
REQ 5 is the only conformance requirement unique to embodied spokes. It is enforced by step 7 of axm-verify. The check is binary: either the frame sequence is gap-free or the shard fails verification.
Triggered when: (1) AXLF magic is absent or wrong, (2) any AXLR record has magic mismatch, (3) any frame_id skips — expected N, found M where M ≠ N+1, (4) file truncates mid-record. All four conditions produce the same error code and the same verification outcome: FAIL, exit 1.
# Step 7 of axm-verify — hot stream continuity check import struct from pathlib import Path from axm_verify.const import E_BUFFER_DISCONTINUITY AXLF_MAGIC = b"AXLF" AXLR_MAGIC = b"AXLR" AXLF_HDR = 32 # bytes AXLR_HDR = 24 # bytes (before payload) def check_stream_continuity(shard_dir: Path) -> list[str]: cam = shard_dir / "content" / "cam_latents.bin" if not cam.exists(): return [] # absent = silent pass (REQ 5 not applicable) errors = [] with cam.open("rb") as f: hdr = f.read(AXLF_HDR) if len(hdr) < AXLF_HDR or hdr[:4] != AXLF_MAGIC: return [E_BUFFER_DISCONTINUITY] # bad magic = immediate fail expected_frame_id = 0 while True: rec_hdr = f.read(AXLR_HDR) if not rec_hdr: break # EOF if len(rec_hdr) < AXLR_HDR or rec_hdr[:4] != AXLR_MAGIC: errors.append(E_BUFFER_DISCONTINUITY); break frame_id, _, payload_len = struct.unpack_from("<QQI", rec_hdr, 4) if frame_id != expected_frame_id: errors.append(E_BUFFER_DISCONTINUITY); break # gap detected f.seek(payload_len, 1) # skip payload expected_frame_id += 1 return errors # Test: synthetic gap # Write frames 0,1,2 then skip to 4 → E_BUFFER_DISCONTINUITY fires on frame 4
def test_req5_buffer_gap_detected(tmp_path): # Build a syntactically valid cam_latents.bin with a deliberate gap cam = tmp_path / "cam_latents.bin" with cam.open("wb") as f: f.write(b"AXLF") f.write(struct.pack("<IQQI", 1, 4, 0, 0)) for fid in [0, 1, 2, 4]: # gap: frame 3 missing payload = f"frame_{fid}".encode() f.write(b"AXLR") f.write(struct.pack("<QQI", fid, 0, len(payload))) f.write(payload) errors = check_stream_continuity(tmp_path.parent) assert "E_BUFFER_DISCONTINUITY" in errors # ← must fire PASSED · test_req5_buffer_gap_detected
axm-verify runs seven steps in sequence. Steps 1–6 are identical to all AXM spokes. Step 7 is the embodied-specific stream continuity check. A failure at any step halts and returns exit 1.
| Step | Name | Pass Condition | Error Code | Scope |
|---|---|---|---|---|
| 01 | Layout | manifest.json, sig/, content/, graph/, evidence/ present | E_LAYOUT_MISSING E_LAYOUT_DIRTY |
All Spokes |
| 02 | Manifest Parse | Valid JSON, required fields present, ≤256 KiB | E_MANIFEST_SYNTAX E_MANIFEST_SCHEMA |
All Spokes |
| 03 | Trusted Key + Signature | publisher.pub matches --trusted-key; signature verifies | E_SIG_MISSING E_SIG_INVALID |
All Spokes |
| 04 | Merkle Root | Computed root == manifest.integrity.merkle_root | E_MERKLE_MISMATCH | All Spokes |
| 05 | Parquet Schema | Column names, types, counts match frozen Arrow schemas | E_SCHEMA_TYPE E_SCHEMA_NULL |
All Spokes |
| 06 | Reference Integrity | All claim subjects, span sources, byte ranges valid | E_REF_ORPHAN E_REF_SOURCE |
All Spokes |
| 07 | Stream Continuity | cam_latents.bin absent OR AXLF valid AND all frame_ids gap-free | E_BUFFER_DISCONTINUITY | Embodied Only |
Spokes must satisfy REQ 1–4 to be conformant with the Genesis spec. Embodied spokes must additionally satisfy REQ 5. Run all 13 conformance tests; the REQ 5 test is test_req5_buffer_gap_detected.
| REQ | Description | Error Codes | Scope |
|---|---|---|---|
| REQ 1 | Manifest integrity — byte-exact signature over manifest | E_SIG_INVALID E_MERKLE_MISMATCH |
All Spokes |
| REQ 2 | Content identity — all content files covered by Merkle tree | E_MERKLE_MISMATCH E_REF_SOURCE |
All Spokes |
| REQ 3 | Lineage events — all references valid, no nulls in required columns | E_REF_ORPHAN E_SCHEMA_NULL |
All Spokes |
| REQ 4 | Proof bundle — valid signature from trusted publisher key | E_SIG_INVALID E_SIG_MISSING |
All Spokes |
| REQ 5 | Non-selective recording — no gaps in binary hot stream | E_BUFFER_DISCONTINUITY | Embodied Only |
# Install dependencies in order pip install -e ./axm-genesis # kernel pip install -e ./axm-core # runtime pip install -e ./axm-embodied # this spoke
# Start a session (opens cam_latents.bin) axm-embodied record start \ --signing-key keys/robot.pem # Frames append at sensor rate # On session end, Forge seals the shard axm-embodied record stop ✓ Sealed ~/.axm/shards/session-<id>/
# Verify a sealed session shard axm-verify shard \ ~/.axm/shards/session-abc123/ \ --trusted-key keys/robot.pub {"status":"PASS","error_count":0,"errors":[]} # Introduce a gap → should FAIL axm-verify shard ./test-gap-shard/ \ --trusted-key keys/robot.pub {"status":"FAIL","errors":["E_BUFFER_DISCONTINUITY"]}
# Run all 13 conformance tests python -m pytest \ tests/test_conformance.py -v test_baseline_gold_shard_passes ....... PASSED test_req5_buffer_gap_detected ......... PASSED test_req5_bad_magic_detected .......... PASSED test_req5_truncation_detected ......... PASSED 13 passed in 0.84s