Skip to content

fix: handle Windows path separators in the TS layer - #17

Merged
SuperLogicAI merged 1 commit into
SuperLogicAI:mainfrom
zeiddata-dev:fix/windows-path-separators
Sep 6, 2026
Merged

fix: handle Windows path separators in the TS layer#17
SuperLogicAI merged 1 commit into
SuperLogicAI:mainfrom
zeiddata-dev:fix/windows-path-separators

Conversation

@zeiddata-dev

Copy link
Copy Markdown
Contributor

Closes #8.

Two spots assumed POSIX paths and a / filesystem root.

1. Accomplished panel filename — src/lib/repo.ts

Built its filename by splitting on /, so a Windows file_path was never shortened and the row rendered the whole C:\Users\x\dev\proj\main.rs instead of main.rs.

The basename moves out of listToolEvents into an exported basename(). It had to be exported to be testable, which matches how dedupeKey, scopeBySession and latestPerTether are already covered.

2. The root guard — src/lib/ingest.ts

This is the half that matters. bindSession refuses / because an untethered session with a rootless cwd would otherwise bind to an arbitrary tab and overwrite its cwd with a key that matches nothing, blanking the panel. A Windows drive root is the identical hazard and walked straight through.

The replacement is anchored and exact rather than a prefix test, deliberately: over-rejecting here would silently stop every real Windows session from binding — a worse bug, and a far quieter one, than the drive root the guard exists to catch.

So bind-check now covers both directions:

  • five rootless keys that must be refused (C:\, C:/, C:, \, d:\)
  • two real Windows project paths that must still bind

The second group is the one I'd actually want reviewed.

Both new cases were run against the old code first

Tests that can't fail aren't worth adding, so I downgraded both lines to the pre-fix logic and confirmed the new assertions catch the real bugs:

  • bind-checkAssertionError: a rootless session (C:\) hijacked the active tab
  • scope-checkAssertionError: backslash path not shortened

Restored; both green.

A judgement call worth flagging

The issue says where the guard's case belongs (bind-check, not a new harness) but not where the basename case goes. scope-check was the nearest existing home, so its header widens from "panel session scoping" to "panel row shaping" rather than adding a tenth check script. Happy to move it if you'd rather it lived elsewhere.

Explicitly out of scope

Still Mac-only, tracked in docs/ROADMAP.md § "Windows port": hook_command's sh -c, pty_spawn's $SHELL, clipboard.rs's pbpaste, and the Rust-side $HOME lookups (#7).

Verification

npx tsc --noEmit clean; all nine check scripts pass on this branch.

🤖 Generated with Claude Code

https://claude.ai/code/session_01WyeecwdT2gD3fxeWkJpTKa

Two spots assumed POSIX paths and a `/` filesystem root.

The Accomplished panel built its filename by splitting on `/`, so a Windows
`file_path` was never shortened and the row rendered the whole
`C:\Users\x\dev\proj\main.rs` instead of `main.rs`. The basename moves out of
listToolEvents into an exported `basename()` — it had to be exported to be
testable, which matches how dedupeKey, scopeBySession and latestPerTether are
already covered.

The one that matters is the root guard in bindSession. It refuses `/` because an
untethered session with a rootless cwd would otherwise bind to an arbitrary tab
and overwrite its cwd with a key that matches nothing, blanking the panel. A
Windows drive root is the identical hazard and walked straight through.

The replacement is anchored and exact rather than a prefix test, on purpose:
over-rejecting here would silently stop every real Windows session from binding,
which is a worse bug and a far quieter one than the drive root the guard exists
to catch. So bind-check now covers both directions — five rootless keys that
must be refused, and two real Windows project paths that must still bind.

Both new cases were run against the old code first, to be sure they could fail:
bind-check with "a rootless session (C:\) hijacked the active tab", scope-check
with "backslash path not shortened".

scope-check was the nearest existing home for the basename cases, so its header
widens from "panel session scoping" to "panel row shaping" rather than adding a
tenth check script.

Out of scope, still Mac-only, tracked in ROADMAP § "Windows port": hook_command's
`sh -c`, pty_spawn's `$SHELL`, clipboard.rs's pbpaste, and the Rust-side $HOME
lookups (SuperLogicAI#7).

npx tsc --noEmit clean; all nine check scripts pass.

Closes SuperLogicAI#8

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WyeecwdT2gD3fxeWkJpTKa
@SuperLogicAI
SuperLogicAI merged commit c4c3a44 into SuperLogicAI:main Sep 6, 2026
3 checks passed
@zeiddata-dev
zeiddata-dev deleted the fix/windows-path-separators branch September 6, 2026 09:19
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.

Windows: TS layer assumes POSIX separators (basename + root-project-key guard)

2 participants