# Configuration

## pyproject.toml

```toml
[tool.menard]
require_links = ["src/**/*.py"]  # Code files that must have doc links
doc_paths = ["docs/**/*.md"]     # Where to look for documentation
exclude_docs = ["**/adr/**"]     # Docs to exclude from bootstrap suggestions
transitive_depth = 1             # Import chain depth for staleness detection
```

The `require_links` glob determines which code files need documentation. Files matching this pattern without a link in `links.toml` will show up in coverage reports.

The `doc_paths` patterns specify where menard looks for documentation files.

The `exclude_docs` patterns prevent `menard bootstrap` from suggesting links to certain docs. This is useful for excluding static/historical documents like ADRs (Architectural Decision Records) or plans that record past decisions rather than living documentation that should track code changes.

Note: `exclude_docs` only affects bootstrap suggestions. You can still manually link to excluded docs in `links.toml`, and staleness checks will run normally. The distinction is intentional: ADRs might be legitimately linked to architecture code, but shouldn't be auto-suggested since they're historical records.

Set `transitive_depth` to control how deep menard follows imports when detecting staleness. If `src/auth.py` imports `src/crypto.py`, and crypto changes, should auth docs be marked stale? With depth 1, yes. With depth 0, no.

## links.toml

Define code→doc relationships in `.menard/links.toml`:

```toml
# Single file → single doc
[[link]]
code = "src/auth.py"
docs = ["docs/api.md"]

# Section-level precision (recommended)
[[link]]
code = "src/auth.py"
docs = ["docs/api.md#Authentication"]

# One code file → multiple doc sections
[[link]]
code = "src/models/user.py"
docs = [
  "docs/models.md#User Model",
  "docs/api.md#User Endpoints",
]

# Glob patterns
[[link]]
code = "src/models/*.py"
docs = ["docs/models.md"]

# Auto-generated docs (skip staleness checks)
[[link]]
code = "src/cli.py"
docs = ["docs/reference/cli.md"]
auto_generated = true

# Permanently ignore staleness (e.g., intentionally outdated)
[[link]]
code = "src/legacy.py"
docs = ["docs/legacy.md"]
ignore = true
```

The `ignore` flag permanently skips staleness checks for a link. Unlike `auto_generated`, this is for cases where you've deliberately decided not to keep docs in sync. Use `menard fix-ignore` to add this flag interactively.

Section-level links are more precise. When you change `src/auth.py`, only the Authentication section needs updating, not the entire 500-line doc file.

menard parses doc files to find section headings, extracts line ranges, then uses `git diff` to check if those specific lines changed. If the section's lines didn't change since the code changed, it's stale.

### Auto-generated Documentation

Use `auto_generated = true` to skip staleness checks for documentation that's automatically regenerated by tools like `mkdocs-click`, `sphinx-autodoc`, or `rustdoc`. These docs stay synchronized with code by definition, so staleness checks are unnecessary.

```toml
[[link]]
code = "src/cli.py"
docs = ["docs/reference/cli.md"]
auto_generated = true  # Skip staleness checks
```

**Important**: Validation still runs for auto-generated links. If `docs/reference/cli.md` doesn't exist, menard will report an error. Only staleness checks are skipped.

When auto-generated docs are skipped, menard reports the count:

```bash
$ menard check
✓ Staged files have up-to-date documentation
  (2 auto-generated docs skipped)
```

JSON output includes `skipped_auto_generated` count for programmatic access.

## Staleness Detection

menard uses git diff analysis to detect stale docs, combined with AST parsing to identify specific symbol changes (functions, classes added/removed). It checks in two places:

```bash
# 1. Check staged content first (same commit workflow)
git diff --cached -- docs/api.md

# 2. Fall back to git history
git log -1 --format=%H -- src/auth.py
git diff <commit> HEAD -- docs/api.md
```

When you stage both code and docs together, menard detects the staged changes and passes. If docs aren't staged, it compares git history: if the diff shows changes overlapping with the section's line range, the doc was updated. If no overlap, it's stale.

This works transitively too. If `src/auth.py` imports `src/crypto.py`, and crypto changes, auth docs can be marked stale (controlled by `transitive_depth`).

