| id | 161 |
|---|---|
| title | Expose rule maintainability patterns via CLI help and LSP |
| status | ✅ |
| model | sonnet |
| depends-on | |
| summary | Each rule README under `internal/rules/` declares a maintainability pattern — the structural shape where adopting the rule (or its directive/config) prevents drift. Schema-validate the block, surface it through `mdsmith help rule <name>` and a new `mdsmith help patterns` topic, and serve the same metadata through the LSP so the mdsmith-reviewer agent (plan 160) and any editor client can query patterns without hard-coding them in skill bodies. |
Move pattern knowledge out of skill bodies and into the rules. Each rule README declares the structural shape that adopting the rule would keep clean. The CLI and LSP expose that documentation so agents and editors can query it.
Plan 160 introduces the mdsmith-reviewer
agent. The agent walks changed files and
proposes which rule, directive, or kind config
to adopt so a pattern stops drifting.
Rules like catalog and include only
validate declared directives; they don't
detect a hand-maintained index. The reviewer
surfaces the opportunity before adoption.
Patterns live where the agent queries them at
runtime, not in the skill body.
The natural home is the existing rule README at
internal/rules/<id>-<name>/README.md.
The markdown-audit skill's
patterns.md
captures seven checks today.
Five rules carry maintainability blocks. The duplicated-content audit check binds to two rules. Detection and the recommended fix live in different places:
- catalog — hand-maintained indexes; adopt
<?catalog?>. - duplicated-content (MDS037) — repeated
paragraphs; extract via
<?include?>or refactor. - include (MDS021) — near-duplicate sections
worth deduping; adopt
<?include?>. - required-structure — kind without a schema;
declare it inline at
kinds.<name>.schemaor via proto file atkinds.<name>.rules.required-structure.schema. - directory-structure — file-placement
violations; move the file to an allowed
directory, or extend
directory-structure.allowedif the new location is correct.
MDS037 and MDS033 fire on the pattern
directly. Their fix matches the diagnostic
remedy. The other three (catalog, include,
required-structure) only validate declared
structures. Those blocks frame adoption
opportunities the reviewer surfaces before
the rule fires. Three audit checks are
config-level and stay in patterns.md: no
.mdsmith.yml, similar files without a kind,
kind without path-pattern. (Non-goal: no
new rules.)
- Adding new rules. This plan only documents and exposes existing rules' patterns.
- Auto-fixing the patterns. Fixes stay with
existing
mdsmith fixpaths and the user-invoked/mdsmith-fix. - Generalising the metadata beyond maintainability patterns; rule docs may grow other structured sections later, but the first cut targets the reviewer's needs.
Make signal and fix structured. The
contract cannot drift from prose. Add a
maintainability block to the rule README's
front matter. The rule-readme proto
validates it:
---
maintainability:
signal: "a list of links to sibling files in the same directory"
fix: "adopt a `<?catalog?>` directive so the list stays in sync"
for-diagnostic: false
---Schema goes in proto.md and directive-proto.md as a quoted CUE expression:
maintainability: '{signal: string & != "", fix: string & != "", "for-diagnostic"?: bool | *false} | null'The field is required (no ? suffix on
maintainability itself). Both signal and
fix are present and non-empty, or the whole
block is the literal null for rules with no
maintainability pattern. mdsmith check
rejects absence and partial blocks at lint
time.
for-diagnostic: true opts the entry into
hover enrichment. The default is false —
catalog, include, and required-structure fire
only after adoption. An "adopt X" sketch on
their diagnostics misleads. The two rules
that fire on the pattern directly set
for-diagnostic: true. Those are
duplicated-content and directory-structure.
Rules with no pattern set
maintainability: null and are omitted from
CLI/LSP payloads below. README bodies stay
free-form; tooling reads front matter only.
mdsmith help rule <name> strips front matter
today
(internal/rules/ruledocs.go).
Extend the renderer to append a
"Maintainability pattern" section built from
the maintainability block. The README body
stays free-form prose.
For bulk-load by agents, add a new
mdsmith help patterns topic (sibling of
rule, metrics, kinds). It emits every
rule's pattern in one shot.
Default output is text. -f json produces
records of {id, name, signal, fix, for-diagnostic}. id is the stable
diagnostic code (e.g. MDS001; matches
Diagnostic.code). name
is the human-readable rule name (e.g.
line-length).
The LSP gets one extension request and one existing-method enrichment:
mdsmith/rulePatterns— server returns the same payload asmdsmith help patterns -f json. Agent clients can call this once per session.textDocument/hoveron a diagnostic from a rule whosemaintainability.fixdescribes a diagnostic-level remediation appends that fix. Adoption-style fixes (e.g. catalog, include — recommending a directive before it exists) are skipped here so an already-firing diagnostic does not get a "adopt<?include?>" suggestion. The implementer adds afor-diagnostic: boolflag (or equivalent) on themaintainabilityblock to mark which entries hover may surface.
The mdsmith-reviewer agent (plan 160) calls one of:
mdsmith help patterns -f jsonwhen running outside an editor.mdsmith/rulePatternswhen an LSP server is attached.
Either way, the agent stays free of hard-coded patterns and picks up new rules automatically.
- Add the
maintainabilityfront-matter block (with the CUE constraint above) to bothinternal/rules/proto.md(used by therule-readmekind) andinternal/rules/directive-proto.md(used by thedirective-rule-readmekind for MDS019/021/038/039). Both kinds reference their respective proto, so the constraint propagates automatically once added. - Populate
maintainabilityon every existing rule README. Reuse content from the audit skill's patterns.md where it overlaps. Rules with no maintainability pattern setmaintainability: null. - Extend
mdsmith help rule <name>to render themaintainabilityblock as a "Maintainability pattern" section appended to the existing body output. Add the newpatternshelp topic tocmd/mdsmithemitting{id, name, signal, fix, for-diagnostic}records (omittingmaintainability: nullrules); honour-f text|json. Write failing tests first per CLAUDE.md. - Add the
mdsmith/rulePatternsLSP method and thetextDocument/hoverenrichment. Failing tests first. - Document both surfaces in
docs/reference/cli/help.mdanddocs/reference/cli/lsp.md. - Trim
patterns.mdto just the three config-level checks (no.mdsmith.yml, similar files without a kind, kind withoutpath-pattern). The five rule-backed checks now live in their rule READMEs. Update the audit skill body to load rule-backed patterns frommdsmith help patternsand keep reading the trimmedpatterns.mdfor the non-rule checks. The marketplace plugin ateditors/claude-code-audit/ships only the SKILL.md (no siblingpatterns.md); either inline the trimmed content into the plugin SKILL.md via<?include?>so installed users still get the non-rule heuristics, or add a siblingpatterns.mdundereditors/claude-code-audit/skills/markdown-audit/.
- Every rule README declares a
maintainabilityblock (either{signal, fix}ornull);mdsmith check internal/rules/passes via therule-readmeanddirective-rule-readmekinds. - Absence of the field, or a partial block
(e.g.
signalwithoutfix), failsmdsmith checkwith a schema error. - For a rule with a non-null
maintainabilityblock,mdsmith help rule <name>renders it as a "Maintainability pattern" section. - For a rule with
maintainability: null,mdsmith help rule <name>does not render a "Maintainability pattern" section (neither empty nor literalnull). -
mdsmith help patterns(default text) lists every rule's pattern in a readable form; covered by a new test asserting the output includes each rule'ssignalandfixlines for non-null rules. -
mdsmith help patterns -f jsonemits a JSON array of{id, name, signal, fix, for-diagnostic}entries (withidmatching diagnostic codes likeMDS001), omitting rules withmaintainability: null. Covered by a new unit test. -
mdsmith/rulePatternsreturns the same payload over LSP. Covered by a new LSP end-to-end test. -
textDocument/hoveron a diagnostic from afor-diagnostic: truerule (duplicated-content, directory-structure) appends the fix sketch. Hover on the three adoption-only rules (catalog, include, required-structure) and onmaintainability: nullrules is unchanged. Covered by a new hover test. -
docs/reference/cli/help.mdanddocs/reference/cli/lsp.mddocument the new topic and LSP method. - Both the local
markdown-auditskill and the installedmdsmith-auditplugin surface all five rule-backed patterns (frommdsmith help patterns) plus the three trimmed config-level checks (siblingpatterns.mdlocally; inlined into the plugin SKILL.md via<?include?>). -
go test ./...passes. -
mdsmith check .passes.