docs: trim CONTEXT.md to a glossary and demote VISION.md
Why: CONTEXT.md is an instructed every-session read at 33,799 bytes (~8,450
tokens), and CONTEXT.md:17 layered docs/VISION.md on top. After the AGENTS.md
trim, that left ~9,650 tokens of instructed reads sitting behind a file whose
own format contract — grill-with-docs/CONTEXT-FORMAT.md:43, "Keep definitions
tight. One sentence max." — it was not following. 22 glossary entries averaged
190 words; the top four were 55% of the file, and one ("Vale audit prefilter")
was 1,444 words of pre-commit forensics filed as a definition.
Implementation notes:
- CONTEXT.md rewritten to CONTEXT-FORMAT.md's prescribed template: ## Language
(five clusters, 22 terms with _Avoid_ aliases), ## Relationships,
## Example dialogue, ## Flagged ambiguities. 33,799 -> 9,762 bytes.
- Vale prefilter forensics moved to docs/spec/gates.md under nine subsections:
the two-copy style layout, vale-wrap.sh and the Vale 3.15.2
text.frontmatter.description limitation, the --config argv defect (E100),
glob scoping, the rule inventory, and 0-files-means-NOT-RUN.
- Instruction-file format and the bidirectional-reference principle moved to
docs/spec/architecture.md, the latter flagged as aspirational: no instruction
file carries a `when:` field, only 2 of 39 skills do, and the reference
scanner script it names does not exist.
- Added a per-plugin scope table to architecture.md so "which plugin owns this
skill" survives the trim, and corrected its claim that the content index
lives in providers/claude-code/CLAUDE.md — that file is now two import lines
and the index sits in core/AGENTS.md.
- "Repo and Gitea are the only source of truth" moved from CONTEXT.md's
Principles into AGENTS.md session rules; it was operative guidance in a
glossary. docs/VISION.md and LESSONS.md added to the on-demand list.
- The apm-consumed install entry (432 words) was deleted outright: all four
consequences are already carried by README.md, ADR-0018, gates.md and
AGENTS.md.
- ADR-0013, ADR-0015 and ADR-0017 each pointed at CONTEXT.md sections that
moved; amended with dated supersession notes rather than left dangling.
Impact: the every-session set drops from ~15,700 to ~4,140 tokens across both
passes (-74%). The deleted "lint plugin" entry was also stale on a safety
claim — it said lint-runner inherits Edit, but ADR-0016 restored
`disallowedTools: Edit, Write, NotebookEdit` and CONTEXT.md was never updated.
Refs: #99
This commit is contained in:
@@ -9,6 +9,12 @@ deferred PR #85 review item to broaden that coverage, retroactively captures #84
|
||||
(since it was never recorded as a decision in its own right), and layers the expansion on top
|
||||
without reversing or weakening the original four rules.
|
||||
|
||||
**2026-08-17 amendment.** The CONTEXT.md section named above no longer holds that documentation.
|
||||
CONTEXT.md was cut back to a glossary and the prefilter's mechanics — the two-copy style layout,
|
||||
`vale-wrap.sh`, the `--config` argv defect, the rule inventory, and the 0-files-means-NOT-RUN
|
||||
fallback — moved to `docs/spec/gates.md`. Read that file, not CONTEXT.md, for the harness itself;
|
||||
this ADR still owns the scope decision.
|
||||
|
||||
**File scope stays the same.** `SKILL.md` plus agent files (`**/agents/*.md`,
|
||||
`**/*.agent.md`) only — matching the existing prefilter's globs. Skill-level
|
||||
`README.md` files and `plugin.json` manifests are not added: README.md files are navigational, not
|
||||
|
||||
@@ -56,6 +56,8 @@ new hand-maintained manifest format.
|
||||
that work through to merge.
|
||||
- `CONTEXT.md`'s "Plugin"/"Plugin marketplace" glossary entries were rewritten in issue #90 to
|
||||
describe the compiled-output model directly, rather than carrying a forward-pointer to this ADR.
|
||||
Superseded 2026-08-17: CONTEXT.md was cut back to one-line definitions, and the compiled-output
|
||||
model is now described in `docs/spec/architecture.md`.
|
||||
|
||||
## Considered options
|
||||
|
||||
|
||||
@@ -329,7 +329,9 @@ mirror does carry, and is reported.
|
||||
stands; this ADR fixes the second, previously-unverified half.
|
||||
- `CONTEXT.md`'s "Plugin" and "Plugin marketplace" glossary entries are updated to describe the
|
||||
flat mirror as a second compiled-output category, alongside the existing
|
||||
`.claude-plugin/plugin.json`/`marketplace.json` description.
|
||||
`.claude-plugin/plugin.json`/`marketplace.json` description. Superseded 2026-08-17: CONTEXT.md was
|
||||
cut back to one-line definitions and no longer describes either compiled-output category;
|
||||
`docs/spec/architecture.md` is where the mirror is documented.
|
||||
- A future apm release that ships a native `.apm/`-aware plugin.json compiler (closing this gap
|
||||
upstream) would let `sync-plugin-content.sh` and its drift gate be deleted outright — nothing in
|
||||
this ADR's decision depends on the flat mirror existing beyond satisfying the current installer's
|
||||
|
||||
@@ -21,12 +21,23 @@ project repo (local overrides)
|
||||
|
||||
Skills are **not** deployed by `install.sh`. They are distributed as plugins and installed separately — in this repo by `apm install` against the `dependencies.apm` entries in the root `apm.yml`, which lands them in `.claude/skills/` and `.claude/agents/` (ADR-0018); elsewhere by `claude plugin install <name>@holocron`.
|
||||
|
||||
`~/.claude/CLAUDE.md` is a thin adapter, not a content source. It imports `~/.agents/AGENTS.md` (always-on rules) and `governance.md` (always-on governance), then lists the content index. All always-on content lives in `AGENTS.md` files so other providers can import the same source without duplication.
|
||||
`~/.claude/CLAUDE.md` is a thin adapter, not a content source. It imports `~/.agents/AGENTS.md` (always-on rules) and `governance.md` (always-on governance) and carries nothing else — the content index of on-demand instruction files sits in `core/AGENTS.md`, deployed beside it. All always-on content lives in `AGENTS.md` files so other providers can import the same source without duplication.
|
||||
|
||||
## Plugin model
|
||||
|
||||
Skills, agents, MCP servers, and hooks are distributed as self-contained plugin units under `plugins/`, installed independently — via `apm install` here, or `claude plugin install <name>@holocron` for a host consuming the marketplace natively (ADR-0018). Each plugin is an **apm package**: `plugins/<name>/apm.yml` plus a hand-authored `plugins/<name>/.apm/{skills,agents,hooks,commands,instructions,extensions}/` tree (ADR-0015). There is no hand-maintained `plugin.json` — every manifest and every host-visible content directory is compiled from that source.
|
||||
|
||||
Which plugin a new skill belongs in follows from what each one is scoped to. The boundary that matters most in practice is `core` vs `kyberforge`: `core` is the home for cross-cutting, repo-agnostic utility skills that a consumer would want against *their* repo, while `kyberforge` is meta-tooling for the holocron marketplace itself. A skill that authors a target repo's `AGENTS.md` is `core`; a skill that audits a `SKILL.md` against this marketplace's contract is `kyberforge`.
|
||||
|
||||
| Plugin | Scope |
|
||||
|---|---|
|
||||
| `core` | Authoring and auditing a repo's `AGENTS.md` and the provider adapter files that defer to it |
|
||||
| `git` | Conventional commits, branch management, history, worktrees, remotes |
|
||||
| `gitea` | Issues, pull requests, labels, milestones, releases, wikis |
|
||||
| `kyberforge` | Creating and maintaining a Claude Code / Copilot CLI plugin marketplace — this repo's own meta-tooling |
|
||||
| `lint` | Configuring and running linters; repo-agnostic, first linter is Vale (`vale-config` / `vale-run`, plus the `lint-runner` agent) |
|
||||
| `bin` | Unsorted skills that have not earned a home yet |
|
||||
|
||||
Two compilers produce the plugin roots you see in the tree:
|
||||
|
||||
- **`apm pack` compiles the manifests** (ADR-0015). Per plugin: `.claude-plugin/plugin.json` and `.github/plugin/plugin.json`, both generated from `plugins/<name>/apm.yml`. Repo-wide, from the root `apm.yml`'s `marketplace:` block: `.claude-plugin/marketplace.json` (apm's `claude` output profile) and `.agents/plugins/marketplace.json` (its `codex` profile, a differently-shaped file). Those two are the only marketplace outputs apm has profiles for — the third root manifest, `.github/plugin/marketplace.json` (Copilot CLI's legacy path), is a byte-identical mirror of the Claude one maintained by `scripts/sync-marketplace-mirror.sh` and gated by the `check-marketplace-mirror-sync` pre-push hook.
|
||||
@@ -40,6 +51,8 @@ That immunity is positional, not by filename. Anything placed *inside* a mirrore
|
||||
|
||||
`core/instructions/governance.md` is the always-on governance instruction file. Unlike the on-demand instruction files in the content index, governance.md is loaded into every Claude session via `@import` in `providers/claude-code/CLAUDE.md`. This is a technical guarantee, not a behavioural instruction — `@import` causes Claude Code to expand and load the file at launch, before any interaction begins.
|
||||
|
||||
Those on-demand files are plain markdown — no frontmatter, no schema. The agent decides when to read each one from task context and the content index label alone. Frontmatter is deferred until there is evidence that agents are loading the wrong files in practice; it is a deliberate deferral, not an oversight to close.
|
||||
|
||||
The governance layer has two phases:
|
||||
- **Phase 1** (complete): instruction and documentation layer — `governance.md` loaded via `@import`; `docs/ai-constitution.md` and `docs/wiki/HUMANS.md` as human-facing reference; `CONTEXT.md` extended with governance domain language.
|
||||
- **Phase 2** (planned): deterministic enforcement layer — pre-commit hooks, CI gates, secret scanning, licence scanning. Specified in `docs/research/governance_principles/CONTROLS.md`.
|
||||
@@ -57,6 +70,10 @@ This repo also has a `CLAUDE.md` at its root — the Claude Code entry point for
|
||||
|
||||
`CONTEXT.md` is therefore **not** always-loaded. `AGENTS.md` instructs agents to read it at session start, which is a behavioural instruction, not an `@import` guarantee — `LESSONS.md`'s 2026-05-17 entry proposed adding the import and it was never applied. Treat that entry as open work rather than a record of a landed change.
|
||||
|
||||
## Reference conventions
|
||||
|
||||
The stated convention is that files referencing other files declare those references explicitly: the referencing file carries the forward reference (the content index in `core/AGENTS.md`, `references:` in frontmatter), the referenced file carries a `when:` field describing when it is loaded, and divergence between the two signals staleness. It is aspirational, not a description of the repo today — no file under `core/instructions/` carries frontmatter at all, `when:` appears in two of the 39 skill sources under `plugins/*/.apm/skills/`, and the reference scanner script meant to derive the reverse map ("what files reference this file?") does not exist; `docs/notes/skill-implementation-workflow.md` still lists it as unbuilt work. Treat it as intent for instruction files, skills, and workflow documents, not as a rule the repo enforces.
|
||||
|
||||
## Provider model
|
||||
|
||||
`core/` is never tool-specific. `providers/` is never shared. When adding a new provider, write an adapter in `providers/<name>/` that translates core content into the tool's expected format and location. The core content itself does not change.
|
||||
|
||||
@@ -87,7 +87,9 @@ loudly (`Error: jq is required but not installed`).
|
||||
## Skill and agent context gates (ADR-0020)
|
||||
|
||||
The `skill-size-check` pre-commit hook, scoped to `^plugins/[^/]+/\.apm/skills/[^/]+/SKILL\.md$`,
|
||||
runs `scripts/skill-size-check.sh`.
|
||||
runs `scripts/skill-size-check.sh`. That scope means it never lints `docs/research/examples/`
|
||||
reference skills. It is also shipped to external repos as `kyberforge-skill-size-check` (see
|
||||
[External consumers](#external-consumers-the-root-pre-commit-hooksyaml)).
|
||||
|
||||
### Two independent gate families, neither replaced the other
|
||||
|
||||
@@ -279,6 +281,81 @@ is needed: the `Kyberforge` styles are **committed** under
|
||||
`plugins/kyberforge/.apm/skills/{skill-audit,agent-audit}/assets/vale/styles/`, not downloaded
|
||||
packages (ADR-0014).
|
||||
|
||||
### Two copies, one canonical
|
||||
|
||||
Wiring Vale as a deterministic prefilter for `skill-audit`/`agent-audit`'s Description dimension
|
||||
(motivation: issue #84) is repo-specific, not part of the generic `lint` plugin, so it does not live
|
||||
in `plugins/lint/` — and per ADR-0014 it no longer lives at the repo root either. It lives **twice**,
|
||||
one copy per skill, both under `plugins/kyberforge/.apm/skills/`:
|
||||
|
||||
| Copy | Styles | `.vale.ini` sections |
|
||||
|---|---|---|
|
||||
| `agent-audit/assets/vale/` — **canonical** | `Kyberforge`, `KyberforgeCopilot` | `[**/agents/*.md]`, `[**/*.agent.md]` |
|
||||
| `skill-audit/assets/vale/` — smaller duplicate | `Kyberforge` | `[**/SKILL.md]` |
|
||||
|
||||
Duplicated rather than shared because a plugin's cache-install copies only each skill's own files —
|
||||
there is no cross-skill sharing to point at. `check-vale-style-sync` at pre-push is what keeps them
|
||||
from drifting; `KyberforgeCopilot` is the one deliberate inequality, being scoped only to `.agent.md`
|
||||
files for the Copilot-only "`Use proactively` has no effect" check.
|
||||
|
||||
### What Vale owns, and what stays LLM judgment
|
||||
|
||||
Eleven rule files across the two copies, six distinct rules:
|
||||
|
||||
| Rule | Vale scope | Bans | From |
|
||||
|---|---|---|---|
|
||||
| `Kyberforge.DescriptionOpener` | `text.frontmatter.description` | non-imperative openers ("This skill/agent…") | issue #84 |
|
||||
| `Kyberforge.VagueWording` | `text.frontmatter.description` | vague capability wording ("helps with", "utilize", …) | issue #84 |
|
||||
| `Kyberforge.PaddingPhrase` | `text` | generic "see `references/` for details" padding | issue #84 |
|
||||
| `KyberforgeCopilot.ProactivePhrase` | `text.frontmatter.description` | `Use proactively` (no effect in Copilot) | issue #84 |
|
||||
| `Kyberforge.SentenceOpenerThereIs` | `sentence` | "There is/are" sentence openers | ADR-0013 |
|
||||
| `Kyberforge.CompositionNote` | `text.frontmatter.description` | architecture and composition prose in a description | ADR-0020 |
|
||||
|
||||
Vale covers the **pattern-matchable** sub-checks named in issue #84 plus, per ADR-0013, one
|
||||
cherry-picked body-wide prose-pattern rule. Everything else stays LLM judgment: defaults-vs-menus,
|
||||
why-rationale, the non-pattern-matchable body-discipline calls, near-miss exclusion strength, and
|
||||
control calibration. New rules land directly in `styles/Kyberforge` and block immediately — there is
|
||||
no trial tier.
|
||||
|
||||
The cherry-pick record, so it is not re-litigated:
|
||||
|
||||
- `Kyberforge.SentenceOpenerThereIs` **landed** — 22 held-out hits, both in-corpus hits clean
|
||||
rewrites, zero suppressions needed.
|
||||
- `Kyberforge.VagueQualifier` was cherry-picked and then **deleted**. 2 hits across the corpus as it
|
||||
stood on 2026-08-08 (before the `.apm/` restructure): one marginal, and one unfixable false
|
||||
positive — `caveman/SKILL.md` quotes `of course` as an example of filler, a mention rather than a
|
||||
use — which forced the repo's only Vale suppression comments.
|
||||
- `governance.md` and `CONTROLS.md` were evaluated as rule sources and **excluded**: nothing
|
||||
prose-pattern-matchable to mine.
|
||||
|
||||
### Why every rule is `level: error`
|
||||
|
||||
Every alert is a FAIL, with no ignorable tier — same all-or-nothing model as shellcheck, the test
|
||||
suite, and conventional-pre-commit. Graded severities do not work here: **Vale's exit code keys on
|
||||
`error` alerts alone**, so a `warning` or `suggestion` rule exits 0, and pre-commit swallows a
|
||||
passing hook's output. Such a rule would be invisible and would block nothing.
|
||||
|
||||
`MinAlertLevel` and `--minAlertLevel` are correspondingly **absent** from both `.vale.ini` files and
|
||||
from the hook definitions. Under this model they are no-ops; adding one is not a missing knob.
|
||||
|
||||
The `verbose: true` escape hatch that makes `skill-size-check`'s SUGGESTION tier audible has no
|
||||
analogue here — Vale has no tier to make audible.
|
||||
|
||||
### External consumers: the root `.pre-commit-hooks.yaml`
|
||||
|
||||
The root `.pre-commit-hooks.yaml` exposes both Vale copies (`kyberforge-vale-audit-skill`,
|
||||
`kyberforge-vale-audit-agent`) plus `kyberforge-skill-size-check`, so any external repo can enforce
|
||||
the same rules with `repo: <this-repo-url>, rev: <tag>` in its own `.pre-commit-config.yaml`.
|
||||
pre-commit clones the pinned rev into its own cache, independent of whether Claude Code or the
|
||||
`kyberforge` plugin is installed at all; the same mechanism covers CI via `pre-commit run
|
||||
--all-files`. `skill-size-check` has no external asset dependency, so it needed no relocation under
|
||||
ADR-0014 — only exposure.
|
||||
|
||||
This repo's own `vale-audit-prefilter-skill` / `-agent` hooks consume the **identical**
|
||||
plugin-bundled copies via `repo: local`. Deliberately not a third root copy, and deliberately **not a
|
||||
pinned self-reference** — a pinned self-reference would lint working-tree edits against the last
|
||||
tagged release rather than against the change being made.
|
||||
|
||||
### Pre-commit
|
||||
|
||||
Two prefilter hooks, with `.apm/`-scoped `files:` patterns:
|
||||
@@ -292,6 +369,92 @@ Only the **authoring source** triggers them. A `SKILL.md` in the generated flat
|
||||
neither pattern, so prose findings surface only when you edit the file you are supposed to be
|
||||
editing. Without the binary the hooks fail with a bare "command not found" and no install pointer.
|
||||
|
||||
**Two hooks, not one combined hook.** Both manifests split the prefilter in two precisely because a
|
||||
single hook can point at only one copy, and that copy would silently 0-file-skip the other file
|
||||
shape (see [A 0-file Vale run is NOT RUN](#a-0-file-vale-run-is-not-run)).
|
||||
|
||||
### The `.vale.ini` globs do no scoping
|
||||
|
||||
Each `.vale.ini`'s section globs are **path-agnostic** — `[**/SKILL.md]` for skill-audit's copy,
|
||||
`[**/agents/*.md]` and `[**/*.agent.md]` for agent-audit's — and constrain filename *shape*, not
|
||||
location: Vale's `*` crosses `/`. A `SKILL.md` outside `plugins/` (a project-scope
|
||||
`.claude/skills/foo/SKILL.md`, say) still matches `[**/SKILL.md]` and gets linted normally.
|
||||
|
||||
All scoping therefore comes from the pre-commit hook's own `files:` regex and from the audit skills
|
||||
passing one explicit file per invocation. The two manifests scope **differently on purpose**:
|
||||
|
||||
| Manifest | `-skill` | `-agent` |
|
||||
|---|---|---|
|
||||
| `.pre-commit-config.yaml` (pins this repo's layout) | `^plugins/[^/]+/\.apm/skills/[^/]+/SKILL\.md$` | `^plugins/[^/]+/\.apm/agents/[^/]+\.agent\.md$` |
|
||||
| `.pre-commit-hooks.yaml` (layout-agnostic for consumers) | `(^\|/)SKILL\.md$` | `(^\|/)agents/[^/]+\.md$\|\.agent\.md$` |
|
||||
|
||||
Narrowing a `.vale.ini` glob to a `plugins/`-shaped path to "tighten" it breaks the consumer case,
|
||||
and `check-vale-style-sync`'s probe set is built to catch exactly that.
|
||||
|
||||
### `vale-wrap.sh`, never bare `vale`
|
||||
|
||||
Both audit skills' Step 1 and both pre-commit hooks call **each copy's own**
|
||||
`scripts/vale-wrap.sh`, not `vale`. It works around a confirmed **Vale 3.15.2** limitation:
|
||||
`text.frontmatter.description` silently stops matching on most — not all — multi-line descriptions.
|
||||
|
||||
Verified by reproduction on a deliberately-bad fixture, not assumed:
|
||||
|
||||
| Description scalar spanning 2+ lines | Vale's behaviour |
|
||||
|---|---|
|
||||
| `>` folded block | 0 alerts, exit 0 — **broken** |
|
||||
| plain (unquoted) continuation lines | 0 alerts, exit 0 — **broken** |
|
||||
| single- or double-quoted, wrapped | 0 alerts, exit 0 — **broken** |
|
||||
| `\|` literal block | alerts fire, exit 1 — lints normally |
|
||||
|
||||
The wrapper flattens the three broken forms to a single-line scalar in a scratch copy — or, for the
|
||||
rare value no inline scalar can spell verbatim, a `|-` block with one content line — padding with
|
||||
blank lines so **every other line number is unchanged**. `|` literal blocks and single-line
|
||||
descriptions pass through untouched. Most descriptions in this repo are `>` blocks, so before the
|
||||
wrapper a bad description in any of the three broken forms sailed straight through the prefilter.
|
||||
|
||||
### The `--config` argv defect
|
||||
|
||||
Handed **no `--config` at all**, the wrapper falls back to its own sibling `assets/vale/.vale.ini`,
|
||||
located from `${BASH_SOURCE[0]}` rather than from the cwd. That is why both manifests' `entry:` is
|
||||
now the bare script path with **no argument after it**.
|
||||
|
||||
pre-commit prefixes only `entry[0]` with the hook-repo clone path (`cmd = (prefix.path(cmd[0]),
|
||||
*cmd[1:])`), so every later argument resolves against the **consuming** repo's root. A `--config` in
|
||||
`.pre-commit-hooks.yaml` therefore pointed at a path no consumer has and hard-failed every external
|
||||
run with `E100 [--config] Runtime error`.
|
||||
|
||||
`.pre-commit-config.yaml` drops the argument too, deliberately keeping the two entries identical.
|
||||
The local `repo: local` hook resolved its `--config` correctly only because the consuming repo *was*
|
||||
this repo — and that divergence is why three review rounds exercised a path no external consumer
|
||||
takes and missed the defect. **Do not reintroduce a `--config` to either manifest to make the local
|
||||
run "explicit".**
|
||||
|
||||
An explicit `--config` from any other caller still wins, in all three argv forms (`--config X`,
|
||||
`--config=/abs`, `--config=rel`), and a relative one resolves against the caller's cwd — matching
|
||||
bare `vale`, not the repo root.
|
||||
|
||||
Both audit skills' Step 1 passes no `--config` either. Step 1 resolves the script relative to the
|
||||
skill's own directory so the call works from an installed plugin cache; a relative `--config`
|
||||
alongside it would resolve against the cwd instead, yielding `E100 Runtime error … does not exist`
|
||||
and exit 2 — which both skills' fallback misreads as "vale unavailable" and silently downgrades to
|
||||
full LLM judgment.
|
||||
|
||||
`tests/test-vale-wrap.sh` regression-tests this against **skill-audit's** copy specifically: its
|
||||
fixtures are all `SKILL.md`-shaped, and only skill-audit's `.vale.ini` carries that glob section.
|
||||
|
||||
### A 0-file Vale run is NOT RUN
|
||||
|
||||
Vale reports 0 files only when the path it is handed matches **no glob section at all** — a
|
||||
differently-named file, or a directory argument holding nothing that matches. That run prints
|
||||
|
||||
```
|
||||
✔ 0 errors ... in 0 files.
|
||||
```
|
||||
|
||||
and exits 0, indistinguishable from a clean pass. Both audits therefore treat a 0-file Vale run as
|
||||
**NOT RUN** and fall back to full LLM judgment rather than reporting the Description dimension
|
||||
clean.
|
||||
|
||||
### Pre-push
|
||||
|
||||
`vale` is a **pre-push** dependency too, not only pre-commit. `check-vale-style-sync` runs **six
|
||||
@@ -314,6 +477,16 @@ Use it only on a machine that genuinely cannot install `vale`, and read that lin
|
||||
was not checked", not as a pass. The hook is `verbose: true` for exactly that reason — its clean
|
||||
output is a single line, so it costs one line per push.
|
||||
|
||||
### Mentioning banned phrasing without tripping the rule
|
||||
|
||||
House convention: banned phrasing that must be **mentioned** rather than used goes in backticks or a
|
||||
fenced code block. Vale skips code spans and fences, so no suppression is needed — which is why this
|
||||
document quotes `Use proactively` and "There is/are" the way it does.
|
||||
|
||||
Inline `<!-- vale Rule = NO -->` is the fallback **only** where backticking is impossible. Use the
|
||||
HTML-comment form; the MDX `{/* */}` form does not work in plain Markdown. The one time a rule forced
|
||||
suppression comments, the rule was deleted instead (see the `VagueQualifier` entry above).
|
||||
|
||||
## Tests
|
||||
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user