Theme: Promote the shared core to a public library with a semver contract; reach cycle accuracy for the NES path; split nessy into its own repo.
D1 — Promote the 6502 core out of internal/ into public packages¶
Context: the future standalone nessy repo can't import internal/.
Decision: move cpu / dap / symbols / peripheral / expr / loader / trace to public top-level paths; keep internal/tui (chippy-only) and internal/nes (nessy-only) private. Document a stability/semver contract (docs/api.md): cpu.Bus/Peripheral/Ticker/Variant are the major-version contract types.
Consequences: third parties + nessy can pin the library; bare vX.Y.Z tags become library semver. The opcode-init lex-order invariant (ADR 0001 D2) is preserved through the move.
D2 — Per-cycle CPU↔PPU interleave for VariantNES (Mesen2 master-clock model)¶
Decision: for VariantNES, Step runs in lockstep — every bus access ticks the chain one cycle (PPU 3 dots / APU / cart) before the access, with the 6502's dummy cycles per addressing template; ported Mesen2's ProcessPendingDma, the branch IRQ-poll quirk, and the NTSC frame-counter intervals. NMOS/CMOS keep the instruction-stepped batch tick (byte-identical).
Consequences: all NES accuracy ROMs pass. Because this path is VariantNES-gated and that variant disables decimal, later NMOS per-cycle bus-trace validation force-enables the path on VariantNMOS (ADR 0008 D4). The per-cycle path also asserts an exact tick budget — a constraint every later per-cycle change honors.
Context: with the public API stable, the monorepo's NES code is dead weight for a 6502-library consumer.
Decision: carve internal/nes + cmd/nessy* into github.com/nkane/nessy (git history preserved via filter-repo, nessy-v* tags → v*). chippy keeps only the library + TUI debugger.
Consequences: chippy is a clean general 6502 library; nessy depends on it. v1.2.0 is the last release with nessy in-tree.