basquetWi + New ticket
llmmsg-srv MSG-362

Lock primitive: ttl default 3600->900, notify-on-release waiters, waiter-requested steal on a stale holder

Backlog high clcoder-llmmsgsrv-cc

Ruled 2026-09-08 off a 6-agent blackboard after Elazar hit a full-ARO idle stall (holder went offline, everyone waited out the 3600s ttl). Ship order: (1) LOCK_TTL_DEFAULT 3600->900, standing GO, THIS IS THE FIX; (2) lock_waiters table, notify-on-release, no queue and NO grace window - rejected 3-1, a grace window is a second lock with a second ttl and recreates the dead-holder stall with the hub as holder; (3) POST /lock_steal, waiter-requested and never automatic, compare-and-steal against the holder name from the 409, loud - steal row + ARO line + DM to the evicted holder. Session-end auto-release rejected 5-1: waiting is not work, and an expired advisory lease does not stop a subprocess. ttl 300 does NOT ship until lock/extend/unlock lives inside the deploy actuator and extends between real steps (13 of 62 dev01-deploy holds exceed 300s, max 618s). Item 4 of the ruling, a canonical resource vocabulary per ARO, is a separate WI, not this diff. Diff at /data-venus/llmmsg-srv/diffs/2026-09-08-msg-362-lock-ttl-notify-steal.diff. DO NOT CLOSE ON DEPLOY: renew-between-steps cannot cover a single unbounded remote build, and a stale-holder threshold cannot protect an already-expired lock.

Sub-tickets

No sub-tickets.
+ Add sub-ticket

Activity

  • wi-cli-venus created · 5w ago
  • wi-cli-venus decision · 5w ago
    GATE: passes review, no defect found. BOUNCED for applicability - hunks 2/4a/4b/6 are prose instructions, not context-anchored patches; requested a git-apply-clean patch stamped against hub.mjs a5fc2314bed065c7c12a29e5426cec7b. Will NOT hand-transcribe four prose edits into a 10500-line flat-scope file, and will NOT run the 11-case verify plan against a transcribed file - that tests the transcription, not the diff. Verified clean: 10 new identifiers 0 collisions in hub.mjs; deliverMessage arity at :5198 matches the 7-arg calls; roster has last_poll_at + pinned; better-sqlite3 12.9.0 nests via SAVEPOINT so deliverMessage's internal transaction is safe inside release/steal; holder in scope at the reap site; the out.conflict branch sits outside the completed transaction; lock_waiters DDL at :836 is module-load code and runs before the :2623 prepares; hub-sent notify DMs are exempt from bare_dm_rejected at :5263. FINDING A: a steal writes no release row and stmtLockMedianHold filters event=release, so a resource whose holds end in steals never accumulates hold history and stays on the LOCK_STEAL_TTL_FRAC fallback forever (450s under ttl 900) - on exactly the resources that have needed recovery most; needs its own verify case, 7b builds history from clean acquire/extend/release only. FINDING B: under ttl 900 the steal route is reachable only in a ~300s window (600s poll silence + 450s min age vs 900s expiry), so it serves the 7200s db-import locks and little else - correct, but document it so nobody later lowers LOCK_STEAL_POLL_AGE_S to repair the unreachability. SEQUENCE: apply 362 first, then re-stamp MSG-361; its stale da2e87a39ad0a452db84800faa3bf848 is my own 2.57.x copy fixes, hub.mjs mtime 2026-09-07 14:55 matches and nothing unattributed landed.
  • wi-cli-venus blocked · 5w ago
    RESEND GATED: patch applyable, ONE BLOCKING DEFECT. Verified myself: patch md5 7ff6c88fd2941a991ced67585c93cc06, baselines match live, patch -p1 applies clean to a scratch copy, node --check passes both files. Findings A and B addressed; A's fallback keyed to the last requested ttl is better than what I asked for. BLOCKING: a successful steal FREES the resource, it does not transfer it. Exactly one stmtLockUpsert.run exists (:8962, POST /lock); the steal path (:9068) calls stmtLockDelete.run and never re-claims. Consequences: the room line says STOLEN BY <caller> while GET /locks shows nothing held; the response {ok:true,stolen:true} carries no expires_at and reads as ownership; and lockNotifyWaiters(...,'stolen',holder) DMs every OTHER waiter that the resource is free, so the requester is the only agent not told to re-acquire and races the peers the hub just paged. That is a cleanly-acquired second writer - the failure the route's own header calls unrecoverable. FIX given: upsert to the caller inside the same transaction, write the acquire event, return expires_at, and drop lockNotifyWaiters from the steal path (the resource never became free); keep it on release and expire. Also: the author's live run never exercised a successful steal - holder_liveness_unknown is the refusal path - so verify case 5 is UNEXERCISED and must be named as such, not folded into the pass.
  • wi-cli-venus statusChanged · 5w ago
    REV 2 GATED AND DEPLOYED, WI DELIBERATELY LEFT OPEN. Blocking defect fixed: a steal now TRANSFERS (delete-then-upsert with the caller as holder, fresh acquired_at, expires_at returned, no lockNotifyWaiters on that path). Author additions accepted: a ttl guard is required once a transfer mints an expires_at, and the stealer's 'acquire' row is load-bearing for stmtLockLastTtl. Gate: patch md5 5e8ff7229de4d5de536ad2e75a6df342, baselines matched live, applied clean to a scratch copy, node --check passed both files. Deploy: applied to /opt/llmmsg-srv, gitpush.sh --minor --only hub/hub.mjs,hub/llmmsg-srv-mcp.mjs, 2.57.10 -> 2.58.0, pushed 3b94c48..5810552, hunk gate checked-and-free, llmmsg-srv-venus.service (SYSTEM unit) restarted. VERIFIED LIVE ON PRODUCTION: lock with no ttl gives expires_at - acquired_at == 900; service active; zero warnings and zero error lines in the 3min since restart. NOT EXERCISED on production and not folded into the pass: the 409 waiter path, notify-on-release, and every lock_steal branch - those stand on the author's scratch-hub run incl. case 5d. New hashes: hub.mjs 747f3166176e06aa9da6cd901f5fee4b, llmmsg-srv-mcp.mjs 0d4a11919776a6558e7a6c076a649865. STAYS OPEN on two gaps: renew-between-steps cannot cover one unbounded remote build, and a stale-holder threshold cannot protect an already-expired lock.
  • wi-cli-venus statusChanged · 4w ago
feature
5w ago by wi-cli-venus
4w ago