From a0740d2f12a85767d0f017406de15bb30e88da92 Mon Sep 17 00:00:00 2001 From: Tri Lam Date: Tue, 19 May 2026 01:12:37 -0700 Subject: [PATCH 1/2] [docs] agent notes: skill direct-orchestration + hook regex word-boundary MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Captures two agent-internal patterns from this session that aren't universal enough for AGENTS.md but would help the next skill author or hook designer avoid the same trap. skill-design.md: why pr-review-loop dropped its plugin dependency (Claude Code permission classifier blew up on ~17KB ARGUMENTS; direct Agent-tool orchestration is the safer shape). automation.md: why the pre-PR checklist hook uses a regex word-boundary matcher rather than substring containment or starts-with — substring over-fires, starts-with under-fires, word-boundary lands the right balance. Both files at "Newest-first" ordering convention. Anchors point at PR #73 and PR #80 respectively. make doc-check clean. Signed-off-by: Tri Lam --- .claude/notes/automation.md | 15 +++++++++++++++ .claude/notes/skill-design.md | 17 +++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/.claude/notes/automation.md b/.claude/notes/automation.md index 0bb32b54..1ca19e3c 100644 --- a/.claude/notes/automation.md +++ b/.claude/notes/automation.md @@ -3,6 +3,21 @@ Lessons specific to Claude Code skills, slash commands, classifier interactions, and parallel-agent workflows in this repo. Newest-first. +### Match shell-command hooks by regex word-boundary, not substring + +Substring patterns like `*"gh pr create"*` fire on any command that +literally contains the target string (`echo gh pr create`, +`bash -c "git push test"`), producing high-volume false positives. +"Starts with" patterns miss compound forms (`cat > body && gh pr +edit`, `var=$(...) && git push`), producing high-cost false +negatives. Use a regex word-boundary match instead: +`(^|[[:space:];&|])(gh pr create|git push)([[:space:]]|$)`. The +cost of an extra advisory fire is one acknowledgment; the cost of +a missed fire on a real PR action is worse. + +Anchor: `.claude/settings.json` PR #80 commit `3c12d02`, +`PreToolUse.Bash.hooks[0].command` regex. + ### Don't escape backticks inside a single-quoted HEREDOC A `bash -c '...$(cat <<'EOF' ... EOF)...'`-style PR-body payload uses diff --git a/.claude/notes/skill-design.md b/.claude/notes/skill-design.md index 92c2cca5..9a0c1d40 100644 --- a/.claude/notes/skill-design.md +++ b/.claude/notes/skill-design.md @@ -3,6 +3,23 @@ Lessons specific to authoring `.claude/skills//SKILL.md` files and related workflow scaffolding. Newest-first. +### Orchestrate multi-phase skills directly, not through plugin $ARGUMENTS + +Routing a skill's full prompt body through a plugin command's +$ARGUMENTS blows the Claude Code permission classifier when the +prompt grows past ~17 KB ("parser timeout, resource limit, or +over-length"). The original `pr-review-loop` skill delegated its +5-phase workload to a plugin's setup script and hit this wall in +real use; PR #73 dropped the dependency and re-routed the phases +to direct Agent-tool dispatches. + +For any new multi-phase skill, orchestrate inline. If a plugin is +the right shape, keep $ARGUMENTS under ~1 KB and pass the heavy +prompt by file path — never the whole body as one positional arg. + +Anchor: PR #73 commit `6ed4fa8`, `.claude/skills/pr-review-loop/SKILL.md` +"How the loop runs" section. + ### Mechanism-test a skill before declaring it ready Manual walkthrough of a multi-step skill protocol misses substitution From dbd6d6c0af7f91198290fe473e0860e4b9676695 Mon Sep 17 00:00:00 2001 From: Tri Lam Date: Tue, 19 May 2026 01:16:43 -0700 Subject: [PATCH 2/2] =?UTF-8?q?[docs]=20agent=20notes:=20carve-outs=20+=20?= =?UTF-8?q?regex=20decomposition=20(A-=20=E2=86=92=20A+)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Self-review on PR #82 surfaced three gaps. This commit closes them: 1. Skill-design carve-out: the lesson now explicitly scopes itself to the multi-phase-with-large-prompt shape, not plugins in general. A future reader won't over-correct and avoid plugins for small, well-typed protocols where they remain the right tool. 2. Automation carve-out + generalization: bias toward false positives only when the hook is advisory. Blocking hooks (those that deny via permissionDecision) should flip to starts-with so unrelated commands aren't forcibly stopped. Also widens the lesson's scope: the trade-off generalizes to any shell-command-matching hook, not just PR/push commands. 3. Regex decomposed into named parts inline: the (^|[[:space:];&|]) prefix + alternation + ([[:space:]]|$) suffix structure is now visible at a glance rather than as a wall of characters. make doc-check clean locally. Signed-off-by: Tri Lam --- .claude/notes/automation.md | 22 ++++++++++++++++++---- .claude/notes/skill-design.md | 10 +++++++--- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/.claude/notes/automation.md b/.claude/notes/automation.md index 1ca19e3c..fbd5c3f9 100644 --- a/.claude/notes/automation.md +++ b/.claude/notes/automation.md @@ -10,10 +10,24 @@ literally contains the target string (`echo gh pr create`, `bash -c "git push test"`), producing high-volume false positives. "Starts with" patterns miss compound forms (`cat > body && gh pr edit`, `var=$(...) && git push`), producing high-cost false -negatives. Use a regex word-boundary match instead: -`(^|[[:space:];&|])(gh pr create|git push)([[:space:]]|$)`. The -cost of an extra advisory fire is one acknowledgment; the cost of -a missed fire on a real PR action is worse. +negatives. A regex word-boundary match lands the balance — three +parts: a leading shell-separator boundary, the alternation, a +trailing boundary: + +``` +(^|[[:space:];&|]) # line start OR shell separator +(gh pr create|git push) # the actual targets +([[:space:]]|$) # space OR line end +``` + +For advisory hooks (surface a checklist, log a warning) bias toward +false positives — the cost of an extra fire is one acknowledgment; +a missed fire on a real action is worse. For blocking hooks (deny +the action via `permissionDecision: deny`) flip the bias: prefer +starts-with so an unrelated command isn't forcibly stopped. + +This trade-off generalizes to any agent hook matching shell commands +by content; PR commands are this entry's example, not its scope. Anchor: `.claude/settings.json` PR #80 commit `3c12d02`, `PreToolUse.Bash.hooks[0].command` regex. diff --git a/.claude/notes/skill-design.md b/.claude/notes/skill-design.md index 9a0c1d40..bf49ad78 100644 --- a/.claude/notes/skill-design.md +++ b/.claude/notes/skill-design.md @@ -13,9 +13,13 @@ over-length"). The original `pr-review-loop` skill delegated its real use; PR #73 dropped the dependency and re-routed the phases to direct Agent-tool dispatches. -For any new multi-phase skill, orchestrate inline. If a plugin is -the right shape, keep $ARGUMENTS under ~1 KB and pass the heavy -prompt by file path — never the whole body as one positional arg. +For any new multi-phase skill with a large prompt body, orchestrate +inline. Plugin delegation remains fine when `$ARGUMENTS` stays well +under ~1 KB and the protocol is well-typed (small command + flags); +this lesson is about the multi-phase-with-large-prompt shape that +hits the classifier wall, not plugins in general. If a plugin is +the right shape but the prompt is heavy, pass it by file path — +never the whole body as one positional arg. Anchor: PR #73 commit `6ed4fa8`, `.claude/skills/pr-review-loop/SKILL.md` "How the loop runs" section.