Skip to content

feat: add rate limiting, README validation, and externalize init-worktree#72

Merged
JacobPEvans merged 10 commits intomainfrom
feat/externalize-and-rate-limit
Mar 6, 2026
Merged

feat: add rate limiting, README validation, and externalize init-worktree#72
JacobPEvans merged 10 commits intomainfrom
feat/externalize-and-rate-limit

Conversation

@JacobPEvans
Copy link
Owner

Summary

  • Rate limiting: Add 24h rate limits (15/24h) for issues and PRs in enforce-issue-limits.py, expanding command matching to catch gh pr create and gh pr edit
  • README validation: New validate-readme.py PostToolUse hook checks required sections, badge health, and install code blocks with configurable .readme-validator.yaml
  • Externalize init-worktree: Replace custom /init-worktree skill with superpowers:using-git-worktrees plus .claude/rules/worktree-conventions.md for path/branch/cleanup conventions
  • Multi-model delegation: Add /delegate-to-ai reference in CLAUDE.md
  • content-guards v1.1.0: Bump version, add readme-validator skill, update keywords and description

Test plan

  • Verify enforce-issue-limits.py passes through non-matching commands (echo hello)
  • Verify enforce-issue-limits.py catches gh issue create, gh pr create, gh pr edit
  • Verify validate-readme.py skips non-README files
  • Verify validate-readme.py passes READMEs with required sections
  • Verify validate-readme.py blocks READMEs missing required sections
  • Verify .readme-validator.yaml config is loaded (only Installation required)
  • Verify superpowers:using-git-worktrees works with worktree-conventions rule
  • Verify /delegate-to-ai is visible in CLAUDE.md

🤖 Generated with Claude Code

…tree

- Add 24h rate limits (15/24h) for issues and PRs in enforce-issue-limits.py,
  expanding command matching to catch gh pr create/edit
- Add README validation PostToolUse hook (validate-readme.py) checking
  required sections, badge health, and install code blocks
- Replace /init-worktree skill with superpowers:using-git-worktrees plus
  .claude/rules/worktree-conventions.md for path/branch/cleanup conventions
- Add /delegate-to-ai reference in CLAUDE.md for multi-model delegation
- Bump content-guards to v1.1.0 with readme-validator skill and keywords

(claude)
Copilot AI review requested due to automatic review settings March 5, 2026 13:35
@gemini-code-assist
Copy link

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the repository's automation and guardrail capabilities by introducing new validation and rate-limiting features. It centralizes README file quality checks, prevents excessive GitHub issue and PR creation, and refines the approach to Git worktree management by externalizing conventions. These changes aim to improve code quality, maintain a cleaner issue tracker, and streamline development workflows.

Highlights

  • Rate Limiting for Issues and PRs: Implemented 24-hour rate limits (15 issues/PRs per 24h) for GitHub issues and pull requests within enforce-issue-limits.py. The script now also catches gh pr create and gh pr edit commands.
  • README Validation Hook: Introduced a new validate-readme.py PostToolUse hook that checks README files for required sections, badge health, and the presence of installation code blocks. This validation is configurable via a new .readme-validator.yaml file.
  • Externalized Git Worktree Management: The custom /init-worktree skill has been replaced by leveraging superpowers:using-git-worktrees and a new .claude/rules/worktree-conventions.md file, which outlines project-specific conventions for worktree paths, branch naming, and cleanup.
  • Multi-Model Delegation Reference: Added documentation for /delegate-to-ai in AGENTS.md, enabling tasks to be routed to external AI models like Gemini or local Ollama via PAL MCP for enhanced capabilities.
  • Content Guards Plugin Update: The content-guards plugin was updated to version 1.1.0, incorporating the new readme-validator skill and updating its keywords and description to reflect the expanded functionality.
