mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-14 23:26:39 +03:00
* Allow context roots to be declared in .impeccable/config.json Monorepo detection previously read workspace roots only from package managers (package.json workspaces, pnpm-workspace.yaml, lerna.json), coupling "where design context lives" to the dependency graph. Add a `contextRoots` glob list to .impeccable/config.json / config.local.json so non-JS repos -- and design-context boundaries that don't match packages -- can declare nested PRODUCT.md/DESIGN.md roots directly. The new source is folded into readWorkspacePatterns(), so detection, project resolution, and the app picker pick it up unchanged. Negation and config.local.json extension work for free. * Define projectRoots composition with package workspaces Address review feedback on #307: - Rename the config key contextRoots -> projectRoots: the globs establish project boundaries and app-picker targets, not just where context files live. - Make cross-source precedence explicit: a path matched by any impeccable pattern, positive or negated, is governed by the impeccable group alone; package-manager patterns fill in the paths it does not match, and `!` negations apply only within their own source. readWorkspacePatterns() becomes readProjectPatternGroups() / readProjectPatterns(), with package workspaces as one discovery source. - Drop app-picker candidates that would resolve elsewhere: a package workspace subsumed by a broader impeccable boundary is no longer listed, since choosing it would silently resolve to that boundary. - Add five composition tests and document the key in the config and context reference pages (path relativity, glob and negation syntax, shared/local merge, precedence).
168 lines
7.2 KiB
Markdown
168 lines
7.2 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;
|
|
- project roots, for repos where design boundaries are not declared by a package manager.
|
|
|
|
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.
|
|
|
|
## Project Roots
|
|
|
|
Impeccable normally finds nested projects through package-manager workspace declarations: `package.json` workspaces, `pnpm-workspace.yaml`, or `lerna.json`. When those files do not exist, or when design boundaries do not line up with packages, declare the roots directly:
|
|
|
|
```json
|
|
{
|
|
"projectRoots": ["docs/design/skins/*"]
|
|
}
|
|
```
|
|
|
|
Each matched folder becomes its own project: it can carry its own `PRODUCT.md` and `DESIGN.md`, it appears in the app picker, and it falls back to the repo root per file for any context it does not define. See [Design Context](/docs/context).
|
|
|
|
How the patterns behave:
|
|
|
|
- Patterns are relative to the repo root and use the same glob syntax as `package.json` workspaces, including `*`, `**`, and `!` negation.
|
|
- `projectRoots` in `config.local.json` extends the shared list, so one developer can add private roots without committing them.
|
|
- A path matched by any `projectRoots` pattern, positive or negated, is governed by this config alone. Package-manager workspaces apply only to paths these patterns do not match, and each source's `!` negations apply only to its own patterns. So `"!apps/internal"` here hides a package workspace from Impeccable, while a package-level negation never hides a folder that `projectRoots` declares.
|
|
|
|
## 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>
|