Skip to content

Windows/Git Bash: agmsg_agent_pid never resolves (MSYS ppid walk cannot cross into native processes) — cc-instance.* is never written, actas locks always GC as stale, despawn reports no-live-lock #371

Description

@tatsuya582

Environment

  • agmsg: 1.1.6 (install.sh --cmd agmsg --agent-type claude-code)
  • Host agent: Claude Code (native Windows install)
  • OS: Windows 11 Home (10.0.26200)
  • Shell: Git for Windows 2.42.0 / GNU bash 5.2.15 (MSYS), uname -s = MINGW64_NT-10.0-26200
  • sqlite3 3.53.3 on the Git Bash PATH

Symptom

Everything user-visible works well on Windows (join, send/inbox, monitor delivery, spawn with a custom spawn.terminal template, readiness handshake). But:

  • Every script that derives an instance id prints:
    agmsg: instance-id falling back to bare session_id (agent pid unresolved for type=claude-code); parallel --continue/--resume isolation is degraded
  • despawn.sh <team> <from> <name> always answers
    '<name>' holds no live actas lock — nothing to confirm a teardown against — even while the spawned member's session is alive, actively working, and its watcher is receiving messages.
  • $SKILL_DIR/run/ never contains any cc-instance.<pid> files and no actas.*.session files survive (they are GC'd as stale almost immediately).

Root cause

compat_get_ppid (scripts/lib/compat.sh) walks the parent chain with MSYS ps -l. MSYS ps only sees MSYS-world processes — the walk terminates at the MSYS pseudo-init (pid 1) as soon as it reaches the boundary to the native Windows process tree, so it can never reach the enclosing Claude Code process (a native node.exe/claude.exe).

Measured from a Claude Code Bash tool on this machine:

hop1: pid=37113 -> ppid=37111
hop2: pid=37111 -> ppid=1      <- MSYS boundary; native ancestors are invisible
agmsg_agent_pid claude-code    -> "" (falls back to bare session_id)

Consequence chain

  1. agmsg_agent_pid always fails → every token degrades to the bare session_id (the documented fallback in instance-id.sh).
  2. session-start.sh resolves CC_PID="" → the cc-instance.$CC_PID liveness record is never written.
  3. agmsg_instance_alive(<bare sid>) scans cc-instance.* — there are none — so every bare token is judged dead.
  4. actas locks (whose owner tokens are bare) always look stale → actas_lock_gc_stale reclaims them on the next pass → despawn finds no live lock, and the Parallel claude --continue / --resume sessions share session_id, breaking actas lock distinctness #93 parallel-resume isolation is fully degraded on Windows.

Notably, the liveness check itself is already Windows-aware (_agmsg_pid_alive uses tasklist for native pids, #134). Only the resolution of the agent pid is broken — if a composite <sid>.<native pid> token existed, everything downstream would work.

Suggested fix direction

In the msys branch of compat_get_ppid (or in agmsg_agent_pid), when the MSYS-side walk hits the boundary without finding the agent: translate the current pid to its native pid via the existing _compat_get_winpid helper, then continue the walk in the native process tree, e.g.

powershell -NoProfile -Command "(Get-CimInstance Win32_Process -Filter 'ProcessId=<winpid>').ParentProcessId"

(or wmic process where ProcessId=<winpid> get ParentProcessId on older systems), matching the type's detect_proc names against native image names (claude.exe, node.exe running the claude CLI). _agmsg_pid_alive's tasklist path already validates such native pids.

Happy to test a patch on this environment — the failure reproduces deterministically here.

Workaround we use meanwhile

Teardown via the terminal manager instead of despawn (close the member's pane/tab, then reset.sh <project> <type> <agent>); operationally fine, just loses the graceful ctrl:despawn path.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions