{
  "schemaVersion": 1,
  "productionFile": "speed-controls.js",
  "productionSha256": "78f4e2279bbbfbd72c238740dfb7d1da765874a35b9b73310ea97b7bba3ed5b8",
  "stylesheetSha256": "a76966146335d62b48f8bf8570f88b700801d8d0db3351861fa99f66e5179a87",
  "date": "2026-10-25",
  "vendorContractTests": {
    "status": "PASS",
    "checks": 113,
    "browserAutomationPerformed": false,
    "physicalControllerTestPerformed": false,
    "nativeCoreExecutionPerformed": false,
    "scope": "Actual bundled JS GameManager, EmulatorJS gamepad event and minified GamepadHandler executed in Node with bounded host spies; shared reconnect adapter executed. DOM/event-model checks are not a real browser or physical-controller test.",
    "sourceHashes": {
      "speedControls": "78f4e2279bbbfbd72c238740dfb7d1da765874a35b9b73310ea97b7bba3ed5b8",
      "speedCss": "a76966146335d62b48f8bf8570f88b700801d8d0db3351861fa99f66e5179a87",
      "GameManager": "f026130eda3648557498c54c70cbb5b36fd71b088e7e42e5a13e413aab11d888",
      "EmulatorJS": "24ebac4baf739892046b82c3bdf01d5b6795b801b77d289e43a4c7d59f9666be",
      "minifiedVendor": "6aec3fd7bb2721255801b0a6af02e47e78b05e28a1822b1f213aacbd348abaee",
      "sharedController": "26296400d462169ed378dd6c05823b79d76384cceb401ffb5bbcc28a3dc05fa7"
    },
    "coverage": [
      "actual vendor rewind/fast-forward dispatch and scoped bounded config",
      "block_sram_overwrite remains true; no memory-card rollback",
      "default-off original trigger pass-through",
      "selected standard Player1 trigger filtering with unchanged bindings",
      "actual shared reconnect adapter before/after speed filter and sparse pads",
      "no shoulder leakage or phantom press across enable/off/focus/disconnect",
      "read-only navigator API preserved; unfilterable provider fails closed to onscreen-only speed",
      "hold priority and public fast-forward API independent of native inversion",
      "pointer capture/cancel/loss; focused Space/Enter holds; no global hotkeys",
      "pause/dialog/card-clear lifecycle; no auto-resume",
      "DOM model and code contracts only; physical/browser QA pending"
    ]
  },
  "coreCardBoundaryAudit": {
    "status": "PASS_WITH_EXPLICIT_SCOPE",
    "auditDate": "2026-10-25",
    "productionChanges": false,
    "priorAssistanceEvidenceChanged": false,
    "assertions": 18,
    "assertionsPerCoreVariant": 9,
    "gameplayStatesReversed": 24,
    "fullSyntheticCardComparisons": 4,
    "syntheticCardBytesPerComparison": 131072,
    "fixture": {
      "script": "work/castlevania-speed-audit/probe-cards.cjs",
      "execution": "Both variants executed successfully as a temporary stdin script; the retained script records the same tested procedure with comments and assertion counts.",
      "hostHook": "JS-only MainLoop.runIter hook compiled in memory; original wrappers and WASM were not changed.",
      "blockSramOverwrite": false,
      "rewindBufferMiB": 8,
      "rewindGranularity": 1,
      "stateBytes": 4456472,
      "saveStateGameplayRamRestored": true,
      "saveStateChangedCardPreserved": true,
      "rewindGameplayRamTraceHex": [
        "50000027",
        "50000026",
        "50000025",
        "50000024",
        "50000023",
        "50000022",
        "50000021",
        "50000020",
        "5000001f",
        "5000001e",
        "5000001d",
        "5000001c"
      ],
      "rewindChangedCardPreserved": true,
      "modern": {
        "wasmSha256": "ce204a800ee0914cabddefe88448dfaa2b43864039c4f39a32d4872c1037b9ed",
        "wrapperSha256": "42f536af90108189a0747698acb20341d04f8ac02913daa6fd9bf238bdc97841"
      },
      "legacy": {
        "wasmSha256": "fc2b803ed940fb63faa89de394d31003f9e4106ee009c2f6798551a3c5fb518f",
        "wrapperSha256": "4f7440bdd6b05f4fe3e51986e28edc24cad75cf6412b1633a3e40ca14d8398e1"
      },
      "userSaveOrBrowserStorageAccessed": false,
      "hostCardFileWritten": false
    },
    "runtimeVersions": {
      "RetroArch": "1.21.0 / 6dd4353937ef48b6ec0bfbdbb15d1c5992d86927",
      "PCSX-ReARMed": "092633f8ad0941958961e71f2cc372ab61364b5a"
    },
    "findings": [
      "The selected PCSX core keeps memory-card bytes in Mcd1Data, exposed separately as RETRO_MEMORY_SAVE_RAM. Its SaveState/LoadState/sioFreeze do not serialize that array. Exact bundled-core synthetic-card tests confirm full card preservation while gameplay state rewinds.",
      "RetroArch rewind calls content_deserialize_state directly. block_sram_overwrite backup/restore is in the ordinary state-loading task, so the flag is not a general rewind protection mechanism.",
      "SIO transfer buffer/status/address fields ARE restored. The runloop executes the core after state restoration. Rewinding through an in-progress save can therefore replay a card write; the fixture did not test or claim safety for that case.",
      "Suppressing browser flushes does not disable emulated card writes. The page's getSaveFile triggers cmd_savefiles; IDBFS is autoPersist, and native RetroArch autosave is also configured. Card operations should not run while rewind is held, and a later flush must still validate card coherence.",
      "Fast-forward/rewind use retained vendor APIs, not RAM writes. Rewind history is initialized before startup. History is finite and compressed-state size varies; no fixed number of seconds is promised.",
      "Current player LT/RT also map to original L2/R2. The new opt-in speed provider must mask those selected-controller triggers without changing persisted mappings. The implementing agent reports this masking and neutral-release fencing is covered by its own vendor/shared-controller tests."
    ],
    "minimalPrecautions": [
      "Keep block_sram_overwrite=true for ordinary state loads, but do not advertise it as rewind protection.",
      "Release rewind on blur, pagehide, pause and card actions. Suspend page manual/periodic card flush, import and export while rewind is held.",
      "Do not restore an older card image as part of rewind. Resume normal emulation and finish any in-game save before a validated flush.",
      "Explain that rewind affects gameplay, not completed memory-card saves, and should not be used through the game's saving screen.",
      "Keep history configuration bounded and report varying duration/performance rather than a guaranteed time window."
    ],
    "sources": [
      "https://github.com/EmulatorJS/RetroArch/blob/6dd4353937ef48b6ec0bfbdbb15d1c5992d86927/state_manager.c#L749-L779",
      "https://github.com/EmulatorJS/RetroArch/blob/6dd4353937ef48b6ec0bfbdbb15d1c5992d86927/tasks/task_save.c#L939-L977",
      "https://github.com/EmulatorJS/RetroArch/blob/6dd4353937ef48b6ec0bfbdbb15d1c5992d86927/tasks/task_save.c#L1037-L1105",
      "https://github.com/EmulatorJS/RetroArch/blob/6dd4353937ef48b6ec0bfbdbb15d1c5992d86927/runloop.c#L7114-L7164",
      "https://github.com/EmulatorJS/RetroArch/blob/6dd4353937ef48b6ec0bfbdbb15d1c5992d86927/retroarch.c#L6217-L6257",
      "https://github.com/EmulatorJS/pcsx_rearmed/blob/092633f8ad0941958961e71f2cc372ab61364b5a/libpcsxcore/sio.c#L773-L788",
      "https://github.com/EmulatorJS/pcsx_rearmed/blob/092633f8ad0941958961e71f2cc372ab61364b5a/libpcsxcore/misc.c",
      "https://github.com/EmulatorJS/pcsx_rearmed/blob/092633f8ad0941958961e71f2cc372ab61364b5a/frontend/libretro.c"
    ],
    "localInterfacesInspected": [
      "original/data/src/GameManager.js: getRetroArchCfg, simulateInput, saveSaveFiles, getSaveFile, toggleFastForward, setFastForwardRatio, setRewindGranularity",
      "original/data/src/emulator.js: rewind initialization, speed settings, save-save-interval",
      "original/player.js: five-second flush, card actions, visibility and pagehide",
      "original/card-manager.js: capture, format validation, serialized flush and IDBFS confirmation",
      "original/speed-controls.js: scoped config preparation, selected-provider mask, neutral fencing and mode release"
    ],
    "limits": [
      "This is an isolated synthetic-card/core-state test, not an actual SotN save-room test or browser persistence test.",
      "No private card bytes were accessed or written. No original BIN, CUE, BIOS, frozen package, production runtime or prior assistance evidence was modified.",
      "The speed UI agent owns behavioral vendor/shared-controller tests; this audit independently establishes the core/card boundary."
    ]
  },
  "actualBrowserGameplayVerified": false,
  "actualSaveRoomPersistenceVerified": false
}
