The main process watched every team directory under ~/.claude/teams (one shallow
chokidar target per team root, per team inboxes, and per task dir). On macOS this
falls back to kqueue, which needs one fd per watched file, so a workspace with
many teams kept ~1600 descriptors open and made startup and reconcile work scale
with the number of teams on disk.
Scope the team-root and task watching to teams that are running or currently
engaged in the UI. The teams root and every team's inboxes are still watched for
all teams, so cross-team message delivery, the lead inbox->stdin relay, and
notifications are unchanged. Idle teams are static, so dropping their team-root/
task watches is safe; opening a team (getData) or launching it re-adds it via an
immediate watch-scope refresh. The provider falls back to watching every team
when unset, and the EMFILE polling fallback is intentionally left unscoped so a
scope change can never look like a deletion.
Measured on a 162-team workspace: open team fds 1600 -> 730, with team-root
watching restored the moment a team is opened or goes live.
The failure.message passed to ensureOpenCodeProfileNodeModulesJunction
comes from normalizeCommandFailure which may produce a JSON-escaped
string when the error contains structured JSON in stdout. Using the
raw runtimeMessage literal causes a mismatch in CI. Switch to
expect.any(String) to accept any string value for the errorMessage
parameter while still verifying the call happens.
- Extract symlink source/target paths directly from the error message
instead of reconstructing them from process.env (Codex P2 review)
- Add extractSymlinkSourcePath and extractSymlinkTargetPath functions
- Update ensureOpenCodeProfileNodeModulesJunction to accept optional
errorMessage parameter and use extracted paths from it
- Fix unused imports in test (remove 'os', replace 'beforeEach' with
'afterEach' per CodeRabbit review)
- Widen fs.statSync mock signatures to use Parameters<typeof fs.statSync>
per CodeRabbit review
- Add tests for new extraction functions
- Pass errorMessage to ensureOpenCodeProfileNodeModulesJunction calls
in CLI client tests
On Windows 10 without Developer Mode, the OpenCode runtime fails to create
a symlink from shared-cache/config-node_modules to the profile's
node_modules directory. The EPERM error blocks the entire OpenCode provider
catalog, leaving it unavailable.
Changes:
- New openCodeWindowsNodeModulesJunction module that pre-creates a Windows
directory junction (no Developer Mode required) before the runtime call
when an EPERM symlink error is detected
- On Windows, loadView and loadProviderDirectory now detect EPERM symlink
errors, extract the profile ID, create the junction, and retry the
runtime command once before falling back to the error response
- Updated diagnostic hints to accurately reflect that the runtime does not
yet include junction fallback, and that the next runtime update will
include it
- Added unit tests for the junction module and retry behavior