Files
lanspread/organize/testing/PEER_CLI_SCENARIOS.md
T
ddidderr 3bdd8d06da build(catalog): expose production publishing workflow
Add small Justfile entry points for generating the complete production
catalog authority or safely regenerating one game. Keep fixture validation
separate and allow operators to select a trusted unrar executable.

Document the complete package layout, BLAKE3 and ContentId model,
full/incremental publication procedure, verification and bundle gates, and
peer-CLI workflows. Record the fresh final local acceptance run without
presenting Docker throughput as physical-LAN evidence.

Test Plan:
- just fixture-catalogs-check
- just test
- just clippy
- just frontend-test
- just build
- LANSPREAD_S37_MIN_MIB_PER_S=100 just peer-cli-tests
- just catalog-check-production (expected fail-closed: production manifests absent)
- deno fmt --check README.md organize/testing/PEER_CLI_SCENARIOS.md
- rumdl check --flavor commonmark README.md organize/testing/PEER_CLI_SCENARIOS.md
- just --fmt --check
- git diff --check
2026-08-12 23:27:40 +02:00

98 KiB

Peer CLI P2P Scenarios

This matrix tracks the headless peer-to-peer contract exercised through lanspread-peer-cli. It intentionally avoids the GUI and uses direct connect for deterministic local runs; mDNS/macvlan remains an environment smoke path.

Scenario Matrix

