Harvey DU b561242ba3
fix(harness): reject Windows reserved device names in thread ID validation (#7892)
* fix(harness): reject Windows reserved device names in thread_id validation

A caller-supplied thread ID of NUL (any casing) passes
validate_thread_id() but Paths.ensure_thread_dirs() then fails on
Windows hosts with FileNotFoundError (WinError 3), because NUL is a
reserved device name in every directory.

Reject the reserved device names (CON, PRN, AUX, NUL, COM1-9, LPT1-9)
case-insensitively in the shared validator, including the ".ext"
form kept legal by recent Windows versions, so thread IDs stay safe
for every filesystem backend regardless of host OS.

* style(harness): apply ruff format to thread_id validation

* refactor(harness): reuse windows_incompatible_segment for thread ID check

Address review feedback on #7892:

- Drop the private _WINDOWS_RESERVED_DEVICE_NAMES copy and route the
  thread-ID check through the canonical windows_incompatible_segment()
  from deerflow.utils.host_paths, which uploads, sandbox writes and
  skill support files already use. The canonical list also covers
  CONIN$/CONOUT$ and the superscript-digit COM/LPT variants.
- Remove the unreachable stem-split: the thread-ID pattern cannot
  contain a dot, so test whole IDs and pin the reserved-name branch
  with the dedicated 'reserved Windows device name' message; the
  unreachable 'NUL.txt' case is removed from the parametrization.
- Document the default-behavior change (Linux-host threads with
  reserved-name IDs will fail validation after upgrade; deletion is
  unaffected) under ### Fixed in CHANGELOG.md.
2026-11-05 14:13:23 +08:00
..