Skip to content

Decide whether a whole-project Vale check should skip build output and vendored trees #101

Description

@theCodeDrift

Scope narrowed. This issue originally bundled two problems. The .taskless/ half is fixed in #100 (63719f3) — Taskless linting its own config and the user's rule definitions is wrong under every reading, so it did not belong behind an open question. What remains is the part that genuinely is a judgement call.

The scaffolded .vale.ini opens an unscoped [*] section. That was harmless while Vale never ran; #100 makes a whole-project check reach it for the first time.

Measured

Scaffolded config, one rule enabled under [*], vale ... -- .:

Path Linted Status
doc.md yes intended
dist/notes.md yes this issue
.taskless/vale/.vale.ini yes fixed in #100
.taskless/vale/rules/no-simply.yml yes fixed in #100
node_modules/somepkg/README.md no Vale skips it already

So node_modules needs nothing. What is left is build output and any vendored tree that is not node_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:

  • A repo that commits generated documentation may want it linted. Prose is prose regardless of who wrote it.
  • The set of build directories is language- and tool-specific, so any built-in list is a guess that is wrong somewhere.
  • Vale already respects the user's section globs, so a user who scopes [*.md] has expressed an intent we would be second-guessing by adding exclusions on top.

Options

  1. Scope the scaffold instead of excluding. Ship [*.md] rather than [*], so the default is prose files and widening is the user's explicit act. Matches how the engine is defined in taskless help engine-selection, and matches what every fixture and test in the repo actually writes. Does not address a dist/ full of .md.
  2. Respect .gitignore. Most build output is already ignored, so this needs no per-language list and follows intent the user already expressed. Vale has no .gitignore awareness, so the CLI would have to resolve the ignore set and translate it into --glob arguments — real work, and the translation is lossy.
  3. A small built-in exclude list. Cheap, immediately useful, wrong for somebody. Would want to be overridable.
  4. Nothing. Defensible: the user controls scope through their config, and a wide [*] 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

Activity

  1. 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
  2. theCodeDrift commented on Aug 19, 2026

    @theCodeDrift
    MemberAuthor

    Closing: the scaffold half of this is resolved by the rule-directory layout, and what remains does not justify a fix.

    init no longer scaffolds a Vale config

    This issue rested on the scaffolded .vale.ini shipping an unscoped [*] section. That file no longer exists. Verified against a CLI built from main at 5596e39:

    $ 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.json
    

    No project-wide Vale config is written. #103 replaced it with per-rule .vale.ini files 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 [*] in src/ is in buildIsolatingConfig (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-project check would then reach dist/**/*.md and 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.txt explicitly 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 .gitignore awareness, so the CLI would resolve the ignore set and translate it into --glob arguments. 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.

    Resolved by #103. Refs #100.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions