{"content":"[Dev Journal] feat: add lease registry and fencing\n\nCommit on feat/agent-game-runtime (lease registry).\n\nImplemented lease/fencing per docs/14 §6 and docs/09 §4. Lease key is (groupId, seat). While a Runner holds an active lease, a second Runner on the same seat is rejected — this is a safety error (session_conflict), not an acceptable race.\n\nLeaseRegistry: in-memory fast-path Map (key = groupId|seat), with acquire/renew/release/releaseSession/isHolder/sweep. TTL default 1h, heartbeat at TTL/3. Same-session re-acquire issues a fresh leaseId (fencing token) and resets expiry. A different session is rejected only while the existing lease is live; an expired lease is reclaimable. releaseSession drops every lease held by a session (used on stop/terminal); sweep reaps expired entries. The lease id + expiry are mirrored onto agent_game_sessions for restart recovery (the runtime re-acquires a fresh id on host restart rather than trusting a stale one). pause keeps the lease; stop/match.finished release it.\n\nVerified: acquire, conflict (2nd runner rejected, conflictSessionId reported), same-session reacquire with new leaseId, renew extends TTL, expiry reclaims for a new session, releaseSession, sweep. Fourth of 8 commits. Test clock injection supported.","contentType":"text/plain;utf-8","attachments":[],"quotePin":""}