### Enriched Output

When docs are stale, menard shows detailed information to help you understand what changed:

- **Dates**: When code and docs were last updated (`code_last_modified`, `doc_last_modified`)
- **Commits**: Recent commits that modified the code since docs were updated
- **Symbol changes**: Functions and classes added or removed (via AST analysis)
- **Code diff**: The actual git diff (with `--show-diff` flag)
- **Line range**: Exact lines to edit in the doc file
- **Suggested action**: `update` or `create`

```bash
$ menard list-stale

  docs/api.md#Authentication
    Code: src/auth.py
    Last code change: 2026-03-17 (abc1234)
    Last doc update: 2026-03-10
    Commits since doc updated:
      abc1234 (2026-03-17) feat: add MFA support
    Changed: +2 symbols, -1 symbol
      Added: mfa_verify, mfa_setup
      Removed: legacy_auth
```

The JSON output includes all this metadata in a structured format for machine consumption:

```json
{
  "stale": [{
    "code_file": "src/auth.py",
    "doc_target": {
      "file": "docs/api.md",
      "section": "Authentication",
      "line_range": [45, 89]
    },
    "code_last_modified": "2026-03-17",
    "doc_last_modified": "2026-03-10",
    "commits_since": [{
      "sha": "abc1234",
      "date": "2026-03-17",
      "message": "feat: add MFA support"
    }],
    "symbols_added": ["mfa_verify", "mfa_setup"],
    "symbols_removed": ["legacy_auth"],
    "severity": null,
    "auto_generated": false,
    "suggested_action": "update",
    "reason": "Section unchanged since src/auth.py changed"
  }]
}
```

The structured `doc_target` with `line_range` enables AI agents to make precise, scoped edits.

Symbol extraction results are cached in `.menard/symbols_cache.json` for performance. The cache uses content-based hashing, so identical file contents always return cached results. Old entries are automatically evicted to keep the cache under 500 entries.

## donttouch

Protect critical content from staleness checks in `.menard/donttouch`:

```
# Section protection - never mark these as stale
README.md#License
docs/contributing.md#Code of Conduct
CLAUDE.md#Terminology (ENFORCED)

# Literal protection - warn if these strings change
"Python 3.10+"
"Apache-2.0"
"#7730E1"
```

License text, brand colors, version requirements, and policies shouldn't be flagged just because related code changed. Protected sections are skipped during staleness checks. Protected literals trigger warnings if modified.

```bash
menard list-protected
```

Shows all protected sections and literals.

## Bootstrap

Auto-generate link suggestions:

```bash
menard bootstrap --apply
```

This uses filename matching (`src/auth.py` → `docs/auth.md`), content analysis (grep docs for code file references), and import graphs to propose links. Review suggestions carefully—bootstrap can't reliably infer links for human-facing docs like tutorials.

Use `exclude_docs` in your config to prevent bootstrap from suggesting links to static documents:

```toml
[tool.menard]
doc_paths = ["docs/**/*.md"]
exclude_docs = ["**/adr/**", "**/plans/**", "**/decisions/**"]
```

## Validation and Coverage

```bash
menard validate-links  # Check all link targets exist
menard coverage        # Show documentation coverage percentage
```

Validation catches typos and missing sections. Coverage shows what percentage of your `require_links` files have documentation.

## Commands

```bash
menard check           # Pre-commit: validate links + check staged files for stale docs
menard check --all     # Manual audit: check ALL tracked files (not just staged)
menard list-stale      # Audit: list ALL stale docs across entire repo
menard fix             # Interactive mode: review/update/mark/ignore stale docs
menard fix-mark-reviewed --code FILE --doc TARGET  # Mark as reviewed (ephemeral)
menard fix-ignore --code FILE --doc TARGET         # Permanently ignore link
menard clean-reviewed  # Remove orphaned review records
```

The `check` command runs during pre-commit and performs two validations:
1. Link validation - ensures all links in `links.toml` point to existing files/sections
2. Staleness detection - checks if staged code changes require doc updates

Both `check` and `list-stale` support `--format json` for machine consumption. The JSON output includes file paths, section names, line ranges, and git diffs—everything an AI agent needs to make scoped updates.
