Skip to content

feat(hooks): add stale branch naming hooks#24

Open
404-Page-Found wants to merge 13 commits into
mainfrom
fix/4-add-pre-commit-hook-integration-to-prevent-stale-branch-creation
Open

feat(hooks): add stale branch naming hooks#24
404-Page-Found wants to merge 13 commits into
mainfrom
fix/4-add-pre-commit-hook-integration-to-prevent-stale-branch-creation

Conversation

@404-Page-Found

@404-Page-Found 404-Page-Found commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds Git hook integration that warns when branch names are likely to become stale.

Changes

  • Add git-broom hook install (also available as hooks)
  • Install post-checkout, pre-commit, and pre-push checks
  • Add configurable branch naming rules, ticket patterns, prefixes, and ignored branches
  • Preserve existing hooks with .git-broom-backup files
  • Support --force, GIT_BROOM_FORCE=1, and Git's --no-verify bypass
  • Add tests and documentation

Testing

  • npm run typecheck
  • npm test -- --run (37 tests)
  • npm run build

Note: npm run lint is currently unavailable because the repository has no ESLint flat configuration.

Related

Closes #4

Summary by CodeRabbit

  • New Features
    • Added git-broom hooks install and git-broom hooks check to install and validate supported Git hooks.
    • Introduced configurable branch naming rules with warnings enabled by default for non-protected branches (including ticket/prefix checks and ignore patterns).
  • Documentation
    • Updated README with branchNaming examples, bypass behavior (--no-verify, forced checks), and hook backup/preservation details.
  • Improvements
    • Improved resolution of global options for nested CLI subcommands.
  • Tests
    • Added coverage for config defaults/parsing, branch naming warnings, hook installation/idempotency/backups, and CLI wiring.

Install post-checkout, pre-commit, and pre-push checks with configurable naming rules and safe bypasses.

Closes #4
@coderabbitai

coderabbitai Bot commented Jul 11, 2026

Copy link
Copy Markdown

Review Change Stack

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 4079b583-ba49-4d89-92be-1c90055335e7

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds configurable branch naming rules, Git hook installation and checking, CLI commands, hook backup handling, tests, and README documentation.

Changes

Branch Naming Hooks

Layer / File(s) Summary
Branch naming configuration
src/types/index.ts, src/core/config.ts, src/core/config.test.ts
Adds typed and validated branchNaming settings with defaults for ticket requirements, prefixes, ticket patterns, and ignore patterns.
Hook validation and installation
src/core/hooks.ts, src/core/git.ts, src/core/hooks.test.ts
Validates branch names, installs managed post-checkout, pre-commit, and pre-push hooks, preserves existing hooks through backups, and tests these behaviors.
Hooks CLI commands and documentation
src/commands/hooks.ts, src/index.ts, src/index.test.ts, README.md
Adds hooks install and hooks check, including repository validation, global option handling, force bypasses, JSON output, CLI tests, and usage documentation.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant GitHook
  participant hooksCheckCommand
  participant getBranchNamingWarnings
  participant logger
  GitHook->>hooksCheckCommand: pass hook name and hook arguments
  hooksCheckCommand->>getBranchNamingWarnings: validate current branch
  getBranchNamingWarnings-->>hooksCheckCommand: return warnings
  hooksCheckCommand->>logger: emit warnings or JSON result
Loading

Poem

I’m a rabbit with hooks in a neat little row,
Checking branch names wherever they go.
Tickets and prefixes hop into place,
Old hooks get tucked in a backup space.
With --force, I bounce free through the gate!

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning Most requirements are met, but pre-push stale-branch warnings are not implemented as required in #4. Add pre-push branch-naming warning logic so pushes trigger stale-branch checks, not just hook installation.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: adding branch-naming hook support.
Out of Scope Changes check ✅ Passed All changes appear to support the hook integration, config, docs, and tests; no unrelated scope is evident.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@404-Page-Found

Copy link
Copy Markdown
Contributor Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Jul 11, 2026

Copy link
Copy Markdown
✅ Action performed

Full review finished.

