- Add tool annotations (readOnlyHint, destructiveHint, idempotentHint, openWorldHint) to all 23 tools
- Add isError flag to error responses (403, 503, KB not ready) for proper MCP error signaling
- Replace global token state with AsyncLocalStorage to prevent cross-session token leaks
- Add session TTL cleanup (12h interval, 2h max age) for abandoned sessions
- DRY server version string from package.json instead of 3x hardcoded
- Split 1060-line tools.ts into domain modules: sessions (359), search (353), admin (351)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
PowerShell 5.1 (used by IME) reads scripts without BOM as ANSI,
corrupting UTF-8 multi-byte chars (em-dashes, Unicode symbols) and
causing cascading parse errors that prevented agent installation.
Replaced all non-ASCII characters with ASCII equivalents in both
Install and Uninstall bootstrap scripts.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Self-review fixes for the EnrollmentTracker locking commit:
- NotifyDesktopArrived: move _logger.Debug outside lock (no I/O under lock)
- CollectDeviceInfoAtFinalizingSetup: same pattern
- EmitEnrollmentFailed: wrap _stateData.SignalsSeen copy in lock via
SnapshotSignalsSeen() to prevent InvalidOperationException if
RecordSignal modifies the list concurrently
- WriteFinalStatus: same fix for SignalsSeen access
https://claude.ai/code/session_01EWzmYXFmXUaPpeksi6WGKZ
All mutable state fields accessed from multiple threads (timer callbacks,
ImeLogTracker events, EspAndHelloTracker events, desktop detection,
background Task.Run) are now protected by a single _stateLock.
Key fixes:
- TryEmitEnrollmentComplete: atomic guard-check-and-claim prevents double
enrollment_complete emission (the most critical race condition)
- RecordSignal: List<string> mutations are now thread-safe
- NotifyDesktopArrived: atomic check-and-set prevents duplicate processing
- CollectDeviceInfo: _enrollmentType/_skipUserStatusPage writes are visible
to concurrent readers immediately after lock release
- OnHelloCompleted/OnWaitingForHelloSafetyTimeout: consistent multi-field
reads prevent wrong branch selection
- SummaryTimerCallback: _stateDirty flag and _stateData serialization are
synchronized to prevent corrupted state persistence
- EmitAppTrackingSummaryIfChanged: hash comparison is atomic to prevent
duplicate summary events
Lock discipline: all lock sections contain ONLY field reads/writes — no
_emitEvent, _logger, timer operations, or external callbacks. This
guarantees no deadlocks and microsecond-level contention.
https://claude.ai/code/session_01EWzmYXFmXUaPpeksi6WGKZ