On Windows 10/11 without Python installed from the Microsoft Store, the
"App Execution Alias" stubs at %LOCALAPPDATA%\Microsoft\WindowsApps\python.exe
and python3.exe are symlinks to AppInstallerPythonRedirector.exe. These
stubs neither launch Python nor honor `-c`; calls print a bare "Python "
line and exit, silently breaking every JSON-parsing step in observe.sh.
Net effect: observations.jsonl is never written, CLV2 appears installed
correctly, and the only residual artifact is `.last-purge`.
This commit:
1. Adds `_is_windows_app_installer_stub` helper that detects the stub
via `command -v` output and optional `readlink -f` resolution.
2. Teaches `resolve_python_cmd` to skip stub candidates and fall
through to the next real interpreter (typically C:\...\Python3xx\python.exe).
3. Exports the stub-aware CLV2_PYTHON_CMD before sourcing
detect-project.sh, which already honors an already-set value,
so the shared helper does not re-resolve and re-select the stub.
POSIX-compatible. No behavior change on macOS / Linux / WSL where no
such stub exists.
Refs: observations.jsonl empty on Windows Claude Desktop users.
The merged hero was being clipped at the bottom by the Puppeteer capture
because the HTML body used flex-centering with 24px padding, shifting the
stage below the viewport top.
- Captures now flush to (0,0) via a min-width 1300px media-query wrapper
so the in-browser preview keeps its padding but the capture viewport
does not.
- Shortens bottom-row labels so the stats row no longer overlaps the foot
line at 1200px:
Catalog, Harnesses, Rust plane, MIT / npm: ecc-universal · AgentShield
No other content changes.
Co-authored-by: livlign <livlign@users.noreply.github.com>
* 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>
The SessionStart hook injects the most recent *-session.tmp as
additionalContext labelled only with 'Previous session summary:'.
After a /compact boundary, the model frequently re-executes stale
slash-skill invocations it finds inside that summary, re-running
ARGUMENTS-bearing skills (e.g. /fw-task-new, /fw-raise-pr) with the
last ARGUMENTS they saw.
Observed on claude-opus-4-7 with ECC v1.9.0 on a firmware project:
after compaction resume, the model spontaneously re-enters the prior
skill with stale ARGUMENTS, duplicating GitHub issues, Notion tasks,
and branches for work that is already merged.
ECC cannot fix Claude Code's skill-state replay across compactions,
but it can stop amplifying it. Wrap the injected summary in an
explicit HISTORICAL REFERENCE ONLY preamble with a STALE-BY-DEFAULT
contract and delimit the block with BEGIN/END markers so the model
treats everything inside as frozen reference material.
Tests: update the two hooks.test.js cases that asserted on the old
'Previous session summary' literal to assert on the new guard
preamble, the STALE-BY-DEFAULT contract, and both delimiters. 219/219
tests pass locally.
Tracked at: #1534
* fix(gateguard): rewrite routineBashMsg to use fact-presentation pattern
The imperative 'Quote user's instruction verbatim. Then retry.' phrasing
triggers Claude Code's runtime anti-prompt-injection filter, deadlocking
the first Bash call of every session. The sibling gates (edit, write,
destructive) use multi-point fact-list framing that the runtime accepts.
Align routineBashMsg with that pattern to restore the gate's intended
behavior without changing run(), state schema, or any public API.
Closes#1530
* docs(gateguard): sync SKILL.md routine gate spec with new message format
CodeRabbit flagged that skills/gateguard/SKILL.md still described the
pre-fix imperative message. Update the Routine Bash Gate section to
match the numbered fact-list format used by the new routineBashMsg().
Fixes#1469.
On Windows the `claude` binary installed via `npm i -g @anthropic-ai/claude-code`
is `claude.cmd`, and Node's spawn() cannot resolve .cmd wrappers via PATH
without shell: true. The call failed with `spawn claude ENOENT` and claw.js
returned an error string to the caller.
Mirrors the fix pattern applied in PR #1456 for the MCP health-check hook.
'claude' is a hardcoded literal (not user input), so enabling shell on Windows
only is safe.
`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.
- 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).