@coderabbitai coderabbitai 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.

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@README.md`:
- Around line 124-136: Add brief documentation immediately after the
branchNaming JSON example explaining requireTicket, requirePrefix,
ticketPattern, allowedPrefixes, and ignorePatterns. Use a concise table or
bullet list, describing each field’s purpose and expected value so users can
configure branch naming without consulting source code.

In `@src/core/config.ts`:
- Around line 60-66: Centralize the branch-naming defaults by defining and
exporting the shared default object from config.ts, then have
defaultConfig.branchNaming reuse it. Remove the duplicate DEFAULT_BRANCH_NAMING
values in hooks.ts and import the exported config default there, preserving the
existing requireTicket, requirePrefix, ticketPattern, allowedPrefixes, and
ignorePatterns values.

In `@src/core/hooks.ts`:
- Around line 52-55: Update globToRegex so the ? glob wildcard is escaped during
regex construction and then converted to . alongside the existing * to .*
conversion. Preserve literal regex-character escaping and all existing *
behavior.
- Around line 107-123: Update renderHookScript so the generated hook treats
git-broom invocation failures as non-blocking: detect when git-broom is
unavailable or its hooks check command fails, emit a warning, and exit
successfully with status 0. Preserve the existing backup-hook execution and
GIT_BROOM_FORCE command selection, while ensuring the hook still propagates
backup-hook failures.

In `@src/index.test.ts`:
- Around line 133-157: Add a focused test alongside “wires nested hook checks to
the repository and hook arguments” that invokes the nested hooks install CLI
command and asserts commandMocks.hooksInstallCommand receives the expected
parsed options and repository path, matching the existing hooks check wiring
coverage.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: d780882f-6d61-4d9e-9d5c-0d63de39445e

📥 Commits

Reviewing files that changed from the base of the PR and between 2d269ff and b16e79b.

📒 Files selected for processing (10)
  • README.md
  • src/commands/hooks.ts
  • src/core/config.test.ts
  • src/core/config.ts
  • src/core/git.ts
  • src/core/hooks.test.ts
  • src/core/hooks.ts
  • src/index.test.ts
  • src/index.ts
  • src/types/index.ts
📜 Review details
🧰 Additional context used
📓 Path-based instructions (9)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use TypeScript with Node.js >=24 and ESM-only modules.

Files:

  • src/index.test.ts
  • src/core/config.test.ts
  • src/core/hooks.test.ts
  • src/core/git.ts
  • src/core/config.ts
  • src/index.ts
  • src/commands/hooks.ts
  • src/types/index.ts
  • src/core/hooks.ts
src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use cross-platform path handling and avoid shell-specific assumptions because the repository must work on Windows.

Files:

  • src/index.test.ts
  • src/core/config.test.ts
  • src/core/hooks.test.ts
  • src/core/git.ts
  • src/core/config.ts
  • src/index.ts
  • src/commands/hooks.ts
  • src/types/index.ts
  • src/core/hooks.ts
src/**/*.{test,spec}.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Add focused automated coverage for configuration resolution, safety filters, and command behavior when touching those areas.

Files:

  • src/index.test.ts
  • src/core/config.test.ts
  • src/core/hooks.test.ts
src/core/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Favor small, composable helpers in core/ for logic that may need direct tests.

Files:

  • src/core/config.test.ts
  • src/core/hooks.test.ts
  • src/core/git.ts
  • src/core/config.ts
  • src/core/hooks.ts
src/core/config.test.ts

📄 CodeRabbit inference engine (AGENTS.md)

Maintain focused automated coverage for configuration resolution when changing configuration behavior.

Files:

  • src/core/config.test.ts
src/core/git.ts

📄 CodeRabbit inference engine (AGENTS.md)

src/core/git.ts: Centralize Git command execution and repository inspection helpers in src/core/git.ts; avoid scattering raw execa('git', ...) calls.
Measure .git size using the established cross-platform dirSize() implementation; do not use Unix-only utilities such as du.

Files:

  • src/core/git.ts
src/core/config.ts

📄 CodeRabbit inference engine (AGENTS.md)

src/core/config.ts: Load .gitbroomrc by walking upward from the target repository path; parse it as JSON, ignore invalid files with a warning, and merge CLI overrides over file config over built-in defaults.
Keep configuration parsing tolerant enough that invalid user configuration does not break read-only inspection commands.

Files:

  • src/core/config.ts
src/index.ts

📄 CodeRabbit inference engine (AGENTS.md)

When changing command options, update the Commander wiring in src/index.ts.

Files:

  • src/index.ts
src/types/index.ts

📄 CodeRabbit inference engine (AGENTS.md)

Extend shared types in src/types/index.ts when command or core contracts change.

Files:

  • src/types/index.ts
🪛 ast-grep (0.44.1)
src/core/config.ts

[warning] 19-19: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(value)
Note: [CWE-1333] Inefficient Regular Expression Complexity

(regexp-from-variable)


[warning] 19-19: Do not use variable for regular expressions
Context: new RegExp(value)
Note: [CWE-1333] Inefficient Regular Expression Complexity. Security best practice.

(regexp-non-literal-typescript)

src/core/hooks.ts

[warning] 81-81: Do not use variable for regular expressions
Context: new RegExp(rules.ticketPattern)
Note: [CWE-1333] Inefficient Regular Expression Complexity. Security best practice.

(regexp-non-literal-typescript)


[warning] 53-53: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(^${escaped.replace(/\*/g, ".*")}$)
Note: [CWE-1333] Inefficient Regular Expression Complexity

(regexp-from-variable)


[warning] 81-81: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(rules.ticketPattern)
Note: [CWE-1333] Inefficient Regular Expression Complexity

(regexp-from-variable)

🔇 Additional comments (10)
src/types/index.ts (1)

52-59: LGTM!

Also applies to: 69-69

src/core/config.ts (1)

12-38: LGTM!

Also applies to: 48-48

src/core/config.test.ts (1)

91-115: LGTM!

src/core/git.ts (1)

3-3: LGTM!

Also applies to: 20-24

src/core/hooks.ts (1)

36-50: LGTM!

Also applies to: 65-105, 125-158

src/core/hooks.test.ts (1)

1-113: LGTM!

src/index.ts (2)

27-29: getParentCommand traversal is correct for nested commands.

Walking to the topmost parent is necessary because hooks check is two levels deep (program → hooks → check). The old one-level traversal would return hooks instead of program, breaking global option resolution. This change is backward compatible for existing one-level commands.


165-201: Hooks command wiring looks correct.

The install subcommand correctly skips config resolution (not needed for installation), and check properly resolves config with global overrides including JSON. The variadic [hookArgs...] argument and --hook/--force options are correctly passed through to hooksCheckCommand.

src/index.test.ts (1)

16-17: Mock setup for hooks commands is correct.

The hoisted mocks and vi.mock block correctly wire hooksInstallCommand and hooksCheckCommand to the command mocks.

Also applies to: 26-29

src/commands/hooks.ts (1)

36-44: 🩺 Stability & Availability

GIT_BROOM_FORCE bypass is already wired through renderHookScript passes --force when GIT_BROOM_FORCE=1, so hooksCheckCommand receives the bypass via options.force.

			> Likely an incorrect or invalid review comment.

Comment thread README.md
Comment thread src/core/config.ts Outdated
Comment thread src/core/hooks.ts Outdated
Comment thread src/core/hooks.ts
Comment thread src/index.test.ts
Centralize branch naming defaults, support question-mark globs, and let unavailable or failing hook checks warn without blocking Git operations. Document the configuration fields and cover nested hook installation wiring.
@404-Page-Found

Copy link
Copy Markdown
Contributor Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Jul 11, 2026

Copy link
Copy Markdown
✅ Action performed

Full review finished.

@coderabbitai

coderabbitai Bot commented Jul 11, 2026

Copy link
Copy Markdown
✅ Action performed

Full review finished.


Your plan includes PR reviews subject to rate limits. More reviews will be available in 59 minutes.

@coderabbitai coderabbitai 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.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/core/config.ts`:
- Line 48: Ensure resolved configurations do not share the mutable
DEFAULT_BRANCH_NAMING object: update the branchNaming default in configSchema
and the corresponding defaultConfig value to create an independent deep-cloned
instance for each resolution, using a factory or established cloning utility
while preserving the existing default contents.
- Around line 20-37: The current validation in branchNamingSchema only checks
whether ticketPattern compiles; no code change is required for the noted ReDoS
risk under the local-config threat model. If broader deployment requires defense
in depth, add a regex-complexity validation to ticketPattern before it is
consumed by the hooks logic, while preserving the existing compilation check and
downstream matching behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 2cbc356f-1218-4dcc-b958-c427c733b881

📥 Commits

Reviewing files that changed from the base of the PR and between 2d269ff and 41b8631.

📒 Files selected for processing (10)
  • README.md
  • src/commands/hooks.ts
  • src/core/config.test.ts
  • src/core/config.ts
  • src/core/git.ts
  • src/core/hooks.test.ts
  • src/core/hooks.ts
  • src/index.test.ts
  • src/index.ts
  • src/types/index.ts
📜 Review details
🧰 Additional context used
📓 Path-based instructions (9)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use TypeScript with Node.js >=24 and ESM-only modules.

Files:

  • src/core/config.test.ts
  • src/types/index.ts
  • src/core/git.ts
  • src/index.test.ts
  • src/core/hooks.ts
  • src/core/config.ts
  • src/core/hooks.test.ts
  • src/commands/hooks.ts
  • src/index.ts
src/core/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Favor small, composable helpers in core/ for logic that may need direct tests.

Files:

  • src/core/config.test.ts
  • src/core/git.ts
  • src/core/hooks.ts
  • src/core/config.ts
  • src/core/hooks.test.ts
src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use cross-platform path handling and avoid shell-specific assumptions because the repository must work on Windows.

Files:

  • src/core/config.test.ts
  • src/types/index.ts
  • src/core/git.ts
  • src/index.test.ts
  • src/core/hooks.ts
  • src/core/config.ts
  • src/core/hooks.test.ts
  • src/commands/hooks.ts
  • src/index.ts
src/core/config.test.ts

📄 CodeRabbit inference engine (AGENTS.md)

Maintain focused automated coverage for configuration resolution when changing configuration behavior.

Files:

  • src/core/config.test.ts
src/**/*.{test,spec}.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Add focused automated coverage for configuration resolution, safety filters, and command behavior when touching those areas.

Files:

  • src/core/config.test.ts
  • src/index.test.ts
  • src/core/hooks.test.ts
src/types/index.ts

📄 CodeRabbit inference engine (AGENTS.md)

Extend shared types in src/types/index.ts when command or core contracts change.

Files:

  • src/types/index.ts
src/core/git.ts

📄 CodeRabbit inference engine (AGENTS.md)

src/core/git.ts: Centralize Git command execution and repository inspection helpers in src/core/git.ts; avoid scattering raw execa('git', ...) calls.
Measure .git size using the established cross-platform dirSize() implementation; do not use Unix-only utilities such as du.

Files:

  • src/core/git.ts
src/core/config.ts

📄 CodeRabbit inference engine (AGENTS.md)

src/core/config.ts: Load .gitbroomrc by walking upward from the target repository path; parse it as JSON, ignore invalid files with a warning, and merge CLI overrides over file config over built-in defaults.
Keep configuration parsing tolerant enough that invalid user configuration does not break read-only inspection commands.

Files:

  • src/core/config.ts
src/index.ts

📄 CodeRabbit inference engine (AGENTS.md)

When changing command options, update the Commander wiring in src/index.ts.

Files:

  • src/index.ts
🪛 ast-grep (0.44.1)
src/core/hooks.ts

[warning] 66-66: Do not use variable for regular expressions
Context: new RegExp(rules.ticketPattern)
Note: [CWE-1333] Inefficient Regular Expression Complexity. Security best practice.

(regexp-non-literal-typescript)


[warning] 38-38: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(^${escaped.replace(/\*/g, ".*").replace(/\\\?/g, ".")}$)
Note: [CWE-1333] Inefficient Regular Expression Complexity

(regexp-from-variable)


[warning] 66-66: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(rules.ticketPattern)
Note: [CWE-1333] Inefficient Regular Expression Complexity

(regexp-from-variable)

src/core/config.ts

[warning] 27-27: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(value)
Note: [CWE-1333] Inefficient Regular Expression Complexity

(regexp-from-variable)


[warning] 27-27: Do not use variable for regular expressions
Context: new RegExp(value)
Note: [CWE-1333] Inefficient Regular Expression Complexity. Security best practice.

(regexp-non-literal-typescript)

🔇 Additional comments (16)
src/types/index.ts (1)

52-58: LGTM!

Also applies to: 69-69

src/core/config.ts (1)

5-13: LGTM! The centralization of DEFAULT_BRANCH_NAMING here and the Zod schema validation (including the RegExp compile check and inner defaults) are well done. The past review comment about duplicating defaults between config.ts and hooks.ts has been addressed.

Also applies to: 20-37

src/core/config.test.ts (1)

91-114: LGTM! Good focused test verifying that partial branchNaming config correctly fills in defaults via the Zod schema.

README.md (2)

13-13: LGTM! The documentation clearly explains the branch naming hooks feature, configuration fields, installation, and bypass options. The field table addresses the prior review feedback about documenting branchNaming fields.

Also applies to: 34-34, 124-153


152-152: 🎯 Functional Correctness

No change needed: GIT_BROOM_FORCE=1 is already handled in the installed hook wrapper.

			> Likely an incorrect or invalid review comment.
src/core/git.ts (1)

3-3: LGTM!

Also applies to: 20-24

src/core/hooks.ts (4)

37-40: LGTM! Past review concern about ? glob wildcard handling has been addressed — ? is now escaped in the character class and converted to . via the second replace.


50-76: LGTM! getBranchNamingReasons and getBranchNamingWarnings correctly handle prefix/ticket validation, protected branch filtering, and ignore patterns.

Also applies to: 78-90


92-113: LGTM! Past review concern about blocking git operations has been addressed — the script now captures the git-broom exit status and exits 0 with a warning on failure, while still propagating backup hook failures.


115-144: LGTM! installHooks correctly handles fresh installs, re-install detection via HOOK_MARKER, and backup preservation. isHookName is a clean type guard.

Also applies to: 146-148

src/core/hooks.test.ts (1)

1-113: LGTM! Tests cover branch naming warning generation, valid branch acceptance, protected/ignored branch filtering, and hook installation with backup preservation.

src/commands/hooks.ts (1)

1-60: LGTM! hooksInstallCommand is a clean wrapper, and hooksCheckCommand correctly handles hook normalization, branch checkout detection, force bypass, and JSON output.

src/index.ts (2)

11-11: LGTM! getParentCommand correctly traverses to the topmost parent, enabling global option resolution for nested subcommands.

Also applies to: 27-29


165-201: LGTM! The hooks command group with install and check subcommands is correctly wired — install passes the repo path, check passes config with hook/force/hookArgs options.

src/index.test.ts (2)

16-17: LGTM! Mock setup for both hook commands is consistent with the existing pattern.

Also applies to: 26-29


133-166: LGTM! Past review concern about missing hooks install CLI wiring test has been addressed. Both hooks check and hooks install wiring are now covered.

Comment thread src/core/config.ts
Comment thread src/core/config.ts Outdated
Create fresh deep-cloned branch naming defaults for each config resolution and cover the isolation behavior with a regression test.
@404-Page-Found

Copy link
Copy Markdown
Contributor Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Jul 11, 2026

Copy link
Copy Markdown
✅ Action performed

Full review finished.


Your plan includes PR reviews subject to rate limits. More reviews will be available in 26 minutes.

@404-Page-Found

Copy link
Copy Markdown
Contributor Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Jul 12, 2026

Copy link
Copy Markdown
✅ Action performed

Full review finished.

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/core/hooks.test.ts`:
- Around line 67-78: Add focused coverage in the existing “does not warn for
protected or ignored branches” test for the `?` wildcard handled by
`globToRegex`: configure `ignorePatterns` with `release/?` and assert that a
matching branch such as `release/1` produces no warnings, while preserving the
existing protected-branch and `*`-pattern assertions.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 3a44a449-be9c-40d3-a462-f235d3569d66

📥 Commits

Reviewing files that changed from the base of the PR and between 2d269ff and f834459.

📒 Files selected for processing (10)
  • README.md
  • src/commands/hooks.ts
  • src/core/config.test.ts
  • src/core/config.ts
  • src/core/git.ts
  • src/core/hooks.test.ts
  • src/core/hooks.ts
  • src/index.test.ts
  • src/index.ts
  • src/types/index.ts
📜 Review details
🧰 Additional context used
📓 Path-based instructions (9)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use TypeScript with Node.js >=24 and ESM-only modules.

Files:

  • src/core/config.test.ts
  • src/core/git.ts
  • src/index.test.ts
  • src/types/index.ts
  • src/core/config.ts
  • src/core/hooks.test.ts
  • src/commands/hooks.ts
  • src/index.ts
  • src/core/hooks.ts
src/core/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Favor small, composable helpers in core/ for logic that may need direct tests.

Files:

  • src/core/config.test.ts
  • src/core/git.ts
  • src/core/config.ts
  • src/core/hooks.test.ts
  • src/core/hooks.ts
src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use cross-platform path handling and avoid shell-specific assumptions because the repository must work on Windows.

Files:

  • src/core/config.test.ts
  • src/core/git.ts
  • src/index.test.ts
  • src/types/index.ts
  • src/core/config.ts
  • src/core/hooks.test.ts
  • src/commands/hooks.ts
  • src/index.ts
  • src/core/hooks.ts
src/core/config.test.ts

📄 CodeRabbit inference engine (AGENTS.md)

Maintain focused automated coverage for configuration resolution when changing configuration behavior.

Files:

  • src/core/config.test.ts
src/**/*.{test,spec}.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Add focused automated coverage for configuration resolution, safety filters, and command behavior when touching those areas.

Files:

  • src/core/config.test.ts
  • src/index.test.ts
  • src/core/hooks.test.ts
src/core/git.ts

📄 CodeRabbit inference engine (AGENTS.md)

src/core/git.ts: Centralize Git command execution and repository inspection helpers in src/core/git.ts; avoid scattering raw execa('git', ...) calls.
Measure .git size using the established cross-platform dirSize() implementation; do not use Unix-only utilities such as du.

Files:

  • src/core/git.ts
src/types/index.ts

📄 CodeRabbit inference engine (AGENTS.md)

Extend shared types in src/types/index.ts when command or core contracts change.

Files:

  • src/types/index.ts
src/core/config.ts

📄 CodeRabbit inference engine (AGENTS.md)

src/core/config.ts: Load .gitbroomrc by walking upward from the target repository path; parse it as JSON, ignore invalid files with a warning, and merge CLI overrides over file config over built-in defaults.
Keep configuration parsing tolerant enough that invalid user configuration does not break read-only inspection commands.

Files:

  • src/core/config.ts
src/index.ts

📄 CodeRabbit inference engine (AGENTS.md)

When changing command options, update the Commander wiring in src/index.ts.

Files:

  • src/index.ts
🪛 ast-grep (0.44.1)
src/core/config.ts

[warning] 31-31: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(value)
Note: [CWE-1333] Inefficient Regular Expression Complexity

(regexp-from-variable)


[warning] 31-31: Do not use variable for regular expressions
Context: new RegExp(value)
Note: [CWE-1333] Inefficient Regular Expression Complexity. Security best practice.

(regexp-non-literal-typescript)

src/core/hooks.ts

[warning] 38-38: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(^${escaped.replace(/\*/g, ".*").replace(/\\\?/g, ".")}$)
Note: [CWE-1333] Inefficient Regular Expression Complexity

(regexp-from-variable)


[warning] 66-66: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(rules.ticketPattern)
Note: [CWE-1333] Inefficient Regular Expression Complexity

(regexp-from-variable)


[warning] 66-66: Do not use variable for regular expressions
Context: new RegExp(rules.ticketPattern)
Note: [CWE-1333] Inefficient Regular Expression Complexity. Security best practice.

(regexp-non-literal-typescript)

🔇 Additional comments (13)
src/types/index.ts (1)

52-59: LGTM!

Also applies to: 69-69

src/core/config.ts (1)

5-17: LGTM! Past review concerns about shared mutable state and ReDoS have been addressed via structuredClone and the local-config threat model.

Also applies to: 24-41, 52-66, 106-106

src/core/config.test.ts (1)

61-77: LGTM!

Also applies to: 108-132

src/core/git.ts (1)

3-3: LGTM!

Also applies to: 20-24

src/core/hooks.ts (3)

37-40: LGTM! The ? glob wildcard handling has been addressed — ? is escaped in the first pass then converted to . in the second pass.


92-113: LGTM! The hook script now gracefully handles git-broom unavailability by printing a warning and exiting 0, aligning with the PR's "warn, not block" objective.


50-90: LGTM!

Also applies to: 115-148

src/core/hooks.test.ts (1)

47-65: LGTM!

Also applies to: 80-113

src/commands/hooks.ts (2)

12-22: LGTM!


24-60: 🎯 Functional Correctness

No change needed The generated hook wrappers already pass --force when GIT_BROOM_FORCE=1, so hooksCheckCommand does not need to read the env var directly.

			> Likely an incorrect or invalid review comment.
src/index.ts (1)

27-29: LGTM!

Also applies to: 165-201

src/index.test.ts (1)

16-29: LGTM!

Also applies to: 134-166

README.md (1)

13-13: LGTM!

Also applies to: 34-34, 124-153

Comment thread src/core/hooks.test.ts Outdated
@404-Page-Found

Copy link
Copy Markdown
Contributor Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Jul 12, 2026

Copy link
Copy Markdown
✅ Action performed

Full review finished.

@coderabbitai coderabbitai 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.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/commands/hooks.ts`:
- Around line 24-59: Add focused tests for hooksCheckCommand covering
post-checkout file mode ("0"), branch mode ("1"), force bypass, warning
emission, and JSON output. Mock getCurrentBranch and logger interactions, and
assert each decision’s returned HookCheckResult plus the expected warning or
JSON behavior; retain existing forwarding coverage in src/index.test.ts.

