Skip to content

Talbot, 2026-08-05: “The windows versus WSL challenges continue to haunt me. After decades of using Windows, my WSL use in the last year or two … has resulted in much frustration and system issues such as this one. What additional configuration changes can be made to help reduce these ongoing frustrations? Review all of my tools that are used and see if there can be any hooks or warnings that can help.”

Approved with “go” in my_backup-verification-alert, which also produced the analysis below.

The friction is not diffuse — it is six specific mechanisms, and five are automatable. Every cross-boundary incident in my_backup’s history is one of these:

#MechanismIncidentsThis task
1Wrong-side interpreter — Linux Python can’t see D:, UNC, robocopy, kopia.exe, 7z.exe3× (2026-03-29, 06-01, 08-03)generalise the guard
2Shared-drive .venv poisoning — a bare uv run from either OS rebuilds the other’s venv2× (07-19→26 silent outage; again 08-03)PreToolUse hook + per-project isolation
3Line endings — CRLF written into WSL-side filesongoingCRLF util
4Case sensitivity — NTFS folds case, ext4 doesn’t7-Zip failure 08-01tracked in my_backup-silent-failure-gaps — not here
5Encoding — cp1252 vs UTF-8 through cmd.exev1.5.0; still present in backup.logfold into #1’s guard
6WSL not running — \\wsl$ unreachable, nobody logged on07-30fixed per-job; no general guard needed

Measured CRLF exposure (2026-08-05):

LocationFiles with CRLF
/mnt/d/FSS/Software/Utils29 of 65 (45%)
~/utils16 of 115
~/projects0 of 163

The shared drive — the only tree Windows editors touch — is nearly half CRLF; pure-WSL ~/projects is spotless. git config is already correct (core.autocrlf=input, core.eol=lf, core.safecrlf=warn), which protects committed files but does nothing for untracked files or working-tree drift.

TextPad is a dead end, confirmed by Talbot 2026-08-05: Configure → Preferences → File offers no line-ending option in TextPad 9. Its ConfigState.xml stores every relevant setting as an opaque hex blob, so there is nothing safe to configure. The fix must therefore be outside the editor — which is better anyway, since it then covers Obsidian, VS Code and anything Talbot switches to later.

1. PreToolUse hook — block the .venv poisoning class (highest leverage, do first)

Section titled “1. PreToolUse hook — block the .venv poisoning class (highest leverage, do first)”

Mechanism #2 caused the two worst outages: an 8-day silent backup failure (07-19→26) and a repeat on 08-03. Both originated the same way — a human or agent ran a bare uv run in a shared-drive project from WSL, rebuilding .venv as a Linux venv that Windows uv.exe then could not sync.

  • Add a PreToolUse hook (matcher: Bash) that warns when a command runs uv run / uv sync with cwd under /mnt/<drive>/ and UV_PROJECT_ENVIRONMENT is unset.
  • Use the update-config skill to edit settings.json — do not hand-roll the hook JSON.
  • A shell function in ~/.bashrc is not sufficient and should not be the primary fix: cron does not source the profile. The failures came from interactive/agent sessions, which is exactly what a PreToolUse hook covers. A ~/.bashrc guard may be added as a secondary net for Talbot’s own manual shells.
  • Test both directions: a bare uv run under /mnt/d/... warns; the same command with UV_PROJECT_ENVIRONMENT set, and any uv run under ~/, stay silent.
  • Build in ~/utils/ (WSL-side per the placement rule), registered in Core/IT/Utils/Custom/ as part of creating it — an unregistered util is invisible to the “does a tool already exist” check.
  • Detect mode (default, read-only): report files containing CRLF across configured roots, grouped by tree, with counts. Repair mode: convert in place, opt-in per path.
  • Must not touch files that are legitimately CRLF: *.bat, *.cmd, *.ps1, and anything under .git/. Windows batch wrappers are consumed by cmd.exe.
  • Consider wiring a periodic run into job_monitor so drift is reported rather than discovered.
  • Baseline to verify against: the three counts in the table above.
  • Talbot addition
    • A detect-repair util would only work if a reliable hook triggered it, after manual file editing. My default text editor was Textpad. I have installed Notepad++ and will try it instead, as it indicates in the status line the line endings for either Linux or Windows.
    • Claude, 2026-08-05: Notepad++ is the right call and it changes the shape of this item. Unlike TextPad, its preferences are readable XML, not opaque blobs — %APPDATA%\Notepad++\config.xml carries <GUIConfig name="NewDocDefaultSettings" format="…"> where 0=Windows CRLF, 1=Mac CR, 2=Unix LF. It was 0; set to 2 on 2026-08-05 while Notepad++ was closed (it rewrites config.xml on exit, so edits made while running are lost). Backup: notepadpp-config.xml.bak-20260805 in the session scratchpad. UI equivalent: Settings → Preferences → New Document → Format.
    • This narrows the util’s job substantially. Notepad++ preserves an existing file’s line endings on save and shows them in the status bar, so the remaining CRLF risk is only (a) newly created files — now defaulted to LF — and (b) an accidental Edit → EOL Conversion. Talbot’s point stands that a detect-repair util needs a trigger, but with the editor no longer introducing CRLF, a periodic scan (daily via job_monitor, reporting drift) is sufficient — no per-save hook needed. Prefer that over trying to hook the editor.
    • Still worth building the detector for the 29 of 65 shared-drive files that already carry CRLF, which no editor setting fixes retroactively.

3. Isolate the three unprotected shared-drive projects

Section titled “3. Isolate the three unprotected shared-drive projects”

Talbot confirmed folding these in. my_backup is the only shared-drive Python project with an isolated UV_PROJECT_ENVIRONMENT; these three have the identical exposure:

ProjectExposure
diskcheck⚠️ live weekly Scheduled Task (\DiskSpaceCheck) running C:\Users\Admin\.local\bin\uv.exe run diskcheck from D:\... with no isolated env — same shape as the July outage
rename_receiptsmanual util, no scheduled task
folder_structuremanual util, no scheduled task
  • Give each a wrapper .bat in D:\FSS\Software\Utils\Windows\ following my_backup-daily-task.bat (isolated UV_PROJECT_ENVIRONMENT, PYTHONUTF8=1, no trailing spaces after set values).
  • Repoint the DiskSpaceCheck scheduled task at its wrapper. Note its history: the task’s real name is DiskSpaceCheck, not diskcheck, and it previously failed silently for 5 months because the elevated action couldn’t resolve a bare uv on PATH — see System-Maintenance LESSONS.md. Verify by actually triggering the task and checking LastTaskResult and a fresh log line, not by running the command interactively.

4. Generalise the wrong-side-interpreter guard

Section titled “4. Generalise the wrong-side-interpreter guard”

check_backups.py::check_environment() (shipped 98e83d1) refuses to run off Windows and alerts as MISCONFIGURED rather than reporting missing data. That pattern belongs anywhere a util depends on one OS.

  • Extract it into a small shared helper rather than copying it — candidates: create_system_image, update_static_zips, debug_kopia, diskcheck, and virus_scan (which is the mirror image: WSL-only, and broke in exactly this way on 2026-08-03 when a duplicate cron entry invoked it through cmd.exe).
  • Decide where the helper lives — my_backup.utils works for that repo, but diskcheck is a separate project; a tiny shared module under PythonUtils/ may be cleaner.
  • While in here: logs/backup.log still contains cp1252/NEL bytes, which makes grep treat it as binary unless -a is passed. send_status_report survives it (errors="ignore") but silently drops the bad bytes. Confirm PYTHONUTF8=1 is now set on every cmd.exe entry point, and consider a one-time clean of the existing log.
  • A bare uv run in a shared-drive project from an agent session produces a warning before it can rebuild the venv.
  • CRLF counts on /mnt/d/FSS/Software/Utils and ~/utils are reduced and measurable on demand, via a registered util — with *.bat/*.ps1 correctly left alone.
  • DiskSpaceCheck runs from a wrapper with an isolated env, verified by triggering the real task.
  • No util that depends on one OS can silently produce wrong results when run from the other.
  • Analysis + measurements: my_backup-verification-alert, 2026-08-05 round-2 response.
  • Related, do not duplicate: my_backup-silent-failure-gaps (case-sensitivity #4 lives there), disk-space-monitoring.
  • Standing rules: AGENTS.md → Dev Standards (utility placement, package managers), GlobalDevRules.md §3.9 (WSL + AI utility gotchas — the SSOT for this whole class).
  • Repos: D:\FSS\Software\Utils\PythonUtils\*, ~/utils/, ~/ai-config/ (hook lives in deployed ~/.claude/settings.json; edit the SSOT, not the deployed copy).