Reading is an evidence-gathering process. At the package layer, @lss/reader is intentionally narrow: it accepts simulated CandidateFragment observations, feeds them into @lss/protocol recovery, and returns reconstructed bytes or null.
Scan loop
Confidence signals
Useful package-level recovery facts include expected fragment count, recovered fragment count, audio candidate count, visual candidate count, checksum rejection, and whether XOR parity recovered exactly one missing data fragment. App-level camera or file detectors can add richer facts such as frame count, crop, lighting, and motion.
Reassembly rules
The recovery layer behaves more like a packet reassembler than a scanner callback. It accepts candidate fragments in any order, groups them by fragment messageId, rejects fragments whose checksum fails, and keeps the highest-confidence candidate for each messageId, fragmentIndex, and parityIndex.
Reconstruction should expose the same kinds of facts a network stack would care about:
- how many fragments were expected,
- which indexes were observed,
- whether parity fragments were used,
- how many audio and visual candidates contributed,
- whether the final signed envelope bytes were complete enough for the caller to parse and verify.
This makes scan failures debuggable. A product can tell the difference between “no LSS fragments found”, “fragments found but too many indexes missing”, “bytes reconstructed but signature failed”, and “payload valid but expired”.
Simulated detectors
@lss/reader includes simulated detector behavior so protocol and reconstruction tests can run without a camera. That keeps package tests deterministic while @lss/web can still expose real interactive reader workflows.
Resolver handoff
The reader should hand off reconstructed bytes, not product decisions. The caller is responsible for parsing the signed envelope, looking up the issuer public key, verifying the Ed25519 signature, checking expiry, and then passing the already-verified payload to @lss/resolver.