Skip to content

feat: read path-scoped .claude/rules/*.md as review context - #184

Open
roqmarcelo wants to merge 3 commits into
alansikora:mainfrom
roqmarcelo:feat/claude-rules
Open

feat: read path-scoped .claude/rules/*.md as review context#184
roqmarcelo wants to merge 3 commits into
alansikora:mainfrom
roqmarcelo:feat/claude-rules

Conversation

@roqmarcelo

Copy link
Copy Markdown
Contributor

Context

Claude Code auto-loads convention files from .claude/rules/*.md (markdown with YAML frontmatter: description + paths globs). CodeCanary can't see them, so consumers hand-duplicate every convention into .codecanary/review.yml, which drifts. This teaches the reviewer to read those rule files directly, scoped to the files a PR actually touches.

Changes

  • ReadClaudeRules (internal/review/rules.go): globs .claude/rules/*.md, parses leading --- frontmatter, and includes a rule only when a changed file matches its paths globs. A rule with no paths is always included (matches Claude Code semantics). Path scoping reuses the existing matchesAny matcher (config.go), so .claude/rules and review.yml rules honor identical full-path glob semantics.
  • Own byte budget (8KB/file, 32KB total) separate from the CLAUDE.md caps, with a visible truncation warning to stderr.
  • Merges discovered rules into the ProjectDocs map in prepareReview so they flow through writeProjectDocs with no prompt-builder changes (rendered as <project-doc path=".claude/rules/…"> blocks).
  • Tests appended to docs_test.go following the existing readXFrom(root, files) testable-core pattern: frontmatter parsing, scope in/out, no-frontmatter fallback, per-file and total byte budgets.
  • Docs: review-flow.md, configuration.md, README.md.

Notes

Complements the existing path-scoped review.yml rules (FilterRules) and ancestor-scoped CLAUDE.md discovery — same idea, applied to Claude Code's native rule files. No config changes, no new dependencies (doublestar/yaml.v3 already vendored).

Verified: go build ./..., go vet ./..., go test ./..., golangci-lint all clean.

🤖 Generated with Claude Code

Claude Code auto-loads convention files from .claude/rules/*.md (markdown
with YAML frontmatter: `description` + `paths` globs). CodeCanary couldn't
see them, forcing consumers to hand-duplicate every convention into
review.yml, which drifts.

- Add ReadClaudeRules (internal/review/rules.go): glob .claude/rules/*.md,
  parse leading `---` frontmatter, include a rule only when a changed file
  matches its `paths` globs (no `paths` = always included, matching Claude
  Code semantics). Own byte budget (8KB/file, 32KB total) separate from the
  CLAUDE.md caps, with a visible truncation warning. Path scoping reuses the
  existing matchesAny matcher (config.go) so it honors identical glob
  semantics to review.yml rule scoping.
- Merge discovered rules into the ProjectDocs map in prepareReview so they
  flow through writeProjectDocs with no prompt-builder changes.
- Tests (docs_test.go): frontmatter parsing, scope in/out, no-frontmatter
  fallback, per-file and total byte budgets — following the existing
  readXFrom(root, files) testable-core pattern.
- Update review-flow.md, configuration.md, README.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
codecanary-bot[bot]

This comment was marked as resolved.

- runner.go: guard against a .claude rule key clobbering an existing
  project-doc key — skip with a warning instead of silently overwriting
  (184-1).
- rules.go: sort glob matches so total-budget exhaustion is deterministic
  across platforms (184-2).
- rules.go: reserve room for the truncation marker so a truncated rule is
  exactly maxRuleBytes, keeping total-budget accounting exact (184-3).
- rules.go: splitFrontmatter now requires the closing fence to be a line
  that is solely `---`, so a `---` in a YAML value or body paragraph is no
  longer mistaken for the fence (184-4). Adds regression tests.
- configuration.md: correct the CLAUDE.md cap figures (16KB/48KB/10 files)
  to match the docs.go constants (184-5).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
codecanary-bot[bot]

This comment was marked as resolved.

Follow-up to the 184-4 fix: matching the closing fence via
strings.TrimSpace also stripped leading indentation, so an indented `---`
inside a YAML block scalar would prematurely end the frontmatter and drop
the remaining keys (184-6). Match an unindented `---` line instead
(TrimRight only, tolerating trailing whitespace/CR for CRLF files). Adds
regression tests for the indented-block-scalar and trailing-whitespace
cases.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

@codecanary-bot codecanary-bot 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.

🐥 CodeCanary

✅ All previous findings have been addressed. No new issues found. ✨

Status

  • Resolved by code: 1

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