Repository navigation
Decide whether a whole-project Vale check should skip build output and vendored trees #101
Description
Activity
- added a commit that references this issue
on Aug 13, 2026 - changed the title
[-]Scope the scaffolded .vale.ini — a whole-project check lints .taskless/ and build output[/-][+]Decide whether a whole-project Vale check should skip build output and vendored trees[/+]on Aug 13, 2026 - added 2 commits that reference this issue
on Aug 19, 2026 Closing: the scaffold half of this is resolved by the rule-directory layout, and what remains does not justify a fix.
initno longer scaffolds a Vale configThis issue rested on the scaffolded
.vale.inishipping an unscoped[*]section. That file no longer exists. Verified against a CLI built frommainat5596e39:$ taskless init && find .taskless -type f .taskless/.gitignore .taskless/README.md .taskless/commands/tskl/tskl.md .taskless/rules/runtime/.gitkeep .taskless/rules/sg/.gitkeep .taskless/rules/vale/.gitkeep .taskless/skills/taskless/SKILL.md .taskless/taskless.jsonNo project-wide Vale config is written. #103 replaced it with per-rule
.vale.inifiles that each declare their own scope, assembled into one config at check time and gitignored. So Option 1 — ship[*.md]instead of[*]— has nothing left to change. It was the cheapest option and the one this issue leaned toward; the layout work removed the thing it would have edited.The only surviving unscoped
[*]insrc/is inbuildIsolatingConfig(packages/cli/src/rules/vale/verify.ts), which is deliberate: it is the ephemeral config that isolates a single rule against its fixtures, and narrowing it would break verification.What is left, and why it stays open-coded
A user can still hand-write
[*]in a per-rule.vale.ini, and a whole-projectcheckwould then reachdist/**/*.mdand similar. That residual is real but much weaker than what was measured here:- Nothing pushes a user toward it. The default is no config at all, and the authoring recipe teaches a scoped matcher.
create-vale-rule.txtexplicitly warns against it: "Do NOT add a[*]matcher to widen a rule that isn't firing" — with the reason, that matchers from every rule are assembled into one config.- Reaching the residual now takes a deliberate act against documented advice, rather than being what the scaffold handed you.
Against that, the remaining options cost more than they return:
- Respect
.gitignore— Vale has no.gitignoreawareness, so the CLI would resolve the ignore set and translate it into--globarguments. Real work, and the translation is lossy. - A built-in exclude list — cheap, and wrong for somebody. A repo that commits generated documentation may want it linted; prose is prose regardless of who wrote it.
- Nothing — the user controls scope through their own matcher, and a matcher they wrote wide producing wide results is arguably correct.
With the scaffold no longer creating the trap, the last option is the honest one.
If this comes back
The signal to reopen is a user who scoped a rule deliberately and still got findings from a tree they did not consider part of their project. That is a different report from this one, and it would come with the concrete tree that surprised them — which is exactly the input any exclusion mechanism would need to be designed against, and what this issue never had.
The scaffolded
.vale.iniopens an unscoped[*]section. That was harmless while Vale never ran; #100 makes a whole-projectcheckreach it for the first time.Measured
Scaffolded config, one rule enabled under
[*],vale ... -- .:doc.mddist/notes.md.taskless/vale/.vale.iniyes.taskless/vale/rules/no-simply.ymlyesnode_modules/somepkg/README.mdSo
node_modulesneeds nothing. What is left is build output and any vendored tree that is notnode_modules—dist/,build/,vendor/,target/, generated docs.Why this half is not obvious
Unlike
.taskless/, there is no reading under which the answer is forced:[*.md]has expressed an intent we would be second-guessing by adding exclusions on top.Options
[*.md]rather than[*], so the default is prose files and widening is the user's explicit act. Matches how the engine is defined intaskless help engine-selection, and matches what every fixture and test in the repo actually writes. Does not address adist/full of.md..gitignore. Most build output is already ignored, so this needs no per-language list and follows intent the user already expressed. Vale has no.gitignoreawareness, so the CLI would have to resolve the ignore set and translate it into--globarguments — real work, and the translation is lossy.[*]producing wide results is arguably correct behavior rather than a bug.Not urgent
The scaffold enables no rules, so nothing happens until a user adds one. Every fixture and test in the repo scopes its own section, which is also why the wide default went unnoticed for so long.
Refs #100