Skip to content

Commit fd7e02a

Browse files
doublegateclaude
andcommitted
docs(roadmap): lockstep re-check vs v2.2.5; close a flag the ladder answered
Three corrections and one new finding, all in the planning docs. No code. The 2026-07-15 lockstep flag still said rustysnes-netplay had "none of" RustyNES's netplay depth, naming six symbols. Three of them now exist: DesyncStatus, PeerLink, and SpectatorSession/delay_frames all shipped in v1.27.0 "Tether". The other three -- SignalMessage, ListRooms, QuickMatch -- are the SERVER side, left out on an explicit scope decision rather than by omission. That distinction is the whole point of the flag, so the entry now draws it instead of asking for a go/no-go on work that landed. This is the same staleness v1.26.0 corrected for the GIF/WAV and CRT-preset flags. The AccuracySNES header said 332 tests / 344 of 443 against two references. It is 346 / 361 of 443 against three, across three tiers that are never summed. The generated report cannot drift; a hand-quoted figure can, and this one had -- the line now says so. NEW, and flagged rather than scoped: RustyNES cut v2.2.5 "Colophon", a provenance/licensing audit prompted by community review. This project's own surface was MEASURED, not assumed: 23 in-source comments claim a port naming a reference emulator. Most read "clean-room port of ares (ISC)" and cite the upstream file, which is the benign shape. TWO name bsnes, which is GPLv3. NOTICE is five lines and discloses nothing concrete -- not the oracle use, not the vendored rcheevos tree (whose own LICENSE is present in-tree, so this is an aggregation gap, not a missing licence). Deliberately NOT acted on. Whether a comment is inaccurate -- the behaviour implemented from fullsnes/anomie with the emulator used only as an oracle, which is this project's documented method everywhere else -- or accurate, and therefore a licensing question, cannot be settled by grepping it. That is a maintainer determination. The check establishes the surface only, and ref-proj/ is gitignored and undistributed, which bounds it to the comments. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent d013ff1 commit fd7e02a

2 files changed

Lines changed: 49 additions & 12 deletions

File tree