ID Scenario Setup Expected result
S1 Startup scan Start one peer with fixture-alpha. Peer emits local-peer-ready and local-library-changed; catalog fixture games are downloaded=true, installed=false, availability=Ready.
S2 Direct connect handshake Start alpha and bravo, then connect each side to the other's authenticated peer endpoint. Both peers record one remote peer, no self-peer entry appears, and each direction's raw GameAvailability plus remote-library-view carries the exact ContentId from that side's fixture manifest.
S3 Remote aggregation Empty client connects to alpha and bravo. list-games shows remote-only games once; shared ggoo has peer_count=2, unique games have peer_count=1.
S4 Single-source download, no install Empty client connected to bravo downloads bfbc2 with install=false. The fixture manifest, raw GameAvailability, remote-library-view, and every verified download-chunk-finished agree on the exact ContentId; every chunk names bravo's authenticated PeerId. Download finishes with downloaded=true, installed=false; root files exist and local/ does not.
S5 Auto-install download Empty client connected to bravo downloads cnctw with default install. Download finishes, install begins and finishes, and local cnctw is downloaded=true, installed=true with local/fixture-payload.txt.
S6 Manual install and uninstall After S4, client sends install bfbc2, then uninstall bfbc2. Install marks bfbc2 installed and creates local/; uninstall removes local/ while preserving downloaded root files.
S7 Duplicate-source catalog download Empty client connects to alpha and bravo, which both advertise the exact catalog-version ggoo, then downloads it. The receiver uses its local catalog manifest as the sole descriptor/hash authority, completes exactly once with chunks from both eligible peers and no duplicate chunk, and the downloaded package matches the fixture bytes.
S8 Catalog file-shape enforcement and failover Two peers start with exact catalog-version ggoo; after their authenticated IDs are known, the lower-PeerId source's .eti is made oversized. A fresh second receiver then connects only to the oversized source. Exact catalog-file admission rejects the oversized archive assigned to the first authenticated source, and only the honest source supplies a successful archive chunk; an exact version.ini may validly come from either peer. The successful attempt has no invalid-data warning for this admission/transport rejection. The oversized-only receiver clears verification, emits download-failed with reason verified-catalog-sources-exhausted, and publishes neither version.ini nor local/.
S9 Known catalog game with no source An empty client asks for catalog-known cod6 while connected to no peers. The command acknowledges queueing, then emits an attempt-keyed download-failed with reason verified-catalog-sources-exhausted, without download-begin or verification activity. The game never enters active operations and no game root, version.ini, or local/ is created.
S10 Shutdown liveness cleanup Alpha and bravo are connected, then bravo shuts down. Within the named 125-second liveness allowance, pinned-liveness failure removes bravo and Alpha converges to an exactly empty authenticated-peer set and remote-library view. The protocol has no explicit departure control message.
S11 Same identity reconnect Bravo shuts down; Alpha first converges to an exactly empty peer set and remote-library view through bounded liveness, then Bravo restarts with the same state dir and reconnects. The OS-assigned listener port may or may not differ. Alpha has exactly one bravo peer entry reusing the same peer ID, not a duplicate identity, and sees Bravo's library again at the newly authenticated endpoint generation.
S12 Transfer serving gates A peer has a non-catalog, missing-sentinel, active-operation, or local/ path request. The serving peer declines the transfer request; covered by unit tests where timing is too small for a stable CLI race test.
S13 Exact transferred-file equality Repeat small and large downloads, then compare every transferred regular file against its source with SHA-256 manifests. Source and receiver manifests match exactly for each transferred file; no extra or missing files appear in the downloaded game root.
S14 Large multi-peer chunked download A source advertises a synthetic catalog game whose .eti is a sparse file of 4 * CHUNK_SIZE (four 128 MiB chunks). A second peer downloads it, then a third peer downloads it from both peers. The third peer's downloaded files match the source by SHA-256; download-chunk-finished shows the .eti split across exactly both peers, all four chunks accounted for, and the per-peer byte totals balanced within one CHUNK_SIZE (a fair 2+2 split; a 3+1 imbalance would trip the check).
S15 Exact-content source selection Peer A has a stale version.ini and publishes no availability. Peer B has a valid but different fixture catalog and ContentId. Peer C matches the client's exact catalog content. The client connects to all three and downloads with install=false. Raw views distinguish B's wrong ContentId from C's expected ContentId; the client's catalog-joined list-games reports peer_count=1. Every verified chunk carries the expected ContentId and C's authenticated PeerId; A and B contribute no verified bytes.
S16 Catalog-version fanout with stale peers present Peer A has a stale version of a game. Peers B and C both advertise the catalog version with matching manifests; the .eti is inflated to 2 * CHUNK_SIZE so it can fan out. The aggregated row counts only catalog-version ready peers. The .eti chunks split across exactly B and C; peer A is not listed as downloadable and contributes no manifest vote or file chunks.
S17 Catalog-byte verification and source quarantine Two peers start with exact catalog-version cnc4; after their authenticated IDs are known, the lower-PeerId source's .eti receives a same-length byte corruption. A fresh second receiver then connects only to the corrupt source. The first receiver detects the BLAKE3 mismatch, quarantines the corrupt source for that content ID, emits exactly one invalid-source retry activity after selecting the honest alternate, and only the honest source supplies a successful archive chunk; an exact version.ini may validly come from either peer. The all-bad receiver emits no false retry warning, clears verification, emits download-failed with reason verified-catalog-sources-exhausted, and publishes neither version.ini nor local/.
S18 Mid-download source drop with redundancy Client confirms two authenticated peers advertise the exact catalog ContentId, orders them by authenticated PeerId, then downloads a sparse 16 * CHUNK_SIZE archive. Once the lower-ID source has four active outbound streams, the harness confirms no terminal event has occurred and force-kills it. The download survives the active source failure without an invalid-data warning: no download-failed occurs, every verified chunk names the exact ContentId and one of the two authenticated PeerIds, all bytes arrive, and the receiver matches the surviving source. The surviving peer must complete the final even-offset chunk originally assigned to the lower-ID peer, proving retry rather than merely completion of its own initial plan.
S19 Mid-download sole-source drop Client downloads a sparse 8 * CHUNK_SIZE archive from one source. Once four outbound streams are positively active and no terminal event has occurred, the source is force-killed. The interrupted transport emits exactly one attempt-keyed download-failed with reason verified-catalog-sources-exhausted, after verification activity clears, and no download-finished; no invalid-data retry warning appears for a transport loss, no committed target version.ini or ready row remains, and the active operation drains so a retry is possible.
S20 Receiver write failure Client downloads a large game into a constrained /games filesystem. The attempt verifies received chunks, then emits exactly one download-failed with reason operation-failed; no committed version.ini is advertised, and active operation state clears so the peer can retry later.
S21 Add-game propagation Two connected peers are running; one peer gains a new catalog game root through a completed download or an external drop. The other peer receives a library update without reconnecting, and list-games shows the new remote game under the existing peer.
S22 Remove-game propagation Two connected peers are running; one peer loses a previously advertised game root. The other peer receives a library update without dropping the peer, and list-games no longer shows that remote game.
S23 Version bump propagation Two connected peers are running; one peer's ready game root starts with a stale version.ini, then changes to the catalog version. The other peer receives a library update without reconnecting; the stale row is absent before the change, then the catalog-version game appears as downloadable.
S24 Two clients pull from one source Two empty clients connect to the same source and download the same large game concurrently. Both downloads finish, both receivers match the source by diff or SHA-256, and the source remains responsive.
S25 One client downloads two games concurrently One client connected to a source issues two different download commands without waiting for the first to finish. Both operations may run in parallel; both eventually finish, each game reaches the requested install state, and each transferred root matches its source.
S26 Same-game duplicate download rejection A client starts downloading a game, then issues a second download command for the same game while the first operation is active. The second request is rejected deterministically as an operation-in-progress condition; the first download is not corrupted and still reaches its documented final state.
S27 Self-connect rejection A peer sends connect with its own peer ID and advertised listener address. The CLI command fails cleanly before dialing, no self-peer entry is created, and the peer remains responsive.
S28 Reconnect generation fencing The same authenticated peer endpoint is committed again, creating a newer endpoint generation, while a stale removal token from the earlier generation remains outstanding. The newer generation is strictly greater, the stale removal loses authority, and the current authenticated endpoint remains. This is covered by the deterministic unit test reconnect_gets_new_generation_and_stale_removal_loses_authority.
S29 Empty-library peer participates An observer and an empty peer share the ordinary network. The source starts only on a scenario-internal network; the empty peer is attached there and dials it directly, while the observer remains unable to authenticate the source. The observer first sees exactly the empty peer with zero games. After that peer downloads alienswarm, the observer remains authenticated only to it and receives its exact ContentId with peer_count=1; the downloader's verified chunks name the isolated source's authenticated PeerId. This proves local republishing without transitive library relay.
S30 5+ peer mesh aggregation Five peers advertise partially overlapping catalog games with a mix of unique and shared catalog-version games; a sixth client connects to all five. The client shows one row per game ID, correct catalog-version ready-source peer_count, catalog eti_game_version, no duplicates, and no self entries.
S31 Bootstrapped peer becomes source in same session An empty client downloads exact catalog content from one authenticated source, verifies every chunk's ContentId and source PeerId, then the original source is killed and a fresh third peer connects only to the bootstrapped client. The third peer's exact authenticated peer set is only the bootstrap, its remote view reports the exact content with peer_count=1, every verified chunk names the bootstrap's PeerId, and its files match the original source by diff or SHA-256. This proves downloaded files become servable without restart.
S32 Reinstall after uninstall A downloaded game is installed, uninstalled, then installed again without another download. local/ is recreated from preserved root files, no transfer events occur during reinstall, and the game returns to installed=true.
S33 Install after external root mutation A downloaded game root is externally mutated before install is issued. The CLI fixture installer installs from the current root bytes. The resulting local/fixture-payload.txt must match the mutated archive bytes exactly.
S34 Many-small-files game without .eti A catalog game root contains version.ini plus many small regular files and no archive. Download with install=false transfers every file, chunk events are coherent for small files, and source/receiver manifests match exactly.
S35 Unknown game ID from remote peer A remote peer's own catalog advertises a game ID and exact ContentId absent from the receiver's catalog. The raw peer snapshot and remote-library-view retain the typed availability, while the receiver's catalog-joined list-games omits it. Download fails deterministically and creates no local files.
S36 Exact-content singleton beats stale majority Five peers contain one game; one peer matches the client's catalog ContentId and four have stale versions that publish no transferable availability. Raw snapshots omit the stale roots, remote-library-view reports the exact ContentId once, and catalog-joined list-games has peer_count=1. Every verified chunk names that content and the singleton peer's authenticated PeerId.
S37 Single-source download throughput A source peer advertises a Rust-published temporary catalog profile with one sparse 2 GiB .eti; an empty client downloads it with install=false. The exact ContentId agrees across the raw snapshot, remote view, and all 17 authenticated verified-chunk events. The attempt emits begin, verification, clear, and exactly one keyed download-finished with no failure. The only canonical root-relative paths are sixteen bf1942.eti chunks with exact 128 MiB lengths and offsets plus one eight-byte version.ini chunk at offset zero. Local state is downloaded, ready, not installed, and drained. The complete receiver root matches the source by SHA-256/diff. Throughput reports internally consistent byte, chunk, duration, MiB/s, and Mbit/s measurements, with LANSPREAD_S37_MIN_MIB_PER_S defaulting to the 100 MiB/s normal-LAN gate.
S38 First-play launch-setting stamping fixture-persona/css ships a real RAR .eti whose tree buries a CRLF SmartSteamEmu.ini with a stub PersonaName line under engine/bin/win64/steam_settings/, plus a stub account_name.txt and language.txt under profiles/local/. A peer installs css (with --unrar), then sends play css with a username and language, then play css again. Before first play, the marker is absent and the installed bytes are exactly stubaccount, english, and the four-line CRLF INI with PersonaName = stubplayer. The first play returns all three write outcomes, stamps the requested values while preserving INI siblings/CRLF, and creates the marker. A second play returns already_applied=true, rewrites nothing, and leaves externally reset files untouched.
S39 Streamed install without keeping archive payload Source and empty client run alone on a scenario-internal network. The source has real RAR .eti payload entries under bin/ and data/; the receiver uses the container-bundled unrar provider and sends stream-install cnctw. One exact event window is Active Downloading → attempt-keyed download-beginverifying-downloaded-chunks → two authoritative verified files (bin then data, exact path/size/offset, catalog ContentId, source PeerId/address) → activity clear → Active Installing → matching download-finishedActive emptyinstall-finished, with no failure. Throughput is exactly 3 MiB/two files. Final state is local-only installed with no root sentinel/archive; payload SHA-256 matches unrar p, and the source transfer drains.
S40 Streamed install receiver is not a peer source After a streamed install, the original source shuts down. An observer starts alone on a fresh internal network, proves an empty roster, then the receiver is attached and dialled at its internal address. The observer roster becomes and remains exactly the receiver. Its authoritative raw snapshot, post-connect remote view, and catalog join omit local-only cnctw. An ordinary download acknowledges queueing, then emits attempt-keyed download-failed with reason verified-catalog-sources-exhausted and no begin or verification activity, success, active-operation snapshot containing cnctw, or game-root mutation.
S41 Solid archive streamed install Source and client run alone on a scenario-internal network using the solid catalog profile; the named source's .eti is verified as a real solid RAR before transfer. The client roster/raw view carry the exact solid-profile ContentId, and every verified file is bound to the named source's authenticated PeerId. Streamed install finishes local-only with no root archive/sentinel; byte count equals the extracted entries and payload SHA-256 matches unrar p.
S42 Streamed install integrity quarantine and retry On an internal network, a lower-PeerId source serves a valid solid archive whose output mismatches the default catalog; a higher-PeerId source serves the exact default package. Both advertise the same exact catalog ContentId. First install observes admission/drain edges on bad then good, emits one invalid-source retry activity only after rollback and alternate selection, and only good supplies authoritative verified files. After uninstall, the same client runtime retains both peers/raw availabilities; a second install observes good admission/drain, zero bad edges, and no invalid-source warning, proving runtime quarantine skip. Both keyed attempts finish with exact 3 MiB, good-source ContentId/PeerId, hashes, local-only state, and no staging/backup/sentinel/archive residue.
S43 Already-installed streamed install rejection A client first stream-installs cnctw, then attempts stream-install cnctw again. The second attempt emits download-failed with reason operation-failed and no begin or verification activity, does not emit a new success event, leaves the existing local-only install intact, and clears active operations.
S44 All-bad streamed integrity rollback Named source and client run alone on an internal network. The source advertises exact default content but serves a verified-solid cnctw archive whose extracted output mismatches that catalog. Exact roster/raw ContentId plus source admission/drain edges prove the named bad source was attempted. Catalog verification clears without falsely promising another source, then emits download-failed with reason verified-catalog-sources-exhausted; no download/install success occurs, active state drains, and no local/, staging, archive, or sentinel remains.
S45 Sender disconnect during streamed install Source and client run alone on an internal network for exact catalog alienswarm; after a verified chunk bound to that source PeerId/ContentId, the source is killed. All observed chunks remain exact-source authoritative. The transport interruption clears verification and promptly emits download-failed with reason verified-catalog-sources-exhausted, without an invalid-data warning, before stale-peer liveness can elapse; no success occurs, active state drains, and local/staging state rolls back.
S46 Receiver cancel during streamed install Source and client run alone on an internal network for exact catalog alienswarm; after a verified chunk bound to that source PeerId/ContentId, the receiver sends cancel-download. All observed chunks remain exact-source authoritative. Cancellation clears verification, drains active state, and rolls back local/staging state; graceful client shutdown then fences the completed JSONL slice, which contains no download/install success or user-visible download failure.
S47 Multi-archive streamed install order Source and client run alone on an internal network using fixture-multi/cnctw, with two root .eti archives named to require sorted processing. The client roster/raw view carry the exact multi-profile ContentId, and every verified file is bound to the named source's authenticated PeerId. Paths arrive in root archive sort order, both payloads install under local/, final state is local-only installed, and no root archive/sentinel is committed.
S48 Call to Play direct-author late join Alice creates a call; Bob publishes RSVP/chat intents against its generated CallId. Alice and Bob remain connected while Charlie starts on a separate internal-only Docker network shared with Alice; Bob joins it only after Charlie's first pull. Alice retains the exact Bob-inclusive view before and after Charlie's first pull, while Charlie's authenticated peer set is exactly Alice and its replacement contains only Alice's generated event ID. After the direct Bob pull it contains the exact three-event union once. Bob's departure converges to exactly Alice plus the creator event; Alice's departure then converges to an empty peer set and view.
S49 Terminal Call to Play direct-author late join Alice creates and later starts a call; Bob publishes ready/chat intents. Alice and Bob remain connected while Charlie first pulls Alice across an internal-only Docker network, then Bob joins that network for a direct pull. Alice retains the exact four-event view throughout the first pull; Charlie is authenticated only to Alice and sees create/start without Bob-owned IDs. Pulling Bob produces the exact four-event terminal view once; creator departure removes the complete call after bounded liveness convergence while Charlie's authenticated peer set remains exactly Bob.