Changelog
  • .claude/rules/worktree-conventions.md
    • Added a new markdown file detailing project-specific conventions for git worktrees, including path, branch naming, and cleanup procedures.
  • .readme-validator.yaml
    • Added a new YAML configuration file to define required and optional sections for README validation, along with settings for badge health checks.
  • AGENTS.md
    • Updated the description for the git-workflows plugin to reflect the removal of /init-worktree and added /refresh-repo.
    • Updated the description for the content-guards plugin to include readme-validator and issue/PR rate limiting.
    • Added a new section on 'Multi-Model Delegation' with a reference to /delegate-to-ai.
  • content-guards/.claude-plugin/plugin.json
    • Updated the plugin version from 1.0.1 to 1.1.0.
    • Revised the plugin description to include readme-validator and issue/PR rate limiter.
    • Added readme and rate-limiting to the plugin keywords.
    • Registered the new ./skills/validate-readme skill.
  • content-guards/README.md
    • Updated the feature list to include readme-validator and enhanced the description of issue-limiter to mention 24h rate limiting.
  • content-guards/hooks/hooks.json
    • Added a new PostToolUse hook that triggers validate-readme.py for Write|Edit operations, ensuring README files are validated upon modification.
  • content-guards/scripts/enforce-issue-limits.py
    • Updated the script's docstring to reflect the new 24-hour rate limiting for issues and PRs.
    • Introduced RATE_LIMIT_24H constant for the new rate limit.
    • Added check_recent_issues and check_recent_prs functions to count recent activity.
    • Implemented block_rate_limit function for consistent error messaging.
    • Expanded command matching to include gh pr create and gh pr edit.
    • Integrated 24-hour rate limit checks for both issue creation and PR creation/editing.
  • content-guards/scripts/validate-readme.py
    • Added a new Python script to perform comprehensive README validation, including checks for required sections, badge URLs, and installation code blocks.
    • Implemented find_config_file to locate .readme-validator.yaml.
    • Included parse_simple_yaml for basic YAML configuration parsing.
    • Developed functions for parsing headings, checking required sections, validating badge URLs, and verifying installation code blocks.
  • content-guards/skills/validate-readme/SKILL.md
    • Added a new skill definition markdown file for /validate-readme, describing its purpose, usage, and steps for auditing README files.
  • git-workflows/.claude-plugin/plugin.json
    • Updated the plugin description to remove reference to 'worktree initialization'.
    • Removed ./skills/init-worktree from the list of skills.
  • git-workflows/skills/init-worktree/SKILL.md
    • Removed the skill documentation for /init-worktree.
Activity
  • No specific human activity (comments, reviews, progress updates) has been recorded for this pull request yet.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@greptile-apps
Copy link

greptile-apps bot commented Mar 5, 2026

Greptile Summary

This PR expands the content-guards plugin with README validation and 24h rate limiting for GitHub issue/PR commands, externalizes the init-worktree skill into a worktree-conventions rule, and updates documentation across AGENTS.md and plugin manifests.

