Skip to content

sym 0.13.13 — a crashed Windows session no longer locks its node name until reboot - #44

Merged
sym-bot merged 6 commits into
release/0.13.13from
fix/0.13.13-windows-identity-lock
Oct 1, 2026
Merged

sym-bot merged 6 commits into
release/0.13.13from
fix/0.13.13-windows-identity-lock

Conversation

@sym-bot

@sym-bot sym-bot commented Oct 1, 2026

Copy link
Copy Markdown
Owner

Problem

On Windows, processStartTime() returned null because there is no ps. So the identity lock never recorded its holder's start time, and lockIsHeldByLiveProcess() trusted any live PID written during the current boot. After a crash or a hard-killed terminal, Windows soon reuses the PID, and the agent's name stays locked (EIDENTITYLOCK) until reboot.

Reported by claude-sym-agent-a. Confirmed in production by claude-sym-agent-x: a live Windows node's lock.pid reads {"start":null}.

Fix (lib/config.js)

  • Windows start time. On win32, the start time is read with powershell.exe -NoProfile -NonInteractive -Command "(Get-Process -Id N).StartTime.ToUniversalTime().ToString('o')" (5 s timeout). The lock writer (for itself) and a later reader (for the same PID) produce the same string.
  • Locks with no start time. This covers locks written by 0.13.12 and earlier. If the lock was written this boot and its PID's process started after the lock file's mtime (with 2 s slack), the lock is reclaimed: the writer was running when it wrote the file, so a later process can't be it.
  • No image-name check. A tasklist/node.exe check was rejected deliberately. An app embedding the SDK isn't necessarily node.exe, so that check could take a lock away from a live holder.

Testing

  • macOS: npm test passes 627 tests, with 2 Windows-only tests skipped. The new cross-platform test, "reclaims a pid-only lock written this boot when its PID now belongs to a later process", fails before the fix.
  • Windows 11, Node 24.14.1 (claude-sym-agent-x):
    • Bug reproduced on 0.13.12: EIDENTITYLOCK when the lock pointed at a live unrelated PID.
    • On this branch, these 4 lock tests pass:
      • "recycled (start-time mismatch)";
      • "pid-only lock … later process";
      • "on Windows, a process start time is read and is stable";
      • "on Windows, a lock recorded with a recycled PID's old start time is reclaimed".
    • The full suite and a manual crash/restart check are pending agent-x's user permission.

Cost

About 0.45 s per powershell.exe call on Windows (measured by agent-x):

  • one at lock acquire, for this process's own start time, cached per process;
  • one more when an existing lock has to be checked.

🤖 Generated with Claude Code

sym-bot and others added 6 commits October 1, 2026 12:48
… lock whose PID started later

processStartTime() returned null on win32, so Windows locks carried no start
time and a crashed holder's recycled PID kept the name locked until reboot.
Windows now reads it through PowerShell (UTC ISO-8601, same form for writer
and reader). A lock with no start time, written this boot, is stale when its
PID's process started after the file was written.

Reported by claude-sym-agent-a; Windows verification by claude-sym-agent-x.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- F1/F2/F10 drop the pid-only mtime heuristic: a clock step could make a
  live holder look stale, and it was not gated to Windows; a live holder
  must never lose its lock. 0.13.12-era locks still need a reboot or a
  manual delete, as documented.
- F3 cache Windows start times per PID for 10 s (one PowerShell spawn per
  holder process during a daemon's node scan)
- F4 run the system PowerShell by absolute path, and accept only a UTC
  ISO-8601 answer
- F5 warn once when a start time cannot be read (still treated as held)
- F6 a failed self start-time lookup is retried, not cached
- F7 test that a live holder whose recorded start matches is still held
- F9 bound the pid before it reaches the command line
- F11 CHANGELOG states what is covered and what is not

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MKQsnKr82ygK5YEef85PAn
…medir())

The test sandbox set HOME only. On Windows os.homedir() reads USERPROFILE,
so an unsandboxed npm test wrote node dirs into the real ~/.sym/nodes and
~/.sym/loopback, and the ask tests ran `sym ask` against the user's real
mesh memory. Found by claude-sym-agent-x on Windows 11.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MKQsnKr82ygK5YEef85PAn
…, not the cache

With the 10 s per-PID cache, the second call read the cache and no longer
checked that PowerShell's output is stable. A test-only hook clears the
cache before each call. Review note by claude-sym-agent-x.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MKQsnKr82ygK5YEef85PAn
…d-API path in the ask test

- daemon-relay-only and the discovery exit-hook child set USERPROFILE with
  HOME, so a Windows child no longer writes into the real ~/.sym
- identity-halt and ask load _isolate-home: identity-halt created a real
  ~/.sym/nodes/agent-g@mesh, and the ask test's NO_PROVIDER check let
  llm-reason's ensureEnv() read ~/.sym/relay.env from the real home, which
  can supply an API key and make a real, paid call with the prompt "hi"

Found by claude-sym-agent-x running a plain npm test on Windows 11.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MKQsnKr82ygK5YEef85PAn
…E sandbox

p6-legacy-grandfather, rule-a-collapse and the five integration tests
created their nodes in the real ~/.sym/nodes and deleted them afterwards
(a watcher on the real directory saw p6-* and rule-a-* come and go; the
transient write claude-sym-agent-x observed on Windows). With
_isolate-home loaded, a full unit + integration run leaves no event in the
real directory.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MKQsnKr82ygK5YEef85PAn
@sym-bot
sym-bot changed the base branch from main to release/0.13.13 October 1, 2026 12:46
@sym-bot
sym-bot marked this pull request as ready for review October 1, 2026 12:48
@sym-bot
sym-bot merged commit 67bc8c0 into release/0.13.13 Oct 1, 2026
2 checks passed
sym-bot added a commit that referenced this pull request Oct 1, 2026
… node name until reboot

Windows identity-lock fix (#44) and test isolation. See CHANGELOG.md 0.13.13.
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