← all tickets

42 — Expose derived totals from the Rust snapshot; delete the Python mirror tables

Status: fixed

Decision (2026-08-02, triage with maintainer): Option A. The snapshot emits hook-derived totals; the Python mirror tables are deleted. The original rationale for the mirror ("avoid growing the snapshot schema for a few ints", serialize.py:26–33) lost: the schema cost is 2–3 integer fields once, while the table grows with every bonus card and fails silently in a user-visible way (the client sizes its discard prompt and MU display off these numbers). Field naming decided too: keep the existing snapshot keys (max_hand_size, memory_total) and fill them with the derived values — that is the wire format static/game.js:602,1426–1427 and tests/test_api.py:134 already depend on, since serialize.py overwrites the base values before the client sees them. No consumer anywhere reads the base value. Do not add total_* keys.

What to do:

Definition of done:

Comments

2026-08-01: Filed from the ticket 40 review, which flagged the duplication but kept it in scope-neutral form. The flag named only corp_total_hand_size; this ticket widens scope to all three mirrored totals since they share the tables and the same drift risk — deciding for one decides for all.

2026-08-02: Fixed as decided (Option A, existing key names). snapshot.rs now emits hooks::corp_total_hand_size / runner_total_hand_size / runner_total_memory under max_hand_size / memory_total; the mirror tables and helpers are gone from server/serialize.py, whose call sites are plain pass-throughs. Coverage: the existing end-to-end test_precision_design_identity_serializes_a_six_card_corp_hand_limit (tests/test_api.py) now runs through the derived path, plus a new Rust test snapshot_reports_hook_derived_totals (cards/sg.rs) covering the runner MU/hand-size fields, which no pytest can reach without a scripted rig. Noted in the snapshot.rs module doc that port-era recorded traces can differ on these two keys under netrunner-replay. Suite green: cargo fmt/clippy/test (135 core tests) and uv run pytest -q (134 passed).

2026-08-02: Triaged with the maintainer (grilling session). Option A chosen over keeping the mirror with a drift test — the drift test would be more machinery (dumping registry tables across the FFI boundary) than simply emitting the totals hooks.rs already computes. Keep-existing-keys naming chosen over new total_* keys because every consumer already receives derived values under the existing names and the base values are provably unused. Status flipped to ready-for-agent.