feat: edit-time comment gate — scope/block-all, narration/density heuristics + PostToolUse hook#11
Open
robdmoore wants to merge 11 commits into
Open
feat: edit-time comment gate — scope/block-all, narration/density heuristics + PostToolUse hook#11robdmoore wants to merge 11 commits into
robdmoore wants to merge 11 commits into
Conversation
robdmoore
commented
Jul 9, 2026
robdmoore
commented
Jul 9, 2026
robdmoore
commented
Jul 9, 2026
robdmoore
commented
Jul 9, 2026
robdmoore
commented
Jul 9, 2026
0228c6e to
16ec6a7
Compare
There was a problem hiding this comment.
Pull request overview
This PR extends the built-in comments check from a single long-block heuristic into a two-axis gate (scope: diff|all, strictness: heuristics vs --block-all) and adds an edit-time Claude PostToolUse hook (verifyx comments-hook) that rejects low-value comments immediately after Write/Edit/MultiEdit operations.
Changes:
- Expand
verifyx commentsto support diff/all scoping, narration detection, comment-density gating, and--block-all(with--block-new-commentsas an alias). - Add a Claude PostToolUse hook pipeline (payload parsing + added-text analysis + CLI command) and scaffold/init support for writing hook/settings + new skills/rules.
- Add templates + generated
.claude/artifacts and update documentation/tests to cover the new behavior.
Reviewed changes
Copilot reviewed 33 out of 33 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| templates/skills/prune-comments/SKILL.md | Adds a remediation skill template for pruning low-value comments. |
| templates/rules/comments-only-when-non-obvious.md | Adds a rule template defining when comments are justified vs noise. |
| src/shared/diff.ts | Adds parsing of removed diff lines to support density net-trim logic. |
| src/shared/config.ts | Extends verify config schema for comments scope/strictness/heuristics tuning. |
| src/shared/comment-scan.ts | Refactors comment scanning to accept source text (enables hook scanning). |
| src/scaffold/init.ts | Adds init flags and wiring for comment gate options and hook installation. |
| src/scaffold/init.test.ts | Tests init script emission for comment gate options. |
| src/scaffold/claudeSettings.ts | Implements idempotent merge into .claude/settings.json for PostToolUse hook. |
| src/scaffold/claudeSettings.test.ts | Tests settings merge/idempotence/unparseable handling. |
| src/scaffold/claudeDir.ts | Adds monorepo-safe resolution of the target .claude directory. |
| src/scaffold/claudeDir.test.ts | Tests .claude resolution rules (ancestor search + git root cap + override). |
| src/scaffold/agentFiles.ts | Scaffolds new prune-comments skill and comment rule into agent integrations. |
| src/report.ts | Adds reporting for block-all, narration, and density violations; exports PUSHBACK. |
| src/hook/payload.ts | Parses Claude PostToolUse payloads and extracts added text for scanning. |
| src/hook/payload.test.ts | Tests payload parsing across tool variants and edge cases. |
| src/hook/analyze.ts | Runs comment heuristics against added text and formats hook feedback. |
| src/hook/analyze.test.ts | Tests hook analysis behavior (narration/blocks/density/exemptions/blockAll). |
| src/comments.ts | Exposes findLongCommentBlocksInContent for reuse by diff/hook analyzers. |
| src/commands/registerInit.ts | Adds init prompts/flags for comment scope/strictness and hook, plus reporting. |
| src/commands/registerCommentsHook.ts | Adds hidden CLI command implementing the PostToolUse hook. |
| src/commands/registerChecks.ts | Updates comments command flags/help and forwards new options into the check. |
| src/cli.ts | Registers the new comments-hook command with the CLI. |
| src/checks/registry.ts | Updates the registry description for the enhanced comments check. |
| src/checks/comments.ts | Reworks the comments check around scope/strictness + narration/density heuristics. |
| src/checks/comments.test.ts | Adds hermetic diff mocking and new test coverage for narration/density/block-all behavior. |
| src/checks/comment-heuristics.ts | Introduces narration detection and density computation utilities. |
| src/checks/comment-heuristics.test.ts | Adds unit tests for narration/density logic. |
| src/checks/comment-common.ts | Centralizes comment exemption logic, scanned extensions, and comment-line helpers. |
| src/checks/comment-collect.ts | Adds diff/all collection pipeline for candidates used by all comment gates. |
| README.md | Documents new comments gate axes, flags, config, hook behavior, and remediation assets. |
| .claude/skills/prune-comments/SKILL.md | Adds repo-local Claude skill for pruning low-value comments. |
| .claude/settings.json | Adds repo-local Claude PostToolUse hook configuration. |
| .claude/rules/comments-only-when-non-obvious.md | Adds repo-local Claude rule for when comments are justified. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Adds two diff-scoped heuristics to the comments check, on by default: session-narration detection ("let me", "as requested", restating what the next line does) and comment density (comments as a share of a changed file's added lines). Both judge only changed lines, exempting JSDoc, context:, and machine directives.
Also adds `verifyx comments-hook`, a Claude Code PostToolUse hook that scans the text an Edit/Write introduced (parsed from the tool payload, no git) and returns exit-2 back-pressure so the agent revises low-value comments in-loop.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
verifyx init now merges the comments-hook PostToolUse entry into .claude/settings.json (idempotent, never clobbering existing keys; --no-comment-hook to skip) and drops a prune-comments remediation skill into .claude/skills and .agent-skills. Dogfoods both into this repo. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ate parity Splits the comments check into two orthogonal axes: --scope diff (default, changed lines) vs all (whole codebase), and --block-all (fail every comment in scope) vs the default heuristics. --block-new-comments becomes an alias for --scope diff --block-all. Long-block detection is now diff-scoped by default like narration/density. Adopts the missing claude-comment-gate signals: H2 LLM punctuation tells (em-dash/curly quotes), H3 net-increase guard (a comment trim is never flagged) and blank-line exclusion from the density denominator. The edit-time hook now reuses the canonical PUSHBACK from report.ts instead of a weaker paraphrase. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
verifyx init now writes .claude/.agent-skills to the nearest existing .claude (cwd, else the closest ancestor within 3 levels, never past the git root, else cwd), with a --claude-dir override, and reports where it landed. Claude Code loads project settings only from its launch dir, so this attaches to the likely launch root instead of clobbering a monorepo parent. Also scaffolds a comments-only-when-non-obvious rule (keep/delete criteria + examples) alongside the skills. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… behaviour Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…comments verifyx init now asks (or takes --comment-scope diff|all and --comment-block-all) how the comments check should gate, and emits the flags into the scaffolded verify:comments script. Non-default choices are emitted even under defaults-only as a verify:comments override, since there's nowhere else to record them. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…t: guidance Scopes the rule's path frontmatter to our extensions (ts/js/yml family); restores the content that was trimmed (the failure-mode preamble, the invented-shorthand and config/infra and duplicated-explanation entries) in TS/YAML; removes all context: guidance from the rule and the prune skill so agents meet the human-paging pushback at the gate rather than pre-learning the escape; no escape-hatch section. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… hook path, init message - --scope all now honours verify.config.json#comments.ignore, not just --ignore. - Diff scope counts a comment as touched when any of its lines changed, not only its opening line (block comments edited in the body now reach narration/block-all). - The hook normalises the payload path (absolute + Windows separators) and matches ignore globs against both absolute and cwd-relative forms. - init's 'wrote to nearest .claude' note only prints when agent files were actually written. - Split resolveSelections to keep registerInit.ts above the maintainability threshold after the rebase. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
c5728e9 to
b87f13f
Compare
…ct no-comments init preset Adds comments.contextOverride (default true; CLI --no-context-override). When off, context: comments are judged like any other — a stricter stance and a way to drive a context: cleanup; JSDoc and machine directives stay exempt. All gate output goes context-free in that mode: the reports drop their 'prefix with context:' lines and --pushback swaps to a strict variant that offers no escape. verifyx init gains a 3-way strictness choice (heuristics / block-all / strict) and --comment-strict: the strict preset bakes --block-all --no-context-override into verify:comments — a no-comments-at-all, JSDoc-only policy. Renames the internal allowContext to contextOverride throughout. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (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.
What & why
Morphs the ideas from jackawatts/claude-comment-gate into
@makerx/verify's comment tooling, re-expressed in our AST-based, cross-agent TS architecture. Thecommentscheck gains real heuristics and an edit-time gate so an agent gets back-pressure the moment it writes a low-value comment — not just at verify/CI time.The
commentscheck — two axes + a strictness dial--scope diff(default: only comments on changed lines) or--scope all(whole codebase).--block-all(every non-exempt comment fails), or, at its strictest,--block-all --no-context-override(a no-comments-at-all, JSDoc-only policy).--block-new-commentsis the alias for--scope diff --block-all.context:override —context:-prefixed comments are exempt by default;--no-context-override(configcomments.contextOverride: false) disables that, judging them like any other comment. Useful for a stricter gate or to drive acontext:cleanup. When disabled, all output goes context-free: the reports drop their "prefix withcontext:" lines and--pushbackswaps to a strict variant that offers no escape.Heuristics (JSDoc /
context:/ machine directives exempt): long blocks, narration (session narration + LLM punctuation tells), density (comment share of the lines in scope, with a net-trim guard).Example invocations
Edit-time PostToolUse hook (
verifyx comments-hook)Reads the Claude Code tool payload on stdin (Write/Edit/MultiEdit; no git), scans only the text the edit introduced, and on a violation writes the canonical pushback to stderr and exits
2— surfaced to the agent in the same turn. HonourscontextOverride(context-free feedback when disabled).Scaffolding & remediation (
verifyx init)prune-commentsskill + acomments-only-when-non-obviousrule (keep/delete criteria + worked examples).verify:commentsscript; also--comment-scope,--comment-block-all,--comment-strict..claude(cwd → nearest ancestor within 3 levels, never past the git root → cwd), with--claude-dirto override, and prints where it landed.Config (
verify.config.json#comments)scope,blockAll,narration,density,minAddedLines,contextOverride,ignore.Divergences from claude-comment-gate (deliberate)
git diff HEADof the file.Testing
npm run verifygreen (all checks + tests + lint + format + types + knip + duplicate-code), including the gates running against this PR's own diff.context:opt-out (check + hook), payload parsing, the.clauderesolver, and the init flag/preset emission.🤖 Generated with Claude Code