You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Split from rollup #1294 (TODO.md backlog), triage task 2544, judged at main HEAD e561ab5.
Already done (do not redo)
Cursor opacity fading/strobing/hover are implemented in pkgs/id/web/src/cursors.ts (fade 30s→60s minimum→5m hidden, strobe slows with fade, hover = 100% opacity + top z-index; the TODO file's own "Done?" list matches).
Remaining scope
Tooltip visibility modes: full / minimal / hidden toggle in the UI (minimal = cursor only, tooltip on hover ≥1s; hidden = tracked but not shown, pinned cursors exempt).
Click-to-enlarge tooltip with the 1s revert chain (big → tooltip → minimal), per-cursor minimize/restore lists for full and minimal modes, and pin/unpin on the big tooltip.
Client + server logging of cursor lifecycle (first inactive, minimum reached, removed, hover/unhover).
Verify inactivity is based on connection liveness (websocket pong/activity), not pointer idleness — a connected client's cursor stays visible.
Acceptance criteria
The modes, pin/unpin, and minimize/restore behaviours above work in the web UI with tests at the existing web/src/*.test.ts pattern level.
Lifecycle log lines exist client- and server-side; the liveness basis for inactivity is verified and documented in the PR.
Still live: filed this hour as a split from rollup id: TODO.md backlog rollup — small ideas not yet covered elsewhere #1294 (queue triage task 2544, judged at main HEAD e561ab5); cursor fading/strobing/hover already exist in pkgs/id/web/src/cursors.ts and are out of scope — tooltip modes, pin/unpin, minimize/restore, and lifecycle logging are not implemented. Confirmed live.
Notes: pure web-UI remainder work with existing test infrastructure at web/src/; the connection-liveness verification item (cursor visibility keyed to websocket liveness, not pointer idleness) is a behaviour check worth doing first since it may already hold.
Risks: tooltip mode state interacts with pinned/minimized per-cursor lists — state model first, or the modes will fight each other.
Suggested approach: verify the liveness item, then modes + pin/unpin behind the existing cursors module, lifecycle logging last.
🤖 Agent note · filed
Agent: fleet monitor
Session / ID: repo-fleet-monitor run 2026-10-28 15:19 CDT
Found via: monitor reconciliation
Task: Intake enrichment — labels normalized, live status verified
agent-note:v1
state: triaged (coverage pass)
Coverage pass 2026-11-03: reviewed in the fleet-wide per-issue pass (drift / overlap / already-handled / stale / blockers / ordering). Verdict: still live; queued in repo-health-code-pilot as triage at priority 30 (priority/low). If this is already handled at current main, the triage closes it with evidence; if it needs splitting, the triage files the split.
Found via: coverage pass 2026-11-03
Verified against fresh origin/main = 9a1fe429c8b4b6ece5fcdf1587dfdf022c63ffe6 (2026-11-03).
Still live. None of the four remaining-scope items exist at current main:
pkgs/id/web/src/cursors.ts still only does opacity fade / strobe / hover restore (FADE_START_MS 30s, FADE_END_MS 60s, HIDE_MS 5m in cursor-utils.ts). No tooltip mode state, no pin/unpin, no minimize/restore lists.
git grep -ni "tooltipMode|minimiz|pinned|presenceLog" -- pkgs/id at main has no hits in the presence surface (only unrelated vendor/example matches).
Lifecycle logging: one client console.log("[cursors] Removing stale cursor:", clientID) at cursors.ts:296. Nothing for first-inactive / minimum-reached / hover / unhover, and no server-side presence lifecycle logs.
Liveness item — verified, and it currently fails the desired behaviour. Inactivity is pointer/selection idleness, not connection liveness:
Client lastUpdate is set only when a CURSOR message (msg 4) arrives (cursors.ts:836-847); opacity and hiding derive from that age (cursors.ts:542-548 + getOpacityForAge).
The client sends CURSOR only on selection/cursor change (collab.tssendCursor). The periodic empty-text "pong refresh" only dispatches an empty transaction to re-render decorations and replies with empty text (collab.ts:643-647) — it does not refresh lastUpdate.
Server tracks connection liveness separately (last_activity + ping/pong, collab.rs:991-1100) and rebroadcasts existing cursors with idle_secs only to a newly joined client (collab.rs:944-965).
=> A connected client that does not move for 5 minutes has its cursor hidden from everyone. So this is a real behaviour change, not a documentation check.
Scope / ordering for the implementing PR (fits effort/m):
State model first — one presence-UI state (tooltipMode: full | minimal | hidden, pinned set, per-mode minimized set) as a pure module with tests in the existing web/src/*.test.ts pattern. Modes, pin and minimize interact, so fix the state model before UI.
Tooltip modes — full / minimal (cursor only, tooltip on hover ≥1s) / hidden (tracked but not shown; pinned exempt).
Tooltip interaction — click-to-enlarge plus the 1s revert chain big → tooltip → minimal; per-cursor minimize/restore for full and minimal; pin/unpin from the big tooltip.
Liveness fix — refresh lastUpdate on a connection-liveness tick (server empty-text ping/pong or a presence heartbeat) so a connected idle client stays visible; keep idle_secs backdating for initial load. Document the liveness basis in the PR.
Lifecycle logging last — client lines for first-inactive / minimum-reached / removed / hover / unhover, plus matching server-side tracing in the collab.rs presence paths.
Blockers: none technical. Step 4 depends on step 1's state model; step 5 last. Sibling #1792 (settings/name propagation) touches the same presence surface but is separable — this issue does not need to wait on it. Parent rollup #1294 is closed; this issue stands alone. Labels stay kind/feature, app/id, effort/m, priority/low.
Activity
developing-today commentedon Oct 28, 2026
CODE-730
dezren39 commentedon Oct 28, 2026
Intake review
pkgs/id/web/src/cursors.tsand are out of scope — tooltip modes, pin/unpin, minimize/restore, and lifecycle logging are not implemented. Confirmed live.web/src/; the connection-liveness verification item (cursor visibility keyed to websocket liveness, not pointer idleness) is a behaviour check worth doing first since it may already hold.🤖 Agent note · filed
dezren39 commentedon Nov 3, 2026
agent-note:v1
state: triaged (coverage pass)
Coverage pass 2026-11-03: reviewed in the fleet-wide per-issue pass (drift / overlap / already-handled / stale / blockers / ordering). Verdict: still live; queued in repo-health-code-pilot as triage at priority 30 (priority/low). If this is already handled at current main, the triage closes it with evidence; if it needs splitting, the triage files the split.
Found via: coverage pass 2026-11-03
dezren39 commentedon Nov 3, 2026
Triage — still live at main
9a1fe42Verified against fresh
origin/main=9a1fe429c8b4b6ece5fcdf1587dfdf022c63ffe6(2026-11-03).Still live. None of the four remaining-scope items exist at current main:
pkgs/id/web/src/cursors.tsstill only does opacity fade / strobe / hover restore (FADE_START_MS30s,FADE_END_MS60s,HIDE_MS5m incursor-utils.ts). No tooltip mode state, no pin/unpin, no minimize/restore lists.git grep -ni "tooltipMode|minimiz|pinned|presenceLog" -- pkgs/idat main has no hits in the presence surface (only unrelated vendor/example matches).console.log("[cursors] Removing stale cursor:", clientID)atcursors.ts:296. Nothing for first-inactive / minimum-reached / hover / unhover, and no server-side presence lifecycle logs.gh pr list --state openfor cursor/presence returns only fix(id): canonicalize presence channels before cap (#4404) #4571 presence-channel dedup, unrelated).Liveness item — verified, and it currently fails the desired behaviour. Inactivity is pointer/selection idleness, not connection liveness:
lastUpdateis set only when a CURSOR message (msg 4) arrives (cursors.ts:836-847); opacity and hiding derive from that age (cursors.ts:542-548+getOpacityForAge).collab.tssendCursor). The periodic empty-text "pong refresh" only dispatches an empty transaction to re-render decorations and replies with empty text (collab.ts:643-647) — it does not refreshlastUpdate.last_activity+ ping/pong,collab.rs:991-1100) and rebroadcasts existing cursors withidle_secsonly to a newly joined client (collab.rs:944-965).=> A connected client that does not move for 5 minutes has its cursor hidden from everyone. So this is a real behaviour change, not a documentation check.
Scope / ordering for the implementing PR (fits effort/m):
tooltipMode: full | minimal | hidden,pinnedset, per-modeminimizedset) as a pure module with tests in the existingweb/src/*.test.tspattern. Modes, pin and minimize interact, so fix the state model before UI.lastUpdateon a connection-liveness tick (server empty-text ping/pong or a presence heartbeat) so a connected idle client stays visible; keepidle_secsbackdating for initial load. Document the liveness basis in the PR.tracingin thecollab.rspresence paths.Blockers: none technical. Step 4 depends on step 1's state model; step 5 last. Sibling #1792 (settings/name propagation) touches the same presence surface but is separable — this issue does not need to wait on it. Parent rollup #1294 is closed; this issue stands alone. Labels stay
kind/feature,app/id,effort/m,priority/low.