In `@src/core/hooks.ts`:
- Around line 37-39: Replace the regex-based implementation of globToRegex with
a linear-time glob matcher for ignorePatterns, avoiding conversion of wildcard
stars into .* and RegExp compilation. Preserve the existing glob semantics for *
and ? and the anchored full-pattern match behavior, using the already validated
ticketPattern input.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 4a70f059-eb0b-47d9-87ef-d0986b248716

📥 Commits

Reviewing files that changed from the base of the PR and between 2d269ff and 060a470.

📒 Files selected for processing (10)
  • README.md
  • src/commands/hooks.ts
  • src/core/config.test.ts
  • src/core/config.ts
  • src/core/git.ts
  • src/core/hooks.test.ts
  • src/core/hooks.ts
  • src/index.test.ts
  • src/index.ts
  • src/types/index.ts
📜 Review details
🧰 Additional context used
📓 Path-based instructions (9)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use TypeScript with Node.js >=24 and ESM-only modules.

Files:

  • src/core/git.ts
  • src/core/config.test.ts
  • src/types/index.ts
  • src/core/config.ts
  • src/index.test.ts
  • src/core/hooks.test.ts
  • src/commands/hooks.ts
  • src/index.ts
  • src/core/hooks.ts
src/core/git.ts

📄 CodeRabbit inference engine (AGENTS.md)

src/core/git.ts: Centralize Git command execution and repository inspection helpers in src/core/git.ts; avoid scattering raw execa('git', ...) calls.
Measure .git size using the established cross-platform dirSize() implementation; do not use Unix-only utilities such as du.

Files:

  • src/core/git.ts
src/core/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Favor small, composable helpers in core/ for logic that may need direct tests.

Files:

  • src/core/git.ts
  • src/core/config.test.ts
  • src/core/config.ts
  • src/core/hooks.test.ts
  • src/core/hooks.ts
src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use cross-platform path handling and avoid shell-specific assumptions because the repository must work on Windows.

Files:

  • src/core/git.ts
  • src/core/config.test.ts
  • src/types/index.ts
  • src/core/config.ts
  • src/index.test.ts
  • src/core/hooks.test.ts
  • src/commands/hooks.ts
  • src/index.ts
  • src/core/hooks.ts
src/core/config.test.ts

📄 CodeRabbit inference engine (AGENTS.md)

Maintain focused automated coverage for configuration resolution when changing configuration behavior.

Files:

  • src/core/config.test.ts
src/**/*.{test,spec}.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Add focused automated coverage for configuration resolution, safety filters, and command behavior when touching those areas.

Files:

  • src/core/config.test.ts
  • src/index.test.ts
  • src/core/hooks.test.ts
src/types/index.ts

📄 CodeRabbit inference engine (AGENTS.md)

Extend shared types in src/types/index.ts when command or core contracts change.

Files:

  • src/types/index.ts
src/core/config.ts

📄 CodeRabbit inference engine (AGENTS.md)

src/core/config.ts: Load .gitbroomrc by walking upward from the target repository path; parse it as JSON, ignore invalid files with a warning, and merge CLI overrides over file config over built-in defaults.
Keep configuration parsing tolerant enough that invalid user configuration does not break read-only inspection commands.

