Context
Mutation-testing run against main (b850e2fec11b1966d2b73670ae56b5eff195284e), mutmut 3.6.0, local run 2026-07-10: 1025 mutants, 151 killed, 235 survived, 639 no-tests.
This issue covers the first half of the no-tests bucket: pure or trivially harnessed helpers in hooks/post-turn-quality-stop-hook.py with zero executing tests. These are not untestable boundaries — every function below is deterministic and unit-testable with plain pytest (plus capsys/monkeypatch where noted). 261 no-tests mutants fall in this group.
Uncovered functions (no-tests mutant counts)
hooks/post-turn-quality-stop-hook.py:719-786 — format_reason (146 mutants): the entire blocked-reason renderer, including the 60-file truncation boundary and failure-block formatting.
hooks/post-turn-quality-stop-hook.py:167-192 — truncate (18): head/tail split arithmetic and the max_chars <= 0 / marker-length boundaries.
hooks/post-turn-quality-stop-hook.py:579-607 — parse_make_targets (22): the rule regex, comment/indent skipping, and %-pattern exclusion.
hooks/post-turn-quality-stop-hook.py:554-576 — detect_categories (19): extension-to-category mapping.
hooks/post-turn-quality-stop-hook.py:807-833 — targets_for_categories (13): category expansion and the include filter.
hooks/post-turn-quality-stop-hook.py:655-675 — dedup_preserve_order (6).
hooks/post-turn-quality-stop-hook.py:610-624 — is_missing_makefile (5).
hooks/post-turn-quality-stop-hook.py:888-904 — parse_hook_input (4): stdin JSON parsing (monkeypatch stdin).
hooks/post-turn-quality-stop-hook.py:907-930 — resolve_start_cwd (13): hook-input cwd versus CLAUDE_PROJECT_DIR versus os.getcwd() precedence.
hooks/post-turn-quality-stop-hook.py:789-804 — block_and_print (11): JSON payload shape (capsys).
hooks/post-turn-quality-stop-hook.py:933-950 — fail_state (4): state flagging plus blocked payload (capsys).
Analysis
The co-located suite exercises only the compush family, run()'s missing-cwd branch, get_make_targets's missing-make branch, and parse_env's compush flag; mutmut therefore records every mutant in the functions above as "no tests". These helpers carry real behaviour (output truncation arithmetic, Makefile parsing, category detection, the hook's block-payload contract) and mutations here change what agents see when the hook blocks.
Suggested tests
truncate: boundary cases (max_chars = 0, shorter-than-limit, limit shorter than the marker, and an exact head/tail split assertion).
parse_make_targets: a representative make -qp fixture asserting the exact target set, including %-pattern and comment exclusion; is_missing_makefile truthy/falsy cases.
detect_categories / targets_for_categories / dedup_preserve_order: parametrized equality assertions covering every extension set and the include filter.
format_reason: snapshot-style assertions (syrupy is already a dev dependency) for the error, >60-files, detected-categories, and failed-command variants.
parse_hook_input / resolve_start_cwd: valid JSON, invalid JSON, non-dict JSON; cwd key present, CLAUDE_PROJECT_DIR fallback, bare os.getcwd() fallback.
block_and_print / fail_state: parse the emitted JSON and assert decision == "block" and the reason verbatim.
Full worklist: triage worklist.md; dataset SHA b850e2f.
Context
Mutation-testing run against
main(b850e2fec11b1966d2b73670ae56b5eff195284e), mutmut 3.6.0, local run 2026-07-10: 1025 mutants, 151 killed, 235 survived, 639 no-tests.This issue covers the first half of the no-tests bucket: pure or trivially harnessed helpers in
hooks/post-turn-quality-stop-hook.pywith zero executing tests. These are not untestable boundaries — every function below is deterministic and unit-testable with plain pytest (pluscapsys/monkeypatchwhere noted). 261 no-tests mutants fall in this group.Uncovered functions (no-tests mutant counts)
hooks/post-turn-quality-stop-hook.py:719-786—format_reason(146 mutants): the entire blocked-reason renderer, including the 60-file truncation boundary and failure-block formatting.hooks/post-turn-quality-stop-hook.py:167-192—truncate(18): head/tail split arithmetic and themax_chars <= 0/ marker-length boundaries.hooks/post-turn-quality-stop-hook.py:579-607—parse_make_targets(22): the rule regex, comment/indent skipping, and%-pattern exclusion.hooks/post-turn-quality-stop-hook.py:554-576—detect_categories(19): extension-to-category mapping.hooks/post-turn-quality-stop-hook.py:807-833—targets_for_categories(13): category expansion and theincludefilter.hooks/post-turn-quality-stop-hook.py:655-675—dedup_preserve_order(6).hooks/post-turn-quality-stop-hook.py:610-624—is_missing_makefile(5).hooks/post-turn-quality-stop-hook.py:888-904—parse_hook_input(4): stdin JSON parsing (monkeypatchstdin).hooks/post-turn-quality-stop-hook.py:907-930—resolve_start_cwd(13): hook-inputcwdversusCLAUDE_PROJECT_DIRversusos.getcwd()precedence.hooks/post-turn-quality-stop-hook.py:789-804—block_and_print(11): JSON payload shape (capsys).hooks/post-turn-quality-stop-hook.py:933-950—fail_state(4): state flagging plus blocked payload (capsys).Analysis
The co-located suite exercises only the compush family,
run()'s missing-cwd branch,get_make_targets's missing-make branch, andparse_env's compush flag; mutmut therefore records every mutant in the functions above as "no tests". These helpers carry real behaviour (output truncation arithmetic, Makefile parsing, category detection, the hook's block-payload contract) and mutations here change what agents see when the hook blocks.Suggested tests
truncate: boundary cases (max_chars = 0, shorter-than-limit, limit shorter than the marker, and an exact head/tail split assertion).parse_make_targets: a representativemake -qpfixture asserting the exact target set, including%-pattern and comment exclusion;is_missing_makefiletruthy/falsy cases.detect_categories/targets_for_categories/dedup_preserve_order: parametrized equality assertions covering every extension set and theincludefilter.format_reason: snapshot-style assertions (syrupy is already a dev dependency) for the error, >60-files, detected-categories, and failed-command variants.parse_hook_input/resolve_start_cwd: valid JSON, invalid JSON, non-dict JSON;cwdkey present,CLAUDE_PROJECT_DIRfallback, bareos.getcwd()fallback.block_and_print/fail_state: parse the emitted JSON and assertdecision == "block"and the reason verbatim.Full worklist: triage
worklist.md; dataset SHAb850e2f.