markdown_paths_resolve
Validate that backticked workspace paths in markdown files resolve to real files or directories in the repo. Targets the AGENTS.md / CLAUDE.md / .cursorrules staleness problem: agent-context files reference paths in inline backticks (`src/api/users.ts`), and those paths drift as the codebase evolves. The agent-context-no-stale-paths rule shipped in v0.6 surfaces candidates via a regex; this rule does the precise existence check.
The prefixes list is required — a backticked token must start with one of these to be considered a path candidate. No defaults: every project's layout differs, and a missing prefix is silent while a wrong default trips false positives.
The scanner skips fenced code blocks (``` / ~~~) and 4-space-indented blocks; those contain code samples, not factual claims about the tree. Trailing :line / #L<n> location suffixes are stripped before lookup, as are trailing punctuation and trailing slashes. Glob characters (*, ?, [) trigger globset matching against the file index — pass if at least one file matches. A command-shaped span such as `tools/run.ts --check` passes when its first word resolves and the remainder begins with an option or contains no path separator. The complete span is always tried first, so a real path containing whitespace is not mistaken for a command.
By default the rule skips backticked tokens containing template-variable markers ({{ }}, ${ }, <…>). Set ignore_template_vars: false to validate them as literal paths.
Check-only — auto-fixing a stale path means guessing the new location, which is unsafe.
Options
Section titled "Options"| Option | Type | Required | Default | Description |
|---|---|---|---|---|
ignore_template_vars | boolean | true | When true (default), skip backticked tokens containing {{ ... }}, ${ ... }, or <...> template-variable markers. These are placeholders, not real paths. | |
prefixes | list of string | yes | Whitelist of path-shape prefixes to validate. A backticked token must start with one of these to be considered a path candidate. No defaults - every project's layout differs and the user must declare which prefixes mark a path. |
Plus the common paths, level, id, when, scope_filter, and expect_matches fields. This table is generated from the JSON Schema; option types and defaults are authoritative.
Example
Section titled "Example"Backticked file paths in Markdown that do not exist
Section titled "Backticked file paths in Markdown that do not exist"The rule fires on this repository:
- AGENTS.md
⚠ warning agents-paths-resolve
4:11 backticked path `src/missing.ts` doesn't resolve to a file or directory
⚠ warning agents-paths-resolve
4:32 backticked path `docs/gone.md` doesn't resolve to a file or directory
⚠ warning agents-paths-resolve
5:37 backticked path `tools/missing.ts --check` doesn't resolve to a file or directory
- docs/
- docs/extant.md✓
- src/
- src/exists.ts✓
# Agents file
See `src/exists.ts` for the implementation.Reference `src/missing.ts` and `docs/gone.md`.A missing command path still fails: `tools/missing.ts --check`.
```yamlexample: `src/in-codeblock.ts````
Inline `npm install` doesn't trigger.Path with line: `src/exists.ts:42`.Template var: `src/{{user_id}}.ts`.# real docexport const x = 1;With this .alint.yml:
version: 1rules: - id: agents-paths-resolve kind: markdown_paths_resolve paths: ["AGENTS.md"] prefixes: ["src/" , "docs/" , "tools/" ] level: warningalint check reports:
--- AGENTS.md ------------------------------------------------------------------ ! warning agents-paths-resolve 4:11 backticked path `src/missing.ts` doesn't resolve to a file or directory ! warning agents-paths-resolve 4:32 backticked path `docs/gone.md` doesn't resolve to a file or directory ! warning agents-paths-resolve 5:37 backticked path `tools/missing.ts --check` doesn't resolve to a file or directory
Summary (3 violations): ! 3 warnings 0 passing * 1 failingEvery backticked path in the doc resolves to a real file
Section titled "Every backticked path in the doc resolves to a real file"This repository is compliant:
AGENTS.mddocs/docs/User Guide.mddocs/guide.mdsrc/src/api.tssrc/utils.tstools/tools/run.ts# Agents file
Production code lives under `src/api.ts` and `src/utils.ts`.User-facing docs are at `docs/guide.md`.Run `tools/run.ts --check` to verify the tree, or use`tools/run.ts verify` for the positional-argument form.A real path containing whitespace still resolves: `docs/User Guide.md`.
```yaml# In code blocks, references aren't validated:example: `src/anything-goes.ts````# user guide# guideexport function api() {}export const u = 1;export function run() {}With this .alint.yml:
version: 1rules: - id: agents-paths-resolve kind: markdown_paths_resolve paths: ["AGENTS.md"] prefixes: ["src/" , "docs/" , "tools/" ] level: warningalint check reports:
v All 1 rule(s) passed.