‎to-dos/LOCKSTEP-CHECKLIST.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,4 @@ continuously.
5454
| 2026-07-12 | `v2.1.10` / `main` | 5 RustyNES releases since baseline (`v2.1.6`–`v2.1.10`). New: a GIF/WAV screen+audio capture subsystem (`v2.1.9`); 3 marquee libretro-slang CRT presets (CRT-Royale, guest-advanced, Sony Megatron, `v2.1.9`) vs. RustySNES's own single scanline+aperture-mask `Crt` filter; a SIMD software blitter + wasm-size/startup pass (`v2.1.8`); browser RetroAchievements + Vs. DualSystem libretro support (`v2.1.10`). Raw NTSC composite-signal decode (`v2.1.9`) confirmed genuinely NES-specific (8:1 dot-clock subsampling, no SNES analog) — validates `v1.12.0`'s own out-of-scope call. `v2.1.6`/`v2.1.7` (expansion-audio oracle, 2A03/PPU die-revision modeling) are NES-chip-specific, not applicable. | Capture subsystem: **large catch-up**, no RustySNES rung exists — flagged in `to-dos/ROADMAP.md`'s "Milestones beyond the phases" for a maintainer go/no-go, not silently scoped in. CRT-preset depth: **medium catch-up**, noted as a future-rung candidate, not urgent (RustySNES's existing `Crt` filter is functional). SIMD blitter/wasm pass: **small catch-up**, could fold into `v1.19.0 "Afterburner"` alongside PGO/BOLT when that rung is scoped. Browser RA + Vs. DualSystem: correctly out of scope (RustySNES's RA is native-only; no Vs. System equivalent on SNES). Raw-composite: reconfirmed already-covered/correctly-deferred. | First re-run since baseline — overdue (8 RustySNES releases, `v1.5.0`–`v1.12.0`, had landed with no lockstep check in between); run at the start of scoping `v1.13.0`. |
5555
| 2026-07-15 | `v2.2.0 "Capstone"` / `main` | RustyNES cut `v2.2.0` since the last check (`v2.1.10`), plus an `[Unreleased]` Dependabot-consolidation PR. New in `v2.2.0`: netplay lobby/matchmaking (browse-and-join room directory + server-side quick-match), delayed-stream spectators, a graded hysteresis-backed desync verdict, peer-liveness RTT timeouts (all `rustynes-netplay` signaling depth); fuzz-target expansion from 3 → 8 cargo-fuzz targets (PPU/APU reg I/O, netplay message parsing, save-state, movie); a read-only ROM Info debugger panel (CRC32/SHA-256/header decode); 4 new MkDocs handbook pages; FDS medium-model completion (CRC-16/gap/continuous head-seek) + Famicom mic + Zapper 3×3 aperture hardening (peripherals); a fuzz-found movie-deserializer OOM-DoS hardening (untrusted `frame_count`/zero-`bytes_per_frame`). Checked RustySNES's own state directly (not assumed): confirmed no `fuzz/` directory exists at all; confirmed `rustysnes-netplay` has no `SignalMessage`/`ListRooms`/`QuickMatch`/`delay_frames`/`DesyncStatus`/`PeerLink` equivalents; confirmed `rustysnes-frontend/src/debugger/` has no ROM-Info-panel equivalent; confirmed `rustysnes-core::movie`'s deserializer is ALREADY hardened against the identical untrusted-`frame_count`/zero-length-frame OOM class (a `deserialize_rejects_a_forged_huge_frame_count_without_oom` regression test already exists — independently discovered, not copied); confirmed RustySNES's `SuperScopeState` uses a purely geometric (coordinate-clamp) offscreen check, architecturally different from a photodiode-luma-sampling model, so the Zapper aperture technique doesn't map onto it. FDS/Famicom-mic reconfirmed NES/Famicom-specific, not applicable. | **No fuzzing infrastructure at all**: **large catch-up** — genuinely new quality-infra category (not incremental growth of anything RustySNES has), and this project's own `docs/testing-strategy.md` already names fuzzability as an intended Layer 1 property never actually built out; flagged in `to-dos/ROADMAP.md`'s "Milestones beyond the phases" for a maintainer go/no-go. **Netplay lobby/matchmaking + spectator/desync/liveness depth**: **large catch-up** — multiple sub-features, would displace no currently-open rung (the ladder is closed) but is genuinely multiple PRs' worth; the `v1.5.0`-era "netplay already at parity" call is now stale against this deepened baseline; also flagged in `ROADMAP.md`. **ROM Info debugger panel**: **small catch-up**, self-contained, fits cleanly into the existing `debugger/` module architecture — candidate for the next time a small patch/quality release is scoped. **MkDocs handbook pages**: already covered in spirit (RustySNES already maintains its own MkDocs site, updated per-release; no distinct action). **Movie-deserializer OOM-DoS hardening**: already covered — RustySNES independently already has equivalent protection. **Zapper aperture hardening**: not directly applicable — architecture mismatch (RustySNES's Super Scope model doesn't sample framebuffer luma at all). **FDS/Famicom mic**: correctly out of scope (no SNES equivalent hardware). **Dependency-consolidation PR**: routine Dependabot hygiene, not a roadmap-scope item. | First re-run since the roadmap ladder closed at `v1.19.0` — confirms the checklist itself stays a live, standing practice even with no open rung to fold findings into; both large-catch-up items intentionally left unscoped pending a maintainer decision rather than opening a new rung unilaterally. |
5656
| 2026-07-31 | `v2.2.4 "Cartridge"` / `main` | RustyNES cut four releases since the last check (`v2.2.0`): `v2.2.1`, `v2.2.2 "Conduit"`, `v2.2.3 "Datum"`, `v2.2.4 "Cartridge"`. **CI supply-chain hardening** (`v2.2.2`): `persist-credentials: false` on all 19 checkouts, a fail-closed release-tag existence check replacing a three-way-collapsing `git ls-remote`, and a pinned toolchain action. Checked RustySNES's own state directly rather than assuming parity: 15 of its 17 checkouts were unhardened, `release-auto.yml:96` carried the identical `ls-remote` bug, and 34 action references were on mutable tags. **Libretro buildbot recipe** (`.gitlab-ci.yml`, `v2.2.2`) putting the core on RetroArch's in-app downloader; RustySNES has `rustysnes-libretro` but no buildbot recipe. **PPU fast-dot-path promoted to default + PGO** (`v2.2.3`) — NES-specific hot path, and RustySNES already shipped its own PGO/BOLT pipeline in `v1.19.0`. **`expansion_level_tripwire`** (`v2.2.3`) — a CI-run unit test pinning the audio level constants that seven `commercial-roms`-gated golden rows depend on, after those rows sat stale for 28 days. **Mapper residuals + 5B audio calibration** (`v2.2.3`) and **`.info` metadata + FDS disk control** (`v2.2.4`): NES/FDS-specific. **Antigravity reviewer template sync** (`v2.2.4`): RustySNES already did this in `v1.25.0` (#270/#273). | **CI hardening**: **small catch-up, ADOPTED IMMEDIATELY** in `v1.26.0` — all three items, with one divergence found by auditing per-site rather than copying the conclusion: `release-auto.yml`'s `prepare` job **genuinely needs** the checkout credential (it `git push`es the annotated tag), where the sibling's audit found no job did. A blanket sweep would have broken every future release. **Golden-staleness tripwire**: the *mechanism* does not port — RustySNES's only `commercial-roms`-gated suite (`commercial_screenshots`) is a screenshot generator that asserts nothing, so it holds no golden that can go stale, and PPU accuracy is not parameterised by a small constant set the way expansion-audio levels are. But checking for the analogue surfaced a **real and worse** structural gap, closed in `v1.26.0`: the 53 rendered-scene goldens and every framebuffer golden ran in **no pull-request job at all** (only `full-test`, which is main/tags/schedule), which is how this project's own coprocessor-golden staleness happened. **Libretro buildbot**: **medium catch-up**, no rung — candidate for a future distribution cut, flagged in `ROADMAP.md` rather than folded in. **Fast dot path / PGO / mapper / FDS / `.info`**: not applicable or already covered. | First re-run since the fuzzing item from the 2026-07-15 row was closed. Note the sibling is now *behind* on one axis: its `fuzz/` is wired into no workflow and its README claims a compile gate that does not exist there, where RustySNES's has both a per-PR compile gate and a scheduled campaign. |
57+
| 2026-08-03 | `v2.2.5 "Colophon"` / `main` | RustyNES cut one release since the last check: **`v2.2.5 "Colophon"`**, a **provenance, licensing, and documentation-integrity** release with zero emulation-core changes, prompted by community review of its licensing and AI-assisted origins. It (a) corrected in-source comments that described independently-implemented, publicly-documented hardware behaviour as "ports of" **copyleft** emulators (Mesen2 GPLv3, puNES GPLv2), (b) reframed its CRT/NTSC shaders from "port of X" to independent reimplementations of a *look and technique*, (c) fixed `blip.rs` mislabelling `blip_buf` as BSD/MIT when it is LGPL-2.1+, (d) **rewrote a previously-thin `NOTICE`** to disclose behavioural-oracle use of GPL emulators (no code incorporated), attribute incorporated permissive components (emu2413, TriCNES, rcheevos) and bundled fonts/test ROMs, and disclose an undisclosed GPL-3.0-only dependency cited across ~58 files, (e) added `docs/originality-and-provenance.md` including an AI-assistance disclosure, and (f) fixed a false exclusion claim in `tests/roms/LICENSES.md`. **Measured RustySNES's own exposure rather than assuming parity or its absence:** 23 in-source comments across the shipped crates claim a port/adaptation naming a reference emulator. Most say "Clean-room port of ares (ISC, vendor-ok)" and name the exact upstream file — ares is ISC, so those are the benign shape. **Two name `bsnes`, which is GPLv3** (`cheat.rs:4` "Ported from bsnes's `CheatEditor::decodeSNES`"; `cpu` direct-page arithmetic "clean-room port of bsnes `memory.cpp`"). Separately, `NOTICE` is **five lines** and discloses nothing concrete — no oracle disclosure, no attribution for the **vendored `rcheevos`** tree (whose own `LICENSE` *is* present in-tree at `crates/rustysnes-cheevos/vendor/rcheevos/LICENSE`), no font or test-ROM attribution, and no AI-assistance disclosure. | **Provenance/licensing audit: large catch-up, NOT scoped unilaterally — flagged in `to-dos/ROADMAP.md`'s "Milestones beyond the phases" for a maintainer go/no-go.** This is a licensing determination, not an engineering defect, and it is the maintainer's to make: whether a given comment is *inaccurate* (the behaviour was independently implemented and the emulator used only as an oracle) or *accurate* (and therefore a licensing question) cannot be settled by grepping the comment. What this check establishes is only the **surface**: 23 claims, 2 of them naming a GPLv3 project, against a `NOTICE` that would not support either reading. The `ref-proj/` trees are gitignored study clones and are not distributed, which bounds the question to the comments and to whatever they describe. Recommended shape if taken up, mirroring the sibling: audit each of the 23 sites for whether it describes documented hardware behaviour cross-checked against an oracle or an actual transcription; rewrite `NOTICE` to disclose oracle use, attribute the vendored `rcheevos`, and cover fonts/test ROMs; and add a provenance document. **Zero emulation-core risk either way** — nothing here changes a value the engine computes. | First re-check since the post-parity ladder closed. **Two dispositions from earlier rows are now closed and the rows are not rewritten (they are dated log entries):** the 2026-07-15 row's *fuzzing* item closed in `v1.26.0`, and its *netplay depth* item is closed **client-side** in `v1.27.0` (`DesyncStatus`, `PeerLink`, `SpectatorSession`/`delay_frames`) with the **signaling half** (`SignalMessage`/`ListRooms`/`QuickMatch`) out of scope by explicit decision rather than by omission — the `ROADMAP.md` entry is corrected in place to say so, since it is a live flag rather than a log row. The 2026-07-31 row's *libretro buildbot* item remains an open candidate. |

‎to-dos/ROADMAP.md‎

Lines changed: 48 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -405,22 +405,55 @@ under `v1.0.0`) and the netplay save-state-cost pre-work.
405405
sibling is *behind* on the CI half: its `fuzz/` is wired into no workflow at all, and its README
406406
claims a compile gate that does not exist there. See `fuzz/README.md` and
407407
`docs/testing-strategy.md` §Layer 7; and
408-
(2) **netplay lobby/matchmaking + spectator/desync/liveness depth** — RustyNES's
409-
`rustynes-netplay` signaling protocol grew a browse-and-join room directory, server-side
410-
quick-match, delayed-stream spectators, a graded hysteresis-backed desync verdict, and
411-
peer-liveness RTT timeouts; `rustysnes-netplay` has none of this (confirmed: no
412-
`SignalMessage`/`ListRooms`/`QuickMatch`/`delay_frames`/`DesyncStatus`/`PeerLink` equivalents),
413-
so the original `v1.5.0`-era "netplay already at parity" assessment is now stale against
414-
RustyNES's deepened baseline. Neither is urgent (RustySNES's existing netplay is functional at
415-
its own, narrower scope, and no untrusted-input crash has ever been found), so neither is
416-
silently folded into an already-closed rung — see `to-dos/LOCKSTEP-CHECKLIST.md`'s 2026-07-15
408+
(2) **netplay lobby/matchmaking + spectator/desync/liveness depth** — **the client-side half is
409+
CLOSED in `v1.27.0 "Tether"`; the signaling half is out of scope by decision, not by omission.**
410+
RustyNES's `rustynes-netplay` signaling protocol grew a browse-and-join room directory,
411+
server-side quick-match, delayed-stream spectators, a graded hysteresis-backed desync verdict,
412+
and peer-liveness RTT timeouts. When this row was written `rustysnes-netplay` had none of it.
413+
Three of the six symbols it names now exist: `DesyncStatus` (graded, sticky, three-consecutive
414+
threshold, keeping the remote framebuffer hash so a mismatch separates a *timing* divergence from
415+
a *state* one), `PeerLink` (`Live`/`Interrupted`/`TimedOut` behind a `Transport` decorator with an
416+
injected clock, so ADR 0004's determinism contract is untouched), and `delay_frames` (a
417+
presentation-only reveal hold on a `SpectatorSession` that never predicts, never rolls back, and
418+
never sends — so it cannot desync). The other three — `SignalMessage`, `ListRooms`, `QuickMatch` —
419+
are the **server** side, and `v1.27.0` was scoped client-side-only on an explicit decision: a
420+
signaling server is a hosted service with its own operational surface, not an emulator feature.
421+
`MAX_PLAYERS` stays 2 for the same reason the mesh transport was not ported — it is built for the
422+
NES Four Score, and core multitap exists here but wiring it into netplay is separate scope.
423+
So the `v1.5.0`-era "netplay already at parity" assessment was correctly retired, and what
424+
replaced it is a narrower claim that is now true. The remaining signaling gap is not urgent
425+
(RustySNES's netplay is functional at its own scope, and no untrusted-input crash has ever been
426+
found) and is not silently folded into an already-closed rung — see
427+
`to-dos/LOCKSTEP-CHECKLIST.md`'s 2026-07-15
417428
log row for the full disposition, including three smaller items (a self-contained ROM Info
418429
debugger panel judged a small catch-up — **closed in `v1.20.0 "Aperture"`**, as part of that
419430
rung's own separate UI/UX-parity audit against RustyNES's frontend, not this lockstep check
420431
directly; RustySNES's `movie.rs` deserializer already independently
421432
hardened against the same OOM-DoS class RustyNES's fuzzing just found, so already covered; and a
422433
Zapper aperture-hardening technique that doesn't map onto RustySNES's own, architecturally
423434
different geometric Super Scope hit-detection model, so not directly applicable).
435+
- **Flagged by the 2026-08-03 lockstep re-check — a provenance / licensing / attribution audit.**
436+
RustyNES cut `v2.2.5 "Colophon"` (zero emulation-core changes) to correct in-source comments that
437+
described independently-implemented, publicly-documented hardware behaviour as "ports of"
438+
**copyleft** emulators, to rewrite a thin `NOTICE` into a real disclosure of behavioural-oracle
439+
use and incorporated permissive components, and to add a provenance document including an
440+
AI-assistance disclosure. **RustySNES's own surface was measured, not assumed:** **23** in-source
441+
comments across the shipped crates claim a port or adaptation naming a reference emulator. Most
442+
read "Clean-room port of ares (ISC, vendor-ok)" and cite the exact upstream file, which is the
443+
benign shape — ares is ISC. **Two name `bsnes`, which is GPLv3** (`rustysnes-core/src/cheat.rs:4`
444+
and the CPU's direct-page arithmetic). Separately `NOTICE` is **five lines** and discloses nothing
445+
concrete: no oracle disclosure, no attribution for the **vendored `rcheevos`** tree (its own
446+
`LICENSE` *is* present in-tree, so this is an aggregation gap rather than a missing licence), no
447+
font or test-ROM attribution, and no AI-assistance disclosure.
448+
**This is a maintainer go/no-go, and deliberately not scoped here.** Whether a given comment is
449+
*inaccurate* — the behaviour implemented from fullsnes/anomie/datasheets with the emulator used
450+
only as an oracle, which is what this project does everywhere else and documents as its method —
451+
or *accurate*, and therefore a licensing question, cannot be settled by grepping the comment. The
452+
check establishes only the surface. The `ref-proj/` trees are **gitignored study clones and are
453+
not distributed**, which bounds the question to the comments and to whatever they describe.
454+
**Zero emulation-core risk either way**: nothing here changes a value the engine computes, so it
455+
can be taken up at any time without touching an accuracy result. See
456+
`to-dos/LOCKSTEP-CHECKLIST.md`'s 2026-08-03 log row for the recommended shape if it is taken up.
424457
- **Further beyond — the fractional-timebase refactor (`docs/adr/0002`).** Assessed in `v1.1.0`
425458
and found **not currently warranted** — every named accuracy residual is answerable within the
426459
existing whole-master-clock-tick model (`docs/audit/fractional-timebase-go-no-go-2026-07-11.md`).
@@ -433,9 +466,12 @@ under `v1.0.0`) and the netplay save-state-cost pre-work.
433466

