{"slug":"desktop-dotbar","total":50,"limit":100,"offset":0,"since":null,"commits":[{"hash":"7956e2f","date":"2026-09-26 11:13:30 -0700","author":"auto-commit-fleet","subject":"auto-data-snapshot: 2026-09-26T11:13:09 (1 data files) — .claude/worktrees/dotbar-keepalive","body":""},{"hash":"d2b3a95","date":"2026-09-26 10:01:01 -0700","author":"Steve Abrams","subject":"dotbar: hide dead sessions from ALL panels (colour groups + parked), fix claude.exe liveness, never hide parked tickets (TK-12236, TK-12174)","body":"- isClaudeComm accepted only /claude(\\s|$)/, so the native installer's .../bin/claude.exe\n  made a LIVE parked tab read as 'recycled' and vanish; now claude/claude.exe/node/codex\n- filterSessions: same ps probe drops dead-tty rows from the colour groups; ps failure = fail-open\n- parked TICKETS are never hidden (always-show rule); closed -> liveness 'closed', off-board -> unknown\n- negative tests: fake dead tty hidden, live kept, unknown kept; mutation-verified red\n\nCo-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01GEE4jWy9RBmz5QnR2xcvno"},{"hash":"a5d20f8","date":"2026-09-25 11:48:22 -0700","author":"Steve Abrams","subject":"bar: add dw / non-dw ticket chips under the five state chips","body":"Same active population cut by business instead of state (dw + non-dw == the five\nstate counts, asserted). Segmentation copies the Fleet board's classifier verbatim;\na test re-reads board.html and fails on drift. Offline board -> both read '-', never 0.\n\nCo-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01AeMJYTDYXnN6A6A1mW7Yud"},{"hash":"7010761","date":"2026-09-25 10:29:31 -0700","author":"Steve Abrams","subject":"dotbar: start-bar comment now says Jev paid is ARMED (Steve 2026-09-23, TK-12078)","body":"Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01RyJoXLrB22bwqavSf2ex1S"},{"hash":"426230a","date":"2026-09-25 10:26:34 -0700","author":"Steve Abrams","subject":"dotbar: document claimed-vs-unclaimed bg-spare liveness + negative test (TK-12236 contrarian follow-up)","body":"Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01RyJoXLrB22bwqavSf2ex1S"},{"hash":"9c338a8","date":"2026-09-25 10:12:25 -0700","author":"Steve Abrams","subject":"dotbar: carry pid on live parked tab rows so folder/realm cwd lookup works post-merge (TK-12236)","body":"Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>"},{"hash":"355916c","date":"2026-09-25 10:11:19 -0700","author":"Steve Abrams","subject":"dotbar: parked panel shows only live rows (pid/claude probe, open tickets), unknown shown not hidden, chip==rows (TK-12236)","body":"Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>"},{"hash":"bbbb012","date":"2026-09-25 09:52:09 -0700","author":"auto-commit-fleet","subject":"auto-data-snapshot: 2026-09-25T09:51:23 (2 data files) — .claude/worktrees/dotbar-always-show-states .claude/worktrees/dotbar-dw-folders","body":""},{"hash":"9053da3","date":"2026-09-25 09:52:06 -0700","author":"Steve Abrams","subject":"dotbar: DW / Non-DW folder chips scope the bar to one folder (TK-12234)","body":"Server tags each live + parked session with realm (dw|other) from the ticket's\nproject/title, then the doing label, then the claude cwd (realm.js, incremental\nindex of the tk event log). UI adds 📁 DW / 📁 Non-DW chips; picking one filters\nevery colour chip, dropdown, parked item and the live total. Persisted in\nlocalStorage. Tests incl. a negative case (never a false DW).\n\nCo-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01BhKndRAeekFseXqd9WFzYA"},{"hash":"fde99cb","date":"2026-09-25 09:45:28 -0700","author":"Steve Abrams","subject":"dotbar: always show every state — all 5 ticket states + all colour groups, offline shown not hidden","body":"Steve 2026-09-25: \"nav bar should be including all from orig nav bar... blocked, parked,\ndoing, idle etc., remember!!\" The original Swift TicketBar kept its state tiles up\npermanently; the Electron port hid zero-count states AND hid the whole ticket row when\nthe board was unreachable. After this morning's reboot pm2 came back empty, ticket-board\n(:9794) never restarted, and every ticket chip silently vanished.\n\n- ticket-states.js: blocked/open/idle/doing/parked always rendered; three states per chip\n  (measured / measured-zero dimmed / NOT-measured \"–\" + offline), never a fake 0.\n- server: tickets snapshot carries ok:false on a failed fetch; /api/tickets returns states.\n- colour groups: every real colour always shown (zero dimmed, no pulse); only 'no dot' hides.\n- tests: healthy + 2 negative fault-injection cases (board never fetched / went down).\n\nCo-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01Bo75Y1rV4if7AbvCEQohXT"},{"hash":"b577919","date":"2026-09-25 09:21:14 -0700","author":"auto-commit-fleet","subject":"auto-data-snapshot: 2026-09-25T09:20:47 (3 data files) — .barcfg.bak-20260925 .barcfg.pre-e2e .barcfg.pre-restart","body":""},{"hash":"c915cfa","date":"2026-09-25 09:09:47 -0700","author":"Steve Abrams","subject":"dotbar: boot guard uses process.versions.electron (require.main!==module under Electron left the bar windowless) (TK-12225)","body":"Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_0161EawVb2Kb9BdpD5NGbtN3"},{"hash":"4f3c60e","date":"2026-09-25 09:07:24 -0700","author":"Steve","subject":"dotbar: floatingPosFor falls back to orphaned display pos on macOS display-ID churn (TK-12225)","body":"Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_0161EawVb2Kb9BdpD5NGbtN3"},{"hash":"60473d3","date":"2026-09-23 13:14:19 -0700","author":"auto-commit-fleet","subject":"auto-data-snapshot: 2026-09-23T13:13:50 (1 data files) — start-bar.command","body":""},{"hash":"a32c6bf","date":"2026-09-23 12:53:47 -0700","author":"Steve Abrams","subject":"dotbar/jev: isolate tests from real cost ledger + reconcile paidCallsToday to the enforced count","body":"Verification caught two defects in the count-cap change:\n- Tests exercising the paid-log path called the real defaultLogSpend -> cost-tracker\n  log.js -> the REAL ~/.claude/cost-ledger.jsonl, writing phantom typesafe_jev rows\n  on every `npm test` (no money spent — mock transport — but polluting prod data and\n  pre-consuming the live caps). Fix: every paid-firing test now injects a mock logSpend\n  via the opts DI seam. Proven: full suite writes 0 rows to the real ledger (line count\n  unchanged across a run). The 7 rows already written were backed up and removed (rest\n  byte-identical).\n- /api/jev showed paidCallsToday:0 while the ledger held 7 rows — the displayed stat\n  (a per-refresh snapshot, only set when armed) diverged from the value the cap enforces\n  (countPaidCallsToday). Fix: getStats() now derives paidCallsToday LIVE from the same\n  ledger (shared defaultReadLedger), so displayed == enforced regardless of paidEnabled;\n  a fail-closed read surfaces as null. Added an observability regression test.\n\n13/13 pass. Bar re-verified: paidEnabled:false, paidCalls:0, paidCallsToday:0, $0.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"1ab5eb8","date":"2026-09-23 12:45:20 -0700","author":"Steve Abrams","subject":"dotbar/jev: price-independent daily call-COUNT cap as the real paid backstop","body":"The dollar cap sums the ledger at a PLACEHOLDER $0.001/call rate, so with the\nreal TypeSafe price unknown it may never trip under cache-gated volume —\neffectively uncapped in real dollars. Add maxPaidCallsPerDay (default 800, env\nDOTBAR_JEV_MAX_CALLS) that bounds worst-case spend to (calls x unknown price)\nregardless of the rate. countPaidCallsToday() counts today's app+api ledger\nrows, fail-closes to Infinity on any read error, composes with the dollar cap\n(paid fires only if under BOTH), reserves in-loop so a burst within one refresh\ncan't exceed the cap, and surfaces paidCallsToday/maxPaidCallsPerDay/\ncountCapBlocked on /api/jev. start-bar.command stages the arm flags OFF\n(DOTBAR_JEV_PAID=0, auto-snapshotted in de2776c). Negative tests prove the\nguard goes red on injected at-cap + burst faults and countPaidCallsToday\nfail-closes; 12/12 pass. No paid call fired; bar stays on the $0 builtin.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"de2776c","date":"2026-09-23 12:42:32 -0700","author":"auto-commit-fleet","subject":"auto-data-snapshot: 2026-09-23T12:42:16 (1 data files) — start-bar.command","body":""},{"hash":"d56df0f","date":"2026-09-23 12:35:47 -0700","author":"Steve Abrams","subject":"dotbar: mark orphaned sessions (live claude, no iTerm2 tab) so open-terminal only shows for focusable tabs","body":"Cross-references iTerm2's attached-session ttys (split-pane-safe index walk) against\nallcolordots' process-based live list. Rows whose claude survives under iTermServer with\nno tab now render 'orphaned - no tab' instead of a dead-end 'open terminal' button.\nFixes 'open terminal never works' (79% of rows were orphans).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"cf77e2f","date":"2026-09-23 11:56:07 -0700","author":"Steve Abrams","subject":"Jev classifies dotbar dot colors ($0 builtin default; paid TypeSafe flip gated off)","body":"Re-decide each active terminal's displayed dot color through a Jev-style typed\nchoice at the dotbar's own getDots() seam. allcolordots.sh is untouched (no fleet\nregression); Jev unavailable/capped/errors falls back to the heuristic color.\n$0 builtin classifier by default; paid path unreachable unless DOTBAR_JEV_PAID=1\nand provably under a $5/day cap (fail-closed). Per-terminal state-hash cache gates\nreclassification to real transitions only. /api/jev exposes the counters.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_019excZ7L7VE14hbPqKQqH3i"},{"hash":"26f22db","date":"2026-09-23 11:36:21 -0700","author":"Steve Abrams","subject":"dotbar: ticket states as vertical chips with right-edge labels","body":"Render blocked/open/idle/doing/parked as individual vertical .chip elements\n(colour dot + count left, state word pushed to the right edge via margin-left:\nauto) matching the colour-dot chips above, replacing the cramped horizontal\n🔴/⚪/⚫ segment footer. Only non-zero states show; each still opens the Fleet\nboard filtered to its section. Moved into the top cluster (before the spacers)\nso they read as a continuation of the list, not a bottom footer.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_019excZ7L7VE14hbPqKQqH3i"},{"hash":"385c3af","date":"2026-09-23 11:11:03 -0700","author":"Steve Abrams","subject":"dotbar: free-position persistence — bar stays where dragged, across restarts (TK-12072)","body":"Steve: \"once moved, keep the nav bar where relocated\" → free-position mode.\n\nelectron-main.js:\n- .barcfg gains floating(bool) + pos(displayId→{x,y,w,h}); readCfg defaults both\n  cleanly so an old .barcfg still loads docked (backward-compatible).\n- per-window 'moved' listener flips floating on and saves getBounds() once the bar\n  leaves its docked spot by >4px; a programmatic-move guard (progUntil, 250ms window\n  around every internal setBounds via setWinBounds) plus a docked-divergence check\n  stop our own setBounds from being mis-captured as a user drag.\n- boundsFor returns the saved pos (clamped to the visible work area) while floating\n  and never re-snaps; createBarFor opens at the saved pos; off-screen/gone-display\n  positions clamp back on-screen so the bar is always grabbable.\n- pollAutohide no-ops while floating (no edge to slide to).\n- setOrientation/cycleOrientation exit floating and re-dock to the edge (escape hatch).\n- grip setters (setBarH/W/Len) patch the saved pos w/h so a floating bar resizes and\n  remembers its size; flushCfg on before-quit so a drag-then-quit isn't lost.\n\nstart-bar.command: drop a stray DOTBAR_DEBUG=1 an auto-snapshot committed mid-test.\n\nVerified by cycling the live launchd app: floating restores at exact (800,400,520,48);\ndocked cfg still edge-snaps ignoring pos; off-screen (5000,5000) clamps to (2040,957).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_019excZ7L7VE14hbPqKQqH3i"},{"hash":"08b744a","date":"2026-09-23 11:07:07 -0700","author":"auto-commit-fleet","subject":"auto-data-snapshot: 2026-09-23T11:06:44 (1 data files) — start-bar.command","body":""},{"hash":"25e5616","date":"2026-09-23 10:47:35 -0700","author":"Steve Abrams","subject":"Harden ram-sniper toggle + ticket-fetch resilience (TK-12071 test findings)","body":"Fix #2: resolve the ram-sniper daemon by exact PID (a shell interpreter\nexecuting the script) and kill by PID, replacing the broad `pkill -f\nbin/ram-sniper.sh` that SIGTERM'd any process merely mentioning the path\n(editors, pgrep shells). See pgrep-f-matches-own-watcher-shell.\n\nFix #1: keep-last-good in getTickets/refreshTickets, mirroring getDots.\nA dead ticket board makes curl return '' which JSON.parse('[]')'d cleanly\nto [] and zeroed every count; now an empty/unparseable body returns null\nand the last-good snapshot is kept instead.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_019excZ7L7VE14hbPqKQqH3i"},{"hash":"36f503b","date":"2026-09-23 10:33:50 -0700","author":"Steve Abrams","subject":"dotbar: fix ticket-segment clicks — Electron can't window.open() an external URL; POST to /api/open-board which shells to macOS open (same pattern as reveal)","body":"Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_017VyZZwbLBMfoBmdLGuxBuD"},{"hash":"fa6b41e","date":"2026-09-23 10:19:37 -0700","author":"Steve Abrams","subject":"dotbar: each ticket state (blocked/open/idle/doing/parked) is individually clickable → loads that filtered Fleet board section","body":"Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_017VyZZwbLBMfoBmdLGuxBuD"},{"hash":"0347444","date":"2026-09-23 10:12:52 -0700","author":"Steve Abrams","subject":"dotbar: ticket summary centered in the middle band, 5 live states (blocked/open/idle/doing/parked), fix auth + 8MB buffer for the 4.5MB board payload","body":"Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_017VyZZwbLBMfoBmdLGuxBuD"},{"hash":"4ad7b46","date":"2026-09-23 10:05:26 -0700","author":"Steve Abrams","subject":"dotbar: merge ticket-board summary (BLOCKED/DOING/OPEN counts) + retire TicketBar (launchd bootout, code preserved)","body":"Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_017VyZZwbLBMfoBmdLGuxBuD"},{"hash":"b05080a","date":"2026-09-23 09:51:33 -0700","author":"Steve Abrams","subject":"dotbar: RAM chip shows real memory pressure, not cache-inflated used% (96%->44%) + green/amber/red bands","body":"Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_017VyZZwbLBMfoBmdLGuxBuD"},{"hash":"fa809cb","date":"2026-09-23 09:39:15 -0700","author":"Steve Abrams","subject":"dotbar: visible dotted resize grip + one-click Compact/Full toggle button","body":"Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_017VyZZwbLBMfoBmdLGuxBuD"},{"hash":"60eea92","date":"2026-09-22 10:24:26 -0700","author":"Steve Abrams","subject":"Fix RAM missing on the bar: move RAM/CPU readout into the always-visible left chip cluster","body":"The bar is a right-docked vertical strip; the RAM chip was in #meta (bottom of\nthe column) with RAM/CPU as a split .cnt/.nm pair, so RAM clipped while CPU showed.\nNow it sits with the dot chips (top of the strip) as one atomic .cnt span\n(🧠 RAM% ⚙ CPU%), plus the 🔫 ON/OFF toggle. Verified rendering on both displays.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01AztR94xH5K8nBe9ssBoagG"},{"hash":"34abb18","date":"2026-09-22 10:13:09 -0700","author":"Steve Abrams","subject":"Add RAM Sniper to the nav bar: live RAM%/CPU% chip, ON/OFF daemon toggle, top-hogs dropdown","body":"- server.js: /api/ram (top -l1 + sysctl + ps, zero-dep, cached 2s) and\n  POST /api/ram/toggle (start/stop ~/bin/ram-sniper.sh, pgrep-f path-qualified)\n- index.html: 🧠 RAM% ⚙ CPU% chip in #meta, 🔫 ON/OFF toggle, click-to-open\n  top-memory dropdown reusing the existing panel pattern\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01AztR94xH5K8nBe9ssBoagG"},{"hash":"b102cca","date":"2026-09-20 11:29:57 -0700","author":"Steve","subject":"desktop-dotbar: collapsed PARKED chip/panel from the durable registry","body":"Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01QZehHfR2cgtmFvznNavrn5"},{"hash":"d88f4e1","date":"2026-09-17 11:01:42 -0700","author":"Steve Abrams","subject":"dotbar: horizontal contract/expand for the top bar (right-end length grip)","body":"Top bar was locked to full screen width. Add a left-anchored barLen config +\nsetBarLen IPC (main+preload) and a top-only right-end #gripx (ew-resize) that\ndrags the bar's horizontal span; snaps back to full at the screen edge, clamped\nper display, persisted in .barcfg. Side docks unchanged (main #grip owns width).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01Mx9jXp5vC4sft858UfivPN"},{"hash":"2415402","date":"2026-09-17 10:14:21 -0700","author":"Steve Abrams","subject":"chore: v1.1.0 — nav bar edge auto-hide + orientation toggle (session close)","body":"Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_017XJaU3fPAuhfFTynAAJmev"},{"hash":"62b3811","date":"2026-09-17 10:11:51 -0700","author":"Steve Abrams","subject":"dotbar (TK-11885): edge auto-hide + top/left/right orientation toggle","body":"Both nav-bar behaviors Steve asked for, in the in-scope Electron app:\n(a) EDGE AUTO-HIDE — 📌 Pinned / 👁 Auto-hide toggle. When on, each strip\n    slides off its docked edge leaving a 3px peek and slides back in when the\n    cursor hits that edge. Cursor-polled (screen.getCursorScreenPoint every\n    110ms) because the panel is non-focusable, so DOM hover can't see an\n    off-screen bar; hysteresis via a 320ms hide-grace so it doesn't flap; an\n    open dropdown or an active grip-drag pins it open.\n(b) ORIENTATION top<->left<->right — one-click dock cycle, so a SIDE bar can\n    be reverted back to a TOP bar. Side docks render the strip as a vertical\n    column (chips stacked, controls at the bottom), grip becomes an ew-resize\n    width handle; prefs persist to .barcfg.\n\nDefault state (top + pinned) is byte-identical to prior behavior — the\nauto-hide poll early-returns when off, so no regression at rest. All 18\norientation x open x hidden bounds combos verified on both displays.\nReversible, local Electron/CSS/JS only.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_017XJaU3fPAuhfFTynAAJmev"},{"hash":"5bfe0b0","date":"2026-09-17 08:29:12 -0700","author":"Steve Abrams","subject":"keep desktop bar supervised by launchd","body":""},{"hash":"8db4601","date":"2026-09-17 08:21:42 -0700","author":"Steve Abrams","subject":"wire arrange bar to master router","body":""},{"hash":"534bea8","date":"2026-09-16 11:54:30 -0700","author":"Steve Abrams","subject":"dotbar: surface Arrange outcome on the button instead of swallowing errors","body":"Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01MtzMyVz6sH79QSHLZzQMEZ"},{"hash":"2f67aa2","date":"2026-09-16 10:42:58 -0700","author":"Steve Abrams","subject":"dotbar: render a strip on EVERY display (Arrange button reachable on both monitors)","body":"One BrowserWindow per screen, pinned to each display's top edge; dropdown-open tracked\nper-window, grip-resize applied to all; rebuilds on monitor plug/unplug. (Steve 2026-09-16)\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_013Szengr4hMUDtYdw3jSCfA"},{"hash":"158144e","date":"2026-09-16 10:42:53 -0700","author":"auto-commit-fleet","subject":"auto-data-snapshot: 2026-09-16T10:40:23 (1 data files) — electron-main.js.bak-single-20260916T174147Z","body":""},{"hash":"71dbcd1","date":"2026-09-16 10:15:08 -0700","author":"Steve Abrams","subject":"dotbar: add top-strip Arrange button — one-click re-tile every screen via the dot-screen router","body":"Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_013Szengr4hMUDtYdw3jSCfA"},{"hash":"0d25ad6","date":"2026-09-16 09:11:31 -0700","author":"Steve","subject":"dotbar: drop bare-Tab global resize hotkeys; keep drag grip (DTD-D 2026-09-16)","body":"A bare Tab/Shift+Tab registered via Electron globalShortcut is consumed OS-wide\nwhile armed, so Tab silently died in the focused app whenever the mouse hovered\nthe top-of-screen strip; mouseleave could also be missed, leaving Tab hijacked.\nAn informed DTD panel (Claude+Codex+Qwen unanimous) chose D: remove the keyboard\npath entirely since the drag grip already covers resize, eliminating the whole\nbug class (no global shortcut, no arm/disarm state).\n\nAlso:\n- perf: setBarH no longer writes .barh to disk or re-asserts always-on-top on\n  every pointermove during a grip drag; disk write is debounced to drag-settle.\n- grip hit target: anchor the grip fully inside the closed-bar window so it isn't\n  a ~4px sliver (it's the sole resize affordance now).\n- gitignore the runtime .barh file (its sibling .port was already ignored).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01FFLLQmm7wJFvyHQkBb5Y21"},{"hash":"f72f77b","date":"2026-09-16 08:38:13 -0700","author":"Steve Abrams","subject":"dotbar: keep-last-good so a slow/empty scan never flaps the live count to 0","body":"The allcolordots scan can take 60-90s on a loaded box with many sessions; a timed-out\nor empty scan returns 0 rows and was overwriting the good snapshot with total:0 (the bar\nflipped back to '0 live'). Now refresh() only replaces the snapshot on a real result (>0)\nor the first run, and the execFile cap is 120s. The bar holds the last good count between\nslow refreshes instead of zeroing.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01AuZ7T3ffxRGXj5rrwgbquD"},{"hash":"ef1d433","date":"2026-09-16 08:31:20 -0700","author":"Steve Abrams","subject":"dotbar: fix '0 live' (scan timeout) + resizable bar (drag/Tab/Shift+Tab)","body":"- 0 live: allcolordots --json takes ~9s but server execFile cap was 8s -> every\n  refresh timed out -> empty -> '0 live'. Bumped to 25s. Now shows 48 live.\n- Resizable strip: drag the bottom grip (screen-Y absolute setBarH), or Tab=expand /\n  Shift+Tab=contract while the pointer is over the bar (hover-scoped globalShortcut so\n  Tab isn't hijacked fleet-wide). Height clamped 22-140px, persisted to .barh.\n- Launcher: start-bar.command used `command -v node` which is empty under launchd\n  kickstart (no homebrew in PATH) -> server never started on a launchd restart. Added\n  absolute-path fallback so launchctl kickstart works.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01AuZ7T3ffxRGXj5rrwgbquD"},{"hash":"aa5dd2c","date":"2026-09-15 18:47:51 -0700","author":"Steve Abrams","subject":"TK-11794: pulse the 4 needs-Steve dots on the bar; green/pink stay solid","body":"The REAL visible pulse (Steve 2026-09-15 dot-flash directive): a CSS @keyframes\ndotpulse animation on the always-on-top bar — one already-running process animates\nthe waiting rows, no per-tab background loop. WAIT set {lightblue,orange,purple,\nyellow} (exact match to server.js /api/dots color keys) gets .pulse on both the\nbar chip .dot and the panel-row .rdot; green/pink are excluded so they render\nsolid. Respects prefers-reduced-motion (animation:none). Verified live on :9787\n(HTTP 200, a lightblue session present and pulsing).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01HKMY3eXqwFUCfqDShfUVnH"},{"hash":"ead5ad7","date":"2026-09-15 18:27:31 -0700","author":"Steve","subject":"debounce dropdown auto-close (2 ticks); login autostart via LaunchAgent","body":""},{"hash":"ca97694","date":"2026-09-15 18:16:40 -0700","author":"Steve","subject":"Gate dbg() debug.log writes behind DOTBAR_DEBUG=1 to prevent unbounded log growth","body":"Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01Pnon7dut9MfPekhhm9YY4Q"},{"hash":"98783dc","date":"2026-09-15 18:10:37 -0700","author":"Steve","subject":"stop tracking transient .port","body":""},{"hash":"994870a","date":"2026-09-15 18:10:21 -0700","author":"Steve","subject":"Electron always-on-top strip: color-dot counts, ticket dropdowns, jump-to-terminal, cached feed","body":""},{"hash":"1f2db8a","date":"2026-09-15 17:43:42 -0700","author":"Steve","subject":"desktop-dotbar: always-on-top color-dot nav strip with ticket dropdowns + jump-to-terminal","body":""}]}