Skip to content

fix(claude-config): defer hook blockability to the upstream per-event exit-2 table - #2041

Merged
kyle-sexton merged 8 commits into
mainfrom
fix/row244-claude-config-hook-event-partition
Aug 9, 2026
Merged

fix(claude-config): defer hook blockability to the upstream per-event exit-2 table#2041
kyle-sexton merged 8 commits into
mainfrom
fix/row244-claude-config-hook-event-partition

Conversation

@kyle-sexton

@kyle-sexton kyle-sexton commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Summary

plugins/claude-config/skills/audit-instructions/reference/conflict-criteria.md adjudicated a
hook-half conflict pair by splitting hook events into two named lists — "Blockable events"
(PreToolUse, UserPromptSubmit, Stop, SubagentStop, PreCompact, UserPromptExpansion) and
"Non-blockable events" (PostToolUse, Notification, SubagentStart, SessionStart,
SessionEnd) — phrased as an exhaustive partition. That phrasing is the defect: the event set is
upstream-owned and grows.

Upstream evidence. The hooks page's #### Exit code 2 behavior per event table
(https://code.claude.com/docs/en/hooks#exit-code-2-behavior-per-event, fetched 2026-08-08 via the
raw-markdown channel) carries 31 rows, not 11. Events this repository's own hooks register that
appeared in neither list:

Hook event Can block? What happens on exit 2 (upstream cell)
ConfigChange Yes Blocks the configuration change from taking effect (except policy_settings)
PostToolBatch Yes Stops the agentic loop before the next model call
StopFailure No Output and exit code are ignored
PermissionDenied No Exit code and stderr are ignored because the denial already occurred
InstructionsLoaded No Exit code is ignored

Under the old text an auditor could grade none of these. Two further rows also show why a copied
list is the wrong shape even when complete: PostToolBatch prevents "the agentic loop before the
next model call" and TaskCreated "rolls back the task creation" — neither is a tool call or a
prompt, so "the act it blocks" needs the row's own cell to supply it.

The fix (pointer-not-copy). The bullet now names that table as the sole authority and restates
none of its rows in either direction. The procedure: resolve the handler's event, read its row, and
pair on the row's own Can block? cell — taking the paired content from what the row states is
prevented rather than assuming a tool call or prompt; pairing as nothing when the cell says no; and
recording an event with no row (or an unreachable table) as blockability-unresolved, reusing the
file's existing text-unresolved / liveness-unresolved report-rather-than-infer shape instead of
inventing a third vocabulary.

The criterion keeps its detection function. Both worked examples survive, now marked as examples:
PostToolUse (blocks nothing, the tool already ran, with the plugins/actionlint/hooks/actionlint-check.sh
pointer) and the PreToolUse counterfactual that eval 16 turns on. The SubagentStop
subagent-scoping sentence is kept as its own standing rule rather than a list member.

Also updated: the file's recheck trigger, which fired on "a change to which events exit 2 can
actually block" — now scoped to the table's removal, renaming, or restructuring, since a row added
upstream can no longer stale anything here. Review follow-up: the exemption is narrowed so that a
change to the SubagentStop, PostToolUse, or PreToolUse rows — the three the worked examples
cite — does fire a recheck.

