Status: fixed
What to fix: Ticket 39 built the decision plumbing for "which card(s) does the player pick" (five kinds: carnivore_trash, longevity_trash, longevity_recur, hansei_trash, anoetic_trash — see rust/netrunner-core/src/legal.rs::hq_trash_options and the resolvers in engine.rs). Two System Gateway cards were left out of scope there and still auto-resolve a corp choice:
1. Spin Doctor (30053) — "Remove this asset from the game: Shuffle up to 2 cards from Archives into R&D." spin_doctor_use (rust/netrunner-core/src/cards/sg.rs, ~sg.rs:1488) drains the first 2 faceup Archives cards. Which cards (and how many, "up to 2") is the corp's choice. DecisionData::LongevityRecur is the same shape — a shared "recur up to N from Archives" decision may fall out naturally, and would let both cards drop their bespoke handling.
UseAsset click ability because the engine has no click-free paid-ability window. That one is *not* in scope here; leave the comment describing it in place.
2. Sprint (30041) — "Draw 3 cards, then shuffle 1 card from HQ into R&D." sprint (~sg.rs:1258) takes hq.remove(0) *and puts it in Archives facedown instead of R&D* — so this is two bugs: the missing choice, and the wrong destination zone. The card returns a card to R&D (and shuffles); it does not trash it.
Definition of done:
Decision with legal-action derivation in legal.rs and resolution in engine.rs, following the ticket-39 kinds.card_30041_* / card_30053_* tests updated to drive the new decisions. Client prompts in static/game.js for the new action types, and log redaction in server/serialize.py if the new log lines name hidden corp cards.cargo fmt, cargo clippy --workspace -- -D warnings, cargo test --workspace (from rust/), and uv run pytest -q (from the repo root).2026-08-01: Filed from ticket 39, which fixed the same shape of approximation for Carnivore, Longevity Serum, Hansei Review and Anoetic Void and left these two as the follow-up. Sprint's wrong destination zone was noticed while writing this ticket — it is not a ticket-39 regression.
2026-08-02: Done. The shared decision did fall out: ticket 39's longevity_recur is now archives_recur, carrying a RecurSource (Longevity Serum / Spin Doctor) that names the log lines, picks the R&D shuffle's rng stream, and drives the client prompt's "up to N" — Spin Doctor's bespoke drain is gone and both cards go through engine::archives_recur. Spin Doctor now pays its cost first (removed from the game up front), offers facedown Archives cards too, honours "up to 2" via done_archives_recur, and shuffles R&D once and only if something moved; the click-ability-window approximation note stays. Sprint gets a new sprint_return decision over HQ (legal.rs::hq_card_options, renamed from hq_trash_options since Sprint is not a trash) and the chosen card is now shuffled into R&D instead of binned facedown in Archives. Corp AI takes every archives_recur card as before, and falls through to the first HQ card for sprint_return (the old auto-behavior). Client prompts for sprint_return / archives_recur in static/game.js off a new pending_archives_recur view field, and server/serialize.py hides the named HQ card in Sprint's new log line from the runner. Tests: Sprint returns a chosen freshly-drawn card and asks nothing with an empty HQ; Spin Doctor recurs a chosen faceup + facedown pair, and separately stops early after one card / asks nothing with an empty Archives.