|
| 1 | +--- |
| 2 | +slug: 260425-rgw-postool-read-tools |
| 3 | +type: quick |
| 4 | +created: 2026-04-25 |
| 5 | +completed: 2026-04-25 |
| 6 | +status: complete |
| 7 | +commit: 7497cc6 |
| 8 | +--- |
| 9 | + |
| 10 | +# Summary: PostToolUse matcher broadened to include read tools |
| 11 | + |
| 12 | +## What changed |
| 13 | + |
| 14 | +`hooks/hooks.json` PostToolUse matcher: |
| 15 | + |
| 16 | +```diff |
| 17 | +-"matcher": "Bash|Edit|Write|MultiEdit|NotebookEdit" |
| 18 | ++"matcher": "Bash|Edit|Write|MultiEdit|NotebookEdit|Read|Grep|Glob|WebFetch|WebSearch" |
| 19 | +``` |
| 20 | + |
| 21 | +`bin/gsd-tools.cjs` post-tool-use handler comment updated to reflect the new matcher set + the reason for the broadening (research-phase usage-cap incident with 18-min checkpoint gap). |
| 22 | + |
| 23 | +`README.md` "Session continuity + drift resilience" paragraph updated to list the broader tool set + note the read-heavy-research coverage benefit. |
| 24 | + |
| 25 | +## Why |
| 26 | + |
| 27 | +Real incident this morning in `/Users/jnuyens/sftp-manager/`: |
| 28 | +- Last HANDOFF written 02:19 (`source: auto-postool`) |
| 29 | +- Usage cap hit 02:37 |
| 30 | +- 18-minute gap |
| 31 | + |
| 32 | +The 18 missing minutes were almost entirely `Read`/`Grep`/`Glob`/`WebFetch` calls — all non-mutating tools, none in the original matcher. PostToolUse never fired during the research-read sweep. Yesterday's 260425-mct change covered the *microcompact* gap but not the *no-mutations* gap. This task closes that. |
| 33 | + |
| 34 | +## Throttle still bounds writes |
| 35 | + |
| 36 | +The 60s mtime throttle in the post-tool-use handler unchanged. Smoke-tested: |
| 37 | + |
| 38 | +| Test | Result | |
| 39 | +|------|--------| |
| 40 | +| Cold start + 1 read | Writes HANDOFF, source=auto-postool ✓ | |
| 41 | +| 4 more rapid reads within 60s | All throttled, mtime unchanged ✓ | |
| 42 | +| Backdate mtime −90s + 1 read | Rewrote (cooldown expired) ✓ | |
| 43 | +| `check-drift.cjs` umbrella | All 3 detectors PASS ✓ | |
| 44 | + |
| 45 | +So even with the matcher firing 50+ times per turn during a heavy research session, actual disk writes stay capped at ≤1/min. Worst case becomes "HANDOFF is ≤60s stale at any point during an active session" — which was always the design intent. |
| 46 | + |
| 47 | +## Token cost |
| 48 | + |
| 49 | +User asked mid-task whether the increased hook-firing frequency drives up token usage. Answer (verified in CC source `_research/claude-code-internals/utils/messages.ts:4099-4115`): |
| 50 | + |
| 51 | +```javascript |
| 52 | +case 'hook_success': |
| 53 | + if (attachment.hookEvent !== 'SessionStart' && attachment.hookEvent !== 'UserPromptSubmit') { |
| 54 | + return []; // PostToolUse output → empty array → zero tokens |
| 55 | + } |
| 56 | +``` |
| 57 | + |
| 58 | +**Zero tokens.** PostToolUse hook output is never injected into the model's context. CC only renders systemReminder messages for SessionStart and UserPromptSubmit events. PostToolUse hook activity is tracked as UI metadata, not as conversation content. |
| 59 | + |
| 60 | +Other costs (all negligible): |
| 61 | +- ~5-10ms per throttled fire (mtime stat + early return) |
| 62 | +- ~50-200ms per actual write (gather state + serialize) |
| 63 | +- 0 bytes of stdout when handler succeeds (silent design) |
| 64 | +- ~1-2KB disk write per actual checkpoint |
| 65 | + |
| 66 | +## Commit |
| 67 | + |
| 68 | +`7497cc6` — fix(quick-260425-rgw): broaden PostToolUse matcher to include read tools |
| 69 | + |
| 70 | +## What's still uncovered |
| 71 | + |
| 72 | +Pure-conversation thinking with no tool calls at all. If Claude isn't running tools, there's nothing meaningful to checkpoint. STATE.md captures phase position separately. Acceptable gap; not worth a "tick" hook. |
0 commit comments