From c7531d37001c41091450b1da6c1305b55d3db323 Mon Sep 17 00:00:00 2001 From: Bryan Van Deusen Date: Mon, 14 Sep 2026 18:37:13 -0400 Subject: [PATCH] fix(409): the report check's prefilter no longer depends on compact JSON (#4014) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CI run #517 failed five of the new hook tests, all of them expecting a request that never went out. The prefilter matched `"name":"…update_task"` with no space after the colon, which is how Claude Code writes its transcripts, while the tests wrote theirs with json.dumps defaults (`"name": "…"`). The hook exited at the prefilter for every test transcript. The silent-case tests passed for the same wrong reason. - The prefilter now allows whitespace after the colon. The jq parse behind it never depended on formatting. - The test transcripts are written compact, matching the real file. The silent-case tests now reach the turn parse rather than stopping at the prefilter. Co-Authored-By: Claude Opus 5 (1M context) --- plugin/.claude-plugin/plugin.json | 2 +- plugin/hooks/scribe_report_check.sh | 2 +- tests/test_report_check_hook.py | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/plugin/.claude-plugin/plugin.json b/plugin/.claude-plugin/plugin.json index 6017ce9..7cd103f 100644 --- a/plugin/.claude-plugin/plugin.json +++ b/plugin/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "scribe", "description": "Scribe for Claude Code: connects the scribe MCP server, adds the hooks that deliver live project state and relevant records at the right moment, ships the shared client-neutral Scribe skills (using-scribe, writing-plans, reporting-back, systematic-debugging, verification, brainstorming, reusing-code, shape-accounting), and syncs your saved Scribe Processes as skills (/scribe:sync).", - "version": "2026.09.14.2234", + "version": "2026.09.14.2237", "author": { "name": "Bryan Van Deusen" }, diff --git a/plugin/hooks/scribe_report_check.sh b/plugin/hooks/scribe_report_check.sh index 72f8a5d..54cf313 100644 --- a/plugin/hooks/scribe_report_check.sh +++ b/plugin/hooks/scribe_report_check.sh @@ -73,7 +73,7 @@ marker="$state_dir/${safe_sid}.blocked" # check. Keeps the ordinary turn at one grep. Process substitution, NOT a pipe: # under `pipefail`, `grep -q` exiting on the first match kills `tail` with # SIGPIPE, and the pipeline then reports failure precisely when it matched. -grep -q -E '"name":"([^"]*__)?(update|create)_task"' < <(tail -c 2000000 "$transcript" 2>/dev/null) || { +grep -q -E '"name":[[:space:]]*"([^"]*__)?(update|create)_task"' < <(tail -c 2000000 "$transcript" 2>/dev/null) || { rm -f "$marker" 2>/dev/null || true exit 0 } diff --git a/tests/test_report_check_hook.py b/tests/test_report_check_hook.py index 2269be9..d401d0f 100644 --- a/tests/test_report_check_hook.py +++ b/tests/test_report_check_hook.py @@ -55,7 +55,8 @@ def _text(text): def _transcript(tmp_path, lines): path = tmp_path / "t.jsonl" - path.write_text("\n".join(json.dumps(line) for line in lines) + "\n") + # Compact, like the file Claude Code writes ({"name":"…"}, no spaces). + path.write_text("\n".join(json.dumps(line, separators=(",", ":")) for line in lines) + "\n") return path