← all tickets

16 — Expand: registry infrastructure + pilot card

What to build: The engine builds hook registries at startup, keyed by card code, with a registration builder so one contiguous block declares all of a card's hooks. Every hook dispatch site consults the registry first and falls back to the existing match arms, so the game plays identically with nothing migrated. Seamless Launch (a multi-registry card: on-play + playability gate) moves into the new form as the tracer bullet.

Blocked by: None — can start immediately.

Status: resolved

Comments

Implementation notes

rust/netrunner-core/src/cards/registry.rs (new) holds the infrastructure:

engine applies unconditionally instead of looking up (INSTALL_COST_MODS, ACCESS_BONUS, POST_PROGRAM_INSTALL, BASIC_DRAW_BONUS — Python looped over .values() in insertion order, and hooks() preserves that).

registry_manifest.rs, so migrating a card in 02/03 never has to add infrastructure — only a block.

so one card is one contiguous block. Registering the same hook twice for a code panics at startup.

with no allocation. Built once by registry() (a OnceLock).

Dispatch is registry-first everywhere: every dispatcher in hooks.rs plus the two inline sites in engine.rs (RUN_EVENT_PRE in _play_event, SUBROUTINE_OVERRIDE in fire_subroutine). Each consults the registry, then falls back to its existing match arm, so nothing changes for the 71 unmigrated cards.

Seamless Launch (30040) moved to cards/sg.rson_play + playability_gate in one block, with seamless_candidates/seamless_launch moved out of hooks.rs and both match arms deleted. Six card_30040_* tests in that module cover the gate (no advanceable card, advanceable card, installed-this-turn exclusion, non-advanceable content), on-play candidate enumeration, the no-candidate no-op, and that 30040 really dispatches through the registry.

Layout note: the pack modules live at src/cards/<pack>.rs alongside the existing src/cards.rs (the 2018 module path style), which is the path ADR-0002 and docs/adding-a-card.md name — no file move was needed.

registry_manifest.rs is unchanged apart from its doc comment: a migration moves *where* a code is registered, not whether, so the frozen-fixture parity test should still pass untouched.

Verified (2026-07-30)

cargo test --workspace green (56 core unit tests incl. the six card_30040_* tests + 5 AI invariants) and the Python suite green (136 passed) after make rust-py.

Sign-off (2026-07-30)

Reviewed and approved by Tomáš Musil; merged as bb576cd. Marked resolved.