diff --git a/.tasks/STATUS.md b/.tasks/STATUS.md index 0cb9105..f2992a1 100644 --- a/.tasks/STATUS.md +++ b/.tasks/STATUS.md @@ -1223,7 +1223,7 @@ Acceptance 1-6 all met by test evidence (not by inspection). Per-task detail in --- -## ⚪ [session-inbox-monitor-stophook-utf8-fix] — Stop-хук портит UTF-8/кириллицу при принудительном вручении письма (inject через `decision:block`). Найдено при `-stophook-blockfix-proof` 2026-06-17 (независимо подтверждено workshop по байтам). +## 🟢 [session-inbox-monitor-stophook-utf8-fix] — Stop-хук портит UTF-8/кириллицу при принудительном вручении письма (inject через `decision:block`). Найдено при `-stophook-blockfix-proof` 2026-06-17 (независимо подтверждено workshop по байтам). **Симптом:** кириллическое тело письма приходит в block-reason как mojibake; английский текст инструкции чист. **Диагноз (verified):** (1) файл на диске — валидный UTF-8 (Get-Content -Encoding UTF8 читает чисто). (2) `~/.claude/hooks/stop-dispatcher.ps1` **читает** тело как `-Encoding UTF8` (стр. 44) — read-сторона ОК. (3) НО stop-dispatcher **не выставляет** `[Console]::OutputEncoding` → `ConvertTo-Json` в stdout при harness-spawn (redirected pipe, WinPS 5.1) кодируется в дефолтном OEM-codepage (cp866 на RU-Windows) → mojibake на выводе. (4) Репро через `Start-Process -RedirectStandardOutput` НЕ воспроизводит (наследует UTF-8 от родителя) → баг харнесс-spawn-специфичен; верифицируется только in-situ (реальный Stop-хук + кириллическое письмо). (5) Писательская сторона: `Set-Content/Out-File -Encoding utf8` под 5.1 сажает BOM (`EF BB BF`) + смешанные EOL — некcanon; Write-тул пишет чистый no-BOM UTF-8 LF. @@ -1236,12 +1236,15 @@ Acceptance 1-6 all met by test evidence (not by inspection). Per-task detail in NB: `stop-dispatcher.ps1` — machine-local (вне git, владелец — workshop-сетап). Правка требует ОК user (shared hook, влияет на Stop во всех проектах машины). ASCII-clean в `inbox-monitor.ps1` — это обход того же encoding-класса, не корень; корень здесь — read/write/output codepage. **Weight:** needs-claude -**Status:** ready -**Where I stopped:** Диагноз полный (verified + workshop-confirmed). Не применял фикс — это shared machine-local hook, нужен ОК user; верификация только in-situ. -**Next action:** По ОК user: добавить OutputEncoding=UTF8 в stop-dispatcher.ps1 (бэкап), прислать кириллическое тест-письмо, end turn → проверить что forced-delivery чист. Затем writer-гайд в SKILL.md. Findings → review. +**Status:** done +**Where I stopped:** Шипнуто+верифицировано 2026-06-17 (ОК user). (1) `[Console]::OutputEncoding = [System.Text.Encoding]::UTF8` (+`$OutputEncoding`) добавлено в начало `~/.claude/hooks/stop-dispatcher.ps1` (бэкап `.bak-utf8fix`; parse 0 ошибок; BOM файла сохранён → русские комменты целы). (2) Writer-гайд (no-BOM/LF, WriteAllText vs Set-Content) задокументирован в SKILL.md Failure modes, bump 0.2.0→0.2.1 PATCH. (3) **In-situ regression PASS:** кириллический pangram «Съешь же ещё этих мягких французских булок…» прислан через реальный inject → block-reason пришёл ЧИСТО (до фикса то же тело давало `������᪮�`); no-loop подтверждён. Root-cause = output-encoding (read был уже UTF8), как диагностировано; Start-Process-репро баг не ловил — только реальный harness-spawn путь. NB: stop-dispatcher.ps1 machine-local (вне git) — фикс на этой машине; для multi-machine надо внести в workshop-сетап, что шипает хук (нотифай ушёл). +**Next action:** (none — kept until merged). Multi-machine propagation фикса stop-dispatcher — на стороне workshop-сетапа. **Branch:** n/a **Notify:** OpeItcLoc03/workshop + + + --- diff --git a/skills/session-inbox-monitor/SKILL.md b/skills/session-inbox-monitor/SKILL.md index 122cd47..3240ed1 100644 --- a/skills/session-inbox-monitor/SKILL.md +++ b/skills/session-inbox-monitor/SKILL.md @@ -1,6 +1,6 @@ --- name: session-inbox-monitor -version: 0.2.0 +version: 0.2.1 description: > Raises a persistent Monitor (Monitor tool, NOT background Bash) on the project's `.claude-inbox/` at the start of an interactive session, so @@ -104,6 +104,16 @@ for free on session end. Headless sessions skip it and rely on the pull-model - **Monitor auto-stopped** → the harness stops monitors that emit too many events. The injected poll command de-dups by filename (pages once per message, not every 15s) to stay under that bar. +- **Mojibake on force-delivery** → the Stop-hook (`stop-dispatcher.ps1`) injects + message bodies to stdout; WinPS 5.1 must set `[Console]::OutputEncoding = + [System.Text.Encoding]::UTF8` or non-ASCII (Cyrillic) bodies arrive mangled + (it emits in the OEM code page under a harness-spawned redirected pipe). Inbox + messages must be written as **no-BOM UTF-8, LF** — the Write tool does this; + PowerShell writers must use + `[IO.File]::WriteAllText($p,$t,[Text.UTF8Encoding]::new($false))`, NOT + `Set-Content`/`Out-File -Encoding utf8` (which adds a BOM under 5.1). Same + WinPS-5.1 encoding class as the hook-source em-dash gotcha. Fixed + in-situ + verified 2026-06-17. ## Side effects