Skip to content

fix(core): resolve Lang and Transform in section order, not map order - #1143

Merged
jdkato merged 2 commits into
vale-cli:v3from
VXNCXNX:fix/deterministic-lang-transform
Aug 19, 2026
Merged

fix(core): resolve Lang and Transform in section order, not map order#1143
jdkato merged 2 commits into
vale-cli:v3from
VXNCXNX:fix/deterministic-lang-transform

Conversation

@VXNCXNX

@VXNCXNX VXNCXNX commented Aug 15, 2026

Copy link
Copy Markdown
Contributor

What's broken

When more than one config section matches a file, the resolved Lang and Transform are picked at random, and can differ between two files in the same run.

With [*] Lang = en and [*.md] Lang = ja, calling NewFile on the same .md path 200 times gave en 169 times and ja 31 times. Linting 40 identical .md files in one invocation sent en for 36 of them and ja for 6.

Why

Both loops in NewFile range over a map, and Go randomises map iteration, so break on the first match picks an arbitrary winner per call.

Lang is not cosmetic here: internal/nlp/prose.go sends it into the POS-tagging request, and internal/nlp/provider.go branches on Lang != "en" to decide whether to bypass the English-only segmenter.

The fix

The same function already solves this twenty lines above, for styles and rule levels, by walking config.RuleKeys in written order so a later section wins. That loop carries the comment referring to #965. These two loops now do the same, using the compiled patterns already in config.SecToPat instead of recompiling a glob for every file.

Two details worth calling out:

[*] is set through globalOpts and deliberately excluded from RuleKeys and SecToPat, so the global value is seeded before the loop and any matching section overrides it.

This changes the semantics from first-match-in-random-order to last-match-in-written-order. That is the point: it makes the behaviour match what the rule loop already documents, and the old order was never well defined.

Verification

internal/core/file_test.go covers a path matched by several sections, asserting the last one wins, plus the [*] fallback. It passes 20 out of 20 with -count=20. With the change reverted it fails on all 20, reporting expected Lang "it" ... got "en". go test ./internal/... is green, including the e2e package.

@jdkato
jdkato merged commit dd09d42 into vale-cli:v3 Aug 19, 2026
7 checks passed
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