Files:

  • src/core/config.ts
src/index.ts

📄 CodeRabbit inference engine (AGENTS.md)

When changing command options, update the Commander wiring in src/index.ts.

Files:

  • src/index.ts
🪛 ast-grep (0.44.1)
src/core/config.ts

[warning] 31-31: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(value)
Note: [CWE-1333] Inefficient Regular Expression Complexity

(regexp-from-variable)


[warning] 31-31: Do not use variable for regular expressions
Context: new RegExp(value)
Note: [CWE-1333] Inefficient Regular Expression Complexity. Security best practice.

(regexp-non-literal-typescript)

src/core/hooks.ts

[warning] 38-38: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(^${escaped.replace(/\*/g, ".*").replace(/\\\?/g, ".")}$)
Note: [CWE-1333] Inefficient Regular Expression Complexity

(regexp-from-variable)


[warning] 66-66: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(rules.ticketPattern)
Note: [CWE-1333] Inefficient Regular Expression Complexity

(regexp-from-variable)


[warning] 66-66: Do not use variable for regular expressions
Context: new RegExp(rules.ticketPattern)
Note: [CWE-1333] Inefficient Regular Expression Complexity. Security best practice.

(regexp-non-literal-typescript)

🔇 Additional comments (17)
src/types/index.ts (1)

52-59: LGTM!

Also applies to: 69-69

src/core/config.ts (1)

5-42: LGTM!

Also applies to: 52-66, 106-106

src/core/config.test.ts (1)

61-77: LGTM!

Also applies to: 108-132

README.md (2)

13-13: LGTM!

Also applies to: 34-34


124-153: ignorePatterns already supports * and ?. matchesPattern uses globToRegex, which expands * to .* and ? to ., so the README matches the implementation.

			> Likely an incorrect or invalid review comment.
src/core/hooks.test.ts (3)

67-87: Assert that ? rejects multiple characters.

release/1 covers only the positive case. Also assert that release/12 is not ignored, so a regression from . to .* is detected.

As per coding guidelines, “Add focused automated coverage for configuration resolution, safety filters, and command behavior when touching those areas.”

Source: Coding guidelines


1-65: LGTM!


89-121: LGTM!

src/core/git.ts (1)

3-3: LGTM!

Also applies to: 20-23

src/core/hooks.ts (5)

1-35: LGTM!


42-48: LGTM!

Also applies to: 50-63, 75-90


92-113: LGTM!


119-148: LGTM!


115-117: 🎯 Functional Correctness

No hook-path change needed.
getGitPath("hooks") already follows core.hooksPath (relative and absolute), so installHooks is writing to the effective hook directory.

			> Likely an incorrect or invalid review comment.
src/commands/hooks.ts (1)

12-22: LGTM!

src/index.ts (1)

11-11: LGTM!

Also applies to: 27-29, 165-200

src/index.test.ts (1)

16-29: LGTM!

Also applies to: 134-166

