Hooks: Muse's owed reads of #643 and #652, a nested backtick's comment is tested and the spelt reading asks about a session

DO
7h ago
+23-4

The follow-on under the merged-early rule: Muse could not read #643 or #652 before they merged (quota). These are its reads, done after the merge, and what they found.

The protected edits to tools/hooks/ are pre-approved by the Maintainer 2026-11-08, ruled by the Factory Builder. Hooks are mistake guards (decision 0038's triage rule), and this PR is held to that standard.

What changes

FromFindingNow
Muse on #643The line in shell._inside that ends a nested backtick at a comment's backtick had no test that killed itecho "$(echo "echo #"" "${?+'…'}")" holds it, with a mutant
Muse on #643Two more lines with no killing test: braces reset entering a nested substitution, and restored leaving itNo test can reach them from _held. A ${...} in a held substitution is refused at its start or skipped whole, so _inside never begins inside a nested substitution with braces open. Left as they are
Muse on #652The protected hook's second, spelt reading never reached sessions(), so a Claude Code session after a nested substitution went unaskedAsked about, with a test and a mutant
Muse and the Claude review of this PRWith $(which claude) anywhere in the command, sessions() read the rewritten text flat, whatever reading it was givenThe spelt reading reads it spelt, with a test and a mutant
Muse on #652A spelt reading that fails drops it whole; past 8 KB it is skippedBoth evasion only, the same as main before #652: #665's items (a) and (b)

Decision 0032 gains one row, naming three mutants.

Checks

  • tests/test_hooks.py::test_a_substitutions_own_quotes_are_read_as_the_shell_reads_them and ::test_a_double_quoted_substitution_in_a_double_quoted_one_hides_no_command_after_it gain the cases.
  • At bd4834de: make verify passes, check_decisions is clean, and the mutants of tools/hooks/shell.py, identity.py and protected.py are all killed (38 at 237592da, 18 again at bd4834de).

Reviews

ReaderFindingsDisposition
Argon (gemini-4-argon-high)None—
Muse (muse-wonder-full-1.0)1, the $(which claude) gap, marked blocking; not a regressionFixed in bd4834de
Claude review and security passNothing major. The same $(which claude) gap, the same on mainFixed in bd4834de. Two cosmetic points: a session the second reading finds with a backtick asks command_unreadable, as main does at the top level, and one prompt can list that code twice. Left as they are

All read 237592da. bd4834de is the fix.

šŸ¤– Generated with Claude Code