Review follow-ups L + I: drop dead openParty, unify the menu-index parser

L: openParty had no production callers (invite path uses joinParty -> seatLeader,
which seats the leader the same way but reads the owner off the expedition row).
Removed it; the tests now seat the leader through a seatLeaderFixture that wraps
seatLeader in a transaction.

I: promoted parseTemperIndex to parseMenuIndex and routed resolveMagicEquipReply
and handleMasterworkEquipReply through it, replacing two hand-inlined copies of
the same digit parser. Behaviour-preserving (the parsed flag was redundant with
the idx<0 guard); the retry-on-bad-parse disagreement is left as-is since this
is a pure dedup.

Full plugin suite green.

Claude-Session: https://claude.ai/code/session_017mEwUmmS7aQTP2NQXj6rUa
This commit is contained in:
prosolis
2026-07-10 08:55:07 -07:00
parent d7a5333048
commit 1f1fbf0251
6 changed files with 48 additions and 77 deletions

View File

@@ -115,18 +115,6 @@ func partySize(expeditionID string) (int, error) {
return n, nil
}
// openParty seats the leader, converting a solo expedition row into a party of
// one. It is idempotent: a second call on the same expedition is a no-op, so
// the invite path can call it unconditionally before adding a member.
func openParty(expeditionID string, leaderID id.UserID) error {
_, err := db.Get().Exec(`
INSERT INTO expedition_party (expedition_id, user_id, role)
VALUES (?, ?, 'leader')
ON CONFLICT (expedition_id, user_id) DO NOTHING`,
expeditionID, string(leaderID))
return err
}
// joinParty seats a member. It refuses a full roster, a duplicate, and a player
// who already leads or rides an expedition of their own — the "one active
// expedition per user" rule that startExpedition enforces in code, extended to
@@ -171,9 +159,11 @@ func joinParty(expeditionID string, userID id.UserID) error {
return tx.Commit()
}
// seatLeader is openParty inside a caller's transaction: it reads the owner off
// the expedition row rather than trusting a passed-in id, so the roster's leader
// can never disagree with dnd_expedition.user_id.
// seatLeader converts a solo expedition row into a party of one, inside a
// caller's transaction. It reads the owner off the expedition row rather than
// trusting a passed-in id, so the roster's leader can never disagree with
// dnd_expedition.user_id. Idempotent (ON CONFLICT DO NOTHING), so the invite
// path can call it unconditionally before adding a member.
func seatLeader(tx *sql.Tx, expeditionID string) error {
var owner string
err := tx.QueryRow(