Review: Convention: PreToolUse hook matchers must use separate entries, not pipe-separated

review-377-2026-03-25 Review

review ready

Verdict: READY

Template Completeness

  • [x] Lineage — present (discovered scope from GroupMe incident remediation)
  • [x] Repo — present (forgejo_admin/claude-custom)
  • [x] User Story — present (As platform operator...)
  • [x] Context — present (detailed finding with root cause and cost)
  • [x] File Targets — present (settings.json + convention note, plus NOT-touch list)
  • [x] Acceptance Criteria — present (4 checkboxes)
  • [x] Test Expectations — present (manual test noted, N/A for automated)
  • [x] Constraints — present (3 constraints: PostToolUse OK, only ask affected, may be Claude Code bug)
  • [x] Checklist — present
  • [x] Related — present (references #160, #164, project-pal-e-agency)
Note: Issue uses "### Type" header (Feature) which is not in the template but is used by check-issue-template.sh for type detection. Harmless addition.

File Targets

  • [x] settings.json — verified exists at ~/claude-custom/settings.json (symlinked to ~/.claude/settings.json)
  • [x] GroupMe matchers already split — verified: lines 113-137 show three separate entries for mcp__groupme__send_message, mcp__groupme__add_member, mcp__groupme__remove_member (fix already applied during incident)
  • [x] Write|Edit|NotebookEdit pipe-separated matcher (line 91) — verified: hooks return deny or exit 2, never ask. NOT affected by this bug. No split needed.
  • [x] mcp__forgejo__create_issue|mcp__forgejo__create_issue_and_branch pipe-separated matcher (line 158) — verified: hooks return deny or allow, never ask. NOT affected by this bug. No split needed.
  • [x] Convention note convention-hook-matcher-pattern — to be created in pal-e-docs (new artifact, not a file modification)

Repo Placement

OK. The settings.json audit belongs in forgejo_admin/claude-custom, which is where the Forgejo issue is filed. The convention note creation is a pal-e-docs write (via MCP tool), not a file in the repo. Single-repo scope is correct.

Dependencies

  • claude-custom#160 (GroupMe incident fix) — CLOSED. The immediate fix (splitting GroupMe matchers) is already merged. This ticket documents the convention and audits remaining matchers.
  • claude-custom#164 (auto-pull hook) — CLOSED. Related but independent — ensures hooks stay current across sessions.
  • Board item #357 (claude-custom#160, story:GM-5, type:incident-fix) — in done column. No blocking dependency.
  • Board item #375 (claude-custom#164) — in done column. No blocking dependency.
  • No items in in_progress or next_up block or are blocked by this ticket.

Acceptance Criteria

All 4 acceptance criteria are verifiable:
  • [x] "All PreToolUse matchers that return permissionDecision: ask use separate entries" — agent can grep settings.json for pipe-separated matchers and cross-reference with hook scripts returning "ask". Audit already done in this review: only remaining pipe-separated matchers (Write|Edit|NotebookEdit and create_issue|create_issue_and_branch) do NOT return "ask", so they pass.
  • [x] "Convention note convention-hook-matcher-pattern created" — agent can verify via get_note(slug="convention-hook-matcher-pattern")
  • [x] "Convention documents the specific failure mode" — verifiable by reading note content
  • [x] "Existing pipe-separated PreToolUse matchers audited" — the audit result is already known: 2 pipe-separated matchers remain, neither uses "ask", both are safe
Test expectations are manual (session-level verification in bypass mode). Appropriate for a convention + config change.

Blast Radius

  • SubagentStart matcher uses pipes too"qa|dev|general-purpose|dottie|penny" (line 278). This is NOT a PreToolUse hook and does NOT return "ask", so it is NOT affected. The ticket's constraints correctly scope this to PreToolUse + ask only.
  • PostToolUse matchers — None use pipes currently. The ticket correctly notes PostToolUse pipes "appear to work fine" and advises not splitting those unnecessarily.
  • No sibling services affected — settings.json is a single global config. No other repos have their own hook matcher configs.
  • Potential future risk — Any new PreToolUse hook added with pipe-separated matchers AND "ask" would silently fail. The convention note is the mitigation.

Recommendation

No action needed — scope is solid. The audit is already effectively complete (verified in this review). The remaining work is:
  • Create the convention note in pal-e-docs
  • Optionally add a comment to settings.json near the pipe-separated matchers noting they are safe because they don't use "ask"
Points (2) are appropriate for the remaining convention-note creation + minor config annotation work.