434467
AccuracySNES (`tests/roms/AccuracySNES/`) closed ticket **T-04** — the monolithic all-in-one
435468
oracle ROM that no publicly available SNES ROM provided, so we wrote one. The battery currently
436-
stands at **332 tests, 100.00% on-cart pass**, cross-validated against Mesen2, snes9x, and (as of
437-
`v1.21.0`) a headless MesenCE. Coverage is **344 of 443** enumerated assertions — 291 on-cart + 53
438-
rendered scenes (`docs/accuracysnes-coverage.md`). The tickets below carry the rest of the enumeration in
469+
stands at **346 tests, 100.00% on-cart pass**, cross-validated against **three** independent
470+
references — snes9x, Mesen2, and (as of `v1.29.0`) a headless ares host, with MesenCE additionally
471+
serving as the per-dot compositor's exact-frame oracle. Coverage is **361 of 443** enumerated
472+
assertions — 304 on-cart + 55 rendered scenes + 2 host-side, three tiers kept apart on purpose and
473+
never summed into a single claim (`docs/accuracysnes-coverage.md`, regenerated with the ROM so it
474+
cannot drift — every figure quoted here by hand can, and this one had). The tickets below carry the rest of the enumeration in
439475
`docs/accuracysnes-research-dossier.md` §5. Full rationale, blocker analysis, and the ordering
440476
constraints live in **`docs/accuracysnes-plan.md`**; this list is the citable ID index.
441477

0 commit comments

Comments
 (0)