Key findings:

  • validate-readme.py: Well-implemented PostToolUse hook that checks README files for required sections (configurable via .readme-validator.yaml), badge URL reachability, and presence of code blocks in the Installation section. Fail-open error handling is solid.
  • enforce-issue-limits.py: Expands rate limiting to gh pr create and gh pr edit. Critical issue: check_recent_prs() counts all repository PR activity (including CI/bot updates and other contributors' changes), not only Claude-originated PRs. This will cause false-positive rate-limit blocks in any active repository. Additionally, the rate-limit error message claims PRs were "created" when the count includes both created and updated PRs.
  • worktree-conventions.md + init-worktree removal: Clean externalization of conventions; deletion is safe and well-documented.
  • plugin.json / AGENTS.md / content-guards/README.md: Accurate bookkeeping updates.

Confidence Score: 2/5

  • PR introduces a critical logic flaw in PR rate limiting that will cause false-positive blocks in active repositories.
  • The PR has one critical issue in enforce-issue-limits.py: the check_recent_prs() function counts all repository PR activity (CI updates, other contributors' PRs) instead of only Claude-originated actions. This will cause false-positive rate-limit blocks whenever 15+ PRs are touched in the past 24 hours by any actor, making the feature unusable in active repositories. Additionally, the error message is misleading. The README validation and worktree externalization components are solid, but the rate-limiting issue is a blocker for deployment.
  • content-guards/scripts/enforce-issue-limits.py — the check_recent_prs() function must be refactored to count only Claude-authored PRs, and the error message must be corrected to reflect that the count includes both created and updated PRs.

Sequence Diagram

sequenceDiagram
    participant Claude
    participant PreToolUse Hook
    participant PostToolUse Hook
    participant enforce-issue-limits.py
    participant validate-readme.py
    participant GitHub CLI (gh)

    Claude->>PreToolUse Hook: Bash: gh issue create / gh pr create / gh pr edit
    PreToolUse Hook->>enforce-issue-limits.py: stdin JSON (tool_input.command)
    enforce-issue-limits.py->>GitHub CLI (gh): gh issue list (24h count)
    enforce-issue-limits.py->>GitHub CLI (gh): gh pr list --state all (all repo PRs, 24h window)
    GitHub CLI (gh)-->>enforce-issue-limits.py: JSON response
    alt limit exceeded
        enforce-issue-limits.py-->>PreToolUse Hook: exit 2 (BLOCK)
        PreToolUse Hook-->>Claude: Blocked with reason
    else within limit
        enforce-issue-limits.py-->>PreToolUse Hook: exit 0 (ALLOW)
        PreToolUse Hook-->>Claude: Command proceeds
    end

    Claude->>PostToolUse Hook: Write/Edit: README*.md
    PostToolUse Hook->>validate-readme.py: stdin JSON (tool_input.file_path)
    validate-readme.py->>validate-readme.py: find_config_file() → .readme-validator.yaml
    validate-readme.py->>validate-readme.py: check_required_sections()
    validate-readme.py->>validate-readme.py: check_install_code_blocks()
    validate-readme.py->>validate-readme.py: check_badges() [HEAD requests]
    alt missing required sections
        validate-readme.py-->>PostToolUse Hook: exit 2 (BLOCK)
        PostToolUse Hook-->>Claude: Blocked with missing sections
    else warnings only / pass
        validate-readme.py-->>PostToolUse Hook: exit 0 (ALLOW, warnings on stderr)
        PostToolUse Hook-->>Claude: Write/Edit accepted
    end
Loading

Last reviewed commit: 9482c05

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces several new features and refactorings, including rate limiting for issues/PRs, a new README validation hook, and externalizing the git worktree initialization logic. A critical Server-Side Request Forgery (SSRF) vulnerability has been identified in the README validation script's badge checking feature, which could allow a malicious repository to probe a developer's local network. Additionally, a bug in the custom YAML parser in validate-readme.py could lead to silently ignored configurations, and there are suggestions to improve the clarity of the rate-limiting logic, command robustness, and error handling.

…only

check_recent_prs() was counting ALL repo PR activity (created or updated)
in the 24h window, causing false-positive blocks when other contributors,
CI, or GitHub automations touched PRs. Now filters with --author @me and
only counts createdAt, matching check_recent_issues() behavior. Also fixes
the block message which now accurately says "created".

(claude)
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR extends the plugin suite by adding a README validation hook + skill, tightening GitHub CLI guardrails with 24h rate limiting for issues/PRs, and removing the bespoke /init-worktree skill in favor of external superpowers:using-git-worktrees guidance plus a local conventions rule.

Changes:

  • Add README validation (new /validate-readme skill, new PostToolUse hook + .readme-validator.yaml config).
  • Expand enforce-issue-limits.py to detect gh pr create/gh pr edit and enforce 24h rate limits.
  • Remove git-workflows/init-worktree skill and add .claude/rules/worktree-conventions.md for standardized worktree conventions.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
git-workflows/skills/init-worktree/SKILL.md Removes the custom /init-worktree skill definition.
git-workflows/.claude-plugin/plugin.json Drops init-worktree from the plugin skill manifest and updates plugin description accordingly.
content-guards/skills/validate-readme/SKILL.md Adds a /validate-readme skill describing repository-wide README audits.
content-guards/scripts/validate-readme.py Introduces a PostToolUse hook to validate README structure + badges using .readme-validator.yaml.
content-guards/scripts/enforce-issue-limits.py Adds 24h issue/PR rate limiting and expands command matching to PR create/edit.
content-guards/hooks/hooks.json Registers the README validator as a PostToolUse hook for Write/Edit.
content-guards/README.md Documents the new readme-validator and updated issue limiter behavior.
content-guards/.claude-plugin/plugin.json Bumps version to 1.1.0, updates description/keywords, and adds the validate-readme skill.
AGENTS.md Updates plugin quick reference table and adds delegation guidance.
.readme-validator.yaml Adds repo-wide defaults for README validation requirements.
.claude/rules/worktree-conventions.md Adds worktree path/branch/cleanup conventions intended to pair with superpowers:using-git-worktrees.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

- Fix YAML parser bug: flush pending list key when a new key is
  encountered, preventing silent data loss when a list key has no
  items before the next key
- Narrow broad `except Exception` to `except (OSError, ValueError)`
  for more precise error handling in load_config
- Fix SSRF vulnerability in check_badges: add BADGE_ALLOWED_HOSTS
  allowlist of known badge domains, skip all non-allowlisted image
  URLs, and add private/loopback IP check via _is_private_ip()
- Fix urlopen resource leak: use context manager `with urlopen(...)`
  to ensure socket/file descriptors are always closed

(claude)
- Fix rate-limit block message to say "creating or updating" to cover
  gh pr edit operations, not just creation
- Fix docstring to accurately document per-resource-type 24h counters
  instead of implying a combined budget
- Replace nonexistent agentsmd/skills/consolidate-issues/SKILL.md
  reference with actionable remediation steps
- Add bats test suite with 12 tests covering command matching,
  hard limits, rate limits, fail-open, and message content

(claude)
- worktree-conventions.md: add `git switch main` before `git pull`
  and normalize placeholder to `{repo-name}` brace style (threads
  PRRT_kwDOQx7E5c5yVnwA and PRRT_kwDOQx7E5c5yVrVM)
- git-workflows/README.md: remove `/init-worktree` skill listing and
  usage example; update description to point to
  `superpowers:using-git-worktrees` (thread PRRT_kwDOQx7E5c5yVrUP)
- github-workflows/skills/finalize-pr/SKILL.md: update workflow
  diagram to reference `superpowers:using-git-worktrees` instead of
  removed `/init-worktree` (thread PRRT_kwDOQx7E5c5yVrUP)
- content-guards/scripts/validate-markdown.sh: fix cspell running
  from wrong directory causing false "Files checked: 0" failures

(claude)
- validate-readme.py: remove badge checking (~90 lines), simplify YAML
  parser (47 → 20 lines), inline get_section_content into caller
- enforce-issue-limits.py: unify check_recent_issues/check_recent_prs
  into _count_recent(), extract _GH_ERRORS tuple, tighten block messages
- validate-markdown.sh: trim verbose cspell comment block
- enforce-issue-limits.bats: add utc_now() and build_json_array()
  helpers, replace 6 copy-paste for-loops
- AGENTS.md: remove 3 duplicate plugin rows and sections already in
  CLAUDE.md (260 → 25 lines)
- content-guards/README.md: fix test path, add coverage bullets
- validate-readme/SKILL.md: replace bash block with prose, add config
  schema section
- delete .readme-validator.yaml from repo root (project-specific config)

All 20 tests pass.

(claude)
Conflicts resolved:
- AGENTS.md: keep HEAD minimal version (sections duplicated from CLAUDE.md removed)
- content-guards/scripts/validate-markdown.sh: keep short comment, adopt
  --no-must-find-files flag from main (cspell fix)
- git-workflows/skills/init-worktree/SKILL.md: keep deleted (externalized)
- github-workflows/skills/finalize-pr/SKILL.md: take main's diagram (shows
  both invocation modes + multi-PR modes from PR #76)

(claude)
@claude
Copy link
Contributor

claude bot commented Mar 6, 2026

Claude finished @JacobPEvans's task in 3m 10s —— View job


PR #72 Review

  • Gather context
  • Review enforce-issue-limits.py
  • Review validate-readme.py
  • Review hook configuration and tests
  • Post inline comments
  • Final summary

Good PR overall — the validate-readme hook is clean, the test suite follows the established bats pattern well, and badge checking was correctly removed after the SSRF concern. A few real issues found:

Issues flagged inline:

  1. Issue 24h rate limit not scoped to current user (enforce-issue-limits.py:172) — _count_recent("issue") counts all repo issues, not just Claude-created ones. The PR rate limit bug was fixed with --author @me but the issue rate limit has the same problem. Fix this →

  2. gh pr edit rate limit is effectively dead (enforce-issue-limits.py:177) — the counter uses createdAt, so editing a PR created >24h ago never counts. The block message says "creating or updating" but only creation is tracked. Either document this limitation or track edits separately.

  3. Placeholder inconsistency in worktree-conventions.md (.claude/rules/worktree-conventions.md:9) — ## Path Convention block still uses <angle-brackets> but "Before Creating" step 1 was already updated to {braces}. Fix this →

  4. parse_headings only matches h2 (validate-readme.py:99) — ## only. READMEs using # Installation (h1) will be incorrectly flagged as missing the required section, blocking writes unexpectedly.

Also noted: The .readme-validator.yaml example config file was introduced in the initial feature commit (9482c05) but removed in the cleanup commit (c7ce1de). The PR description and validate-readme.py docstring both reference it as a configuration mechanism, but no example is shipped. Worth either restoring a minimal example or removing the references to the config file from the docs.

…it limitation

- Add ["--author", "@me"] to the 24h issue rate-limit call so only
  Claude-created issues count against the limit, consistent with the
  existing PR rate-limit filter.
- Add inline comment documenting that `gh pr edit` on PRs created >24h
  ago does not accumulate against the rate limit because _count_recent
  uses createdAt; tracking edit frequency separately is out of scope.

(claude)
…ormat

Replace all <angle-bracket> placeholders with {brace} style to match
the existing convention used in the Before Creating section.

(claude)
parse_headings and check_install_code_blocks only matched ## (h2),
causing false-positive blocking when READMEs use # or ### for major
sections. Update both regex patterns to #{1,3} to cover h1, h2, h3.

(claude)
@JacobPEvans JacobPEvans merged commit 97bfa05 into main Mar 6, 2026
28 of 40 checks passed
@JacobPEvans JacobPEvans deleted the feat/externalize-and-rate-limit branch March 6, 2026 22:35
This was referenced Mar 6, 2026
This was referenced Mar 6, 2026
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.

2 participants