Version-Skew Contract

Use S15-S17 to pin down what happens when several peers have the same game ID but only some match the receiver's exact catalog content:

  • The receiver's catalog is authoritative. A remote root whose version.ini does not match the catalog's expected version for that game ID is not downloadable.
  • list-games joins raw remote availability against the local manifest. The game appears once; peer_count counts only ready peers with the exact local ContentId.
  • The aggregated eti_game_version must be the catalog version.
  • File paths, sizes, chunk boundaries, and BLAKE3 values come exclusively from the receiver's bundled catalog. There is no remote descriptor preflight. Stale or wrong-ContentId peers must not supply verified chunks.
  • If exactly one peer has the catalog version, that peer is the only transfer source. If several peers match, chunk fanout uses that set; byte mismatches quarantine the exact source/content pair and retry elsewhere.
  • Capture proof by matching the fixture manifest ContentId to raw GameAvailability, remote-library-view, and every verified download-chunk-finished event. Chunk proof uses authenticated PeerId; the socket address is diagnostic only.

Extended Failure And Mutation Contracts

Use S18-S36 to pin down operational behavior that is awkward to prove with the GUI:

  • A failed download must not commit the root version.ini sentinel. Partial payload files may remain, but they must not be advertised as a ready local game and must not leave an active operation stuck.
  • Source failure during a redundant download should retry failed chunks against another validated source for the same catalog-version file.
  • Live local library changes are observable through revision hints followed by authoritative full snapshots; reconnect is not required for add, remove, or version-bump cases.
  • Same-game operations are single-flight. A duplicate download request while a game is already active is rejected instead of starting another writer.
  • Unknown remote game IDs are filtered by the receiver's current catalog and are not downloadable.

For a manual run, prefer a catalog game ID already served by the fixture lab, such as cnc4, then create temporary just peer-cli-run game roots where some peers match the catalog version and others deliberately use stale version.ini contents. The existing alpha/bravo/charlie fixtures cover duplicate-source and shared-game cases; S15-S17 add the focused skew cases.

First-Play Launch-Setting Contract

Use S38 to pin down how launcher settings are stamped into an installed game:

  • Stamping happens on the first play, not during install/update. The install transaction only clears the games/<id>/launch_settings_applied marker so the next play reapplies settings to a freshly (re)created local/.
  • The first play stamps the username into the first account_name.txt and the first SmartSteamEmu.ini PersonaName line, and the language into the first language.txt, searching the whole local/ tree. The matched PersonaName line keeps its existing line ending (\n or \r\n).
  • The marker records only that we tried: it is written unconditionally after the first play, so a game with none of these files is still marked done.
  • S38 needs a real archive expanded with --unrar; the Docker matrix image now carries the Linux sidecar for streamed-install coverage, while the peer crate's launch_settings unit tests cover the rewrite, line-ending, and marker logic deterministically.

Streamed Install Archive Contract

Use S39-S47 to pin down low-disk streamed installs:

  • The stream provider performs one archive metadata pass and one payload pass per .eti, then frames entry boundaries for the receiver.
  • Non-solid and solid archives both install into local/ without committing a root archive or root version.ini, so the receiver is installed but not a downloadable source.
  • RAR size/CRC32 checks are only an early sender-consistency check. The security boundary is the receiver's catalog-owned extracted path set, sizes, and BLAKE3 file hashes. Scenario SHA-256 comparisons independently demonstrate that the installed bytes match the intended fixture.
  • S41 verifies the fixture is actually solid inside the source container, so solid handling stays covered by the same Docker harness as the existing streamed-install scenarios.
  • S42 verifies integrity quarantine and retry: a valid archive with extracted output from the wrong catalog profile rolls back its staging directory, then the receiver retries the whole stream from an honest matching source. There is no byte-offset resume contract.
  • S43-S47 cover the remaining streamed-install failure and archive-shape edges: already-installed rejection, all-bad catalog mismatch rollback, sender disconnect, receiver cancel, and multi-archive root sorting.

Run Log

2026-08-12 - Final local acceptance refresh

  • A fresh-image LANSPREAD_S37_MIN_MIB_PER_S=100 just peer-cli-tests run passed every scenario from S1 through S49. S37 transferred and verified the exact 2,147,483,656 bytes in 17 chunks over 3.487s, reporting 587.33 MiB/s and 4926.92 Mbit/s against the active 100 MiB/s floor. These are Docker acceptance measurements on this host and storage, not representative physical-LAN performance evidence.
  • On the same source tree, just test passed all 708 workspace tests (including 480 peer and 56 Tauri tests), just clippy passed with warnings denied, just frontend-test passed 91/91, just fixture-catalogs-check passed, and just build passed the default fixture gate plus the Deno/Vite and release-mode Tauri build. just catalog-check-production separately failed closed because the external production manifest corpus is absent; no fixture authority was accepted as a production substitute.

2026-08-10 - Phase 5 Unfiltered Acceptance

  • A fresh-image LANSPREAD_S37_MIN_MIB_PER_S=100 just peer-cli-tests run passed every scenario from S1 through S49. S37 transferred the exact 2,147,483,656 bytes in 17 verified chunks over 3.716s, reporting 551.10 MiB/s and 4622.93 Mbit/s against the active 100 MiB/s floor. These are Docker acceptance measurements on this host and storage, not a representative external-LAN performance claim. The run included the attempt-keyed verification/retry/exhaustion traces, authenticated exact-content sources, structured cancellation and rollback, streamed-install lifecycle, same-runtime quarantine skip, direct-author Call to Play replacement, and non-vacuous bounded peer-departure proofs.
  • On the final implementation snapshot, just test passed all 708 workspace tests (including 480 peer and 56 Tauri tests), just clippy passed, just frontend-test passed 91/91, and just build passed the fixture catalog checks plus the Deno/Vite and release-mode Tauri build. just build uses fixture catalogs and is not the production corpus/bundle gate.

2026-08-10 - Phase 5 Typed Transfer Focused Acceptance

  • This fresh-image command passed all fourteen scenarios:

    LANSPREAD_S37_MIN_MIB_PER_S=100 just peer-cli-tests \
      S8 S9 S17 S18 S19 S20 S37 S39 S40 S42 S43 S44 S45 S46
    

    Their operation-local JSONL windows proved one canonical decimal attempt ID, exact begin/verification/retry/clear/terminal milestone order, no status after settlement, typed exhaustion versus local operation failure, no invalid-data warning for transport loss, and silent user cancellation. S42 emitted the invalid-source warning only for its first bad-to-good rollback; the same runtime's quarantined-source retry emitted none. S37 transferred 2,147,483,656 bytes in 17 verified chunks over 3.679s, reporting 556.69 MiB/s and 4669.84 Mbit/s against the active 100 MiB/s Docker-on-this-host acceptance floor. This focused run is retained as targeted evidence; the refreshed unfiltered S1-S49 result is recorded above.

2026-08-10 - Phase 4 v8 Unfiltered Acceptance

  • A fresh-image LANSPREAD_S37_MIN_MIB_PER_S=100 just peer-cli-tests run passed every scenario from S1 through S49. S37 transferred the exact 2,147,483,656 bytes in 17 verified chunks over 6.999s, reporting 292.61 MiB/s and 2454.61 Mbit/s against the active 100 MiB/s floor. These are Docker acceptance measurements on this host and storage, not an external LAN performance claim. The same unfiltered run exercised the strengthened exact-byte, lifecycle, topology, authenticated-source, quarantine, rollback, and cancellation proofs in S38-S47, plus the direct-author Call to Play and bounded-departure proofs in S48-S49.

2026-08-10 - Phase 4 v8 Focused Surface Acceptance

  • A fresh-image just peer-cli-tests S48 run passed the hardened direct-author topology. Alice retained the exact Bob-inclusive view while Charlie's authenticated peer set was exactly Alice and Charlie saw only Alice's creator event. After Bob joined Charlie's network, Charlie pulled the exact union directly; bounded liveness convergence then removed Bob's participant slice and finally Alice's complete call.
  • The unchanged-image command just peer-cli-tests S12 S42 S48 S49 then passed all four focused scenarios. S12 ran the current v8 transfer-admission unit suite. S42 assigned the lower authenticated PeerId to the catalog-mismatched source, quarantined it, and completed all 3,145,728 bytes from the exact honest source. S49 reconstructed terminal creator and participant slices by direct pulls and removed the complete call when the creator became stale, while Charlie's authenticated peer set remained exactly Bob.
  • A later fresh-image just peer-cli-tests S18 S19 S31 run passed the hardened source-failure cases. S18 observed four active outbound streams on the lower-PeerId source before force-killing it; the survivor then supplied all 2,147,483,648 archive bytes, including the final even-offset chunk originally assigned to the killed peer, with no failure event and an exact directory diff. S19 force-killed its sole source with four active streams and reached download-failed with no ready row, sentinel, or active operation. S31 proved exact ContentId and authenticated-source attribution on both the original download and the bootstrapped peer's same-session re-serve before matching the original fixture by diff.
  • A subsequent fresh-image just peer-cli-tests S29 S30 S31 run passed the isolated bootstrap topology. S29 kept its source on an internal network and attached only the empty peer; the observer remained authenticated exactly to that formerly-empty peer before and after its download, then saw its exact alienswarm ContentId with peer_count=1. S30 retained the expected six aggregate game rows and per-content source counts across five peers. S31 proved an exact bootstrap-only peer set and peer_count=1, with each chunk on the second hop attributed to that bootstrap before the directory diff matched.
  • With LANSPREAD_S37_MIN_MIB_PER_S=100, the existing frozen image then passed python3 crates/lanspread-peer-cli/scripts/run_extended_scenarios.py S37. The exact-content single-source download transferred 2,147,483,656 bytes in 17 verified chunks over 10.138s, reporting 202.02 MiB/s and 1694.64 Mbit/s. All events carried the catalog ContentId and authenticated source PeerId; their canonical root-relative paths comprised sixteen exact bf1942.eti offsets plus version.ini, and the complete receiver directory matched the source by SHA-256/diff. The configured 100 MiB/s floor was active.
  • The same frozen image then passed python3 crates/lanspread-peer-cli/scripts/run_extended_scenarios.py S40 S45. S40 shut down the original source before starting the observer; the observer authenticated exactly the local-only receiver, whose raw snapshot and post-connect remote view both omitted cnctw, then observed the queued ordinary download fail asynchronously without a game-root mutation. S45 killed its sender after the first verified alienswarm stream chunk and observed prompt download-failed, no success, drained active state, and complete local/staging rollback before stale-peer liveness could elapse.
  • The frozen image then passed the Python scenario runner for S38 S39 S40 S41 S42 S44 S45 S46 S47. S38 proved the exact account, language, and CRLF INI stub bytes before first play. S39 proved the complete ordered streamed-install lifecycle, including both exact verified chunks (3,145,728 bytes total) from the isolated named source. S40 proved an isolated empty-to-receiver topology and an asynchronous no-source failure with no active-operation event or local mutation. S41 streamed the named solid source and reproduced both expected hashes over 118 bytes. On S42's first install, the mismatched and honest sources each emitted exactly two admission/drain edges; after uninstall, the same receiver runtime emitted zero further edges for the quarantined source and exactly two for the honest source while reproducing the exact 3,145,728 bytes and hashes. S44 proved the sole bad source was admitted and drained before rollback. S45 bound its first verified chunk and prompt sender-loss failure to the exact authenticated source and ContentId. S46 used a strict graceful event-loop drain to prove receiver cancellation emitted no terminal success or failure. S47 bound the sorted multi-archive install to its isolated named source.
  • This was a focused post-cutover acceptance run, not a new unfiltered S1-S49 run. The full run below predates the final v8 Call to Play harness and compact catalog-index cutovers and is retained only as historical baseline evidence.

2026-08-10 - Earlier Catalog Authority S1-S49 Baseline

  • Built a fresh lanspread-peer-cli:dev image after the streamed-install durability changes. The focused acceptance command LANSPREAD_S37_MIN_MIB_PER_S=100 just peer-cli-tests S8 S17 S37 S42 S44 passed all five scenarios. S8 and S17 proved ordinary-download failover and all-bad rollback for oversized and same-length-corrupt catalog content. S42 and S44 proved streamed-install quarantine/retry and all-bad rollback for a valid archive whose extracted output mismatched the local catalog authority.
  • The exact unfiltered command LANSPREAD_S37_MIN_MIB_PER_S=100 just peer-cli-tests then passed S1-S49. This includes the source-only unknown-game profile in S35, the solid profile in S41, the multi-archive profile in S47, and the runtime-published temporary profiles used by the large-file scenarios. These catalogs and manifests are generated by the Rust fixture publisher; the peer does not derive authority from runtime package contents.
  • Fresh post-catalog-hash S37 evidence from the unfiltered run: a 2.00 GiB single-source download completed in 3.651s at 560.93 MiB/s (4705.43 Mbit/s) and emitted exactly 17 verified chunks: sixteen 128 MiB archive chunks plus version.ini. Environment: host pfs-arch, Linux 7.1.6-arch1-1 x86_64, Docker network lanspread, dynamic profile dynamic-s37, storage path .lanspread-peer-cli/extended-scenarios on /dev/dm-2 (btrfs), date 2026-08-10. The 100 MiB/s normal-LAN acceptance floor was active.
  • The repository still intentionally contains no fabricated 186-game production manifest corpus. The production bundle gate therefore remains fail-closed until the publisher is run against the real package source.

2026-07-21 - Call to Play Transport (S48)

  • Added JSONL commands to publish local Call to Play intents and inspect full replacement views.
  • S2 passed against the rebuilt image, preserving bidirectional library exchange after the protocol version bump.
  • The Phase 4 scenario now captures core-generated receipt IDs and proves that a late third peer sees only Alice's author slice until it pulls Bob directly.

