feat: v2.2.9 "Studio II" — TAStudio wiring, .bk2 playback, detachable tool windows - #346
Conversation
|
Warning Review limit reached
Next review available in: 29 minutes You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (6)
📝 WalkthroughWalkthroughRustyNES v2.2.9 changes the project license to GPL-3.0-or-later, records source provenance, updates release metadata, fixes ChangesRustyNES v2.2.9
Estimated code review effort: 4 (Complex) | ~60 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 8 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (8 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🟡 Not ready to approve
The new detachable_window helper drops existing per-panel window defaults (size/position/resizability), which is a user-visible regression for several tool panels.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
This review doesn't count toward merge requirements. Sign up for the private preview to control whether Copilot approvals count.
Pull request overview
This PR bumps RustyNES to v2.2.9 “Studio II” and implements three frontend-focused UX fixes: TAStudio edits are now applied to the running emulator, BizHawk .bk2 playback now honors LogKey column order, and debugger/tool panels can detach into native OS windows via egui multi-viewport.
Changes:
- Added a shared
detachable_windowhelper and routed many debugger/tool panels through it to enable native multi-window detaching. - Updated
.bk2import to parse and apply the declaredLogKey:column order (with fallback behavior) and added regression tests. - Updated release/version documentation and workspace versioning to 2.2.9.
File summaries
| File | Description |
|---|---|
| README.md | Updates “Current Release” text to v2.2.9 and summarizes the Studio II changes. |
| docs/STATUS.md | Updates the status header to reflect v2.2.9 as current release. |
| docs/frontend.md | Documents detachable tool windows as shipped in v2.2.9 and updates deferred list accordingly. |
| crates/rustynes-frontend/src/debugger/trace_panel.rs | Routes Trace panel through detachable_window and threads detached state. |
| crates/rustynes-frontend/src/debugger/rom_info_panel.rs | Routes ROM Info panel through detachable_window and threads detached state. |
| crates/rustynes-frontend/src/debugger/replay_panel.rs | Routes Replay/TAS panel through detachable_window and threads detached state. |
| crates/rustynes-frontend/src/debugger/ppu_panel.rs | Routes PPU panel through detachable_window and threads detached state. |
| crates/rustynes-frontend/src/debugger/oam_panel.rs | Routes OAM panel through detachable_window and threads detached state. |
| crates/rustynes-frontend/src/debugger/nsf_panel.rs | Routes NSF panel through detachable_window and threads detached state. |
| crates/rustynes-frontend/src/debugger/mod.rs | Introduces detachable_window, adds detached_panels tracking, and updates panel call sites. |
| crates/rustynes-frontend/src/debugger/memory_compare_panel.rs | Routes Memory Compare panel through detachable_window and threads detached state. |
| crates/rustynes-frontend/src/debugger/mapper_panel.rs | Routes Mapper panel through detachable_window and threads detached state. |
| crates/rustynes-frontend/src/debugger/input_miniatures_panel.rs | Routes Input Display panel through detachable_window and threads detached state. |
| crates/rustynes-frontend/src/debugger/game_db_panel.rs | Routes ROM Database panel through detachable_window and threads detached state. |
| crates/rustynes-frontend/src/debugger/event_panel.rs | Routes Event Viewer panel through detachable_window and threads detached state. |
| crates/rustynes-frontend/src/debugger/doc_panel.rs | Routes Documentation panel through detachable_window and threads detached state. |
| crates/rustynes-frontend/src/debugger/cheat_panel.rs | Routes Cheats panel through detachable_window and threads detached state on both native/wasm. |
| crates/rustynes-frontend/src/debugger/audio_mixer.rs | Routes Audio Mixer panel through detachable_window and threads detached state. |
| crates/rustynes-frontend/src/debugger/apu_panel.rs | Routes APU panel through detachable_window and threads detached state. |
| crates/rustynes-core/src/bk2_interop.rs | Implements LogKey: parsing for per-port column mapping and updates input parsing + tests. |
| CHANGELOG.md | Adds v2.2.9 release notes describing the new behaviors and constraints. |
| Cargo.toml | Bumps workspace package version to 2.2.9. |
| Cargo.lock | Updates crate versions to 2.2.9 across workspace packages. |
Review details
- Files reviewed: 27/28 changed files
- Comments generated: 1
- Review effort level: Lite
We're testing this review assessment. Please use 👍 or 👎 to tell us if it's correct.
…ilot #346) Copilot flagged a real UX regression in the v2.2.9 detachable-window conversion: routing every tool panel through the shared `detachable_window` helper dropped each panel's bespoke `egui::Window` builder options — `default_pos`, `default_size`, `default_width` / `min_width`, and `resizable(false)` on ROM Info / Input Display / ROM Database / Performance. Losing the `default_pos` values in particular collapsed the debugger's designed workspace layout into egui's default overlap cascade on first open, and four fixed-size panels silently became resizable. `detachable_window` now takes a `WindowCfg { default_pos, default_size, default_width, min_width, resizable }` (all `Option`, `Copy + Default`) and applies each set field to the docked `egui::Window`; all 19 call sites (18 panels; `cheat_panel` has a native + a wasm variant) pass back their exact prior values, so first-open placement/size and the four non-resizable panels are restored. The config applies to the docked form only — a detached panel is a real OS window the window manager sizes and places (egui persists the docked window's own position/size by id after first open, so `WindowCfg` only seeds the first appearance). Native + wasm32 `clippy -D warnings` clean on both feature sets. Also (proactive, matching the CodeRabbit finding already fixed on #345): the v2.2.4 entry in the AGENTS.md lineage paragraph still called v2.2.4 "the current release" — reworded to point at the actual current-release paragraph so AGENTS.md carries a single current-release record. Frontend-only; the emulation core, AccuracyCoin 141/141, and nestest 0-diff are untouched. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…2 import (v2.2.9)
Two of the v2.2.9 'Studio II' items, both objectively verified:
TAStudio inputs now drive the emulator. handle_tas_requests (the piano-roll panel
path) only mutated the editor's input_log on a SetInput and never re-derived the
running Nes, so a cell edit looked disconnected from emulation (the NESdev-forum
'TAStudio inputs do not seem to be connected up' report). It now tracks an
input_dirty flag across the batch and does a single deterministic re-seek to the
cursor afterward, exactly like the scripting path (apply_tas_commands). InsertFrame
/ DeleteFrame / StampMacro also mark dirty; Seek / CreateBranch / LoadBranch reseat
the Nes themselves.
.bk2 import honors the LogKey column order. The parser ignored the LogKey: line and
mapped pad columns by fixed U D L R S s B A position, so a BizHawk movie authored
with a different column order or extra columns mapped every button to the wrong bit
('.bk2 did not play back'). parse_log_key now reads the per-port column order from
the LogKey (# groups, | columns), maps each column by its button name (ignoring the
'Pn ' prefix), and falls back to the standard order when a group is truncated/exotic
(preserving the existing tests). parse_pad maps by that column list and tolerates a
group LONGER than the modeled columns (extra buttons like a mic are ignored). A new
test proves a non-standard order + an extra column.
.bk2 import feedback is on-screen. handle_movie_import surfaced every outcome via
eprintln! to a terminal nobody sees (so a failed import looked like nothing
happened). It now sets the on-screen status line for each path (no ROM, parse error,
wrong-ROM seek failure, success) via StatusMessage. Consolidated the file's nine
per-function StatusMessage imports into one module-level use.
Verification: bk2 tests 7/7 (incl. the new order test), rustynes-frontend 464/464,
core no_std cross-compile clean, clippy -D warnings + fmt clean on both crates.
Remaining v2.2.9 item: floating tool windows.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Addresses the NESdev-forum report that tool windows are trapped inside the main OS window on Windows 10: every debugger/tool panel used `egui::Window::new(...)` inside the single central viewport, so it could never leave the host window. Adds a shared `detachable_window` helper in `debugger/mod.rs` that gives each panel a "⧉ Detach" button. Detached, the panel renders in a real OS window via `ctx.show_viewport_immediate` (the same egui multi-viewport mechanism `basic_bot_panel` already used) with a "⧉ Reattach" button; the OS window's close button reattaches too. A `DebuggerOverlay::detached_panels: HashSet<&'static str>` (keyed by each panel's stable id) tracks which panels are floating across frames. **Native-only by construction.** egui multi-viewport needs winit multi-window, absent on wasm, so the detached branch and the Detach button are `#[cfg(not(target_arch = "wasm32"))]`; on wasm the panel always renders docked in an `egui::Window`, unchanged. The helper carries a wasm-scoped `allow(clippy::needless_pass_by_ref_mut)` plus a `let _ = (&detached, id)` discard so both the rustc `unused_variables` and clippy `needless_pass_by_ref_mut` lints stay green there without desyncing the native signature (verified: `cargo clippy -p rustynes-frontend --target wasm32-unknown-unknown --lib --bins` clean for both the default and `wasm-canvas` feature sets). 17 panels are routed through the helper (PPU, OAM, APU, Memory, Event Viewer, NSF, Mapper, Watch, Trace, Cheats [native + wasm cfg variants], ROM Database, Performance, Documentation, Input Display, Audio Mixer, Replay/TAS, Memory Compare, ROM Info), each dropping its bespoke `.resizable()/.default_pos()/ .default_size()/.min_width()` builder options for the shared affordance. Panels whose `show()` returns a value (`cpu_panel`) or that already own multi-window / config-heavy bodies (settings, netplay, cheevos, input-rebind, tastudio, basic_bot) are intentionally left for a follow-up. Frontend-only — the deterministic core, save-states, and every golden vector are untouched (AccuracyCoin 141/141, nestest 0-diff). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Version bump 2.2.8 → 2.2.9 (workspace `version`, Cargo.lock) and the docs-as-spec sync for the "Studio II" release — the fourth step of the v2.2.6 → v2.3.0 NESdev-remediation line, capping the TAStudio-wiring, `.bk2` playback, and detachable-tool-window work committed earlier on this branch. - **CHANGELOG.md** — new `[2.2.9]` section (Fixed: TAStudio piano-roll edits now drive the emulator, `.bk2` playback honors the `LogKey` column order; Added: detachable/floating tool windows across 17 panels, native-only). - **docs/STATUS.md** (single source of truth) — current-release lead reset to v2.2.9, demoting v2.2.8 to "Built on". - **README.md** — Current Release lead updated to v2.2.9. - **AGENTS.md** — both the top current-release block and the operating-note paragraph lead with v2.2.9; the "never claim a version later than …" guard and the v2.2.6 → v2.3.0 line-summary bump to mark v2.2.8/v2.2.9 shipped. - **docs/frontend.md** — detachable multi-viewport tool windows moved out of the Deferred list into shipped (v2.2.9), with the `detachable_window` / `show_viewport_immediate` mechanism noted. Frontend-only across the whole release, so the deterministic core, save-states, and every golden vector are byte-identical: **AccuracyCoin 141/141**, nestest 0-diff. The detached-window behavior itself awaits an on-device (ideally Windows-10) visual check; the mechanism compiles + clippy-passes on native and both wasm feature sets. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ilot #346) Copilot flagged a real UX regression in the v2.2.9 detachable-window conversion: routing every tool panel through the shared `detachable_window` helper dropped each panel's bespoke `egui::Window` builder options — `default_pos`, `default_size`, `default_width` / `min_width`, and `resizable(false)` on ROM Info / Input Display / ROM Database / Performance. Losing the `default_pos` values in particular collapsed the debugger's designed workspace layout into egui's default overlap cascade on first open, and four fixed-size panels silently became resizable. `detachable_window` now takes a `WindowCfg { default_pos, default_size, default_width, min_width, resizable }` (all `Option`, `Copy + Default`) and applies each set field to the docked `egui::Window`; all 19 call sites (18 panels; `cheat_panel` has a native + a wasm variant) pass back their exact prior values, so first-open placement/size and the four non-resizable panels are restored. The config applies to the docked form only — a detached panel is a real OS window the window manager sizes and places (egui persists the docked window's own position/size by id after first open, so `WindowCfg` only seeds the first appearance). Native + wasm32 `clippy -D warnings` clean on both feature sets. Also (proactive, matching the CodeRabbit finding already fixed on #345): the v2.2.4 entry in the AGENTS.md lineage paragraph still called v2.2.4 "the current release" — reworded to point at the actual current-release paragraph so AGENTS.md carries a single current-release record. Frontend-only; the emulation core, AccuracyCoin 141/141, and nestest 0-diff are untouched. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
16e18ac to
7aa5836
Compare
…k of GPL emulators
RustyNES incorporates and is derived from code from GPL-licensed NES emulators.
It is therefore a derivative work distributable only under the GPL, and this
commit relicenses it from `MIT OR Apache-2.0` to **GPL-3.0-or-later**, credits
the derived-from sources per subsystem, and withdraws the incorrect "no GPL
source incorporated" position taken in v2.2.5 "Colophon".
Context. A NESdev community review found that the codebase contains bugs,
constants, variable names, code ordering, and comments referencing specific
upstream files, functions, and line numbers that go well beyond using an
emulator as a testing oracle. That is correct. The project's own in-source
comments, before a v2.2.5 edit reworded them, said as much: "Faithful port of
Mesen2's `ProcessSpriteEvaluation` (`NesPpu.cpp:1015-1141`)", "Ported bit-for-bit
from puNES `JV001.c`", "numeric tables ported verbatim from Bisqwit's C", and
~12 "Ported from Mesen2 `<file>.h`" mapper comments. v2.2.5 reframed that code as
"oracle cross-checks" and kept a permissive license the combined work was not
entitled to use. Laundering GPL code through AI tooling does not change its
license, and responsibility for what landed in the tree rests with the project.
Derived-from sources and their licenses (full file-by-file table in
docs/originality-and-provenance.md Section 1):
- Mesen2 (GPL-3.0-or-later): CPU unstable-store opcodes; the PPU
sprite-evaluation FSM + OAM-data-bus model; ~15 mapper boards (Bandai EEPROM,
JY Company, Waixing, Sachen, Txc, NTDEC, Kaiser, MMC3 variants, FK23C,
CoolBoy); the Bisqwit NTSC filter tables; the UNIF tables; the debug-symbol
importer; the PGO harness.
- puNES (GPL-2.0-or-later): JV001 / mapper 147 (bit-for-bit); the FDS per-CRC
drive-timing table.
- FCEUX (GPL-2.0-or-later): UNIF handling; some mapper banking.
- Nestopia UE (GPL-2.0-or-later): FME-7 / 5B audio detail.
Every upstream grants "or (at your option) any later version", so the
GPL-2.0-or-later material upgrades to v3 and GPL-3.0-or-later is the correct,
consistent expression for the combined work. GeraNES (GPL-3.0-only) was used as
an oracle only, with no code derived, so it does not force `-only`.
Changes:
- LICENSE is now the GPLv3 text; LICENSE-MIT and LICENSE-APACHE are removed;
the workspace + rustynes-cheevos `license` fields become GPL-3.0-or-later;
deny.toml allows GPL-3.0-or-later for the project's own crates (cargo-deny
`check licenses` = ok); release.yml packages LICENSE instead of the two
removed files.
- docs/originality-and-provenance.md is rewritten to lead with the derivation
table and the derivative-work declaration; NOTICE attributes each GPL
upstream and the code derived from it; README, AGENTS, CONTRIBUTING, SUPPORT,
ROADMAP, the in-app About/CLI/doc-panel strings, the Android about_body
(EN + ES), and the libretro `.info` license field all state GPL-3.0-or-later.
- New ADR 0036 records the decision, the SPDX rationale, and the GPLv3/App-Store
distribution caveat. The scattered "port of" comments are deliberately NOT
restored (they were imprecise; the audited derivation table supersedes them),
but the derivation is now stated plainly and completely.
- Incorporated permissive components (emu2413/MIT, TriCNES/MIT, rcheevos/MIT,
blip_buf/LGPL-2.1-or-later, fonts) are GPL-compatible and keep their notices.
Zero emulation-core behavior change: AccuracyCoin holds 141/141 and nestest is
0-diff by construction. This is a licensing and documentation correction.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Carry-over fix: the version badge still read v2.2.8 after the v2.2.9 doc bump. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ived source
Follows the v2.2.9 relicense: now that the accurate license and attribution are
established, mark the derived source itself. Each of the 23 files that contains
code derived from a GPL emulator gains a top-of-file header:
// SPDX-License-Identifier: GPL-3.0-or-later
//
// Provenance: <what is derived, from which upstream file/function>. See
// docs/originality-and-provenance.md (Section 1) and NOTICE ...
so the license and the specific upstream are discoverable at the point of use —
e.g. `rustynes-ppu/src/ppu.rs` names Mesen2 `NesPpu.cpp`
(`ProcessSpriteEvaluation` / `ReadSpriteRam`) plus the TriCNES (MIT) octal-latch
model; `rustynes-mappers/src/fds.rs` names puNES `fds.c`;
`rustynes-frontend/src/ntsc_bisqwit.rs` records the verbatim-ported Bisqwit
tables via Mesen2. The ~15 Mesen2-derived mapper boards, the CPU unstable-store
opcodes, the emu2413/blip_buf audio, the CRT-shader reimplementations, the debug-
symbol importer, and the PGO harness are all likewise marked.
This is the accurate replacement for the old scattered, imprecise per-line "port
of" comments (not restored verbatim); the SPDX + provenance headers plus the
audited §1 derivation table are the discoverable record. CHANGELOG, ADR 0036, and
docs/originality-and-provenance.md §8 are updated to describe this approach.
Comments only — `cargo fmt --all --check` clean, `cargo check --workspace`
compiles, zero behavior change (AccuracyCoin 141/141, nestest 0-diff).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 11
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@android/app/src/main/res/values/strings.xml`:
- Line 188: The AccuracyCoin release counts are outdated in the user-facing
accuracy text. Update about_body in android/app/src/main/res/values/strings.xml
at lines 188-188 and android/app/src/main/res/values-es/strings.xml at lines
168-168 from 139/139 to 141/141, and update the frontend accuracy text in
crates/rustynes-frontend/src/debugger/doc_panel.rs at lines 1192-1192 to 100%
(141/141).
In `@CHANGELOG.md`:
- Around line 75-80: Count the actual detachable_window call sites, then use
that verified count and complete panel list consistently in CHANGELOG.md lines
75-80, AGENTS.md lines 30 and 188, and docs/frontend.md lines 1743-1747; update
each affected summary/specification without removing a valid panel name or
introducing inconsistent counts.
In `@crates/rustynes-core/src/bk2_interop.rs`:
- Around line 365-370: Update the parsing logic around the groups and cols
closures to preserve empty interior fields while removing only the
syntax-defined terminal delimiter, so empty controller columns and console
groups retain their positional indexes. Ensure malformed or unsupported layouts
are rejected with Bk2Error rather than silently remapped, and add regression
tests covering an empty controller column and empty console group.
In `@crates/rustynes-frontend/src/app.rs`:
- Around line 3036-3044: Before handling TasRequest::CreateBranch or
TasRequest::LoadBranch, check input_dirty and call ed.seek(nes, ed.cursor()) to
flush pending edits; only then invoke create_branch or load_branch, preserving
the flushed state instead of unconditionally clearing the flag. Add a regression
covering pending edit requests followed by each branch operation in the same
batch.
In `@crates/rustynes-frontend/src/debugger/event_panel.rs`:
- Around line 98-115: Update detachable_window to apply applicable WindowCfg
fields, including default size/position and resizable, when constructing the
detached native ViewportBuilder, while preserving docked-window behavior; verify
this on native desktop targets. The affected call sites require no direct
changes: crates/rustynes-frontend/src/debugger/event_panel.rs:98-115,
crates/rustynes-frontend/src/debugger/input_miniatures_panel.rs:130-147,
crates/rustynes-frontend/src/debugger/mapper_panel.rs:41-60,
crates/rustynes-frontend/src/debugger/perf_panel.rs:195-214,
crates/rustynes-frontend/src/debugger/ppu_panel.rs:122-141,
crates/rustynes-frontend/src/debugger/replay_panel.rs:81-99,
crates/rustynes-frontend/src/debugger/rom_info_panel.rs:71-90,
crates/rustynes-frontend/src/debugger/trace_panel.rs:60-78, and
crates/rustynes-frontend/src/debugger/watch_panel.rs:456-478.
In `@crates/rustynes-frontend/src/debugger/mod.rs`:
- Around line 303-320: Remove or gate the Detach action and its
show_viewport_immediate path until secondary viewport rendering is implemented.
Before re-enabling it, update DebuggerOverlay::render and
DebuggerOverlay::render_shell to own child winit windows, route their
input/output, and render secondary viewport output so the detached panel remains
interactive.
In `@docs/adr/0036-relicense-gplv3-derivative-work.md`:
- Around line 95-97: Update the accuracy statement in the ADR to describe
AccuracyCoin’s 141/141 and nestest’s 0-diff results as verified release-check
evidence rather than “by construction,” and link to the authoritative
docs/STATUS.md pass counts.
- Around line 78-82: Revise the historical-release language in
docs/adr/0036-relicense-gplv3-derivative-work.md (lines 78-82) and
docs/originality-and-provenance.md (lines 98-102) to preserve immutable
snapshot/tag history without stating or implying that prior unauthorized
permissive license grants remain valid. Use legally reviewed wording
consistently in both documents, while retaining the GPL-3.0-or-later
applicability from v2.2.9 onward.
In `@docs/originality-and-provenance.md`:
- Around line 43-62: Revise Section 1 so its introductory claims apply only to
rows derived from GPL-licensed emulators and do not include the BSD/Apache,
LGPL, or MIT components. Separate the ares, blip_buf, emu2413, and shader
reimplementation entries into appropriately labeled non-GPL or
visual-reimplementation provenance tables/sections, and update the licensing
rationale to match each table’s documented relationship and license.
In `@README.md`:
- Line 12: Update the version citation in the README’s Current Release section,
including the matching citation at the additional referenced location, from
2.2.8 to 2.2.9 so it aligns with the release badge and current release metadata;
alternatively, explicitly mark it as historical if it must remain unchanged.
In `@SUPPORT.md`:
- Line 109: Synchronize release metadata across SUPPORT.md:97 and
crates/rustynes-libretro/rustynes_libretro.info:6: update the current-release
description from v2.0.4 “Harbor” to v2.2.9 “Studio II”, and change the Libretro
display_version from v2.2.5 to v2.2.9 unless an independently documented
Libretro version contract is added instead.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: eb00d6a6-da48-4c8c-9089-fca3cd6173c7
⛔ Files ignored due to path filters (1)
Cargo.lockis excluded by!**/*.lock,!Cargo.lock
📒 Files selected for processing (44)
.github/workflows/release.ymlAGENTS.mdCHANGELOG.mdCONTRIBUTING.mdCargo.tomlLICENSELICENSE-APACHELICENSE-MITNOTICEREADME.mdROADMAP.mdSUPPORT.mdandroid/app/src/main/res/values-es/strings.xmlandroid/app/src/main/res/values/strings.xmlcrates/rustynes-cheevos/Cargo.tomlcrates/rustynes-core/src/bk2_interop.rscrates/rustynes-frontend/src/app.rscrates/rustynes-frontend/src/cli.rscrates/rustynes-frontend/src/debugger/apu_panel.rscrates/rustynes-frontend/src/debugger/audio_mixer.rscrates/rustynes-frontend/src/debugger/cheat_panel.rscrates/rustynes-frontend/src/debugger/doc_panel.rscrates/rustynes-frontend/src/debugger/event_panel.rscrates/rustynes-frontend/src/debugger/game_db_panel.rscrates/rustynes-frontend/src/debugger/input_miniatures_panel.rscrates/rustynes-frontend/src/debugger/mapper_panel.rscrates/rustynes-frontend/src/debugger/memory_compare_panel.rscrates/rustynes-frontend/src/debugger/memory_panel.rscrates/rustynes-frontend/src/debugger/mod.rscrates/rustynes-frontend/src/debugger/nsf_panel.rscrates/rustynes-frontend/src/debugger/oam_panel.rscrates/rustynes-frontend/src/debugger/perf_panel.rscrates/rustynes-frontend/src/debugger/ppu_panel.rscrates/rustynes-frontend/src/debugger/replay_panel.rscrates/rustynes-frontend/src/debugger/rom_info_panel.rscrates/rustynes-frontend/src/debugger/trace_panel.rscrates/rustynes-frontend/src/debugger/watch_panel.rscrates/rustynes-frontend/src/ui_shell.rscrates/rustynes-libretro/rustynes_libretro.infodeny.tomldocs/STATUS.mddocs/adr/0036-relicense-gplv3-derivative-work.mddocs/frontend.mddocs/originality-and-provenance.md
💤 Files with no reviewable changes (2)
- LICENSE-APACHE
- LICENSE-MIT
…-mortem Two things: the maintainer-directed forensic analysis of the GPL-provenance failure, and the CodeRabbit review pass on the v2.2.9 PR. **docs/provenance-failure-postmortem.md (new).** A complete, evidence-cited reconstruction of how RustyNES came to incorporate lifted GPL emulator code despite a black-box-only instruction: the timeline across RustyNES_v2 (the private "engine stack" where the porting happened, 2026-05, Opus 4.7) and the 2026-06-13 transplant into this repo; the two distinct failures (the port itself, then the v2.2.5 scrubbing of the honest "port of" comments); the root causes (GPL source on disk + accuracy-bar goal + no firewall; the guardrail post-dating the violation; honest-at-build-time then laundered; multi-session framing propagation; trusted AI self-attestation); and an honest accounting of what is NOT recoverable (the RustyNES_v2 porting-era session logs are gone). The single hardest fact: the original "Faithful port of Mesen2's ..." comments still exist verbatim in RustyNES_v2 today — only this public repo scrubbed them. Linked from originality-and-provenance.md §8. **CodeRabbit #346 review (9 threads):** - **`.bk2` LogKey empty-field bug (Major, data integrity).** `parse_log_key` filtered out empty positional fields, shifting later columns/groups (an empty console group promoted P2's map into P1; an empty interior column misaligned buttons so `U.A` replayed as `Up` alone). Now strips only the syntax delimiters and keeps interior empties; +regression test for both cases. - **TAS branch/load ordering (correctness).** `CreateBranch` / `LoadBranch` cleared `input_dirty` without flushing pending edits, so a branch snapshot captured stale state; they now `ed.seek` to flush first. - **`WindowCfg` -> `ViewportBuilder` (Major).** The detached branch maps default size / position / resizability onto the viewport, not just the docked window. - **Multi-viewport honesty (Major).** RustyNES's frontend is a single-viewport `egui_winit` integration, so `show_viewport_immediate` renders the "detached" panel EMBEDDED in the main window rather than a separate OS window — it does not yet fully resolve the Windows-10 trapped-window report. Documented honestly in code, CHANGELOG, AGENTS.md, and docs/frontend.md; true OS-window detach is tracked follow-up. Corrects an overclaim. - Doc/metadata: panel count 17 -> 18; ADR 0036 "by construction" -> verified release-check evidence + STATUS link; README badge/BibTeX -> v2.2.9; SUPPORT current-release v2.0.4 -> v2.2.9; libretro display_version -> v2.2.9; Android about_body 139/139 -> 141/141 and 168 -> 172 mappers (EN + ES). Core-affecting fixes (bk2, TAS) are core/frontend only; cargo check + the bk2 tests pass. AccuracyCoin 141/141 unaffected. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…d/followed Reconcile the root-cause framing with the maintainer's correction: the black-box / oracle-only instruction WAS given — the failure was that it was not mechanically enforced (no barrier at the tool boundary; no persisted written rule in the loaded guidance until 2026-06-13) and the porting model did not follow it. §4.1 and §4.2 reframed from "no guardrail / the guardrail post-dated the violation" to "instruction given, neither persisted early nor enforced"; §4.5 sharpened (an instruction the agent can silently disregard and then falsely certify is not a control). The evidentiary caveat is unchanged: the porting-era logs are gone, so the exact wording/timing of the spoken instruction cannot be quoted. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
crates/rustynes-core/src/bk2_interop.rs (1)
369-391: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick winDo not allocate every
LogKeygroup.Line 369 collects all
#-separated groups, but this parser reads only the console, P1, and P2 groups. A movie with many repeated#delimiters creates oneVec<&str>entry per empty group. This can exhaust memory during import.Consume the first three groups from the
split('#')iterator.Iterator::next()preserves empty groups.Proposed fix
- let groups: Vec<&str> = body.split('#').collect(); - let cols = |g: Option<&&str>| -> Vec<Option<Buttons>> { + let mut groups = body.split('#'); + let _console = groups.next(); + let cols = |g: Option<&str>| -> Vec<Option<Buttons>> { let mapped: Vec<Option<Buttons>> = g.map_or_else(Vec::new, |grp| { grp.strip_suffix('|') .unwrap_or(grp) .split('|') .map(button_for_column) .collect() }); @@ - (cols(groups.get(1)), cols(groups.get(2))) + (cols(groups.next()), cols(groups.next()))🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/rustynes-core/src/bk2_interop.rs` around lines 369 - 391, Replace the groups Vec allocation in the button-column parsing flow with a split('#') iterator, then consume exactly the console, P1, and P2 entries via successive next() calls while preserving empty groups. Update the existing cols calls to use those optional group references so only the required three groups are processed and trailing delimiters cannot cause unbounded allocation.CHANGELOG.md (2)
19-19: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winRemove future v2.3.0 references from both release-facing documents.
The repository documents v2.2.9 as the current release and must not claim a later release.
As per coding guidelines: do not claim or document a release later than v2.2.9.
CHANGELOG.md#L19-L19: replace the v2.2.6 → v2.3.0 wording with neutral current-line wording.SUPPORT.md#L97-L97: remove the v2.3.0 endpoint from the current-release description.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@CHANGELOG.md` at line 19, Update CHANGELOG.md line 19 to replace the v2.2.6 → v2.3.0 wording with neutral wording for the current release line, and update SUPPORT.md line 97 to remove the v2.3.0 endpoint from the current-release description. Ensure neither release-facing document claims a version later than v2.2.9.Source: Coding guidelines
28-31: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winCorrect the detached-window description.
These lines say that detached tool windows use real OS windows. Lines 86-93 state that the current single-viewport integration embeds them in the main window. Keep the release overview consistent with the documented limitation.
As per path instructions: Markdown documentation must match the behavior it describes.
Proposed fix
- > **Windowing needs an on-device check.** Detached tool windows use egui - > multi-viewport (real OS windows); the mechanism compiles and clippy-passes on + > **Windowing needs an on-device check.** Detached tool windows remain embedded + > in the main viewport; the multi-viewport mechanism compiles and clippy-passes🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@CHANGELOG.md` around lines 28 - 31, Update the detached tool window description in the release overview to state that the current single-viewport integration embeds tool windows in the main window, matching the limitation documented later in CHANGELOG.md. Remove the claim that detached windows currently use real OS windows, while preserving the existing note about on-device validation.Source: Path instructions
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@AGENTS.md`:
- Line 30: Remove future-release references from AGENTS.md: at AGENTS.md lines
30-30, replace the “v2.2.6 → v2.3.0” wording with version-neutral post-v2.2.9
future-work language; at lines 188-188, remove the detailed v2.3.0 release
narrative and retain only post-v2.2.9 planning language.
In `@docs/adr/0036-relicense-gplv3-derivative-work.md`:
- Around line 62-68: The per-file provenance requirement must match the Kaiser
header. In docs/adr/0036-relicense-gplv3-derivative-work.md lines 62-68 and
docs/originality-and-provenance.md lines 244-252, retain or revise the
requirement consistently so every derived file names an exact upstream source
location or function; in crates/rustynes-mappers/src/kaiser.rs lines 1-4, add
the specific Mesen2 source path or function to the provenance header.
In `@docs/provenance-failure-postmortem.md`:
- Around line 25-28: In docs/provenance-failure-postmortem.md lines 25-28,
qualify the claims about the model deciding to match Mesen2 and partially
porting it as inference rather than established fact. In lines 89-99, clearly
distinguish maintainer testimony from recovered evidence and state when the
reasoning or exact instruction is unavailable; keep the evidentiary standard
consistent across both sections.
- Line 52: Update the 2026-06-13 RustyNES provenance entry to identify the
transplanted stack as an internal “RustyNES_v2” engine-lineage snapshot,
explicitly stating that it is not a RustyNES release. Preserve the existing
event details while avoiding any wording that presents v2.8.0 as a RustyNES
release beyond the permitted v2.2.9 documentation limit.
---
Outside diff comments:
In `@CHANGELOG.md`:
- Line 19: Update CHANGELOG.md line 19 to replace the v2.2.6 → v2.3.0 wording
with neutral wording for the current release line, and update SUPPORT.md line 97
to remove the v2.3.0 endpoint from the current-release description. Ensure
neither release-facing document claims a version later than v2.2.9.
- Around line 28-31: Update the detached tool window description in the release
overview to state that the current single-viewport integration embeds tool
windows in the main window, matching the limitation documented later in
CHANGELOG.md. Remove the claim that detached windows currently use real OS
windows, while preserving the existing note about on-device validation.
In `@crates/rustynes-core/src/bk2_interop.rs`:
- Around line 369-391: Replace the groups Vec allocation in the button-column
parsing flow with a split('#') iterator, then consume exactly the console, P1,
and P2 entries via successive next() calls while preserving empty groups. Update
the existing cols calls to use those optional group references so only the
required three groups are processed and trailing delimiters cannot cause
unbounded allocation.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: dd7a7a68-e916-42c5-8106-089b5b939e3a
📒 Files selected for processing (37)
AGENTS.mdCHANGELOG.mdREADME.mdSUPPORT.mdandroid/app/src/main/res/values-es/strings.xmlandroid/app/src/main/res/values/strings.xmlcrates/rustynes-apu/src/blip.rscrates/rustynes-apu/src/opll.rscrates/rustynes-core/src/bk2_interop.rscrates/rustynes-cpu/src/cpu.rscrates/rustynes-frontend/src/app.rscrates/rustynes-frontend/src/debugger/mod.rscrates/rustynes-frontend/src/debugger/source_map.rscrates/rustynes-frontend/src/ntsc_bisqwit.rscrates/rustynes-gfx-shaders/src/crt_stack.rscrates/rustynes-libretro/rustynes_libretro.infocrates/rustynes-mappers/src/fds.rscrates/rustynes-mappers/src/kaiser.rscrates/rustynes-mappers/src/lib.rscrates/rustynes-mappers/src/m016_bandai_fcg.rscrates/rustynes-mappers/src/m035_jy_asic.rscrates/rustynes-mappers/src/m069_sunsoft_fme7.rscrates/rustynes-mappers/src/m176_bmc_fk23c.rscrates/rustynes-mappers/src/m268_bmc_coolboy.rscrates/rustynes-mappers/src/m513_sachen_9602.rscrates/rustynes-mappers/src/mmc3_clones.rscrates/rustynes-mappers/src/multicart_discrete.rscrates/rustynes-mappers/src/ntdec.rscrates/rustynes-mappers/src/sachen_discrete.rscrates/rustynes-mappers/src/unif.rscrates/rustynes-ppu/src/palette_gen.rscrates/rustynes-ppu/src/ppu.rscrates/rustynes-test-harness/src/bin/pgo_trainer.rsdocs/adr/0036-relicense-gplv3-derivative-work.mddocs/frontend.mddocs/originality-and-provenance.mddocs/provenance-failure-postmortem.md
…r's edits
Non-substantive cleanup of the maintainer's review edits: stripped trailing
whitespace (§1, §2, and the closing NOTE), evened out the wrap widths the inline
edits left uneven, standardized hyphen-as-dash to em-dash in the NOTE, fixed one
phrase that didn't parse ("finally did baseline" -> "finally did become the
baseline"), and reconciled §5 with §4.2's "written instruction" framing (dropped
the now-inconsistent "or verbally"; the honest "cannot be quoted, logs gone"
point is unchanged). No substantive claims or the maintainer's wording/voice
were altered. markdownlint clean, no trailing whitespace.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ed sites
Restore accurate, license-specific attribution at each genuine ported site,
replacing the v2.2.5-laundered false-independence claims that were STILL in the
shipped per-function comments (the SPDX top-of-file headers alone did not undo
them). At each ported function the comment now names the upstream file/function
and its license, instead of asserting "an independent implementation … no
third-party emulator code is incorporated" / "cross-checked … as oracles".
Corrected (18 files) — examples:
- `cpu.rs` SH* stores → Mesen2 `NesCpu.h` (`SyaSxaAxa`), GPL-3.0-or-later
- `ppu.rs` OAM-data-bus / sprite-eval → Mesen2 `NesPpu.cpp`
(`ProcessSpriteEvaluation` / `ReadSpriteRam`), GPL-3.0-or-later
- `ntsc_bisqwit.rs` → tables ported verbatim via Mesen2 `BisqwitNtscFilter`,
GPL-3.0-or-later
- `blip.rs` → BLEP technique derived from Shay Green's `blip_buf`,
LGPL-2.1-or-later (our kernel is a finer 32-phase refinement)
- mapper boards (m016 Bandai EEPROM, m035/lib JY, m176/m268 FK23C/CoolBoy,
m513/mmc3_clones/sachen_discrete Sachen, multicart/ntdec NTDEC/Txc, kaiser
Waixing) → their specific Mesen2 `.h` sources, GPL-3.0-or-later; CoolBoy also
FCEUX (GPL-2.0-or-later)
- `unif.rs` → Mesen2 `UnifLoader.cpp` (GPLv3) + FCEUX `unif.cpp` (GPLv2)
- `sachen_discrete.rs` JV001 → puNES `JV001.c` / `mapper_147.c` (GPL-2.0-or-later)
- `fds.rs` per-CRC drive table → puNES `src/core/fds.c` (GPL-2.0-or-later)
- `source_map.rs` → mirrors Mesen2 `DbgImporter` (GPL-3.0-or-later)
Deliberately LEFT unchanged (no over-attribution): `opll.rs` (already honestly
"a pure-Rust port of emu2413", MIT), `pgo_trainer.rs` (honest `PGOHelper`
pattern), `palette_gen.rs` / `crt_stack.rs` (documented method / genuine
look-reimplementation, no false claim), and `m069_sunsoft_fme7.rs` (its Mesen2
mentions are genuine `_volumeLut` oracle cross-checks). Genuine oracle-comparison
mentions ("matches Mesen2", "Mesen2-independent oracle") were NOT converted.
Comments only — `cargo fmt`, `cargo check`, and `cargo clippy -D warnings`
(cpu/ppu/apu/mappers/frontend) all clean. Zero behavior change.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ocs/) A styled PDF rendering of docs/provenance-failure-postmortem.md for the reference corpus, at ref-docs/RustyNES_Provenance-Failure-Postmortem.pdf. Themed as a forensic incident record — oxblood-crimson accents (severity), a charcoal serif body (official-record readability), dark-slate evidence-table headers, and monospace for commit hashes / file paths — with a title block, table of contents, and page footers. 8 pages, US Letter. Built with pandoc 3.6.1 -> WeasyPrint 68.1 from the committed markdown; content is identical to the source document. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ulator dev A forward-looking, general-purpose ruleset distilled from the provenance-failure post-mortem: docs/ai-emulator-provenance-guardrails.md. Written to be dropped into a project's agent instructions / permanent memory BEFORE development starts so the same trap cannot recur — in this project or any other emulator project using prior art (reference emulators, test ROMs). Contents: why emulators are a special trap for AI agents (accuracy is convergent + references are mostly copyleft); a classification of every external input (documentation / test ROMs / observable oracles / incorporated components) and what each permits; the reference firewall (oracles are run and observed, never opened and read — enforced by a denied read-path + a CI check, not by prose); attribution on four consistent surfaces (site comment + SPDX + central table + NOTICE) with a no-over-attribution rule; license arithmetic (the or-later grant, combined-work copyleft, the license gate); mechanical enforcement; a pre-development checklist; a paste-ready guardrail block for CLAUDE.md/AGENTS.md; a remediation runbook (do NOT scrub); and a red-flags table of the thoughts that precede the failure. Intended for sharing as NESdev-community best-guidance. Cross-linked from the post-mortem's §7 (Lessons and prevention) as the actionable counterpart. markdownlint clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Redesign per maintainer feedback ("less harsh on the eyes"): a cool blue/teal
palette (navy title, blue headings + rules, teal accents) on soft cool-slate
text, with RED reserved only for genuine takeaways; humanist sans-serif
throughout (Fira Sans, with FiraCode for code) at a comfortable weight/leading;
a two-column layout for an ideal ~55-60 character measure (per readability
research); and the maintainer's closing NOTE set apart in a full-width
light-blue "Maintainer's Statement" box. Compacted from 8 pages to 4 (US Letter).
Built pandoc 3.6.1 -> a bs4 DOM assembler (full-width title + evidence table
between 2-column prose groups) -> WeasyPrint 68.1. Content unchanged.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…e-agnostic doc Generalize docs/ai-emulator-provenance-guardrails.md so it stands on its own as a community resource — no references to any specific project or its source-tree documents, and applicable to emulation of ANY console, not just the NES: - Reworded the opening to describe the failure pattern generically (no specific project, no cross-link to a project post-mortem) and to state it applies to NES / SNES / Genesis / Game Boy / N64 / PlayStation / arcade / etc. - Broadened the reference-emulator examples across consoles (Mesen2/FCEUX, bsnes/Mesen-S, Genesis Plus GX/BlastEm, SameBoy/mGBA, ares/higan/MAME, …) in the bucket table and the paste-ready block. - Genericized the example provenance comment, the central-table / provenance-doc filenames (`PROVENANCE.md` or equivalent), the firewall-check grep, and the "matches reference X" over-attribution example. - Removed the "case study" / "this project" phrasings and the two links to project source-tree docs (post-mortem, derivation table); the remediation and closing now speak generally. Content and rules are unchanged; only the framing is now project-neutral and multi-console. markdownlint clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@crates/rustynes-cpu/src/cpu.rs`:
- Around line 877-882: Correct the central provenance table so Txc/TxcChip.h and
Sachen/Sachen8259.h are attributed only to
rustynes-mappers/src/sachen_discrete.rs, with mmc3_clones.rs and
multicart_discrete.rs mapped to their actual local references. The sites in
crates/rustynes-cpu/src/cpu.rs:877-882,
crates/rustynes-mappers/src/m513_sachen_9602.rs:347-349, and
crates/rustynes-ppu/src/ppu.rs:759-761 require no direct changes; update the
corresponding provenance entries for
crates/rustynes-mappers/src/mmc3_clones.rs:784-785 and
crates/rustynes-mappers/src/multicart_discrete.rs:3805-3806 as part of the table
correction.
In `@docs/ai-emulator-provenance-guardrails.md`:
- Around line 150-156: Update the licensing guidance around “Determine each
derived-from source's exact license” and “The combined work takes the strongest
copyleft” to require removing or rewriting an incompatible code component, or
obtaining compatible permission, before documenting remediation. Make clear that
documentation changes alone do not resolve incompatible code licenses, and only
update the documentation after the underlying code/license issue is resolved.
- Around line 174-179: Update the “Firewall check” guidance to make the
tool-level read-deny or sandbox policy the enforced control for blocking access
to reference-source trees, including sibling, mounted, read-only-mounted, and
renamed paths. Retain the existing git ls-files/grep command only as a
supplemental repository-path check, not as the firewall mechanism.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 39edce25-9385-41a8-b20c-b494d8ecd4c8
⛔ Files ignored due to path filters (1)
ref-docs/RustyNES_Provenance-Failure-Postmortem.pdfis excluded by!**/*.pdf,!ref-docs/**
📒 Files selected for processing (20)
crates/rustynes-apu/src/blip.rscrates/rustynes-cpu/src/cpu.rscrates/rustynes-frontend/src/debugger/source_map.rscrates/rustynes-frontend/src/ntsc_bisqwit.rscrates/rustynes-mappers/src/fds.rscrates/rustynes-mappers/src/kaiser.rscrates/rustynes-mappers/src/lib.rscrates/rustynes-mappers/src/m016_bandai_fcg.rscrates/rustynes-mappers/src/m035_jy_asic.rscrates/rustynes-mappers/src/m176_bmc_fk23c.rscrates/rustynes-mappers/src/m268_bmc_coolboy.rscrates/rustynes-mappers/src/m513_sachen_9602.rscrates/rustynes-mappers/src/mmc3_clones.rscrates/rustynes-mappers/src/multicart_discrete.rscrates/rustynes-mappers/src/ntdec.rscrates/rustynes-mappers/src/sachen_discrete.rscrates/rustynes-mappers/src/unif.rscrates/rustynes-ppu/src/ppu.rsdocs/ai-emulator-provenance-guardrails.mddocs/provenance-failure-postmortem.md
… layout
Reflow `ref-docs/RustyNES_Provenance-Failure-Postmortem.pdf` from the
prior dense two-column treatment to a single wide-column, full-page
layout. The two-column measure forced an awkward mid-title column break
and cramped the first page; the evidence timeline table (already a
full-width block) sat inconsistently between the two flowed columns.
Typographic changes (theme CSS, WeasyPrint pipeline unchanged otherwise):
- `.cols` collapses from `columns: 2` (with a column rule) to a plain
single-column block; body text switches from justified to left-aligned
(ragged right) for the wider measure.
- Base type 8.75pt -> 10.2pt, line-height 1.4 -> 1.5; page margins
widened to 1.9/2.1/1.6/2.1cm to hold the single-column measure near a
comfortable ~80-char line rather than a full 19cm bleed.
- Headings scaled to the new base (h2 11.5 -> 13.5pt, h3 9.6 -> 11pt),
the evidence table 6.9 -> 8.4pt, code blocks 7.6 -> 8.6pt, and the
maintainer's NOTE box 8.6 -> 10pt.
Cool blue/teal structure, red-only-for-takeaways emphasis, and the
blue-shaded "MAINTAINER'S STATEMENT" NOTE box are all preserved; the
document grows from 4 to 5 pages, which the maintainer accepted
("regardless of the final page count"). Source markdown
`docs/provenance-failure-postmortem.md` is unchanged.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… PDF Two presentation tweaks to the closing "Maintainer's Statement": - Source `docs/provenance-failure-postmortem.md`: remove the surrounding quotation marks from the DoubleGate NOTE so the statement reads as a first-person remark rather than a quoted block. Wording unchanged. - Regenerated `ref-docs/RustyNES_Provenance-Failure-Postmortem.pdf`: the PDF assembly now wraps everything after "NOTE (from DoubleGate): " in an <em>, so the statement body renders italic while the "NOTE (from DoubleGate):" label stays upright. This is a PDF-only styling step (the assembler splits the note paragraph at the "): " marker and re-parents the trailing nodes — including the `~/.claude/` code span — under an emphasis element); the Markdown source carries no emphasis markup so its own rendering is unaffected. Layout, theme, and page count (5) are otherwise unchanged. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ons and prevention" In the maintainer's NOTE, change the cross-reference from "#7 'Lessons and prevention'" to a bold "7. Lessons and prevention" in both surfaces: - Source `docs/provenance-failure-postmortem.md`: wrap the phrase in `**...**` and drop the `#` prefix and single quotes. - Regenerated `ref-docs/RustyNES_Provenance-Failure-Postmortem.pdf`: the phrase is now a <strong> inside the italic NOTE body, so it reads as a bold section label (the assembler re-parents it under the note's <em> along with the rest of the statement body). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
PDF-only styling: within the italic NOTE body, "Fiskbit" is now wrapped
in a <strong class="upright"> so it reads bold and non-italicized while
the rest of the statement stays italic. The assembler splits the note
text run and re-parents the name under an upright strong; the theme adds
`.note-box strong.upright { font-style: normal; }` to cancel the
inherited italic (leaving the bold "7. Lessons and prevention" label,
also a strong, italic as before). Markdown source unchanged.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Render `docs/ai-emulator-provenance-guardrails.md` to a styled PDF at
`ref-docs/AI-Emulator-Provenance-Guardrails.pdf`, using the same cool
"Calm" family theme as RustyNES_Provenance-Failure-Postmortem.pdf so the
two provenance documents read as a set.
Pipeline (pandoc gfm -> html5, a small BeautifulSoup title-block/emphasis
pass, WeasyPrint with a dedicated theme CSS):
- Full-width single-column, humanist sans (Fira Sans), blue/teal
structure; red reserved for the few hardest takeaways ("capability +
availability + accuracy objective", "C used as if it were A",
"source physically unavailable to the agent", "Never launder").
- Title block reflecting the doc's own framing (community best-guidance;
ready-to-ingest ruleset), running header/footer retitled for this doc.
- The document's own structures styled to match: the "in one sentence"
blockquote becomes a teal TL;DR callout; GitHub task-list checklists
render as blue-outlined checkboxes (the real <input> hidden, the box
drawn as an absolutely-positioned gutter marker — reliable in
WeasyPrint); the paste-ready block keeps the monospace code panel;
tables get the navy-header/zebra treatment with hyphenated long words.
8 pages. The Markdown source is unchanged; this is a presentation
artifact derived from it.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ls PDF The §8 code panel rendered at 8.6pt, so its ~95-char lines wrapped raggedly inside the box and one bullet's leading "-" was orphaned onto its own line. Drop the monospace size to 6.9pt (the block's lines now fit the panel width) and add a hanging indent so any residual continuation line stays readable under its bullet. The document tightens from 8 to 7 pages; nothing else changes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…opment rule Add a `## MOST IMPORTANT RULE — Provenance & license firewall` section at the top of the AGENTS.md project block (reached via the CLAUDE.md / GEMINI.md symlinks), positioned before "## What this is" so it is the first substantive guidance every session loads. It is declared to outrank everything else in the file. Motivation: RustyNES is a corrected provenance failure — GPL emulator source (Mesen2, puNES, FCEUX, GeraNES) was reproduced despite a black-box instruction, the honest "ported from X" comments were later scrubbed, and the project was relicensed MIT/Apache -> GPL-3.0-or-later as the derivative work it actually is. The failure was caught by an outside NESdev reviewer, not by tooling, which is the empirical basis for the "do not self-certify" clause. The full preventive ruleset now lives in docs/ai-emulator-provenance-guardrails.md (with a forensic post-mortem in docs/provenance-failure-postmortem.md); this section is the always-loaded distillation that binds an agent before it touches any file. The section encodes the six non-negotiables — the REFERENCE FIREWALL (reference emulators are black-box oracles whose output may be observed but whose source is never read or reproduced; the local ref-proj/ clone is removed from disk and stays gitignored so the source is out of reach by design), IMPLEMENT FROM DOCS, IF YOU DERIVE SAY SO AND STOP (attribute at the site + originality doc §1 + NOTICE + SPDX; keep the license GPL-3.0-or-later-compatible), NEVER LAUNDER, NO OVER-ATTRIBUTION, and DO NOT SELF-CERTIFY — and points at the mechanical enforcement that backs the prose (the gitignore / dockerignore / markdownlintignore / CodeRabbit exclusions, deny.toml, and the per-file SPDX + provenance headers), on the principle that a rule the tooling enforces beats a rule an agent is merely asked to follow. Also updates the existing `.markdownlintignore` note to record that ref-proj/ is now removed from disk but retained in the ignore lists as a firewall guard rather than as a build convenience. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… paths Delete the removed-clone `ref-proj/` prefix from every in-source provenance citation so each names the upstream project + file directly (attribution surface #1 of the guardrails: "the upstream project, the specific file/function, and its license"), rather than a path into a local working copy that no longer exists. `ref-proj/GeraNES/src/GeraNES/Mappers/Mapper0NN.h` becomes `GeraNES/src/GeraNES/Mappers/Mapper0NN.h`; `ref-proj/Mesen2/Core/...`, `ref-proj/TriCNES/Emulator.cs`, `ref-proj/tetanes`, and `ref-proj/fceux/...` likewise. The one non-path use — m024_vrc6.rs's "a cross-check against the whole `ref-proj/` field" — is reworded to "the whole field of reference emulators". This is a pure path/wording normalization: it does not change any derivation claim. The sites that genuinely document a port keep their verb and license verbatim — ppu.rs still reads "Ported from TriCNES (`TriCNES/Emulator.cs`, MIT, commit 9199870)", and m093_sunsoft3r.rs still says its `writePrg` matches "the designated reference `GeraNES/src/GeraNES/Mappers/Mapper093.h`, whose `writePrg` opens with `data &= readPrg(addr);`". Nothing is softened, laundered, or over-attributed; only the dangling local-clone prefix is removed. Scope: 30 files across rustynes-core (movie_interop), rustynes-frontend (crt + two debugger panels), rustynes-mappers (28 board modules), and rustynes-ppu. The changes are comments and doc-comments only — no code tokens move — so the compiled `#![no_std]` chip stack is byte-identical, the deterministic contract is untouched, and AccuracyCoin holds 141/141 and nestest stays 0-diff by construction. Verified: `cargo check --workspace` clean, `RUSTDOCFLAGS="-D warnings" cargo doc --workspace --no-deps` clean, `cargo fmt --all --check` clean, and `git grep "ref-proj/" -- crates/**/*.rs` now returns nothing. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ocs and ignores The local `ref-proj/` reference-emulator clone (Mesen2, puNES, FCEUX, GeraNES, TriCNES, tetanes, ...) has been removed from disk. Update the surrounding documentation and ignore configuration so nothing points a developer — or an agent — back at reference-emulator source, and so the firewall is stated where the setup that used to depend on ref-proj/ lived. - .gitignore: keep the `/ref-proj/` entry but re-annotate it as a *firewall guard* — the directory is removed and must never re-enter the working tree, because its copyleft source is what made RustyNES a derivative work. The entry now cross-links the guardrails doc and the AGENTS.md top rule. (The parallel ignores in .dockerignore / .markdownlintignore / .pre-commit-config.yaml / .coderabbit.yaml are retained unchanged for the same belt-and-suspenders reason.) - Oracle / trace tooling (docs/tooling/oracle-tooling-setup.md, docs/ppu-trace-tooling.md): add a REFERENCE FIREWALL banner and rewrite the ref-proj/ paths. These guides build and instrument a reference emulator to capture its *output* for cross-diffing — legitimate black-box-oracle use — so they now state that any such build must live out-of-tree, outside the agent's allowed paths, and be used for output only; the committed golden vectors (crates/rustynes-test-harness/golden/) remain the preferred, self-contained path that needs no reference source at all. - Provenance / spec docs: originality-and-provenance.md records that the §1 derivation table was cross-checked against the sources at the time (the since-removed ref-proj/ clone) and stands on its named upstream citations; STATUS.md, to-dos/ROADMAP.md, adr/0030, adr/0006, apu-2a03.md, hd-pack-zelda-troubleshooting.md, and SALVAGE_MANIFEST.md have their ref-proj/ citations normalized to upstream (or, where they said "vendored ref-proj/X", corrected to "out-of-tree" / "in-repo", since the clone is no longer vendored). - Discoverability: add a "Provenance & Licensing" section to docs/DOCUMENTATION_INDEX.md and a matching group to the mkdocs nav so the guardrails, post-mortem, originality record, and ADR 0036 are linked from the documentation entry points rather than only from AGENTS.md. Frozen / historical trees (docs/archive/, to-dos/archive/, to-dos/plans/**, ref-docs/, .github/release-notes/, CHANGELOG-FULL.md) deliberately keep their ref-proj/ mentions as immutable record. No behavior changes; markdownlint clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…GELOG Surface the provenance guardrails on the two developer-facing entry points. - README.md: add a "Reference firewall (so it does not recur)" paragraph to the License section, immediately after the existing GPLv3-derivation and AI-assistance disclosures. It names the forensic post-mortem and the console-agnostic guardrails ruleset (with the themed PDFs in ref-docs/), states that it is the project's top development rule ingested into AGENTS.md, and summarizes the firewall: reference emulators are black-box oracles whose output may be observed but whose source is never read; the ref-proj/ clone is removed and gitignored so that source is out of reach; hardware behavior is implemented from documentation and test ROMs; genuine derivation is attributed and license-checked, never laundered. Notes the guardrails are shared as community best-guidance for other AI-assisted emulator projects. - CHANGELOG.md [Unreleased]: add a "Provenance guardrails + reference firewall" block recording the new guardrails doc + post-mortem + PDFs, the ingestion into AGENTS.md and the memory bank, the ref-proj/ removal and the retained firewall ignores, the comments-only normalization of in-source citations to upstream paths (deterministic core byte-identical), the out-of-tree oracle posture in the tooling docs, and the new documentation-index / mkdocs-nav entries. Documentation only. markdownlint clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…tations A CodeRabbit review of #346 flagged a per-site ↔ central-table inconsistency in the provenance record. A full audit of every `derived from Mesen2's \`X\`` comment against its `docs/originality-and-provenance.md` §1 row confirmed six files whose in-source citations name an upstream Mesen2 header that the central table row omitted. Each such header is a shared chip/transform that a sibling file already lists in its own row, so the table under-reported which files derive from it: - `kaiser.rs` (mapper-253 IRQ board, line 614) derives from `Waixing/Mapper253.h`. - `m035_jy_asic.rs` (`invert_prg_bits`, line 315) derives from `InvertPrgBits`. - `m176_bmc_fk23c.rs` (CoolBoy banking, line 554) derives from `Mmc3Variants/MMC3_Coolboy.h`. - `m513_sachen_9602.rs` (TxcChip accumulator, line 349) derives from `Txc/TxcChip.h`. - `mmc3_clones.rs` (Sachen 8259A/B/C, mappers 138/139/141, line 784) derives from `Sachen/Sachen8259.h`. - `ntdec.rs` (BMC-11160, line 1262) derives from `Txc/Bmc11160.h`. Add each missing upstream header to the corresponding table row so the central derivation record is fully consistent with the per-site attributions, per the provenance guardrails' "provenance-comment ↔ table consistency" rule. This is an alignment, not new attribution: each derivation is already asserted verbatim in the source comment; the table now records what the code already documents (a correction toward completeness, not over-attribution). No license changes — all six sources are Mesen2 (GPL-3.0-or-later), already the project's license. Documentation only; markdownlint clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
crates/rustynes-frontend/src/debugger/input_miniatures_panel.rs (1)
132-147: 🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy liftEnable native multi-viewport support before claiming OS-window detachment.
super::detachable_windowusesshow_viewport_immediate, butcrates/rustynes-frontend/src/debugger/mod.rs:285-367states that the currentegui_winitintegration is single-viewport. The detached panel therefore renders embedded in the main window instead of opening a native OS window.Enable multi-viewport handling in the frontend render loop, or update the release behavior and documentation to describe embedded detachment.
Also applies to: 169-170
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/rustynes-frontend/src/debugger/input_miniatures_panel.rs` around lines 132 - 147, Enable native multi-viewport support in the frontend render loop used by super::detachable_window before relying on show_viewport_immediate for detached panels. Update the egui_winit integration and viewport event/render handling so “Input Display” opens as a native OS window, and apply the same behavior to the other detachable panel call sites. If multi-viewport support cannot be enabled, change detachable_window’s release behavior and documentation to describe embedded detachment instead.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.gitignore:
- Around line 191-194: Update the .gitignore comment for /ref-proj/ to remove
the blanket claim that all referenced emulator sources are copyleft, stating
instead that project licenses are specific (including TriCNES as MIT) or
omitting the license claim. Preserve the existing /ref-proj/ ignore rule.
In `@docs/DOCUMENTATION_INDEX.md`:
- Around line 48-61: Remove the literal ref-proj/ path from the provenance
documentation entry in DOCUMENTATION_INDEX.md, while preserving the explanation
that the reference clone was removed and firewall-gitignored. Do not add that
repository path elsewhere in the documentation index.
In `@docs/originality-and-provenance.md`:
- Around line 47-51: Remove the published ref-proj/ repository path from the
provenance description in docs/originality-and-provenance.md lines 47-51,
describing the removed reference-emulator clone without reproducing its path.
Apply the same wording change to the documentation index description in
docs/DOCUMENTATION_INDEX.md lines 48-61; both sites require direct updates.
In `@docs/tooling/oracle-tooling-setup.md`:
- Around line 3-21: Resolve the contradictory reference-source policy in the
documentation: retain the firewall rule that reference emulators are black-box
oracles, remove or relocate the vendored TriCNES source under the golden
artifacts, and update the preferred harness guidance to reference only outputs
and golden vectors. Ensure the related sections consistently prohibit
in-repository reference source.
---
Outside diff comments:
In `@crates/rustynes-frontend/src/debugger/input_miniatures_panel.rs`:
- Around line 132-147: Enable native multi-viewport support in the frontend
render loop used by super::detachable_window before relying on
show_viewport_immediate for detached panels. Update the egui_winit integration
and viewport event/render handling so “Input Display” opens as a native OS
window, and apply the same behavior to the other detachable panel call sites. If
multi-viewport support cannot be enabled, change detachable_window’s release
behavior and documentation to describe embedded detachment instead.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 52fa777b-8539-4f3e-bd22-3771d1457291
⛔ Files ignored due to path filters (2)
ref-docs/AI-Emulator-Provenance-Guardrails.pdfis excluded by!**/*.pdf,!ref-docs/**ref-docs/RustyNES_Provenance-Failure-Postmortem.pdfis excluded by!**/*.pdf,!ref-docs/**
📒 Files selected for processing (48)
.gitignoreAGENTS.mdCHANGELOG.mdREADME.mdcrates/rustynes-core/src/movie_interop.rscrates/rustynes-frontend/src/crt.rscrates/rustynes-frontend/src/debugger/hd_pixel_panel.rscrates/rustynes-frontend/src/debugger/input_miniatures_panel.rscrates/rustynes-mappers/src/homebrew_boards.rscrates/rustynes-mappers/src/jaleco_discrete.rscrates/rustynes-mappers/src/m024_vrc6.rscrates/rustynes-mappers/src/m035_jy_asic.rscrates/rustynes-mappers/src/m038_bitcorp38.rscrates/rustynes-mappers/src/m039_subor39.rscrates/rustynes-mappers/src/m041_caltron41.rscrates/rustynes-mappers/src/m079_ave_nina03_06.rscrates/rustynes-mappers/src/m093_sunsoft3r.rscrates/rustynes-mappers/src/m096_bandai96.rscrates/rustynes-mappers/src/m107_magic_dragon107.rscrates/rustynes-mappers/src/m113_ave_nina006.rscrates/rustynes-mappers/src/m156_daou156.rscrates/rustynes-mappers/src/m180_nichibutsu180.rscrates/rustynes-mappers/src/m185_cnrom185.rscrates/rustynes-mappers/src/m232_camerica_bf9096.rscrates/rustynes-mappers/src/m240_cne_multicart.rscrates/rustynes-mappers/src/m241_bxrom241.rscrates/rustynes-mappers/src/m244_cne_decathlon.rscrates/rustynes-mappers/src/m246_fong_shen_bang246.rscrates/rustynes-mappers/src/m250_nitra250.rscrates/rustynes-mappers/src/multicart_discrete.rscrates/rustynes-mappers/src/ntdec.rscrates/rustynes-mappers/src/sachen_8259.rscrates/rustynes-mappers/src/sachen_discrete.rscrates/rustynes-ppu/src/ppu.rsdocs/DOCUMENTATION_INDEX.mddocs/SALVAGE_MANIFEST.mddocs/STATUS.mddocs/adr/0006-vrc7-audio-landed.mddocs/adr/0030-accuracycoin-ale-read-hybrid-addresses-octal-latch.mddocs/ai-emulator-provenance-guardrails.mddocs/apu-2a03.mddocs/hd-pack-zelda-troubleshooting.mddocs/originality-and-provenance.mddocs/ppu-trace-tooling.mddocs/provenance-failure-postmortem.mddocs/tooling/oracle-tooling-setup.mdmkdocs.ymlto-dos/ROADMAP.md
…nore docs Address four follow-on CodeRabbit findings on #346: - .gitignore: the ref-proj/ guard comment claimed the referenced emulators' source is uniformly "copyleft". That over-generalized — Mesen2 / puNES / FCEUX / GeraNES are GPL, but TriCNES is MIT. Reword to state the licenses are project-specific (copyleft for the four GPL oracles; MIT for TriCNES) and note that the MIT TriCNES source is instead deliberately vendored, with attribution, under crates/rustynes-test-harness/golden/tricnes/. The /ref-proj/ ignore rule itself is unchanged. - docs/tooling/oracle-tooling-setup.md: resolve a genuine contradiction. The two firewall notes said "any Mesen2 / TriCNES build must live out of tree", but the same page (§2a) vendors the complete MIT TriCNES source in-repo at golden/tricnes/tricnes-full-src/ and calls the in-tree harness the preferred path. Scope the out-of-tree / never-reproduce rule to the copyleft references (Mesen2, puNES, FCEUX, GeraNES) and state TriCNES explicitly as the MIT exception whose in-repo vendoring is license-compatible and not a firewall violation. The committed golden vectors remain the preferred, no-live-emulator path. - docs/originality-and-provenance.md and docs/DOCUMENTATION_INDEX.md: describe the removed reference-emulator clone without reproducing its literal repository path in these provenance/index prose additions (the path stays authoritatively named where it is load-bearing — the /ref-proj/ ignore rule and the AGENTS.md rule). Documentation only; markdownlint clean. No behavior change. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…fication
`bk2_interop::parse_log_key` collected every `#`-separated group of the BizHawk
`LogKey` header into a `Vec<&str>` and then read only `groups[1]` (P1) and
`groups[2]` (P2). A hostile `.bk2` whose `LogKey` is padded with a large run of
`#` delimiters therefore allocated one `&str` slot (~16 bytes on 64-bit) per
empty group — an unbounded, ~16x-of-input allocation on an untrusted import path,
the same DoS class the v2.2.0 `Movie::deserialize` fuzzing already closed
elsewhere.
Read the three groups we actually consume (console, P1, P2) directly from the
`split('#')` iterator via `next()` instead of collecting. `split` still yields
empty groups, so `next()` preserves the empty console slot (`##P1…`) and keeps
P1/P2 from shifting left into it — the behavior is byte-identical for every valid
movie, only the unbounded intermediate allocation is removed. The parse now
touches at most three groups regardless of how many `#` the input contains.
Adds `log_key_bounded_against_pathological_group_padding`, which imports a movie
whose `LogKey` carries 100k trailing `#` delimiters and asserts P1/P2 still map
correctly (the trailing groups are ignored), as the standing regression guard.
This is the `.bk2` *import* path only; the deterministic chip stack and every
golden vector are untouched (AccuracyCoin 141/141 unaffected).
Reported by CodeRabbit as an outside-diff-range finding on #346.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
….2.9 notes Three corrections to the [2.2.9] release notes (which release-auto.yml publishes verbatim, so accuracy and completeness there matter): - **Honesty fix (CodeRabbit outside-diff-range finding).** The intro note claimed detached tool windows use "egui multi-viewport (real OS windows)", which contradicted both the detailed "Fixed" entry and AGENTS.md: the frontend is a single-viewport `egui_winit` integration, so `show_viewport_immediate` renders a detached panel *embedded in the main window*, not as a separate OS window, and the Windows-10 "trapped window" report is therefore not yet fully resolved. Reword the note to state the embedded scope honestly and point at the v2.3.0 multi-viewport follow-up, matching the rest of the section. - **Fold [Unreleased] into [2.2.9].** The provenance-guardrails + reference-firewall work (guardrails doc + post-mortem + PDFs, ingestion into AGENTS.md and memory, the ref-proj/ removal and citation normalization, the §1 derivation-table audit, and the MIT-TriCNES vendoring exception) all ship in v2.2.9, so it belongs in the v2.2.9 notes rather than a separate [Unreleased] section the release body would omit. Recorded as a new "Added — Provenance & license firewall" subsection. - **Log the .bk2 import hardening** (the `LogKey` allocation-amplification bound) in the same subsection. Documentation only; markdownlint + fmt clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adjudication of the "Outside diff range" findingsThese aren't resolvable inline threads, so recording the disposition here. 1. 2/3. 4. |
Antigravity review (Gemini via Ultra)This PR updates RustyNES to v2.2.9 "Studio II", wiring TAStudio piano-roll input edits to trigger an emulator re-seek, parsing dynamic Blocking issuesNone found. Suggestions
Nitpicks
Automated first-pass review by |
… tool windows; GPL-3.0-or-later relicense (#346) Two independent bodies of work land together in v2.2.9: a frontend quality-of-life pass ("Studio II") and the licensing/provenance remediation prompted by NESdev-community review. Both are confined to the frontend and the docs/licensing surface — the deterministic `#![no_std]` chip stack, the save-state / TAS / netplay formats, and every golden vector are byte-identical, so AccuracyCoin holds 141/141 (100.00%) and nestest is 0-diff by construction. Frontend — "Studio II" ---------------------- TAStudio piano-roll edits now drive the emulator. The panel path (`handle_tas_requests`) previously mutated only the editor's `input_log` on a `SetInput` and never re-derived the running `Nes`, so a cell edit looked disconnected from emulation (the "TAStudio inputs are not connected up" report). It now tracks an `input_dirty` flag across a batch and does a single deterministic re-seek to the cursor afterward, exactly as the scripting path (`apply_tas_commands`) already did; `InsertFrame` / `DeleteFrame` / `StampMacro` also mark dirty, while `Seek` / `CreateBranch` / `LoadBranch` reseat the `Nes` themselves. `.bk2` movie import honors the movie's column order. The parser ignored the `LogKey:` header and mapped pad columns by a fixed `U D L R S s B A` position, so a BizHawk movie authored with a different order or extra columns mapped every button to the wrong bit ("`.bk2` did not play back"). `parse_log_key` now reads the per-port column order from the `LogKey` (`#` groups, `|` columns), maps each column by its button name (ignoring the `Pn ` prefix), and falls back to the standard order when a group is truncated or exotic; `parse_pad` maps by that column list and tolerates a group longer than the modeled columns (extra buttons such as a microphone are ignored). A new test covers a non-standard order plus an extra column. Tool windows gain a detach / pop-out affordance via a shared `detachable_window` helper wired across 18 panels, and per-panel window geometry (first-open position / size / resizability) is preserved through it. Honest scope caveat: the frontend is a single-viewport `egui_winit` integration, so `show_viewport_immediate` currently renders a detached panel *embedded* in the main window rather than as a separate OS window — this does not yet fully resolve the Windows-10 "trapped window" report; true OS-window detach needs multi-viewport render-loop wiring and is tracked as a v2.3.0 follow-up. All detach code is native-only; wasm stays docked. Licensing & provenance — relicense to GPL-3.0-or-later (ADR 0036) ---------------------------------------------------------------- A NESdev-community review established that RustyNES is a derivative work of GPL-licensed emulators: it incorporates code derived from Mesen2 (GPL-3.0-or-later) and, for several mappers and the FDS drive model, from puNES, FCEUX, and Nestopia UE (all GPL-2.0-or-later). The v2.2.5 "no GPL source incorporated" / MIT-OR-Apache-2.0 position was therefore wrong and is withdrawn: `LICENSE` becomes GPL-3.0-or-later and `deny.toml` is updated to match. Every genuinely-derived source file carries a corrected SPDX identifier plus a per-file provenance header naming the upstream file/function it was ported or closely modeled from, and the earlier "laundered" per-function comments at those ported sites are restored to state the real derivation. `NOTICE` is rewritten to separate derived code (why the project is GPL) from behavioral-oracle use (no code incorporated), and `docs/originality-and-provenance.md` leads with the file-by-file derivation record. Documentation ------------- Adds the provenance-failure post-mortem (`docs/provenance-failure-postmortem.md`) and the console-agnostic, ingestible provenance/license guardrails for AI-assisted emulator development (`docs/ai-emulator-provenance-guardrails.md`), each with a themed PDF in `ref-docs/`; folds in the CodeRabbit / Copilot #346 review items; and bumps the README version badge to v2.2.9. Verification ------------ Frontend- and docs-only, so the emulation core is untouched: AccuracyCoin 141/141, nestest 0-diff, blargg/kevtris and the 60-ROM oracle unchanged. The tree passes `cargo fmt`, `clippy -D warnings` (workspace + feature combos), `rustdoc -D warnings`, markdownlint, and the `no_std` cross-compile. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
v2.2.9 "Studio II" — TAS/movie wiring + detachable tool windows
Fourth step of the v2.2.6 → v2.3.0 NESdev-remediation line. Addresses three
forum items: TAStudio piano-roll edits that never reached the emulator,
.bk2movies that imported but didn't play back, and tool windows trapped inside the
main OS window on Windows 10.
Frontend-only — core untouched
Nothing here touches emulation, so the deterministic chip stack, save-states, and
every golden vector are byte-identical (AccuracyCoin 141/141, nestest 0-diff).
Fixed
handle_tas_requestsmutatedTasEditor::input_logonly and never re-seeked theNes, so a cell edit wasinvisible until an unrelated seek. It now re-derives through
TasEditor::seekafter the batch — the path the scripting bridge (
apply_tas_commands) already used..bk2playback honors the movie'sLogKeycolumn order.bk2_interopmappedcolumns by a fixed built-in order and ignored the
LogKey:header, so BizHawkmovies with a different column order drove the wrong buttons. It now parses the
real
LogKey:order (standard-order fallback), and import parse errors surface onthe on-screen status bar instead of only
eprintln!.Added
detachable_windowhelper gives each tool panel a "⧉ Detach" button that pops it into a real OS
window (
show_viewport_immediate) with a "⧉ Reattach" affordance; 17 panels arerouted through it. Native-only — egui multi-viewport needs winit multi-window, so
on wasm panels stay docked in an
egui::Window(unchanged).Checks
native
clippy -D warnings(sweeper + pre-commit), wasm32clippy -D warningsgreen on both the default and
wasm-canvasfeature sets (the detach path is#[cfg]-gated native-only; a wasm-scopedallow/discard keepsunused_variablesneedless_pass_by_ref_mutclean),cargo fmt, markdownlint,cargo check --workspace. Docs: STATUS/README/AGENTS/CHANGELOG +docs/frontend.md.🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
.bk2playback honors declaredLogKeyordering and accepts extra columns.Bug Fixes
Documentation
Chores