Skip to content

fix(config): discover global config from cwd for multi-path runs#660

Merged
rvben merged 1 commit into
rvben:mainfrom
darwin:fix/multi-path-global-config
Jun 8, 2026
Merged

fix(config): discover global config from cwd for multi-path runs#660
rvben merged 1 commit into
rvben:mainfrom
darwin:fix/multi-path-global-config

Conversation

@darwin

@darwin darwin commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Summary

rumdl check with multiple paths can silently drop findings for files that should be linted. When the
paths span several config scopes, the global config is seeded from the first path's directory. If that
path lives in a subdirectory whose .rumdl.toml extend-disables a rule, that nested config becomes the
global baseline for the whole run — disabling the rule for files in other directories that inherit the
project-root config.

Reproduction

proj/.rumdl.toml        → [MD013] line-length = 120                       (MD013 enabled)
proj/.git/              → project-root marker
proj/dir_a/.rumdl.toml  → extends "../.rumdl.toml" + extend-disable = ["MD013"]
proj/dir_a/a.md         → short
proj/dir_b/b.md         → long line (inherits root config → MD013 must fire)
$ cd proj
$ rumdl check dir_a/a.md dir_b/b.md   # MD013 NOT reported for dir_b/b.md  ← bug
$ rumdl check dir_b/b.md dir_a/a.md   # MD013 reported                      ← ok
$ rumdl check dir_b/b.md              # MD013 reported                      ← ok

The result depends on argument order. Tools that pass a sorted file list (pre-commit, editor wrappers) hit
this whenever the alphabetically-first file sits under such a subdirectory — e.g. a repo with a root config
plus .claude/.rumdl.toml / src/.rumdl.toml that extend-disable a rule will have that rule disabled
repo-wide on a full-tree rumdl check, even for files that should keep it. The effect is a false-negative
gate (long lines pass), which is how this was found.

Root cause

src/commands/check.rs derives discovery_dir from the first path's directory:

let discovery_dir = if !args.paths.is_empty() {
    let first_path = Path::new(&args.paths[0]);
    if first_path.is_dir() { Some(first_path) }
    else { first_path.parent().filter(|p| p.is_dir()) }
} else { None };

load_config_with_cli_error_handling_with_dir then chdirs there and discovers the nearest .rumdl.toml,
which becomes root_config. In resolution.rs, files outside that subdirectory land in the root group
(effective_config = None) and use this contaminated root_config, so a rule the project root enables
ends up disabled for them.

Fix

For multi-path runs, discover the global config from the cwd (project root) instead of the first path's
directory. Per-file grouping still layers each file's own nearest config on top, so nested extend-disable
keeps working for files actually under those directories. Single-path runs keep the existing
"discover next to that path" behavior.

Tests

Added test_multi_path_global_config_not_seeded_from_first_path in
tests/config/config_upward_traversal_test.rs — it fails before this change and passes after. The full
cargo test suite passes, and the existing single-path config-discovery tests are unchanged.

When several paths are passed to `rumdl check`, the global config was
seeded from the first path's directory. If that path lived in a
subdirectory whose `.rumdl.toml` `extend-disable`s a rule, that nested
config became the global baseline for the whole run, silently disabling
the rule for files in other directories that inherit the project-root
config.

Tools that pass a sorted file list (pre-commit, editor wrappers) hit
this whenever the alphabetically-first file sits under such a
subdirectory: e.g. `rumdl check .claude/a.md d/b.md` dropped MD013 on
`d/b.md` because `.claude/.rumdl.toml` extend-disables it.

Discover the global config from the cwd for multi-path runs; per-file
grouping still layers each file's own nearest config on top. Single-path
runs keep discovering next to the given path.
@rvben rvben merged commit 3c28327 into rvben:main Jun 8, 2026
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