chore: drop the flat content mirror and native install support (ADR-0024)
apm becomes the only supported install path. The flat mirror at each plugin root existed solely so Claude Code's native `claude plugin install` could convention-scan plugin content (ADR-0017). With no native consumers, it cost ~20,000 tracked lines plus ~2,100 lines of sync tooling and ~88s of every push to guard content apm never reads — and its only automated gate, `claude plugin validate --strict`, passes on a plugin with zero content, so it could not detect the defect ADR-0017 was created to fix. Removes the mirror (213 files), the six per-plugin manifest pairs, sync-plugin-content.sh, its 1,289-line test, the orphaned marketplace-plugins.sh, and the check-plugin-content-sync and validate-plugins pre-push hooks. The root `marketplace:` block and .claude-plugin/ catalogue stay: apm's own marketplace consumers read that same file, so `<name>@holocron` short names keep working. tests/run-bats.sh now excludes .claude/skills/. apm installs from .apm/, which carries the tests/ dirs the mirror stripped, so deployed .bats files would otherwise be discovered and double-run. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YR2CjVumUbEGWcMikcoXBD
This commit is contained in:
@@ -1,19 +0,0 @@
|
||||
{
|
||||
"name": "lint",
|
||||
"version": "1.1.7",
|
||||
"description": "Skills and agents for configuring and running linters.",
|
||||
"author": {
|
||||
"name": "Defame1297",
|
||||
"email": "defame1297@rkdr.net",
|
||||
"url": "https://git.dev.rkdr.net/Defame1297/"
|
||||
},
|
||||
"license": "MIT",
|
||||
"homepage": "https://git.dev.rkdr.net/Defame1297/holocron/src/branch/main/plugins/lint",
|
||||
"repository": "https://git.dev.rkdr.net/Defame1297/holocron/src/branch/main/plugins/lint",
|
||||
"keywords": [
|
||||
"lint",
|
||||
"style",
|
||||
"prose",
|
||||
"linter"
|
||||
]
|
||||
}
|
||||
19
plugins/lint/.github/plugin/plugin.json
vendored
19
plugins/lint/.github/plugin/plugin.json
vendored
@@ -1,19 +0,0 @@
|
||||
{
|
||||
"name": "lint",
|
||||
"version": "1.1.7",
|
||||
"description": "Skills and agents for configuring and running linters.",
|
||||
"author": {
|
||||
"name": "Defame1297",
|
||||
"email": "defame1297@rkdr.net",
|
||||
"url": "https://git.dev.rkdr.net/Defame1297/"
|
||||
},
|
||||
"license": "MIT",
|
||||
"homepage": "https://git.dev.rkdr.net/Defame1297/holocron/src/branch/main/plugins/lint",
|
||||
"repository": "https://git.dev.rkdr.net/Defame1297/holocron/src/branch/main/plugins/lint",
|
||||
"keywords": [
|
||||
"lint",
|
||||
"style",
|
||||
"prose",
|
||||
"linter"
|
||||
]
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
---
|
||||
name: lint-runner
|
||||
|
||||
description: Runs a linter sweep over a target file or directory scope and reports findings. Currently backs onto Vale (prose/style linting) via the vale-config and vale-run skills; built to add other linters later without changing its own contract. Use when a caller needs a lint pass run in an isolated context and wants findings back, not fixes applied.
|
||||
|
||||
source_keys:
|
||||
- context7-websites-vale-sh
|
||||
|
||||
disallowedTools: Edit, Write, NotebookEdit
|
||||
---
|
||||
|
||||
You are a linter runner. When invoked, you run the appropriate linter(s) over the requested scope, collect their findings, and report them back in a structured, reviewable form. You never edit files.
|
||||
|
||||
## Inputs
|
||||
|
||||
- **scope:** file path, directory path, or glob to lint
|
||||
- **linter:** which linter to run (defaults to `vale` — the only backend currently wired up)
|
||||
- **config context:** any project-specific linter configuration already in place (e.g. an existing `.vale.ini` for Vale, or whatever config format the requested linter expects); if none exists, say so in your report rather than inventing one
|
||||
|
||||
## Process
|
||||
|
||||
1. Determine whether the target scope already has configuration in place for the requested `linter` (whatever config format that linter expects). If not, use the `<linter>-config` skill (e.g. `vale-config` when `linter` is `vale`) to understand what's expected, but do not create or modify config yourself unless the caller explicitly asked for that separately from a lint run — report the gap instead.
|
||||
2. Use the `<linter>-run` skill (e.g. `vale-run` when `linter` is `vale`) to invoke the linter over the scope and interpret its raw output.
|
||||
3. Normalize findings into one shape regardless of backend linter: file, line, rule/check, severity, message.
|
||||
4. Do not edit, fix, or rewrite any flagged content. If a finding looks trivially fixable, note that in the report — do not act on it.
|
||||
5. If the linter itself is missing or misconfigured (not installed, no styles path, etc.), or if no `<linter>-config`/`<linter>-run` skill pair exists for the requested linter, report that as a blocking finding rather than attempting to install, configure, or substitute a fallback silently.
|
||||
|
||||
## Output
|
||||
|
||||
Report findings as a flat list, most-severe first:
|
||||
|
||||
```
|
||||
- file: <path>
|
||||
line: <line number or range>
|
||||
rule: <check/rule name>
|
||||
severity: <error | warning | suggestion>
|
||||
message: <finding text>
|
||||
```
|
||||
|
||||
Follow with a one-line summary: total findings by severity, and whether the run was blocked (e.g. linter not configured). If there are zero findings, say so explicitly — do not omit the report.
|
||||
@@ -1,63 +0,0 @@
|
||||
---
|
||||
name: vale-config
|
||||
|
||||
description: >
|
||||
Use when installing or configuring Vale, the prose/style linter — writing a `.vale.ini` whose
|
||||
styles are fetched and actually activated — even when the user says only "set up prose
|
||||
linting". Not running Vale on an existing config -> `vale-run`.
|
||||
|
||||
metadata:
|
||||
category: lint
|
||||
version: "0.1.2"
|
||||
source_keys:
|
||||
- context7-websites-vale-sh
|
||||
- house-vale-3-15-2-repro
|
||||
---
|
||||
|
||||
## Gotchas
|
||||
|
||||
- A style in `BasedOnStyles` that is neither built-in nor a directory under `StylesPath` fails hard, not silently: `E100 [loadStyles]`, exit 2, nothing linted.
|
||||
- `vale sync` alone does not clear that `E100`. Sync fetches only what the top-level `Packages` key declares, so against a `BasedOnStyles`-only name it reports `Synced 0 package(s)` and exits 0, fetching nothing. Add the style to `Packages`, then sync. A style lints only once it is in both keys — and the reverse case is silent, exiting 0.
|
||||
- Only *package* styles need fetching: built-in `Vale`, and any style whose YAML is already committed under `StylesPath`, lint with no `Packages` entry and no sync.
|
||||
- `.vale.ini` order is enforced, not stylistic: put core settings first, then `[formats]`, then glob sections. A core setting (`StylesPath`, `MinAlertLevel`, `Vocab`, `IgnoredScopes`, `SkippedScopes`) written below a `[glob]` header is a hard error — `E201 ... 'StylesPath' is a core option; it should be defined above any syntax-specific options`, exit 2, nothing linted. `Packages` is the exception, and the worse one: below a glob header it is accepted with no error, then ignored — `vale sync` reports `Synced 0 package(s)` and downloads nothing.
|
||||
- An `.mdx` file covered by one of your globs takes the whole run down unless `[formats]` maps it. Vale 3.15.2 has no built-in MDX support: unmapped, it shells out to an external `mdx2vast` binary, and with that absent from `PATH` the invocation dies on `E100 [lintMDX] Runtime error / mdx2vast not found`, exit 2 — every other file in the same command goes unlinted, with no output of its own. Default to the mapping — a `[formats]` section holding `mdx = md`, above the glob sections — which needs nothing installed; `npm install -g mdx2vast` is the alternative. The choice also inverts the inline-suppression syntax `vale-run` uses, so record which one the config took.
|
||||
- A rule scoped to `text.frontmatter.<key>` silently matches nothing when the field spans multiple lines in most YAML forms. If you scope a rule to frontmatter, read `references/configuration-reference.md` first.
|
||||
|
||||
## Setup workflow
|
||||
|
||||
- [ ] **Install** the `vale` binary: `brew install vale` (macOS), `snap install vale` (Linux), `choco install vale` (Windows), or `docker pull jdkato/vale`.
|
||||
- [ ] **Pick a `StylesPath`** (conventionally `styles`) and create it. This is where all styles, dictionaries, and vocab live.
|
||||
- [ ] **Write `.vale.ini`** at the project root with at minimum:
|
||||
```ini
|
||||
StylesPath = styles
|
||||
MinAlertLevel = suggestion
|
||||
|
||||
[*.md]
|
||||
BasedOnStyles = Vale
|
||||
```
|
||||
`Vale` here is the built-in style (`Vale.Spelling`, `Vale.Terms`, `Vale.Avoid`, `Vale.Repetition`): no `Packages` entry and no `vale sync`. It still needs the `StylesPath` directory to exist — declare `StylesPath = styles` without creating `styles/` and even a `Vale`-only config dies with `E201 ... The path '...' does not exist`, exit 2. That is why the previous step creates the directory.
|
||||
|
||||
**Settings in a glob section only apply to files matching that glob.** `BasedOnStyles` under `[*.md]` governs `.md` and nothing else: a `.mdx`, `.rst` or `.txt` in the same tree has no style active, is skipped without being counted, and a run over only such files reports `0 files` and exits 0 — indistinguishable from clean. Give every extension you mean to lint a glob that covers it.
|
||||
- [ ] **Add third-party styles** (optional) by declaring them in `Packages`, then activating them in the same or another glob's `BasedOnStyles`:
|
||||
```ini
|
||||
Packages = Google, write-good
|
||||
|
||||
[*.md]
|
||||
BasedOnStyles = Vale, Google, write-good
|
||||
```
|
||||
- [ ] **Sync**: run `vale sync` to download everything listed in `Packages` into `StylesPath`.
|
||||
- [ ] **Verify activation**: confirm every style named in `Packages` also appears in at least one glob's `BasedOnStyles` — an unreferenced package downloads but never lints anything.
|
||||
|
||||
For the full `.vale.ini` field reference (formats mapping, vocab, local overrides, custom rule header fields) and the verified style-resolution matrix — which error each misconfiguration raises, and the two that exit 0 while linting nothing — read `references/configuration-reference.md`.
|
||||
|
||||
## Custom styles
|
||||
|
||||
A custom style is just a new subdirectory under `StylesPath`, holding one YAML file per rule:
|
||||
|
||||
```
|
||||
styles/
|
||||
└── MyStyle/
|
||||
└── NoJargon.yml
|
||||
```
|
||||
|
||||
Each rule file needs `extends` (the check it implements, e.g. `existence`) and `message` at minimum. Activate the style the same way as any other: add `MyStyle` to `BasedOnStyles` for the relevant glob. If a rule needs a field beyond those two, read `references/configuration-reference.md` for the full rule header field table.
|
||||
@@ -1,113 +0,0 @@
|
||||
---
|
||||
topic: configuration-reference
|
||||
source_keys:
|
||||
- context7-websites-vale-sh
|
||||
- house-vale-3-15-2-repro
|
||||
---
|
||||
|
||||
## Core Settings
|
||||
|
||||
| Key | Type | Purpose |
|
||||
|---|---|---|
|
||||
| `StylesPath` | string | Path to all Vale-related resources (styles, dictionaries, vocab). |
|
||||
| `Packages` | string[] | Packages to download and install via `vale sync`. |
|
||||
| `Vocab` | string[] | Vocabularies to load. |
|
||||
| `MinAlertLevel` | enum | Minimum severity to report: `suggestion`, `warning`, or `error`. |
|
||||
| `IgnoredScopes` | enum | Inline-level HTML tags to ignore. |
|
||||
| `SkippedScopes` | enum | Block-level HTML tags to ignore entirely. |
|
||||
|
||||
## Format Associations
|
||||
|
||||
Map an unrecognized extension onto a supported one so Vale lints it with the right parser — an extension-level substitution only, it does not add new file-type support:
|
||||
|
||||
```ini
|
||||
[formats]
|
||||
mdx = md
|
||||
```
|
||||
|
||||
`mdx` is the case that matters, because Vale 3.15.2 has no built-in MDX support. The mapping above is not cosmetic: it is what lets `.mdx` files lint with nothing else installed. Leave it out and Vale takes the native MDX path, which shells out to an external `mdx2vast` binary — absent from `PATH`, the run dies with `E100 [lintMDX] Runtime error / mdx2vast not found`, exit 2, and every other file in the same invocation goes unlinted too. Take the mapping: it is this skill's recommended default, because it needs nothing installed, and it is the branch `vale-run` assumes when it documents inline suppressions. Install `mdx2vast` (`npm install -g mdx2vast`) only when something else in the toolchain already needs the native MDX parser.
|
||||
|
||||
The choice also decides the inline-suppression syntax, and it is inverted between the two: mapped to `md`, `.mdx` takes Markdown's `<!-- vale off -->`; native, it takes `{/* vale off */}`. `vale-run`'s `references/troubleshooting.md` carries the verified matrix.
|
||||
|
||||
## Vocabularies
|
||||
|
||||
Reference a named vocabulary (a folder of accept/reject word lists under `StylesPath`) via `Vocab`, then apply styles per glob:
|
||||
|
||||
```ini
|
||||
StylesPath = styles
|
||||
|
||||
Vocab = Blog
|
||||
|
||||
[*]
|
||||
BasedOnStyles = Vale, MyStyle
|
||||
```
|
||||
|
||||
## Local Overrides
|
||||
|
||||
A project can layer a local `.vale.ini` that overrides `StylesPath`, adds packages, and changes `BasedOnStyles` for a subset of files — local settings merge with or override the global ones:
|
||||
|
||||
```ini
|
||||
StylesPath = localpath
|
||||
|
||||
Packages = write-good
|
||||
|
||||
[*.md]
|
||||
BasedOnStyles = write-good
|
||||
```
|
||||
|
||||
## Rule Header Fields
|
||||
|
||||
Individual rule YAML files (under a style's directory) support these header fields:
|
||||
|
||||
| Field | Required | Default | Purpose |
|
||||
|---|---|---|---|
|
||||
| `extends` | yes | — | Check this rule extends (e.g. `existence`). |
|
||||
| `message` | yes | — | Message shown when triggered; supports `%s` formatting per check type. |
|
||||
| `level` | no | `suggestion` | Severity: `suggestion`, `warning`, or `error`. |
|
||||
| `scope` | no | `text` | Scope the rule applies to (e.g. `heading`). |
|
||||
| `link` | no | — | URL with more info about the rule. |
|
||||
| `limit` | no | — | Max number of triggers per file. |
|
||||
| `vocab` | no | `true` | Set `false` to disable active vocabularies for this rule. |
|
||||
|
||||
## Checks
|
||||
|
||||
The underlying functions a rule's `extends` field can reference: `existence`, `substitution`, `occurrence`, `repetition`, `consistency`, `conditional`, `capitalization`, `metric`, `spelling`, `sequence`, `script`.
|
||||
|
||||
## Style Resolution
|
||||
|
||||
Only *package* styles need fetching. A style whose YAML rule files are already committed under `StylesPath` lints immediately, with no `Packages` entry and no `vale sync`; the same is true of the built-in `Vale` style, which ships with the binary and contains four rules:
|
||||
|
||||
- `Vale.Spelling` — spell-checks against Hunspell-compatible dictionaries in `<StylesPath>/config/dictionaries`.
|
||||
- `Vale.Terms` — enforces the project's accepted vocabulary terms.
|
||||
- `Vale.Avoid` — enforces the project's rejected vocabulary terms.
|
||||
- `Vale.Repetition` — flags repeated words (e.g. "the the").
|
||||
|
||||
`Packages` (top-level, what `vale sync` downloads) and `BasedOnStyles` (per-glob, what activates) are separate keys: a style lints a file only once it is in both. Every row below reproduced against Vale 3.15.2 (slug `house-vale-3-15-2-repro`):
|
||||
|
||||
| Configuration | Result |
|
||||
|---|---|
|
||||
| `BasedOnStyles` names a style with no directory under `StylesPath`, not built-in | `E100 [loadStyles] Runtime error` — `style 'X' does not exist on StylesPath`, exit 2 |
|
||||
| `StylesPath` directory itself absent, even with only `Vale` active | `E201 Invalid value` — `The path '...' does not exist`, exit 2 |
|
||||
| `vale sync` with a name in `BasedOnStyles` but not `Packages` | `SUCCESS Synced 0 package(s)`, exit 0, nothing downloaded — the next lint repeats the `E100` |
|
||||
| `vale sync` with the name added to `Packages` | package lands under `StylesPath`, exit 0; lint then loads it |
|
||||
| Style in `Packages` and synced, but in no glob's `BasedOnStyles` | 0 findings, exit 0 — downloads, never lints, indistinguishable from a clean run |
|
||||
| `BasedOnStyles` names an *empty* directory under `StylesPath` | 0 findings, exit 0 — loads and lints nothing; `vale sync` never produces this state |
|
||||
| Built-in `Vale`, or a style's YAML committed under `StylesPath` | lints immediately, no `Packages` entry, no sync |
|
||||
| Core option (`StylesPath`, `MinAlertLevel`, `Vocab`, `IgnoredScopes`, `SkippedScopes`) below a `[glob]` header | `E201 Invalid value` — `'X' is a core option; it should be defined above any syntax-specific options ([...])`, exit 2 |
|
||||
| `Packages` below a `[glob]` header | no error, exit unaffected — parsed as a per-glob rule toggle (`SChecks: {"*.md": {"Packages": false}}` in `ls-config`), so `vale sync` reports `Synced 0 package(s)` and downloads nothing |
|
||||
|
||||
## Frontmatter Scopes
|
||||
|
||||
House-verified behaviour, not documented on vale.sh — reproduced locally against Vale 3.15.2 (slug `house-vale-3-15-2-repro`).
|
||||
|
||||
A rule scoped to `text.frontmatter.<key>` (e.g. `text.frontmatter.description`) matches reliably when that field's value is a single physical line, and breaks on most — not all — multi-line forms. Multi-line forms spanning 2+ lines:
|
||||
|
||||
| Frontmatter value form | Result |
|
||||
|---|---|
|
||||
| Single physical line (control) | Lints, exits 1 |
|
||||
| `\|` literal block scalar | Lints, exits 1 |
|
||||
| `>` folded block scalar | 0 findings, exits 0 |
|
||||
| Plain (unquoted) continuation lines | 0 findings, exits 0 |
|
||||
| Single- or double-quoted multi-line scalar | 0 findings, exits 0 |
|
||||
|
||||
The silent cases produce no error of any kind, so a passing run is indistinguishable from a clean one. Do not assume a literal block scalar and a folded one behave alike — reproduce both against your own config before trusting a frontmatter-scoped rule in production. If the field is commonly authored in one of the broken forms, flatten it to one physical line ahead of the `vale` call rather than relying on the scope alone.
|
||||
@@ -1,17 +0,0 @@
|
||||
# Sources
|
||||
|
||||
## context7-websites-vale-sh
|
||||
|
||||
- **URL:** context7:/websites/vale_sh
|
||||
- **Description:** Official Vale documentation site (vale.sh) indexed by Context7 — `.vale.ini` config reference, style/rule/check model, installation across package managers and Docker.
|
||||
- **Research doc:** plugins/lint/docs/research/docs/vale/sources.md
|
||||
- **Contributing files:** SKILL.md, references/configuration-reference.md
|
||||
- **Status:** `extracted`
|
||||
|
||||
## house-vale-3-15-2-repro
|
||||
|
||||
- **URL:** (house-verified — reproduced locally against the `vale` binary, not an external source)
|
||||
- **Description:** Behaviour of Vale 3.15.2 established by running it against purpose-built fixtures in this repo, where vale.sh documents nothing: the `E100 [loadStyles]` / exit-2 failure for a `BasedOnStyles` name absent from `StylesPath`, `vale sync` reporting `Synced 0 package(s)` for a name not declared in `Packages`, the `E201` / exit-2 failure when the `StylesPath` directory does not exist, the exit-0 no-op of an empty style directory, the `E201` / exit-2 failure when a core option is written below a `[glob]` header (with `Packages` as the silent exception), and the `text.frontmatter.<key>` scope matrix across multi-line YAML forms.
|
||||
- **Research doc:** none — house-verified reproduction, not part of the plugin's research corpus (no `plugins/lint/docs/research/` topic file backs this entry)
|
||||
- **Contributing files:** SKILL.md, references/configuration-reference.md
|
||||
- **Status:** `extracted`
|
||||
@@ -1,61 +0,0 @@
|
||||
---
|
||||
name: vale-run
|
||||
description: >
|
||||
Use when running Vale (a prose/style linter) on a project that already has a
|
||||
.vale.ini and acting on its output — even when the user does not say "Vale",
|
||||
as in "lint the docs", "check prose style", or "why is CI failing on the docs
|
||||
check". Not setting up Vale config or styles -> `vale-config`.
|
||||
metadata:
|
||||
version: "0.1.3"
|
||||
category: lint
|
||||
source_keys:
|
||||
- context7-websites-vale-sh
|
||||
- house-vale-3-15-2-repro
|
||||
---
|
||||
|
||||
## Gotchas
|
||||
|
||||
- Vale's exit code keys off `error`-level alerts only — `warning` and `suggestion` alerts print and still exit `0`, and `MinAlertLevel`/`--minAlertLevel` filter what is displayed, never the exit code — no flag makes warnings fail. A rule that must gate CI or a commit hook has to be `level: error`. This is the most common way a Vale gate silently passes everything.
|
||||
- Check whether the target repo documents its own `vale` wrapper script (README, CONTRIBUTING, pre-commit config, `scripts/`) before calling the binary. Some projects wrap `vale` to work around real bugs — e.g. a `text.frontmatter.<key>` scope that silently stops matching multi-line values (`>` folded scalars, plain continuation lines and quoted multi-line scalars all go unmatched; a `|` literal block scalar still works) — so bare `vale` skips whatever the wrapper fixes. Invoke the documented wrapper with the same arguments.
|
||||
|
||||
## Running vale
|
||||
|
||||
Default invocation (when the target repo has no documented Vale wrapper — see Gotchas):
|
||||
|
||||
```bash
|
||||
vale <path-or-glob>
|
||||
```
|
||||
|
||||
Key flags:
|
||||
|
||||
| Flag | Purpose |
|
||||
|---|---|
|
||||
| `--output=<style>` | Output format/template: `CLI` (default, human-readable), `line` (compact, one alert per line, good for grep/piping), `JSON` (for programmatic parsing), or a custom template. |
|
||||
| `--minAlertLevel=<suggestion\|warning\|error>` | Overrides `MinAlertLevel` from `.vale.ini` for this run only, without editing config. Filters what is displayed; does not affect the exit code. |
|
||||
| `--no-exit` | Suppresses the nonzero exit that `error`-level alerts would otherwise cause; a no-op when no rule is `error`-level. Use in CI stages that should surface lint output without hard-failing the build. |
|
||||
| `--ignore-syntax` | Treats input as plain text, skipping format-aware parsing — use when a file's syntax-aware parser produces noisy or wrong results. |
|
||||
|
||||
`vale sync` downloads the packages/styles declared in `.vale.ini` — that's a one-time-per-change setup step (vale-config's territory), not part of a normal lint run. If a run behaves as though no styles are active, check `vale ls-config` before concluding it is a sync problem — an unrun `vale sync` is the usual cause, and not a `vale-run` problem. `ls-config` resolves config files, styles and `StylesPath` search paths; it never enumerates rules, so it cannot tell you a given rule is live.
|
||||
|
||||
Prefer `--output=JSON` whenever the caller (a script, a CI step, another agent) needs to act on individual alerts rather than just get a pass/fail signal — `CLI` and `line` are for humans reading the terminal.
|
||||
|
||||
## Fixing false positives
|
||||
|
||||
Before writing any inline suppression markup (steps 2 and 3 below), read `references/troubleshooting.md`: the form follows the parser the config picks, not the file extension, and the wrong form suppresses nothing while Vale reports no error.
|
||||
|
||||
`.mdx` is the trap — the two parsers take opposite forms, so read `.vale.ini` first. Under `[formats] mdx = md` (what `vale-config` recommends) it is Markdown: `<!-- vale off -->` suppresses, `{/* vale off */}` does not. Without that mapping Vale takes the native MDX path, which needs the external `mdx2vast` binary (`npm install -g mdx2vast`); missing, the whole invocation dies — `E100 [lintMDX] ... mdx2vast not found`, exit 2 — leaving every other file in the run unlinted too.
|
||||
|
||||
Scope the fix as narrowly as possible, in this order:
|
||||
|
||||
1. **Mentioning banned phrasing rather than using it**: wrap it in backticks or a fenced code block. Vale skips code spans and fences, so no suppression is needed at all. Try this before any suppression markup.
|
||||
2. **One-off**: inline-suppress the specific text run with the format's `vale off`/`vale on` markup.
|
||||
3. **Recurring known-exception string, one rule**: disable that specific rule for that specific match inline (in Markdown, e.g. `<!-- vale Style.Redundancy["ACT test","OTHER"] = NO -->` ... `= YES`), rather than the whole rule.
|
||||
4. **Known project term failing spell check**: add it to the style's `ignore` list, not an inline suppression — and put the listed file at the `StylesPath` root, because an `ignore` path that resolves nowhere is a silent no-op (`references/troubleshooting.md`).
|
||||
|
||||
Never disable a rule project-wide to fix one false positive — editing `.vale.ini`/`BasedOnStyles` is vale-config's job, and it silences the rule everywhere, not just the false-positive case.
|
||||
|
||||
If output looks wrong because Vale mis-parsed a file's format, rerun with `--ignore-syntax` before assuming the rule itself is broken.
|
||||
|
||||
For CI that fails solely because Vale returned non-zero on `error`-level alerts — not because the content is wrong for that pipeline stage — add `--no-exit` rather than disabling the rule. If the failing alerts are warnings or suggestions, Vale is not what failed the build; look elsewhere.
|
||||
|
||||
If a rule appears not to apply, if you need the spelling-ignore syntax, if a CI failure still needs diagnosing, or if setting Vale up as a pre-commit hook, read `references/troubleshooting.md`.
|
||||
@@ -1,17 +0,0 @@
|
||||
# Sources
|
||||
|
||||
## context7-websites-vale-sh
|
||||
|
||||
- **URL:** context7:/websites/vale_sh
|
||||
- **Description:** Official Vale documentation site (vale.sh) indexed by Context7 — `.vale.ini` config reference, style/rule/check model, CLI commands and flags, installation across package managers and Docker, format-specific inline disable syntax, pre-commit integration, spelling ignore lists.
|
||||
- **Research doc:** plugins/lint/docs/research/docs/vale/sources.md
|
||||
- **Contributing files:** SKILL.md, references/troubleshooting.md
|
||||
- **Status:** `extracted`
|
||||
|
||||
## house-vale-3-15-2-repro
|
||||
|
||||
- **URL:** (house-verified — reproduced locally against the `vale` binary, not an external source)
|
||||
- **Description:** Behaviour of Vale 3.15.2 established by running it against purpose-built fixtures in this repo, where vale.sh documents nothing or documents it wrongly: `.mdx` has no built-in support and needs either `[formats] mdx = md` or an external `mdx2vast` binary (absent, the whole invocation exits 2 with `E100 [lintMDX]`), the inline-suppression form inverts between those two configurations, the `spelling` check's `ignore` paths resolve against `StylesPath` or the working directory but never against the rule file's own directory and fail silently when they resolve nowhere, `ls-config` reports styles and paths but never rules, and the `text.frontmatter.<key>` scope matrix across multi-line YAML forms.
|
||||
- **Research doc:** none — house-verified reproduction, not part of the plugin's research corpus (no `plugins/lint/docs/research/` topic file backs this entry)
|
||||
- **Contributing files:** SKILL.md, references/troubleshooting.md
|
||||
- **Status:** `extracted`
|
||||
@@ -1,191 +0,0 @@
|
||||
---
|
||||
source_keys:
|
||||
- context7-websites-vale-sh
|
||||
- house-vale-3-15-2-repro
|
||||
---
|
||||
|
||||
# Vale troubleshooting reference
|
||||
|
||||
## Why a rule isn't applying
|
||||
|
||||
`vale ls-config` prints the fully-resolved, currently active configuration as JSON. Check that
|
||||
before rereading `.vale.ini` — what is written in the config file is not necessarily what is
|
||||
active, and the resolved output is the fastest way to see which config files, styles and
|
||||
`StylesPath` directories a run actually loaded.
|
||||
|
||||
It stops at styles. It does not enumerate rules, and neither does any other Vale 3.15.2
|
||||
subcommand — `ls-config`, `ls-dirs`, `ls-vars` and `ls-metrics` were each checked and none
|
||||
names the rule. Against a config
|
||||
whose custom rule was demonstrably firing on the target file, `ls-config` reported
|
||||
`"SBaseStyles": {"*.md": ["MyStyle"]}` and the two `StylesPath` search paths, but
|
||||
`"Checks": null`, `"SChecks": {"*.md": {}}` and `"RuleToLevel": {}` — the firing rule's own name
|
||||
appeared nowhere in the output. So `ls-config` answers "is this style loaded, and from where",
|
||||
not "is this rule live". For the latter, run Vale over a small fixture that should trigger the
|
||||
rule and see whether it alerts.
|
||||
|
||||
## Inline suppression syntax by format
|
||||
|
||||
### Prerequisite: `.mdx` needs a decision before it lints at all
|
||||
|
||||
Vale 3.15.2 has no built-in MDX support. If `.vale.ini` does **not** map the extension, Vale takes
|
||||
the native MDX path and shells out to an external `mdx2vast` binary. Without it on `PATH` the run
|
||||
dies before linting anything:
|
||||
|
||||
```
|
||||
$ vale . # doc.md and doc.mdx both present, no [formats] mapping
|
||||
E100 [lintMDX] Runtime error
|
||||
|
||||
mdx2vast not found
|
||||
|
||||
Execution stopped with code 1.
|
||||
$ echo $?
|
||||
2
|
||||
```
|
||||
|
||||
That is the whole invocation, not just the `.mdx` file — the `.md` alongside it produced no output
|
||||
either. Fix it one of two ways, and the choice is not cosmetic because it also decides the
|
||||
suppression syntax:
|
||||
|
||||
| `.vale.ini` | Prerequisite | Parser | Suppression form that works |
|
||||
|---|---|---|---|
|
||||
| `[formats]` maps `mdx = md` (what `vale-config` recommends) | none | Markdown | `<!-- vale off -->` |
|
||||
| no `mdx` mapping (native MDX) | `npm install -g mdx2vast` | MDX | `{/* vale off */}` |
|
||||
|
||||
Key the markup to that config row, never to the file extension. Verified against Vale 3.15.2, same
|
||||
three fixtures under each config:
|
||||
|
||||
| File | Mapped `mdx = md` | Native MDX (`mdx2vast` installed) |
|
||||
|---|---|---|
|
||||
| no suppression (control) | alert, exit 1 | alert, exit 1 |
|
||||
| `<!-- vale off -->` | suppressed, exit 0 | `E100 ... failed to parse MDX: Unexpected character` `` `!` ``, exit 2 |
|
||||
| `{/* vale off */}` | **not suppressed**, exit 1 | suppressed, exit 0 |
|
||||
|
||||
Under the mapping the JSX comment is worse than inert: it is linted as prose, so
|
||||
`{/* vale Vale.Repetition = NO */}` produced three alerts where the un-suppressed file produced
|
||||
one — its own markup tripped the rule twice more.
|
||||
|
||||
Markdown, and `.mdx` mapped onto it — HTML comments:
|
||||
```markdown
|
||||
<!-- vale off -->
|
||||
This text will be ignored.
|
||||
<!-- vale on -->
|
||||
```
|
||||
|
||||
Native MDX only (no `[formats]` mapping, `mdx2vast` on `PATH`):
|
||||
```mdx
|
||||
{/* vale off */}
|
||||
This text will be ignored.
|
||||
{/* vale on */}
|
||||
```
|
||||
|
||||
Org mode:
|
||||
```org
|
||||
# vale off
|
||||
This text will be ignored.
|
||||
# vale on
|
||||
```
|
||||
|
||||
## Disabling a specific rule for specific matches
|
||||
|
||||
Targets one rule and specific known-exception strings, then re-enables — the preferred fix for a recurring false positive on a specific term, since it keeps the rule active everywhere else:
|
||||
|
||||
Markdown:
|
||||
```markdown
|
||||
<!-- vale Style.Redundancy["ACT test","OTHER"] = NO -->
|
||||
This is some text ACT test
|
||||
<!-- vale Style.Redundancy["ACT test","OTHER"] = YES -->
|
||||
```
|
||||
|
||||
Native MDX only — under `[formats] mdx = md` an `.mdx` file takes the Markdown form above, and
|
||||
this one silences nothing:
|
||||
```mdx
|
||||
{/* vale Style.Redundancy["ACT test","OTHER"] = NO */}
|
||||
This is some text ACT test
|
||||
{/* vale Style.Redundancy["ACT test","OTHER"] = YES */}
|
||||
```
|
||||
|
||||
## Ignoring words in spell check
|
||||
|
||||
The `spelling` check accepts an `ignore` list of external plain-text files, so project-specific terms don't need touching the dictionary:
|
||||
|
||||
```yaml
|
||||
extends: spelling
|
||||
message: "Did you really mean '%s'?"
|
||||
level: error
|
||||
ignore:
|
||||
- ignore1.txt
|
||||
- ignore2.txt
|
||||
```
|
||||
|
||||
**Where the file goes, and why a wrong answer is invisible.** Each entry resolves against the
|
||||
`StylesPath` root, or against the working directory `vale` is invoked from. It does **not** resolve
|
||||
against the rule file's own directory — which is the natural reading of the YAML above, since the
|
||||
path sits inside the rule, and it is wrong. Verified against Vale 3.15.2 across four fresh trees,
|
||||
each with the same rule and the same unknown word:
|
||||
|
||||
| Where `ignore1.txt` was placed | Result |
|
||||
|---|---|
|
||||
| `<StylesPath>/ignore1.txt` | word ignored, exit 0 |
|
||||
| `./ignore1.txt` in the directory `vale` runs from | word ignored, exit 0 |
|
||||
| `<StylesPath>/<Style>/ignore1.txt`, beside the rule | word still flagged, exit 1 |
|
||||
| file absent entirely | word still flagged, exit 1 |
|
||||
|
||||
The two failing rows emit no warning, no error, and no diagnostic of any kind: the output is
|
||||
byte-identical to the same rule with the `ignore` key deleted. A misplaced ignore list looks exactly
|
||||
like a list that was read and did not contain the word.
|
||||
|
||||
Prefer the `StylesPath` root. The run-directory form is the fragile one — move the invocation and it
|
||||
silently stops working. Same tree, same file, only the working directory changed:
|
||||
|
||||
```
|
||||
$ cd project && vale doc.md # ignore1.txt at project root
|
||||
✔ 0 errors, 0 warnings and 0 suggestions in 1 file. # exit 0
|
||||
|
||||
$ cd /elsewhere && vale --config=project/.vale.ini project/doc.md
|
||||
1:5 error Did you really mean 'zzqwidget'? MyStyle.Spell # exit 1
|
||||
```
|
||||
|
||||
The `StylesPath` copy survives that move; the run-directory copy does not.
|
||||
|
||||
## Plain-text fallback
|
||||
|
||||
If a file's syntax-aware parsing produces noisy or incorrect results (an unsupported or malformed format), rerun with `--ignore-syntax` to treat it as plain text instead of relying on the format-specific parser.
|
||||
|
||||
## CI failing unexpectedly
|
||||
|
||||
Only `error`-level alerts make Vale exit non-zero; `warning` and `suggestion` alerts are printed but exit `0`. If a CI job fails solely because of `error`-level alerts — not because the content is actually wrong for that pipeline stage — add `--no-exit` rather than suppressing the rule itself. This preserves the lint output while not gating the build on it. If the alerts are warnings or suggestions, Vale did not fail the job — look elsewhere.
|
||||
|
||||
## pre-commit integration
|
||||
|
||||
Vale ships a pre-commit hook definition. A typical setup runs `vale sync` once (with `pass_filenames: false`) plus the actual lint pass with CI-appropriate flags:
|
||||
|
||||
```yaml
|
||||
repos:
|
||||
- repo: https://github.com/errata-ai/vale
|
||||
rev: 16d3a7f
|
||||
hooks:
|
||||
- id: vale
|
||||
name: vale sync
|
||||
pass_filenames: false
|
||||
args: [sync]
|
||||
- id: vale
|
||||
args: [--output=line, --minAlertLevel=error]
|
||||
```
|
||||
|
||||
If the project has documented a wrapper script for a known Vale scope/escaping limitation (see the Gotchas section of `SKILL.md`), point the second hook's `entry:` at that wrapper instead of at bare `vale`, even though the hook's `repo`/`rev`/`id` still come from the upstream definition above — only the invocation target changes:
|
||||
|
||||
```yaml
|
||||
- id: vale
|
||||
entry: <path-to-project-wrapper>
|
||||
args: [--output=line, --minAlertLevel=error]
|
||||
```
|
||||
|
||||
Using the upstream hook's bare `vale` entry in a project that has such a wrapper reintroduces exactly the bug the wrapper exists to fix.
|
||||
|
||||
## CI output for machine parsing
|
||||
|
||||
```bash
|
||||
$ vale --output=JSON README.md
|
||||
```
|
||||
|
||||
Use `--output=JSON` when a CI step needs to parse results programmatically rather than read the default CLI-formatted output.
|
||||
Reference in New Issue
Block a user