2026-06-21 - Test-Suite Integrity Audit And Hardening

  • An adversarial review of run_extended_scenarios.py found assertions that passed vacuously, raced, or diverged from the spec. A full baseline run (S1-S47, rebuilt image) passed beforehand, confirming these were test-quality gaps, not peer regressions. Baseline evidence of the gaps: S14 chunk totals were {134217728, 1048576} (a 2-chunk file whose "balanced within one chunk" check can never fail), and S16/S18 each served the whole ~120 MiB alienswarm.eti from a single source, so neither fanout (S16) nor retry-onto-survivor (S18) was actually exercised.
  • Fixes applied to the runner (and the matching rows above):
    • S18: replaced the dead assert_no_event (it reused a LineWaiter already advanced past download-finished, so it scanned an empty tail and could never fire) with assert_no_event_since over the whole download window; switched to a multi-chunk sparse archive (4 * CHUNK_SIZE) so both peers own .eti chunks and the test proves the download survives a mid-download source kill (retry-onto-survivor is the mechanism, exercised when the kill interrupts an unfinished chunk, but not asserted since the race can't be forced).
    • S7: added chunk-source, both-sources-served, single-download-finished, and no-duplicate-chunk checks (the byte-identical ggoo fixtures made the old diff-only assertion source-agnostic).
    • S14: 4 * CHUNK_SIZE file so the balance check is meaningful (a 3+1 split would now exceed one chunk); asserts an exact 2+2 split and full byte total.
    • S16: inflated .eti to 2 * CHUNK_SIZE so it fans out across both catalog-version peers (the stock 120 MiB fixture is a single chunk).
    • S19: force-kill right after download-begin on a multi-chunk file, require the typed download-failed source-exhaustion terminal, assert no download-finished (the old graceful shutdown could let a single-chunk transfer finish first).
    • S26: large sparse source so the first op is reliably still active, and asserts the active operation == "Downloading" (no scenario checked it).
    • S37: validates the throughput rate fields (positive, self-consistent mbit_per_s/mib_per_s == 8.388608, mib_per_s == bytes/duration), not just the byte count.
    • S35: asserts the source actually advertises cod2 with its typed ContentId before checking the receiver's local catalog filters it.
    • S15: cross-checks raw typed availability for the wrong and expected ContentId values; the catalog-joined list counts only the expected one.
    • S2: polls for library convergence and verifies the bidirectional exchange (bravo sees alpha's 3 games, not just alpha seeing bravo's 4).
    • S11: dropped the "listener address must change" assertion (it tested the OS ephemeral-port allocator and could fail spuriously).
    • S12/S28: require the gating unit test to appear as <name> ... ok so an #[ignore]d (un-run) test no longer satisfies the check.
    • S24/S25: assert the requested install=false final state.
    • S34: assert exactly 21 coherent chunks (20 files + version.ini), 21 distinct paths, no duplicates, instead of a >= 21 floor.
    • Historical S27 note: protocol v7 added the handshake::tests::inbound_hello_from_self_is_ignored test for its Hello self guard. That test and handshake shape were removed by v8; the current CLI scenario independently proves typed self-connect rejection and this old test name is not current acceptance evidence.
    • Harness: find_fixture_game now iterates sorted(...), so the ambiguous cnctw (bravo/multi/solid) resolves deterministically to fixture-bravo.
  • Accepted as-is (reviewed, deliberately not changed): S20 (disk-full via chunk write_all is equivalent coverage), S21 (inotify across the bind mount is inherent to the harness), S30 (dup-row/self-peer checks are cheap defensive guards), and S32/S39/S44 absence checks (cheap regression guards against committing a root sentinel). S45 remained unchanged at this historical checkpoint; current acceptance requires the prompt transport download-failed rather than a later stale-peer event. S42 now persists two honest installation identities first, assigns the mismatching profile to the lower decoded PeerId, and proves that only the higher-ID honest source emits verified chunks after retry/quarantine.
  • Live runs against the rebuilt lanspread-peer-cli:dev image: baseline S1-S47 passed; post-fix S1-S47 passed. Post-fix evidence: S14 {268435456, 268435456} (balanced 2+2); S16 .eti split across B and C {134217728, 134217728}; S18 all 536870912 bytes delivered despite the source drop (the survivor served the whole archive in that run); S19 deterministic download-failed; S37 874.24 MiB/s. Gates: just test (incl. the new handshake test), just clippy (-D warnings), and just fmt all passed.

2026-06-20 - Prune Dead Lifecycle Events

  • Code under test removed the unconsumed InstallGameBegin, UninstallGameBegin, and RemoveDownloadedGameBegin PeerEvent variants (and their peer-cli JSONL install-begin/uninstall-begin/remove-download-begin events), plus the Tauri webview emits that no frontend listener consumed (peer-local-ready, game-download-begin, game-download-pre, game-download-finished, game-uninstall-finished, peer-connected/-disconnected/-discovered/-lost). peer-runtime-failed was kept pending a UI decision.
  • Rationale: the GUI is state-as-source-of-truth (it renders the games-list snapshot), and no scenario asserted these begin events; the install, uninstall, and removal start transitions stay observable via active-operations-changed.
  • Contract update: the S39 row no longer lists install-begin. Older run-log entries below predate the removal and are left intact as historical records.
  • Gates: just test, just clippy, just frontend-test, and just build passed. (just fmt's tombi step needs network and was skipped; no TOML changed.) The Docker S39-S47 matrix was not re-run for this cleanup; S39-S47 never asserted the removed begin events, so coverage is unchanged.

2026-06-07 - Catalog-Version Matrix Alignment (S1-S47)

  • Code under test aligned checked-in fixture version.ini sentinels with the catalog, made run_extended_scenarios.py stamp generated fixture games with catalog versions by default, updated S15-S17/S23/S30/S36/S37 to assert catalog-authoritative aggregation, and wired S38 into the executable matrix.
  • Gates before Docker: python3 -m py_compile crates/lanspread-peer-cli/scripts/run_extended_scenarios.py passed.
  • The rebuilt-image Python runner passed S3, S8, S14-S17, S21-S24, S29-S31, S34, S36-S37, and S39-S47 with --build-image.
  • S38 standalone runner: python3 crates/lanspread-peer-cli/scripts/run_extended_scenarios.py S38 passed, proving the real-RAR css fixture installs with the container /usr/local/bin/unrar sidecar and stamps launch settings only once.
  • Full matrix runner: python3 crates/lanspread-peer-cli/scripts/run_extended_scenarios.py passed for S1-S47 against the rebuilt lanspread-peer-cli:dev image.
  • The final full-run highlights included S3 aggregation, S15-S17 catalog-version skew/fanout/conflict, S23 stale-to-catalog propagation, S30 mesh aggregation, S36 catalog singleton over stale majority, S37 throughput, S38 first-play stamping, and S39-S47 streamed-install coverage.

2026-06-07 - Streamed Install Edge Coverage (S43-S47)

  • Code under test added cancel-download to lanspread-peer-cli, added the tiny fixture-multi/cnctw two-archive fixture, and added S43-S47 in run_extended_scenarios.py.
  • Gates before Docker: just fmt and python3 -m py_compile crates/lanspread-peer-cli/scripts/run_extended_scenarios.py passed.
  • The Python runner passed S43-S47 with --build-image against the rebuilt lanspread-peer-cli:dev image.
  • S43 stream-installed cnctw, retried stream-install cnctw, observed download-failed, and verified the existing local-only install stayed intact.
  • S44 replaced the source cnctw.eti with invalid bytes. The receiver emitted download-failed, cleared active operations, and left no local/, .local.installing, root archive, or root version.ini.
  • S45 killed the sole alienswarm source after the first streamed chunk. The receiver ended with download-failed, emitted no success, cleared active operations, and rolled back local/staging state.
  • S46 cancelled alienswarm on the receiver after the first streamed chunk. The receiver emitted no success and no user-visible download-failed, cleared active operations, and rolled back local/staging state.
  • S47 streamed fixture-multi/cnctw and observed chunk paths in sorted root archive order: cnctw/.local.installing/order/first.txt, then cnctw/.local.installing/order/second.txt.

2026-06-07 - Streamed Install Whole-Stream Retry (S42)

  • Code under test added S42 in run_extended_scenarios.py.
  • Gates before Docker: python3 -m py_compile crates/lanspread-peer-cli/scripts/run_extended_scenarios.py passed.
  • Runner: python3 crates/lanspread-peer-cli/scripts/run_extended_scenarios.py S42 passed against the current lanspread-peer-cli:dev image.
  • S42 started a broken source with --unrar /missing-unrar and a good source with the same catalog-version cnctw metadata. The broken source sorted first (10.66.0.2:32897) and the good source second (10.66.0.3:34092).
  • The broken source contributed zero chunks; the good source completed the fresh whole-stream attempt with 3145728 streamed file bytes.
  • The final client state was downloaded=false, installed=true, availability=LocalOnly, with no root version.ini, no root cnctw.eti, and no .local.installing staging directory. Payload SHA-256 hashes matched the good source's unrar p output.

2026-06-07 - Solid Streamed Install Coverage (S41)

  • Code under test added fixture-solid/cnctw, a real solid RAR .eti, plus S41 in run_extended_scenarios.py.
  • Gates before Docker: just fmt, git diff --check, and python3 -m py_compile crates/lanspread-peer-cli/scripts/run_extended_scenarios.py passed.
  • Runner: python3 crates/lanspread-peer-cli/scripts/run_extended_scenarios.py S41 --build-image passed against the rebuilt lanspread-peer-cli:dev image.
  • S41 verified the source archive with unrar lt -cfg- inside the source container; the archive reported Details: RAR 5, solid.
  • The streamed install finished with downloaded=false, installed=true, availability=LocalOnly, no root version.ini, and no root cnctw.eti.
  • The client received 118 streamed file bytes, matching the extracted solid entries. Payload SHA-256 hashes matched unrar p output: 88764c9a6c9b5b846b4323cf7725cb7fd70766ddd7fba4168332804a839fa193 (bin/cnctw-solid-payload.bin) and 44afc308269b2381b7c707a056dd8d9d393274108ac4d880237fa6772c861d7a (data/cnctw-solid-assets.dat).

2026-06-07 - Streamed Install Prototype (S39-S40)

  • Code under test added stream-install to lanspread-peer-cli, a peer StreamInstallGame command, streamed install frames over QUIC, and an injected unrar lt/unrar p provider for archive-derived bytes.
  • Gates before Docker: just fmt and RUSTC_WRAPPER= CARGO_BUILD_RUSTC_WRAPPER= just test passed for the workspace.
  • Runner: python3 crates/lanspread-peer-cli/scripts/run_extended_scenarios.py S39 S40 --build-image passed against the rebuilt lanspread-peer-cli:dev image.
  • S39 streamed a catalog-version-adjusted cnctw fixture from a real RAR .eti into the receiver's local/ only. The receiver had downloaded=false, installed=true, availability=LocalOnly, no root version.ini, no root .eti, and payload SHA-256 hashes 82f4da22dc042166def2a5ee2eca19fc9e52785f99838e86c32167cb342e2588 (bin/cnctw-payload.bin) and abf833a06c74ea9f17d505c2684186491898ce906405e0f098f0deac19476b06 (data/cnctw-assets.dat) matching unrar p.
  • S40 connected an observer only to that streamed-install receiver. The observer saw the receiver's cnctw summary as local-only, remote aggregation hid it as a downloadable source, and download cnctw failed with no peers have game cnctw.

2026-05-28 - First-Play Launch-Setting Stamping (S38)

  • Code under test moved the account_name.txt/language.txt overwrite out of the install transaction and into a single first-play step (shared with the new SmartSteamEmu.ini PersonaName rewrite) gated by the games/<id>/launch_settings_applied marker.
  • just test passed the whole workspace, including the new lanspread_peer::launch_settings unit tests and install::transaction::tests::install_resets_launch_settings_marker.
  • S38 host run: built crates/lanspread-peer-cli/fixtures/fixture-persona/css with a stored RAR .eti (verified by unrar t) burying a CRLF SmartSteamEmu.ini plus stub account_name.txt/language.txt. A host peer installed css with --unrar /usr/bin/unrar, then play css stamped the username into the deep PersonaName line (CRLF preserved, sibling lines intact) and account_name.txt, the language into language.txt, and created the marker. A second play css returned already_applied=true and rewrote nothing even after the value was reset externally.

2026-05-19 - Snapshot Status Fix Docker Matrix Pass

  • Code under test included 5c4976d (fix(peer): settle local state before clearing operations) and 6651f02 (fix(ui): derive operation status from snapshots).
  • Gates before the matrix: just fmt, just test, just frontend-test, and just build passed. The peer harness image was rebuilt with just peer-cli-image.
  • Runner: python3 crates/lanspread-peer-cli/scripts/run_extended_scenarios.py passed S1-S36 against the rebuilt lanspread-peer-cli:dev image.
  • Auto-install coverage remained good: S5 downloaded and installed cnctw, saw the fixture payload under local/, and the downloaded root diffed cleanly against fixture-bravo/cnctw excluding local metadata.
  • Large/exact transfer coverage remained good: S13 small and large downloads diffed cleanly; S14 split alienswarm between two sources with chunk totals 67,108,864 and 58,721,049 bytes and the final root diffed cleanly.
  • Failure and mutation coverage remained good: S17 latest-version conflict, S19 sole-source drop, S20 write failure, S26 duplicate operation, and S35 unknown catalog filtering all failed safely without advertising bad local state; S21-S23 propagation, S24-S25 concurrency, S29-S31 bootstrapping, S32 reinstall, S33 mutation install, S34 many-small-files, and S36 latest singleton all passed.

2026-05-18 - Full Automated Docker Matrix Pass

  • Historical pre-v8 record: this section describes the then-current image and does not establish current typed-identity, exact-ContentId, or v8 admission behavior. See the 2026-08-10 focused acceptance entry for current evidence.
  • Runner: python3 crates/lanspread-peer-cli/scripts/run_extended_scenarios.py passed S1-S36 against the then-current lanspread-peer-cli:dev image.
  • S1-S17 rerun highlights: startup, direct connect, aggregation, download, install/uninstall, duplicate-source, ambiguous metadata, missing game, shutdown cleanup, identity reconnect, serve gates, exact equality, large multi-peer chunking, and latest-version selection/conflict all passed. Exact transfer scenarios used diff -r/SHA-256 manifest checks; S14 chunk totals were 58,721,049 and 67,108,864 bytes, balanced within one 32 MiB chunk.
  • S18-S36 rerun highlights: source-drop, disk-full, live mutation, concurrency, duplicate-operation rejection, self-connect rejection, empty-peer sourcing, 5-peer aggregation, bootstrapped sourcing, reinstall, external mutation, many-small-files, unknown catalog filtering, and stale-majority/latest singleton cases all passed. File-copy scenarios used diff/manifests or cmp for the mutated install payload.

2026-05-18 - Extended Scenario Docker Pass

  • Historical pre-v8 record: the scenario details below preserve the behavior tested at that date and are not current v8 authority or admission evidence.
  • Runner: python3 crates/lanspread-peer-cli/scripts/run_extended_scenarios.py passed for S18-S36 after rebuilding lanspread-peer-cli:dev with just peer-cli-image.
  • S18 redundant source drop: one alienswarm source was killed after download-begin; the client emitted download-finished, no download-failed, and diff -r/SHA-256 manifest comparison matched the surviving source. Recorded large-file chunk bytes from the surviving source: 58,721,049.
  • S19 sole-source drop: killing the only source after download-begin emitted download-failed; the receiver had no committed alienswarm/version.ini, no ready local row, and no active operation left.
  • S20 receiver write failure: a client with /games constrained to a 32m tmpfs emitted download-failed; /games/alienswarm/version.ini was absent inside the container and active operations were empty.
  • S21-S23 live mutation propagation: a connected peer observed cod5 added, cod5 removed, and cnc4 bumped from 20250101 to 20260501 without reconnecting or dropping the peer.
  • S24-S25 concurrency: two clients downloaded alienswarm from one source at the same time and both diffed cleanly; one client downloaded bfbc2 and cnctw concurrently and both roots diffed cleanly.
  • S26 duplicate same-game download: the second alienswarm download command returned operation already in progress for game alienswarm; the first download still finished and diffed cleanly.
  • S27 self-connect rejection: connecting a peer to its own listener returned cannot connect peer to itself ...; list-peers stayed empty and the peer stayed responsive.
  • Historical S28 recorded the then-current address-change invariant; it does not establish the current v8 proof. Current S28 uses peer_db::tests::reconnect_gets_new_generation_and_stale_removal_loses_authority.
  • S29 empty-library peer: an observer first saw the empty peer with zero games; after that peer downloaded alienswarm, the downloaded root diffed cleanly and the observer's peer snapshot for that same peer contained alienswarm.
  • S30 5-peer aggregation: a sixth client connected to five peers and aggregated six game IDs with expected peer_count and latest versions, with no duplicate game rows and no self-peer entry.
  • S31 bootstrapped source: after the original source was killed, a third peer downloaded alienswarm from the bootstrapped client and diffed cleanly against the original fixture.
  • S32 reinstall: reinstall after uninstall recreated local/, reported installed=true, and produced no transfer chunk events during reinstall.
  • S33 external root mutation: after mutating the downloaded bfbc2.eti inside the client container, install wrote local/fixture-payload.txt that matched the mutated archive exactly by cmp.
  • S34 many-small-files transfer: a bf1942 fixture with 20 small regular files and no .eti downloaded with install=false; 21 file chunks were observed including version.ini, and the receiver diffed cleanly against the source.
  • S35 unknown game ID: a source advertised cod2; the receiver filtered it from list-games, rejected the download, and created no local files.
  • S36 latest singleton: four stale-version roots and one then-current root were present; the client selected the singleton current-version source and completed the download. This historical result does not establish the later exact-ContentId and authenticated-source contract.

2026-05-18 - Full Matrix Manual Docker Pass

  • Historical pre-v8 record: command names, protocol behavior, and unit coverage below belong to that snapshot. They are not evidence that current v8 tests ran in May; current v8 admission proof is recorded in the 2026-08-10 entry.
  • Build/setup: just peer-cli-image passed. Local just peer-cli-build needed RUSTC_WRAPPER= because the host kache wrapper failed with a read-only filesystem error; RUSTC_WRAPPER= just peer-cli-build passed.
  • Temporary skew/conflict fixtures were created under the ignored .lanspread-peer-cli/full-fixtures/ tree using rar a -idq -m0 against /dev/urandom payloads and then renaming the archives to .eti. find .lanspread-peer-cli/full-fixtures -name '*.eti' -exec unrar t -idq {} \; passed.
  • S1 startup scan: just peer-cli-alpha emitted cli-started, local-library-changed, and local-peer-ready; alienswarm, bf1942, and ggoo were downloaded=true, installed=false, availability=Ready.
  • S2 clean direct connect: with only alpha and bravo running, alpha connected to bravo at 10.66.0.3:42776; wait-peers returned peer_count=1, and list-peers showed exactly one bravo peer with four games.
  • S3 clean remote aggregation: an empty clean-s3-client saw exactly alpha and bravo. list-games showed ggoo peer_count=2; alienswarm, bf1942, bfbc2, cnc4, and cnctw each had peer_count=1.
  • S4 single-source no-install: full-empty-client downloaded bfbc2 from bravo with install=false. Events included download-begin, verified chunk completions, download-finished, and local installed=false. Host verification: diff -r crates/lanspread-peer-cli/fixtures/fixture-bravo/bfbc2 .lanspread-peer-cli/full-empty-client/games/bfbc2 passed and local/ was absent.
  • S5 auto-install: full-empty-client downloaded cnctw with default install. Events included download finish, install-begin, and install-finished; local/fixture-payload.txt existed. Host verification diffed the downloaded files against fixture-bravo/cnctw excluding local/ and .lanspread.json.
  • S6 manual install/uninstall: after S4, install bfbc2 created local/ and marked installed=true; uninstall bfbc2 removed local/ and preserved the downloaded root files. Host verification diffed the preserved files against fixture-bravo/bfbc2 excluding .lanspread.json.
  • S7 duplicate-source download: full-empty-client downloaded shared ggoo from alpha/bravo with install=false. Chunk events used alpha for version.ini and bravo for ggoo.eti; host diff -r matched both fixture-alpha/ggoo and fixture-bravo/ggoo.
  • S8 ambiguous metadata rejection: full-s8-a and full-s8-b both advertised ggoo version 20260101 but with different .eti sizes (1,048,746 and 2,097,323 bytes). The client saw peer_count=2, then download ggoo emitted download-failed; no target ggoo/version.ini was committed.
  • S9 missing game: download does-not-exist emitted no-peers-have-game and returned a command error; .lanspread-peer-cli/full-empty-client/games had no does-not-exist directory.
  • S10 shutdown cleanup: alpha saw bravo before shutdown with one remote peer and bravo-only remote games. After bravo shutdown, alpha emitted peer-lost; list-peers returned [] and list-games returned an empty remote list.
  • S11 same identity reconnect: restarting bravo reused peer ID 019e347d901e70c19adf5b9fd313fce4 at new address 10.66.0.3:41764. Alpha list-peers showed exactly one bravo entry at the new address.
  • S12 transfer serving gates: this remains covered by unit tests because the CLI cannot stably race raw transfer requests against non-catalog, missing sentinel, active-operation, and local/ path states. RUSTC_WRAPPER= just test passed its then-current serve-gate coverage; this historical entry intentionally does not attribute later v8 test names to that run.
  • S13 exact transferred-file equality: the S4 small transfer and S14 large transfer both passed host diff -r against the original source game directories, proving exact file equality beyond event flow.
  • S14 large multi-peer chunked download: full-empty-client first downloaded alienswarm from alpha and diffed cleanly against fixture-alpha/alienswarm. A fresh full-s14-client then saw alienswarm peer_count=2 and downloaded from both alpha and full-empty-client. Large .eti chunk totals were 67,108,864 bytes from alpha and 58,721,049 bytes from the staged peer, balanced within one 32 MiB chunk. Final host diff -r against fixture-alpha/alienswarm passed.
  • S15 three-way version skew: peers A/B/C advertised cnc4 versions 20250101, 20250201, and 20250301. The client saw one row with peer_count=3 and eti_game_version=20250301; all chunks came only from C at 10.66.0.4:60290. Host diff -r against C passed.
  • S16 latest-version fanout with stale peer present: A advertised stale 20250101; B/C both advertised latest 20250301 with a 134,217,906 byte .eti. The client saw peer_count=3; chunks came only from B/C (67,108,873 and 67,109,042 bytes respectively), with stale A contributing zero. Host diff -r matched both B and C.
  • S17 latest-version conflict rejection: A advertised stale 20250101; B/C both advertised latest 20250301 but with conflicting .eti sizes (1,048,748 and 2,097,325 bytes). The client saw peer_count=3 and latest 20250301, then download cnc4 emitted download-failed; no target cnc4/version.ini was committed.
  • Gates after manual runs: just fmt, RUSTC_WRAPPER= just test, and RUSTC_WRAPPER= just clippy passed.

2026-05-17 - Exact Transfer And Large Multi-Peer Chunking

  • Fixture update: fixture-alpha/alienswarm/alienswarm.eti was rebuilt with rar a -idq -m0 from three random 40 MiB payload files, then renamed to .eti. Final archive size: 125,829,913 bytes. unrar t -idq passed.
  • Gates before manual runs: just fmt, just test, just peer-cli-build, just clippy, and just peer-cli-image passed.
  • S13 small exact transfer: deep-small-client downloaded bfbc2 from fixture-bravo with install=false. SHA-256 manifests matched exactly: bfbc2/bfbc2.eti f7accef0833f29481acdeaac58261bc4fc23ebb58b7197049024d354f60daabc; bfbc2/version.ini f3d94f70edcebbbc7d8ce38fdf076412fb95114ce1ecf071b26c9c2f93586372.
  • S13 large exact transfer: deep-stage-b downloaded alienswarm from fixture-alpha with install=false. SHA-256 manifests matched exactly: alienswarm/alienswarm.eti 8a4fb1fd458e731affb175134b7b99efc8d8a5eda80e978ba81f721d01aecc43; alienswarm/notes.txt 3832bcb7057a4453981e975d2d2d528bfd9a26671423352f4a8527362d5b9810; alienswarm/version.ini 8dfdc51d4dbfb06015b41a85a5f5d47f44144139e4a12db2b17eb040773082a3.
  • S14 multi-peer setup: deep-stage-c connected to alpha (10.66.0.3:53514) and deep-stage-b (10.66.0.2:58491). list-games showed alienswarm with peer_count=2 before the download.
  • S14 chunk-source evidence for alienswarm/alienswarm.eti: deep-stage-c received chunks from deep-stage-b at offsets 0 and 67,108,864 (67,108,864 bytes total) and from alpha at offsets 33,554,432 and 100,663,296 (58,721,049 bytes total). The source-byte difference was 8,387,815 bytes, below one 32 MiB chunk.
  • S14 final exactness: deep-stage-c's alienswarm SHA-256 manifest matched fixture-alpha exactly for alienswarm.eti, notes.txt, and version.ini.