Files changed

  • plugins/claude-config/skills/audit-instructions/reference/conflict-criteria.md — the partition
    rewrite, the recheck trigger, and the file header (1.3.0 → 1.4.0, 2026-08-08)
  • plugins/claude-config/skills/audit-instructions/evals/evals.json — eval 16's expected_output
    and second expectation now test the row lookup rather than the memorized split; the PostToolUse
    verdict the eval exists to check is unchanged, ids are not renumbered
  • plugins/claude-config/.claude-plugin/plugin.json — 0.25.0 → 0.27.1 (re-versioned twice after
    merges of main: first to 0.26.1 when 0.26.0 landed, then to 0.27.1 when 0.27.0 landed via feat(plugins): align instruction surfaces with the current prompting guide and add the posture-audit lane #2018)
  • plugins/claude-config/CHANGELOG.md## [0.27.1] entry, placed above main's ## [0.27.0]

Deviations from the row brief

  • The row says the same claims appear in SKILL.md. They do not. A grep for
    blockable|non-blocking|blocks nothing|UserPromptExpansion|SessionEnd|PostToolUseFailure|Notification
    across audit-instructions/ returns only conflict-criteria.md and evals.json for the
    partition; SKILL.md:157 carries a generic "the act it blocks under its event and matcher"
    (event-agnostic, still correct) and SKILL.md:160/:164 concern stdout and additionalContext
    scoping, not blockability. No SKILL.md edit was manufactured to satisfy the row's wording.
  • The centrally allocated version was 0.21.11, which is behind this plugin's current version on
    main and would have regressed the changelog order — the exact failure class
    check-changelog-parity.sh --check-order exists to catch. Used the reallocated 0.25.2, then
    re-versioned to 0.26.1 (via a merge of origin/main, not a rebase) after 0.26.0 landed on main,
    then to 0.27.1 via a second merge of origin/main after feat(plugins): align instruction surfaces with the current prompting guide and add the posture-audit lane #2018 landed 0.27.0 (that merge also
    composed feat(plugins): align instruction surfaces with the current prompting guide and add the posture-audit lane #2018's evals.json changes — eval 2's I27 → I28 — with this PR's eval-16 rewrite).
  • No new eval was added for an event outside the old lists. It would prove the fix, but the row
    asks only that evals stay consistent, and evals.json is contended by sibling PRs.

Test plan

  • scripts/check-changelog-parity.sh --check — PASS ("Every versioned plugin has a CHANGELOG.md")
  • scripts/check-changelog-parity.sh --check-bump origin/main — PASS (version entry present at
    head, absent at base; re-run at 0.27.1 after the second merge of main)
  • scripts/check-changelog-parity.sh --check-order — PASS (all 72 changelogs newest-first)
  • scripts/check-changed-skills.sh origin/main — PASS, 0 errors, 2 warnings, both pre-existing and
    untouched by this diff (SKILL.md 398 lines vs the 200-line soft target;
    reference/criteria.md:976 fresh-eyes declaration)
  • markdownlint-cli2 over the changed markdown — 0 errors
  • evals.json validated against plugins/skill-quality/reference/evals.schema.json via ajv-cli
    (draft 2020-12) — valid; 16 eval cases parse
  • Discriminating check: an auditor holding only conflict-criteria.md can now grade an event named
    nowhere in the file (Elicitation, FileChanged, PostToolBatch) — look up its row, quote the
    cell, or mark it blockability-unresolved.

Related

No linked issue — this PR closes nothing. It fixes one row (row 244) of the multi-row umbrella issue
#1989, which stays open for its remaining rows, so a closing keyword would be wrong here.

… exit-2 table

The exit-2 bullet in audit-instructions' conflict-criteria.md split hook events
into six "blockable" and five "non-blockable" names and read as exhaustive. The
hooks page's "Exit code 2 behavior per event" table documents far more, and this
repository's own hooks register five events in neither list — ConfigChange and
PostToolBatch block on exit 2, while StopFailure, PermissionDenied, and
InstructionsLoaded have their exit code ignored — so an auditor holding this file
could not grade any of them.

The bullet now names that table as the sole authority and restates none of its
rows: resolve the handler's event, read its row, pair on the row's own
`Can block?` cell, and take the paired content from what the row states is
prevented rather than assuming a tool call or a prompt. An event with no row, or
an unreachable table, is recorded as `blockability-unresolved` on the same terms
as the file's existing text-unresolved rule instead of being inferred. The
SubagentStop subagent-scoping rule and the PostToolUse/PreToolUse worked pair
survive as examples, so the criterion keeps its detection function. The recheck
trigger no longer fires on a row added upstream, and eval 16 tests the lookup
procedure rather than the memorized split.

Refs #1989 (row 244)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@cursor

cursor Bot commented Aug 8, 2026

Copy link
Copy Markdown

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

@claude

claude Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Claude finished @kyle-sexton's task in 41s —— View job


Security review complete

  • Gather context (PR diff, changed files)
  • Review changed files for security issues
  • Post findings

Scope: all 4 files changed in this PR (per git diff origin/main...HEAD):

  • plugins/claude-config/.claude-plugin/plugin.json (version bump only)
  • plugins/claude-config/CHANGELOG.md (changelog entry)
  • plugins/claude-config/skills/audit-instructions/evals/evals.json (eval prompt/expectation text)
  • plugins/claude-config/skills/audit-instructions/reference/conflict-criteria.md (reference doc prose)

Findings: none.

This PR is a documentation/reference-content change to a Claude Code skill's audit criteria, plus a matching eval-fixture update, changelog entry, and semver bump. There is no executable code, no shell/script logic, no GitHub Actions workflow or permissions: change, no .mcp.json/settings/hook-wiring change, and no secret, token, or credential handling anywhere in the diff.

Specifically checked and ruled out for this diff:

  • Injection surfaces (command/SQL/path/template): none — no code paths, only static Markdown prose and JSON string fields consumed as documentation/eval text, never executed or interpolated into a shell/template.
  • Prompt-injection / trust-boundary risk: the new conflict-criteria.md prose is static, PR-reviewed repo content (not fetched or generated from an untrusted runtime source), so it doesn't introduce an attacker-controlled instruction surface for the skill.
  • Secrets/credentials: none referenced or introduced.
  • GitHub Actions / CI risk (pull_request_target, workflow_run, github context script injection, unpinned actions): not applicable — no workflow files are touched.
  • Permission widening: plugin.json only changes version (0.25.0 → 0.25.2); no permissions, allowedTools, or grant fields touched.
  • Supply chain: no dependency or action pin changes.

No further action needed from a security standpoint.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fac543af4b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread plugins/claude-config/skills/audit-instructions/reference/conflict-criteria.md Outdated
@claude

claude Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Claude finished @kyle-sexton's task in 3m 56s —— View job


Review complete

  • Gather context (diff, changed files, CLAUDE.md/REVIEW.md guidelines)
  • Review conflict-criteria.md changes
  • Review evals.json changes
  • Review plugin.json / CHANGELOG.md version bump
  • Post inline findings
  • Post final summary

Scope. Reviewed the 4 changed files against origin/main (git diff origin/main -- <path> per file, since the checkout's origin/main had no common merge-base with HEAD for a single three-dot diff — worked around by diffing per file). Also independently fetched the live hooks page (https://code.claude.com/docs/en/hooks#exit-code-2-behavior-per-event) via WebFetch, since this PR modifies a hook-contract-adjacent surface and CLAUDE.md's fresh-docs mandate applies.

Independently verified (I ran these myself):

  • The live "Exit code 2 behavior per event" table has 31 rows, confirming the PR's headline claim. All five newly-cited rows (ConfigChange, PostToolBatch, StopFailure, PermissionDenied, InstructionsLoaded) match what the PR quotes, including the PostToolBatch and PermissionDenied cell text.
  • evals.json is syntactically valid JSON (jq empty), and eval id 16's new expected_output/expectations are internally consistent with the rewritten conflict-criteria.md prose.
  • plugin.json's version is 0.25.2, matching the new ## [0.25.2] CHANGELOG.md entry (no gap in existing heading conventions — none of this plugin's other headings carry dates either, so that's consistent).
  • Grepped the plugin for stale references to the old "Blockable events"/"Non-blockable events" partition — none remain outside the historical (and correctly untouched) CHANGELOG.md entry for 0.21.9.
  • SKILL.md:157/160/164 (cited in the PR's "Deviations" section as not needing an edit) is in fact event-agnostic prose already, confirming that claim.

Author-claimed, not independently re-run by me (sandboxed shell blocked script execution in this session — bash scripts/check-changelog-parity.sh ..., ajv-cli, markdownlint-cli2, check-changed-skills.sh all required approval I couldn't grant): the PR body's Test Plan results for those specific commands are the author's claim, not something I verified.

One finding posted inline (conflict-criteria.md L24, non-blocking): the new recheck-trigger text says a table row "changed within" the upstream table "needs no recheck — nothing here restates its rows," but the two worked examples a few paragraphs later (L226, L230) do quote verbatim cell text for the PostToolUse and PreToolUse rows specifically. If either of those two rows' wording changes upstream, this file's own examples could go stale without triggering a recheck. Doesn't undermine the core fix — the partition-to-pointer rewrite is correct and well-reasoned — but worth a maintainer call on whether to narrow the exemption or stop quoting cell text verbatim.

Everything else checked out: the pointer-not-copy rewrite is a real improvement (the old text was a closed 11-event partition against a table that now has 31 rows), the new blockability-unresolved marker follows the file's existing text-unresolved/liveness-unresolved pattern correctly, the SubagentStop subagent-scoping carve-out is preserved, and the eval update tests the lookup procedure rather than the memorized list as intended.
· branch

Comment thread plugins/claude-config/skills/audit-instructions/reference/conflict-criteria.md Outdated
@github-actions

github-actions Bot commented Aug 8, 2026

Copy link
Copy Markdown

Claude has reviewed this PR 5 times. The lane skips further automatic reviews after 5; deleting this comment resets the count.

Also narrow the conflict-criteria recheck exemption: a change to the
SubagentStop, PostToolUse, or PreToolUse rows now fires a recheck, since
the worked examples cite those rows' content (review threads on lines
24-25).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HbtPzLRe1yBavNpsmv5Tum
@claude

claude Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Claude finished @kyle-sexton's task in 43s —— View job


Security review complete

  • Gather context (gh pr diff / git diff origin/main...HEAD, changed files)
  • Review changed files for security issues
  • Post findings

Scope: all 4 files changed in this PR relative to origin/main (confirmed via git diff origin/main...HEAD --stat, matching the PR's file list):

  • plugins/claude-config/.claude-plugin/plugin.json — version bump only (0.26.00.26.1, a re-version after 0.26.0 landed on main first)
  • plugins/claude-config/CHANGELOG.md — new ## [0.26.1] entry (prose)
  • plugins/claude-config/skills/audit-instructions/evals/evals.json — eval 16's expected_output/expectations text
  • plugins/claude-config/skills/audit-instructions/reference/conflict-criteria.md — reference-doc prose rewrite

This synchronize event corresponds to commit 1283642 — a merge of origin/main plus the resulting version re-bump; the substantive content is unchanged from the diff reviewed previously.

Findings: none.

Checked and ruled out for this diff:

  • Injection surfaces (command/SQL/path/template): none present — every changed file is static Markdown/JSON content or a manifest version string, never executed, interpolated into a shell command, or used as a template.
  • GitHub Actions / workflow risk (pull_request_target, workflow_run, permissions: widening, github-context script injection, unpinned actions): not applicable — no workflow file is touched by this PR.
  • Secrets / credentials / tokens: none referenced or introduced anywhere in the diff.
  • Permission widening: plugin.json's only change is the version field; no permissions, allowedTools, or grant-related field is touched.
  • Prompt-injection / trust-boundary risk: the rewritten conflict-criteria.md prose is static, PR-reviewed repository content (not fetched or generated from an untrusted runtime source at execution time), so it does not introduce an attacker-controlled instruction surface for the audit-instructions skill.
  • Supply chain: no dependency, action pin, or lockfile changes.

No further action needed from a security standpoint. (Note: the two non-security review threads already on this PR — the recheck-trigger scope on PostToolUse/PreToolUse rows — are documentation-correctness concerns, out of scope for this security-only lane.)

@claude

claude Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Claude finished @kyle-sexton's task in 4m 6s —— View job


Review complete

  • Gather context (PR diff via gh pr diff, REVIEW.md lane scope)
  • Review conflict-criteria.md changes
  • Review evals.json changes
  • Review plugin.json / CHANGELOG.md version bump
  • Post inline findings
  • Post final summary

Lane scope. This repo has a claude-security-review workflow, so per REVIEW.md this lane owns correctness/design/conventions/tests/docs and explicitly leaves security to the security lane (already posted separately on this PR).

What I independently checked (ran these myself):

  • jq empty evals.json — valid JSON.
  • Diffed fac543a (the commit Codex's and the prior Claude review's comments were anchored to) against current HEAD 1283642 for conflict-criteria.md: the recheck-trigger overbreadth both prior reviews flagged has already been fixed on this branch. The current text now carries a change to the table's SubagentStop, PostToolUse, or PreToolUse rows — the three the worked examples below cite as an explicit recheck trigger, closing exactly the gap both comments identified (the two verbatim-quoted rows no longer fall through the "needs no recheck" exemption). No action needed there.
  • plugin.json version (0.26.1) matches the ## [0.26.1] CHANGELOG.md heading; grepped the plugin for stale 1.3.0/old-version references to conflict-criteria.md — none found outside the changelog's own historical entries.
  • Grepped the repo for ConfigChange, PostToolBatch, StopFailure, PermissionDenied, InstructionsLoaded — confirmed this repo's own hooks (plugins/claude-ops/hooks/*) do register handlers on these events, backing the PR body's claim that the old partition left them ungradeable.
  • Read plugins/actionlint/hooks/actionlint-check.sh in full to check the worked example's citation — posted one inline finding: the doc cites this hook as recording "the same thing" as PostToolUse's exit-2-blocks-nothing row, but the hook's own header states # ADVISORY: always exits 0 and every exit path in the script is exit 0 — it never produces exit-2 stderr, so it can't illustrate the exit-2 behavior being cited. This wording pre-dates this PR (unchanged from criteria 1.3.0), but it sits inside the hunk this PR rewrote, in a file whose entire point is citation precision, so flagging it here.

Not independently re-run (would require live-doc fetch or script execution I didn't repeat this pass): the PR body's Test Plan commands (check-changelog-parity.sh, markdownlint-cli2, ajv-cli schema validation) and the upstream 31-row hooks table fetch — the prior Claude review on this PR already fetched that page independently and confirmed the row count and cell text for the five newly-cited events, so I didn't re-fetch it.

Everything else checked out: the pointer-not-copy rewrite is sound — deferring to the upstream table instead of restating a closed partition is the right fix for the actual defect (the old 11-event list vs. the 31-row table); the new blockability-unresolved marker correctly reuses the existing text-unresolved/liveness-unresolved report-rather-than-infer shape (verified both are literally defined later in the same file, so the "below" cross-references resolve correctly); eval 16's rewritten expected_output/expectations test the row-lookup procedure rather than the memorized split, consistent with the new prose; and the SubagentStop subagent-scoping carve-out is preserved.

One unrelated note, not a defect: origin/main has advanced one commit past this branch's merge point (a8e6607, unrelated to claude-config) since this PR's last push — not a version collision (still 0.26.0 there vs. this branch's 0.26.1), just worth a rebase before merge so check-changelog-parity.sh --check-order runs against current main.
· branch

Comment thread plugins/claude-config/skills/audit-instructions/reference/conflict-criteria.md Outdated
The PostToolUse worked example read the hook as an exit-2 emitter; it is
advisory by design — always exit 0, findings via additionalContext —
because exit 2 there could block nothing. The citation now states that,
and the exit-2 hypothetical is generic rather than pinned to this hook.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HbtPzLRe1yBavNpsmv5Tum
@claude

claude Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Claude finished @kyle-sexton's task in 47s —— View job


Security review complete

  • Gather context (gh pr diff, changed files)
  • Review changed files for security issues
  • Post findings

Scope: all 4 files changed in this PR at HEAD cc2a4d3 (per gh pr diff 2041):

Findings: none.

This diff is entirely static Markdown reference-doc prose, a JSON eval-fixture text update, a changelog entry, and a manifest version bump. There is no executable code, no GitHub Actions workflow file, no .mcp.json/settings/hook-wiring change, and no secret, token, or credential handling anywhere in the diff.

Specifically checked and ruled out:

  • Injection surfaces (command/SQL/path/template): none — every changed file is consumed as documentation or eval text, never executed, shelled out, or interpolated into a template.
  • Prompt-injection / trust-boundary risk: the rewritten conflict-criteria.md content is static, PR-reviewed repository content, not fetched or generated from an untrusted runtime source, so it doesn't introduce an attacker-controlled instruction surface for the audit-instructions skill.
  • Link/URL audit: every URL added or touched in conflict-criteria.md resolves to code.claude.com/docs/... or this repo's own GitHub issues — no unexpected or attacker-controlled domains.
  • Secrets/credentials: none referenced or introduced.
  • GitHub Actions / CI risk (pull_request_target, workflow_run, permissions: widening, github-context script injection, unpinned actions): not applicable — no workflow file is touched by this PR.
  • Permission widening: plugin.json's only change is the version field; no permissions, allowedTools, or grant-related field is touched.
  • Supply chain: no dependency, action pin, or lockfile changes.

No further action needed from a security standpoint. (The two prior non-security review threads on this PR — the recheck-trigger scope and the actionlint-check.sh citation — are documentation-correctness concerns already addressed by the author in the latest commit; out of scope for this security-only lane.)
· branch

@claude

claude Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Claude finished @kyle-sexton's task in 2m 24s —— View job


Review complete

  • Gather context (diff per changed file vs origin/main, prior review threads, REVIEW.md lane scope)
  • Review conflict-criteria.md changes (post-fix state)
  • Review evals.json changes
  • Review plugin.json / CHANGELOG.md version bump
  • Post inline findings (none survive — see below)
  • Post final summary

Lane scope. Per REVIEW.md, this repo runs a claude-security-review workflow, so this lane owns correctness/design/conventions/docs and leaves security to the security lane (already posted separately, findings: none).

What I independently verified myself (not author-claimed):

  • jq empty evals.json — valid JSON.
  • Read plugins/actionlint/hooks/actionlint-check.sh in full and grepped every exit call (lines 38, 44, 47, 66, 72, 129, 145, 160, 180, 186) — all are exit 0, and the header (L5) says # ADVISORY: always exits 0. This confirms the fix in the latest commit (cc2a4d3) is now accurate: conflict-criteria.md:227-230 now says the hook "deliberately always exits 0 ... because an exit 2 there could block nothing" instead of the prior wording that implied the hook demonstrates exit-2 behavior. That closes the finding from my previous review pass on this PR.
  • Two WebFetch calls against the live hooks page's Exit code 2 behavior per event table (first pass under-read via the summarizing model; a more explicit "list every row" prompt got the full table): 31 data rows, confirming the PR's headline claim. Verbatim cell text for the three rows this file now cites and gates its recheck trigger on:
    • PreToolUse — Yes / "Blocks the tool call" — matches conflict-criteria.md:233's quote.
    • PostToolUse — No / "Shows stderr to Claude; the tool already ran" — matches the "the tool already ran" quote at L227.
    • SubagentStop — Yes / "Prevents the subagent from stopping" — matches the "blocks" claim at L222.
    • Also independently confirmed the five newly-cited events (ConfigChange, PostToolBatch, StopFailure, PermissionDenied, InstructionsLoaded) and their cell text exactly as quoted in the PR body.
  • Read conflict-criteria.md:16-25 (recheck trigger) and confirmed the narrowed exemption is internally consistent: it now fires on a change to the SubagentStop, PostToolUse, or PreToolUse rows — exactly the three rows the worked examples at L219-234 quote verbatim — and stays exempt only for added rows or rows this file doesn't cite. This resolves the Codex review comment and my own prior inline comment on the same gap.
  • Cross-checked the blockability-unresolved marker (L236) against the text-unresolved rule it says to reuse — confirmed at L242, below as claimed, so the "below" cross-reference resolves correctly.
  • plugin.json version (0.26.1) matches the ## [0.26.1] CHANGELOG.md heading, which is correctly ordered above ## [0.26.0].

Not independently re-run (would require executing repo scripts I don't have approval to run in this session): check-changelog-parity.sh, markdownlint-cli2, ajv-cli schema validation against evals.schema.json, check-changed-skills.sh — these remain author-claimed per the PR body's Test Plan.

Conclusion: both open review threads on this PR (the recheck-trigger overbreadth flagged by Codex and my prior pass, and the actionlint-check.sh citation mismatch I flagged) are fixed in the current HEAD (cc2a4d3) and verified above. I found no new issues. The pointer-not-copy rewrite is sound: it correctly defers a growing, upstream-owned event set to the table itself instead of re-encoding a closed partition, the worked examples and their recheck coverage are now consistent, and the eval update (id 16) tests the row-lookup procedure rather than the memorized split.
· branch

Composed both sides: main's prompting-guide alignment (#2018, seven-skill
description, eval 2 I27->I28) and this PR's eval-16 row-lookup rewrite.
CHANGELOG entry retitled [0.26.1] -> [0.27.1] above main's [0.27.0].

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HbtPzLRe1yBavNpsmv5Tum
@claude

claude Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Claude finished @kyle-sexton's task in 47s —— View job


Security review complete

  • Gather context (git diff origin/main...HEAD, changed files)
  • Review changed files for security issues
  • Post findings

Scope: all 4 files changed in this PR at HEAD 9cd5a2b (matches the PR's stated file list and line counts exactly — git diff origin/main...HEAD --stat confirms +53/-21 across the same 4 paths):

  • plugins/claude-config/.claude-plugin/plugin.json — version bump only (0.27.00.27.1, a re-version after 0.27.0 landed on main first)
  • plugins/claude-config/CHANGELOG.md — new ## [0.27.1] entry (prose)
  • plugins/claude-config/skills/audit-instructions/evals/evals.json — eval 16's expected_output/expectations text
  • plugins/claude-config/skills/audit-instructions/reference/conflict-criteria.md — reference-doc prose rewrite (unchanged in substance from the version reviewed at cc2a4d3; this synchronize is just the merge-and-reversion to keep pace with main)

Findings: none.

This diff is entirely static Markdown reference-doc prose, a JSON eval-fixture text update, a changelog entry, and a manifest version bump. There is no executable code, no GitHub Actions workflow file, no .mcp.json/settings/hook-wiring change, and no secret, token, or credential handling anywhere in the diff.

Specifically checked and ruled out:

  • Injection surfaces (command/SQL/path/template): none — every changed file is consumed as documentation or eval text, never executed, shelled out, or interpolated into a template.
  • Prompt-injection / trust-boundary risk: the rewritten conflict-criteria.md content is static, PR-reviewed repository content, not fetched or generated from an untrusted runtime source, so it doesn't introduce an attacker-controlled instruction surface for the audit-instructions skill.
  • Link/URL audit: the one URL touched (https://code.claude.com/docs/en/hooks#exit-code-2-behavior-per-event) resolves to the official docs domain already cited elsewhere in this file — no new or attacker-controlled domains introduced.
  • Secrets/credentials: none referenced or introduced.
  • GitHub Actions / CI risk (pull_request_target, workflow_run, permissions: widening, github-context script injection, unpinned actions): not applicable — no workflow file is touched by this PR.
  • Permission widening: plugin.json's only change is the version field; no permissions, allowedTools, or grant-related field is touched.
  • Supply chain: no dependency, action pin, or lockfile changes.

No further action needed from a security standpoint. (The prior non-security review threads on this PR — the recheck-trigger scope and the actionlint-check.sh citation — are documentation-correctness concerns already resolved by the author in earlier commits per the review thread; out of scope for this security-only lane.)
· branch

@claude

claude Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Claude finished @kyle-sexton's task in 1m 23s —— View job


Review complete

  • Gather context (gh pr diff 2041 for the authoritative diff, since this branch is a shallow clone with no local merge-base against origin/main; prior review threads; REVIEW.md lane scope)
  • Review what changed since the last reviewed commit (cc2a4d3)
  • Review conflict-criteria.md changes
  • Review evals.json changes
  • Review plugin.json / CHANGELOG.md version bump
  • Post inline findings (none — nothing new to anchor)
  • Post final summary

Lane scope. Per REVIEW.md this repo runs a claude-security-review workflow, so this lane owns correctness/design/conventions/docs and leaves security to the security lane (already posted separately on this PR, findings: none).

What changed in this synchronize event. I ran gh pr diff 2041 directly (this checkout is a shallow clone, so git diff origin/main...HEAD has no local merge-base — gh pr diff is authoritative regardless). The actual PR diff against main is 135 lines across the same 4 files, and is content-identical to what the last two review passes (at cc2a4d3) already examined:

  • plugin.json: 0.27.00.27.1 (pure re-version)
  • CHANGELOG.md: new ## [0.27.1] entry, correctly ordered above ## [0.27.0] — I read the file directly and confirmed the ordering and that the entry text is unchanged from the prior ## [0.26.1] entry (only the heading number moved)
  • evals.json eval 16 and conflict-criteria.md: I diffed these files between cc2a4d3 and current HEAD directly — zero content difference. Both previously-open review threads (the recheck-trigger exemption narrowing, and the actionlint-check.sh citation fix) remain exactly as fixed and verified in the prior pass.

The extra commits visible in git log between cc2a4d3 and HEAD (audit-prompting-postures, I28, etc.) are origin/main commits pulled in by the Merge origin/main; re-version to 0.27.1 merge commit — they touch SKILL.md, criteria.md, and eval id 2, none of which are in this PR's actual diff (already on main, not introduced by this branch). Confirmed via git diff cc2a4d3..HEAD that eval id 2 and criteria.md's I6–I27I6–I28 edits are part of that unrelated main history, not this PR.

Conclusion: no new findings. This synchronize event is a merge-forward-and-re-version housekeeping push with no substantive content change; the two issues raised earlier in review (Codex's and my own recheck-trigger comment, and my actionlint-check.sh citation comment) were already fixed and independently re-verified in the prior review pass, and remain fixed here. The changelog ordering after the re-version is correct.
· branch

@kyle-sexton
kyle-sexton enabled auto-merge (squash) August 9, 2026 04:21
@claude

claude Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Claude finished @kyle-sexton's task in 2m 16s —— View job


Review complete

  • Gather context (git diff origin/main...HEAD, changed files, prior review threads, REVIEW.md lane scope)
  • Review conflict-criteria.md changes at current HEAD
  • Review evals.json changes
  • Review plugin.json / CHANGELOG.md version bump
  • Post inline findings
  • Post final summary

Lane scope. Per REVIEW.md, this repo runs a claude-security-review workflow, so this lane owns correctness/design/conventions/docs and leaves security to the security lane (posted separately on this PR, findings: none).

One finding posted inline, and it's a real blocker: plugins/claude-config/CHANGELOG.md:8-33 has unresolved git merge-conflict markers committed into the file (<<<<<<< HEAD, ||||||| 75b0c7b9, =======, >>>>>>> origin/main) — I confirmed this by reading the file at current HEAD (6acc3e1) and confirmed git status is clean, so it's committed content from the "Merge origin/main; re-version to 0.27.2" merge commit, not a stray local state. Worse, plugin.json now declares "version": "0.27.2" but the changelog's newest heading is still ## [0.27.1] — there's no ## [0.27.2] entry at all, which is exactly the mismatch check-changelog-parity.sh --check-bump exists to catch. The PR body's passing test-plan run for that script predates this merge commit (its own "Deviations" section only narrates re-versioning through 0.27.1). This needs a real merge resolution — this PR's ### Fixed entry and main's ### Changed entry both need to land cleanly, most likely under a new ## [0.27.2] heading — not just a marker strip.

What I independently verified myself (not author-claimed):

  • git diff origin/main...HEAD --stat matches the PR's stated file list and line counts exactly (4 files, +54/-21 total once counted against my working tree — matches the PR's "+54/-21" line).
  • Grepped all 4 changed files for leftover <<<<<<</=======/>>>>>>> markers — only CHANGELOG.md is affected; plugin.json, evals.json, and conflict-criteria.md are clean.
  • Read conflict-criteria.md's full recheck-trigger text (lines 17-26): the exemption Codex and a prior review pass both flagged is fixed — it now explicitly fires on a change to the SubagentStop, PostToolUse, or PreToolUse rows (the three the worked examples quote verbatim), and only exempts added rows or rows this file doesn't cite.
  • Confirmed the blockability-unresolved marker (line 236) correctly cross-references the text-unresolved rule, which is in fact defined below it at line 242.
  • Read the PostToolUse worked example (lines 224-234): the actionlint-check.sh citation fix flagged in an earlier review pass is in place — it now describes the hook as deliberately always exiting 0, not as a hook that demonstrates exit-2 behavior.
  • The evals.json diff (eval 16) is internally consistent with the rewritten prose — it now asks for a row-lookup procedure rather than a memorized partition, matching the file's new approach.

Not independently re-run (sandboxed shell in this session blocked script execution, same as prior review passes on this PR): check-changelog-parity.sh, markdownlint-cli2, ajv-cli schema validation, check-changed-skills.sh — the PR body's Test Plan results for these are the author's claim, not something I verified, and in the case of check-changelog-parity.sh specifically, the claimed pass is now stale relative to the current HEAD given the finding above.

Everything else checks out: the pointer-not-copy rewrite of the blockability criterion is a real improvement — deferring to the upstream 31-row table instead of a stale 11-event partition is the correct fix for the defect described in the PR body, both previously-open review threads (recheck-trigger scope, actionlint-check.sh citation) are resolved in the current content, and the eval update tests the lookup procedure rather than the memorized list as intended. The only outstanding issue is the changelog merge conflict.
· branch

@claude

claude Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Claude finished @kyle-sexton's task in 50s —— View job


Security review complete

  • Gather context (git diff origin/main...HEAD, changed files)
  • Review changed files for security issues
  • Post findings

Scope: all 4 files changed in this PR at HEAD 6acc3e1 (git diff origin/main...HEAD --stat confirms +54/-21 across the same 4 paths the PR describes):

  • plugins/claude-config/.claude-plugin/plugin.json — version bump only (0.27.10.27.2)
  • plugins/claude-config/CHANGELOG.md — changelog content (see note below)
  • plugins/claude-config/skills/audit-instructions/evals/evals.json — eval 16 text (unchanged since the last review pass — identical to 9cd5a2b)
  • plugins/claude-config/skills/audit-instructions/reference/conflict-criteria.md — reference-doc prose (unchanged since the last review pass — identical to 9cd5a2b)

This synchronize event corresponds to a merge of origin/main plus a version re-bump (0.27.10.27.2, after main's 0.27.1 landed). conflict-criteria.md and evals.json are byte-identical to the version already reviewed and cleared multiple times on this PR.

Findings: none (security).

As with every prior pass, this diff is entirely static Markdown/JSON reference content and a manifest version bump — no executable code, no GitHub Actions workflow file, no .mcp.json/settings/hook-wiring change, and no secret, token, or credential handling anywhere in the diff. No injection surfaces, no trust-boundary changes, no permission widening, no supply-chain/pin changes.

Non-security note (flagging since it affects merge-worthiness, not filing as a finding since it's out of this lane's scope): plugins/claude-config/CHANGELOG.md currently contains unresolved git merge-conflict markers, committed at HEAD 6acc3e1:

6acc3e1:plugins/claude-config/CHANGELOG.md:8:<<<<<<< HEAD
6acc3e1:plugins/claude-config/CHANGELOG.md:25:||||||| 75b0c7b9
6acc3e1:plugins/claude-config/CHANGELOG.md:26:=======
6acc3e1:plugins/claude-config/CHANGELOG.md:33:>>>>>>> origin/main

(permalink)

This isn't a security issue (no code execution/parsing risk beyond changelog tooling), but it's a real content defect from the origin/main merge that resolved the version number without resolving the changelog body — both this PR's 0.27.1 "Fixed" entry and main's unrelated 0.27.0→ actually a 0.27.1 "Changed" entry (the audit-instructions listing-description trim) are left straddling raw conflict markers under the same ## [0.27.1] heading. This would very likely fail check-changelog-parity.sh --check-order / markdownlint and should be resolved before merge.

No further action needed from a security standpoint.
· branch

… commit

The prior merge commit pushed a CHANGELOG.md still carrying conflict markers and
the 0.27.1 heading while plugin.json claimed 0.27.2. The row-244 entry now heads
the file as 0.27.2 above main's 0.27.1 listing-trim entry.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HbtPzLRe1yBavNpsmv5Tum
@claude

claude Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Claude finished @kyle-sexton's task in 43s —— View job


Security review complete

  • Gather context (gh pr diff 2041, changed files)
  • Review changed files for security issues
  • Post findings

Scope: all 4 files changed in this PR at HEAD c383014 (matches the PR's stated file list and diff exactly):

Findings: none.

This diff is entirely static Markdown reference-doc prose, a JSON eval-fixture text update, a changelog entry, and a manifest version bump. There is no executable code, no GitHub Actions workflow file, no .mcp.json/settings/hook-wiring change, and no secret, token, or credential handling anywhere in the diff.

Specifically checked and ruled out:

  • Injection surfaces (command/SQL/path/template): none — every changed file is consumed as documentation or eval text, never executed, shelled out, or interpolated into a template.
  • Prompt-injection / trust-boundary risk: the conflict-criteria.md content is static, PR-reviewed repository content, not fetched or generated from an untrusted runtime source, so it doesn't introduce an attacker-controlled instruction surface for the audit-instructions skill.
  • Link/URL audit: no new or changed URLs in this synchronize's diff beyond what was already reviewed in prior commits (code.claude.com/docs/...).
  • Secrets/credentials: none referenced or introduced.
  • GitHub Actions / CI risk (pull_request_target, workflow_run, permissions: widening, github-context script injection, unpinned actions): not applicable — no workflow file is touched by this PR.
  • Permission widening: plugin.json's only change is the version field; no permissions, allowedTools, or grant-related field is touched.
  • Supply chain: no dependency, action pin, or lockfile changes.

No further action needed from a security standpoint. (The prior non-security review threads on this PR — the recheck-trigger scope and the actionlint-check.sh citation — are documentation-correctness concerns already resolved by the author in earlier commits per the review thread; out of scope for this security-only lane.)
· branch

Comment thread plugins/claude-config/CHANGELOG.md
…fig-hook-event-partition

# Conflicts:
#	plugins/claude-config/CHANGELOG.md
@claude

claude Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Claude finished @kyle-sexton's task in 51s —— View job


Security review complete

  • Gather context (git diff origin/main...HEAD, changed files)
  • Review changed files for security issues
  • Post findings

Scope: all 4 files changed in this PR at HEAD 82646f2 (git diff origin/main...HEAD --stat confirms +52/-21 across the same 4 paths the PR describes):

Findings: none (security).

As with every prior pass on this PR, this diff is entirely static Markdown/JSON reference content and a manifest version bump. No executable code, no GitHub Actions workflow file, no .mcp.json/settings/hook-wiring change, and no secret, token, or credential handling anywhere in the diff.

  • Injection surfaces (command/SQL/path/template): none — every changed file is consumed as documentation or eval text, never executed, shelled out, or interpolated into a template.
  • Prompt-injection / trust-boundary risk: conflict-criteria.md's content is static, PR-reviewed repository content, not fetched or generated from an untrusted runtime source at execution time, so it doesn't introduce an attacker-controlled instruction surface for the audit-instructions skill.
  • Link/URL audit: the one URL in the diff (https://code.claude.com/docs/en/hooks#exit-code-2-behavior-per-event) resolves to the official docs domain already cited elsewhere in this file — no new or attacker-controlled domain.
  • Secrets/credentials: none referenced or introduced.
  • GitHub Actions / CI risk (pull_request_target, workflow_run, permissions: widening, github-context script injection, unpinned actions): not applicable — no workflow file is touched by this PR.
  • Permission widening: plugin.json's only change is the version field; no permissions, allowedTools, or grant-related field is touched.
  • Supply chain: no dependency, action pin, or lockfile changes.

Non-security note (out of this lane's scope, flagged for visibility only): CHANGELOG.md still carries the unresolved git merge-conflict markers (<<<<<<< HEAD / ||||||| b77782a0 / ======= / >>>>>>> origin/main, lines 10, 25–26, 43) flagged by a prior review pass on this PR — they were not resolved by this synchronize event, and plugin.json was re-bumped to 0.27.3 with still no ## [0.27.3] heading to match. Not a security issue (no code execution/parsing risk), but worth resolving before merge per the earlier correctness-lane finding.

No further action needed from a security standpoint.
· branch

…s 0.27.3

The previous merge commit again left conflict markers in CHANGELOG.md while
plugin.json moved to 0.27.3 (main shipped its own 0.27.2 mid-flight). The
row-244 entry now heads the file as 0.27.3; main's 0.27.2 entry is preserved
byte-identically beneath it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HbtPzLRe1yBavNpsmv5Tum
@claude

claude Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Claude finished @kyle-sexton's task in 49s —— View job


Security review complete

  • Gather context (gh pr diff 2041, changed files)
  • Review changed files for security issues
  • Post findings

Scope: all 4 files changed in this PR at HEAD a03855d (gh pr diff 2041 confirms the same 4 paths as every prior pass):

Findings: none.

This synchronize event resolves the changelog merge conflict flagged by a prior security-lane pass on this PR: I checked CHANGELOG.md directly and confirmed no <<<<<<</=======/>>>>>>>/||||||| markers remain (grep returns nothing), and the new ## [0.27.3] heading now sits at the top of the file matching plugin.json's "version": "0.27.3" — no version/changelog gap. That was a correctness issue, not a security one, but it's the reason this synchronize event exists.

As with every prior pass, this diff is entirely static Markdown/JSON reference content and a manifest version bump — no executable code, no GitHub Actions workflow file, no .mcp.json/settings/hook-wiring change, and no secret, token, or credential handling anywhere in the diff.

  • Injection surfaces (command/SQL/path/template): none — every changed file is consumed as documentation or eval text, never executed, shelled out, or interpolated into a template.
  • Prompt-injection / trust-boundary risk: conflict-criteria.md's content is static, PR-reviewed repository content, not fetched or generated from an untrusted runtime source at execution time, so it doesn't introduce an attacker-controlled instruction surface for the audit-instructions skill.
  • Link/URL audit: the one URL in the diff (https://code.claude.com/docs/en/hooks#exit-code-2-behavior-per-event) resolves to the official docs domain already cited elsewhere in this file — no new or attacker-controlled domain.
  • Secrets/credentials: none referenced or introduced.
  • GitHub Actions / CI risk (pull_request_target, workflow_run, permissions: widening, github-context script injection, unpinned actions): not applicable — no workflow file is touched by this PR.
  • Permission widening: plugin.json's only change is the version field; no permissions, allowedTools, or grant-related field is touched.
  • Supply chain: no dependency, action pin, or lockfile changes.

No further action needed from a security standpoint. (The two non-security review threads previously raised on this PR — the recheck-trigger scope and the actionlint-check.sh citation — were already resolved by the author in earlier commits, and the changelog-merge-conflict correctness issue flagged by this lane's prior pass is now resolved as noted above; all out of scope for this security-only lane.)
· branch

@kyle-sexton
kyle-sexton merged commit 98f94b6 into main Aug 9, 2026
33 checks passed
@kyle-sexton
kyle-sexton deleted the fix/row244-claude-config-hook-event-partition branch August 9, 2026 08:47
kyle-sexton added a commit that referenced this pull request Aug 9, 2026
Version collision on the claude-config plugin: main shipped 0.27.3 (#2041)
while this branch also staged a bump. This branch takes 0.27.4, the next free
number above main, and both changelog entries are kept in full — they fix
unrelated defects.

An earlier merge on this branch had dropped the manifest's `description` field
and unindented its `version` line. The manifest is restored byte-for-byte from
main with only the version line changed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant