6 Commits

  • fix(hooks): avoid Claude Code v2.1.116 argv-dup bug in settings.local.json (#1524)
    * fix: resolve Claude Code Bash hook "cannot execute binary file" on Windows
    
    Root cause in ~/.claude/settings.local.json (user-global):
    1. UTF-8 BOM + CRLF line endings left by patch_settings_cl_v2_simple.ps1
    2. Double-wrapped command "\"bash.exe\" \"wrapper.sh\"" broke Windows
       argument splitting on the space in "Program Files", making bash.exe
       try to execute itself as a script.
    
    Fix:
    - Rewrite settings.local.json as UTF-8 (no BOM), LF, with the hook command
      pointing directly at observe-wrapper.sh and passing "pre"/"post" as a
      positional arg so HOOK_PHASE is populated correctly in observe.sh.
    
    Docs:
    - docs/fixes/HOOK-FIX-20260421.md — full root-cause analysis.
    - docs/fixes/apply-hook-fix.sh — idempotent applier script.
    
    * docs: addendum for HOOK-FIX-20260421 (v2.1.116 argv duplication detail)
    
    - Documents Claude Code v2.1.116 argv duplication bug as the underlying
      cause of the bash.exe:bash.exe:cannot execute binary file error
    - Records night-session fix variant using explicit `bash <path>` prefix
      (matches hooks.json observer pattern, avoids EFTYPE on Node spawn)
    - Keeps morning commit 527c18b intact; both variants are now documented
    
    ---------
    
    Co-authored-by: suusuu0927 <sugi.go.go.gm@gmail.com>
  • Merge pull request #1540 from suusuu0927/claude/install-hook-wrapper-argv-dup-fix-20260422
    fix(hooks): rewrite install_hook_wrapper.ps1 to avoid argv-dup bug
  • fix(hooks): add Windows PowerShell 5.1 compatibility to install_hook_wrapper.ps1
    `ConvertFrom-Json -AsHashtable` is PowerShell 7+ only, and the Windows 11
    reference machine used to validate this PR ships with Windows PowerShell
    5.1 only (no `pwsh` on PATH). Without this follow-up, running the
    installer on stock Windows fails at the parse step and leaves the
    installation half-applied.
    
    - Fall back to a manual `PSCustomObject` -> `Hashtable` conversion when
      `-AsHashtable` raises, so the script parses the existing
      settings.local.json on both PS 5.1 and PS 7+.
    - Normalize both hook buckets (`PreToolUse`, `PostToolUse`) and their
      inner `hooks` arrays as `System.Collections.ArrayList` before
      serialization. PS 5.1 `ConvertTo-Json` otherwise collapses
      single-element arrays into bare objects, which breaks the canonical
      PR #1524 shape.
    - Create the `skills/continuous-learning/hooks` destination directory
      when it does not exist yet, and emit a clearer error if
      settings.local.json is missing entirely.
    - Update `INSTALL-HOOK-WRAPPER-FIX-20260422.md` to document the PS 5.1
      compatibility guarantee and to cross-link PR #1542 (companion simple
      patcher).
    
    Verified on Windows 11 / Windows PowerShell 5.1.26100.8115 by running
    `powershell -NoProfile -ExecutionPolicy Bypass -File
    docs/fixes/install_hook_wrapper.ps1` against a sandbox `$env:USERPROFILE`
    and against the real settings.local.json. Both produce the canonical
    PR #1524 shape with LF-only output.
  • fix(hooks): rewrite patch_settings_cl_v2_simple.ps1 to avoid argv-dup bug
    - Use PATH-resolved `bash` as first token instead of quoted `.exe` path
      so Claude Code v2.1.116 argv duplication does not feed a binary to
      bash as its $0 (repro: exit 126 "cannot execute binary file").
    - Point the command at `observe-wrapper.sh` and pass distinct `pre` /
      `post` positional arguments so PreToolUse and PostToolUse are
      registered as separate entries.
    - Normalize the wrapper path to forward slashes before embedding in the
      hook command to avoid MSYS backslash surprises.
    - Write UTF-8 (no BOM) with CRLF normalized to LF so downstream JSON
      parsers never see mixed line endings.
    - Preserve existing hooks (legacy `observe.sh`, third-party entries)
      by appending only when the canonical command string is not already
      registered. Re-runs are idempotent ([SKIP] both phases).
    - Keep the script compatible with Windows PowerShell 5.1: fall back to
      a manual PSCustomObject → Hashtable conversion when
      `ConvertFrom-Json -AsHashtable` is unavailable, and materialize hook
      arrays as `System.Collections.ArrayList` so single-element arrays
      survive PS 5.1 `ConvertTo-Json` serialization.
    
    Companion to PR #1524 (settings.local.json shape fix) and PR #1540
    (install_hook_wrapper.ps1 argv-dup fix).
  • fix(hooks): rewrite install_hook_wrapper.ps1 to avoid argv-dup bug
    Under Claude Code v2.1.116 the first argv token of a hook command is
    duplicated. When the token is a quoted Windows .exe path, bash.exe is
    re-invoked with itself as script (exit 126). PR #1524 fixed the shape
    of settings.local.json; this script keeps the installer consistent so
    re-running it does not regenerate the broken form.
    
    Changes:
    - First token is now PATH-resolved `bash` instead of the quoted bash.exe
    - Wrapper path is normalized to forward slashes for MSYS safety
    - PreToolUse and PostToolUse get distinct pre/post positional arguments
    - JSON output is written with LF endings (no mixed CRLF/LF)
    
    Companion doc: docs/fixes/INSTALL-HOOK-WRAPPER-FIX-20260422.md