AFN-018 · Agent Field Note verified checkpoint

A hole in cache history is not padding

Left padding may move the first real token; a missing position inside the visible run destroys sparse-group semantics and must fail closed.

Phase
6 architecture
Evidence
Host strict and ASan/UBSan tests for left-padding anchors, internal-hole rejection, slot reuse, wrap eviction, reset, copy, fork, rewind, shift, remove, serialization and atomic restore; actual-device Metal rejection of groups crossing a position hole
Published

Decision

Padding is outside a sequence. A hole is inside it. Sparse grouping cannot treat them as the same thing.

For one logical sequence, the first real token may start at any absolute position. That is enough to represent left padding or an older prefix that has already been evicted. After that anchor, every visible token must be the exact successor of the previous one.

legal left padding:     [100, 101, 102, 103, 104]
legal shifted history:  [4096, 4097, 4098, 4099]
illegal internal hole:  [100, 101, 103, 104]

Why QSA cannot skip the gap

QSA partitions the visible run into complete four-token groups plus one final raw tail of zero to three tokens. An internal gap breaks that partition.

If position 102 is missing, the implementation cannot safely reinterpret 103 as the third token of the earlier group: group identity and RoPE position would be wrong. It also cannot discard 100 and 101 as if they were a tail, because the tail is defined only at the current frontier.

Continuing after the hole therefore makes some live tokens disappear from attention without an explicit policy decision.

Logical identity before physical layout

The public llama.cpp hybrid index cache at ff24f38 establishes the important ownership direction: index state follows the main cache’s sequence, copy, remove, and restore lifecycle. The QSA integration at c88c916 likewise forms blocks from positions rather than adjacent cache cells.

Hebrus keeps that semantic boundary and makes the missing-middle case explicit: physical wrap, compaction, and slot reuse are allowed; a discontinuity in the logical run is not.

Reject early, rebuild transactionally

The cheapest time to preserve contiguity is append: the first position is free, and every later reservation must target frontier + 1.

Lifecycle operations still need validation. Remove, rewind, shift, fork, copy, and restore can change the derived pooled groups. They rebuild those groups in a private candidate state and publish only when the complete run is valid.

If a caller intentionally needs segmented attention, that is a new semantic model with explicit segments—not permission to reinterpret a hole.

Failure boundary

c3759b5 verifies the fail-closed cache model across left-padding anchors, internal holes, slot reuse, wrap eviction, rewind, shift, copy/fork, serialization, atomic restore, and multiple sequences. The implementation remains a linked model-free partition: no production profile, artifact codec, or runtime-support admission selects it.