Skip to content

fix(rules): avoid duplicate home rule scope#62

Merged
kenryu42 merged 2 commits into
mainfrom
fix/issue-61-home-rule-scope
Jun 15, 2026
Merged

fix(rules): avoid duplicate home rule scope#62
kenryu42 merged 2 commits into
mainfrom
fix/issue-61-home-rule-scope

Conversation

@kenryu42

@kenryu42 kenryu42 commented Jun 15, 2026

Copy link
Copy Markdown
Owner

PR Summary

Fixes #61.

This PR prevents user-scope rulebooks from being loaded twice when cc-safety-net runs with cwd === $HOME.

When the current working directory is the user’s home directory, the computed user config path and project config path can both point to:

~/.cc-safety-net/rules/rule.json

Previously, the policy loader treated those as separate scopes, which duplicated the same active rulebook and caused runtime fail-closed behavior:

  duplicate active rulebook name "user-rules"

That blocked every tool call, including harmless commands.

Changes

  • Detect when user and project rule config paths refer to the same file.
  • Load the shared config only once as user scope.
  • Preserve duplicate-rulebook-name detection for genuinely distinct user/project configs.
  • Add regression coverage for:
    • core policy loading from $HOME
    • runtime analysis allowing harmless commands after loading the config
    • rule list not showing duplicated global rules when run from $HOME

Summary by CodeRabbit

Release Notes

  • Bug Fixes

    • Fixed duplicate rule configuration loading when the user and project config paths point to the same real filesystem location, preventing redundant reads and avoiding incorrect project-scope handling.
  • Tests

    • Added coverage to ensure global/user rules are not loaded twice when running from a home directory and that policy recovery behaves correctly.

@coderabbitai

coderabbitai Bot commented Jun 15, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c3d9255f-a8ac-41a1-946b-6063cac171ea

📥 Commits

Reviewing files that changed from the base of the PR and between e2b9708 and 141fb3d.

📒 Files selected for processing (1)
  • tests/bin/rule.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/bin/rule.test.ts

📝 Walkthrough

Walkthrough

loadRulesPolicy in scope-policy.ts gains a guard that compares the real filesystem paths of the user and project config files using a new isSameConfigPath() helper backed by realpathSync. When the paths match (i.e., cwd is the home directory), the project config slot is filled with an empty result instead of re-reading the same file. Two new tests verify the single-load behavior at the integration and CLI levels.

Changes

Home directory config deduplication

Layer / File(s) Summary
Same-path guard in loadRulesPolicy
src/core/rules/policy/scope-policy.ts
Adds realpathSync import, introduces isSameConfigPath() helper that resolves and compares real paths with existence checks, and calls it in loadRulesPolicy to substitute an empty project config result when user and project paths resolve to the same file.
Integration and CLI tests
tests/core/rules-policy-recovery.test.ts, tests/bin/rule.test.ts
Adds an integration test that sets up a temp home-directory cwd, runs syncRulesConfig in global mode, and asserts a single rulebook/policy entry with failClosedReason undefined and analyzeCommand returning null. Adds a CLI test that runs rule list from a temp HOME and asserts no duplicate or incorrectly scoped active source entries.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐇 When HOME is your cwd, oh what a surprise,
The rulebook appeared twice before my own eyes!
But now realpathSync compares paths with care,
If user meets project — one copy stays there.
No duplicates blocked, let the commands run free,
A single true rulebook is all that you need! 🥕

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
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 (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and concisely describes the main change: preventing duplicate user-scope rule loading when home directory configs collide.
Linked Issues check ✅ Passed The PR implements the exact fix suggested in issue #61: detecting matching real paths and treating shared configs as user scope only, preventing duplicate rulebook errors.
Out of Scope Changes check ✅ Passed All changes directly address the root cause of issue #61 with no unrelated modifications to the codebase.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/issue-61-home-rule-scope

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 and usage tips.

@codecov

codecov Bot commented Jun 15, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 87.50000% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 97.40%. Comparing base (b82142f) to head (141fb3d).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
src/core/rules/policy/scope-policy.ts 87.50% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main      #62      +/-   ##
==========================================
- Coverage   97.42%   97.40%   -0.02%     
==========================================
  Files          94       94              
  Lines       10327    10341      +14     
==========================================
+ Hits        10061    10073      +12     
- Misses        266      268       +2     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@greptile-apps

greptile-apps Bot commented Jun 15, 2026

Copy link
Copy Markdown

Greptile Summary

This PR fixes a fail-closed regression that triggered whenever cc-safety-net ran with cwd === $HOME: because the user config path and project config path both resolved to ~/.cc-safety-net/rules/rule.json, the same rulebook was loaded twice, causing the "duplicate active rulebook name" error that blocked every tool call.

  • Adds isSameConfigPath which first compares resolve()-normalized paths (catching the cwd === HOME case) and falls back to realpathSync for symlink-identical files, then skips loading project config when a match is detected.
  • Preserves all existing duplicate-name detection for genuinely distinct user/project configs.
  • Adds regression tests at both the unit level (rules-policy-recovery.test.ts) and the CLI level (rule.test.ts) covering the bug scenario end-to-end.

Confidence Score: 5/5

The change is safe to merge — it adds a targeted deduplication guard with no impact on the normal distinct-scope code path.

The fix is narrow: a new helper that short-circuits one readRulesConfig call when both config paths resolve to the same file. The existing duplicate-detection logic, override handling, and lock-file validation are all untouched for the normal case. Regression tests cover both the unit and CLI surfaces of the bug.

No files require special attention; the three dist/ bundles are mechanical rebuilds of the single source change in scope-policy.ts.

Important Files Changed

Filename Overview
src/core/rules/policy/scope-policy.ts Adds isSameConfigPath helper that skips loading project config when it resolves to the same file as user config; fix is minimal and correctly handles symlinks via realpathSync fallback.
tests/core/rules-policy-recovery.test.ts Adds regression test verifying policy loads correctly when cwd equals home directory, with no errors and single user-scoped rulebook.
tests/bin/rule.test.ts Adds CLI-level regression test confirming rule list shows exactly one active source and no duplicate/error output when run from home directory.
dist/bin/cc-safety-net.js Regenerated bundle matching source changes; no independent logic.
dist/index.js Regenerated bundle matching source changes; no independent logic.
dist/pi/index.js Regenerated bundle matching source changes; no independent logic.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[loadRulesPolicy] --> B[getPolicyPaths]
    B --> C{isSameConfigPath?}
    C -- resolve paths equal --> D[true]
    C -- paths differ, check existence --> E{Both files exist?}
    E -- no --> F[false]
    E -- yes --> G[realpathSync comparison]
    G --> H{Same real path?}
    H -- yes --> D
    H -- no --> F
    D --> I[project = null config]
    F --> J[readRulesConfig project path]
    I --> K[userPolicy only]
    J --> L[userPolicy + projectPolicy]
    K --> M[Return policy - single user scope]
    L --> N[getDuplicateRulebookNames check]
    N --> O[Return merged policy]
Loading

Reviews (1): Last reviewed commit: "fix(rules): avoid duplicate home rule sc..." | Re-trigger Greptile

@kenryu42 kenryu42 merged commit 297e740 into main Jun 15, 2026
7 checks passed
@kenryu42 kenryu42 deleted the fix/issue-61-home-rule-scope branch June 15, 2026 16:54
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.

[Bug]: Every tool call blocked with "duplicate active rulebook name" when the agent runs from $HOME

1 participant