Comment thread src/commands/hooks.ts
Comment on lines +24 to +59
export async function hooksCheckCommand(
config: BroomConfig,
options: { hook: string; force?: boolean; hookArgs?: string[] },
cwd?: string,
): Promise<HookCheckResult> {
const hook: HookName = isHookName(options.hook) ? options.hook : "pre-commit";
const branch = await getCurrentBranch(cwd);
const isBranchCheckout =
hook !== "post-checkout" ||
!options.hookArgs ||
options.hookArgs.length === 0 ||
options.hookArgs.at(-1) === "1";
const warnings =
options.force || !isBranchCheckout
? []
: getBranchNamingWarnings(branch, config);
const result: HookCheckResult = {
hook,
branch,
warnings,
bypassed: Boolean(options.force),
};

if (config.json) {
logger.json(result);
return result;
}

for (const warning of warnings) {
logger.warn(
`Branch "${warning.branch}" may become stale: ${warning.reasons.join("; ")}. ` +
"Use --force or Git --no-verify to bypass this warning.",
);
}

return result;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Add direct coverage for hook-check decisions.

src/index.test.ts verifies forwarding only; it does not exercise post-checkout file mode (0), branch mode (1), force bypass, or emitted warning/JSON behavior. Add focused handler tests with mocked branch lookup and logger.

As per coding guidelines, “Add focused automated coverage for configuration resolution, safety filters, and command behavior when touching those areas.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/commands/hooks.ts` around lines 24 - 59, Add focused tests for
hooksCheckCommand covering post-checkout file mode ("0"), branch mode ("1"),
force bypass, warning emission, and JSON output. Mock getCurrentBranch and
logger interactions, and assert each decision’s returned HookCheckResult plus
the expected warning or JSON behavior; retain existing forwarding coverage in
src/index.test.ts.

Source: Coding guidelines

Comment thread src/core/hooks.ts Outdated
Add focused hooks check coverage for checkout modes, bypassing, warnings, and JSON output.
@404-Page-Found

Copy link
Copy Markdown
Contributor Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Jul 12, 2026

Copy link
Copy Markdown
✅ Action performed

Full review finished.

@coderabbitai coderabbitai 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.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/core/config.test.ts`:
- Around line 108-132: Add a test alongside “parses configurable branch naming
rules” that writes a non-compilable ticketPattern to .gitbroomrc, calls
resolveConfig, and asserts the configuration falls back to the default
branch-naming settings rather than retaining the invalid value.

In `@src/core/git.ts`:
- Around line 20-24: Add direct unit coverage for getGitPath, mocking git to
return both an absolute path and a relative path. Verify absolute results are
returned unchanged and relative results are resolved against the supplied cwd,
covering both branches of the normalization logic.

In `@src/core/hooks.ts`:
- Around line 63-89: The ticket validation in getBranchNamingReasons must not
execute arbitrary ticketPattern regexes that can catastrophically backtrack.
Replace the new RegExp(...).test(branch) path with a linear-time matcher, or
validate and restrict ticketPattern to a safe supported pattern shape before
matching, while preserving the existing missing-ticket reason and
invalid-pattern handling.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: a6d21957-8962-45d8-aade-01dc349dced7

📥 Commits

Reviewing files that changed from the base of the PR and between 2d269ff and 767ac7a.

📒 Files selected for processing (11)
  • README.md
  • src/commands/hooks.test.ts
  • src/commands/hooks.ts
  • src/core/config.test.ts
  • src/core/config.ts
  • src/core/git.ts
  • src/core/hooks.test.ts
  • src/core/hooks.ts
  • src/index.test.ts
  • src/index.ts
  • src/types/index.ts
📜 Review details
🧰 Additional context used
📓 Path-based instructions (9)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use TypeScript with Node.js >=24 and ESM-only modules.

Files:

  • src/index.test.ts
  • src/core/git.ts
  • src/commands/hooks.test.ts
  • src/core/config.test.ts
  • src/index.ts
  • src/core/config.ts
  • src/commands/hooks.ts
  • src/types/index.ts
  • src/core/hooks.test.ts
  • src/core/hooks.ts
src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use cross-platform path handling and avoid shell-specific assumptions because the repository must work on Windows.

Files:

  • src/index.test.ts
  • src/core/git.ts
  • src/commands/hooks.test.ts
  • src/core/config.test.ts
  • src/index.ts
  • src/core/config.ts
  • src/commands/hooks.ts
  • src/types/index.ts
  • src/core/hooks.test.ts
  • src/core/hooks.ts
src/**/*.{test,spec}.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Add focused automated coverage for configuration resolution, safety filters, and command behavior when touching those areas.

Files:

  • src/index.test.ts
  • src/commands/hooks.test.ts
  • src/core/config.test.ts
  • src/core/hooks.test.ts
src/core/git.ts

📄 CodeRabbit inference engine (AGENTS.md)

src/core/git.ts: Centralize Git command execution and repository inspection helpers in src/core/git.ts; avoid scattering raw execa('git', ...) calls.
Measure .git size using the established cross-platform dirSize() implementation; do not use Unix-only utilities such as du.

Files:

  • src/core/git.ts
src/core/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Favor small, composable helpers in core/ for logic that may need direct tests.

Files:

  • src/core/git.ts
  • src/core/config.test.ts
  • src/core/config.ts
  • src/core/hooks.test.ts
  • src/core/hooks.ts
src/core/config.test.ts

📄 CodeRabbit inference engine (AGENTS.md)

Maintain focused automated coverage for configuration resolution when changing configuration behavior.

Files:

  • src/core/config.test.ts
src/index.ts

📄 CodeRabbit inference engine (AGENTS.md)

When changing command options, update the Commander wiring in src/index.ts.

Files:

  • src/index.ts
src/core/config.ts

📄 CodeRabbit inference engine (AGENTS.md)

src/core/config.ts: Load .gitbroomrc by walking upward from the target repository path; parse it as JSON, ignore invalid files with a warning, and merge CLI overrides over file config over built-in defaults.
Keep configuration parsing tolerant enough that invalid user configuration does not break read-only inspection commands.

Files:

  • src/core/config.ts
src/types/index.ts

📄 CodeRabbit inference engine (AGENTS.md)

Extend shared types in src/types/index.ts when command or core contracts change.

Files:

  • src/types/index.ts
🪛 ast-grep (0.44.1)
src/core/config.ts

[warning] 31-31: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(value)
Note: [CWE-1333] Inefficient Regular Expression Complexity

(regexp-from-variable)


[warning] 31-31: Do not use variable for regular expressions
Context: new RegExp(value)
Note: [CWE-1333] Inefficient Regular Expression Complexity. Security best practice.

(regexp-non-literal-typescript)

src/core/hooks.ts

[warning] 79-79: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(rules.ticketPattern)
Note: [CWE-1333] Inefficient Regular Expression Complexity

(regexp-from-variable)


[warning] 79-79: Do not use variable for regular expressions
Context: new RegExp(rules.ticketPattern)
Note: [CWE-1333] Inefficient Regular Expression Complexity. Security best practice.

(regexp-non-literal-typescript)

🔇 Additional comments (13)
src/types/index.ts (1)

52-59: LGTM!

Also applies to: 69-69

src/core/config.ts (1)

5-42: LGTM!

Also applies to: 52-66, 106-106

src/core/config.test.ts (1)

61-77: LGTM!

src/commands/hooks.test.ts (1)

1-135: LGTM!

README.md (2)

13-13: LGTM!

Also applies to: 34-34, 124-153


152-152: No issue with the GIT_BROOM_FORCE=1 bypass.

src/core/git.ts (1)

3-3: LGTM!

src/core/hooks.test.ts (1)

1-122: LGTM!

src/core/hooks.ts (2)

1-61: LGTM!


91-161: LGTM!

src/commands/hooks.ts (1)

1-60: LGTM!

src/index.ts (1)

11-11: LGTM!

Also applies to: 27-29, 165-201

src/index.test.ts (1)

16-17: LGTM!

Also applies to: 26-29, 133-157, 159-166

Comment thread src/core/config.test.ts
Comment thread src/core/git.ts
Comment on lines +20 to +24
export async function getGitPath(path: string, cwd?: string): Promise<string> {
const gitPath = await git(['rev-parse', '--git-path', path], cwd)
return isAbsolute(gitPath) ? gitPath : resolve(cwd ?? process.cwd(), gitPath)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
fd -i 'git.test' 
rg -n -C2 'getGitPath' --type=ts -g '*.test.ts' -g '*.spec.ts'

Repository: 404-PF/git-broom

Length of output: 154


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate all references to getGitPath and git-path usage.
rg -n -C 2 --hidden --glob '!**/node_modules/**' 'getGitPath|--git-path|rev-parse' .

# List test files that might cover git helpers.
fd -t f -i 'test' .

# Inspect the git helper source with line numbers.
if [ -f src/core/git.ts ]; then
  wc -l src/core/git.ts
  cat -n src/core/git.ts | sed -n '1,220p'
fi

Repository: 404-PF/git-broom

Length of output: 8872


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Show hooks tests around the mocked getGitPath usage.
if [ -f src/core/hooks.test.ts ]; then
  wc -l src/core/hooks.test.ts
  cat -n src/core/hooks.test.ts | sed -n '1,220p'
fi

# Search for any git-specific test files or direct assertions on normalization behavior.
fd -t f 'git' src
rg -n -C 2 'resolve\(cwd ?? process\.cwd\(\),|isAbsolute\(|getGitPath\(' src --glob '*.test.ts' --glob '*.spec.ts'

Repository: 404-PF/git-broom

Length of output: 4481


Add a direct unit test for getGitPath normalization
The absolute/relative branching is only covered indirectly through src/core/hooks.test.ts mocks. A small test for absolute passthrough and relative resolution against cwd would lock in the cross-platform path handling here.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/core/git.ts` around lines 20 - 24, Add direct unit coverage for
getGitPath, mocking git to return both an absolute path and a relative path.
Verify absolute results are returned unchanged and relative results are resolved
against the supplied cwd, covering both branches of the normalization logic.

Comment thread src/core/hooks.ts
Comment on lines +63 to +89
function getBranchNamingReasons(
branch: string,
rules: BranchNamingConfig,
): string[] {
const reasons: string[] = [];

if (rules.requirePrefix) {
const prefix = branch.split("/")[0];
if (!rules.allowedPrefixes.includes(prefix ?? "")) {
reasons.push(
`missing a recognized prefix (${rules.allowedPrefixes.join(", ")})`,
);
}
}

if (rules.requireTicket) {
try {
if (!new RegExp(rules.ticketPattern).test(branch)) {
reasons.push(`missing a ticket number matching ${rules.ticketPattern}`);
}
} catch {
reasons.push("uses an invalid ticket pattern in .gitbroomrc");
}
}

return reasons;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
rg -n -C5 'ticketPattern' src/core/config.ts src/types/index.ts

Repository: 404-PF/git-broom

Length of output: 2400


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== src/core/hooks.ts ==\n'
wc -l src/core/hooks.ts
sed -n '1,180p' src/core/hooks.ts

printf '\n== src/core/config.ts ==\n'
wc -l src/core/config.ts
sed -n '1,120p' src/core/config.ts

printf '\n== search for renderHookScript / ignorePatterns matcher ==\n'
rg -n -C3 'renderHookScript|ignorePatterns|ticketPattern|new RegExp' src/core src/types

Repository: 404-PF/git-broom

Length of output: 14939


🏁 Script executed:

#!/bin/bash
set -euo pipefail

node - <<'JS'
const { performance } = require('node:perf_hooks');

const regex = new RegExp('^(a+)+$');

for (const n of [10, 12, 14, 16, 18, 20, 22, 24]) {
  const s = 'a'.repeat(n) + '!';
  const t0 = performance.now();
  regex.test(s);
  const dt = performance.now() - t0;
  console.log(`${n}\t${dt.toFixed(3)}ms`);
}
JS

Repository: 404-PF/git-broom

Length of output: 245


Avoid evaluating ticketPattern as a raw regex
src/core/hooks.ts:78-83 still runs new RegExp(rules.ticketPattern).test(branch) on every hook invocation. .gitbroomrc only checks that the pattern compiles, so a pathological expression can still trigger catastrophic backtracking and stall commits/pushes. Use a linear matcher or constrain the allowed pattern shape.

🧰 Tools
🪛 ast-grep (0.44.1)

[warning] 79-79: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(rules.ticketPattern)
Note: [CWE-1333] Inefficient Regular Expression Complexity

(regexp-from-variable)


[warning] 79-79: Do not use variable for regular expressions
Context: new RegExp(rules.ticketPattern)
Note: [CWE-1333] Inefficient Regular Expression Complexity. Security best practice.

(regexp-non-literal-typescript)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/core/hooks.ts` around lines 63 - 89, The ticket validation in
getBranchNamingReasons must not execute arbitrary ticketPattern regexes that can
catastrophically backtrack. Replace the new RegExp(...).test(branch) path with a
linear-time matcher, or validate and restrict ticketPattern to a safe supported
pattern shape before matching, while preserving the existing missing-ticket
reason and invalid-pattern handling.

@404-Page-Found

Copy link
Copy Markdown
Contributor Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown
✅ Action performed

Full review finished.


Your plan includes PR reviews subject to rate limits. More reviews will be available in 46 minutes.

…k names

- Remove redundant nullish coalescing in prefix check
- Clarify increment logic in glob matching algorithm
- Add warning when unknown hook name is provided
- Document shell choice for portability
writeFileSync with mode: 0o755 already sets permissions correctly.
The subsequent chmodSync call was redundant.
- Cache ticketPattern RegExp per branch check to avoid redundant compilation
- Clarify that /bin/sh usage is a Git constraint, not a portability choice
- Document hook name interpolation as safe via enum literal
- Add trailing newline to hooks.test.ts
- Add hook name to warning messages for better debugging context
- Fix regex escaping in isProtectedBranch to handle special characters
- Validate ignorePatterns for unmatched brackets to catch glob typos

These improvements make the hooks feature more reliable and easier to debug when issues arise.
Split the monolithic 'does not warn for protected or ignored branches'
test into three focused assertions: protected branches, * glob, and ?
single-character glob with a negative case. Add a note to README
explaining that installed hooks use #!/bin/sh and require Git Bash or
WSL on Windows.
Add validation to detect ambiguous unbounded quantifiers in ticket patterns to prevent catastrophic backtracking. Patterns like `a{1,}a{1,}!` are now rejected, falling back to the default safe pattern.
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.

Add pre-commit hook integration to prevent stale branch creation

1 participant