Skip to content

feat(rules): add MDS060 occurrence rule (plan 2607022118) - #758

Merged
jeduden merged 3 commits into
mainfrom
claude/youthful-knuth-3l4bh6
Jul 25, 2026
Merged

feat(rules): add MDS060 occurrence rule (plan 2607022118)#758
jeduden merged 3 commits into
mainfrom
claude/youthful-knuth-3l4bh6

Conversation

@jeduden

@jeduden jeduden commented Jul 20, 2026

Copy link
Copy Markdown
Owner

Summary

  • Add MDS060 occurrence rule: counts tokens or a regex pattern per scope unit (paragraph, section, file) and flags when the count falls below min or exceeds max
  • Fenced and indented code blocks are excluded via CollectSectionParagraphsWithText
  • Opt-in rule (enabled: false by default); supports lists: wordlist integration via WordlistTarget() = "tokens"
  • 32 unit tests + 5 integration fixture tests (3 bad, 2 good); all tests green

Code review fixes applied

Four confirmed bugs found during xhigh code review and fixed before committing:

  • File: f.Path missing from diagnosticsdiagEach/diagCombined produced diagnostics with empty File, breaking CLI output filename display and sort order; all 61 other rules set File: f.Path
  • Allocation budget violationcountToken called strings.ToLower(text) once per token per paragraph; with N tokens and P paragraphs that's N×P allocations. Fixed by pre-lowercasing text once per scope unit before the token loop, keeping Check within the ≤10-alloc budget
  • FindAllString allocates matched substrings — switched to FindAllStringIndex which returns positions only, eliminating one string copy per match
  • min < 0 accepted silently — negative min made the lower-bound check always true; ApplySettings now returns an error for min < 0

Files changed

  • internal/rules/occurrence/rule.go — rule implementation
  • internal/rules/occurrence/rule_test.go — 32 unit tests
  • internal/rules/MDS060-occurrence/README.md — rule documentation
  • internal/rules/MDS060-occurrence/bad/ — 3 bad fixtures
  • internal/rules/MDS060-occurrence/good/ — 2 good fixtures
  • internal/rules/all/all.go — import registration
  • internal/integration/perrule_bench_test.go — alloc ceiling entry (MDS060: 4)
  • internal/integration/testdata/rule_walk_audit.json — regenerated walk audit
  • internal/rulelayer/rule_walk_audit.json — copy kept in sync
  • docs/research/markdownlint-coverage/README.md, internal/rules/index.md — catalog regeneration

Generated by Claude Code

Counts each configured token or regex pattern within a scope unit
(paragraph, heading-bounded section, or file) and flags when the count
falls below `min` or exceeds `max`. Prose only — fenced and indented
code blocks are excluded via CollectSectionParagraphsWithText.

Fixes found during code review:
- Add File: f.Path to every diagnostic (was empty, breaking CLI output
  and sort order)
- Pre-lowercase paragraph text once per scope unit rather than once per
  (paragraph × token), keeping Check within the ≤10-alloc budget
- Use FindAllStringIndex instead of FindAllString in countPattern to
  avoid allocating matched substrings just to count them
- Validate min >= 0 in ApplySettings (negative min silently made the
  lower bound unreachable)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FgvajK8jHk49ncLChABAq2
@codecov

codecov Bot commented Jul 20, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.70%. Comparing base (d4af5d5) to head (8f5e5c4).
⚠️ Report is 3 commits behind head on main.

Additional details and impacted files
Components Coverage Δ
Go 98.69% <100.00%> (+<0.01%) ⬆️
TypeScript 99.54% <ø> (ø)

☔ 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.

claude added 2 commits July 20, 2026 04:54
…ng test coverage

Extract per-setting helper methods from ApplySettings to satisfy the
gocognit <= 30 limit. Also add tests for file-scope each mode,
section-scope combined and pattern modes, type-error paths in
ApplySettings helpers, and multi-section range-skip branches,
raising unit coverage from 79% to 99%.
…en test

countPattern is only called when r.Pattern != nil (all callers guard it),
so the nil check was dead code per the project's defensive-code rule
(branches must be driveable red/green). Remove it and add a test for
the empty-token path in countToken to reach 100% statement coverage.
@jeduden jeduden added queue Add to a PR to enqueue it queue:active Applied automatically when a PR is in an active batch and removed queue Add to a PR to enqueue it labels Jul 25, 2026
@jeduden

jeduden commented Jul 25, 2026

Copy link
Copy Markdown
Owner Author

🟢 Merge Queue — picked up

This PR is in the queue and will be batched with other queue-labelled PRs.

Next: No action needed — you'll get another comment when CI starts on the batch. View merge queue run.

@jeduden

jeduden commented Jul 25, 2026

Copy link
Copy Markdown
Owner Author

🔵 Merge Queue — CI running

Merged into batch branch merge-queue/batch-754-1785006212 alongside #754, #756, #762, #764. View CI run.

Next: No action needed — you'll be notified when CI completes.

@jeduden
jeduden merged commit 6138b7b into main Jul 25, 2026
35 checks passed
@jeduden jeduden removed the queue:active Applied automatically when a PR is in an active batch label Jul 25, 2026
@jeduden

jeduden commented Jul 25, 2026

Copy link
Copy Markdown
Owner Author

Merge Queue — merged

This PR landed on main via commit 47ace27. CI run that validated the merge.

Next: Done — nothing more to do here.

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