feat(cc027): PreToolUse hook-tool-trace.sh metadata signal layer#54
Merged
Conversation
Add per-tool-call JSONL trace (~/.claude/projects/<proj>/memory/tool-trace.jsonl) to unblock CC-025 /skill-refine and CC-028 routing-log auto-append. - scripts/hook-tool-trace.sh (new): pure-bash, no jq, multi-path JSON hedge for tool name (.tool_name / .tool / .tool_use.name) and first_arg per tool family; fast-path escape skip for safe-char values; non-blocking append (chmod 0444 → exit 0); CLAUDE_TOOL_TRACE_DISABLE=1 escape hatch. Median per-call overhead 8.2ms (100-iter benchmark). - scripts/install-hooks.sh: wire as PreToolUse matcher "*" with idempotent jq-splice pattern matching existing three guards. - scripts/test-hooks.sh: 14 cases (happy paths, hedge variants, missing fields, malformed JSON, non-blocking proof, payload-leak prevention, install idempotency); 267/267 pass. - BACKLOG.md: CC-027 ✅ closed; CC-035 (install-hooks basename collision edge case from spike audit), CC-044 (rotation/retention deferred). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Security (block → cleared):
- Bash first_arg: redact env-prefix (^X=...) → null; only safe bare command
names (^[a-z][a-z0-9_-]{0,30}$) kept; pathful/quoted commands → null.
- Grep/Glob first_arg: always null (patterns can carry secrets/hostnames).
- Read/Edit/Write first_arg: cwd-relative when inside repo; basename only
when under $HOME but outside cwd; null for foreign paths.
Risk (block → cleared):
- Rotation: stat-based 4 MiB cap; over-cap → mv to .jsonl.1 (single archive
slot) then start fresh. Constant-time check, non-blocking on mv failure.
Advise findings handled:
- critic medium / qa medium (malformed key-bearing JSON): strict jq
validation deferred to CC-027c — `jq -e .` alone is ~25ms/call subprocess
startup, exceeds entire 12ms budget. Bash brace heuristic stays
best-effort; garbage-line risk is data quality, not security/risk.
- qa medium (docstrings): all new tool_trace_case invocations carry
`# Behavior:` + `# Steps:` lines per QA AGENT.md §1 Step 3.
- qa low (no-leakage coverage): added cases for Bash env-prefix, Grep
pattern, Read foreign path, Read cwd-relative.
BACKLOG:
- CC-027b deferred: tool-trace health signal (bounded error counter).
- CC-027c deferred: async strict JSON validation (inline jq cost).
Self-verify (main shell): 278 passed, 0 failed. Perf 9.45ms/call < 12ms.
leak_grep_audit returned 0 matches. Rotation evidenced.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
QA block (missing perf budget coverage): - Add tool_trace_performance_budget test: 100 calls < 3500ms wall time (≈ 35ms/call cap, generous for slow CI runners). Local observed ~10ms/call; CI headroom prevents flakes. Critic advise (dead helpers + rotation/retention contract): - Remove unused json_string_after_stdout, first_nonempty, home_abbrev. Each had only its own definition with zero call sites. - Update CC-044 prose to reflect that 4 MiB single-archive rotation is now the shipped BASELINE, not deferred. CC-044 scope becomes the UPGRADE from "current + one overwritten archive" to multi-window retention (gzip windows, time-based eviction, etc.). Architecture advise (latency as architectural constraint): - Addressed by the new perf budget test — global PreToolUse matcher "*" latency is now structurally guarded in CI rather than design-only. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
PR-gate critic + security both noted `cwd` exceeded the documented
4-field contract at BACKLOG.md:202 (`{ts, session_id, tool,
first_arg_or_skill}`) and could leak path metadata if traces are
shared. The cwd is already encoded in the jsonl's directory location
(`~/.claude/projects/<encoded-cwd>/memory/tool-trace.jsonl`), so the
inline field was redundant. Consumers (CC-025/026, not yet
implemented) derive project anchor from file location.
- hook-tool-trace.sh: emit 4-field JSONL; cwd still read from envelope
for project resolution + Read/Edit/Write path relativization (used
internally only).
- test-hooks.sh: update schema_shape assertion (5→4 keys); update
happy_path_bash to assert `has("cwd") == false`.
279 passed, 0 failed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Per critic low advise from PR-gate round 3. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This was referenced May 15, 2026
screenleon
added a commit
that referenced
this pull request
May 16, 2026
…/028/034 (#60) Index row CC-029 was still 🔵 active even though PR #57 landed it 2026-05-15. Promote to ✅ closed and add Outcome + See pointers. Backfill missing **See**: pr:#NN stubs for previously-closed entries CC-027/CC-028/CC-034 that already pointed at PR #54/#55/#53 in their Refs column but lacked the body-side See stub required by pm/scripts/validate.sh E-CLOSURE-NO-SEE. Pure data drift fix; no validator or runtime change. Remaining baseline noise (CC-035 E-INDEX-MISMATCH, CC-038 E-AREA-ENUM + E-REFS-PREFIX) is tracked separately and intentionally out of scope here. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
scripts/hook-tool-trace.sh: PreToolUse hook (matcher"*") that appends a 4-field JSONL record per tool invocation to~/.claude/projects/<proj>/memory/tool-trace.jsonl. Pure metadata ({ts, session_id, tool, first_arg_or_skill}), non-blocking, ~10ms/call.scripts/install-hooks.shwith idempotent jq-splice matching the existing PreToolUse guard pattern.test-hooks.shcases (happy paths, hedge variants, security redaction, rotation, performance budget, install idempotency)./skill-refine+ CC-026/skill-distill+ CC-028 routing-log auto-append by providing the per-tool signal source.Design
.tool_name/.tool/.tool_use.name) and per-tool first-arg fields, per [[feedback_undocumented_harness_payload]].X=Y ...) → null; Grep/Glob patterns → null; Read/Edit/Write paths → cwd-relative > basename > null; only bare lowercase command names persisted from Bash..jsonl.1); CC-044 designs multi-window upgrade.tool-trace.errsidecar; no stdout writes (PreToolUse stdout is interpreted by harness).CLAUDE_TOOL_TRACE_DISABLE=1for immediate disable.Commit stack
a4abd29feat: initial spikefae73c2fix: address PR-gate security + risk blocks (redaction + rotation)2464b33fix: address PR-gate qa block + critic advise (perf test + dead code)e282198fix: drop cwd from schema (4-field contract per BACKLOG.md:202)PR-gate (full tier, sequential mode)
Final round verdict: GO (advise only). Stack went through 3 gate rounds; all
blockverdicts resolved via fixup commits, no overrides.Backlog
Test plan
bash scripts/test-hooks.sh→ 279 passed, 0 failed/etc/passwdnever appear in jsonl across 5 firings.1archive, main resets to fresh file🤖 Generated with Claude Code