Files
pbakaus_impeccable/site/content/reference/config.md
T
776c019041 Add inline, in-file ignore comments for the detector (#283) (#285)
* Add inline, in-file ignore comments for the detector (issue #283)

Complement config ignores with eslint-disable-style waivers that live where
they apply and travel with the file when it leaves the repo. The motivating
case is a generated/exported standalone document that legitimately uses a
first-party brand typeface (on the overused-font list) and is later scanned
without .impeccable/config.json present.

Marker is comment-syntax-agnostic (works in //, /* */, <!-- -->, #, {/* */}):

  impeccable-disable <rule>[, <rule>...] [-- reason | : reason]   whole file
  impeccable-disable-line <rule>...                               same line
  impeccable-disable-next-line <rule>...                          next line

Bare directive or * means every rule; reason is optional and discarded at
scan time. Behavior is suppression, for parity with config ignores.

Implementation:
- New pure module cli/engine/shared/inline-ignores.mjs (parser + filter, no
  Node deps). Static-HTML findings have no line number, so only whole-file
  directives apply there -- exactly the standalone-document case; the
  regex/text engine additionally honors the line-scoped forms.
- Wired into detectText and detectHtml, gated by options.inlineIgnores.
- detect CLI applies inline ignores by default; --no-inline-ignores skips
  just them, --no-config skips config and inline ignores together.

Docs: config.md (new section), detector.md, README. skill/reference/hooks.md
reversed its prior "inline comments are not supported" guidance and now points
the agent to inline waivers for the travels-with-the-file case. Changelog 3.x.

Tests: tests/inline-ignores.test.mjs (parser units, detectText/detectHtml
integration, CLI end-to-end), registered in the detector suite.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Reconcile design hook wording with inline ignores

Two hook-side fixes prompted by review of the new inline-ignore feature:

1. Clean-ack steer line. The old line ("Keep typography hierarchy, spacing
   rhythm, and color contrast intentional on the next change.") read as an
   odd non-sequitur after "No anti-patterns." Reworded the whole clean ack to
   say what it means: a clean scan only clears the deterministic rule set, not
   overall design quality, so keep following the design system and skill
   guidance. Now: "Design hook scanned X. No deterministic design-quality
   issues found. That does not mean the design is good: keep following the
   project design system and the impeccable skill guidance."

2. Directive footer. It still told the agent "Do not add source comments such
   as `impeccable: ignore`; those pollute the code and do not suppress hook
   findings." That is now misleading: the hook runs the same detector engine
   as the CLI, which honors inline `impeccable-disable` waivers, so they DO
   suppress hook findings (consistent with config ignores, which filterFindings
   already honors). Reworded to: don't silence a real finding to skip fixing
   it; suppress only after the user confirms intent; prefer a config ignore,
   and reach for an inline `impeccable-disable <rule>` comment only when the
   waiver must travel with a file that leaves the repo.

Added a hook test asserting an inline `impeccable-disable-line` comment makes
the hook scan the file clean (locks in the cross-cutting behavior), and updated
the clean-ack / footer assertions to the new wording.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Address review on inline-ignores parser

- Case-insensitive fast-path bail-out (Cursor): the cheap substring guard was
  lowercase-only while DIRECTIVE_RE has the `i` flag, so a mixed-case marker
  like `Impeccable-Disable` skipped parsing entirely and never suppressed.
  Switched the guard to `/impeccable-disable/i.test(...)`. Added a regression
  test.
- Removed the unreachable `-->` branch from TRAILING_CLOSER_RE (Greptile):
  `--+>` already matches `-->` and any longer dash run.
- Replaced the always-truthy lazy-match + `if (sep)` reason strip with an
  explicit first-separator slice (Greptile): clearer and drops the dead branch.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Align inline-ignore line numbering with the detector (CRLF/CR endings)

parseInlineIgnores split lines with /\r\n|\r|\n/, but detectText numbers lines
with split('\n'). On classic `\r`-only endings the two diverged, so a
disable-line / disable-next-line directive could key a different line than the
finding it should waive (Cursor review). Split on '\n' only, matching the
detector exactly; the directive regex already excludes '\r', so a trailing '\r'
on CRLF files is never captured into the rule list. Added a CRLF regression test
through the real detectText.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 21:41:36 +09:00

149 lines
5.9 KiB
Markdown

---
title: Config and ignores
tagline: "Project settings for detector exceptions, hook behavior, and local overrides."
description: "Use .impeccable config for confirmed detector exceptions and runtime settings. Keep product and design intent in PRODUCT.md and DESIGN.md."
section: concepts
order: 2
---
Impeccable stores runtime settings under `.impeccable/`. Most users do not need to hand-edit those files. Use the CLI when you want to record a confirmed exception.
Use config for:
- detector ignores shared by `npx impeccable detect` and the design hook;
- private local ignores that should not be committed;
- hook lifecycle settings such as enabled, quiet mode, and audit logging.
Use `PRODUCT.md` and `DESIGN.md` for product and design intent. See [Design Context](/docs/context).
## The usual path
List the current ignores:
```bash
npx impeccable ignores list
```
Add the narrowest exception that matches the real reason:
```bash
npx impeccable ignores add-value design-system-color "#ff00aa" --reason "Campaign accent"
npx impeccable ignores add-file "src/legacy/**"
npx impeccable ignores add-rule side-tab
```
Remove an exception when the underlying code is fixed:
```bash
npx impeccable ignores remove-value design-system-color "#ff00aa"
```
The same detector config is used by the CLI and the hook, so an ignore behaves consistently in both places.
## Shared or local
Default ignores go into `.impeccable/config.json`. Commit them when they represent team intent: a legacy folder, a confirmed brand exception, or a project-wide rule decision.
Use `--local` for private work:
```bash
npx impeccable ignores add-file "src/private-experiment/**" --local
```
Local settings go into `.impeccable/config.local.json`, which Impeccable keeps out of git.
## Value ignores
Prefer value ignores when a rule reports a specific value:
```bash
npx impeccable ignores add-value overused-font Inter --reason "Brand font"
```
Fonts, colors, radii, and motion values should usually be suppressed by value, not by whole rule. That keeps the rule useful everywhere else.
Wildcard value ignores are allowed only when scoped to a file:
```bash
npx impeccable ignores add-value design-system-color "*" --file "src/demo.css"
```
That keeps one intentionally experimental file from teaching the whole project that every undocumented color is acceptable.
## Inline ignore comments
Config ignores live in `.impeccable/config.json`, which is the right home for repo-wide policy. They do not follow a file out of the repo, though. When a waiver belongs to one file and needs to travel with it (a generated or exported standalone document, an emailed HTML file, a snippet scanned out of context), put the waiver in the file itself:
```html
<!-- impeccable-disable overused-font: exported brand doc, font is first-party -->
```
The directive is comment-syntax-agnostic, so the same marker works in `//`, `/* */`, `<!-- -->`, `#`, and `{/* */}` comments across HTML, CSS, JSX, TSX, Vue, and Svelte. Three scopes are available:
```css
/* impeccable-disable overused-font */ /* whole file */
.brand { font-family: Inter } /* impeccable-disable-line overused-font */
/* impeccable-disable-next-line bounce-easing */
```
List one or more rule ids, comma-separated, or omit them (or use `*`) for every rule. A reason after `:` or `--` is optional and recommended; it is for the diff, and the scanner discards it. Like config ignores, a matched directive suppresses the finding.
Static HTML findings have no line number, so only whole-file `impeccable-disable` applies to them. That is the standalone-document case this exists for. The line-scoped forms apply to CSS, JSX, TSX, Vue, and Svelte, where findings carry a line.
Inline directives apply by default. `--no-inline-ignores` turns them off for one run while keeping config ignores; `--no-config` turns off config and inline ignores together.
## Details when the default path is not enough
<details class="docs-prose-details">
<summary>What the config file looks like</summary>
<div>
<p>The shared config lives at <code>.impeccable/config.json</code>. A typical file looks like this:</p>
<pre><code>{
"detector": {
"ignoreRules": [],
"ignoreFiles": [],
"ignoreValues": [],
"designSystem": {
"enabled": true
}
},
"hook": {
"enabled": true,
"quiet": false,
"auditLog": ".impeccable/hook.ndjson"
}
}</code></pre>
<p>The <code>detector</code> section is shared by manual scans and hooks. The <code>hook</code> section only controls automatic hook execution and hook output.</p>
</div>
</details>
<details class="docs-prose-details">
<summary>Disable design-system checks</summary>
<div>
<p>Design-aware rules run when <code>DESIGN.md</code> exists. Disable them for the project only when the design file is intentionally not authoritative yet:</p>
<pre><code>{
"detector": {
"designSystem": {
"enabled": false
}
}
}</code></pre>
<p>For one manual run, keep config but skip the design-system rules:</p>
<pre><code>npx impeccable detect --no-design-system src/</code></pre>
<p>Use <code>--no-config</code> only when you want a raw scan with no project ignores and no <code>DESIGN.md</code> context.</p>
</div>
</details>
<details class="docs-prose-details">
<summary>Hook runtime settings</summary>
<div>
<p>Use <code>/impeccable hooks</code> for normal lifecycle changes:</p>
<pre><code>/impeccable hooks status
/impeccable hooks on
/impeccable hooks off</code></pre>
<p><code>hook.quiet: true</code> suppresses clean and pending acknowledgements while still surfacing new findings.</p>
<p><code>hook.auditLog</code> writes one NDJSON line per hook invocation for debugging. Leave it off during normal work.</p>
<p>Environment variables still override config for one shell: <code>IMPECCABLE_HOOK_DISABLED</code>, <code>IMPECCABLE_HOOK_QUIET</code>, and <code>IMPECCABLE_HOOK_LOG</code>.</p>
</div>
</details>