Skip to content

fix(server): macOS support for live gjc session detection — remove Linux-only lsof/proc/locale assumptions - #1

Open
thisisjun786 wants to merge 2 commits into
devswha:feat/gjc-providerfrom
thisisjun786:fix/live-sessions-macos
Open

fix(server): macOS support for live gjc session detection — remove Linux-only lsof/proc/locale assumptions#1
thisisjun786 wants to merge 2 commits into
devswha:feat/gjc-providerfrom
thisisjun786:fix/live-sessions-macos

Conversation

@thisisjun786

@thisisjun786 thisisjun786 commented Jul 12, 2026

Copy link
Copy Markdown

Problem

On macOS the sidebar always shows "no gjc sessions running in tmux" even with multiple gjc tmux sessions active (measured: 4 sessions running, 0 detected).

Root causes (Linux-only assumptions in live-sessions.service.ts)

  1. lsof -c gjc matches the process COMM, but a script install runs gjc under its runtime — on macOS the comm is bun, so lsof finds nothing.
  2. The ancestor pid chain (/proc/<pid>/stat) and holder cwd (/proc/<pid>/cwd) depend on /proc, which does not exist on macOS — both lineage matching and the cwd fallback fail wholesale.
  3. Service managers (launchd/systemd) ship no locale env. In a non-UTF-8 locale tmux SANITIZES its output: the \t field separators come back as _ and non-ASCII paths get escaped, so every pane row silently fails to parse (measured under launchd: every session had tmuxName: null, demoting the whole UI to read-only).

Changes

  • Widen the lsof filter to -c gjc -c bun -c node. SESSION_FILE_RE (the session-file path) remains the authoritative filter; -c only bounds scan cost — no false positives.
  • Remove /proc walks: one ps -eo pid=,ppid= snapshot feeds pure helpers parsePidParents/buildPidChain; holder cwds come from one batched lsof -a -p <pids> -d cwd -F pn (parseCwdByPidFromLsof). Single code path for Linux and macOS — no platform branching.
  • Force a UTF-8 LANG in the detection runCommand spawn env (both services).
  • External CLI lane: macOS ps -eo comm prints full executable paths, so claude/codex descendant classification missed everything — normalize comm to basename (test covers a real .app path with spaces).

Verification

  • Unit: 30/30 (tsx --test), 7 new pure-function cases (BSD ps padding, cycle guard, paths with spaces, full-path comm).
  • tsc --noEmit -p server/tsconfig.json and eslint pass.
  • Real machine (darwin arm64, tmux 3.7b): getLiveGjcSessions() went from 0 to 5 sessions, with correct claim grades (lineage/cwd/null) — the lineage-only kill/relay safety contract is unchanged. Same result under a reproduced launchd env (env -i).

Note

PR #2 (idle-lane macOS port) contains this PR as a subset. If you prefer landing everything at once, merge #2 with its base retargeted to feat/gjc-provider and close this one.

gjc 라이브 레인이 macOS에서 항상 0건이었다:
- lsof -c gjc: comm 매칭이라 bun 런타임으로 도는 gjc(comm=bun)를 못 찾음
  → -c gjc -c bun -c node로 확장 (SESSION_FILE_RE가 실질 필터, -c는 비용 절감용)
- /proc/<pid>/stat, /proc/<pid>/cwd: macOS에 /proc 없음
  → 조상 체인은 ps -eo pid=,ppid= 스냅샷 1회, holder cwd는 배치 lsof -d cwd로 대체
  (둘 다 Linux에서도 동일 동작 — 플랫폼 분기 없음)

외부 CLI 레인: macOS ps -eo comm은 실행파일 풀 경로를 찍어 claude/codex
descendant 분류가 전부 미스 → comm basename 정규화.

검증: 유닛 30/30, tsc 통과, 실기(darwin) getLiveGjcSessions() 5건 검출
(lineage/cwd/null 클레임 분류 정상).
launchd/systemd는 로케일 env를 안 준다. 비UTF-8 로케일의 tmux는 출력을
새니타이즈해 \t 필드 구분자가 '_'로 치환되고 비ASCII 경로가 이스케이프됨
→ parseTmuxPanes가 전 행 파싱 실패 → 모든 라이브 세션 tmuxName:null
(실측: launchd 서버에서 UI 전 세션 열람 전용으로 강등, 전송 불가).

runCommand spawn env에 LANG UTF-8 강제 (양 서비스 동일 적용).
검증: env -i(launchd 재현)에서 lineage/cwd 클레임 정상 복원, 유닛 30/30, tsc 통과.
@thisisjun786 thisisjun786 changed the title fix(server): 라이브 세션 감지 macOS 호환 — /proc·lsof -c gjc 리눅스 가정 제거 fix(server): macOS support for live gjc session detection — remove Linux-only lsof/proc/locale assumptions Jul 12, 2026
@thisisjun786

Copy link
Copy Markdown
Author

Review note (independent architect lane over the combined branch): the lsof -c gjc -c bun -c node breadth introduced here can trip the 4MiB/4s subprocess guard on node-heavy hosts and drop the transcript lane for that poll. The fix (pid-scoped lsof -a -p over proven gjc process trees) lives in #2 (commits 0abfd15, fd977cf) because it depends on the argv-evidence helpers from the idle lane. If you merge #1 alone, consider following up with #2 promptly — or tell me and I'll rebase the scoping fix into this branch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant