{
  "schemaVersion": "4.0",
  "about": "Structured index of the same public research, production findings, and claim-specific proof states shown on the REFORGE website.",
  "snapshot": "a58ea4ac37c644e9a3e810d4aaf0164fc47640b7be06e64101ccc59da1374846",
  "humanIndex": "/reforge/findings/",
  "method": "/reforge/methodology/",
  "definitions": {
    "researchDossier": "Documented hardware knowledge. Publication does not imply a working runtime.",
    "productionFinding": "A conclusion recorded during implementation or verification work.",
    "proofRow": "Claim-specific L0-L5 results; untested boundaries remain explicit.",
    "confirmed": "The named finding has direct supporting evidence.",
    "beingVerified": "The finding or its proof boundary remains open.",
    "corrected": "An earlier model was replaced; the correction remains visible."
  },
  "proofLevels": {
    "L0": {
      "name": "BUILDS",
      "requiredObservation": "A native artifact is produced."
    },
    "L1": {
      "name": "LIVES",
      "requiredObservation": "The requested headless run completes."
    },
    "L2": {
      "name": "RENDERS",
      "requiredObservation": "Fresh visible output is verified."
    },
    "L3": {
      "name": "RESPONDS",
      "requiredObservation": "Scripted input changes title state."
    },
    "L4": {
      "name": "MECHANICS",
      "requiredObservation": "Named game rules pass deterministic checks."
    },
    "L5": {
      "name": "ACCEPTED",
      "requiredObservation": "Corpus, build receipt, and human acceptance gates pass."
    }
  },
  "research": [
    {
      "slug": "odyssey",
      "name": "Magnavox Odyssey",
      "year": "1972",
      "state": "published",
      "programState": "reference",
      "externalReferences": "linked",
      "systemUrl": "/reforge/consoles/odyssey/",
      "publicDossierUrl": "/reforge/research/odyssey/",
      "outline": [
        "The architecture: 12 modules on a single-layer motherboard",
        "How three dots and a line become video: signal generation in detail",
        "Sync generation: two independent oscillators",
        "Spot positioning through analog RC delays",
        "RF modulation and output",
        "Controllers: potentiometers directly driving RC timing circuits",
        "Control layout",
        "Electrical operation",
        "Player 1 vs. Player 2 asymmetry",
        "Game cards: passive jumper PCBs as the world's first interchangeable game media",
        "The 44-pin edge connector",
        "Pin function assignments",
        "Complete jumper configurations for all 12 cards",
        "What each card actually changes",
        "Collision detection and ball behavior: the gate matrix and flip-flops",
        "From Brown Box to production Odyssey",
        "Essential reference documents and recreation projects",
        "Conclusion: implications for a recompilation engine"
      ]
    },
    {
      "slug": "pong",
      "name": "Atari Pong / Home Pong",
      "year": "1975",
      "state": "published",
      "programState": "reference",
      "externalReferences": "linked",
      "systemUrl": "/reforge/consoles/pong/",
      "publicDossierUrl": "/reforge/research/pong/",
      "outline": [
        "Two chips, one architecture: Atari 3659-1C vs. GI AY-3-8500",
        "Complete AY-3-8500 pinout and electrical characteristics",
        "Internal architecture: game logic without a processor",
        "Video generation: from master clock to NTSC signal",
        "Paddle controllers: analog position through RC timing",
        "Every Atari Pong variant from C-100 to C-450",
        "Recreating Pong in software: no CPU means no traditional emulation",
        "Conclusion"
      ]
    },
    {
      "slug": "atari2600",
      "name": "Atari 2600",
      "year": "1977",
      "state": "published",
      "programState": "current",
      "externalReferences": "linked",
      "systemUrl": "/reforge/consoles/atari2600/",
      "publicDossierUrl": "/reforge/research/atari2600/",
      "outline": [
        "1. Power-on Through First Rendered Frame",
        "1.1 6507 reset sequence",
        "1.2 RIOT RAM ($0080–$00FF, 128 bytes) at power-on",
        "1.3 First-frame timing budget",
        "2. Frame-Loop Anatomy (\"Kernel Pattern\")",
        "2.1 NTSC frame structure",
        "2.2 WSYNC ($02)",
        "2.3 RESPx + HMOVE positioning",
        "2.4 RESP0 strobe offset",
        "2.5 HMOVE blank stripe (\"the comb\")",
        "2.6 Score kernel vs. play-field kernel",
        "3. Attract Mode → Gameplay Transition",
        "3.1 Demo-loop detection idioms",
        "3.2 SWCHB ($0282) console-switch bits",
        "3.3 Indirect-JMP-via-zero-page dispatch",
        "4. 6507-Specific Behaviors vs. Textbook 6502",
        "4.1 13-bit address bus consequences",
        "4.2 JMP indirect page-boundary bug",
        "4.3 BRK without IRQ wiring",
        "4.4 Undocumented opcodes used by commercial games",
        "5. TIA Quirks Beyond the Register Table",
        "5.1 Position counters",
        "5.2 HMOVE comb",
        "5.3 Mid-frame RESPx re-strobe",
        "5.4 Collision latches",
        "5.5 Audio",
        "6. RIOT 6532 Quirks",
        "6.1 INTIM countdown",
        "6.2 SWCHA, SWCHB internal pull-ups",
        "6.3 DDR registers",
        "6.4 RAM mirroring and stack-share",
        "7. Bank-Switching Formats",
        "7.1 DEEP coverage",
        "7.2 Bank-switch-while-PC-in-window — the dual-bank trampoline",
        "7.3 LDA-from-hotspot and RMW-on-hotspot",
        "7.4 STUB enumeration",
        "8. Asteroids (CX2649, 1981, Atari, F8, 8192 bytes)",
        "8.1 Boot",
        "8.2 Visible-frame kernel (bank 0, $D003)",
        "8.3 Bank-1 ↔ Bank-0 swap pattern",
        "8.4 Attract mode → gameplay",
        "8.5 Known indirect-JMP-via-zero-page sites",
        "8.6 Variants — sidebar",
        "9. Static-Recompilation Hazards (DEEP)",
        "9.1 Self-modifying code",
        "9.2 PC-relative idioms defeating recursive descent",
        "9.3 The `.byte $2C` / `.byte $24` skip trick",
        "9.4 Cycle-counting taxonomy",
        "9.5 What breaks if WSYNC/VSYNC are faked",
        "9.6 Other landmines",
        "10. Recommended Runtime Checklist",
        "10.1 Minimum side-effect-accurate register set",
        "10.2 Common false-GREEN failure modes",
        "10.3 Per-game smoke-test invariants",
        "10.4 Suggested milestone gates"
      ]
    },
    {
      "slug": "intellivision",
      "name": "Intellivision",
      "year": "1979",
      "state": "published",
      "programState": "research-ready",
      "externalReferences": "linked",
      "systemUrl": "/reforge/consoles/intellivision/",
      "publicDossierUrl": "/reforge/research/intellivision/",
      "outline": [
        "CPU Architecture — CP1610",
        "STIC (Graphics)",
        "Memory Map",
        "I/O & Controllers",
        "Recompilation Notes"
      ]
    },
    {
      "slug": "colecovision",
      "name": "ColecoVision",
      "year": "1982",
      "state": "published",
      "programState": "research-ready",
      "externalReferences": "linked",
      "systemUrl": "/reforge/consoles/colecovision/",
      "publicDossierUrl": "/reforge/research/colecovision/",
      "outline": [
        "CPU Architecture — Z80A",
        "VDP — TMS9928A",
        "Memory Map",
        "Audio — SN76489",
        "BIOS",
        "I/O & Controllers",
        "Recompilation Notes"
      ]
    },
    {
      "slug": "nes",
      "name": "NES",
      "year": "1983",
      "state": "queued",
      "programState": "research-not-started",
      "externalReferences": "linked",
      "systemUrl": "/reforge/consoles/nes/",
      "publicDossierUrl": null,
      "outline": []
    },
    {
      "slug": "sms",
      "name": "Sega Master System",
      "year": "1985",
      "state": "published",
      "programState": "research-ready",
      "externalReferences": "linked",
      "systemUrl": "/reforge/consoles/sms/",
      "publicDossierUrl": "/reforge/research/sms/",
      "outline": [
        "1. CPU architecture — Z80 at 3.579545 MHz",
        "Registers and flag layout",
        "Addressing modes",
        "Instruction set with T-state counts",
        "Undocumented instructions relevant to SMS emulation",
        "SMS-specific interrupt behavior",
        "Clock timing",
        "2. VDP — Sega 315-5124 (Mode 4, sprites, scrolling, line interrupt)",
        "What changed from the TMS9928A",
        "Mode 4 tile format and VRAM layout",
        "Scrolling mechanics",
        "Sprite system",
        "VDP registers R0–R10",
        "VDP control port protocol",
        "Status register (read $BF)",
        "Scanline interrupt (line counter)",
        "Frame timing",
        "Legacy TMS9928 modes",
        "3. Memory map — complete address space and I/O ports",
        "Z80 address space",
        "I/O port map",
        "Port $3E — Memory control (write only)",
        "Port $3F — I/O port control (write only)",
        "4. Audio — SN76489 PSG + YM2413 OPLL",
        "SN76489 PSG — 3 squares + 1 noise",
        "YM2413 OPLL — 9-channel FM synthesis",
        "FM detection and PSG/FM switching",
        "5. Bank switching — Sega, Codemasters, and Korean mappers",
        "Sega mapper (standard, ~99% of games)",
        "Codemasters mapper",
        "Korean mapper variants",
        "Mapper identification",
        "6. I/O and controllers — D-pad, buttons, Pause NMI, Light Phaser",
        "Standard controller reading",
        "Pause button",
        "Light Phaser protocol",
        "Paddle and Sports Pad",
        "7. Recompilation notes — critical quirks for REFORGE",
        "VDP command word timing",
        "Sprite overflow flag and collision",
        "Line interrupt internal counter",
        "Vertical scroll wrap at 224",
        "VDP data port read-ahead buffer",
        "The first 1 KB protection and recompilation implications",
        "EI delay and interrupt acceptance",
        "VDP status register read side effects",
        "Scanline-accurate VDP rendering",
        "Bank switch detection in recompiled code"
      ]
    },
    {
      "slug": "genesis",
      "name": "Sega Genesis / Mega Drive",
      "year": "1988",
      "state": "published",
      "programState": "research-ready",
      "externalReferences": "linked",
      "systemUrl": "/reforge/consoles/genesis/",
      "publicDossierUrl": "/reforge/research/genesis/",
      "outline": [
        "CPU Architecture — Motorola 68000",
        "VDP — Sega 315-5313",
        "Audio — YM2612 + SN76489",
        "Memory Map",
        "I/O & Controllers",
        "Recompilation Notes"
      ]
    },
    {
      "slug": "gb",
      "name": "Game Boy / Game Boy Color",
      "year": "1989",
      "state": "published",
      "programState": "current",
      "externalReferences": "linked",
      "systemUrl": "/reforge/consoles/gb/",
      "publicDossierUrl": "/reforge/research/gb/",
      "outline": [
        "CPU — Sharp LR35902 (SM83)",
        "Architecture: neither Z80 nor 8080",
        "Register file",
        "Complete instruction set with cycle counts",
        "HALT, STOP, and the HALT bug",
        "Interrupt system",
        "PPU (Pixel Processing Unit)",
        "Tile format and data storage",
        "Background layer",
        "Window layer",
        "Sprites and OAM",
        "PPU modes and frame timing",
        "STAT register ($FF41) and interrupt behavior",
        "Pixel FIFO renderer",
        "LCDC register ($FF40)",
        "DMG palette registers",
        "OAM DMA ($FF46)",
        "GBC enhancements",
        "Double-speed CPU mode",
        "VRAM banking",
        "Color palettes",
        "HDMA (HBlank DMA)",
        "WRAM banking",
        "DMG compatibility mode",
        "Complete memory map",
        "Complete I/O register map ($FF00–$FF7F)",
        "Memory Bank Controllers",
        "MBC1 (up to 2 MB ROM, 32 KB RAM)",
        "MBC2 (up to 256 KB ROM, 512×4-bit built-in RAM)",
        "MBC3 (up to 2 MB ROM, 32 KB RAM + RTC)",
        "MBC5 (up to 8 MB ROM, 128 KB RAM)",
        "MBC7 (accelerometer + EEPROM)",
        "ROM header ($0100–$014F)",
        "Audio — DMG APU",
        "Four channels and signal architecture",
        "Frame sequencer (DIV-APU)",
        "Frequency and period formulas",
        "Sweep unit (CH1 only)",
        "Volume envelope",
        "Noise channel LFSR",
        "Channel trigger behavior (NRx4 bit 7 = 1)",
        "Audio register read masks",
        "Timer system",
        "Registers and the 16-bit internal counter",
        "Timer overflow with 1 M-cycle delay",
        "DIV-related timing obscurities",
        "Joypad ($FF00)",
        "Boot ROM and initial register state",
        "DMG boot ROM (256 bytes)",
        "GBC boot ROM (2048 bytes)",
        "Hardware errata and recompilation edge cases",
        "OAM bug (DMG only)",
        "HALT bug",
        "Window internal line counter",
        "STAT interrupt blocking",
        "Wave RAM corruption (DMG only)",
        "Memory access restrictions",
        "Practical static recompilation considerations",
        "Conclusion"
      ]
    },
    {
      "slug": "snes",
      "name": "Super Nintendo / Super Famicom",
      "year": "1990",
      "state": "published",
      "programState": "research-ready",
      "externalReferences": "linked",
      "systemUrl": "/reforge/consoles/snes/",
      "publicDossierUrl": "/reforge/research/snes/",
      "outline": [
        "CPU Architecture — Ricoh 5A22 (65C816)",
        "PPU — S-PPU1/S-PPU2",
        "Audio — SPC700 + S-DSP",
        "Memory Map",
        "DMA & HDMA",
        "I/O & Controllers",
        "Recompilation Notes"
      ]
    },
    {
      "slug": "ps1",
      "name": "PlayStation 1",
      "year": "1994",
      "state": "published",
      "programState": "research-ready",
      "externalReferences": "linked",
      "systemUrl": "/reforge/consoles/ps1/",
      "publicDossierUrl": "/reforge/research/ps1/",
      "outline": [
        "CPU Architecture — MIPS R3000A",
        "GPU",
        "Memory Map",
        "DMA",
        "I/O & Controllers",
        "BIOS",
        "Recompilation Notes",
        "I/O Dispatch Reference (Iteration 10 Synthesis)",
        "GTE (COP2) — Geometry Transformation Engine",
        "DMA Controller ($1F801080–$1F8010F8)",
        "Root Counters / Timers ($1F801100–$1F801130)",
        "SPU ($1F801C00–$1F801E00) — 24 Voices",
        "CD-ROM Controller ($1F801800–$1F801803)",
        "MDEC ($1F801820–$1F801828)",
        "DICR ($1F8010F4) — DMA Interrupt Control Register",
        "Complete I/O Register Dispatch Table",
        "x86-64 Dispatch Handler Stubs",
        "Verification Notes"
      ]
    },
    {
      "slug": "saturn",
      "name": "Sega Saturn",
      "year": "1994",
      "state": "published",
      "programState": "research-ready",
      "externalReferences": "linked",
      "systemUrl": "/reforge/consoles/saturn/",
      "publicDossierUrl": "/reforge/research/saturn/",
      "outline": [
        "CPU Architecture — Dual SH-2",
        "VDP1 (Sprite/Polygon)",
        "VDP2 (Background/Scroll)",
        "Memory Map (Master SH-2)",
        "I/O & Controllers",
        "Recompilation Notes",
        "I/O Dispatch Reference (Iteration 9 Synthesis)",
        "VDP1 Registers ($05D00000 base)",
        "VDP2 Registers ($05F80000 base)",
        "SCU Registers ($25FE0000 base)",
        "SCSP Registers ($05B00000 base, Sound RAM at $05A00000)",
        "SMPC Registers ($00100001, odd bytes only)",
        "SCU DSP (32-bit VLIW, 14.3 MHz)",
        "Dual-CPU Coordination",
        "Timing Tables (Cycle-Accurate)",
        "Complete I/O Register Dispatch Table",
        "x86-64 Dispatch Handler Skeleton",
        "Verification Notes",
        "Iteration 7 Synthesis — SH-2 Internals, SCSP DSP Stack, SCU DSP Upload, MINIT Sync",
        "SH-2 Internal Peripheral Registers ($FFFFFE00 base, on-chip)",
        "SCSP DSP Data Registers ($05B00480+ base)",
        "SCU DSP Upload Registers ($25FE0080+ base)",
        "MINIT/SINIT — Inter-CPU Synchronization",
        "VDP2 Extended Registers (Iteration 7 Additions)",
        "Side Effects & Timing Summary (Iteration 7 Verified)",
        "C++ Reference Implementation (reforge_saturn_io.h)",
        "Updated Dispatch Table (Combined Iteration 9 + Iteration 7)"
      ]
    },
    {
      "slug": "n64",
      "name": "Nintendo 64",
      "year": "1996",
      "state": "published",
      "programState": "research-ready",
      "externalReferences": "linked",
      "systemUrl": "/reforge/consoles/n64/",
      "publicDossierUrl": "/reforge/research/n64/",
      "outline": [
        "CPU Architecture — VR4300 (MIPS III)",
        "RSP (Reality Signal Processor)",
        "RDP (Reality Display Processor)",
        "Audio",
        "Memory Architecture",
        "Memory Map",
        "I/O & Controllers",
        "Save Systems",
        "Boot Process",
        "Recompilation Notes"
      ]
    },
    {
      "slug": "dreamcast",
      "name": "Sega Dreamcast",
      "year": "1998",
      "state": "published",
      "programState": "research-ready",
      "externalReferences": "linked",
      "systemUrl": "/reforge/consoles/dreamcast/",
      "publicDossierUrl": "/reforge/research/dreamcast/",
      "outline": [
        "SH-4 CPU: instruction set, registers, and pipeline",
        "Register file",
        "Instruction set architecture",
        "Floating-point instructions (all new vs SH-2)",
        "Cache control and other SH-4 additions over SH-2",
        "Addressing modes",
        "Superscalar pipeline",
        "Memory-mapped control registers (P4 area, 0xFFxxxxxx)",
        "Exception handling",
        "PowerVR CLX2 (Holly): tile-based deferred rendering",
        "How TBDR works",
        "Three rendering lists",
        "Tile Accelerator parameter format",
        "Texture formats",
        "PVR core registers (base 0xA05F8000)",
        "8MB VRAM layout",
        "Yamaha AICA: 64-channel sound with ARM7DI core",
        "Architecture overview",
        "AICA registers from SH-4 (physical addresses in Area 0)",
        "Channel registers (64 channels × 0x80 bytes = 0x2000 bytes at offset 0x0000)",
        "Key system registers",
        "SH-4 ↔ ARM7 communication",
        "Memory architecture and address map",
        "Physical address space (29-bit, 8 × 64MB areas)",
        "Logical address regions (32-bit, SH-4 with MMU off)",
        "Bus architecture",
        "GD-ROM: proprietary disc format and controller",
        "GD-ROM registers (G1 bus, ATAPI-like)",
        "Boot sequence",
        "Maple bus: controller protocol and peripherals",
        "Protocol fundamentals",
        "Maple DMA registers",
        "Frame format",
        "Command codes",
        "Function codes (device capabilities)",
        "Controller data format (Get Condition response)",
        "VMU (Visual Memory Unit)",
        "Conclusion",
        "I/O Dispatch Reference (Final Synthesis)",
        "AICA Audio Registers (G2-bus, $00700000 base)",
        "GD-ROM Controller Registers (G1-bus, $A05F7000 base)",
        "Maple Bus DMA Registers ($A05F6C00 base)",
        "SH-4 DMAC + Store Queue",
        "PVR Tile Accelerator (TA) Parameter Format",
        "Additional Holly Registers ($A05F8000+)",
        "Complete I/O Register Dispatch Table",
        "Integration with Existing Pipeline",
        "Verification Notes",
        "I/O Dispatch Deepening (Maximum Depth Synthesis)",
        "AICA DSP — ARM7 Address Space + Upload Protocol",
        "GD-ROM — Full ATAPI Command Table + ASC/ASCQ Error Codes",
        "Maple Bus — Wire Protocol Timing + Response Parsing",
        "SH-4 DMAC — Channel Control Bits + DMA Contention Matrix",
        "PVR TA — Named Registers + Dual FIFO",
        "Holly/PVR Video Output — Timing Tables + Quad-Buffer Swap",
        "Expanded I/O Register Dispatch Table",
        "Cross-Subsystem DMA Coordination",
        "Additional Verification Notes (Maximum Depth)"
      ]
    },
    {
      "slug": "ps2",
      "name": "PlayStation 2",
      "year": "2000",
      "state": "queued",
      "programState": "research-not-started",
      "externalReferences": "linked",
      "systemUrl": "/reforge/consoles/ps2/",
      "publicDossierUrl": null,
      "outline": []
    },
    {
      "slug": "gba",
      "name": "Game Boy Advance",
      "year": "2001",
      "state": "published",
      "programState": "research-ready",
      "externalReferences": "linked",
      "systemUrl": "/reforge/consoles/gba/",
      "publicDossierUrl": "/reforge/research/gba/",
      "outline": [
        "ARM7TDMI core at 2²⁴ Hz",
        "Register file and processor modes",
        "ARM instruction set (32-bit)",
        "Data processing encoding",
        "Barrel shifter operations and special cases",
        "Multiply instructions",
        "Branch, load/store, block transfer",
        "Cycle timing summary",
        "THUMB instruction set (16-bit)",
        "Memory map and bus architecture",
        "WAITCNT register (`$4000204`, 16-bit R/W)",
        "Open bus behavior",
        "Internal memory control (`$4000800`, 32-bit R/W)",
        "Graphics subsystem",
        "DISPCNT — `$4000000` (16-bit R/W)",
        "Display modes",
        "DISPSTAT (`$4000004`) and VCOUNT (`$4000006`)",
        "BGxCNT — `$4000008`–`$400000E` (16-bit R/W per BG)",
        "BG scroll and affine registers",
        "VRAM layout (96 KB at `$06000000`)",
        "OAM and sprites (`$07000000`, 1 KB)",
        "Palette RAM (`$05000000`, 1 KB)",
        "Windowing",
        "Blending and special effects",
        "Mosaic (`$400004C`, write-only)",
        "Audio subsystem",
        "Legacy PSG channels (channels 1–4)",
        "DMA sound channels (Direct Sound A & B)",
        "Sound control registers",
        "Mixing pipeline",
        "Timer-DMA-audio chain",
        "4 timers at `$4000100`–`$400010E`",
        "The complete audio DMA chain",
        "DMA controller (4 channels)",
        "Register map",
        "Interrupt system",
        "Registers",
        "Interrupt dispatch flow",
        "BIOS SWI functions",
        "Cartridge and save system",
        "Save type detection",
        "Flash command protocol",
        "EEPROM protocol",
        "Static recompilation pitfalls for REFORGE",
        "I/O Dispatch Reference (Iteration 13 Synthesis)",
        "Complete Register Dispatch Table",
        "Sound FIFO Internal Details",
        "Internal Memory Control (`$4000800`) Deep Dive",
        "Flash 128KB Save System (Pokémon Emerald / FireRed / LeafGreen)",
        "x86-64 Dispatch Table Skeleton",
        "Verification Notes"
      ]
    },
    {
      "slug": "gamecube",
      "name": "Nintendo GameCube",
      "year": "2001",
      "state": "queued",
      "programState": "research-not-started",
      "externalReferences": "linked",
      "systemUrl": "/reforge/consoles/gamecube/",
      "publicDossierUrl": null,
      "outline": []
    },
    {
      "slug": "xbox",
      "name": "Microsoft Xbox",
      "year": "2001",
      "state": "queued",
      "programState": "research-not-started",
      "externalReferences": "linked",
      "systemUrl": "/reforge/consoles/xbox/",
      "publicDossierUrl": null,
      "outline": []
    },
    {
      "slug": "xbox360",
      "name": "Microsoft Xbox 360",
      "year": "2005",
      "state": "published",
      "programState": "research-ready",
      "externalReferences": "linked",
      "systemUrl": "/reforge/consoles/xbox360/",
      "publicDossierUrl": "/reforge/research/xbox360/",
      "outline": [
        "CPU: IBM Xenon at 3.2 GHz with in-order PowerPC cores",
        "PowerPC ISA: register file and encoding",
        "Thread synchronization primitives",
        "Xenon-specific extensions",
        "VMX128: 128 vector registers and custom SIMD instructions",
        "Encoding the 128-register file in 32-bit instructions",
        "Key VMX128-unique instructions not in standard AltiVec",
        "GPU: ATI Xenos at 500 MHz with unified shaders and eDRAM",
        "48 unified shader ALUs in 3 SIMD groups",
        "Shader microcode format",
        "10 MB eDRAM: the rendering backbone",
        "Tiled rendering is forced by eDRAM capacity",
        "Texture formats and specialized capabilities",
        "Command buffer and register interface",
        "Memory: 512 MB unified GDDR3 at 22.4 GB/s",
        "Memory map layout",
        "Audio: hardware XMA decode with CPU-based mixing",
        "Disc and controllers",
        "GDFX disc format",
        "Controller interface",
        "OS architecture, XEX format, and hypervisor security",
        "Two-layer kernel architecture",
        "XEX2 executable format",
        "Hypervisor security model",
        "Static recompilation: strategies and implementation guidance",
        "Byte order: swap on every load and store",
        "Condition register: explicit computation with lazy evaluation",
        "Link register: function mapping for static recompilation",
        "VMX128 to SSE/AVX: the register allocation wall",
        "Floating-point fidelity: require FMA3",
        "Atomics and memory barriers: x86 TSO simplifies everything",
        "Threading: pin 6 guest threads to host threads",
        "GPU emulation: the hardest problem",
        "Conclusion: what matters most for a recompiler"
      ]
    },
    {
      "slug": "ps3",
      "name": "PlayStation 3",
      "year": "2006",
      "state": "queued",
      "programState": "research-not-started",
      "externalReferences": "linked",
      "systemUrl": "/reforge/consoles/ps3/",
      "publicDossierUrl": null,
      "outline": []
    },
    {
      "slug": "wii",
      "name": "Nintendo Wii",
      "year": "2006",
      "state": "published",
      "programState": "research-ready",
      "externalReferences": "linked",
      "systemUrl": "/reforge/consoles/wii/",
      "publicDossierUrl": "/reforge/research/wii/",
      "outline": [
        "CPU: IBM Broadway at 729 MHz",
        "Broadway-specific register differences from Gekko",
        "Memory architecture: MEM1, MEM2, and the death of ARAM",
        "Physical memory map (PPC view)",
        "Comparison with GameCube",
        "MEM2 IOS reservation",
        "Global memory locations (MEM1 low area)",
        "GPU: ATI Hollywood at 243 MHz",
        "Pipeline architecture (inherited from Flipper)",
        "Hardware register bases",
        "eDRAM: 3 MB vs Flipper's 2 MB",
        "Video output",
        "Audio: Macronix DSP at 121.5 MHz",
        "DSP specifications",
        "Key DSP registers (base 0x0C005000)",
        "ARAM DMA registers (still present but non-functional on Wii)",
        "Audio Interface (AI) registers",
        "DSP-ADPCM format",
        "Disc format: proprietary DVD",
        "Partition structure",
        "Encryption",
        "Wii Remote: Bluetooth HID protocol and data formats",
        "Button bitmask (2 bytes, big-endian, present in all reports except 0x3d)",
        "Accelerometer: ADXL330",
        "IR camera: PixArt sensor",
        "Data reporting modes",
        "Speaker",
        "Rumble",
        "Extension controllers",
        "GameCube controller (SI protocol)",
        "IOS: the ARM Starlet security co-processor",
        "Hardware",
        "IPC mechanism (Broadway ↔ Starlet)",
        "Device nodes",
        "NAND flash",
        "GameCube backward compatibility",
        "Transition sequence",
        "State comparison",
        "What MIOS patches",
        "Limitations",
        "Implications for REFORGE static recompilation"
      ]
    }
  ],
  "proof": [
    {
      "console": "odyssey",
      "publicResult": "Circuit-level hardware dossier; no native-runtime result recorded",
      "gates": {
        "L0": "not-run",
        "L1": "not-run",
        "L2": "not-run",
        "L3": "not-run",
        "L4": "not-run",
        "L5": "not-run"
      },
      "systemUrl": "/reforge/consoles/odyssey/#verification"
    },
    {
      "console": "pong",
      "publicResult": "Circuit-level hardware dossier; no native-runtime result recorded",
      "gates": {
        "L0": "not-run",
        "L1": "not-run",
        "L2": "not-run",
        "L3": "not-run",
        "L4": "not-run",
        "L5": "not-run"
      },
      "systemUrl": "/reforge/consoles/pong/#verification"
    },
    {
      "console": "atari2600",
      "publicResult": "11-title public aggregate; title boundaries range from L2 to L4",
      "gates": {
        "L0": "functional",
        "L1": "functional",
        "L2": "functional",
        "L3": "in-review",
        "L4": "in-review",
        "L5": "not-run"
      },
      "systemUrl": "/reforge/consoles/atari2600/#verification"
    },
    {
      "console": "intellivision",
      "publicResult": "Hardware dossier published; native-runtime verification not started",
      "gates": {
        "L0": "not-run",
        "L1": "not-run",
        "L2": "not-run",
        "L3": "not-run",
        "L4": "not-run",
        "L5": "not-run"
      },
      "systemUrl": "/reforge/consoles/intellivision/#verification"
    },
    {
      "console": "colecovision",
      "publicResult": "Hardware dossier published; native-runtime verification not started",
      "gates": {
        "L0": "not-run",
        "L1": "not-run",
        "L2": "not-run",
        "L3": "not-run",
        "L4": "not-run",
        "L5": "not-run"
      },
      "systemUrl": "/reforge/consoles/colecovision/#verification"
    },
    {
      "console": "nes",
      "publicResult": "Research collection and native-runtime verification not started",
      "gates": {
        "L0": "not-run",
        "L1": "not-run",
        "L2": "not-run",
        "L3": "not-run",
        "L4": "not-run",
        "L5": "not-run"
      },
      "systemUrl": "/reforge/consoles/nes/#verification"
    },
    {
      "console": "sms",
      "publicResult": "Hardware dossier published; native-runtime verification not started",
      "gates": {
        "L0": "not-run",
        "L1": "not-run",
        "L2": "not-run",
        "L3": "not-run",
        "L4": "not-run",
        "L5": "not-run"
      },
      "systemUrl": "/reforge/consoles/sms/#verification"
    },
    {
      "console": "genesis",
      "publicResult": "Hardware dossier published; native-runtime verification not started",
      "gates": {
        "L0": "not-run",
        "L1": "not-run",
        "L2": "not-run",
        "L3": "not-run",
        "L4": "not-run",
        "L5": "not-run"
      },
      "systemUrl": "/reforge/consoles/genesis/#verification"
    },
    {
      "console": "gb",
      "publicResult": "Native build and 1,800-frame liveness recorded; title-level verification not claimed",
      "gates": {
        "L0": "functional",
        "L1": "functional",
        "L2": "not-run",
        "L3": "not-run",
        "L4": "not-run",
        "L5": "not-run"
      },
      "systemUrl": "/reforge/consoles/gb/#verification"
    },
    {
      "console": "snes",
      "publicResult": "Hardware dossier published; native-runtime verification not started",
      "gates": {
        "L0": "not-run",
        "L1": "not-run",
        "L2": "not-run",
        "L3": "not-run",
        "L4": "not-run",
        "L5": "not-run"
      },
      "systemUrl": "/reforge/consoles/snes/#verification"
    },
    {
      "console": "ps1",
      "publicResult": "Hardware dossier published; native-runtime verification not started",
      "gates": {
        "L0": "not-run",
        "L1": "not-run",
        "L2": "not-run",
        "L3": "not-run",
        "L4": "not-run",
        "L5": "not-run"
      },
      "systemUrl": "/reforge/consoles/ps1/#verification"
    },
    {
      "console": "saturn",
      "publicResult": "Hardware dossier published; native-runtime verification not started",
      "gates": {
        "L0": "not-run",
        "L1": "not-run",
        "L2": "not-run",
        "L3": "not-run",
        "L4": "not-run",
        "L5": "not-run"
      },
      "systemUrl": "/reforge/consoles/saturn/#verification"
    },
    {
      "console": "n64",
      "publicResult": "Hardware dossier published; native-runtime verification not started",
      "gates": {
        "L0": "not-run",
        "L1": "not-run",
        "L2": "not-run",
        "L3": "not-run",
        "L4": "not-run",
        "L5": "not-run"
      },
      "systemUrl": "/reforge/consoles/n64/#verification"
    },
    {
      "console": "dreamcast",
      "publicResult": "Hardware dossier published; native-runtime verification not started",
      "gates": {
        "L0": "not-run",
        "L1": "not-run",
        "L2": "not-run",
        "L3": "not-run",
        "L4": "not-run",
        "L5": "not-run"
      },
      "systemUrl": "/reforge/consoles/dreamcast/#verification"
    },
    {
      "console": "ps2",
      "publicResult": "Research collection and native-runtime verification not started",
      "gates": {
        "L0": "not-run",
        "L1": "not-run",
        "L2": "not-run",
        "L3": "not-run",
        "L4": "not-run",
        "L5": "not-run"
      },
      "systemUrl": "/reforge/consoles/ps2/#verification"
    },
    {
      "console": "gba",
      "publicResult": "Hardware dossier published; native-runtime verification not started",
      "gates": {
        "L0": "not-run",
        "L1": "not-run",
        "L2": "not-run",
        "L3": "not-run",
        "L4": "not-run",
        "L5": "not-run"
      },
      "systemUrl": "/reforge/consoles/gba/#verification"
    },
    {
      "console": "gamecube",
      "publicResult": "Research collection and native-runtime verification not started",
      "gates": {
        "L0": "not-run",
        "L1": "not-run",
        "L2": "not-run",
        "L3": "not-run",
        "L4": "not-run",
        "L5": "not-run"
      },
      "systemUrl": "/reforge/consoles/gamecube/#verification"
    },
    {
      "console": "xbox",
      "publicResult": "Research collection and native-runtime verification not started",
      "gates": {
        "L0": "not-run",
        "L1": "not-run",
        "L2": "not-run",
        "L3": "not-run",
        "L4": "not-run",
        "L5": "not-run"
      },
      "systemUrl": "/reforge/consoles/xbox/#verification"
    },
    {
      "console": "xbox360",
      "publicResult": "Hardware dossier published; native-runtime verification not started",
      "gates": {
        "L0": "not-run",
        "L1": "not-run",
        "L2": "not-run",
        "L3": "not-run",
        "L4": "not-run",
        "L5": "not-run"
      },
      "systemUrl": "/reforge/consoles/xbox360/#verification"
    },
    {
      "console": "ps3",
      "publicResult": "Research collection and native-runtime verification not started",
      "gates": {
        "L0": "not-run",
        "L1": "not-run",
        "L2": "not-run",
        "L3": "not-run",
        "L4": "not-run",
        "L5": "not-run"
      },
      "systemUrl": "/reforge/consoles/ps3/#verification"
    },
    {
      "console": "wii",
      "publicResult": "Hardware dossier published; native-runtime verification not started",
      "gates": {
        "L0": "not-run",
        "L1": "not-run",
        "L2": "not-run",
        "L3": "not-run",
        "L4": "not-run",
        "L5": "not-run"
      },
      "systemUrl": "/reforge/consoles/wii/#verification"
    }
  ],
  "findings": [
    {
      "id": "atari2600-f182",
      "number": "182",
      "console": "atari2600",
      "title": "YARS' REVENGE ONBOARDED; MID-SCANLINE PLAYFIELD REPLAY RESTORES THE NEUTRAL ZONE",
      "summary": "Yars' Revenge exposed the playfield half of Finding 181's deferred work. The first native build was live and interactive, but visual evidence alternated between a full-width chevron-like shield and an almost empty frame.",
      "state": "confirmed",
      "category": "Timing / bus",
      "publicUrl": "/reforge/findings/atari2600-f182-yars-revenge-onboarded-mid-scanline-playfield-replay-restores-the-neutral-zone/",
      "publicSource": "/reforge/research/atari2600/#finding-182"
    },
    {
      "id": "atari2600-f181",
      "number": "181",
      "console": "atari2600",
      "title": "CLASS A LANDED: MID-SCANLINE GRP/COLUP REPLAY IN THE SCANLINE RENDERER",
      "summary": "THE DEFECT (Verdict-6 dominant visual class, 5+ ROMs): the 48px/6-digit score kernel sets NUSIZx=3-copies-close and rewrites GRPx between copies so each 8px copy shows a different digit. Our renderer drew each line from ONE end-of-line snapshot state — all three copies rendered the same bytes (\"three sets of scores that are just one\").",
      "state": "confirmed",
      "category": "Evidence",
      "publicUrl": "/reforge/findings/atari2600-f181-class-a-landed-mid-scanline-grp-colup-replay-in-the-scanline-renderer/",
      "publicSource": "/reforge/research/atari2600/#finding-181"
    },
    {
      "id": "atari2600-f180",
      "number": "180",
      "console": "atari2600",
      "title": "CLASS C ASPECT FIX: ATARI WINDOW NOW PRESENTS 2× HORIZONTAL PIXEL ASPECT (Verdict-6 \"squished left-right\", universal)",
      "summary": "A TIA color clock is ~2 scanline-height units wide; square-pixel presentation rendered every title tall-and-narrow (owner verdict 6 on Adventure, true corpus-wide; the old code's width*4 WINDOW with width-logical content just pillarboxed square pixels). Fix in the Atari `ppu_init` (ppu_c.py): `SDL_RenderSetLogicalSize(2*width, height)` with window `(2*width*3, height*3)` — the 160-wide TIA framebuffer texture is stretched horizontally by RenderCopy;…",
      "state": "active",
      "category": "Video",
      "publicUrl": "/reforge/findings/atari2600-f180-class-c-aspect-fix-atari-window-now-presents-2-horizontal-pixel-aspect-verdict-6-squishe/",
      "publicSource": "/reforge/research/atari2600/#finding-180"
    },
    {
      "id": "atari2600-f179",
      "number": "179",
      "console": "atari2600",
      "title": "COMBAT FRAME-0 DEATH ROOT-CAUSED AND FIXED",
      "summary": "SYMPTOM: fresh builds of Combat die before frame 1 completes — [DISPATCH] t=0x1CC8 → (cache-dependent) [DISPATCH-MISS] or phantom sub_001CC8 execution → dispatch t=0x0001 → OUTER-LOOP-NATURAL-EXIT, 0/1800 frames. June-12 fresh corpus had Combat L2/1800f; every corpus \"refresh\" since classified from stale artifacts (F178), so the break stayed invisible until the first honest rebuild.",
      "state": "confirmed",
      "category": "Evidence",
      "publicUrl": "/reforge/findings/atari2600-f179-combat-frame-0-death-root-caused-and-fixed/",
      "publicSource": "/reforge/research/atari2600/#finding-179"
    },
    {
      "id": "atari2600-f178",
      "number": "178",
      "console": "atari2600",
      "title": "EVIDENCE-PIPELINE DEFECT (F102 CLASS)",
      "summary": "MECHANISM: prove_loop's template-regen step (09ag-10 lineage) constructs its CEmitter with only console_id/architecture/screen dims. The platform.c template emits the headless stats call only when `\"ppu_collect_stats\" in self._ppu_source` — with ppu_source empty, every regen emitted the no-hook stub.",
      "state": "active",
      "category": "Evidence",
      "publicUrl": "/reforge/findings/atari2600-f178-evidence-pipeline-defect-f102-class/",
      "publicSource": "/reforge/research/atari2600/#finding-178"
    },
    {
      "id": "atari2600-f177",
      "number": "177",
      "console": "atari2600",
      "title": "JSR PUSHED THE CANONICALIZED PAGE BYTE ($1A), NOT THE CPU'S LOGICAL 6502 PAGE ($FA)",
      "summary": "MECHANISM: `emitter_c.py _emit_call` computed `push_val = insn.source_address + 2` from the lifter's canonicalized/banked address. A JSR physically at $FA1D is canonicalized to $1A1D, so we pushed hi byte $1A where real hardware pushes the logical 16-bit page $FA.",
      "state": "active",
      "category": "Evidence",
      "publicUrl": "/reforge/findings/atari2600-f177-jsr-pushed-the-canonicalized-page-byte-1a-not-the-cpu-s-logical-6502-page-fa/",
      "publicSource": "/reforge/research/atari2600/#finding-177"
    },
    {
      "id": "atari2600-f176",
      "number": "176",
      "console": "atari2600",
      "title": "REFERENCE-TRACE INSTRUMENT PART (a) LANDED",
      "summary": "WHAT LANDED: (1) emitter_c.py `reforge_debug_frame` (the all-console per-frame debug hook, active when reforge_debug_active — any --watch flag) now emits `[ZP] f=N ` + 512 hex chars = the first 256 bytes of cpu->memory, the SAME window the frame CRC hashes — so a CRC mismatch between runs can immediately be decomposed into the exact cells. One line per frame, debug runs only, zero release-build cost.",
      "state": "confirmed",
      "category": "Evidence",
      "publicUrl": "/reforge/findings/atari2600-f176-reference-trace-instrument-part-a-landed/",
      "publicSource": "/reforge/research/atari2600/#finding-176"
    },
    {
      "id": "atari2600-f175",
      "number": "175",
      "console": "atari2600",
      "title": "TRAJECTORY VERIFIED CONSISTENT",
      "summary": "This record documents the conclusion: TRAJECTORY VERIFIED CONSISTENT; SINGLE-CELL DIFFERENTIAL TOOLKIT EXHAUSTED. The $95 fine-pos evolves in clean -$10 steps ($FA9A wrap store, every 7th odd frame) punctuated by $FDE3/$FDE7 rewrites — which identifies F134's RAM-shift loop as OBJECT-LIST COMPACTION. Every observable cell feeding the deadlock is now either verified-faithful code or self-consistent data; the remaining instrument is a REFERENCE TRACE. Spec…",
      "state": "confirmed",
      "category": "Evidence",
      "publicUrl": "/reforge/findings/atari2600-f175-trajectory-verified-consistent/",
      "publicSource": "/reforge/research/atari2600/#finding-175"
    },
    {
      "id": "atari2600-f174",
      "number": "174",
      "console": "atari2600",
      "title": "RIOT I/O MIRROR READ DECODE FIXED",
      "summary": "Even frames instead write E7=$DF@$F838 (ROM shape page) — the two flicker programs use the SAME cells with different meanings. A4 participates only in timer WRITES ($294-$297).",
      "state": "confirmed",
      "category": "CPU",
      "publicUrl": "/reforge/findings/atari2600-f174-riot-i-o-mirror-read-decode-fixed/",
      "publicSource": "/reforge/research/atari2600/#finding-174"
    },
    {
      "id": "atari2600-f173",
      "number": "173",
      "console": "atari2600",
      "title": "TWO-STREAM KERNEL DECODED (F171's page-cursor model corrected)",
      "summary": "Exit $11422: LDX #$1F / TXS (SP → TIA ENABL $1F — the per-scanline stack-blit re-arm; the $1C variant lives at the $11313 site) / TAX / INY (SCANLINE ADVANCE) / CPY #89 (band wrap). So the scanline structure is: [stream-A read/advance-or-repeat] → [draw A] → [stream-B read/advance-or-repeat] → [blit re-arm] → INY → CPY #89 → next line.",
      "state": "disproven",
      "category": "Timing / bus",
      "publicUrl": "/reforge/findings/atari2600-f173-two-stream-kernel-decoded-f171-s-page-cursor-model-corrected/",
      "publicSource": "/reforge/research/atari2600/#finding-173"
    },
    {
      "id": "atari2600-f172",
      "number": "172",
      "console": "atari2600",
      "title": "THE SPIN LOOP DECODED: it is the asteroid SHAPE-STREAM draw loop, and the deadlock is a stream/scanline DESYNC",
      "summary": "bank1[$0F09]=$88 ≠ bank0's $FF: the bank-aware read is FAITHFUL (bank 0 active, bank 0 byte served — F133 re-confirmed at the exact deadlock address).",
      "state": "confirmed",
      "category": "Timing / bus",
      "publicUrl": "/reforge/findings/atari2600-f172-the-spin-loop-decoded-it-is-the-asteroid-shape-stream-draw-loop-and-the-deadlock-is-a-st/",
      "publicSource": "/reforge/research/atari2600/#finding-172"
    },
    {
      "id": "atari2600-f171",
      "number": "171",
      "console": "atari2600",
      "title": "F170's CAUSALITY INVERTED: the DC/DD rebuild runs at frame END (after kernel exit)",
      "summary": "This record documents the conclusion: F170's CAUSALITY INVERTED: the DC/DD rebuild runs at frame END (after kernel exit) — its absence on the death frame is a CONSEQUENCE of the spin, not its cause; the walk ALWAYS runs with DC=$00/DD=$09. The merged five-cell tape gives the complete intra-frame program, and the true differential is the OBJECT'S BAND VALUE: bands 14/13/12 render fine, band 11 — the top-zone boundary — kills the walk at cursor step $D4.…",
      "state": "confirmed",
      "category": "Timing / bus",
      "publicUrl": "/reforge/findings/atari2600-f171-f170-s-causality-inverted-the-dc-dd-rebuild-runs-at-frame-end-after-kernel-exit/",
      "publicSource": "/reforge/research/atari2600/#finding-171"
    },
    {
      "id": "atari2600-f170",
      "number": "170",
      "console": "atari2600",
      "title": "THE FREEZE MECHANISM, FULLY EVIDENCED",
      "summary": "THE TELL: at f=666 the rebuild ran; at f=667 the reset ran ($F5CE/$F5D2) but the REBUILD NEVER FIRED — and from f=668 NOTHING writes DC/DD again (the kernel never yields back to logic). [STUCK-STATE] DC=$00/DD=$09 = the reset values, frozen.",
      "state": "active",
      "category": "Evidence",
      "publicUrl": "/reforge/findings/atari2600-f170-the-freeze-mechanism-fully-evidenced/",
      "publicSource": "/reforge/research/atari2600/#finding-170"
    },
    {
      "id": "atari2600-f169",
      "number": "169",
      "console": "atari2600",
      "title": "F168 REFUTED twice over: SP=$1C is Asteroids' stack-on-TIA blit kernel (TXS), not corruption",
      "summary": "CAPABILITY LANDED (all-console pattern, atari2600-gated where noted): the emitter now accumulates every masked target routed through a deferred-dispatch emission — the F158 unresolved-branch path AND the F47 trampoline fallback — in `CEmitter.deferred_targets`; after `emit_project` the engine unions the set into `dispatch_miss_cache.txt` (same `[DISPATCH-MISS] target=0x%04X (cached)` format the Findings-51/52 feedback loop parses).",
      "state": "disproven",
      "category": "CPU",
      "publicUrl": "/reforge/findings/atari2600-f169-f168-refuted-twice-over-sp-1c-is-asteroids-stack-on-tia-blit-kernel-txs-not-corruption/",
      "publicSource": "/reforge/research/atari2600/#finding-169"
    },
    {
      "id": "atari2600-f168",
      "number": "168",
      "console": "atari2600",
      "title": "FREEZE ROOT CAUSE FOUND: a RUNAWAY JSR CYCLE at f=668 pushes ~113 orphaned stack frames IN ONE FRAME (SP $FF→$1C)…",
      "summary": "CAPABILITY LANDED: the platform-template STUCK detector now emits `[STUCK-STATE] f a x y sp last_addr last_func mem 83 84 8C DC DD E5 E6 EA C8` to stderr before exit(2) — a STUCK verdict now carries its own forensic snapshot (F158 diagnostics pattern; cells chosen for the Asteroids band loop but harmless everywhere). MECHANISM (fits every prior observation): the ship-death path enters, for the first time, a loop whose JSR'd helper hits an F158 deferred…",
      "state": "active",
      "category": "CPU",
      "publicUrl": "/reforge/findings/atari2600-f168-freeze-root-cause-found-a-runaway-jsr-cycle-at-f-668-pushes-113-orphaned-stack-frames-in/",
      "publicSource": "/reforge/research/atari2600/#finding-168"
    },
    {
      "id": "atari2600-f167",
      "number": "167",
      "console": "atari2600",
      "title": "GOAL AC#3 BANKED: F8 bank-switch regions added to the runtime memory map (runtime/memory_map.py",
      "summary": "The atari2600 map (`_atari2600_memory_map`) previously modeled the cart as a flat 4KB ROM region with a passing mention of bank schemes. Added per Findings A2600-F34/F36/F159 with citations inline: (1) `f8_hotspots` MemoryRegion $1FF8-$1FFA, MemoryRegionType.IO, readable AND writable — on F8 hardware ANY access (LDA/BIT/data fetch or store) to $1FF8 selects bank 0 and $1FF9 selects bank 1; the cells still return ROM bytes on read; mirrors at every 8KB…",
      "state": "active",
      "category": "Evidence",
      "publicUrl": "/reforge/findings/atari2600-f167-goal-ac-3-banked-f8-bank-switch-regions-added-to-the-runtime-memory-map-runtime-memory-m/",
      "publicSource": "/reforge/research/atari2600/#finding-167"
    },
    {
      "id": "atari2600-f166",
      "number": "166",
      "console": "atari2600",
      "title": "VECTOR SELECTOR DECODED ($111E9-$11200)",
      "summary": "Then `LDA #0 / INY / CPY #89 / BEQ $11218` (band-loop wrap at 89) `/ TAX / JMP $11005` (next band). MODEL CORRECTION (F151/F163 revised): the $83+i array holds BAND POSITIONS (vertical Y-coordinates in kernel bands 0-88), not lifetime ages — new entries spawn at #$59=89 (just past the wrap = entering from the bottom edge), and the per-two-frame DEC at $F424 moves the object up one band.",
      "state": "active",
      "category": "Memory / cartridge",
      "publicUrl": "/reforge/findings/atari2600-f166-vector-selector-decoded-111e9-11200/",
      "publicSource": "/reforge/research/atari2600/#finding-166"
    },
    {
      "id": "atari2600-f165",
      "number": "165",
      "console": "atari2600",
      "title": "F164 MODEL CORRECTED: the freeze is a JMP ($E5) KERNEL SELF-CYCLE, not an in-function spin",
      "summary": "CORRECTED FREEZE MODEL: from f=668 the dispatch chain still cycles — kernel → JMP ($E5) → kernel — but the selector never matches (TYA's band value vs $83+X ages), so neither the renderer nor the logic segment ever runs again: empty world AND frozen ager are the same symptom. THE DEADLOCK: the ages that would satisfy the match are advanced by the ager, which lives behind the match.",
      "state": "disproven",
      "category": "CPU",
      "publicUrl": "/reforge/findings/atari2600-f165-f164-model-corrected-the-freeze-is-a-jmp-e5-kernel-self-cycle-not-an-in-function-spin/",
      "publicSource": "/reforge/research/atari2600/#finding-165"
    },
    {
      "id": "atari2600-f164",
      "number": "164",
      "console": "atari2600",
      "title": "THE FREEZE IS AN INFINITE LIST-SCAN LOOP, NOT A DISPATCH CYCLE",
      "summary": "CORRECTED MODEL: the \"display loop\" of F162/F163 is not a degenerate dispatch cycle — the CPU is stuck inside ONE C function (sub_0110C0, the same function iter-34's non-TAS natural-exit implicated) in a goto-only infinite loop; frames keep advancing solely because io_tick inside the spinning loop drives the frame clock, and the TIA snapshot state (olive bk, no objects) is whatever the last full frame left behind.",
      "state": "active",
      "category": "CPU",
      "publicUrl": "/reforge/findings/atari2600-f164-the-freeze-is-an-infinite-list-scan-loop-not-a-dispatch-cycle/",
      "publicSource": "/reforge/research/atari2600/#finding-164"
    },
    {
      "id": "atari2600-f163",
      "number": "163",
      "console": "atari2600",
      "title": "prove_loop `--watch` passthrough landed (first TAS+watch capture) and the DEATH SEQUENCE IS ON TAPE",
      "summary": "CAPABILITY: prove_loop.py now accepts repeatable `--watch ADDR,MODE` and forwards them to the exe run — watch evidence under TAS replay, previously impossible (prove_loop.py is not in _HASH_INPUTS, so no regen invalidation). INTERPRETATION: $83 counting $0F→$0B looks like a death/expiry timer; at the $0B transition a state change fires whose post-transition dispatch path loops display-only — the logic re-entry (overscan logic segment of the frame chain)…",
      "state": "confirmed",
      "category": "CPU",
      "publicUrl": "/reforge/findings/atari2600-f163-prove-loop-watch-passthrough-landed-first-tas-watch-capture-and-the-death-sequence-is-on/",
      "publicSource": "/reforge/research/atari2600/#finding-163"
    },
    {
      "id": "atari2600-f162",
      "number": "162",
      "console": "atari2600",
      "title": "TAS-freeze content identified",
      "summary": "Combined with iter-34's logic-stall signature (LFSR churn ceases) and the alive bank-switch counter: the display loop cycles bank-0 kernel frames forever while the bank-1 logic that populates the object list and sprite data never runs again (or runs but produces an empty world). The shape matches the F151-class object-list death, now triggered in the TAS timeline around f≈668 — TAS inputs (rotation/thrust/fire) plausibly get the ship killed near a wave…",
      "state": "active",
      "category": "Timing / bus",
      "publicUrl": "/reforge/findings/atari2600-f162-tas-freeze-content-identified/",
      "publicSource": "/reforge/research/atari2600/#finding-162"
    },
    {
      "id": "atari2600-f161",
      "number": "161",
      "console": "atari2600",
      "title": "THIRD DISPLAY KERNEL DISCOVERED AND ROOTED ($x10B, vector-swapped at $111EF)",
      "summary": "Notable: after the swap ALL logic activity ceased in the watch stream — the LFSR churn (ROL $82 at $FAE9, ~2 writes/frame) stopped — the logic loop stalls when the display chain dies. CORRECTION RECORDED: in Asteroids $82 is an LFSR cell (sub_00FAE2's ROL chain), NOT a game-state variable — do not reuse Pac-Man's RAM map labels.",
      "state": "active",
      "category": "Input / mechanics",
      "publicUrl": "/reforge/findings/atari2600-f161-third-display-kernel-discovered-and-rooted-x10b-vector-swapped-at-111ef/",
      "publicSource": "/reforge/research/atari2600/#finding-161"
    },
    {
      "id": "atari2600-f160",
      "number": "160",
      "console": "atari2600",
      "title": "GAMEPLAY KERNEL RUNS: FIRST-EVER ASTEROIDS GAMEPLAY VISUAL",
      "summary": "THE DROP MECHANISM (closes the F159 question): engine.py's CFG-seed block correctly forwarded 0x115C/0x1115C (both decoded), but cfg.py's Finding-74 misaligned-leader filter removed 0x1115C from the leader set because it falls inside another decoded instruction's byte range — built before the F8 alias stitch existed, F74 assumed interior-ness is absolute; with deliberately-overlapping alias streams an address can be interior to one alignment AND a…",
      "state": "confirmed",
      "category": "Video",
      "publicUrl": "/reforge/findings/atari2600-f160-gameplay-kernel-runs-first-ever-asteroids-gameplay-visual/",
      "publicSource": "/reforge/research/atari2600/#finding-160"
    },
    {
      "id": "atari2600-f159",
      "number": "159",
      "console": "atari2600",
      "title": "F8 READ-PATH bank switching landed (any access to $1FF8/$1FF9 now flips the bank, matching hardware",
      "summary": "Two changes landed (emitter_c.py): (1) HARDWARE-CORRECTNESS — `addr_map_read` now flips `reforge_active_bank` on ANY read of $1FF8/$1FF9 (LDA/BIT/data fetches), where Finding 36 had implemented only the write path; the bank flips before the byte fetch so the returned byte comes from the newly selected bank. Affects only F8 ROMs (rom_size > 0x1000); Asteroids is the corpus' only F8 cart.",
      "state": "confirmed",
      "category": "Evidence",
      "publicUrl": "/reforge/findings/atari2600-f159-f8-read-path-bank-switching-landed-any-access-to-1ff8-1ff9-now-flips-the-bank-matching-h/",
      "publicSource": "/reforge/research/atari2600/#finding-159"
    },
    {
      "id": "atari2600-f158",
      "number": "158",
      "console": "atari2600",
      "title": "DYING INSTRUCTION PINPOINTED AND FIXED",
      "summary": "The emitted code at $11155 was `if (cond) {{ /* branch to unresolved bb_01115C */ return; }}` — THE DEFECT CLASS: `_emit_branch` (emitter_c.py ~1415) emitted a bare `return;` for any taken branch whose target block wasn't decoded, ending the outer dispatch chain silently AND leaking reforge_call_depth (the depth=1 fingerprint). FIX: on atari2600, an unresolved conditional branch now emits `cpu->trampoline_target = (target & 0x1FFF); reforge_call_depth--;…",
      "state": "active",
      "category": "CPU",
      "publicUrl": "/reforge/findings/atari2600-f158-dying-instruction-pinpointed-and-fixed/",
      "publicSource": "/reforge/research/atari2600/#finding-158"
    },
    {
      "id": "atari2600-f157",
      "number": "157",
      "console": "atari2600",
      "title": "CORRECTION: the dispatch-miss feedback loop ALREADY EXISTS (engine.py, Findings 51/52) and it WORKED",
      "summary": "One prove cycle after F156, the regen rooted $145 in BOTH banks: `case 0x1145: if (reforge_active_bank == 0) sub_011145(cpu); else sub_001145(cpu);`. The new run produces NO DISPATCH-MISS — the kernel dispatch happens — but STILL exits at f=313 with `[OUTER-LOOP-NATURAL-EXIT] last_dispatched=0x1145`.",
      "state": "active",
      "category": "CPU",
      "publicUrl": "/reforge/findings/atari2600-f157-correction-the-dispatch-miss-feedback-loop-already-exists-engine-py-findings-51-52-and-i/",
      "publicSource": "/reforge/research/atari2600/#finding-157"
    },
    {
      "id": "atari2600-f156",
      "number": "156",
      "console": "atari2600",
      "title": "The f=313 exit is a DISPATCH-MISS on the GAMEPLAY DISPLAY KERNEL",
      "summary": "Evidence chain: (1) F154's fix is confirmed in the regenerated code (the 13 `DEC $0285,X` sites now emit `(0x0285 + cpu->x)` unmasked). The dispatcher (game_main.c ~line 1130-1495) is a static switch over lifter-rooted 13-bit entries with `reforge_active_bank` disambiguation for dual-rooted offsets; 0x1145 has no case, and the default miss handler logs + counts but does NOT set trampoline_target, so the outer loop ends (it also force-stops after 200 total…",
      "state": "active",
      "category": "CPU",
      "publicUrl": "/reforge/findings/atari2600-f156-the-f-313-exit-is-a-dispatch-miss-on-the-gameplay-display-kernel/",
      "publicSource": "/reforge/research/atari2600/#finding-156"
    },
    {
      "id": "atari2600-f155",
      "number": "155",
      "console": "atari2600",
      "title": "Analyzer run-length floor landed",
      "summary": "The F154 caveat (analyze_log false-GREENed Asteroids' 313-of-1800-frame run) is closed. `GenericExitCheck` in analyze_log.py — generic, runs for every console — now parses both `REFORGE: headless mode -- N frames max` (requested) and `REFORGE: clean exit after M frames` (completed) and emits FAIL when M < N, echoing any `NATURAL-EXIT` diagnostic lines into section 1.",
      "state": "confirmed",
      "category": "CPU",
      "publicUrl": "/reforge/findings/atari2600-f155-analyzer-run-length-floor-landed/",
      "publicSource": "/reforge/research/atari2600/#finding-155"
    },
    {
      "id": "atari2600-f154",
      "number": "154",
      "console": "atari2600",
      "title": "THE TERMINATOR KILLER DECODED",
      "summary": "There is NO ager. (2) INDEXED-RMW ZERO-PAGE WRAP — lifter.py's INC/DEC indexed path created the `_rmw_addr` effective-address vreg with the 6502 register width (W8), so the emitter masked the address ADD with `& 0xFF`: `DEC $0285,X` (RIOT I/O space — harmless on hardware, likely never even executed there) became `DEC ($85+X)` in RAM — and with X=0 that is the list terminator.",
      "state": "confirmed",
      "category": "CPU",
      "publicUrl": "/reforge/findings/atari2600-f154-the-terminator-killer-decoded/",
      "publicSource": "/reforge/research/atari2600/#finding-154"
    },
    {
      "id": "atari2600-f153",
      "number": "153",
      "console": "atari2600",
      "title": "F152 REFUTED both ways: the terminator IS written on every build ($FE71",
      "summary": "STATIC refutation of F152: both suspect callees are clean. Neither can fire the caller's unwind guard.",
      "state": "confirmed",
      "category": "Memory / cartridge",
      "publicUrl": "/reforge/findings/atari2600-f153-f152-refuted-both-ways-the-terminator-is-written-on-every-build-fe71/",
      "publicSource": "/reforge/research/atari2600/#finding-153"
    },
    {
      "id": "atari2600-f152",
      "number": "152",
      "console": "atari2600",
      "title": "ROOT-CAUSE MECHANISM LOCATED",
      "summary": "METHODOLOGY CORRECTION: F140's \"all #$E0 loads\" enumeration was TRUNCATED by grep pagination (head_limit 60) and missed $FE6F — re-verify enumerations are exhaustive before negative conclusions. THE MECHANISM: every JSR in the emitted sub_00FE16 carries the unwind guard `if (trampoline_target) return; if (rts_target != expected) return;`.",
      "state": "active",
      "category": "CPU",
      "publicUrl": "/reforge/findings/atari2600-f152-root-cause-mechanism-located/",
      "publicSource": "/reforge/research/atari2600/#finding-152"
    },
    {
      "id": "atari2600-f151",
      "number": "151",
      "console": "atari2600",
      "title": "TWO-LIST architecture confirmed (list-0 base $83 / list-1 base $8C, tails $DC/$DD)",
      "summary": "THE REAPER RUNS EVERY COUNTDOWN FRAME BY DESIGN (the F150 quiescence hypothesis is refuted). So either (a) $FE16 is supposed to write the terminator after the last entry and a diverged branch skips it, (b) the terminator is supposed to come from the $F121 init which is gated behind the very countdown the reaper runs during (circular — unlikely; hardware boots fine), or (c) $FE16 terminates via a path involving the appender ($144B STA $84,X) that our flow…",
      "state": "active",
      "category": "Recompiler",
      "publicUrl": "/reforge/findings/atari2600-f151-two-list-architecture-confirmed-list-0-base-83-list-1-base-8c-tails-dc-dd/",
      "publicSource": "/reforge/research/atari2600/#finding-151"
    },
    {
      "id": "atari2600-f150",
      "number": "150",
      "console": "atari2600",
      "title": "Game-state dispatcher $F0A9-$F101 decoded",
      "summary": "REFRAME: nothing here is structurally unreached — the path opens when the counters finish: non-TAS reset releases f=271 → countdown completes ≈f=469; TAS reset f=45 → ≈f=243. ALL our \"never executes\" watches ran 280 frames — too short for non-TAS, and in the TAS run the F138 reaper wedge fires at f≈261, ANNIHILATING zero page (counters included) BEFORE the countdown completes (f≈243 was close — the wedge and completion race, and the wedge appears to win…",
      "state": "confirmed",
      "category": "CPU",
      "publicUrl": "/reforge/findings/atari2600-f150-game-state-dispatcher-f0a9-f101-decoded/",
      "publicSource": "/reforge/research/atari2600/#finding-150"
    },
    {
      "id": "atari2600-f149",
      "number": "149",
      "console": "atari2600",
      "title": "$BF lifecycle COMPLETE: cleared at $F110 gated on $80 bit5, consumed by the $F114 init gate, decremented at $11ADE",
      "summary": "DECISIVE NEGATIVE: the iter-18 fixed watch shows ZERO $F110 writes and ZERO $F114 reads in 280 frames — the ENTIRE $F101+ region never executes; same for $11ADE. All of it lives inside sub_00100E (the main boot/frame flow, dispatcher-called) — so a branch INSIDE sub_00100E diverts before $F101 every frame.",
      "state": "confirmed",
      "category": "Timing / bus",
      "publicUrl": "/reforge/findings/atari2600-f149-bf-lifecycle-complete-cleared-at-f110-gated-on-80-bit5-consumed-by-the-f114-init-gate-de/",
      "publicSource": "/reforge/research/atari2600/#finding-149"
    },
    {
      "id": "atari2600-f148",
      "number": "148",
      "console": "atari2600",
      "title": "$1059-$107A is the GAME-RESET HANDLER (SWCHB-gated)",
      "summary": "CORRECTION to F147: the handler does NOT run every frame — the F145 watch counts ($106B ×14, $1074 ×14-15) exactly match the non-TAS autoplay RESET window f=257-270 (released f=271); in the TAS run it runs f=30-45. Each reset-window frame jumps to $FA03; whatever it does, the system lands in the F146 phantom-list state with $BF stuck at $40.",
      "state": "confirmed",
      "category": "Memory / cartridge",
      "publicUrl": "/reforge/findings/atari2600-f148-1059-107a-is-the-game-reset-handler-swchb-gated/",
      "publicSource": "/reforge/research/atari2600/#finding-148"
    },
    {
      "id": "atari2600-f147",
      "number": "147",
      "console": "atari2600",
      "title": "Asteroids TAS authored and replay-verified (RESET f=30-45 + three 36-frame fire holds pre-wedge)",
      "summary": "tests/tas/atari2600/Asteroids.tas.json committed (35 events; GAME RESET press f=30-45, fire holds f=80-115/150-185/230-265 each spanning the $DE&$1F debounce, then rotation/thrust/fire gameplay cadence; SELECT never pressed). Iter-21: decode the $106B/$1074 routine — entry conditions, the branch (if any) guarding the $40 store, what $40 means (bit6 of $BF), and whether a mislifted branch/flag makes it unconditional; cross-check the mirror copy; then…",
      "state": "confirmed",
      "category": "Input / mechanics",
      "publicUrl": "/reforge/findings/atari2600-f147-asteroids-tas-authored-and-replay-verified-reset-f-30-45-three-36-frame-fire-holds-pre-w/",
      "publicSource": "/reforge/research/atari2600/#finding-147"
    },
    {
      "id": "atari2600-f146",
      "number": "146",
      "console": "atari2600",
      "title": "Object lifecycle machinery decoded ($F384-$F3AC)",
      "summary": "So in steady state the terminator is MAINTAINED by $F3A8 — no explicit init required once the list is healthy. Iter-20: author tests/tas/atari2600/Asteroids.tas.json (fire press with release, plus maybe a second press; no SELECT), run prove with --tas, and check (a) ENTPROBE first-call sidx (terminator present?), (b) wedge gone?, (c) PPM f=400 nonblack — potentially the first rendered rocks.",
      "state": "active",
      "category": "Timing / bus",
      "publicUrl": "/reforge/findings/atari2600-f146-object-lifecycle-machinery-decoded-f384-f3ac/",
      "publicSource": "/reforge/research/atari2600/#finding-146"
    },
    {
      "id": "atari2600-f145",
      "number": "145",
      "console": "atari2600",
      "title": "Init gate fully decoded: $BF passes ($1074 writes $40 per frame)",
      "summary": "The alternate path $F63D clears bit6 (AND #$BF) when the input bit is held — classic press-edge + debounce + accept state machine. If that routine is the attract builder and SHOULD be writing real entries + terminator instead of $00, the divergence is inside IT (mislifted compare, wrong input, or an early-exit our runtime takes).",
      "state": "confirmed",
      "category": "Input / mechanics",
      "publicUrl": "/reforge/findings/atari2600-f145-init-gate-fully-decoded-bf-passes-1074-writes-40-per-frame/",
      "publicSource": "/reforge/research/atari2600/#finding-145"
    },
    {
      "id": "atari2600-f144",
      "number": "144",
      "console": "atari2600",
      "title": "F143 fix set IMPLEMENTED (watch \"rw\" parse, 6507 RAM-mirror canonicalization, stack ops through the memory bus)",
      "summary": "RESULTS: Asteroids rebuilt + 1800f prove — behavior shifted measurably (376 unique CRCs vs 358; TRAP 101→94; sprite-lines 235→226) but the screen remains black and the ENTPROBE first-call signature is unchanged (f=275, x=$01, sidx=-1): SP never enters the aliasing-sensitive region pre-wedge, so the PHA-strobe hypothesis is REFUTED as the Asteroids root cause (the fix remains correct hardware modeling and a real corpus-wide defect class — any title that…",
      "state": "disproven",
      "category": "CPU",
      "publicUrl": "/reforge/findings/atari2600-f144-f143-fix-set-implemented-watch-rw-parse-6507-ram-mirror-canonicalization-stack-ops-throu/",
      "publicSource": "/reforge/research/atari2600/#finding-144"
    },
    {
      "id": "atari2600-f143",
      "number": "143",
      "console": "atari2600",
      "title": "TWO runtime-model defects found",
      "summary": "Perfect correlation across all six watch runs this goal: every ,w watch recorded writes; every ,rw watch ($96, $83, $BF, $C8) recorded none. The $83 WRITE history must be redone with ,w.",
      "state": "active",
      "category": "Evidence",
      "publicUrl": "/reforge/findings/atari2600-f143-two-runtime-model-defects-found/",
      "publicSource": "/reforge/research/atari2600/#finding-143"
    },
    {
      "id": "atari2600-f142",
      "number": "142",
      "console": "atari2600",
      "title": "$83 watch proves the terminator was NEVER WRITTEN",
      "summary": "The boot-init block therefore NEVER EXECUTES. In our headless runtime these gates never pass, so the game never initializes its object list, and the f=275 reap walks uninitialized cells straight into the F138 runaway cascade.",
      "state": "active",
      "category": "Timing / bus",
      "publicUrl": "/reforge/findings/atari2600-f142-83-watch-proves-the-terminator-was-never-written/",
      "publicSource": "/reforge/research/atari2600/#finding-142"
    },
    {
      "id": "atari2600-f141",
      "number": "141",
      "console": "atari2600",
      "title": "Object reap loop decoded ($FCE7-$FD1D)",
      "summary": "THREE paths to DELETE: scan overflow (X reaches $80 — degenerate), $FD0B dead-entry reap, $FD1B status-$30 reap. The F139 first call (f=275, x=$01) therefore arrived via a REAP at index 1 — which requires the scan to have walked PAST [$83] and [$84] as live non-terminator entries.",
      "state": "active",
      "category": "Recompiler",
      "publicUrl": "/reforge/findings/atari2600-f141-object-reap-loop-decoded-fce7-fd1d/",
      "publicSource": "/reforge/research/atari2600/#finding-141"
    },
    {
      "id": "atari2600-f140",
      "number": "140",
      "console": "atari2600",
      "title": "Sentinel machinery fully mapped",
      "summary": "Static + watchpoint triangulation. Therefore the actual divergence is UPSTREAM in the $FCFF caller's GATE: on hardware that code path only invokes DELETE when the list has entries; our runtime's caller-side condition (object count, game-state flag, or a flag computed from a mislifted instruction) evaluates differently.",
      "state": "active",
      "category": "Input / mechanics",
      "publicUrl": "/reforge/findings/atari2600-f140-sentinel-machinery-fully-mapped/",
      "publicSource": "/reforge/research/atari2600/#finding-140"
    },
    {
      "id": "atari2600-f139",
      "number": "139",
      "console": "atari2600",
      "title": "[ENTPROBE] per-call DELETE evidence",
      "summary": "New permanent emitter capability: function-entry STATE probes (`_entry_state_probe_pcs` in emitter_c.py, emitted in the function PREAMBLE so they fire once per CALL, not per loop-iteration of the bb label) printing `[ENTPROBE $PC] f x s83 sidx ret` — call-time X, the $83 counter, a $E0-sentinel scan over $84-$B3, and the caller's JSR return address read from the stack.",
      "state": "active",
      "category": "Evidence",
      "publicUrl": "/reforge/findings/atari2600-f139-entprobe-per-call-delete-evidence/",
      "publicSource": "/reforge/research/atari2600/#finding-139"
    },
    {
      "id": "atari2600-f138",
      "number": "138",
      "console": "atari2600",
      "title": "Asteroids object-list primitives decoded",
      "summary": "Both movers decoded from the lifted C (no rebuild). RUNAWAY MECHANISM: if the $84 stream contains no $E0, DELETE's X runs through 255 and the zp,X wrap shifts the ENTIRE zero page down — explaining in one stroke the TIA-window bleed (F134), the $E5/$E6 vector stomp (F137), and total RAM decay.",
      "state": "active",
      "category": "Memory / cartridge",
      "publicUrl": "/reforge/findings/atari2600-f138-asteroids-object-list-primitives-decoded/",
      "publicSource": "/reforge/research/atari2600/#finding-138"
    },
    {
      "id": "atari2600-f137",
      "number": "137",
      "console": "atari2600",
      "title": "Kernel vector $E5/$E6 dies at f≈345",
      "summary": "Zero-rebuild diagnosis via the built-in write watchpoints on the standing iter-9 exe (`--headless 500 --watch 0xE5,w --watch 0xE6,w`, 4,063 parsed events; note: PowerShell `>`/`2>` redirection writes UTF-16 — parse with encoding=utf-16). — live display dispatch.",
      "state": "active",
      "category": "Memory / cartridge",
      "publicUrl": "/reforge/findings/atari2600-f137-kernel-vector-e5-e6-dies-at-f-345/",
      "publicSource": "/reforge/research/atari2600/#finding-137"
    },
    {
      "id": "atari2600-f136",
      "number": "136",
      "console": "atari2600",
      "title": "Flicker hypothesis REFUTED by consecutive-frame journals",
      "summary": "Iter-9 evidence closed the F135 fork decisively. Part 1 (no rebuild): pixel-counted ALL existing consecutive PPMs — f=400/401/402/403 and f=1500/1501/1502/1503 are 100% black (0 nonblack pixels each); only f=50 has content (234 px of $C6-red).",
      "state": "disproven",
      "category": "Memory / cartridge",
      "publicUrl": "/reforge/findings/atari2600-f136-flicker-hypothesis-refuted-by-consecutive-frame-journals/",
      "publicSource": "/reforge/research/atari2600/#finding-136"
    },
    {
      "id": "atari2600-f135",
      "number": "135",
      "console": "atari2600",
      "title": "Widened journal (strobes + enables + HMOVE)",
      "summary": "F134's fork resolves to (ii) for the dump frames. NEW LEAD from the volume math: ~38 events/frame run-average vs ~12 on each dump frame — frames are HETEROGENEOUS, which is exactly what Asteroids' flicker display would produce (the 2600 port multiplexes many rocks by drawing alternating subsets on alternating frames; a frame can legitimately be object-light).",
      "state": "active",
      "category": "Memory / cartridge",
      "publicUrl": "/reforge/findings/atari2600-f135-widened-journal-strobes-enables-hmove/",
      "publicSource": "/reforge/research/atari2600/#finding-135"
    },
    {
      "id": "atari2600-f134",
      "number": "134",
      "console": "atari2600",
      "title": "Journal writer-PC attribution lands",
      "summary": "The TIASnap journal now records the writer PC per event ((cycle,$reg,$val@PC) in [JRNL]; TIASnap.ev_pc + staging + io_write hook pass reforge_last_addr — permanent capability for every console using the TIA journal). Asteroids result, conclusive: EVERY journaled visible-frame TIA write across both dump frames — 321 events — comes from exactly three PCs: $FDE3 (x108), $FDE7 (x105), $FDEB (x108).",
      "state": "active",
      "category": "Timing / bus",
      "publicUrl": "/reforge/findings/atari2600-f134-journal-writer-pc-attribution-lands/",
      "publicSource": "/reforge/research/atari2600/#finding-134"
    },
    {
      "id": "atari2600-f133",
      "number": "133",
      "console": "atari2600",
      "title": "Bank tracking verified live (1512 switches); the zero source narrows to the RAM display list",
      "summary": "Asteroids f=800: bank=1, switches=1512 (~1.9 per frame — exactly the kernel-in-bank-0 / logic-in-bank-1 per-frame rhythm), last switch at $11FF0 (the bank-0 SwitchTo1 stub). The F132 cross-bank-data-read suspect is REFUTED: reforge_active_bank tracks faithfully (the lifted STA $FFF8/$FFF9 hotspot writes execute ~twice per frame), so bank-aware mem_read8 (F38) serves correct bytes to each bank's code.",
      "state": "confirmed",
      "category": "Memory / cartridge",
      "publicUrl": "/reforge/findings/atari2600-f133-bank-tracking-verified-live-1512-switches-the-zero-source-narrows-to-the-ram-display-lis/",
      "publicSource": "/reforge/research/atari2600/#finding-133"
    },
    {
      "id": "atari2600-f132",
      "number": "132",
      "console": "atari2600",
      "title": "Asteroids black screen convicted: the game writes $00 to every color register; renderer innocent",
      "summary": "The renderer and snapshot pipeline are innocent (write-then-clear sampling was also considered and excluded: the journal shows the written VALUES are zero). The L2 blocker is therefore the COLOR SOURCE CHAIN: the kernel stages colors from RAM/tables computed by overscan logic (the Pac-Man $D0-staging class), and that staging produces zeros — candidate causes: the color-computing routine not reached (F119 class), a color-table data read returning the wrong…",
      "state": "active",
      "category": "Video",
      "publicUrl": "/reforge/findings/atari2600-f132-asteroids-black-screen-convicted-the-game-writes-00-to-every-color-register-renderer-inn/",
      "publicSource": "/reforge/research/atari2600/#finding-132"
    },
    {
      "id": "atari2600-f131",
      "number": "131",
      "console": "atari2600",
      "title": "ASTEROIDS REACHES L1: dispatch-miss chain exhausted in two cycles; render gap (black frames) is the L2 blocker",
      "summary": "Chain burn results: cycle 1 f=324 (miss 0x190F resolved, next 0x1834); cycle 2 f=1800, NO dispatch miss — the full 1800-frame headless run completes. After ~53 iterations across two goal-runs, Asteroids moves L0 -> L1.",
      "state": "active",
      "category": "CPU",
      "publicUrl": "/reforge/findings/atari2600-f131-asteroids-reaches-l1-dispatch-miss-chain-exhausted-in-two-cycles-render-gap-black-frames/",
      "publicSource": "/reforge/research/atari2600/#finding-131"
    },
    {
      "id": "atari2600-f130",
      "number": "130",
      "console": "atari2600",
      "title": "Runtime-entry alias STITCHING implemented; the dispatch-miss feedback loop compounds again",
      "summary": "Implementation simplification discovered during design: the F129 alias decode RE-SYNCHRONIZES with the natural alignment within a few instructions ($1159: ORA $85 consumes 2 bytes, $115B: ORA ($EA),Y consumes 2, landing on $115D which the natural pool already owns) — so full standalone alias functions are unnecessary. The fix is entry STITCHING: in engine.py's F8 multi-bank block (inside the console_id==atari2600 + Atari2600Mapper.is_banked gate —…",
      "state": "confirmed",
      "category": "CPU",
      "publicUrl": "/reforge/findings/atari2600-f130-runtime-entry-alias-stitching-implemented-the-dispatch-miss-feedback-loop-compounds-agai/",
      "publicSource": "/reforge/research/atari2600/#finding-130"
    },
    {
      "id": "atari2600-f129",
      "number": "129",
      "console": "atari2600",
      "title": "$1159 is a deliberate mid-instruction kernel-ladder entry; the single-decode-per-address model cannot represent it",
      "summary": "Forensic complete; the F128 suspicion chain resolves three layers deep. (1) BANK ATTRIBUTION: the exit site virtual 0x11108 is BANK-0 $1108 — the JMP ($E5) is the Asteroids display kernel's computed goto.",
      "state": "active",
      "category": "Recompiler",
      "publicUrl": "/reforge/findings/atari2600-f129-1159-is-a-deliberate-mid-instruction-kernel-ladder-entry-the-single-decode-per-address-m/",
      "publicSource": "/reforge/research/atari2600/#finding-129"
    },
    {
      "id": "atari2600-f128",
      "number": "128",
      "console": "atari2600",
      "title": "Asteroids re-baseline: the $1159 dispatch-miss seed vanishes inside the lift pipeline",
      "summary": "G-A2600-005 run 1 opening measurement (resuming the 49-heartbeat G5 arc at its iter-49/51 state). This is PROGRESS relative to the iter-51 memory ($E6=$00 -> $00CF garbage): the vector now resolves to a plausible bank-1 address; the blocker has moved from vector-corruption to function-coverage.",
      "state": "active",
      "category": "CPU",
      "publicUrl": "/reforge/findings/atari2600-f128-asteroids-re-baseline-the-1159-dispatch-miss-seed-vanishes-inside-the-lift-pipeline/",
      "publicSource": "/reforge/research/atari2600/#finding-128"
    },
    {
      "id": "atari2600-f127",
      "number": "127",
      "console": "atari2600",
      "title": "Ratchet audit green; console_loop exit-code theory refuted (PS 5.1 stderr quirk was the chain-breaker)",
      "summary": "G-A2600-004 iter 2, verification iteration. (1) REFUTATION: the working theory from the G2 ceremonies (\"console_loop --run-prove-loop exits nonzero on Asteroids L0, breaking if-chained automation\") is WRONG — console_loop.main() already returns 0 unconditionally after writing the report (\"nonzero only for infrastructure failure\", returns 2 only for missing corpus dir), and the empirical probe confirms EXITCODE=0 with $?=True.",
      "state": "disproven",
      "category": "Recompiler",
      "publicUrl": "/reforge/findings/atari2600-f127-ratchet-audit-green-console-loop-exit-code-theory-refuted-ps-5-1-stderr-quirk-was-the-ch/",
      "publicSource": "/reforge/research/atari2600/#finding-127"
    },
    {
      "id": "atari2600-f126",
      "number": "126",
      "console": "atari2600",
      "title": "Tunnel pass-under adjudicated",
      "summary": "G-A2600-004 opening iteration (corpus ratchet: document the drop, don't hide it). The v3 zero-SELECT TAS introduced a wall_collision FAIL (\"sustained penetration\", run of 9, first f=422).",
      "state": "confirmed",
      "category": "Evidence",
      "publicUrl": "/reforge/findings/atari2600-f126-tunnel-pass-under-adjudicated/",
      "publicSource": "/reforge/research/atari2600/#finding-126"
    },
    {
      "id": "atari2600-f125",
      "number": "125",
      "console": "atari2600",
      "title": "AC#3 verification trace consolidated; G-A2600-002 acceptance criteria all addressed",
      "summary": "Docs-only consolidation closing G-A2600-002 AC#3. A \"Collision Latch Verification Trace\" subsection now sits directly under the TIA collision-detection spec (after the REFORGE implementation note), cross-referencing each spec contract (sticky-until-CXCLR, mid-scanline recompute-on-read, D6/D7-only bus) against the F118-F124 runtime evidence and recording the full latch->consumption->death->DEC chain with its permanent mechanical assertions.",
      "state": "active",
      "category": "Evidence",
      "publicUrl": "/reforge/findings/atari2600-f125-ac-3-verification-trace-consolidated-g-a2600-002-acceptance-criteria-all-addressed/",
      "publicSource": "/reforge/research/atari2600/#finding-125"
    },
    {
      "id": "atari2600-f124",
      "number": "124",
      "console": "atari2600",
      "title": "lives_decremented + ghost_collision_death asserted; the death pipeline is now a mechanical contract",
      "summary": "G-A2600-002 AC#2 and AC#4 close-out. New evaluator evaluate_ghost_collision_death in oracles/mechanical_oracle.py: every [CXRD] consumed-collision event (the game READ CXPPMM bit7 set — the F118 read-hit telemetry) must be followed by a lives decrement in [PAC] within max_lag=300 frames (timing basis F119/F121: ~125f death freeze + up to ~130f $F500 DEC $E4 cadence before $F53E lands).",
      "state": "active",
      "category": "Input / mechanics",
      "publicUrl": "/reforge/findings/atari2600-f124-lives-decremented-ghost-collision-death-asserted-the-death-pipeline-is-now-a-mechanical-/",
      "publicSource": "/reforge/research/atari2600/#finding-124"
    },
    {
      "id": "atari2600-f123",
      "number": "123",
      "console": "atari2600",
      "title": "One SELECT EDGE (not hold duration) selects the 2-player variation",
      "summary": "Three results, one refinement of F122. (1) REFUTATION: trimming the SELECT hold 31->2 frames produced a BYTE-IDENTICAL run (same death frames, same $99=8) — and $99 is 8 from FRAME 1, before any input.",
      "state": "active",
      "category": "Input / mechanics",
      "publicUrl": "/reforge/findings/atari2600-f123-one-select-edge-not-hold-duration-selects-the-2-player-variation/",
      "publicSource": "/reforge/research/atari2600/#finding-123"
    },
    {
      "id": "atari2600-f122",
      "number": "122",
      "console": "atari2600",
      "title": "Not invulnerability: two-player-alternating variation selected by the TAS",
      "summary": "Edge-triggered [98W] log at the mem_write8 capture site (value-changing writes, frame floor 400 — the RESET-held boot window re-inits $98 every frame via the $FC86/$FBFE toggle and exhausted the first cap by f=41). (d) The [PAC] lvl=8 anomaly resolves: $99 is the GAME VARIATION register, not level — the TAS's 30-frame SELECT hold (f=280-310) advanced it to variation 8, a two-player alternating variation per the Atari game-variation table.",
      "state": "active",
      "category": "Timing / bus",
      "publicUrl": "/reforge/findings/atari2600-f122-not-invulnerability-two-player-alternating-variation-selected-by-the-tas/",
      "publicSource": "/reforge/research/atari2600/#finding-122"
    },
    {
      "id": "atari2600-f121",
      "number": "121",
      "console": "atari2600",
      "title": "The death-DEC EXECUTES; lives are re-initialized to 3 during respawn (refines F120)",
      "summary": "DEC $98 RAN. Yet every [PAC] frame sample read lives=3 and the poll-based [TRAP] $98 printed nothing: lives went 3->2->3 inside one poll gap.",
      "state": "active",
      "category": "Timing / bus",
      "publicUrl": "/reforge/findings/atari2600-f121-the-death-dec-executes-lives-are-re-initialized-to-3-during-respawn-refines-f120/",
      "publicSource": "/reforge/research/atari2600/#finding-121"
    },
    {
      "id": "atari2600-f120",
      "number": "120",
      "console": "atari2600",
      "title": "$98 writer universe captured: the death-DEC at $F53E is NEVER reached",
      "summary": "The [TRAP] $98 writer trap sat inside #ifdef REFORGE_VERBOSE since 09ag-3, so no default prove build ever printed it — the $F53E \"death DEC\" provenance (agent static disassembly) had never been runtime-checked. Moved the trap out of the VERBOSE gate (precedent: the minimal [MOV] trace).",
      "state": "active",
      "category": "Input / mechanics",
      "publicUrl": "/reforge/findings/atari2600-f120-98-writer-universe-captured-the-death-dec-at-f53e-is-never-reached/",
      "publicSource": "/reforge/research/atari2600/#finding-120"
    },
    {
      "id": "atari2600-f119",
      "number": "119",
      "console": "atari2600",
      "title": "Death sequence runs end-to-end on a seen collision; lives ($98) are never decremented",
      "summary": "Per-event collision context telemetry ([CXFIRE] one line per fire-frame at the latch-set site with screen position + game state; [CXRD] at the CXPPMM read path with state/$E7/$98/$99) plus a 2400-frame extended TAS run overturn the F118 read of the logic-side defect. A SECOND collision was seen at f=2368 (ghost walked into stationary pac) and the e7 cycle restarted — two complete death sequences in one run.",
      "state": "active",
      "category": "Input / mechanics",
      "publicUrl": "/reforge/findings/atari2600-f119-death-sequence-runs-end-to-end-on-a-seen-collision-lives-98-are-never-decremented/",
      "publicSource": "/reforge/research/atari2600/#finding-119"
    },
    {
      "id": "atari2600-f118",
      "number": "118",
      "console": "atari2600",
      "title": "Ghost-collision invulnerability split into two defects by cumulative CXPPMM telemetry",
      "summary": "G-A2600-002 opening measurement. New always-on counters in io_dispatch_c.py (never reset by CXCLR, so they survive the game's per-frame latch strobe that made [CX] sampling blind): frames-with-P0/P1-latch-fire and CXPPMM reads that returned bit7 set, both surfaced on the per-frame [PAC] line.",
      "state": "active",
      "category": "Evidence",
      "publicUrl": "/reforge/findings/atari2600-f118-ghost-collision-invulnerability-split-into-two-defects-by-cumulative-cxppmm-telemetry/",
      "publicSource": "/reforge/research/atari2600/#finding-118"
    },
    {
      "id": "atari2600-f117",
      "number": "117",
      "console": "atari2600",
      "title": "Dot-clear chain proven live; center bar adjudicated authentic; wall_collision PASSES",
      "summary": "Closing the F113->F115->F116 investigation. (1) Cross-frame journal diff (f=400 vs f=1600, two-tag [JRNL] dump): band lines sl 190-191 changed PF0 $A0 -> $00 — an eaten dot's playfield cells CLEARED.",
      "state": "confirmed",
      "category": "Input / mechanics",
      "publicUrl": "/reforge/findings/atari2600-f117-dot-clear-chain-proven-live-center-bar-adjudicated-authentic-wall-collision-passes/",
      "publicSource": "/reforge/research/atari2600/#finding-117"
    },
    {
      "id": "atari2600-f116",
      "number": "116",
      "console": "atari2600",
      "title": "Maze PF values come from zero-page staging, not a ROM display table",
      "summary": "The F115 fork test (ROM byte comparison) returned a decisive negative with structure. (1) The journaled per-band PF sequences (49 band lines/frame) do NOT exist anywhere in ROM, forward or reversed — the maze playfield is COMPUTED, not read from a flat display table.",
      "state": "active",
      "category": "Memory / cartridge",
      "publicUrl": "/reforge/findings/atari2600-f116-maze-pf-values-come-from-zero-page-staging-not-a-rom-display-table/",
      "publicSource": "/reforge/research/atari2600/#finding-116"
    },
    {
      "id": "atari2600-f115",
      "number": "115",
      "console": "atari2600",
      "title": "Journal contents refute the mid-scanline-gap hypothesis; the game itself writes the center bar solid",
      "summary": "Two results. (1) Journal plumbing correction: a scanline can be snapshotted more than once (WSYNC path AND the Finding-86 cycle-driven beam path); the capture handoff used assignment, so the later empty-stage call zeroed ev_n on every line while the capture counters grew — every snapshot read as event-free.",
      "state": "active",
      "category": "Timing / bus",
      "publicUrl": "/reforge/findings/atari2600-f115-journal-contents-refute-the-mid-scanline-gap-hypothesis-the-game-itself-writes-the-cente/",
      "publicSource": "/reforge/research/atari2600/#finding-115"
    },
    {
      "id": "atari2600-f114",
      "number": "114",
      "console": "atari2600",
      "title": "Mid-scanline TIA write journal: capture step",
      "summary": "Step 1 of the G-A2600-002 class-1 fix (built under G-A2600-001/AC#3 with the human-named design from verdict 4). Each TIASnap now carries the scanline write JOURNAL: up to 16 (cpu-cycle-offset, register, value) events for the visible-content registers (PF0/1/2, GRP0/1, COLUP0/1, COLUPF, COLUBK), captured by a single hook at the Atari io_write entry after TIA address normalization, staged per line, handed to the snapshot at the WSYNC strobe, cleared at…",
      "state": "active",
      "category": "Timing / bus",
      "publicUrl": "/reforge/findings/atari2600-f114-mid-scanline-tia-write-journal-capture-step/",
      "publicSource": "/reforge/research/atari2600/#finding-114"
    },
    {
      "id": "atari2600-f113",
      "number": "113",
      "console": "atari2600",
      "title": "[SPR]-calibrated wall oracle catches the maze center passage missing from the render",
      "summary": "Three results in one chain. (1) wall_collision calibration now comes from [SPR] telemetry instead of screenshot sprite-hunting: GRP1 drives the score/lives band EVERY frame (grp1_last pins at the band bottom), so window height cannot identify pac — but grp1_first can: it is pac top when drawn and the band fixed top when starved, making the band top the MODE of grp1_first.",
      "state": "confirmed",
      "category": "Evidence",
      "publicUrl": "/reforge/findings/atari2600-f113-spr-calibrated-wall-oracle-catches-the-maze-center-passage-missing-from-the-render/",
      "publicSource": "/reforge/research/atari2600/#finding-113"
    },
    {
      "id": "atari2600-f112",
      "number": "112",
      "console": "atari2600",
      "title": "The sprite-vs-logic \"drift\" is a discrete one-band (22-row) misplacement toggle, not timing drift",
      "summary": "First continuous [SPR] dataset (Finding 111) across 1800 TAS frames decomposes the F108 divergence completely. (1) When the pac sprite IS drawn (19-row GRP1 window), the RAM->render mapping is EXACTLY y_screen = 2*pacY + 6 (anchored rows) — locked for 150 straight frames at gameplay start and again in the f=1700+ wall-hold era; there is NO continuous drift and NO timing-residual component.",
      "state": "active",
      "category": "Timing / bus",
      "publicUrl": "/reforge/findings/atari2600-f112-the-sprite-vs-logic-drift-is-a-discrete-one-band-22-row-misplacement-toggle-not-timing-d/",
      "publicSource": "/reforge/research/atari2600/#finding-112"
    },
    {
      "id": "atari2600-f111",
      "number": "111",
      "console": "atari2600",
      "title": "[SPR] sprite row-window telemetry (GRP first/last scanline vs logic Y)",
      "summary": "Instrumentation finding serving the F108v2 diagnosis (residual ~20-row era-dependent sprite-vs-logic vertical drift, sprite channel only). tia_publish_frame_truth() now tracks, per frame, the first/last visible scanline where GRP0 and GRP1 were nonzero plus the frame first-visible scanline (the F104 anchor), exposed via tia_grp{0,1}_{first,last}_sl() / tia_first_visible_sl().",
      "state": "active",
      "category": "Evidence",
      "publicUrl": "/reforge/findings/atari2600-f111-spr-sprite-row-window-telemetry-grp-first-last-scanline-vs-logic-y/",
      "publicSource": "/reforge/research/atari2600/#finding-111"
    },
    {
      "id": "atari2600-f110",
      "number": "110",
      "console": "atari2600",
      "title": "Cycle table v2: NMOS page-cross +1 cycles emitted (reads + taken branches)",
      "summary": "Closes the two deferred items from Finding 103. (a) READ-class indexed ops (loads/ALU with abs,X / abs,Y / (ind),Y) now emit a runtime page-cross check alongside the base io_tick: abs-indexed compares the static base page against base+index (elided entirely when the base low byte is $00 — can never cross); (ind),Y fetches the zero-page pointer (with the NMOS (zp+1)&$FF pointer-high wrap) and ticks +1 when pointer+Y crosses.",
      "state": "active",
      "category": "Timing / bus",
      "publicUrl": "/reforge/findings/atari2600-f110-cycle-table-v2-nmos-page-cross-1-cycles-emitted-reads-taken-branches/",
      "publicSource": "/reforge/research/atari2600/#finding-110"
    },
    {
      "id": "atari2600-f109",
      "number": "109",
      "console": "atari2600",
      "title": "R-MECH-4 is a real gate: checksums now evaluates every existing mechanical oracle",
      "summary": "Chassis finding (Finding 102 class). The blocking CHECKSUMS rule R-MECH-4 (\"per-ROM mechanical assertions pass, L4\") had been a stub returning pass since the revival migration — the L4 ladder rung existed on paper only.",
      "state": "active",
      "category": "Evidence",
      "publicUrl": "/reforge/findings/atari2600-f109-r-mech-4-is-a-real-gate-checksums-now-evaluates-every-existing-mechanical-oracle/",
      "publicSource": "/reforge/research/atari2600/#finding-109"
    },
    {
      "id": "atari2600-f108",
      "number": "108",
      "console": "atari2600",
      "title": "Sprite-vs-logic divergence measured",
      "summary": "Built the maze-wall-map oracle for G-A2600-001 AC#3 (oracles/maze_map.py + phase2/console_loop.py wall_collision wiring): wall mask from the rendered playfield (large tan components inside the 189-row maze band; dots fall under a 31px size floor), sprite-shaped component detection, scale-aware RAM->pixel calibration with candidate voting, sustained-penetration run semantics (>= 4 consecutive in-wall samples; single-sample jitter is render quantization,…",
      "state": "active",
      "category": "Evidence",
      "publicUrl": "/reforge/findings/atari2600-f108-sprite-vs-logic-divergence-measured/",
      "publicSource": "/reforge/research/atari2600/#finding-108"
    },
    {
      "id": "atari2600-f107",
      "number": "107",
      "console": "atari2600",
      "title": "Per-frame [MOV] telemetry + wall_hold mechanical assertion (G-A2600-001 AC#2 mechanized)",
      "summary": "Human verdict 4 confirmed walls hold visually; this finding converts that observation into a deterministic, regression-guarded Layer-3/4 assertion. (a) [MOV] moved from the 60-frame DBG cadence into the per-frame [PAC] telemetry block — at the old cadence a 30-frame wall-hold window contained at most one sample, indistinguishable from dead telemetry.",
      "state": "active",
      "category": "Evidence",
      "publicUrl": "/reforge/findings/atari2600-f107-per-frame-mov-telemetry-wall-hold-mechanical-assertion-g-a2600-001-ac-2-mechanized/",
      "publicSource": "/reforge/research/atari2600/#finding-107"
    },
    {
      "id": "atari2600-f104",
      "number": "104",
      "console": "atari2600",
      "title": "Per-frame first-visible render anchor kills the screen shake",
      "summary": "The frame composer COMPACTED visible scanlines (stacked top-down, skipping blanked lines): any mid-frame line drop made everything below it breathe upward, and frame-start variance translated content. v2 policy: each frame's first visible scanline pins to row 0 and all other lines map by ABSOLUTE offset from it — no interior compaction, no translation; gaps render black; bottom score/lives bands stay locked.",
      "state": "active",
      "category": "Video",
      "publicUrl": "/reforge/findings/atari2600-f104-per-frame-first-visible-render-anchor-kills-the-screen-shake/",
      "publicSource": "/reforge/research/atari2600/#finding-104"
    },
    {
      "id": "atari2600-f103",
      "number": "103",
      "console": "atari2600",
      "title": "Exact NMOS 6502 cycle table replaces per-IR estimates",
      "summary": "io_tick costs came from flat per-IR-op guesses (loads 4, reg-ops 2, max-per-address): INC zp ticked 4 vs the real 5, PHA 4 vs 3, (ind),Y loads 4 vs 5 — thousands of small errors per frame. On a machine where 76 cycles = one scanline and 1 cycle = 3 beam pixels, that error budget IS the human-reported symptom cluster: RESP-strobed sprites land pixels away from where game logic believes them (sprite drift + phantom CXPPMM collisions = random deaths), and…",
      "state": "active",
      "category": "CPU",
      "publicUrl": "/reforge/findings/atari2600-f103-exact-nmos-6502-cycle-table-replaces-per-ir-estimates/",
      "publicSource": "/reforge/research/atari2600/#finding-103"
    },
    {
      "id": "atari2600-f102",
      "number": "102",
      "console": "atari2600",
      "title": "Template regen emitted default screen dims; interactive launch crashed after the 250-line window",
      "summary": "prove_loop's template regenerate() constructed its CEmitter without screen dimensions, so every regenerated platform.c called ppu_init(256, 240) for every console. Latent for months: the Atari SDL render walk stayed within 240 rows, so the wrong-sized window merely letterboxed.",
      "state": "active",
      "category": "Video",
      "publicUrl": "/reforge/findings/atari2600-f102-template-regen-emitted-default-screen-dims-interactive-launch-crashed-after-the-250-line/",
      "publicSource": "/reforge/research/atari2600/#finding-102"
    },
    {
      "id": "atari2600-f101",
      "number": "101",
      "console": "atari2600",
      "title": "TIA render: P0>P1 fixed priority + 250-line window restores the score/lives bands",
      "summary": "(a) render_scanline_from_snap drew P1 after P0 (P1 won overlaps); real TIA fixed priority is P0>M0>P1>M1>BL>PF. Draw order swapped.",
      "state": "confirmed",
      "category": "Timing / bus",
      "publicUrl": "/reforge/findings/atari2600-f101-tia-render-p0-p1-fixed-priority-250-line-window-restores-the-score-lives-bands/",
      "publicSource": "/reforge/research/atari2600/#finding-101"
    },
    {
      "id": "atari2600-f100",
      "number": "100",
      "console": "atari2600",
      "title": "Entity map correction: Pac-Man is ($B1,$B6); $B0/$BA is a ghost",
      "summary": "The long-standing map (pacX=$B0/pacY=$BA) was watching ghost slot 0 — the same diagnostic-mislabel class as 09ag-16. GRP0 = ghost channel (4-frame color rotation), GRP1 = Pac (constant tan) — also inverted vs prior assumption.",
      "state": "active",
      "category": "Recompiler",
      "publicUrl": "/reforge/findings/atari2600-f100-entity-map-correction-pac-man-is-b1-b6-b0-ba-is-a-ghost/",
      "publicSource": "/reforge/research/atari2600/#finding-100"
    },
    {
      "id": "atari2600-f99b",
      "number": "99b",
      "console": "atari2600",
      "title": "Faithful JSR/RTS stack semantics; the ghost cluster-trap was lost abort semantics",
      "summary": "JSR was a bare C call (no return-address push) and RTS a bare C return. Two corpus-wide consequences: (a) the universal \"first-valid-wins\" abort idiom (try-routine stores result, PLA/PLA discards the return address, RTS returns TWO levels) didn't abort — every direction try ran and the LAST valid one won.",
      "state": "active",
      "category": "CPU",
      "publicUrl": "/reforge/findings/atari2600-f99b-faithful-jsr-rts-stack-semantics-the-ghost-cluster-trap-was-lost-abort-semantics/",
      "publicSource": "/reforge/research/atari2600/#finding-99b"
    },
    {
      "id": "atari2600-f99",
      "number": "99",
      "console": "atari2600",
      "title": "PHP/PLP were flag no-ops; Pac-Man's maze-row parity died in transit",
      "summary": "The lifter pushed/pulled a dead r_flags vreg; the materialized model (ucmp carry, cmp_result N/Z, decimal_mode, overflow_flag) was never packed/unpacked. Pac-Man computes its legal-move table index as (X>>2) + 0x28*(row&1), preserving row parity in CARRY across two LSRs via PHP/PLP ($FBC5-$FBCE).",
      "state": "active",
      "category": "CPU",
      "publicUrl": "/reforge/findings/atari2600-f99-php-plp-were-flag-no-ops-pac-man-s-maze-row-parity-died-in-transit/",
      "publicSource": "/reforge/research/atari2600/#finding-99"
    },
    {
      "id": "atari2600-f98",
      "number": "98",
      "console": "atari2600",
      "title": "input_c demo_mode: second phantom-switch source with a RESET deadlock",
      "summary": "The interactive build had its OWN autoplay (09ag-23): RESET held f=10-270, fire/joystick pump after, latched off on first keypress — but a keypress DURING the hold window latched it off with key_reset still 1, pinning GAME RESET low forever (game locked in init, no select screen, no control). Removed entirely; window title now carries the key legend (Arrows/Z/Space/Enter=RESET/Tab=SELECT/F12=Power).",
      "state": "active",
      "category": "Input / mechanics",
      "publicUrl": "/reforge/findings/atari2600-f98-input-c-demo-mode-second-phantom-switch-source-with-a-reset-deadlock/",
      "publicSource": "/reforge/research/atari2600/#finding-98"
    },
    {
      "id": "atari2600-f97",
      "number": "97",
      "console": "atari2600",
      "title": "Synthetic RESET/SELECT injection ran in interactive mode",
      "summary": "The io_dispatch autoplay RESET hold (f=10-270) + SELECT probe (f=280-310) were not gated on headless_mode: a human player's first 4.5 seconds fought a phantom held RESET, then a phantom SELECT silently changed the game variation. Human play verdict (\"no main menu\") traced partly here.",
      "state": "active",
      "category": "Recompiler",
      "publicUrl": "/reforge/findings/atari2600-f97-synthetic-reset-select-injection-ran-in-interactive-mode/",
      "publicSource": "/reforge/research/atari2600/#finding-97"
    },
    {
      "id": "atari2600-f96",
      "number": "96",
      "console": "atari2600",
      "title": "Nested-layout builds compiled a 7-week-stale game_main.c: full-regen never copied the lift into the c_project",
      "summary": "`prove_loop.copy_to_project` copied only runtime templates (io.c, ppu.c, ...) into nested c_project dirs. `full_regen` wrote the fresh `game_main.c` into the game_dir root — and the build compiled `Pac_Man_NA_c_project/game_main.c`, dated April 23.",
      "state": "active",
      "category": "Evidence",
      "publicUrl": "/reforge/findings/atari2600-f96-nested-layout-builds-compiled-a-7-week-stale-game-main-c-full-regen-never-copied-the-lif/",
      "publicSource": "/reforge/research/atari2600/#finding-96"
    },
    {
      "id": "atari2600-f95",
      "number": "95",
      "console": "atari2600",
      "title": "The 09-series RAM probes were corrupting the state they were meant to unlock",
      "summary": "This record documents the conclusion: The 09-series RAM probes were corrupting the state they were meant to unlock. Supporting raw traces remain outside the public finding.",
      "state": "active",
      "category": "Timing / bus",
      "publicUrl": "/reforge/findings/atari2600-f95-the-09-series-ram-probes-were-corrupting-the-state-they-were-meant-to-unlock/",
      "publicSource": "/reforge/research/atari2600/#finding-95"
    },
    {
      "id": "atari2600-f94",
      "number": "94",
      "console": "atari2600",
      "title": "The lifter dropped decimal mode: SED/CLD were NOPs, all BCD score math ran binary",
      "summary": "`lifter.py` lifted SED/CLD into the generic flag-NOP bucket, so the standard 2600 score idiom (`SED / CLC / ADC score / CLD` — Pac-Man's add-score routine at $FC45, and the same shape in most of the era's library) silently performed BINARY arithmetic: ten dots showed $0A instead of BCD $10, corrupting every displayed digit past 9. Fix: `cpu->decimal_mode` flag in CpuState; SED/CLD NOP-comments now emit set/clear; ADC/SBC emission branches at runtime into…",
      "state": "active",
      "category": "CPU",
      "publicUrl": "/reforge/findings/atari2600-f94-the-lifter-dropped-decimal-mode-sed-cld-were-nops-all-bcd-score-math-ran-binary/",
      "publicSource": "/reforge/research/atari2600/#finding-94"
    },
    {
      "id": "atari2600-f93",
      "number": "93",
      "console": "atari2600",
      "title": "TAS replay runtime + universal input-coupling oracle: the L3 gate is live",
      "summary": "Layer 3 (\"playable\") was unverifiable because nothing could drive deterministic input: the .tas.json schema existed but the runtime had no replay support and --check-input-coupling was a stub. Landed end-to-end this session: (a) `platform.c` (via emitter_c.py) parses `--tas-replay <path>` and loads a flat event script (\"<frame> <swcha-hex> <swchb_clear-hex> <fire 0|1>\"; the C loader is a trivial fscanf — prove_loop converts .tas.json to this format so no…",
      "state": "confirmed",
      "category": "Evidence",
      "publicUrl": "/reforge/findings/atari2600-f93-tas-replay-runtime-universal-input-coupling-oracle-the-l3-gate-is-live/",
      "publicSource": "/reforge/research/atari2600/#finding-93"
    },
    {
      "id": "atari2600-f83",
      "number": "83",
      "console": "atari2600",
      "title": "Autoplay GAME RESET hold (iter 48 binary-test probe) left active for every corpus ROM",
      "summary": "The iter-48 Asteroids binary test extended the synthetic GAME RESET hold from frames 10-270 to 10-1500 and was never reverted after the test concluded. Every corpus ROM therefore ran with the console's RESET switch held for 25 of the 30 simulated seconds.",
      "state": "active",
      "category": "Memory / cartridge",
      "publicUrl": "/reforge/findings/atari2600-f83-autoplay-game-reset-hold-iter-48-binary-test-probe-left-active-for-every-corpus-rom/",
      "publicSource": "/reforge/research/atari2600/#finding-83"
    },
    {
      "id": "atari2600-f82",
      "number": "82",
      "console": "atari2600",
      "title": "protected-seed override in `_drop_overlapping_instructions` unconditionally favours dispatch_miss seeds, even when…",
      "summary": "Concern: iter 48 identified `sub_001046` (misaligned function at bank-1 `$1046`) as the runtime exit cause. iter 49 audits why iter 41's misaligned-leader filter didn't catch it.",
      "state": "active",
      "category": "CPU",
      "publicUrl": "/reforge/findings/atari2600-f82-protected-seed-override-in-drop-overlapping-instructions-unconditionally-favours-dispatc/",
      "publicSource": "/reforge/research/atari2600/#finding-82"
    },
    {
      "id": "atari2600-f81",
      "number": "81",
      "console": "atari2600",
      "title": "RESET-released-path hypothesis falsified by binary test",
      "summary": "Concern: iter 47 hypothesised the RESET-released scan path at `$107D` produces the 271-frame exit. iter 48 implements the binary test: extend autoplay GAME RESET hold from frames 10-270 to 10-1500.",
      "state": "disproven",
      "category": "Memory / cartridge",
      "publicUrl": "/reforge/findings/atari2600-f81-reset-released-path-hypothesis-falsified-by-binary-test/",
      "publicSource": "/reforge/research/atari2600/#finding-81"
    },
    {
      "id": "atari2600-f80",
      "number": "80",
      "console": "atari2600",
      "title": "$E3/$E4 init IS correct in RESET-pressed cycles; the real exit is at $104F in the RESET-released scan path",
      "summary": "Concern: iter 46 attributed the 271-frame exit to \"$E3/$E4 = 0 after ZP-clear at $106B-$106E\". Iter 47 adds a $E3/$E4/$E5/$E6 write trace (windowed at frames 0-2 / 190-210 / 260-280) to confirm whether/when these pointers get set.",
      "state": "confirmed",
      "category": "Timing / bus",
      "publicUrl": "/reforge/findings/atari2600-f80-e3-e4-init-is-correct-in-reset-pressed-cycles-the-real-exit-is-at-104f-in-the-reset-rele/",
      "publicSource": "/reforge/research/atari2600/#finding-80"
    },
    {
      "id": "atari2600-f79",
      "number": "79",
      "console": "atari2600",
      "title": "bank-collision in dispatch switch picks wrong function for F8 carts",
      "summary": "Concern: iter 45's diagnostic showed first `$1000` dispatch at frame 195 within autoplay's RESET window, yet chain still ends `$19DA`. iter 46 traces `$F7/$F8` writes by PC + frame to disambiguate.",
      "state": "confirmed",
      "category": "CPU",
      "publicUrl": "/reforge/findings/atari2600-f79-bank-collision-in-dispatch-switch-picks-wrong-function-for-f8-carts/",
      "publicSource": "/reforge/research/atari2600/#finding-79"
    },
    {
      "id": "atari2600-f78",
      "number": "78",
      "console": "atari2600",
      "title": "dispatch-trace frame correlation",
      "summary": "Concern: iter 44 left an open question: does autoplay's GAME RESET press window (frames 10-270) actually cover the frame when sub_001000 first executes? Without per-dispatch frame data, the question is unanswerable.",
      "state": "active",
      "category": "Evidence",
      "publicUrl": "/reforge/findings/atari2600-f78-dispatch-trace-frame-correlation/",
      "publicSource": "/reforge/research/atari2600/#finding-78"
    },
    {
      "id": "atari2600-f77",
      "number": "77",
      "console": "atari2600",
      "title": "Asteroids ROM has ZERO standard INPT4/INPT5 read patterns; iter 43 hypothesis falsified",
      "summary": "Concern: iter 43 hypothesised that Asteroids' fire-button polling code exists in undecoded ROM regions. Iter 44 ROM-byte search exhaustively tests this.",
      "state": "disproven",
      "category": "Memory / cartridge",
      "publicUrl": "/reforge/findings/atari2600-f77-asteroids-rom-has-zero-standard-inpt4-inpt5-read-patterns-iter-43-hypothesis-falsified/",
      "publicSource": "/reforge/research/atari2600/#finding-77"
    },
    {
      "id": "atari2600-f76",
      "number": "76",
      "console": "atari2600",
      "title": "soft-reset cycle is the game's attract-mode flow, not a bug; fire-button polling absent from lifted code",
      "summary": "Concern: iter 42 named the cycle `$143C → $1000 → $19DA → $1B00` a \"soft-reset trap\". iter 43's task: audit `sub_01143C` exit paths to find the writer of `trampoline_target = $1000`.",
      "state": "active",
      "category": "Timing / bus",
      "publicUrl": "/reforge/findings/atari2600-f76-soft-reset-cycle-is-the-game-s-attract-mode-flow-not-a-bug-fire-button-polling-absent-fr/",
      "publicSource": "/reforge/research/atari2600/#finding-76"
    },
    {
      "id": "atari2600-f75",
      "number": "75",
      "console": "atari2600",
      "title": "$1100` DISPATCH-MISS already resolved by iter-41 + dispatch_miss_cache feedback",
      "summary": "Concern: Investigate the `$1100` DISPATCH-MISS that iter 41's commit row reported as the runtime exit point. Either the function isn't decoded (no walker path led there) or it's decoded under the bank-0 virtual prefix `$11100` and the dispatch-table name resolution is matching wrong.",
      "state": "active",
      "category": "CPU",
      "publicUrl": "/reforge/findings/atari2600-f75-1100-dispatch-miss-already-resolved-by-iter-41-dispatch-miss-cache-feedback/",
      "publicSource": "/reforge/research/atari2600/#finding-75"
    },
    {
      "id": "atari2600-f74",
      "number": "74",
      "console": "atari2600",
      "title": "Drop misaligned CFG leaders; runtime dispatch chain extends from 3 → 5 calls",
      "summary": "Concern: Iter 40's audit identified `$114BA` as a misaligned CFG leader splitting the kernel function. Iter 41 implements fix candidate (1): drop leaders whose address falls inside another decoded instruction's byte range.",
      "state": "active",
      "category": "CPU",
      "publicUrl": "/reforge/findings/atari2600-f74-drop-misaligned-cfg-leaders-runtime-dispatch-chain-extends-from-3-5-calls/",
      "publicSource": "/reforge/research/atari2600/#finding-74"
    },
    {
      "id": "atari2600-f73",
      "number": "73",
      "console": "atari2600",
      "title": "Misaligned CFG leader $114BA splits the kernel function; sub_01143C falls off end with no terminator",
      "summary": "Concern: Iter 39 named iter-40 forensic concerns: inspect `sub_01143C` (the 194-frame dead-end function) for trampoline_target writes; grep all lifted code for `trampoline_target = $1003`. Both were specifically called out.",
      "state": "active",
      "category": "CPU",
      "publicUrl": "/reforge/findings/atari2600-f73-misaligned-cfg-leader-114ba-splits-the-kernel-function-sub-01143c-falls-off-end-with-no-/",
      "publicSource": "/reforge/research/atari2600/#finding-73"
    },
    {
      "id": "atari2600-f72",
      "number": "72",
      "console": "atari2600",
      "title": "Runtime dispatch trace reveals only 3 calls in 194 frames",
      "summary": "Concern: Iter 38 closed with the bank-switch infrastructure landed in the static lifter, but the Asteroids runtime visual + frame count UNCHANGED. The static lift now contains the visible-frame kernel ($11003), dispatch writers ($1101B / $1109A), and at least one dispatch destination ($11083).",
      "state": "active",
      "category": "Evidence",
      "publicUrl": "/reforge/findings/atari2600-f72-runtime-dispatch-trace-reveals-only-3-calls-in-194-frames/",
      "publicSource": "/reforge/research/atari2600/#finding-72"
    },
    {
      "id": "atari2600-f71",
      "number": "71",
      "console": "atari2600",
      "title": "Bank-switch hotspot byte-pattern scan",
      "summary": "Concern: Iter 37's queue named bank-switch hotspot modelling as the principled fix for the runtime gap. Iter 33 + iter 34 + iter 35 + iter 37 progressively decoded more of Asteroids' bank-0 kernel code statically, but the runtime call chain still dispatches via `sub_01143C` (one of iter 24's const-prop seeds) and never reaches the visible-frame kernel.",
      "state": "active",
      "category": "Memory / cartridge",
      "publicUrl": "/reforge/findings/atari2600-f71-bank-switch-hotspot-byte-pattern-scan/",
      "publicSource": "/reforge/research/atari2600/#finding-71"
    },
    {
      "id": "atari2600-f70",
      "number": "70",
      "console": "atari2600",
      "title": "Cross-bank ZP-pointer const-prop resolves $E3/$E4 dispatch; $11083 decoded",
      "summary": "Concern: Iter 35-36 left two dispatch destinations missing ($11083 / $110C0) and two of the three `STA $E3` writers ($1107C, $1109A) missing. Iter 35's queue named two-byte ZP-pointer const-prop for `JMP ($zp)` as the highest-leverage fix.",
      "state": "active",
      "category": "CPU",
      "publicUrl": "/reforge/findings/atari2600-f70-cross-bank-zp-pointer-const-prop-resolves-e3-e4-dispatch-11083-decoded/",
      "publicSource": "/reforge/research/atari2600/#finding-70"
    },
    {
      "id": "atari2600-f69",
      "number": "69",
      "console": "atari2600",
      "title": "Bank-1 byte-pattern scan attempted, regressed Asteroids, reverted; helper extraction retained",
      "summary": "Concern: Iter 35's byte-pattern scan (with opcode source seeding) was bank-0-only. Iter 36 candidate (2) from the queue: \"Symmetric byte-pattern scan in bank-1 (currently bank-0 only).",
      "state": "active",
      "category": "Memory / cartridge",
      "publicUrl": "/reforge/findings/atari2600-f69-bank-1-byte-pattern-scan-attempted-regressed-asteroids-reverted-helper-extraction-retain/",
      "publicSource": "/reforge/research/atari2600/#finding-69"
    },
    {
      "id": "atari2600-f68",
      "number": "68",
      "console": "atari2600",
      "title": "Byte-pattern scan extended to opcode source positions; JMP-$D003 sites + new runtime path",
      "summary": "Concern: Iter 34's byte-pattern scan was target-only — it seeded the destination of every `4C XX YY` (JMP abs) / `20 XX YY` (JSR abs) opcode position, but not the source position itself. As a result, the four `JMP $D003` source sites in Asteroids ($1125 / $113B / $11A9 / $1215) stayed missing: no decoded reference pointed at them.",
      "state": "active",
      "category": "CPU",
      "publicUrl": "/reforge/findings/atari2600-f68-byte-pattern-scan-extended-to-opcode-source-positions-jmp-d003-sites-new-runtime-path/",
      "publicSource": "/reforge/research/atari2600/#finding-68"
    },
    {
      "id": "atari2600-f67",
      "number": "67",
      "console": "atari2600",
      "title": "Bank-0 byte-pattern JMP/JSR target scan; kernel entry now decoded",
      "summary": "The first fix candidate from iter 33's queue was a fixed-point bank-0 walker: collect bank-0's own branch_targets after each pass and re-seed.",
      "state": "active",
      "category": "CPU",
      "publicUrl": "/reforge/findings/atari2600-f67-bank-0-byte-pattern-jmp-jsr-target-scan-kernel-entry-now-decoded/",
      "publicSource": "/reforge/research/atari2600/#finding-67"
    },
    {
      "id": "atari2600-f66",
      "number": "66",
      "console": "atari2600",
      "title": "Bank-0 walker under-coverage: the kernel entry and dispatch writers are never decoded",
      "summary": "Concern: Iter 32 ruled out the RIOT timer as the attract-mode wedge. The dossier's next-priority hypothesis was the `JMP (mE3)` target-resolution audit (§3.3 / §8.2): are the dispatch targets `{$D083, $D0C0, …}` reachable in our lifted code?",
      "state": "active",
      "category": "CPU",
      "publicUrl": "/reforge/findings/atari2600-f66-bank-0-walker-under-coverage-the-kernel-entry-and-dispatch-writers-are-never-decoded/",
      "publicSource": "/reforge/research/atari2600/#finding-66"
    },
    {
      "id": "atari2600-f65",
      "number": "65",
      "console": "atari2600",
      "title": "RIOT timer trace diagnostic; rules out §10.2 #1 as attract-mode wedge",
      "summary": "Concern: Iter 31's audit picked dossier §10.2 #1 (\"Timer never fires → TIM64T not modeled or INTIM not decrementing → attract state machine wedged\") as the highest-prior diagnostic. Asteroids' attract mode renders only the score/lives HUD; the dossier explicitly names timer wedge as the canonical cause.",
      "state": "active",
      "category": "Evidence",
      "publicUrl": "/reforge/findings/atari2600-f65-riot-timer-trace-diagnostic-rules-out-10-2-1-as-attract-mode-wedge/",
      "publicSource": "/reforge/research/atari2600/#finding-65"
    },
    {
      "id": "atari2600-f64",
      "number": "64",
      "console": "atari2600",
      "title": "Deep-research dossier integrated; SWCHB pull-up default fix; visual ground truth captured",
      "summary": "Concern: Iter 30's READY-FOR-REVIEW was based on the analyzer's \"OK all checks passed\" verdict for Asteroids. The user opened the .exe and observed the screen renders only the score+lives HUD on a black background — no title text, no rotating asteroids, no demo animation.",
      "state": "active",
      "category": "Recompiler",
      "publicUrl": "/reforge/findings/atari2600-f64-deep-research-dossier-integrated-swchb-pull-up-default-fix-visual-ground-truth-captured/",
      "publicSource": "/reforge/research/atari2600/#finding-64"
    },
    {
      "id": "atari2600-f63",
      "number": "63",
      "console": "atari2600",
      "title": "G-A2600-005 corpus regression audit + acceptance assessment",
      "summary": "Concern: With iter 29's chassis fix in place (full-pipeline regen on every prove), validate that G-A2600-005's F8 bank-switching work hasn't broken any non-F8 ROMs in the Atari corpus. Acceptance #4 (\"fix applies to any F8-mapped cartridge\") needs to hold against the actual lifted output, not the previously-cached output.",
      "state": "active",
      "category": "Recompiler",
      "publicUrl": "/reforge/findings/atari2600-f63-g-a2600-005-corpus-regression-audit-acceptance-assessment/",
      "publicSource": "/reforge/research/atari2600/#finding-63"
    },
    {
      "id": "atari2600-f62",
      "number": "62",
      "console": "atari2600",
      "title": "Chassis: `prove_loop` runs full `RecompilationEngine` before template regen",
      "summary": "Concern: Iter 28 (Finding 61) uncovered that `prove_loop.regenerate()` refreshes only templated files (`io.c`, `ppu.c`, `apu.c`, `input.c`, `memory.{c,h}`, `debug.{h,c}`, `platform.c`) — NOT `game_main.c`, which requires the full IR/CFG/lifter/emitter pipeline. This silently invalidated every \"L2 GREEN preserved\" verdict in iters 7-27 that touched disassembler/CFG/lifter/emitter source.",
      "state": "active",
      "category": "Recompiler",
      "publicUrl": "/reforge/findings/atari2600-f62-chassis-prove-loop-runs-full-recompilationengine-before-template-regen/",
      "publicSource": "/reforge/research/atari2600/#finding-62"
    },
    {
      "id": "atari2600-f61",
      "number": "61",
      "console": "atari2600",
      "title": "Chassis: `prove_loop` does not regenerate `game_main.c`; iter 25-27 walker filter reverted",
      "summary": "Concern: Iter 27 noted that with the gap-bridge filter live, the bank-0 walker decoded only 3 instructions in the $19E0-$1A20 range, yet `game_main.c` still contained the fake-JMP region $119EA-$11A0F. This was treated as \"downstream emitter pipeline reconstructing filtered content\" and deferred to iter 28+ investigation.",
      "state": "active",
      "category": "Recompiler",
      "publicUrl": "/reforge/findings/atari2600-f61-chassis-prove-loop-does-not-regenerate-game-main-c-iter-25-27-walker-filter-reverted/",
      "publicSource": "/reforge/research/atari2600/#finding-61"
    },
    {
      "id": "atari2600-f60",
      "number": "60",
      "console": "atari2600",
      "title": "Gap-bridge for unclassified data sandwiched between classified regions",
      "summary": "Concern: Iter 26's threshold-24 filter caught the 30-byte POINTER_TABLE at ROM 0x09EA-0x0A08 right before Asteroids' fake-JMP region, but the walker still walked into bytes 0x0A08-0x0A11 (the actual sprite digit-shape data). Those bytes are *unclassified* by the analyzer — they don't form a valid pointer table after iter 24's cart-bit check, they're not padding, not printable text, not detectable as graphics on Atari 2600.",
      "state": "active",
      "category": "Recompiler",
      "publicUrl": "/reforge/findings/atari2600-f60-gap-bridge-for-unclassified-data-sandwiched-between-classified-regions/",
      "publicSource": "/reforge/research/atari2600/#finding-60"
    },
    {
      "id": "atari2600-f59",
      "number": "59",
      "console": "atari2600",
      "title": "Fall-through data threshold lowered 32 → 24",
      "summary": "Concern: Iter 25's `[DATA-AS-CODE]` diagnostic on Asteroids still emitted 5 spans of small data overlap (8-30 insns each). The 32-byte minimum-region threshold for `_is_high_confidence_data` was conservatively chosen against the 1900 → 21 collapse risk, but the resulting cutoff missed a few legitimate data tables (notably a 30-byte POINTER_TABLE at ROM 0x09EA-0x0A08, just below the bar).",
      "state": "active",
      "category": "Recompiler",
      "publicUrl": "/reforge/findings/atari2600-f59-fall-through-data-threshold-lowered-32-24/",
      "publicSource": "/reforge/research/atari2600/#finding-59"
    },
    {
      "id": "atari2600-f58",
      "number": "58",
      "console": "atari2600",
      "title": "Fall-through-only data filter in recursive descent",
      "summary": "Concern: Iter 24's tightened pointer-table heuristic gave the data analyzer enough accuracy that the `[DATA-AS-CODE]` diagnostic could pinpoint actual fall-through-into-data paths (e.g. `0x119EA-0x11A06`, 15 insns, ending 9 bytes before the fake-JMP at $1A0F).",
      "state": "active",
      "category": "Recompiler",
      "publicUrl": "/reforge/findings/atari2600-f58-fall-through-only-data-filter-in-recursive-descent/",
      "publicSource": "/reforge/research/atari2600/#finding-58"
    },
    {
      "id": "atari2600-f57",
      "number": "57",
      "console": "atari2600",
      "title": "Atari 2600 pointer-table heuristic cart-bit validity",
      "summary": "Concern: Iter 23's `[DATA-AS-CODE]` diagnostic on Asteroids reported 5 spans, the largest being `0x11000-0x11A06 (602 insns)` covering essentially the entire walked body of sub_011000. The 602-insn span was so wide it provided poor signal — the diagnostic was dominated by the data analyzer's overall false-positive rate (~98.8% of ROM classified as data on Atari 2600).",
      "state": "active",
      "category": "Memory / cartridge",
      "publicUrl": "/reforge/findings/atari2600-f57-atari-2600-pointer-table-heuristic-cart-bit-validity/",
      "publicSource": "/reforge/research/atari2600/#finding-57"
    },
    {
      "id": "atari2600-f56",
      "number": "56",
      "console": "atari2600",
      "title": "Data-as-code overlap diagnostic",
      "summary": "Concern: Iter 22's `[OUTER-LOOP-NATURAL-EXIT]` confirmed that sub_011000 returned after reading uninitialised `($0038, $0039)` to compute its trampoline target. Investigation revealed:",
      "state": "active",
      "category": "Recompiler",
      "publicUrl": "/reforge/findings/atari2600-f56-data-as-code-overlap-diagnostic/",
      "publicSource": "/reforge/research/atari2600/#finding-56"
    },
    {
      "id": "atari2600-f55",
      "number": "55",
      "console": "atari2600",
      "title": "Outer-Loop Natural-Exit Diagnostic — sub_011000 Returns Without Setting Trampoline",
      "summary": "The outer dispatch loop exited cleanly but for an unidentified reason. The loop's exit condition is `cpu->running && cpu->trampoline_target` — at least one of those was false.",
      "state": "active",
      "category": "Memory / cartridge",
      "publicUrl": "/reforge/findings/atari2600-f55-outer-loop-natural-exit-diagnostic-sub-011000-returns-without-setting-trampoline/",
      "publicSource": "/reforge/research/atari2600/#finding-55"
    },
    {
      "id": "atari2600-f54",
      "number": "54",
      "console": "atari2600",
      "title": "Scoped Seed Protection — Trace-Feedback Targets Override Fall-Through Overlap",
      "summary": "Concern: Iter 20 discovered the trace-feedback loop's convergence ceiling: `$10C0` kept recurring as a dispatch miss despite being in `extra_entry_points`. The CFG-builder couldn't make `$10C0` a function root (no instruction at the leader address).",
      "state": "active",
      "category": "Evidence",
      "publicUrl": "/reforge/findings/atari2600-f54-scoped-seed-protection-trace-feedback-targets-override-fall-through-overlap/",
      "publicSource": "/reforge/research/atari2600/#finding-54"
    },
    {
      "id": "atari2600-f53",
      "number": "53",
      "console": "atari2600",
      "title": "Trace-Feedback Loop Convergence Run — 123→238 Functions, Plateau at 194 Frames",
      "summary": "Concern: Iter 19's monotonic trace-feedback loop is operational. Iter 20 RUNS the loop to convergence within a single iter (no further source changes — just exercise the existing mechanism) and documents the convergence behavior + the next blocker.",
      "state": "active",
      "category": "Evidence",
      "publicUrl": "/reforge/findings/atari2600-f53-trace-feedback-loop-convergence-run-123-238-functions-plateau-at-194-frames/",
      "publicSource": "/reforge/research/atari2600/#finding-53"
    },
    {
      "id": "atari2600-f52",
      "number": "52",
      "console": "atari2600",
      "title": "Trace-Feedback Loop Converges — Best-Effort Dispatch + Cache Accumulator",
      "summary": "Concern: Iter 18's trace-feedback loop had two stability problems: 1. One target per run: the outer dispatch loop's default case set `cpu->running = 0` on the FIRST miss, so each prove_loop run surfaced exactly one new target.",
      "state": "active",
      "category": "Evidence",
      "publicUrl": "/reforge/findings/atari2600-f52-trace-feedback-loop-converges-best-effort-dispatch-cache-accumulator/",
      "publicSource": "/reforge/research/atari2600/#finding-52"
    },
    {
      "id": "atari2600-f51",
      "number": "51",
      "console": "atari2600",
      "title": "Runtime Trace Feedback — sub_001A07 (1655 insns) Lifted from prove_log [DISPATCH-MISS]",
      "summary": "Concern: Iter 17 restored the `[DISPATCH-MISS] target=0xXXXX` log line, surfacing concrete runtime-needed function addresses. The trace + feedback loop closes the static-vs-runtime gap iteratively.",
      "state": "active",
      "category": "Evidence",
      "publicUrl": "/reforge/findings/atari2600-f51-runtime-trace-feedback-sub-001a07-1655-insns-lifted-from-prove-log-dispatch-miss/",
      "publicSource": "/reforge/research/atari2600/#finding-51"
    },
    {
      "id": "atari2600-f50",
      "number": "50",
      "console": "atari2600",
      "title": "Dispatch-Miss Log Restores Runtime Visibility — Asteroids' Phase-2 Target Surfaced",
      "summary": "Concern: Iter 16's chassis improvements landed but Asteroids' frame count stayed at 194 with `last_addr=0x11FF3` (bank-0's JMP-indirect trampoline). The outer dispatch loop's `default` case set `cpu->running = 0` silently — no log line.",
      "state": "confirmed",
      "category": "CPU",
      "publicUrl": "/reforge/findings/atari2600-f50-dispatch-miss-log-restores-runtime-visibility-asteroids-phase-2-target-surfaced/",
      "publicSource": "/reforge/research/atari2600/#finding-50"
    },
    {
      "id": "atari2600-f49",
      "number": "49",
      "console": "atari2600",
      "title": "Bank-0 High-Mirror Canonicalisation — Asteroids Has Correct Bank-Switch Trampoline",
      "summary": "Concern: Iter 15's breakthrough revealed a new blocker at `$11BC3` — bank-0 lifted code that JMPs to `$FFF0` (the bank-switch trampoline). The runtime sets `cpu->trampoline_target = 0x1FF0` (the masked form per iter 14's emit), but no function at `$1FF0` or `$11FF0` exists in the dispatch table.",
      "state": "confirmed",
      "category": "Memory / cartridge",
      "publicUrl": "/reforge/findings/atari2600-f49-bank-0-high-mirror-canonicalisation-asteroids-has-correct-bank-switch-trampoline/",
      "publicSource": "/reforge/research/atari2600/#finding-49"
    },
    {
      "id": "atari2600-f48",
      "number": "48",
      "console": "atari2600",
      "title": "Masked Branch-Target Seeds Promote $1B24 etc. to Function Roots — Asteroids RUNS 194 FRAMES",
      "summary": "🎯 BREAKTHROUGH ITER. After 11 iters (4-14) chipping at F8 bank-switching infrastructure, iter 15 lands the missing piece: cross-bank-jump targets get their masked-and-bank-mirrored form added as CFG entry points without rewriting the source instructions' branch_targets.",
      "state": "active",
      "category": "Memory / cartridge",
      "publicUrl": "/reforge/findings/atari2600-f48-masked-branch-target-seeds-promote-1b24-etc-to-function-roots-asteroids-runs-194-frames/",
      "publicSource": "/reforge/research/atari2600/#finding-48"
    },
    {
      "id": "atari2600-f47",
      "number": "47",
      "console": "atari2600",
      "title": "Direct-JMP Unresolved Routes Through Trampoline (Masked)",
      "summary": "Concern: Iter 13's overlap resolver exposed an unresolved direct JMP at `$11BAE` (`JMP $DB24`, bytes `4C 24 DB`). Capstone returns `branch_target=$DB24` — the raw 16-bit operand.",
      "state": "active",
      "category": "Memory / cartridge",
      "publicUrl": "/reforge/findings/atari2600-f47-direct-jmp-unresolved-routes-through-trampoline-masked/",
      "publicSource": "/reforge/research/atari2600/#finding-47"
    },
    {
      "id": "atari2600-f46",
      "number": "46",
      "console": "atari2600",
      "title": "Post-Scan Instruction Overlap Resolver — Misalignment Cascade Suppressed",
      "summary": "Concern: Iter 12's interior-address filter caught misaligned const-prop seeds at seed time, but seeds in unvisited regions still passed through and their fall-through walks created decode cascades. Bank-0 virtual space had 189 overlapping instruction pairs (~30% of decoded code).",
      "state": "active",
      "category": "Recompiler",
      "publicUrl": "/reforge/findings/atari2600-f46-post-scan-instruction-overlap-resolver-misalignment-cascade-suppressed/",
      "publicSource": "/reforge/research/atari2600/#finding-46"
    },
    {
      "id": "atari2600-f45",
      "number": "45",
      "console": "atari2600",
      "title": "Const-Prop Interior-Address Filter — Partial Misalignment Suppression",
      "summary": "Concern: Iter 11 surfaced a misalignment cascade in bank-0 virtual address space: bank-0's `sub_011B00` decoded a stray `0x02` JAM at `$11B13` (mid-instruction of the `STA $02` at bank-0 `$1B12`), and `platform_exit(cpu)` for that JAM is now Asteroids' visible exit point. Iter 12 attacks the cascade at its source: the multi-path const-prop's `(lo × hi)` cross-product over-seeds — for Asteroids' bank-0 walk, the const-prop discovers candidate targets like…",
      "state": "active",
      "category": "Timing / bus",
      "publicUrl": "/reforge/findings/atari2600-f45-const-prop-interior-address-filter-partial-misalignment-suppression/",
      "publicSource": "/reforge/research/atari2600/#finding-45"
    },
    {
      "id": "atari2600-f44",
      "number": "44",
      "console": "atari2600",
      "title": "Bank-0 Walk Receives Const-Prop Targets — Asteroids Hits Bank-0 Code at Runtime",
      "summary": "Concern: Iter 10 surfaced a critical bug. The lifter's `sub_001B00` had BANK 1's bytes (`FC 85 F4 A2 ...`) at CPU `$1B00`, not bank-0's (`A9 03 85 25 ...`).",
      "state": "active",
      "category": "Memory / cartridge",
      "publicUrl": "/reforge/findings/atari2600-f44-bank-0-walk-receives-const-prop-targets-asteroids-hits-bank-0-code-at-runtime/",
      "publicSource": "/reforge/research/atari2600/#finding-44"
    },
    {
      "id": "atari2600-f43",
      "number": "43",
      "console": "atari2600",
      "title": "JMP-Indirect Uses Outer Dispatch Loop (Not Nested C Call)",
      "summary": "Concern: Iter 6 implemented JMP-indirect via a synchronous `reforge_dispatch_indirect_jmp(cpu, target)` helper that CALLED the matched function and returned. That's wrong semantics — real 6502 hardware NEVER returns from a `JMP $XXXX`: control flow transfers permanently.",
      "state": "active",
      "category": "CPU",
      "publicUrl": "/reforge/findings/atari2600-f43-jmp-indirect-uses-outer-dispatch-loop-not-nested-c-call/",
      "publicSource": "/reforge/research/atari2600/#finding-43"
    },
    {
      "id": "atari2600-f42",
      "number": "42",
      "console": "atari2600",
      "title": "atari2600 Entry-Point Selection — Bank-1 Reset Vector, Not Lowest-Address Function",
      "summary": "Concern: Iter 8's multi-path const-prop over-seeded function roots — the cross-product of immediate writers to ($F7, $F8) included combinations that don't correspond to real subroutine entries. Most were harmless extras (they decode some bytes, the lifter wraps them in a function, no other code references them).",
      "state": "active",
      "category": "Memory / cartridge",
      "publicUrl": "/reforge/findings/atari2600-f42-atari2600-entry-point-selection-bank-1-reset-vector-not-lowest-address-function/",
      "publicSource": "/reforge/research/atari2600/#finding-42"
    },
    {
      "id": "atari2600-f41",
      "number": "41",
      "console": "atari2600",
      "title": "Multi-Path ZP-Indirect JMP Const-Propagation",
      "summary": "Concern: Iter 7's single-path const-prop walked backward from one JMP site in address order and took the first matching `LDA #imm / STA $ZP` pair. Iter 8 generalises: enumerate EVERY immediate LDA writer for `$ZP` and `$ZP+1`, cross-product the (lo, hi) sets, seed all targets that map to ROM addresses.",
      "state": "active",
      "category": "Recompiler",
      "publicUrl": "/reforge/findings/atari2600-f41-multi-path-zp-indirect-jmp-const-propagation/",
      "publicSource": "/reforge/research/atari2600/#finding-41"
    },
    {
      "id": "atari2600-f40",
      "number": "40",
      "console": "atari2600",
      "title": "ZP-Indirect JMP Const-Propagation — Asteroids Discovers 6 More Functions",
      "summary": "Concern: Iter 6 surfaced the runtime indirect-JMP target (0xD43C → bank-0 $143C) but no function was registered at $143C, so the dispatch helper exited cleanly with the target value in the log. The static lifter never decoded $143C because the recursive descent scanner only reached code via direct control flow + the explicit vector entries; bank-1's `JMP ($00F7)` is unresolvable through static analysis as-implemented (the existing `_resolve_6502_indirect`…",
      "state": "active",
      "category": "Recompiler",
      "publicUrl": "/reforge/findings/atari2600-f40-zp-indirect-jmp-const-propagation-asteroids-discovers-6-more-functions/",
      "publicSource": "/reforge/research/atari2600/#finding-40"
    },
    {
      "id": "atari2600-f39",
      "number": "39",
      "console": "atari2600",
      "title": "JMP-Indirect-via-ZP Runtime Dispatch — Asteroids Sees the Target",
      "summary": "Concern: Iter 3 + iter 5 built the F8 bank-switch write/read sides. The third runtime link — control flow through `JMP ($00F7)` at $FFF3 — was a static-lift dead-end: the lifter emitted `/* jump to unresolved target bb_0000F7 */ return;` for any indirect JMP, because capstone's `_parse_branch_target` regex extracts `$F7` from `($F7)` and the lifter encodes it as label `bb_0000F7` — which is never a valid label (zero-page is RAM, not code).",
      "state": "active",
      "category": "CPU",
      "publicUrl": "/reforge/findings/atari2600-f39-jmp-indirect-via-zp-runtime-dispatch-asteroids-sees-the-target/",
      "publicSource": "/reforge/research/atari2600/#finding-39"
    },
    {
      "id": "atari2600-f38",
      "number": "38",
      "console": "atari2600",
      "title": "F8 Bank-Aware mem_read8 — Operand Fetches Honor Active Bank",
      "summary": "Concern: Iter 3 landed `reforge_active_bank` + STA $1FF8/$1FF9 hotspot tracking. Iter 4 made the static disassembler walk bank 0.",
      "state": "active",
      "category": "Memory / cartridge",
      "publicUrl": "/reforge/findings/atari2600-f38-f8-bank-aware-mem-read8-operand-fetches-honor-active-bank/",
      "publicSource": "/reforge/research/atari2600/#finding-38"
    },
    {
      "id": "atari2600-f37",
      "number": "37",
      "console": "atari2600",
      "title": "F8 Bank 0 Static Disassembly — Asteroids Walks Both Banks",
      "summary": "Concern: Iter 1+2 made the disassembler F8-aware but only ever walked the BOOT bank (bank 1) — because `Atari2600Mapper.cpu_to_rom` returned bank-1 bytes for any cart-window address, including bank 0's reset vector at $1591. Bank 0's instructions were never decoded, so the IR/CFG/C emitter had no visibility into post-switch code.",
      "state": "active",
      "category": "Timing / bus",
      "publicUrl": "/reforge/findings/atari2600-f37-f8-bank-0-static-disassembly-asteroids-walks-both-banks/",
      "publicSource": "/reforge/research/atari2600/#finding-37"
    },
    {
      "id": "atari2600-f36",
      "number": "36",
      "console": "atari2600",
      "title": "F8 Runtime Bank-Switch State + Hotspot Handler in Emitter",
      "summary": "Concern: Iter 1+2 made the static analyzer + disassembler F8-aware. Iter 3 lands the RUNTIME side: a `reforge_active_bank` global state that gets updated when generated code writes to the F8 bank-switch hotspots `$FFF8` (select bank 0) or `$FFF9` (select bank 1).",
      "state": "active",
      "category": "Timing / bus",
      "publicUrl": "/reforge/findings/atari2600-f36-f8-runtime-bank-switch-state-hotspot-handler-in-emitter/",
      "publicSource": "/reforge/research/atari2600/#finding-36"
    },
    {
      "id": "atari2600-f35",
      "number": "35",
      "console": "atari2600",
      "title": "F8 Cartridge Disassembler Mapper — Asteroids Walks Actual Bank-1 Code",
      "summary": "Concern: Iter 1 (Finding 34) made the vector tracer F8-aware but the `Atari2600Mapper` in `disassembler/recursive_descent.py:99-127` still treated the ROM as a single 4 KB blob. Walking from bank 1's reset vector `$19DA` read bank 0's data bytes at file offset `$9DA` (because `addr - 0x1000 = $9DA` always lands in bank 0).",
      "state": "active",
      "category": "Memory / cartridge",
      "publicUrl": "/reforge/findings/atari2600-f35-f8-cartridge-disassembler-mapper-asteroids-walks-actual-bank-1-code/",
      "publicSource": "/reforge/research/atari2600/#finding-35"
    },
    {
      "id": "atari2600-f34",
      "number": "34",
      "console": "atari2600",
      "title": "Asteroids F8 Bank-Switching — Diagnosis + Vector Tracer Becomes F8-Aware",
      "summary": "Game: Asteroids (NA), 8 KB ROM Goal: G-A2600-005 (Asteroids F8 bank switching) Concern: Diagnose why Asteroids stays at L0 (build succeeds; runtime returns from `game_entry` at frame 0 with `last_addr=0x1A9C`); establish the F8 cartridge-format signal in the analyzer so downstream lifter / engine work has a concrete trigger.",
      "state": "active",
      "category": "Evidence",
      "publicUrl": "/reforge/findings/atari2600-f34-asteroids-f8-bank-switching-diagnosis-vector-tracer-becomes-f8-aware/",
      "publicSource": "/reforge/research/atari2600/#finding-34"
    },
    {
      "id": "atari2600-f33",
      "number": "33",
      "console": "atari2600",
      "title": "Layer 3 TAS Skeleton Bootstrap",
      "summary": "Concern: G-A2600-001's acceptance criterion #2 (\"TAS-driven 30-frame wall-hold: pacX delta within 1 pixel of expected\") needs a `tests/tas/atari2600/Pac_Man.tas.json` file conforming to the Layer 3 schema documented in `[internal specification]`. Until the file exists, `/prove`'s Layer 3 path falls back to the universal coupling smoke (drive joystick 30 frames each direction, assert ≥1 position delta) — enough for L3 but not L4.",
      "state": "active",
      "category": "Input / mechanics",
      "publicUrl": "/reforge/findings/atari2600-f33-layer-3-tas-skeleton-bootstrap/",
      "publicSource": "/reforge/research/atari2600/#finding-33"
    },
    {
      "id": "atari2600-f32",
      "number": "32",
      "console": "atari2600",
      "title": "L2 Golden Manifest Now Self-Describing — `captured_at` + `generator_hash_at_capture` Filled From Real Sources",
      "summary": "Concern: Iter 7 captured the first L2 golden manifest but the `captured_at` and `generator_hash_at_capture` fields were placeholder TODOs (pre-existing oracle-infrastructure debt). R-REBASELINE-PROVENANCE-1 can't validate a rebaseline without real provenance metadata, and a manifest with `\"TODO-utc\"` defeats the point of the schema.",
      "state": "active",
      "category": "Memory / cartridge",
      "publicUrl": "/reforge/findings/atari2600-f32-l2-golden-manifest-now-self-describing-captured-at-generator-hash-at-capture-filled-from/",
      "publicSource": "/reforge/research/atari2600/#finding-32"
    },
    {
      "id": "atari2600-f31",
      "number": "31",
      "console": "atari2600",
      "title": "Layer 4 Re-Fire on FRESH Data",
      "summary": "Game: Pac-Man (NA) Goal: G-A2600-001 (Pac-Man wall collision correctness) Concern: Iter 3's Layer 4 agent verdict (`broken@0.95`) was poisoned by stale PPMs (Finding 30). Iter 7 re-fires the agent oracle on the FRESH screenshots from the current build, and captures the L2 golden manifest now that `visual_oracle._default_run_dir()` resolves to the correct fresh directory.",
      "state": "active",
      "category": "Recompiler",
      "publicUrl": "/reforge/findings/atari2600-f31-layer-4-re-fire-on-fresh-data/",
      "publicSource": "/reforge/research/atari2600/#finding-31"
    },
    {
      "id": "atari2600-f30",
      "number": "30",
      "console": "atari2600",
      "title": "Stale `screenshots/` Cache Caused Phantom Palette Bug (Findings 27-29 Premise Retracted)",
      "summary": "Game: Pac-Man (NA) Goal: G-A2600-001 (Pac-Man wall collision correctness) Concern: Iter 6 added multi-scanline `[PALETTE f%u sl%d]` dump (sl=20/60/100/140/180) in the f=1400..1500 window. The data should have shown which scanlines transitioned.",
      "state": "disproven",
      "category": "Evidence",
      "publicUrl": "/reforge/findings/atari2600-f30-stale-screenshots-cache-caused-phantom-palette-bug-findings-27-29-premise-retracted/",
      "publicSource": "/reforge/research/atari2600/#finding-30"
    },
    {
      "id": "atari2600-f29",
      "number": "29",
      "console": "atari2600",
      "title": "Mid-Screen Palette Sample sl=100 Is Stable Across the f=1400..f=1500 Transition Window",
      "summary": "Game: Pac-Man (NA) Goal: G-A2600-001 (Pac-Man wall collision correctness) Concern: Iter 4 (Finding 28) bracketed the palette transition to f=1400..f=1500. Iter 5 instruments per-5-frame palette samples in that window to identify the exact transition frame.",
      "state": "active",
      "category": "Video",
      "publicUrl": "/reforge/findings/atari2600-f29-mid-screen-palette-sample-sl-100-is-stable-across-the-f-1400-f-1500-transition-window/",
      "publicSource": "/reforge/research/atari2600/#finding-29"
    },
    {
      "id": "atari2600-f28",
      "number": "28",
      "console": "atari2600",
      "title": "Pac-Man Palette Transition Bracketed to f=1400..f=1500",
      "summary": "Game: Pac-Man (NA) Goal: G-A2600-001 (Pac-Man wall collision correctness) Status: ACTIVE (overriding prior iter 3 BLOCKED: agent-divergence per autonomous-mode policy — agent divergence is signal to investigate, not stop) Concern: narrow the f=800..f=1500 palette-transition window (Finding 27) so iter 5 has a 10-frame target instead of a 700-frame fishing expedition.",
      "state": "active",
      "category": "Video",
      "publicUrl": "/reforge/findings/atari2600-f28-pac-man-palette-transition-bracketed-to-f-1400-f-1500/",
      "publicSource": "/reforge/research/atari2600/#finding-28"
    },
    {
      "id": "atari2600-f27",
      "number": "27",
      "console": "atari2600",
      "title": "Layer 4 Agent Oracle — Palette Shift Between f=800 and f=1500",
      "summary": "Game: Pac-Man (NA) Goal: G-A2600-001 (Pac-Man wall collision correctness) Concern: Iter 3 fired the Layer 4 sub-agent oracle (`/vision`-style) on the four standard PPM screenshots (f=50/400/800/1500) to independently verify Finding 26's claim that Pac-Man is at the top maze row when `pacY=$00`. The agent classified the build as `broken` (0.95 confidence) and flagged a palette-shift artifact that Finding 26 did not catch.",
      "state": "active",
      "category": "Evidence",
      "publicUrl": "/reforge/findings/atari2600-f27-layer-4-agent-oracle-palette-shift-between-f-800-and-f-1500/",
      "publicSource": "/reforge/research/atari2600/#finding-27"
    },
    {
      "id": "atari2600-f26",
      "number": "26",
      "console": "atari2600",
      "title": "wall_collision Oracle False Positive — pacY=$00 Is The In-Maze Top Row",
      "summary": "Game: Pac-Man (NA) Goal: G-A2600-001 (Pac-Man wall collision correctness) Concern: the `wall_collision` oracle in `phase2/console_loop.py` was failing on every 1800-frame Pac-Man run with `pacY=$00 = off-maze top boundary`. Iter 1 (Finding 25) added Y-write telemetry on the assumption that the writer at `$FA23` was bypassing a missing maze-top guard.",
      "state": "active",
      "category": "Evidence",
      "publicUrl": "/reforge/findings/atari2600-f26-wall-collision-oracle-false-positive-pacy-00-is-the-in-maze-top-row/",
      "publicSource": "/reforge/research/atari2600/#finding-26"
    },
    {
      "id": "atari2600-f25",
      "number": "25",
      "console": "atari2600",
      "title": "Pac-Man Y-Write Old/New/Frame Telemetry — Maze-Boundary Bypass Happens 13 Frames Before Oracle Sample",
      "summary": "Game: Pac-Man (NA) Goal: G-A2600-001 (Pac-Man wall collision correctness) Concern: add `yOld/yNew/yFrame` telemetry to `[MOV]` trace + `wall_collision` oracle failure detail so the Y-write that brings `pacY` to `$00` is observable, not just the post-write sample.",
      "state": "active",
      "category": "Evidence",
      "publicUrl": "/reforge/findings/atari2600-f25-pac-man-y-write-old-new-frame-telemetry-maze-boundary-bypass-happens-13-frames-before-or/",
      "publicSource": "/reforge/research/atari2600/#finding-25"
    },
    {
      "id": "atari2600-f24",
      "number": "24",
      "console": "atari2600",
      "title": "PHA/PHA/RTS Jump-Table Dispatch — Lifter Unblocks Missile_Command + River_Raid",
      "summary": "Games affected: Missile Command (dispatch by game-mode table at $F597/$F598, 8 targets), River Raid (dispatch by game-stage table at $FBEF/$FDF6, 10 targets). Both previously terminated at frame 0 with `game_entry returned (running=1, frame=0, last_addr=0x{F596,1139})`.",
      "state": "confirmed",
      "category": "CPU",
      "publicUrl": "/reforge/findings/atari2600-f24-pha-pha-rts-jump-table-dispatch-lifter-unblocks-missile-command-river-raid/",
      "publicSource": "/reforge/research/atari2600/#finding-24"
    },
    {
      "id": "atari2600-f23",
      "number": "23",
      "console": "atari2600",
      "title": "Analyzer False-FAIL Cleanup — 6 ROMs Reclassified GREEN",
      "summary": "Games affected: Combat, Adventure, Frogger, Breakout, Pitfall, Space_Invaders (plus existing Pac-Man GREEN). Symptom: prove_loop exit codes misaligned with visual ground truth.",
      "state": "confirmed",
      "category": "Memory / cartridge",
      "publicUrl": "/reforge/findings/atari2600-f23-analyzer-false-fail-cleanup-6-roms-reclassified-green/",
      "publicSource": "/reforge/research/atari2600/#finding-23"
    },
    {
      "id": "atari2600-f16",
      "number": "16",
      "console": "atari2600",
      "title": "Writer-PC Stomp Bug Invalidated 6 Sessions of $82 Attribution",
      "summary": "Game: Pac-Man (NA) Correction: Finding 15 said the $5F→$6E progression came from \"`$F857 (pacman_state_writer)`.\" That label has been wrong since review cycle introduced the writer-PC capture infrastructure. `$F857` is `AND $0282` — Pac-Man's per-frame SWCHB COLOR/B&W switch read.",
      "state": "active",
      "category": "Recompiler",
      "publicUrl": "/reforge/findings/atari2600-f16-writer-pc-stomp-bug-invalidated-6-sessions-of-82-attribution/",
      "publicSource": "/reforge/research/atari2600/#finding-16"
    },
    {
      "id": "atari2600-f15",
      "number": "15",
      "console": "atari2600",
      "title": "$82 Progression Is the Attract-Demo Timer, Not Gameplay",
      "summary": "Game: Pac-Man (NA) Correction: Finding 14 above framed the 5000f $82 progression to `$6B` as five new states beyond the 09aa best of $66. This was wrong.",
      "state": "active",
      "category": "Timing / bus",
      "publicUrl": "/reforge/findings/atari2600-f15-82-progression-is-the-attract-demo-timer-not-gameplay/",
      "publicSource": "/reforge/research/atari2600/#finding-15"
    },
    {
      "id": "atari2600-f14",
      "number": "14",
      "console": "atari2600",
      "title": "Four TIA Primitive Audits — All Pass",
      "summary": "Game: Pac-Man (NA) Trigger: Third-party review flagged four TIA contracts as suspect: RESPx/HMOVE timing, VDELP cross-latch, collision latch/clear, and SWCHB/$82 gating. After 09af landed unified TIA observation + generator hash gating + writer-PC symbolization, every audit was re-run against falsifiable data from the unified observation layer.",
      "state": "confirmed",
      "category": "Timing / bus",
      "publicUrl": "/reforge/findings/atari2600-f14-four-tia-primitive-audits-all-pass/",
      "publicSource": "/reforge/research/atari2600/#finding-14"
    },
    {
      "id": "atari2600-f13",
      "number": "13",
      "console": "atari2600",
      "title": "$F882 INPT4 Read via TIA Mirror $3C",
      "summary": "This is NOT a collision check — it's checking if the fire button is pressed during gameplay. The BPL at $F888 branches when fire is pressed (INPT4 bit 7 = 0), triggering game state reset.",
      "state": "active",
      "category": "Timing / bus",
      "publicUrl": "/reforge/findings/atari2600-f13-f882-inpt4-read-via-tia-mirror-3c/",
      "publicSource": "/reforge/research/atari2600/#finding-13"
    },
    {
      "id": "atari2600-f12",
      "number": "12",
      "console": "atari2600",
      "title": "Mid-Scanline Collision Timing Critical for Death Detection",
      "summary": "Game: Pac-Man (NA) Symptom: Ghosts never kill Pac-Man, can't eat frightened ghosts, even though CXPPMM=$80 at end of frame. Root Cause: Pac-Man reads CXPPMM at $F5D9 during the display kernel, right after writing GRP0 for the current ghost.",
      "state": "active",
      "category": "Timing / bus",
      "publicUrl": "/reforge/findings/atari2600-f12-mid-scanline-collision-timing-critical-for-death-detection/",
      "publicSource": "/reforge/research/atari2600/#finding-12"
    },
    {
      "id": "atari2600-f11",
      "number": "11",
      "console": "atari2600",
      "title": "VSYNC Guard Too Conservative — Pac-Man Writes VSYNC at sl=193",
      "summary": "Game: Pac-Man (NA) Bug: Scanline count fluctuated: 259, 263, 265, 271, 288, 326, 511 per frame instead of ~193. Root Cause: VSYNC handler guard required `scanline_count >= 200`.",
      "state": "active",
      "category": "Timing / bus",
      "publicUrl": "/reforge/findings/atari2600-f11-vsync-guard-too-conservative-pac-man-writes-vsync-at-sl-193/",
      "publicSource": "/reforge/research/atari2600/#finding-11"
    },
    {
      "id": "atari2600-f10",
      "number": "10",
      "console": "atari2600",
      "title": "Variable RESP0 Sprite Positioning Confirmed Working",
      "summary": "Game: Pac-Man (NA) Investigation: Debug output showed P0=40, P1=51 constant. Initially suspected RESP0 always strobed at same cycle.",
      "state": "confirmed",
      "category": "Video",
      "publicUrl": "/reforge/findings/atari2600-f10-variable-resp0-sprite-positioning-confirmed-working/",
      "publicSource": "/reforge/research/atari2600/#finding-10"
    },
    {
      "id": "atari2600-f9",
      "number": "9",
      "console": "atari2600",
      "title": "MSVC /O2 Miscompiles io.c",
      "summary": "Game: Pac-Man (NA) Bug: SIGSEGV crash at PC=$FBD5 in sub_00FBAD (movement calculation routine) — only in Release builds. Root Cause: MSVC /O2 optimizer miscompiles the complex switch/case logic in io.c with volatile pointer accesses.",
      "state": "active",
      "category": "Recompiler",
      "publicUrl": "/reforge/findings/atari2600-f9-msvc-o2-miscompiles-io-c/",
      "publicSource": "/reforge/research/atari2600/#finding-9"
    },
    {
      "id": "atari2600-f8",
      "number": "8",
      "console": "atari2600",
      "title": "TIA Read/Write Register Overlap — INPT4 Clobbered by REFP1",
      "summary": "Game: Pac-Man (NA) Bug: Game state ($82) stuck at 0x00 (attract mode) — never entering play mode. Root Cause: TIA read register INPT4 ($0C, fire button) and TIA write register REFP1 ($0C, player 1 reflect) share address $0C.",
      "state": "active",
      "category": "Timing / bus",
      "publicUrl": "/reforge/findings/atari2600-f8-tia-read-write-register-overlap-inpt4-clobbered-by-refp1/",
      "publicSource": "/reforge/research/atari2600/#finding-8"
    },
    {
      "id": "atari2600-f6",
      "number": "6",
      "console": "atari2600",
      "title": "Input Mapping Verified Working",
      "summary": "Game: Pac-Man (NA) Confirmation: SWCHA correctly reads joystick state (saw SWCHA=$BF during test = LEFT pressed). Input handler maps: Arrow keys→SWCHA, Z→INPT4 fire, Enter→SWCHB RESET, RShift→SWCHB SELECT.",
      "state": "confirmed",
      "category": "Input / mechanics",
      "publicUrl": "/reforge/findings/atari2600-f6-input-mapping-verified-working/",
      "publicSource": "/reforge/research/atari2600/#finding-6"
    },
    {
      "id": "atari2600-f5",
      "number": "5",
      "console": "atari2600",
      "title": "Game State Oscillation — RAM[$82] Root Cause",
      "summary": "Game: Pac-Man (NA) Symptom: RAM[$82] (game state: 0=attract, 1=playing) oscillates between 0 and 1 every few frames. Game never enters stable play mode.",
      "state": "confirmed",
      "category": "Timing / bus",
      "publicUrl": "/reforge/findings/atari2600-f5-game-state-oscillation-ram-82-root-cause/",
      "publicSource": "/reforge/research/atari2600/#finding-5"
    },
    {
      "id": "atari2600-f3",
      "number": "3",
      "console": "atari2600",
      "title": "RMW Write-Backs to $00 Cause Spurious VSYNC",
      "summary": "Game: Pac-Man (NA) Symptom: Graphics \"jumping and streaking\" — display constantly resetting mid-frame. Root cause: Pac-Man uses `ROR $00` (Read-Modify-Write on collision register/VSYNC address) for RNG.",
      "state": "active",
      "category": "Timing / bus",
      "publicUrl": "/reforge/findings/atari2600-f3-rmw-write-backs-to-00-cause-spurious-vsync/",
      "publicSource": "/reforge/research/atari2600/#finding-3"
    },
    {
      "id": "atari2600-f7",
      "number": "7",
      "console": "atari2600",
      "title": "Audio System Works",
      "summary": "Game: Pac-Man (NA) Confirmation: Manual playback confirmed that sounds and music were audible. Audio registers (AUDC0/1, AUDF0/1, AUDV0/1) at TIA addresses $15-$1A are correctly written through the default io_write path.",
      "state": "confirmed",
      "category": "Audio",
      "publicUrl": "/reforge/findings/atari2600-f7-audio-system-works/",
      "publicSource": "/reforge/research/atari2600/#finding-7"
    },
    {
      "id": "atari2600-f4",
      "number": "4",
      "console": "atari2600",
      "title": "LFSR Collision Simulation for Multi-ROR RNG",
      "summary": "Game: Pac-Man (NA) Symptom: Game state never transitioned (stuck in attract mode) when collision registers returned static values. Root cause: Pac-Man uses two consecutive `ROR $00` instructions to extract 2 carry bits from the collision register.",
      "state": "active",
      "category": "Input / mechanics",
      "publicUrl": "/reforge/findings/atari2600-f4-lfsr-collision-simulation-for-multi-ror-rng/",
      "publicSource": "/reforge/research/atari2600/#finding-4"
    },
    {
      "id": "atari2600-f2",
      "number": "2",
      "console": "atari2600",
      "title": "6502 Flag Instructions Must NOT Modify Carry",
      "summary": "Game: Pac-Man (NA) Symptom: No player movement, no AI, no game state transitions. Game logic branches based on carry flag were always taking the same path.",
      "state": "active",
      "category": "CPU",
      "publicUrl": "/reforge/findings/atari2600-f2-6502-flag-instructions-must-not-modify-carry/",
      "publicSource": "/reforge/research/atari2600/#finding-2"
    },
    {
      "id": "atari2600-f1",
      "number": "1",
      "console": "atari2600",
      "title": "TIA Write/Read Address Overlap Destroys State",
      "summary": "Game: Pac-Man (NA) Symptom: CXCLR ($2C write) was zeroing TIA write registers (NUSIZ0/1, COLUP0/1) stored at cpu->memory[$00-$07], because collision registers (CXM0P-CXPPMM, read at $00-$07) shared the same memory locations. Root cause: On real TIA silicon, the READ address space ($00-$0D) and WRITE address space ($00-$2C) are physically separate circuits that share the same pin addresses.",
      "state": "active",
      "category": "Timing / bus",
      "publicUrl": "/reforge/findings/atari2600-f1-tia-write-read-address-overlap-destroys-state/",
      "publicSource": "/reforge/research/atari2600/#finding-1"
    },
    {
      "id": "atari2600-f91",
      "number": "91",
      "console": "atari2600",
      "title": "Corpus ROM-name matcher missed space-named dumps; three ROMs ran 7-week-stale lifts",
      "summary": "`prove_loop.find_rom` tried underscore/hyphen variants only, so corpus dirs `Space_Invaders` / `Missile_Command` / `River_Raid` never matched \"Space Invaders (NA).a26\" / \"Missile Command (NA).a26\" / \"River Raid (NA).a26\" — full regen silently fell back to template-only, and those three ran `game_main.c` lifts dated April 23 (predating ~50 iterations of lifter fixes) while every prove run reported success.",
      "state": "active",
      "category": "Evidence",
      "publicUrl": "/reforge/findings/atari2600-f91-corpus-rom-name-matcher-missed-space-named-dumps-three-roms-ran-7-week-stale-lifts/",
      "publicSource": "/reforge/research/atari2600/#finding-91"
    },
    {
      "id": "atari2600-f90",
      "number": "90",
      "console": "atari2600",
      "title": "Visual-evidence pipeline was broken corpus-wide: screenshots written to a shared CWD and read stale",
      "summary": "`prove_loop.run_headless` launched the exe without `cwd`, so the generated runtime's `frame_NNNN.ppm` writes landed in whatever directory prove_loop was launched from — every corpus ROM overwrote the same repo-root set, and the per-ROM `build/Release/` dirs that `console_loop` globs for visual evidence never received fresh screenshots. The classifier then silently read months-stale files (Pac-Man's \"screenshot evidence\" dated April 9; Asteroids' May 23)…",
      "state": "active",
      "category": "Evidence",
      "publicUrl": "/reforge/findings/atari2600-f90-visual-evidence-pipeline-was-broken-corpus-wide-screenshots-written-to-a-shared-cwd-and-/",
      "publicSource": "/reforge/research/atari2600/#finding-90"
    },
    {
      "id": "atari2600-f89",
      "number": "89",
      "console": "atari2600",
      "title": "BRK is a walk terminator on the 6507 (padding fall-through blocks real routine entries)",
      "summary": "The 6507 has no IRQ/NMI wired; games never execute BRK, so every $00 byte the walker meets is data or inter-routine padding. Falling through BRK chained the walk INTO padding runs, and a 2-byte BRK decode ending mid-padding spanned the first byte of the REAL routine after the padding — the overlap resolver then dropped the (unprotected) seeded decode as misaligned.",
      "state": "active",
      "category": "Recompiler",
      "publicUrl": "/reforge/findings/atari2600-f89-brk-is-a-walk-terminator-on-the-6507-padding-fall-through-blocks-real-routine-entries/",
      "publicSource": "/reforge/research/atari2600/#finding-89"
    },
    {
      "id": "atari2600-f88",
      "number": "88",
      "console": "atari2600",
      "title": "Analyzer game-specific checks must be gated per title (the Pac-Man RAM-map phantom)",
      "summary": "The `[MOV]` trace prints $B0/$BA/$BB (Pac-Man's entity map) on EVERY Atari ROM, and the analyzer escalated \"1 unique position\" to FAIL for all titles. Frogger — visibly playing in screenshots (river, logs, cars, frog) — carried a phantom \"Player position FROZEN\" FAIL for weeks; same for Space Invaders, Missile Command, Breakout.",
      "state": "active",
      "category": "Memory / cartridge",
      "publicUrl": "/reforge/findings/atari2600-f88-analyzer-game-specific-checks-must-be-gated-per-title-the-pac-man-ram-map-phantom/",
      "publicSource": "/reforge/research/atari2600/#finding-88"
    },
    {
      "id": "atari2600-f87",
      "number": "87",
      "console": "atari2600",
      "title": "F8 cross-bank const-prop: bank-blind interior veto + unexported overlay targets (Asteroids DISPATCH-MISS 0x10C0)",
      "summary": "Two compounding lift bugs kept Asteroids' kernel dispatch destinations unrooted. (A) `_detect_zp_indirect_jmp_constprop` Phase 3 built its misalignment veto from the MERGED instruction dict during the cross-bank overlay — bank-1 alias instructions at the same 13-bit window addresses vetoed clean bank-0 targets ($D0C0 masked 0x10C0 was \"interior\" of a bank-1 byte span; runtime exited at f=194 with DISPATCH-MISS target=0x10C0).",
      "state": "active",
      "category": "CPU",
      "publicUrl": "/reforge/findings/atari2600-f87-f8-cross-bank-const-prop-bank-blind-interior-veto-unexported-overlay-targets-asteroids-d/",
      "publicSource": "/reforge/research/atari2600/#finding-87"
    },
    {
      "id": "atari2600-f86",
      "number": "86",
      "console": "atari2600",
      "title": "Cycle-driven TIA beam model: scanlines advance every 76 CPU cycles, not only at WSYNC",
      "summary": "The snapshot pipeline captured TIA state only in the WSYNC handler. Kernels that race the beam without WSYNC (Space Invaders' 6-invader rows: mid-scanline GRP0/GRP1 rewrites with PHA/PLA cycle padding, 2 scanlines per iteration, zero WSYNCs; every title's INTIM-paced VBLANK/overscan) starved the snapshot ring (SI: 77 snapshots vs 262 real lines) and the screenshot path extrapolated the last captured snapshot down the screen — SI's lower 2/3 was a solid…",
      "state": "active",
      "category": "Timing / bus",
      "publicUrl": "/reforge/findings/atari2600-f86-cycle-driven-tia-beam-model-scanlines-advance-every-76-cpu-cycles-not-only-at-wsync/",
      "publicSource": "/reforge/research/atari2600/#finding-86"
    },
    {
      "id": "atari2600-f85",
      "number": "85",
      "console": "atari2600",
      "title": "Emitter dropped the entry-block goto when the function entry is not the lowest-address block (Missile Command + River…",
      "summary": "`emitter_c.py emit_function` emitted blocks address-sorted and jumped to the entry label only when blocks[0] was a \"stale RTS\" stub — otherwise execution FELL INTO blocks[0]. A 6502 control transfer (JSR, PHA/PHA/RTS dispatch, indirect trampoline) always begins at the target address, so the fall-in is never correct.",
      "state": "confirmed",
      "category": "Recompiler",
      "publicUrl": "/reforge/findings/atari2600-f85-emitter-dropped-the-entry-block-goto-when-the-function-entry-is-not-the-lowest-address-b/",
      "publicSource": "/reforge/research/atari2600/#finding-85"
    },
    {
      "id": "atari2600-f84",
      "number": "84",
      "console": "atari2600",
      "title": "TIA VSYNC decodes only D1; the `val <= 0x03` guard rejected hardware-legal assertions (Breakout $FF, River Raid $82)",
      "summary": "Real TIA VSYNC latches D1 only. Breakout strobes VSYNC via `STX` with X=$FF (triple-duty: NUSIZ=$FF quad-width paddle / 8-clock missiles + VSYNC D1), River Raid asserts with $82 (bit-7 dump rider).",
      "state": "active",
      "category": "Timing / bus",
      "publicUrl": "/reforge/findings/atari2600-f84-tia-vsync-decodes-only-d1-the-val-0x03-guard-rejected-hardware-legal-assertions-breakout/",
      "publicSource": "/reforge/research/atari2600/#finding-84"
    },
    {
      "id": "gb-f026",
      "number": "026",
      "console": "gb",
      "title": "HALT wake needs explicit pending-source state",
      "summary": "Generated SM83 projects now keep an explicit `gb_halted` state around HALT instead of falling through after one frame tick. Each logical timing boundary recomputes `IE & IF & $1F`; an enabled pending source clears the halted state even with IME clear, while the opt-in vector service may then enter a known handler.",
      "state": "active",
      "category": "CPU",
      "publicUrl": "/reforge/findings/gb-f026-halt-wake-needs-explicit-pending-source-state/",
      "publicSource": "/reforge/research/gb/#finding-026"
    },
    {
      "id": "gb-f025",
      "number": "025",
      "console": "gb",
      "title": "Interrupt entry needs an explicit opt-in before promotion",
      "summary": "Generated projects now include an opt-in `--gb-interrupts` vector-service contract. For a known handler it pushes the captured return PC, clears the selected IF bit and IME/EI delay, guards nested entry, and counts dispatches and misses.",
      "state": "active",
      "category": "CPU",
      "publicUrl": "/reforge/findings/gb-f025-interrupt-entry-needs-an-explicit-opt-in-before-promotion/",
      "publicSource": "/reforge/research/gb/#finding-025"
    },
    {
      "id": "gb-f024",
      "number": "024",
      "console": "gb",
      "title": "Return-PC provenance must precede interrupt stack mutation",
      "summary": "Timing boundaries now derive the architectural next PC from the translated branch instruction length and expose it beside the last source PC. The value is not yet pushed or used to dispatch; indirect control flow, IF/IME mutation, handler execution, and RETI return integration remain open.",
      "state": "confirmed",
      "category": "CPU",
      "publicUrl": "/reforge/findings/gb-f024-return-pc-provenance-must-precede-interrupt-stack-mutation/",
      "publicSource": "/reforge/research/gb/#finding-024"
    },
    {
      "id": "gb-f023",
      "number": "023",
      "console": "gb",
      "title": "Interrupt priority needs provenance before handler dispatch",
      "summary": "The runtime now computes the lowest set bit of `IE & IF & $1F`, maps it to the fixed SM83 vector `$0040 + 8*bit`, and records the pending mask and last translated source PC. The three authorized 3,200-frame runs expose candidate `$0040` observations.",
      "state": "active",
      "category": "CPU",
      "publicUrl": "/reforge/findings/gb-f023-interrupt-priority-needs-provenance-before-handler-dispatch/",
      "publicSource": "/reforge/research/gb/#finding-023"
    },
    {
      "id": "gb-f022",
      "number": "022",
      "console": "gb",
      "title": "MBC3 RTC selection and latch state must not alias external RAM",
      "summary": "MBC3 types `$0F-$13` now use a distinct 7-bit ROM-bank path and treat `$08-$0C` in the RAM/RTC select register as RTC registers rather than RAM banks. The bus models RAM/RTC enable, the `0 -> 1` latch edge, latched seconds/minutes/hours/day values, deterministic T-cycle advancement, halt, and day carry.",
      "state": "active",
      "category": "Timing / bus",
      "publicUrl": "/reforge/findings/gb-f022-mbc3-rtc-selection-and-latch-state-must-not-alias-external-ram/",
      "publicSource": "/reforge/research/gb/#finding-022"
    },
    {
      "id": "gb-f021",
      "number": "021",
      "console": "gb",
      "title": "RETI must re-enable IME after the full SM83 stack pop",
      "summary": "The Game Boy RETI lift now follows the same full 16-bit stack-pop path as RET and immediately restores IME while clearing any delayed-EI state. Focused architecture coverage and the three-title 3,200-frame native regression pass.",
      "state": "active",
      "category": "CPU",
      "publicUrl": "/reforge/findings/gb-f021-reti-must-re-enable-ime-after-the-full-sm83-stack-pop/",
      "publicSource": "/reforge/research/gb/#finding-021"
    },
    {
      "id": "gb-f020",
      "number": "020",
      "console": "gb",
      "title": "IME and EI delay need observable state before vector dispatch",
      "summary": "The generated SM83 runtime now keeps an explicit interrupt-master-enable latch and one-instruction EI delay. DI clears both immediately, and the instruction boundary records pending sources from `IE & IF & $1F`; internal evidence expose the resulting IME, delay, and pending-source states for every sampled frame.",
      "state": "active",
      "category": "CPU",
      "publicUrl": "/reforge/findings/gb-f020-ime-and-ei-delay-need-observable-state-before-vector-dispatch/",
      "publicSource": "/reforge/research/gb/#finding-020"
    },
    {
      "id": "gb-f019",
      "number": "019",
      "console": "gb",
      "title": "MBC1 banking mode must not collapse into MBC5 registers",
      "summary": "MBC1 cartridge types `$01-$03` now have separate lower/upper ROM-bank fields, ROM/RAM banking mode, forbidden-bank remapping, RAM enable, and mode-dependent fixed-window/RAM-bank behavior. MBC5 remains unchanged.",
      "state": "active",
      "category": "Memory / cartridge",
      "publicUrl": "/reforge/findings/gb-f019-mbc1-banking-mode-must-not-collapse-into-mbc5-registers/",
      "publicSource": "/reforge/research/gb/#finding-019"
    },
    {
      "id": "gb-f018",
      "number": "018",
      "console": "gb",
      "title": "HDMA needs register-visible state before dot arbitration",
      "summary": "CGB HDMA1–HDMA5 (`$FF51-$FF55`) now model masked source/destination values, immediate 16-byte general-DMA blocks, queued HBlank blocks, and status length. Source bytes traverse the CPU bus and destinations use the selected VRAM bank; internal evidence records transfer count and active state.",
      "state": "active",
      "category": "Timing / bus",
      "publicUrl": "/reforge/findings/gb-f018-hdma-needs-register-visible-state-before-dot-arbitration/",
      "publicSource": "/reforge/research/gb/#finding-018"
    },
    {
      "id": "gb-f017",
      "number": "017",
      "console": "gb",
      "title": "Serial link state must not be silently treated as generic RAM",
      "summary": "SB/SC (`$FF01/$FF02`) now have explicit bus handlers. Internal-clock transfers complete after 4,096 T-cycles with open-link `$FF` input and serial IF signaling; external-clock transfers remain pending.",
      "state": "active",
      "category": "Timing / bus",
      "publicUrl": "/reforge/findings/gb-f017-serial-link-state-must-not-be-silently-treated-as-generic-ram/",
      "publicSource": "/reforge/research/gb/#finding-017"
    },
    {
      "id": "gb-f016",
      "number": "016",
      "console": "gb",
      "title": "KEY1 and STOP need explicit CGB state before double-speed work",
      "summary": "The runtime now models CGB KEY1 (`$FF4D`) current/prepare speed bits and lifts SM83 STOP into a tracked Game Boy state; a prepared STOP toggles the current speed bit and clears preparation. DMG mode leaves the register inactive, and internal evidence expose KEY1/stopped state.",
      "state": "active",
      "category": "Timing / bus",
      "publicUrl": "/reforge/findings/gb-f016-key1-and-stop-need-explicit-cgb-state-before-double-speed-work/",
      "publicSource": "/reforge/research/gb/#finding-016"
    },
    {
      "id": "gb-f015",
      "number": "015",
      "console": "gb",
      "title": "Coarse frame timing cannot safely unlock dot access rules",
      "summary": "A bounded native experiment attempted Mode 2/3/0/1 transitions, dot-based LY, and CPU VRAM/OAM blocking. It stalled before the first fresh Rhythm Land frame; deferring the newly asserted Mode-2 STAT edge did not cure the failure.",
      "state": "active",
      "category": "Timing / bus",
      "publicUrl": "/reforge/findings/gb-f015-coarse-frame-timing-cannot-safely-unlock-dot-access-rules/",
      "publicSource": "/reforge/research/gb/#finding-015"
    },
    {
      "id": "gb-f014",
      "number": "014",
      "console": "gb",
      "title": "CGB palettes are a separate color pipeline",
      "summary": "CGB background and object palette RAM is now modeled as 64 bytes per class. BCPS/BCPD and OCPS/OCPD provide indexed data access with auto-increment, and tile/OAM palette IDs select RGB555 colors in the renderer.",
      "state": "active",
      "category": "Video",
      "publicUrl": "/reforge/findings/gb-f014-cgb-palettes-are-a-separate-color-pipeline/",
      "publicSource": "/reforge/research/gb/#finding-014"
    },
    {
      "id": "gb-f013",
      "number": "013",
      "console": "gb",
      "title": "OAM and HRAM must share the real Game Boy bus",
      "summary": "The generated runtime now keeps OAM and HRAM outside the generic flat backing store. The 13-test architecture suite and three-title 3,200-frame matrix remain green.",
      "state": "active",
      "category": "Timing / bus",
      "publicUrl": "/reforge/findings/gb-f013-oam-and-hram-must-share-the-real-game-boy-bus/",
      "publicSource": "/reforge/research/gb/#finding-013"
    },
    {
      "id": "gb-f012",
      "number": "012",
      "console": "gb",
      "title": "CGB bank selectors must not be modeled as flat memory",
      "summary": "The native Game Boy state now owns dual VRAM and banked WRAM storage. CGB VBK/SVBK writes route CPU-visible VRAM/WRAM accesses, zero SVBK selects bank 1, and DMG mode reads the selectors as inactive.",
      "state": "active",
      "category": "Memory / cartridge",
      "publicUrl": "/reforge/findings/gb-f012-cgb-bank-selectors-must-not-be-modeled-as-flat-memory/",
      "publicSource": "/reforge/research/gb/#finding-012"
    },
    {
      "id": "gb-f011",
      "number": "011",
      "console": "gb",
      "title": "MBC5 routing must precede visual and mechanics proof",
      "summary": "The three authorized headers are MBC5 cartridges: Rhythm Land uses `$19`, while Little Green Blob and Dark Force use `$1B`. The runtime now detects the header, implements fixed and switchable ROM windows, MBC5 ROM-bank registers, RAM enable, RAM-bank selection, and bounded external RAM storage.",
      "state": "active",
      "category": "Memory / cartridge",
      "publicUrl": "/reforge/findings/gb-f011-mbc5-routing-must-precede-visual-and-mechanics-proof/",
      "publicSource": "/reforge/research/gb/#finding-011"
    },
    {
      "id": "gb-f010",
      "number": "010",
      "console": "gb",
      "title": "Indirect JP (HL) requires target provenance before dispatch",
      "summary": "Routing SM83 `JP (HL)` directly through a full-address native dispatcher was tested as a bounded experiment. The CGB corpus produced an unresolved target `$74C9`, and both CGB native proofs failed liveness.",
      "state": "active",
      "category": "CPU",
      "publicUrl": "/reforge/findings/gb-f010-indirect-jp-hl-requires-target-provenance-before-dispatch/",
      "publicSource": "/reforge/research/gb/#finding-010"
    },
    {
      "id": "gb-f009",
      "number": "009",
      "console": "gb",
      "title": "Timer and STAT timing must be observable before visual rebaseline",
      "summary": "The first timing iteration keeps the existing logical scanline boundary but adds a 456-T-cycle accumulator for the SM83 divider. TAC-selected timer edges, the four-T-cycle TIMA reload delay, DIV reset behavior, and STAT rising-edge requests are now emitted in the Game Boy I/O runtime.",
      "state": "active",
      "category": "Timing / bus",
      "publicUrl": "/reforge/findings/gb-f009-timer-and-stat-timing-must-be-observable-before-visual-rebaseline/",
      "publicSource": "/reforge/research/gb/#finding-009"
    },
    {
      "id": "gb-f008",
      "number": "008",
      "console": "gb",
      "title": "CB bit operations must preserve byte masks and memory RMW",
      "summary": "The first CB-family lift treated the bit index itself as the TEST operand and treated `(HL)` as an ALU lvalue. That was wrong for SM83: `BIT n,r` tests `1 << n`, while `SET n,(HL)` and `RES n,(HL)` must load one byte, update it, and store it back.",
      "state": "confirmed",
      "category": "Memory / cartridge",
      "publicUrl": "/reforge/findings/gb-f008-cb-bit-operations-must-preserve-byte-masks-and-memory-rmw/",
      "publicSource": "/reforge/research/gb/#finding-008"
    },
    {
      "id": "gb-f007",
      "number": "007",
      "console": "gb",
      "title": "Indirect vector recovery is a bounded liveness fallback",
      "summary": "Some homebrew vector helpers use JP (HL) targets that recursive descent does not yet recover. The current Game Boy-only unresolved-target path performs the callee's return-pop boundary so saved registers remain balanced and the native proof does not fail for the wrong reason.",
      "state": "active",
      "category": "Evidence",
      "publicUrl": "/reforge/findings/gb-f007-indirect-vector-recovery-is-a-bounded-liveness-fallback/",
      "publicSource": "/reforge/research/gb/#finding-007"
    },
    {
      "id": "gb-f006",
      "number": "006",
      "console": "gb",
      "title": "Copied ROM diagnostics must not shadow WRAM reads",
      "summary": "The native project copies an internal cartridge into a flat diagnostic buffer. A generic ROM-first reader therefore returned cartridge bytes for work-RAM/stack addresses in C000-DDFF, corrupting translated returns.",
      "state": "active",
      "category": "Memory / cartridge",
      "publicUrl": "/reforge/findings/gb-f006-copied-rom-diagnostics-must-not-shadow-wram-reads/",
      "publicSource": "/reforge/research/gb/#finding-006"
    },
    {
      "id": "gb-f005",
      "number": "005",
      "console": "gb",
      "title": "Startup opcode coverage must be proven at the decoder boundary",
      "summary": "The dependency-free SM83 decoder was emitting RST, pair arithmetic, PUSH/POP, INC (HL), CB, and HL post-increment/decrement forms as raw bytes. This caused the generated program to reach a frame hook while losing the real startup control path.",
      "state": "confirmed",
      "category": "CPU",
      "publicUrl": "/reforge/findings/gb-f005-startup-opcode-coverage-must-be-proven-at-the-decoder-boundary/",
      "publicSource": "/reforge/research/gb/#finding-005"
    },
    {
      "id": "gb-f004",
      "number": "004",
      "console": "gb",
      "title": "SM83 pair width and full-stack semantics are native blockers",
      "summary": "The z80 variant's default ALU width is 8 bits, but AF/BC/DE/HL/SP address and stack operations are 16-bit. The first native pass truncated pair state and used the Atari 6502 stack-page convention for Game Boy calls.",
      "state": "active",
      "category": "CPU",
      "publicUrl": "/reforge/findings/gb-f004-sm83-pair-width-and-full-stack-semantics-are-native-blockers/",
      "publicSource": "/reforge/research/gb/#finding-004"
    },
    {
      "id": "gb-f003",
      "number": "003",
      "console": "gb",
      "title": "Native proof artifacts are internal",
      "summary": "Source hashes, generated C projects, native executables, SDL2.dll, PPM samples, full replay logs, and TAS event files remain outside the public publication manifest. Public or client-facing output may carry only policy-approved metadata, limitations, and explicit trust state until human rights and acceptance decisions exist.",
      "state": "active",
      "category": "Recompiler",
      "publicUrl": "/reforge/findings/gb-f003-native-proof-artifacts-are-internal/",
      "publicSource": "/reforge/research/gb/#finding-003"
    },
    {
      "id": "gb-f002",
      "number": "002",
      "console": "gb",
      "title": "JOYP transport now has attributable replay evidence",
      "summary": "The Game Boy TAS contract converts the shared `.tas.json` schema into flat events containing active-low direction and button nibbles. Native replay logs `[TAS]` and `[GB_INPUT]` rows; the three-title matrix records multiple direction and button states for all titles.",
      "state": "confirmed",
      "category": "Evidence",
      "publicUrl": "/reforge/findings/gb-f002-joyp-transport-now-has-attributable-replay-evidence/",
      "publicSource": "/reforge/research/gb/#finding-002"
    },
    {
      "id": "gb-f001",
      "number": "001",
      "console": "gb",
      "title": "L1 liveness is not visual correctness",
      "summary": "The first three authorized homebrew lifts (Rhythm Land, Little Green Blob, and Dark Force) all build with the local MSVC/CMake/SDL2 toolchain and reach 1,800 native frames. A internal evidence records `LCDC=$00`, fixed `LY`, fixed visual CRC, and identical frame CRC across the full run for each title.",
      "state": "active",
      "category": "Evidence",
      "publicUrl": "/reforge/findings/gb-f001-l1-liveness-is-not-visual-correctness/",
      "publicSource": "/reforge/research/gb/#finding-001"
    }
  ]
}
