Skip to content

Fix #1034: split transcript basenames on backslash too, so the scan cache works on Windows - #1035

Merged
fdaviddpt merged 1 commit into
mainfrom
fix/1034-backslash-transcript-basename
Oct 17, 2026
Merged

fdaviddpt merged 1 commit into
mainfrom
fix/1034-backslash-transcript-basename

Conversation

@fdaviddpt

Copy link
Copy Markdown
Contributor

Closes #1034

Diagnosis and the proposed expansion are @RidoMr's, from the issue: thank you for the clear repro and the before/after numbers.

What was wrong

Claude Code on Windows sends transcript_path as a native C:\Users\...\<session-id>.jsonl path. After #829 decodes the JSON escapes, TRANSCRIPT holds single backslashes and no / at all. post-tool-hook.sh derived basenames with ${TRANSCRIPT##*/}, so the whole path survived, failed the [A-Za-z0-9._-] sanitiser and came out empty. The #913 tmp/transcript-scan.<id> sidecar was then never read or written, and every PostToolUse call outside the save cooldown cold-rescanned the whole transcript. Nothing was logged.

Change

Tests (tests/test_post_tool_backslash_transcript_basename_1034.py)

Runs the real hook with a stdin payload, through resolve_bash() so it runs on the Windows leg (unlike the #913 module, which is skipped there).

  • Native backslash transcript_path writes tmp/transcript-scan.<id> after one call -- Windows only, because str(Path) there is the real native shape. Skipped elsewhere with a reason: on POSIX a backslash is a filename byte, so it would be a different file, not the Windows path.
  • Forward-slash transcript_path, same fixture -- positive control, every platform.
  • SESSION_ID fallback (no session_id in the payload) checked through tmp/capture-alive.d/<id>: backslash case on Windows, forward-slash control everywhere.
  • POSIX-only: a file whose name literally contains backslashes now splits at the last one. This pins the one behaviour change the fix makes on POSIX; it is not Windows evidence. It is also what let me watch the module go red locally.
  • Guard: an unusable name (bad+name.jsonl) logs the warning exactly once across two calls (must fire); a good name logs nothing (must not fire).

Observed vs reasoned

🤖 Generated with Claude Code

[AI-generated]

…can cache works on Windows

Claude Code on Windows sends a native C:\Users\...\<id>.jsonl transcript_path;
after #829 decoding it holds no '/', so ${TRANSCRIPT##*/} kept the whole
path, the sanitiser emptied it, and the transcript-scan sidecar was never
read or written: every PostToolUse call cold-rescanned the transcript.

Split on both separators at all three basename sites (scan-cache name,
SESSION_ID fallback, log text). The sanitiser is unchanged. An empty
cache name now logs one warning per transcript, fork-free.

Reported and diagnosed by @RidoMr.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
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.

post-tool-hook.sh: transcript-scan cache is never used on Windows (backslash transcript_path), so every PostToolUse call rescans the whole transcript

1 participant