# Kill AI Slop Documentation

> Technical docs for the kill-ai-slop agent skill, dependency-free project scanner, shared slop taxonomy, and Astro field-guide site. For engineers scanning web projects, remediating machine-default UI, or extending the catalogue and demos.

## Context Links

- [Agent index](https://grok-wiki.com/public/docs/yetone-kill-ai-slop-c0d8c9670cbb/llms.txt)
- [Human interactive docs](https://grok-wiki.com/public/docs/yetone-kill-ai-slop-c0d8c9670cbb)
- [GitHub repository](https://github.com/yetone/kill-ai-slop)

## Repository Metadata

- Repository: yetone/kill-ai-slop

- Generated: 2026-07-11T08:26:28.683Z
- Updated: 2026-07-11T08:27:01.780Z
- Runtime: Grok CLI
- Format: Documentation
- Pages: 18

## Page Index

- 01. [Overview](https://grok-wiki.com/public/docs/yetone-kill-ai-slop-c0d8c9670cbb/pages/01-overview.md) - What Kill AI Slop exposes: the agent skill, scanner entry points, shared catalogue, and field-guide site, plus who should use which surface first.
- 02. [Installation](https://grok-wiki.com/public/docs/yetone-kill-ai-slop-c0d8c9670cbb/pages/02-installation.md) - Install the kill-ai-slop skill via npx or manual copy, and set up the Astro website dependencies for local development.
- 03. [Quickstart](https://grok-wiki.com/public/docs/yetone-kill-ai-slop-c0d8c9670cbb/pages/03-quickstart.md) - Shortest path to a first scanner report and a local field-guide run, with expected success signals and one recovery note each.
- 04. [Slop taxonomy](https://grok-wiki.com/public/docs/yetone-kill-ai-slop-c0d8c9670cbb/pages/04-slop-taxonomy.md) - Repo-specific model of AI-slop tells: categories, named signals, and how the field guide and skill share the same taxonomy language.
- 05. [Catalogue model](https://grok-wiki.com/public/docs/yetone-kill-ai-slop-c0d8c9670cbb/pages/05-catalogue-model.md) - How catalogue.ts is the single source of truth for tells, how demos and i18n attach, and boundaries between site data and skill references.
- 06. [Skill workflow](https://grok-wiki.com/public/docs/yetone-kill-ai-slop-c0d8c9670cbb/pages/06-skill-workflow.md) - Agent skill lifecycle: scan, triage, report, then propose or apply fixes without silent file edits from the standalone scanner.
- 07. [Use the agent skill](https://grok-wiki.com/public/docs/yetone-kill-ai-slop-c0d8c9670cbb/pages/07-use-the-agent-skill.md) - Invoke kill-ai-slop inside a coding agent after install: prompts, expected host behavior, and how the skill uses references and the scanner.
- 08. [Scan a web project](https://grok-wiki.com/public/docs/yetone-kill-ai-slop-c0d8c9670cbb/pages/08-scan-a-web-project.md) - Point the dependency-free scanner at a project path, interpret grouped vs JSON reports, and verify findings against detection rules.
- 09. [Apply clean fixes](https://grok-wiki.com/public/docs/yetone-kill-ai-slop-c0d8c9670cbb/pages/09-apply-clean-fixes.md) - Map scanner hits to remediation steps from the fixes playbook, choose propose vs apply in an agent host, and confirm the clean alternative.
- 10. [Run the field guide site](https://grok-wiki.com/public/docs/yetone-kill-ai-slop-c0d8c9670cbb/pages/10-run-the-field-guide-site.md) - Develop and preview the multilingual Astro field guide: install, dev server, static build output, and how entries and demos render on the index.
- 11. [Extend the catalogue](https://grok-wiki.com/public/docs/yetone-kill-ai-slop-c0d8c9670cbb/pages/11-extend-the-catalogue.md) - Add or update a tell: catalogue entry, i18n strings, plain-HTML demo, and alignment with skill taxonomy, detection, and fix references.
- 12. [Scanner CLI reference](https://grok-wiki.com/public/docs/yetone-kill-ai-slop-c0d8c9670cbb/pages/12-scanner-cli-reference.md) - Invocation, path argument, --json mode, walk/scan behavior, console formatting helpers, and hard constraint that the scanner never edits files.
- 13. [Detection patterns](https://grok-wiki.com/public/docs/yetone-kill-ai-slop-c0d8c9670cbb/pages/13-detection-patterns.md) - Code-level signals the skill and scanner look for per tell: patterns, match targets, and how findings map back to taxonomy ids.
- 14. [Remediation playbook](https://grok-wiki.com/public/docs/yetone-kill-ai-slop-c0d8c9670cbb/pages/14-remediation-playbook.md) - Per-tell clean fixes, what to remove or replace, and how before or after demos illustrate the preferred outcome.
- 15. [Catalogue and demos data](https://grok-wiki.com/public/docs/yetone-kill-ai-slop-c0d8c9670cbb/pages/15-catalogue-and-demos-data.md) - Fields and shapes in catalogue.ts, catalogue.i18n.ts, and demos.ts: tell ids, copy locales, and demo HTML payloads used by site components.
- 16. [Design tokens](https://grok-wiki.com/public/docs/yetone-kill-ai-slop-c0d8c9670cbb/pages/16-design-tokens.md) - Site self-constraints in tokens and global styles: paper and ink palette, single editorial red, hierarchy rules, and banned slop defaults.
- 17. [Build and deploy](https://grok-wiki.com/public/docs/yetone-kill-ai-slop-c0d8c9670cbb/pages/17-build-and-deploy.md) - Static site build to dist, deploy-anywhere assumptions, and operational notes for the zero-JS-by-default Astro field guide.
- 18. [Contributing](https://grok-wiki.com/public/docs/yetone-kill-ai-slop-c0d8c9670cbb/pages/18-contributing.md) - Where to change skill references, scanner logic, catalogue data, or site components while keeping skill and website taxonomy aligned.

## Source File Index

- `README.md`
- `skill/README.md`
- `skill/references/detection.md`
- `skill/references/fixes.md`
- `skill/references/taxonomy.md`
- `skill/scripts/scan.mjs`
- `skill/SKILL.md`
- `website/astro.config.mjs`
- `website/src/components/BeforeAfter.astro`
- `website/src/components/LangToggle.astro`
- `website/src/components/SlopEntry.astro`
- `website/src/components/T.astro`
- `website/src/components/ThemeToggle.astro`
- `website/src/data/catalogue.i18n.ts`
- `website/src/data/catalogue.ts`
- `website/src/data/demos.ts`
- `website/src/layouts/Base.astro`
- `website/src/pages/index.astro`
- `website/src/styles/demos.css`
- `website/src/styles/global.css`
- `website/src/styles/tokens.css`

---

## 01. Overview

> What Kill AI Slop exposes: the agent skill, scanner entry points, shared catalogue, and field-guide site, plus who should use which surface first.

- Page Markdown: https://grok-wiki.com/public/docs/yetone-kill-ai-slop-c0d8c9670cbb/pages/01-overview.md
- Generated: 2026-07-11T08:24:27.902Z

### Source Files

- `README.md`
- `skill/SKILL.md`
- `skill/scripts/scan.mjs`
- `website/src/data/catalogue.ts`
- `website/src/pages/index.astro`

---
title: "Overview"
description: "What Kill AI Slop exposes: the agent skill, scanner entry points, shared catalogue, and field-guide site, plus who should use which surface first."
---

**Kill AI Slop** (`yetone/kill-ai-slop`) is a two-surface repo: a static multilingual Astro field guide under `website/`, and a portable agent skill under `skill/` (`name: kill-ai-slop`) with a dependency-free scanner at `skill/scripts/scan.mjs`. Both surfaces share one 23-tell taxonomy; the website catalogue at `website/src/data/catalogue.ts` is the documented single source of truth the skill enforces.

## Product surfaces

| Surface | Path | Role | Edits project files? |
| --- | --- | --- | --- |
| Field guide site | `website/` | Multilingual catalogue (en/zh/ja/ko), before→after HTML demos, principles | No |
| Agent skill | `skill/SKILL.md` + `skill/references/` | Scan → triage → report → propose/apply fixes in a coding-agent host | Only when the host applies fixes after the report |
| Scanner CLI | `skill/scripts/scan.mjs` | Greps frontend source for code-level signals; grouped or JSON report | **Never** |

```mermaid
flowchart TB
  subgraph repo["yetone/kill-ai-slop"]
    subgraph site["website/"]
      cat["src/data/catalogue.ts\n23 tells · tier · group · detect · demo"]
      index["src/pages/index.astro\nfield guide UI"]
      tokens["src/styles/tokens.css\npaper + ink self-rules"]
    end
    subgraph skillPack["skill/"]
      skillmd["SKILL.md\nworkflow + guardrails"]
      refs["references/\ntaxonomy · detection · fixes"]
      scan["scripts/scan.mjs\nTELS[] patterns"]
    end
  end
  cat -->|"taxonomy / detect chips"| index
  cat -->|"spec the skill enforces"| skillmd
  skillmd --> refs
  skillmd -->|"run for leads"| scan
  scan -->|"file:line hits only"| skillmd
```

Live field guide: [killaislop.com](https://killaislop.com).

## Who should use which surface first

| Goal | Start here | Then |
| --- | --- | --- |
| Learn what each tell looks like and the clean alternative | Field guide (`website/`, or killaislop.com) | Scan a real project |
| Clean a vibe-coded UI/docs project with an agent | Install skill → invoke with “kill the AI slop in this project” | Host runs scanner, triage, report, then fix |
| Get a machine-readable hit map without an agent | `node skill/scripts/scan.mjs <root> [--json]` | Confirm hits by reading code; map to fixes |
| Add or change a tell | Update catalogue entry (+ i18n/demo as needed) and keep skill refs/scanner aligned | See extend-catalogue and contributing pages |

<Info>
The standalone scanner never edits files. Mass edits happen only in an agent host after the user has seen the report and approved groups to apply (`skill/SKILL.md` workflow).
</Info>

## Repo layout

```
website/   Astro site — field guide (multilingual, static, zero-JS-by-default)
skill/     kill-ai-slop Agent Skill (SKILL.md + references + scanner)
```

### Website (`website/`)

- Stack: Astro, static build to `dist/`, deploy anywhere.
- Local:

```bash
cd website
npm install
npm run dev        # http://localhost:4321
npm run build      # → dist/
```

- Design self-constraints (README): paper + ink, **one** editorial red, hierarchy from scale and space, hairline rules; no gradients / emoji / glass / badges. Rules live in `website/src/styles/tokens.css`.
- Index (`website/src/pages/index.astro`) loads `catalogue` and renders each entry via `SlopEntry`; sections include definition, catalogue (23 tells), and six principles.

### Skill (`skill/`)

- Skill id: `kill-ai-slop`.
- Host install (universal):

```
npx skills add yetone/kill-ai-slop
```

- Manual: copy `skill/` contents into the agent’s `kill-ai-slop/` skills directory (see repo README / `skill/README.md` for host-specific paths).
- Works on HTML/CSS, React/Vue/Svelte/Astro, Tailwind, and Markdown copy (skill description).
- Provider-neutral: the skill is files on disk (SKILL.md + references + scanner). Any Agent-Skills-compatible host can load it; no model-provider or hosted connector is required.

### Scanner (`skill/scripts/scan.mjs`)

```bash
node skill/scripts/scan.mjs path/to/project          # grouped report
node skill/scripts/scan.mjs path/to/project --json    # machine-readable
```

| CLI | Behavior |
| --- | --- |
| `[root]` | Project root; default `.` |
| `--json` | Machine-readable output for triage |
| `--no-color` | Disable ANSI color (also off when not a TTY or when `--json`) |

Constraints from the scanner header and skill workflow:

- Pure Node (`node:fs` / `node:path` only); no package dependencies.
- **Never edits files.** Hits are leads to confirm by reading code, not verdicts.
- Walks frontend extensions (`.html`, `.css`, `.scss`, `.sass`, `.less`, `.tsx`/`.jsx`/`.ts`/`.js`/`.mjs`/`.cjs`, `.vue`, `.svelte`, `.astro`, `.md`, `.mdx`, plus `tailwind.config.*`).
- Skips dirs such as `node_modules`, `.git`, `dist`, `build`, `out`, `.next`, `.astro`, coverage, vendor, lockfiles, minified `*.min.js|css`, and files larger than 512 KiB.

## Shared taxonomy: 23 tells

Both the site and the skill operate on **23** AI-slop tells.

### Catalogue model (`website/src/data/catalogue.ts`)

Documented as the single source of truth for the website and the spec the skill enforces.

| Field | Type / notes |
| --- | --- |
| `id` | String slug (e.g. `indigo-violet-gradient`) |
| `n` | Position number (auto from array order) |
| `tier` | `1` classic · `2` evolved |
| `group` | `color` \| `type` \| `copy` \| `component` \| `layout` \| `evolved` |
| `title` / `what` / `why` / `fix` | Localized `Bi` (`en` required; `zh` inline; `ja`/`ko` optional, merged from `catalogue.i18n.ts`) |
| `detect` | Code-level signal chips shared with skill heuristics |
| `demo?` | Key into demo HTML / before→after data |

### Scanner tell table (`skill/scripts/scan.mjs` `TELLS`)

Numeric ids `01`–`23`, with `group`, human `name`, one-line `fix`, and regex `patterns`. Some tells set `copy: true` so they also scan prose files.

| Group | Scanner examples (id · name) |
| --- | --- |
| `color` | `01` indigo→violet gradient · `02` gradient-clip headline · `03` warm cozy palette · `04` default semantic palette · `05` one-hue status box · `06` gradients as atmosphere |
| `type` | `07` serif-italic emphasis · `08` serif where sans belongs · `09` decorative strikes & highlights |
| `copy` | `10` highlighted keywords · `11` AI copywriting voice · `12` emoji everywhere |
| `component` | `13`–`21` (glowing status dot, left-border callout, pastel icon tiles, max-radius/glass, shadows, nested corners, badge spam, AI SVG icon, icon-in-tint) |
| `layout` | `22` all-caps card grid |
| `evolved` | `23` tasteful-terminal |

<Note>
Catalogue string ids and scanner numeric ids describe the same 23-tell set; keep names, groups, and detect patterns aligned when extending the catalogue.
</Note>

## Agent skill lifecycle

From `skill/SKILL.md` — run in order; do not mass-edit before the user sees the report.

```mermaid
stateDiagram-v2
  [*] --> Scope
  Scope --> Scan: confirm roots; skip build artifacts
  Scan --> Triage: scan.mjs hits as map
  Triage --> Report: slop vs intentional
  Report --> Fix: user picks groups / all
  Fix --> Scan: re-run; count should drop
  Report --> [*]: user stops without apply
```

1. **Scope** — Default app/site source; skip `node_modules`, `dist`, `build`, `.git`, vendor, lockfiles, minified files. Ask if multiple apps are mixed.
2. **Scan** — `node scripts/scan.mjs <root>` or `--json`.
3. **Triage** — Open each hit; keep deliberate brand/authorship; flag machine defaults. Use `references/taxonomy.md` and `references/detection.md`.
4. **Report** — Grouped summary before any write: tell, `file:line`, why, proposed fix. Ask which groups to apply.
5. **Fix** — Minimal change via `references/fixes.md`; prefer shared tokens/components; no new brand colors without user confirm; re-scan after.

### Guardrails

- Respect authorship; ask when unsure.
- Small reviewable diffs; never `git add -A`.
- No new dependencies to do the work.
- Visual check when a dev server exists; a clean scan ≠ a better page.

### Skill references

| Path | Contents |
| --- | --- |
| `references/taxonomy.md` | 23 tells: what, why slop, fix |
| `references/detection.md` | ripgrep/regex patterns + false positives |
| `references/fixes.md` | before→after remediation patterns |
| `scripts/scan.mjs` | Dependency-free scanner |

## Field guide content model

Index sections (from `index.astro`):

| Section | Purpose |
| --- | --- |
| Hero | Positioning + CTAs to `#catalogue` and `#skill` |
| Definition | What “AI slop” means in this project |
| Catalogue | 23 entries; classic vs evolved legend; before→after demos |
| Principles | Six anti-slop rules (same spine as skill principles) |

### Six principles (site + skill)

1. Decide before you decorate  
2. One accent, one voice  
3. Hierarchy from scale and space  
4. Subtract first  
5. Specific beats loud / punchy (copy)  
6. Decoration must mean something  

Demos are plain-HTML rebuilds for education, not screenshots of specific products (catalogue comments + README).

## Constraints and non-goals

| Constraint | Surface |
| --- | --- |
| Scanner never edits files | `scan.mjs` |
| Agent must report before mass fix | `SKILL.md` workflow |
| Zero-JS-by-default static site | `website/` README |
| Design system bans the tells it documents | `tokens.css` + site itself |
| Skill adds no new npm deps for cleanup | Guardrails |
| Hits are not automatic truth | Scanner + triage |

Out of scope for this overview: full CLI flag reference, per-tell regex lists, remediation playbooks, catalogue field schemas, and install variants — those are separate docs pages.

## Next

<CardGroup>
  <Card title="Installation" href="/installation">
    Install the skill via npx or manual copy; set up website dependencies.
  </Card>
  <Card title="Quickstart" href="/quickstart">
    First scanner report and local field-guide run with success signals.
  </Card>
  <Card title="Slop taxonomy" href="/slop-taxonomy">
    Categories, named signals, and shared language across site and skill.
  </Card>
  <Card title="Catalogue model" href="/catalogue-model">
    How catalogue.ts is the single source of truth and how demos/i18n attach.
  </Card>
  <Card title="Skill workflow" href="/skill-workflow">
    Scan → triage → report → propose/apply without silent scanner edits.
  </Card>
  <Card title="Scanner CLI reference" href="/scanner-cli-reference">
    Invocation, --json, walk behavior, and the no-edit hard constraint.
  </Card>
</CardGroup>

---

## 02. Installation

> Install the kill-ai-slop skill via npx or manual copy, and set up the Astro website dependencies for local development.

- Page Markdown: https://grok-wiki.com/public/docs/yetone-kill-ai-slop-c0d8c9670cbb/pages/02-installation.md
- Generated: 2026-07-11T08:24:13.292Z

### Source Files

- `README.md`
- `skill/README.md`
- `skill/SKILL.md`
- `website/astro.config.mjs`

---
title: "Installation"
description: "Install the kill-ai-slop skill via npx or manual copy, and set up the Astro website dependencies for local development."
---

Kill AI Slop ships two installable surfaces from the same repository: the `kill-ai-slop` Agent Skill under `skill/` (SKILL.md, references, and a dependency-free scanner), and the multilingual Astro field guide under `website/`. Skill install is a directory copy into an agent skills root; the website is a normal `npm install` under `website/`.

## What you install

| Surface | Path | Requires packages | Purpose after install |
|---|---|---|---|
| Agent skill | `skill/` → host skills dir as `kill-ai-slop/` | No | Agent-driven scan → triage → report → fix |
| Standalone scanner | `skill/scripts/scan.mjs` | No (pure Node) | Read-only grouped or JSON report |
| Field guide site | `website/` | Yes (`npm install`) | Local dev at `http://localhost:4321`, static build to `dist/` |

```
website/   Astro site (multilingual, static, zero-JS-by-default)
skill/     kill-ai-slop Agent Skill (SKILL.md + references + scanner)
```

The skill is self-contained: copy the whole directory; there is no package install and no build step for the skill itself.

## Prerequisites

| Task | Runtime |
|---|---|
| Universal skill installer | `npx` (Node) |
| Manual skill copy | `git` + shell (or any copy tool) |
| Standalone scanner | Node only |
| Website local run / build | Node + npm under `website/` |

No model provider, API key, or hosted connector is required for install. Agent hosts (for example Claude Code) only need their own skills directory layout.

## Install the agent skill

Choose one path. Destination folder name must be `kill-ai-slop`.

### Option A — Universal agent installer

```bash
npx skills add yetone/kill-ai-slop
```

Follow the installer prompt for the target coding agent.

### Option B — Ask the agent to install

Paste into the coding agent (Claude Code, Cursor, or another Agent Skills host):

```
Install the kill-ai-slop skill from
https://github.com/yetone/kill-ai-slop/tree/main/skill

Copy everything in that directory into a kill-ai-slop/ folder
inside your agent's skills directory, then confirm it's registered.
```

The host should read `SKILL.md`, place the directory, and register the skill. You do not need to name individual files; the agent copies the directory as-is.

### Option C — Manual clone and copy

```bash
git clone https://github.com/yetone/kill-ai-slop

# Claude Code examples — swap the destination for other agents
cp -r kill-ai-slop/skill ~/your-project/.claude/skills/kill-ai-slop   # this project only
cp -r kill-ai-slop/skill ~/.claude/skills/kill-ai-slop                # every project
```

Copy the **entire** `skill` directory. Do not flatten or omit `references/` or `scripts/`.

| Host example | Project-scoped skills | User-global skills |
|---|---|---|
| Claude Code | `<project>/.claude/skills/kill-ai-slop` | `~/.claude/skills/kill-ai-slop` |

Other agents use their own skills root; keep the folder name `kill-ai-slop`.

### Skill layout after install

| Path | Role |
|---|---|
| `SKILL.md` | Skill name, description, workflow, guardrails |
| `references/taxonomy.md` | 23 tells: definition, why it reads as slop, fix direction |
| `references/detection.md` | Code patterns per tell and common false positives |
| `references/fixes.md` | Before→after remediation patterns |
| `scripts/scan.mjs` | Dependency-free scanner |

Skill frontmatter identity:

| Field | Value |
|---|---|
| `name` | `kill-ai-slop` |
| Triggers (examples) | “kill AI slop”, “de-slop”, “remove the AI look”, “make this not look AI-generated” |

### Verify the skill

1. Confirm the host lists or loads `kill-ai-slop`.
2. Confirm the directory contains `SKILL.md`, `references/`, and `scripts/scan.mjs`.
3. Invoke with a plain request such as:

   > Kill the AI slop in this project.

   Also accepted: “de-slop this”, “remove the AI look”, “make this not look AI-generated”.

Expected host behavior after install: **scan** → **triage** (slop vs intentional) → **report** grouped summary **before** edits → **fix** only approved groups. The standalone scanner never edits files; file changes come only from the agent workflow when you approve them.

## Install website dependencies (local field guide)

Live site: [killaislop.com](https://killaislop.com). For a local copy:

```bash
cd website
npm install
npm run dev        # http://localhost:4321
npm run build      # → dist/  (static, deploy anywhere)
```

| Command | Result |
|---|---|
| `npm install` | Install website dependencies in `website/` |
| `npm run dev` | Dev server at `http://localhost:4321` |
| `npm run build` | Static output under `website/dist/` |

Astro config (`website/astro.config.mjs`):

| Key | Value | Notes |
|---|---|---|
| `site` | `https://killaislop.com` | Canonical site URL |
| `build.inlineStylesheets` | `'auto'` | Stylesheet inlining policy |
| Integrations | none | Single static, dependency-light content site by design |

Success signals:

- Dev: field guide serves on `http://localhost:4321`.
- Build: `dist/` is produced and is static (deploy-anywhere artifact).

## Run the scanner without the agent skill

You can point the scanner at any web project path. It is pure Node, has no dependencies, and never edits files.

From the repository root:

```bash
node skill/scripts/scan.mjs path/to/project          # grouped report
node skill/scripts/scan.mjs path/to/project --json    # machine-readable
```

From inside the installed skill directory (or `skill/`):

```bash
node scripts/scan.mjs path/to/src          # human-readable report
node scripts/scan.mjs path/to/src --json   # machine-readable
```

| Mode | Flag | Output use |
|---|---|---|
| Human-readable | (default) | Grouped `file:line` hits for review |
| Machine-readable | `--json` | Triage / tooling |

Treat hits as leads to confirm by reading code, not automatic verdicts.

## Constraints

- Skill install = full directory copy as `kill-ai-slop/`; no skill packages, no skill build.
- Scanner: read-only; no file writes.
- Website: install and run only under `website/`; skill and site installs are independent.
- No new dependencies are required to *use* the skill workflow on a target project (skill guardrail).

## Troubleshooting

| Symptom | Check |
|---|---|
| Agent does not pick up the skill | Folder name is `kill-ai-slop`; path is the host’s skills directory (e.g. `.claude/skills/` or `~/.claude/skills/`); `SKILL.md` is present at the skill root. |
| Incomplete skill (missing taxonomy / scanner) | Entire `skill/` tree was copied, including `references/` and `scripts/`. |
| `npx skills add` fails | Node/`npx` available; network can reach the package/skills registry and `yetone/kill-ai-slop`. Fall back to Option B or C. |
| `npm run dev` / `npm run build` fails | Commands run from `website/` after `npm install`. |
| Scanner path wrong | From repo root use `skill/scripts/scan.mjs`; from skill root use `scripts/scan.mjs`. |

## Next

<CardGroup>
  <Card title="Quickstart" href="/quickstart">
    Shortest path to a first scanner report and a local field-guide run.
  </Card>
  <Card title="Use the agent skill" href="/use-agent-skill">
    Prompts, host behavior, and how the skill uses references and the scanner after install.
  </Card>
  <Card title="Scan a web project" href="/scan-web-project">
    Point the dependency-free scanner at a path and read grouped vs JSON reports.
  </Card>
  <Card title="Run the field guide site" href="/run-field-guide-site">
    Dev server, static build output, and how catalogue entries render on the index.
  </Card>
  <Card title="Skill workflow" href="/skill-workflow">
    Scan, triage, report, then propose or apply fixes without silent scanner edits.
  </Card>
  <Card title="Scanner CLI reference" href="/scanner-cli-reference">
    Invocation, path argument, `--json`, and the no-edit constraint.
  </Card>
</CardGroup>

---

## 03. Quickstart

> Shortest path to a first scanner report and a local field-guide run, with expected success signals and one recovery note each.

- Page Markdown: https://grok-wiki.com/public/docs/yetone-kill-ai-slop-c0d8c9670cbb/pages/03-quickstart.md
- Generated: 2026-07-11T08:24:14.025Z

### Source Files

- `README.md`
- `skill/scripts/scan.mjs`
- `skill/README.md`
- `website/astro.config.mjs`
- `website/src/pages/index.astro`

---
title: "Quickstart"
description: "Shortest path to a first scanner report and a local field-guide run, with expected success signals and one recovery note each."
---

`kill-ai-slop` has two independent first-run surfaces: the dependency-free scanner at `skill/scripts/scan.mjs` (read-only `file:line` report, never edits), and the Astro field guide under `website/` (`npm run dev` → `http://localhost:4321`). Neither path requires the other; both share the same 23-tell catalogue language as the agent skill.

## Prerequisites

| Surface | Need |
| --- | --- |
| Scanner | Node.js (run `node` on `scan.mjs`); a local path to a web project |
| Field guide | Node + npm; clone or checkout of this repo |

Optional later: install the `kill-ai-slop` Agent Skill via `npx skills add yetone/kill-ai-slop` or by copying `skill/` into your agent’s skills directory. The skill is not required for the two runs below.

## A. First scanner report

The scanner walks frontend-ish sources under a root path, greps code-level signals for each of the 23 tells, and prints a grouped report of `file:line` hits. It skips large files, lockfiles, minified assets, and common build dirs. Hits are leads to confirm by reading the code, not verdicts.

### Run

From the repository root:

```bash
node skill/scripts/scan.mjs path/to/project          # grouped report
node skill/scripts/scan.mjs path/to/project --json    # machine-readable
```

From inside `skill/`:

```bash
node scripts/scan.mjs path/to/src          # human-readable report
node scripts/scan.mjs path/to/src --json   # machine-readable
```

CLI shape from `scan.mjs`:

```text
node scan.mjs [root] [--json] [--no-color]
```

| Input | Behavior |
| --- | --- |
| `root` | First non-flag argument; defaults to `.` |
| `--json` | Machine-readable output; disables color |
| `--no-color` | Force plain console output |

**Scanned extensions (examples):** `.html`, `.css`, `.scss`, `.sass`, `.less`, `.tsx`, `.jsx`, `.ts`, `.js`, `.mjs`, `.cjs`, `.vue`, `.svelte`, `.astro`, `.md`, `.mdx`, plus `tailwind.config.*`.

**Skipped directories (examples):** `node_modules`, `.git`, `dist`, `build`, `out`, `.next`, `.astro`, `.output`, `.svelte-kit`, `.nuxt`, `coverage`, `vendor`, `.cache`, `.vercel`, `.turbo`.

### Success signal

- Process exits after printing a **grouped report** of hits (human mode) or a **JSON** payload (`--json`).
- No project files change: the scanner is read-only and dependency-free.
- With color enabled (TTY, not `--json`, no `--no-color`), console formatting may be colored; plain text is still valid success.

### Recovery (one note)

If the report is empty or the walk seems to miss your app, confirm the path argument points at real frontend source (not only `node_modules` / `dist`), that files use a scanned extension, and that individual files are under the 512 KB skip threshold. Re-run with an explicit root, e.g. `node skill/scripts/scan.mjs ./src`.

## B. Local field-guide run

The site under `website/` is a multilingual (English, Chinese, Japanese, Korean) static Astro field guide: 23 tells with interactive before→after HTML demos, catalogue data as the taxonomy source of truth, and a paper/ink design system.

### Run

```bash
cd website
npm install
npm run dev        # http://localhost:4321
```

Optional static build check:

```bash
npm run build      # → dist/  (static, deploy anywhere)
```

`website/astro.config.mjs` sets `site: 'https://killaislop.com'` and `build.inlineStylesheets: 'auto'`. No Astro integrations are configured by design.

### Success signal

- Dev server serves the field guide at **`http://localhost:4321`**.
- Index shows the hero, definition, **catalogue** section (`#catalogue`) with entries from `catalogue` data (23 tells, before→after demos), and principles.
- `npm run build` writes a static tree under `website/dist/`.

### Recovery (one note)

If `npm run dev` fails or the port never comes up, ensure you ran `npm install` **inside** `website/` (not the repo root) and that nothing else is bound to `4321`; re-run from `website/` after a clean install.

## Optional: agent skill in one prompt

After skill install (`npx skills add yetone/kill-ai-slop`, or copy `skill/` → `kill-ai-slop/` under the host skills dir), ask the agent:

> Kill the AI slop in this project.

Expected host behavior (from `skill/README.md` / skill docs): **scan** → **triage** → **report** a grouped summary before edits → **fix** only approved groups. The standalone scanner never applies fixes; edits happen only through the agent skill workflow when you approve them.

## What you should not expect from these first runs

| Surface | Does | Does not |
| --- | --- | --- |
| `scan.mjs` | Read, match patterns, print hits | Edit files, install packages, call network APIs |
| `website` dev/build | Serve/build the field guide | Scan your product code |
| Agent skill (optional) | Scan, triage, report, propose/apply fixes under host control | Silent file edits from the scanner alone |

## Next

<CardGroup>
  <Card title="Installation" href="/installation">
    Skill install via npx or manual copy, and website dependency setup.
  </Card>
  <Card title="Scan a web project" href="/scan-web-project">
    Interpret grouped vs JSON reports and verify hits against detection rules.
  </Card>
  <Card title="Run the field guide site" href="/run-field-guide-site">
    Dev server, static build, and how catalogue entries render on the index.
  </Card>
  <Card title="Use the agent skill" href="/use-agent-skill">
    Invoke kill-ai-slop inside a coding agent after install.
  </Card>
  <Card title="Scanner CLI reference" href="/scanner-cli-reference">
    Full invocation, flags, walk behavior, and the no-edit constraint.
  </Card>
</CardGroup>

---

## 04. Slop taxonomy

> Repo-specific model of AI-slop tells: categories, named signals, and how the field guide and skill share the same taxonomy language.

- Page Markdown: https://grok-wiki.com/public/docs/yetone-kill-ai-slop-c0d8c9670cbb/pages/04-slop-taxonomy.md
- Generated: 2026-07-11T08:24:29.612Z

### Source Files

- `skill/references/taxonomy.md`
- `website/src/data/catalogue.ts`
- `skill/references/detection.md`
- `README.md`

---
title: "Slop taxonomy"
description: "Repo-specific model of AI-slop tells: categories, named signals, and how the field guide and skill share the same taxonomy language."
---

`website/src/data/catalogue.ts` is the single source of truth for the AI-slop catalogue: 23 numbered tells, two tiers, six groups, and per-tell `what` / `why` / `fix` / `detect` fields that the Astro field guide renders and that the `kill-ai-slop` skill enforces. The skill restates the same model in `skill/references/taxonomy.md`, with code-level signals in `skill/references/detection.md` (encoded by `skill/scripts/scan.mjs`) and remediations in `skill/references/fixes.md`.

## Canonical model

Kill AI Slop defines **tells** — named machine-default UI/copy patterns — not abstract design theory. Every tell is meant to be findable in shipped products; each field-guide entry rebuilds the tell in plain HTML so the machine default and the clean fix sit side by side.

| Surface | Role | Taxonomy artifact |
| --- | --- | --- |
| Website (`website/`) | Multilingual field guide + before→after demos | `catalogue.ts` entries, `GROUPS`, `demo` keys |
| Agent skill (`skill/`) | Scan, triage, report, propose/apply fixes | `references/taxonomy.md`, `detection.md`, `fixes.md` + `scripts/scan.mjs` |

```text
website/src/data/catalogue.ts     ← single source of truth (spec)
        │
        ├─► field guide UI (groups, copy, demos)
        │
        └─► skill enforcement
                taxonomy.md   (what / why / fix language)
                detection.md  (human + scanner patterns)
                fixes.md      (remediation playbook)
                scan.mjs      (encodes detection; never edits files)
```

<Note>
English catalogue strings are the source of truth. Chinese is inline in `catalogue.ts`; Japanese and Korean merge from `catalogue.i18n.ts` and fall back to English at the localization layer.
</Note>

## Decision rule

Slop is the **absence of a decision**. A tell counts only when the element is a default nobody chose. The same visual or copy move, chosen and defended for the product, is not slop. Detection docs treat every match as a **lead, not a verdict** — open the file and confirm before acting.

## Tiers

Catalogue comments and `taxonomy.md` use the same two-tier split:

| Tier | Label | Meaning |
| --- | --- | --- |
| `1` | Classic | Widely recognized tells most people already spot |
| `2` | Evolved | Newer defaults that already read as templated (e.g. “tasteful terminal”) |

In `catalogue.ts`, `Entry.tier` is `1 | 2`. Entries are numbered by position in the array (`n` is applied via map), so inserting a case renumbers the rest automatically.

## Groups

Stable group keys (`Group` type) and English labels:

| `group` | English label | Scope in taxonomy |
| --- | --- | --- |
| `color` | Color | Gradients, palettes, semantic/status color defaults |
| `type` | Type | Serif misuse, decorative strike/highlight emphasis |
| `copy` | Copy | Keyword highlighting, AI voice, decorative emoji |
| `component` | Components | Status dots, callout bars, icon tiles, glass, shadows, badges, SVG marks |
| `layout` | Layout | All-caps interchangeable card/stat grids |
| `evolved` | Evolved slop | Terminal-chic mono + near-black template look |

Localized group titles live in `GROUPS` (`en` / `zh` / `ja` / `ko`).

## Tell inventory

Numbers **01–23** are shared by `skill/references/taxonomy.md` and `skill/references/detection.md`. Catalogue stable string `id` values appear below only where present in the supplied `catalogue.ts` excerpt; remaining tells are identified by number and title until you read the full raw entry list.

### Color (`group: "color"`, classic)

| # | Title | Catalogue `id` (when present) | One-line what |
| --- | --- | --- | --- |
| 01 | Indigo→violet gradient | `indigo-violet-gradient` | `#6366f1 → #a855f7` diagonal on buttons, glows, heroes |
| 02 | Gradient headline text | `gradient-text` | `background-clip: text` rainbow fills on headings |
| 03 | Warm “cozy” palette | `warm-cozy-palette` | Amber/stone/orange wash on soft beige |
| 04 | Default semantic palette | `default-semantic-palette` | Stock info/tip/success/error `-50` / `-600` set |
| 05 | One-hue status box | `mono-hue-alert` | Border, text, and tint bg all one hue at three opacities |
| 06 | Gradients as atmosphere | `atmosphere-gradient` | Page-wide glow + gradient card fills as “premium dark” |

### Type (`group: "type"`, classic)

| # | Title | Catalogue `id` (when present) | One-line what |
| --- | --- | --- | --- |
| 07 | Serif-italic on one word | `serif-emphasis` | One word in a sans headline swapped to serif italic |
| 08 | Serif where sans belongs | `serif-body-misuse` | Display serif (Playfair/Lora/etc.) as UI/body on tools/SaaS |
| 09 | Decorative strikes & highlights | — | Strike/underline/highlight as decoration, not edit/link/annotation |

### Copy (`group: "copy"`, classic)

| # | Title | One-line what |
| --- | --- | --- |
| 10 | Highlighted keywords | Colored/bold spans mid-paragraph as default emphasis |
| 11 | AI copywriting voice | “Not just X — it’s Y”, triad slogans, em-dash rhythm |
| 12 | Emoji everywhere | Emoji on every heading, button, and bullet |

### Components (`group: "component"`, classic)

| # | Title | One-line what |
| --- | --- | --- |
| 13 | Glowing status dot | Pulsing/haloing green “ready/online/live” gem |
| 14 | Rounded card, colored left border | Docs admonition bar wrapped around ordinary list rows |
| 15 | Rounded-square icon tiles | Feature grid of icon chips with little content link |
| 16 | Max radius + glassmorphism | `rounded-full` + `backdrop-blur` as default surface |
| 17 | Oversized drop shadow | Huge soft blur/spread larger than the casting element |
| 18 | Corners that don’t nest | Same large radius on nested boxes (no outer − padding math) |
| 19 | Badge and pill spam | Decorative “New/Beta/Popular” pills in chrome |
| 20 | AI-drawn SVG icons | Blob/mascot primitive SVG shipped as product mark |
| 21 | Icon in a tint of itself | Icon on `bg-{hue}/10` matching its own color |

### Layout (`group: "layout"`, classic)

| # | Title | One-line what |
| --- | --- | --- |
| 22 | All-caps card grid | ALL-CAPS micro-labels + number/icon in equal-weight cards |

### Evolved slop (`group: "evolved"`, tier 2)

| # | Title | One-line what |
| --- | --- | --- |
| 23 | The “tasteful terminal” | Mono UI chrome, near-black, one warm accent, ASCII decoration |

## Entry shape (catalogue)

```ts
export type Group = "color" | "type" | "copy" | "component" | "layout" | "evolved";

export interface Bi {
  en: string;
  zh: string;
  ja?: string;
  ko?: string;
}

export interface Entry {
  id: string;
  n: number;           // assigned by position
  tier: 1 | 2;
  group: Group;
  title: Bi;
  what: Bi;            // one line: what the tell is
  why: Bi;             // why it reads as machine-made
  fix: Bi;             // the clean move
  detect: string[];    // code-level signals (chips + skill heuristics)
  demo?: string;       // key into demos / BeforeAfter data
}
```

Field roles:

| Field | Use |
| --- | --- |
| `id` | Stable tell key; demo key usually matches when set |
| `n` | Display number; renumbers with array order |
| `tier` / `group` | Filter and section grouping on the site |
| `what` / `why` / `fix` | Shared prose language with skill taxonomy |
| `detect` | Short signal chips; parallel to detection reference patterns |
| `demo` | Optional live HTML before→after key |

## How the skill speaks the same language

| Concern | Skill reference | Aligns with catalogue |
| --- | --- | --- |
| Names, what/why/fix | `skill/references/taxonomy.md` | Entry titles + `what` / `why` / `fix` |
| Code-level signals | `skill/references/detection.md` + `scan.mjs` | Entry `detect[]` |
| Remediation | `skill/references/fixes.md` | Entry `fix` + site demos |
| Invocation path | `skill/SKILL.md` (scan → triage → report → fix) | Same 23-tell set |

Detection is numbered **01–23** to match taxonomy. Scan scope (from `detection.md`): frontend sources `.html .css .scss .tsx .jsx .ts .js .vue .svelte .astro .md .mdx` plus `tailwind.config.*`; skip `node_modules`, `dist`, `build`, `.git`, `out`, `.next`, `.astro`, `coverage`, `vendor`, `*.min.*`, and lockfiles.

Scanner entry points (read-only; never edit files):

```bash
node skill/scripts/scan.mjs path/to/project          # grouped report
node skill/scripts/scan.mjs path/to/project --json    # machine-readable
```

## Signal language (examples)

Catalogue `detect` chips are short human/scanner heuristics. Skill `detection.md` expands them to concrete `rg` patterns and false-positive notes. Examples from catalogue entries present in evidence:

| Tell | Sample `detect` chips |
| --- | --- |
| `indigo-violet-gradient` | `from-indigo-500 to-purple-500`, `#6366f1 → #a855f7`, `shadow-purple-500/50` |
| `gradient-text` | `bg-clip-text text-transparent`, `background-clip: text` |
| `warm-cozy-palette` | `amber-50 / stone-100 / orange-400`, `border-amber-200` |
| `default-semantic-palette` | `-50 bg + -600 text semantic set` |
| `mono-hue-alert` | `border-{c} text-{c} bg-{c}/10 status box` |
| `atmosphere-gradient` | `radial-gradient page background`, dark navy + top glow |
| `serif-emphasis` | `font-serif italic inside a sans <h1>` |
| `serif-body-misuse` | Playfair / Lora / Cormorant family usage in UI body |

Hard-to-grep tells (serif-italic nesting, nested corner math, visual SVG judgment, tasteful terminal) require human confirmation even when a pattern fires.

## Fix language (taxonomy pattern)

Every taxonomy entry ends with a short **Fix:** line. Pattern:

1. Remove or stop the default reflex.
2. Prefer structure (weight, space, hierarchy, one chosen accent) over decoration.
3. Keep the device only when it carries real product meaning (true status, real link, real brand).

Site demos (`demo` keys) and the remediation playbook illustrate the preferred outcome; the standalone scanner never applies fixes — only an agent host following `skill/SKILL.md` proposes or applies them.

## Alignment constraints

When extending or changing the model:

- Add or edit the tell in `catalogue.ts` first (SoT).
- Keep `taxonomy.md` / `detection.md` / `fixes.md` on the same number, name, and intent.
- Attach a plain-HTML demo when the site should show before→after.
- Do not treat a deliberate brand choice as a hit without confirmation.

## Related pages

<CardGroup>
  <Card title="Catalogue model" href="/catalogue-model">
    How catalogue.ts owns tells, demos, and i18n, and where site data ends and skill references begin.
  </Card>
  <Card title="Detection patterns" href="/detection-patterns">
    Per-tell code signals, match targets, and mapping back to taxonomy numbers.
  </Card>
  <Card title="Remediation playbook" href="/fixes-playbook">
    Per-tell clean fixes and how before/after demos show the preferred outcome.
  </Card>
  <Card title="Extend the catalogue" href="/extend-catalogue">
    Add or update a tell across catalogue, i18n, demo, and skill references.
  </Card>
  <Card title="Skill workflow" href="/skill-workflow">
    Scan, triage, report, then propose or apply fixes without silent scanner edits.
  </Card>
  <Card title="Catalogue and demos data" href="/catalogue-data-reference">
    Field shapes for catalogue.ts, catalogue.i18n.ts, and demos.ts.
  </Card>
</CardGroup>

---

## 05. Catalogue model

> How catalogue.ts is the single source of truth for tells, how demos and i18n attach, and boundaries between site data and skill references.

- Page Markdown: https://grok-wiki.com/public/docs/yetone-kill-ai-slop-c0d8c9670cbb/pages/05-catalogue-model.md
- Generated: 2026-07-11T08:25:10.887Z

### Source Files

- `website/src/data/catalogue.ts`
- `website/src/data/catalogue.i18n.ts`
- `website/src/data/demos.ts`
- `skill/references/taxonomy.md`
- `website/src/components/SlopEntry.astro`

---
title: "Catalogue model"
description: "How catalogue.ts is the single source of truth for tells, how demos and i18n attach, and boundaries between site data and skill references."
---

`website/src/data/catalogue.ts` defines the field-guide tell list: stable `id`s, display order `n`, tier, group, localized `title` / `what` / `why` / `fix`, code-level `detect` chips, and an optional `demo` key. The file header states it is the single source of truth for the website and the spec the kill-ai-slop skill enforces. Japanese and Korean copy attach from `catalogue.i18n.ts`; before→after HTML lives in `demos.ts` and is rendered by `SlopEntry.astro` via `BeforeAfter`.

## Role in the repo

| Artifact | Path | Owns |
| --- | --- | --- |
| Catalogue entries | `website/src/data/catalogue.ts` | Tell identity, order, tiers, groups, EN/ZH copy, `detect` strings, `demo` key |
| JA/KO strings | `website/src/data/catalogue.i18n.ts` | Optional `title` / `what` / `why` / `fix` per `id` for `ja` and `ko` |
| Demo HTML | `website/src/data/demos.ts` | Plain-HTML `before` / `after` payloads keyed by demo id |
| Demo styles | `styles/demos.css` (scoped under `.demo-<id>`) | Visual treatment for each demo pane |
| Entry UI | `website/src/components/SlopEntry.astro` | Renders one `Entry`: group tag, localized fields, demo, detect chips |
| Skill taxonomy prose | `skill/references/taxonomy.md` | Agent-facing narrative of the same tell set (what / why / fix) |
| Skill detection / fixes | `detection.md`, `fixes.md` (referenced from taxonomy) | Detection patterns and code patches for the skill workflow |

```mermaid
flowchart TB
  subgraph site["Field guide site"]
    CAT["catalogue.ts\nEntry[], GROUPS, Bi"]
    I18N["catalogue.i18n.ts\nja / ko by id"]
    DEM["demos.ts\nbefore / after HTML"]
    CSS["demos.css\n.demo-id scopes"]
    SE["SlopEntry.astro"]
    T["T.astro locale layer"]
    BA["BeforeAfter"]
    CAT -->|"merge ja/ko into Bi"| SE
    I18N --> CAT
    CAT -->|"entry.demo key"| BA
    DEM --> BA
    CSS --> BA
    SE --> T
    SE --> BA
  end

  subgraph skill["Agent skill references"]
    TAX["taxonomy.md\n23 tells, tiers, categories"]
    DET["detection.md"]
    FIX["fixes.md"]
    TAX --> DET
    TAX --> FIX
  end

  CAT -.->|"shared tell language / enforce as spec"| TAX
  CAT -->|"detect[] as mono chips + skill heuristics"| DET
```

The dashed link is alignment, not a TypeScript import. Site components import from `../data/catalogue`; skill agents read markdown under `skill/references/`. Keep ids, meaning, and remediation language in sync across both surfaces.

## Entry shape

`Entry` and related types in `catalogue.ts`:

| Field | Type | Required | Role |
| --- | --- | --- | --- |
| `id` | `string` | yes | Stable slug; article `id` / deep-link hash (`#${entry.id}`) |
| `n` | `number` | yes | Display number; assigned from array position (inserting renumbers the rest) |
| `tier` | `1 \| 2` | yes | `1` classic, `2` evolved |
| `group` | `Group` | yes | Category key into `GROUPS` |
| `title` | `Bi` | yes | Short name |
| `what` | `Bi` | yes | One line: what the tell is |
| `why` | `Bi` | yes | Why it reads as machine-made |
| `fix` | `Bi` | yes | Clean alternative |
| `detect` | `string[]` | yes | Code-level signals (UI mono chips + skill heuristics) |
| `demo` | `string` | no | Key into demos data / `demos.css` / `BeforeAfter` |

```ts
export type Group = "color" | "type" | "copy" | "component" | "layout" | "evolved";

export interface Bi {
  en: string;
  zh: string;
  ja?: string;
  ko?: string;
}

export interface Entry {
  id: string;
  n: number;
  tier: 1 | 2;
  group: Group;
  title: Bi;
  what: Bi;
  why: Bi;
  fix: Bi;
  detect: string[];
  demo?: string;
}
```

`rawEntries` is typed as `Omit<Entry, "n">[]`. Comments state numbering is by position so inserts renumber automatically. `GROUPS` is a `Record<Group, Bi>` used for the category tag on each entry.

### Tiers and groups

| Concept | Values | Meaning in catalogue header / UI |
| --- | --- | --- |
| Tier 1 | `tier: 1` | Classic slop — tells most people already recognise |
| Tier 2 | `tier: 2` | Evolved slop — newer defaults that already read as templated |
| Groups | `color`, `type`, `copy`, `component`, `layout`, `evolved` | EN labels: Color, Type, Copy, Components, Layout, Evolved slop (plus ZH/JA/KO in `GROUPS`) |

`SlopEntry` styles the group tag with `t${entry.tier}` (e.g. `tag group t2` for evolved emphasis).

### Localized strings (`Bi`)

- English is the source of truth and always present.
- Chinese (`zh`) is authored inline on each entry in `catalogue.ts`.
- Japanese and Korean are optional on `Bi` and are merged in from `catalogue.i18n.ts`.
- Missing locales fall back to English at the `<T>` layer; partial translations are safe.

`catalogue.i18n.ts` exports:

```ts
type Field = "title" | "what" | "why" | "fix";
type LangText = Partial<Record<Field, string>>;

export interface EntryI18n {
  ja?: LangText;
  ko?: LangText;
}

export const i18n: Record<string, EntryI18n> = { /* keyed by entry id */ };
```

Voice rule in that file: match English — terse, plain, specific; no punchy triads, no “not just X, it’s Y”, no exclamation. Site copy must not commit the slop patterns the catalogue documents.

## How demos attach

1. Catalogue entry sets `demo` to a string key (usually the same slug as `id`, e.g. `"indigo-violet-gradient"`).
2. `demos.ts` exports `demos: Record<string, { before: string; after: string }>` with plain HTML for each key.
3. Styles live under `.demo-<id>` in `styles/demos.css`.
4. `SlopEntry` renders `{entry.demo && <BeforeAfter id={entry.demo} />}`.

Demo contract (from `demos.ts` header):

- Rebuild the tell in HTML (`before`) and the clean counterpart (`after`).
- Keep illustrative copy short and neutral.
- `after` panes follow the same rules the site and skill enforce: one accent, no gradient chrome, hierarchy from scale + space, mono for code only, no decorative emoji/badges.

Earlier drafts used annotated screenshots of a reference product; those were removed in favour of live HTML demos so comparisons stay precise and do not drift.

### Example wire-up

Catalogue fragment:

```ts
{
  id: "indigo-violet-gradient",
  tier: 1,
  group: "color",
  title: { zh: "蓝紫渐变", en: "The indigo→violet gradient" },
  // what, why, fix...
  detect: [
    "from-indigo-500 to-purple-500",
    "#6366f1 → #a855f7",
    "bg-gradient-to-r via-purple",
    "shadow-purple-500/50",
  ],
  demo: "indigo-violet-gradient",
}
```

Matching demo key in `demos.ts`:

```ts
"indigo-violet-gradient": {
  before: `/* card with gradient chrome, decorative emoji */`,
  after: `/* solid surfaces, plain label, solid button */`,
}
```

If `demo` is omitted, `SlopEntry` still renders text fields and detect chips; only the evidence pane is skipped.

## How the site consumes an entry

`SlopEntry.astro` props: `{ entry: Entry }`.

| UI region | Data |
| --- | --- |
| Permalink number | `String(entry.n).padStart(2, "0")`; `href={`#${entry.id}`}`; click copies shareable `#id` URL |
| Group tag | `<T {...GROUPS[entry.group]} />` with class `t${entry.tier}` |
| Title / what | `<T {...entry.title} />`, `<T {...entry.what} />` |
| Demo | `BeforeAfter` when `entry.demo` is set |
| Why / fix | Localized section labels + `<T {...entry.why} />` / `fix` |
| Code signals | `entry.detect.map` → `<code>` chips |

Article root: `<article class="entry" id={entry.id}>`. Deep links land on the tell; sticky-nav offset is handled globally (`html { scroll-padding-top }`), not inside the entry.

## Skill boundary: catalogue vs references

`skill/references/taxonomy.md` opens with **23 tells, in two tiers** (Classic / Evolved). For each tell it covers what it is, why it reads as machine-made, and the fix. Detection patterns live in `detection.md`; code patches in `fixes.md`.

Shared rule across taxonomy and catalogue framing: **slop is the absence of a decision**. A tell is only slop when it is a default nobody chose; the same element, chosen and defended, is fine.

| Concern | Site catalogue | Skill references |
| --- | --- | --- |
| Authoritative structured data for the Astro field guide | Yes (`catalogue.ts`) | No |
| Multilingual field-guide UI copy | Yes (`Bi` + i18n) | Taxonomy is prose (EN in the evidence) |
| Live before/after demos | Yes (`demos.ts` + CSS) | No |
| Agent scan / triage narrative | Spec alignment via comments + `detect` heuristics | Yes (`taxonomy.md`) |
| Machine-oriented detection rules | `detect[]` chips (shared language) | Full patterns in `detection.md` |
| Remediation patches | `fix` prose on the entry | Playbook in `fixes.md` |

Do not treat `catalogue.ts` as runtime input for the standalone scanner unless another surface imports it. Treat it as the website SSOT and the human/agent-aligned **spec** that skill docs must match. When adding or renaming a tell, update catalogue identity first, then demos, i18n, and skill taxonomy / detection / fix references so ids and meaning stay one language.

### Id ↔ taxonomy alignment (examples)

Stable catalogue ids are slug identifiers; taxonomy.md uses numbered titles. Align by meaning, not by inventing a runtime bridge:

| Catalogue `id` (examples from data) | Taxonomy title (examples) |
| --- | --- |
| `indigo-violet-gradient` | 01 · Indigo→violet gradient |
| `gradient-text` | 02 · Gradient headline text |
| `warm-cozy-palette` | 03 · Warm "cozy" palette |
| `default-semantic-palette` | 04 · The default semantic palette |
| `mono-hue-alert` | 05 · The one-hue status box |
| `atmosphere-gradient` | 06 · Gradients as atmosphere |
| `serif-emphasis` | 07 · Serif-italic on one word |
| `emoji-everywhere` | 12 · Emoji everywhere |
| `status-dot-glow` | 13 · The glowing status dot |
| `left-border-callout` | 14 · Rounded card, colored left border |

Full id inventory, complete `detect` lists, and full demo HTML shapes belong on the data reference page; this page defines the model and attachment rules only.

## Constraints and verification

| Constraint | Signal |
| --- | --- |
| English always present on every `Bi` field | Required `en` / `zh` on type; EN is fallback |
| JA/KO optional and partial-safe | `Partial` fields; missing → EN at `<T>` |
| `demo` key must exist in `demos` when set | Runtime: `BeforeAfter` lookup by id; missing key fails the evidence pane |
| Demo styles scoped by id | `.demo-<id>` in `demos.css` |
| Numbering is positional | Insert/reorder `rawEntries` renumbers `n` |
| Site copy must not be slop | i18n header voice rules; demo `after` rules |
| Skill docs stay in the same language | Parallel update of taxonomy / detection / fixes |

<Check>
After a catalogue change: confirm `id` uniqueness, `demo` key match, i18n key match, and that taxonomy/detection/fix text still describe the same tell.
</Check>

## Related pages

<CardGroup>
  <Card title="Slop taxonomy" href="/slop-taxonomy">
    Categories, named signals, and how field guide and skill share taxonomy language.
  </Card>
  <Card title="Catalogue and demos data" href="/catalogue-data-reference">
    Field-level shapes for catalogue.ts, catalogue.i18n.ts, and demos.ts.
  </Card>
  <Card title="Extend the catalogue" href="/extend-catalogue">
    Add or update a tell across catalogue, i18n, demo, and skill references.
  </Card>
  <Card title="Detection patterns" href="/detection-patterns">
    Code-level signals and how findings map back to taxonomy ids.
  </Card>
  <Card title="Remediation playbook" href="/fixes-playbook">
    Per-tell clean fixes and before/after outcomes.
  </Card>
  <Card title="Run the field guide site" href="/run-field-guide-site">
    Local Astro preview and how entries/demos render on the index.
  </Card>
</CardGroup>

---

## 06. Skill workflow

> Agent skill lifecycle: scan, triage, report, then propose or apply fixes without silent file edits from the standalone scanner.

- Page Markdown: https://grok-wiki.com/public/docs/yetone-kill-ai-slop-c0d8c9670cbb/pages/06-skill-workflow.md
- Generated: 2026-07-11T08:24:32.177Z

### Source Files

- `skill/SKILL.md`
- `skill/scripts/scan.mjs`
- `skill/references/detection.md`
- `skill/references/fixes.md`
- `skill/README.md`

---
title: "Skill workflow"
description: "Agent skill lifecycle: scan, triage, report, then propose or apply fixes without silent file edits from the standalone scanner."
---

The `kill-ai-slop` agent skill (`skill/SKILL.md`) runs a fixed five-step lifecycle—**Scope → Scan → Triage → Report → Fix**—so a host agent detects AI-slop tells, confirms them against real intent, reports before any write, and only then proposes or applies minimal fixes. The bundled scanner `skill/scripts/scan.mjs` is read-only: it walks frontend source, matches tell patterns, and prints `file:line` hits (human or `--json`); it never edits files.

<Warning>
Do not mass-edit before the user has seen the report. Standalone `node scripts/scan.mjs` is a map of leads, not a verdict and not a mutator.
</Warning>

## Surfaces in play

| Surface | Path | Role in the lifecycle |
|---|---|---|
| Skill definition | `skill/SKILL.md` | Principles, ordered workflow, guardrails |
| Scanner | `skill/scripts/scan.mjs` | Dependency-free Node walk + regex match; report only |
| Taxonomy | `skill/references/taxonomy.md` | 23 tells: what each is, why it reads as slop, the fix |
| Detection reference | `skill/references/detection.md` | Patterns + common false positives (human reference; scanner encodes the patterns) |
| Fixes playbook | `skill/references/fixes.md` | Before→after directions per tell |

Trigger phrases the skill is meant for include: “kill AI slop”, “de-slop”, “remove the AI look”, “make this not look AI-generated”, or cleaning a templated landing page / UI / docs.

## Lifecycle at a glance

```mermaid
stateDiagram-v2
  [*] --> Scope
  Scope --> Scan: root confirmed
  Scan --> Triage: file:line hits
  Triage --> Report: confirmed slop only
  Report --> AwaitingApproval: grouped summary shown
  AwaitingApproval --> Fix: user picks groups / all
  AwaitingApproval --> [*]: user declines
  Fix --> Rescan: re-run scanner
  Rescan --> [*]: counts dropped; leftovers noted
```

Ownership boundary: **scan/report stay read-only**; **writes happen only in Fix**, under host-agent control after user approval. The scanner process itself never crosses that boundary.

## Principles (held on every fix)

From `SKILL.md`, applied during triage and fix—not as optional style notes:

1. **Decide before you decorate.** Every visual choice must be explainable.
2. **One accent, one voice.**
3. **Hierarchy from scale and space.** Coloring words or swapping fonts is a shortcut.
4. **Subtract first.** First move toward not-ugly is removing things.
5. **Specific beats punchy** in copy.
6. **Decoration must mean something** — icons, badges, callouts are signals.

## Step-by-step workflow

<Steps>
<Step title="1. Scope">
Confirm what to scan. Default to app/site source. Skip `node_modules`, `dist`, `build`, `.git`, `vendor`, lockfiles, and minified files (the scanner also skips additional build caches such as `.next`, `.astro`, `.output`, `.svelte-kit`, `.nuxt`, `coverage`, `.cache`, `.vercel`, `.turbo`).

If the repo mixes several apps, ask which tree to target before scanning.
</Step>

<Step title="2. Scan">
Run the bundled scanner for code-level signals of each tell and print grouped `file:line` hits:

```bash
node scripts/scan.mjs <root>          # human-readable report
node scripts/scan.mjs <root> --json   # machine-readable, for triage
```

From the skill directory, invocation is the same shape as documented on the scanner (`node scan.mjs [root] [--json] [--no-color]`). Defaults: `root` is `.` when omitted; color is on only when stdout is a TTY, not JSON, and `--no-color` is absent.

**Scanner contract**

| Fact | Behavior |
|---|---|
| Runtime | Pure Node (`node:fs`, `node:path` only)—no package install |
| Mutates files? | **Never** |
| Hit meaning | Lead to confirm by reading code, not a verdict |
| Large files | Skip files larger than `512 * 1024` bytes |
| Extensions | `.html .css .scss .sass .less .tsx .jsx .ts .js .mjs .cjs .vue .svelte .astro .md .mdx`, plus `tailwind.config.*` |
| Also skipped | `*.min.js` / `*.min.css`, lockfiles |

Each tell in `TELLS` has `id`, `group`, `name`, one-line `fix`, and `patterns`. Some copy-oriented tells set `copy: true` (ids `10`–`12`).
</Step>

<Step title="3. Triage">
For every hit, open the file and decide **slop vs. intentional**. This step separates the skill from a lint rule.

- Keep brand tokens, logos, deliberate illustrations, and defended design choices.
- Flag defaults and pile-ons that lack intent.
- Use `references/taxonomy.md` for what the tell is and why it reads as machine-made.
- Use `references/detection.md` for exact patterns and common false positives.

Examples of “can be real choices”: a brand-true purple, a single deliberate hero gradient headline, emoji in a picker feature, serif for an editorial product.
</Step>

<Step title="4. Report">
**Before changing anything**, give a grouped summary: each tell, confirmed `file:line` hits, one sentence on why, and the proposed fix. Mirror this format:

```
slop  src/Hero.tsx:12   indigo→violet gradient        → one solid accent
slop  src/Hero.tsx:31   gradient-clip headline        → solid ink, scale up
slop  src/Note.tsx:8    border-l-4 callout ×3         → 1 aside, rest is body
slop  copy.md:1         "not just X — it's Y"         → say the specific thing
→ 4 groups, 11 hits.
```

Then ask which groups to apply, or whether to proceed on all. Do not skip this gate.
</Step>

<Step title="5. Fix">
Apply the **minimal** change that removes the tell while preserving intent and function. Use `references/fixes.md` for before→after direction per tell (adapt to project tokens/framework; not blind find-and-replace).

**Fix order of operations** (`fixes.md`):

1. Design tokens / theme first (colors, radius, fonts)—many hits disappear at once.
2. Shared components, then one-off call sites.
3. Copy last.

**Fix rules**

- Prefer shared tokens/components over every call site.
- Never invent new brand colors; if palette must change, propose neutrals + the project’s existing accent and wait for confirmation.
- Keep copy meaning; make it specific—don’t just delete it.
- Re-run the scanner after fixing; confirm hit count dropped; note intentional leftovers with reasons.
</Step>
</Steps>

## Scanner vs agent skill

| | Standalone scanner | Agent skill host |
|---|---|---|
| Command / surface | `node scripts/scan.mjs [root] [--json] [--no-color]` | Host invokes skill after install; user prompt like “Kill the AI slop in this project” |
| Reads source | Yes | Yes (via scanner + file open) |
| Edits source | **No** | Only after report + user approval, in Fix |
| Output | Grouped human report or JSON | Same scan map, then triage narrative + proposal + optional apply |
| Judgment | Pattern match only | Slop vs intentional; false-positive handling |

<Info>
Use `--json` when the host needs a machine-readable hit list for triage. Treat JSON hits the same as the human report: confirm by reading the code before proposing edits.
</Info>

## Tell inventory (scanner `TELLS`)

Twenty-three tells, ids `01`–`23`, with groups used for reporting and prioritization:

| Group | IDs | Examples (name → one-line fix) |
|---|---|---|
| `color` | `01`–`06` | indigo→violet gradient → one solid, chosen accent |
| `type` | `07`–`09` | serif-italic emphasis → emphasise by weight, one voice |
| `copy` | `10`–`12` | AI copywriting voice → say the specific thing |
| `component` | `13`–`21` | left-border callout → one aside, rest is body |
| `layout` | `22` | all-caps card grid → show the one key thing fully |
| `evolved` | `23` | tasteful-terminal → mono for code only |

Full pattern lists live in `skill/scripts/scan.mjs` and the parallel human reference `skill/references/detection.md`.

## Guardrails

| Guardrail | Constraint |
|---|---|
| Respect authorship | Unfamiliar files and deliberate flourishes are someone’s choice; when unsure, ask—don’t strip |
| Small, reviewable diffs | No unrelated reformats; never `git add -A`; stage explicit files only |
| No new dependencies | Do not add packages to perform this work |
| Visual verify when possible | If a dev server exists, compare before/after; a clean scan ≠ a better page |

## Verification signals

| Stage | Success signal |
|---|---|
| Scan | Grouped `file:line` (or JSON) report; no files modified by the scanner |
| Triage | Each kept/discarded hit has a reason (intentional brand vs default) |
| Report | User sees groups + proposed fixes **before** any edit |
| Fix | Minimal diffs; preferred shared-token changes; scanner re-run shows lower counts |
| Leftovers | Intentionally retained hits documented with reason |

## Skill package layout

:::files
skill/
  SKILL.md                 # workflow + guardrails
  README.md                # install + use
  references/
    taxonomy.md            # 23 tells (what / why / fix)
    detection.md           # patterns + false positives
    fixes.md               # before→after remediation
  scripts/
    scan.mjs               # dependency-free, read-only scanner
:::

## Related pages

<CardGroup>
  <Card title="Use the agent skill" href="/use-agent-skill">
    Invoke kill-ai-slop in a coding agent after install: prompts and host behavior.
  </Card>
  <Card title="Scan a web project" href="/scan-web-project">
    Point the scanner at a path; interpret grouped vs JSON reports.
  </Card>
  <Card title="Apply clean fixes" href="/apply-clean-fixes">
    Map hits to the fixes playbook; choose propose vs apply.
  </Card>
  <Card title="Scanner CLI reference" href="/scanner-cli-reference">
    Invocation, flags, walk/scan behavior, and the hard no-edit constraint.
  </Card>
  <Card title="Detection patterns" href="/detection-patterns">
    Code-level signals per tell and how findings map to taxonomy ids.
  </Card>
  <Card title="Remediation playbook" href="/fixes-playbook">
    Per-tell clean fixes and preferred before/after outcomes.
  </Card>
  <Card title="Slop taxonomy" href="/slop-taxonomy">
    Shared language for categories, named signals, and field-guide alignment.
  </Card>
</CardGroup>

---

## 07. Use the agent skill

> Invoke kill-ai-slop inside a coding agent after install: prompts, expected host behavior, and how the skill uses references and the scanner.

- Page Markdown: https://grok-wiki.com/public/docs/yetone-kill-ai-slop-c0d8c9670cbb/pages/07-use-the-agent-skill.md
- Generated: 2026-07-11T08:24:31.068Z

### Source Files

- `skill/SKILL.md`
- `skill/README.md`
- `skill/scripts/scan.mjs`
- `skill/references/taxonomy.md`
- `README.md`

---
title: "Use the agent skill"
description: "Invoke kill-ai-slop inside a coding agent after install: prompts, expected host behavior, and how the skill uses references and the scanner."
---

After install, the `kill-ai-slop` Agent Skill is the host-driven path: the agent loads `skill/SKILL.md`, runs `scripts/scan.mjs` as a read-only map, triages hits against `references/`, reports before any edit, then proposes or applies fixes only for groups you approve.

<Info>
The skill is provider-neutral and portable: it is a directory of files (`SKILL.md`, `references/`, `scripts/scan.mjs`) that any Agent Skills host can load from its own skills path. No model vendor, hosted API, or proprietary connector is required.
</Info>

## Prerequisites

| Requirement | Detail |
|---|---|
| Skill installed | `kill-ai-slop/` under the host skills directory (project or user scope) |
| Node available | For the bundled scanner: `node scripts/scan.mjs …` |
| Target | A web UI / docs tree (HTML/CSS, React/Vue/Svelte/Astro, Tailwind, Markdown) |

Install paths and the `npx skills add yetone/kill-ai-slop` flow are documented on the installation page. This page assumes registration succeeded and the host can resolve the skill by name or description.

:::files
skill/
  SKILL.md                 # definition, workflow, guardrails
  references/
    taxonomy.md            # 23 tells: what / why / fix
    detection.md           # patterns + false positives
    fixes.md               # before→after remediation
  scripts/
    scan.mjs               # dependency-free scanner (never edits)
:::

## Invoke the skill

Once registered, start with a plain-language request. The skill’s frontmatter `description` is what hosts match on; these phrases are the intended triggers:

| Intent | Example prompts |
|---|---|
| Full de-slop pass | `Kill the AI slop in this project.` |
| Short forms | `de-slop this`, `remove the AI look`, `make this not look AI-generated` |
| Scope hints | Landing page / UI / docs that feel templated; clean up vibe-coded UI defaults |

You do not need to name files or pass flags unless you want a narrower root. The agent should confirm scope when the repo holds multiple apps.

```text
Kill the AI slop in this project.
```

```text
De-slop the marketing site under apps/web. Keep brand tokens.
```

## Expected host behavior

Hosts must follow the ordered workflow in `SKILL.md`. **Do not mass-edit before the user has seen the report.**

```mermaid
sequenceDiagram
  participant User
  participant Agent as Agent host<br/>(SKILL.md)
  participant Scan as scripts/scan.mjs
  participant Refs as references/*

  User->>Agent: kill AI slop / de-slop / remove AI look
  Agent->>User: 1. Scope (root; multi-app?)
  Agent->>Scan: node scripts/scan.mjs root [--json]
  Scan-->>Agent: grouped file:line hits (read-only)
  Agent->>Refs: taxonomy + detection (triage)
  Agent->>User: 4. Report + ask which groups
  User->>Agent: approve groups / all
  Agent->>Refs: fixes.md patterns
  Agent->>User: 5. Minimal diffs + re-scan note
```

### 1. Scope

- Default to app/site source.
- Skip noise dirs and artifacts the scanner also skips (`node_modules`, `dist`, `build`, `.git`, `vendor`, lockfiles, minified files, and the scanner’s own `SKIP_DIRS` set).
- Ask if the project mixes several apps before walking everything.

### 2. Scan

Run the bundled scanner (path relative to the installed skill directory):

```bash
node scripts/scan.mjs <root>          # human-readable report
node scripts/scan.mjs <root> --json   # machine-readable, for triage
```

| Property | Behavior |
|---|---|
| Runtime | Pure Node; no npm dependencies |
| Side effects | **Never edits files** |
| Role of output | Starting map of code-level signals, **not** verdicts |
| Confirmation | Every hit must be checked by reading the file |

From the repo root (without installing into the host), the same binary is:

```bash
node skill/scripts/scan.mjs path/to/project
node skill/scripts/scan.mjs path/to/project --json
```

Scanner CLI surface (as implemented in `scan.mjs`):

| Input | Default | Meaning |
|---|---|---|
| `[root]` | `.` | First non-flag argv path |
| `--json` | off | Machine-readable report |
| `--no-color` | off | Disable ANSI when not JSON |

Optional flags beyond those three are not part of the documented scanner contract.

### 3. Triage

For every hit, open the file and decide **slop vs intentional**. This is what separates the skill from a lint rule:

- Keep defended choices: brand tokens, logos, deliberate illustration, intentional serif/gradient/emoji.
- Flag **defaults** — “absence of a decision,” per `references/taxonomy.md`.
- Use `references/detection.md` for exact patterns and common false positives.

### 4. Report

**Before any edit**, emit a grouped summary: tell, confirmed `file:line`, one sentence why, proposed fix. Mirror this shape:

```text
slop  src/Hero.tsx:12   indigo→violet gradient        → one solid accent
slop  src/Hero.tsx:31   gradient-clip headline        → solid ink, scale up
slop  src/Note.tsx:8    border-l-4 callout ×3         → 1 aside, rest is body
slop  copy.md:1         "not just X — it's Y"         → say the specific thing
→ 4 groups, 11 hits.
```

Then ask which groups to apply, or whether to proceed on all.

### 5. Fix

Only after approval:

- Apply the **minimal** change that removes the tell while preserving intent and function.
- Use `references/fixes.md` for before→after patterns.
- Prefer shared tokens/components over every call site.
- **Never invent new brand colors**; if palette must change, propose neutrals + existing accent and wait for confirmation.
- Keep copy meaning; make it specific rather than deleting.
- Re-run the scanner; confirm hit count dropped; list intentional leftovers with reasons.

## How the skill uses references

| Path | Role in the agent loop |
|---|---|
| `SKILL.md` | Host skill entry: `name: kill-ai-slop`, trigger `description`, workflow, guardrails |
| `references/taxonomy.md` | 23 tells (classic + evolved): definition, why it reads machine-made, fix intent |
| `references/detection.md` | Concrete patterns + false positives for triage |
| `references/fixes.md` | Remediation before→after patterns when applying edits |
| `scripts/scan.mjs` | Automated lead generation only |

Taxonomy rule the agent must honor: a tell is slop only when it is a **default nobody chose**. The same element, chosen and defended, stays.

Coverage called out by the skill description (code and copy surfaces): indigo→violet gradients, gradient-clip headlines, warm cozy palettes, default semantic palette, one-hue status boxes, atmospheric gradients, serif-italic emphasis, serif-where-sans, decorative strikes/highlights, highlighted keywords, AI copywriting voice, emoji spam, glowing status dots, left-border callouts, pastel icon tiles, glass/over-rounding, oversized shadows, non-nesting corners, badge/pill spam, AI-drawn SVG icons, icon-in-tint tiles, all-caps card grids, and “tasteful terminal” — across HTML/CSS, React/Vue/Svelte/Astro, Tailwind, and Markdown.

## How the skill uses the scanner

The scanner is a **lead generator**, not the decision engine.

| Concern | Scanner | Agent (skill) |
|---|---|---|
| Walk sources | Yes (`walk`, extension filter, skip dirs) | Chooses `<root>` after Scope |
| Match patterns | Yes (`TELLS` regexes in `scan.mjs`) | Confirms / rejects each hit |
| Edit files | **No** | Yes, only after Report + approval |
| Intent / brand | No | Yes (triage + fixes playbook) |
| Visual QA | No | Yes when a dev server exists |

Internal constraints encoded in `scan.mjs` (for interpreting empty or sparse reports):

- Skips directories such as `node_modules`, `.git`, `dist`, `build`, `out`, `.next`, `.astro`, `.output`, `.svelte-kit`, `.nuxt`, `coverage`, `vendor`, `.cache`, `.vercel`, `.turbo`
- Scans extensions including `.html`, `.css`/`.scss`/`.sass`/`.less`, `.tsx`/`.jsx`/`.ts`/`.js`/`.mjs`/`.cjs`, `.vue`, `.svelte`, `.astro`, `.md`, `.mdx`, plus `tailwind.config.*`
- Skips `*.min.js` / `*.min.css`, lockfiles, and files larger than **512 KiB**
- Tells marked `copy: true` (e.g. AI voice, emoji) also consider prose-bearing files; others focus on code/style signals

<Warning>
A clean re-scan is not proof of a better page. `SKILL.md` requires visual verification when a dev server is available: before/after beats a zero hit count.
</Warning>

## Guardrails the host must enforce

| Rule | Constraint |
|---|---|
| Authorship | Unfamiliar files and deliberate flourishes are someone’s choice; when unsure, **ask** — do not strip |
| Diff size | No unrelated reformats; never `git add -A`; stage explicit files only |
| Dependencies | **No new packages** for de-slop work |
| Verification | Prefer visual check; re-scan and document intentional remaining hits |
| Order | Report → user choice → fix (no silent bulk edits from the skill path) |

Standalone scanner use (no skill host) is scan-only; it cannot apply fixes. Fix application is host-mediated via the skill workflow.

## Verification signals

| Stage | Success signal |
|---|---|
| Invoke | Host loads `kill-ai-slop` from skills path (not a free-form guess of the catalogue) |
| Scan | Grouped `file:line` report or JSON; process does not write project files |
| Report | Summary before edits; user asked which groups to apply |
| Fix | Small diffs; scanner count down; intentional leftovers listed with reasons |
| Visual | Page looks intentional under one accent / one voice, not just “lint clean” |

## Troubleshooting

| Symptom | Check |
|---|---|
| Skill never fires | Re-install registration; prompt with a description-matching phrase (“kill AI slop”, “de-slop”, “remove the AI look”) |
| Agent edits immediately | Workflow violation — require step 4 report and approval first |
| Scanner path not found | Run relative to the installed skill: `node scripts/scan.mjs …`, or from clone: `node skill/scripts/scan.mjs …` |
| Hits look wrong | Expected — treat as leads; re-read with `taxonomy.md` + `detection.md` false positives |
| Palette rewrite surprises | Agent must not invent brand colors; stop and confirm neutrals + existing accent |
| Multi-app monorepo noise | Re-scope to a single app root before scan |

## Next

<CardGroup>
  <Card title="Skill workflow" href="/skill-workflow">
    Lifecycle detail: scan → triage → report → propose/apply without silent scanner edits.
  </Card>
  <Card title="Scan a web project" href="/scan-web-project">
    Point the dependency-free scanner at a path; grouped vs JSON reports.
  </Card>
  <Card title="Apply clean fixes" href="/apply-clean-fixes">
    Map hits to the fixes playbook; propose vs apply in an agent host.
  </Card>
  <Card title="Scanner CLI reference" href="/scanner-cli-reference">
    Flags, walk/scan behavior, and the hard no-edit constraint.
  </Card>
  <Card title="Remediation playbook" href="/fixes-playbook">
    Per-tell clean fixes and before/after intent.
  </Card>
  <Card title="Installation" href="/installation">
    npx or manual copy into the host skills directory.
  </Card>
</CardGroup>

---

## 08. Scan a web project

> Point the dependency-free scanner at a project path, interpret grouped vs JSON reports, and verify findings against detection rules.

- Page Markdown: https://grok-wiki.com/public/docs/yetone-kill-ai-slop-c0d8c9670cbb/pages/08-scan-a-web-project.md
- Generated: 2026-07-11T08:24:48.736Z

### Source Files

- `skill/scripts/scan.mjs`
- `skill/references/detection.md`
- `skill/README.md`
- `README.md`
- `skill/references/taxonomy.md`

---
title: "Scan a web project"
description: "Point the dependency-free scanner at a project path, interpret grouped vs JSON reports, and verify findings against detection rules."
---

`skill/scripts/scan.mjs` is a Node-only, dependency-free walker that greps frontend source for the 23 AI-slop tells encoded in its `TELLS` table (aligned with `skill/references/detection.md`). Point it at a project root, read the grouped `file:line` report or `--json` output, and treat every hit as a lead to confirm in code—not a verdict. The scanner never edits files.

## Prerequisites

- Node.js available as `node` (ESM: `import` from `node:fs` / `node:path`).
- A local checkout that includes `skill/scripts/scan.mjs` (no `npm install` for the scanner itself).
- A web project path to scan (HTML/CSS, React/Vue/Svelte/Astro, Tailwind, Markdown, and related frontend source).

<Note>
Standalone scan is read-only. Proposing or applying clean fixes is the agent skill path (`skill/SKILL.md`), not this script.
</Note>

## Invoke the scanner

Usage from the script header:

```text
node scan.mjs [root] [--json] [--no-color]
```

From a full repo checkout:

```bash
node skill/scripts/scan.mjs path/to/project          # grouped report
node skill/scripts/scan.mjs path/to/project --json    # machine-readable
```

From inside `skill/` (paths in `skill/README.md`):

```bash
node scripts/scan.mjs path/to/src          # human-readable report
node scripts/scan.mjs path/to/src --json   # machine-readable
```

### CLI inputs

| Input | Behavior |
| --- | --- |
| `root` (positional) | First argv token that does not start with `-`. Default: `.` |
| `--json` | Machine-readable report mode (`asJson`). Disables ANSI color. |
| `--no-color` | Force plain console output even when stdout is a TTY. |

Color is enabled only when all of these hold: `--no-color` is absent, stdout is a TTY (`process.stdout.isTTY`), and `--json` is absent.

## What the walker includes and skips

`walk(dir)` recurses from `root` and collects files for `scanFile`.

### Included extensions and special names

`EXTS` in `scan.mjs`:

| Extension | Notes |
| --- | --- |
| `.html`, `.css`, `.scss`, `.sass`, `.less` | Markup and styles |
| `.tsx`, `.jsx`, `.ts`, `.js`, `.mjs`, `.cjs` | App/source JS/TS |
| `.vue`, `.svelte`, `.astro` | Framework SFCs |
| `.md`, `.mdx` | Prose / docs copy |

Also included by basename: any `tailwind.config.*` file (matched with `/^tailwind\.config\./`).

`detection.md` documents the same frontend scope (with a slightly shorter extension list in prose); the implementation in `scan.mjs` is authoritative for what the script actually opens.

### Skipped directories

`SKIP_DIRS`:

`node_modules`, `.git`, `dist`, `build`, `out`, `.next`, `.astro`, `.output`, `.svelte-kit`, `.nuxt`, `coverage`, `vendor`, `.cache`, `.vercel`, `.turbo`

Dot-directories that appear in `SKIP_DIRS` are skipped; other walk errors on `readdirSync` return the files collected so far.

### Skipped files

- `*.min.js` / `*.min.css`
- Lockfiles matching `package-lock`, `pnpm-lock`, or `yarn.lock` in the basename
- Files larger than **512 KiB** (`st.size > 512 * 1024`) — treated as large/generated; `scanFile` returns no hits
- Unreadable paths (`statSync` / `readFileSync` failures return `[]`)

## Tell catalogue encoded in the scanner

Each entry in `TELLS` has:

| Field | Role |
| --- | --- |
| `id` | Two-digit tell id (`"01"` … `"23"`), shared with taxonomy/detection language |
| `group` | Bucket used for reporting: `color`, `type`, `copy`, `component`, `layout`, `evolved` |
| `name` | Short human label |
| `fix` | One-line remediation hint printed with the tell |
| `patterns` | One or more `RegExp`s applied to file text |
| `copy` | Optional; when `true`, the tell is a copy tell (prose-oriented). Set on **10**, **11**, **12** |

Script comment: code tells target code/style files; copy tells also read prose. `scanFile` begins an `isCode` branch after the read (remainder of match/filter logic is in the full script); pattern lists themselves are fully declared in `TELLS`.

### Tell inventory (ids and groups)

| Id | Group | Name | Fix (scanner one-liner) |
| --- | --- | --- | --- |
| 01 | color | indigo→violet gradient | one solid, chosen accent |
| 02 | color | gradient-clip headline | solid ink, scale up |
| 03 | color | warm ‘cozy’ palette | neutral base + one warm accent |
| 04 | color | default semantic palette | one palette: neutrals + a couple of chosen states |
| 05 | color | one-hue status box | state in words; one muted accent on neutral |
| 06 | color | gradients as atmosphere | one flat bg; depth from a hairline |
| 07 | type | serif-italic emphasis | emphasise by weight, one voice |
| 08 | type | serif where sans belongs | one legible UI sans |
| 09 | type | decorative strikes & highlights | strike for edits, underline for links |
| 10 | copy | highlighted keywords | let structure carry emphasis |
| 11 | copy | AI copywriting voice | say the specific thing |
| 12 | copy | emoji everywhere | cut emoji from product copy |
| 13 | component | glowing status dot | flat dot + a word; no halo |
| 14 | component | left-border callout | one aside, rest is body |
| 15 | component | pastel icon tiles | labelled list with specifics |
| 16 | component | max-radius / glassmorphism | one small radius, solid surfaces |
| 17 | component | oversized drop shadow | tight elevation, never bigger than the element |
| 18 | component | corners that don't nest | inner = outer − padding |
| 19 | component | badge / pill spam | badges only for real status |
| 20 | component | AI-drawn SVG icon | a real, high-quality icon (a designer, or a strong image model) |
| 21 | component | icon in a tint of itself | no tinted tile; inherit text color |
| 22 | layout | all-caps card grid | show the one key thing fully |
| 23 | evolved | tasteful-terminal | mono for code only |

Human-oriented pattern notes, false positives, and confirm checks live in `skill/references/detection.md`. Taxonomy prose lives in `skill/references/taxonomy.md`.

## Interpreting reports

### Grouped (default)

Default mode prints a **grouped report of `file:line` hits** for matching tells. Expect human-oriented grouping by tell (ids/names/fixes from `TELLS`) and path/line locations relative to the walk root—not a pass/fail grade.

Success signals:

- Process exits after printing (no write side effects).
- Hits appear as locations you can open in an editor.
- Empty or sparse output means no pattern matched under the walk rules (not proof that the UI is free of slop).

### JSON (`--json`)

`--json` selects machine-readable output and turns color off. Use it for piping into triage tooling or agent hosts. Treat payload fields as whatever the script emits at runtime; wire consumers against a real run of `scan.mjs` rather than inventing a schema from this page.

### Constraint shared by both modes

From the scanner header and READMEs:

- **Never edits files**
- **Every hit is a lead to confirm by reading the code, not a verdict**

A gradient, serif, emoji, or monospaced UI can be intentional design. The skill (when used) triages slop vs chosen design; the standalone scanner only surfaces signals.

## Verify findings against detection rules

Use `skill/references/detection.md` as the human checklist for each tell id. Workflow:

<Steps>
  <Step title="Map the hit to a tell id">
    Match the report’s tell id/name to the same numbered section in `detection.md` (and the taxonomy entry in `taxonomy.md` for “why it reads as machine-made” and the intended fix direction).
  </Step>
  <Step title="Open the file at the reported line">
    Confirm the match is real in context (class list, CSS, markup, or copy), not a partial string inside an unrelated token.
  </Step>
  <Step title="Apply the confirm / false-positive rules">
    Detection entries call out usual lies of each pattern—for example brand-true purple vs indigo→violet factory gradient; logo wordmark vs default gradient headings; food/craft warm identity vs cozy-as-default; emoji in documented code samples vs emoji on every chrome heading.
  </Step>
  <Step title="Keep defended choices">
    Taxonomy rule: slop is the *absence of a decision*. Keep anything clearly intentional; only treat default, unchosen machine patterns as fix candidates.
  </Step>
</Steps>

### Representative confirm checks (from detection.md)

| Id | Confirm / false-positive stance |
| --- | --- |
| 01 | Slop is the *combination* (purple gradient + glow + pill + “AI-powered” eyebrow), not every purple brand accent |
| 02 | Logo wordmark or one deliberate hero treatment can be fine; default gradient heading style is the tell |
| 04 | Confirm several stock `-50` / `-600` semantic pairs together, unrelated to brand |
| 05 | Same hue on border, text, and `/10` background on one alert |
| 11 | Quotes or docs *discussing* the phrases (including this project’s own docs) can false-positive |
| 12 | Code samples, emoji pickers, UGC are not chrome spam |
| 16 | `rounded-full` on avatars/pills is expected; on cards/inputs as default surface is the concern |
| 17 | 60px+ blur/spread fog under a small element; large surfaces with proportionate shadow can be fine |
| 18 | Same large radius on nested boxes (inner should be outer − padding) |
| 20 | Visual judgment on blob-with-dot-eyes / primitive mascot SVGs, not every `<svg>` |

When a pattern is “hard to grep” in detection notes (e.g. serif-italic *inside* a sans heading, nested corner math), the scanner’s regexes are still leads—open the structure and decide.

## Runbook: first report

<Steps>
  <Step title="Point at a tree">
    Prefer the app’s source root (or monorepo package path), not a parent full of unrelated repos, so skip lists and path noise stay useful.
  </Step>
  <Step title="Run grouped once">
    ```bash
    node skill/scripts/scan.mjs path/to/project
    ```
  </Step>
  <Step title="Optionally capture JSON">
    ```bash
    node skill/scripts/scan.mjs path/to/project --json > slop-report.json
    ```
  </Step>
  <Step title="Triage by id">
    Work tell-by-tell using `detection.md` confirm notes; drop false positives before any fix work.
  </Step>
  <Step title="Hand off to remediation only when ready">
    Map confirmed hits to `skill/references/fixes.md` / agent fix flow. Do not expect `scan.mjs` to rewrite the tree.
  </Step>
</Steps>

## Failure modes and quiet results

| Situation | What the script does | What to check |
| --- | --- | --- |
| Path missing or unreadable | `walk` / `scanFile` soft-fail toward empty collections | Permissions, path spelling, root default `.` |
| Only build artifacts under root | Skipped via `SKIP_DIRS` | Point at `src` / app package |
| Large generated bundles | Files &gt; 512 KiB skipped | Scan sources, not minified dumps |
| Zero hits | No matching patterns in included files | Patterns are heuristic; visual review still applies |
| Hits on this repo’s own docs | Copy patterns can match documented phrases | Apply false-positive guidance for tell 11 (and similar) |

## Relationship to the agent skill

| Surface | Role |
| --- | --- |
| `skill/scripts/scan.mjs` | Read-only signal report |
| Agent skill (`kill-ai-slop`) | Scan → triage → report → propose/apply fixes per `skill/SKILL.md` |
| `skill/references/detection.md` | Human pattern book; scanner encodes the same class of signals |
| `skill/references/taxonomy.md` | What each tell is and the fix direction |
| `skill/references/fixes.md` | Before→after remediation patterns |

After a confirmed report, move to clean fixes through the skill or the remediation playbook—not by expecting the scanner to mutate files.

## Related pages

<CardGroup>
  <Card title="Scanner CLI reference" href="/scanner-cli-reference">
    Invocation, flags, walk/scan behavior, and the hard no-edit constraint.
  </Card>
  <Card title="Detection patterns" href="/detection-patterns">
    Per-tell patterns, match targets, and false-positive notes.
  </Card>
  <Card title="Skill workflow" href="/skill-workflow">
    Full agent lifecycle: scan, triage, report, then propose or apply fixes.
  </Card>
  <Card title="Apply clean fixes" href="/apply-clean-fixes">
    Map confirmed hits to the fixes playbook and agent propose vs apply.
  </Card>
  <Card title="Slop taxonomy" href="/slop-taxonomy">
    Categories and named signals shared by the field guide and skill.
  </Card>
  <Card title="Quickstart" href="/quickstart">
    Shortest path to a first scanner report and field-guide run.
  </Card>
</CardGroup>

---

## 09. Apply clean fixes

> Map scanner hits to remediation steps from the fixes playbook, choose propose vs apply in an agent host, and confirm the clean alternative.

- Page Markdown: https://grok-wiki.com/public/docs/yetone-kill-ai-slop-c0d8c9670cbb/pages/09-apply-clean-fixes.md
- Generated: 2026-07-11T08:25:12.107Z

### Source Files

- `skill/references/fixes.md`
- `skill/SKILL.md`
- `skill/references/detection.md`
- `website/src/data/demos.ts`
- `website/src/components/BeforeAfter.astro`

---
title: "Apply clean fixes"
description: "Map scanner hits to remediation steps from the fixes playbook, choose propose vs apply in an agent host, and confirm the clean alternative."
---

After triage and the pre-edit report, **kill-ai-slop** remediates confirmed tells through the agent skill’s **Fix** step: map each hit to a direction in `skill/references/fixes.md`, apply the minimal edit (or only propose it), then re-scan and visually check that the clean alternative holds. The standalone scanner (`node scripts/scan.mjs`) **never edits files** — only an agent host that loads the skill can write changes.

## Prerequisites

| Requirement | Detail |
| --- | --- |
| Agent skill | `kill-ai-slop` installed in a coding agent (`skill/SKILL.md`) |
| Prior steps | Scope → Scan → Triage → Report already done; do **not** mass-edit before the user has seen the report |
| Playbook | `skill/references/fixes.md` (before→after directions per tell) |
| Scanner | `node scripts/scan.mjs <root>` and optional `--json` for machine-readable triage |
| Optional visual ref | Field-guide demos in `website/src/data/demos.ts` via `BeforeAfter.astro` (Slop / Clean) |

<Warning>
Do not treat scanner output as a verdict. Every hit is a lead: open the file, decide **slop vs intentional**, and keep deliberate brand choices (tokens, logos, real illustrations).
</Warning>

## Propose vs apply

The skill workflow splits **proposal** (Report) from **application** (Fix). The scanner never crosses that boundary.

```text
Scanner (read-only)          Agent host (skill)
─────────────────            ──────────────────
scan.mjs → hits              triage (slop vs intentional)
                             report + proposed fix per group
                             ask: which groups / all?
                             ── user decision ──
                             apply minimal diffs (Fix)
                             re-scan + visual check
```

| Mode | When | What the agent does | Files written? |
| --- | --- | --- | --- |
| **Propose** | Always before edits; default until the user chooses groups | Group confirmed hits; one-sentence why + proposed fix; ask which groups to apply or whether to proceed on all | No |
| **Apply** | After the user approves some or all groups | Minimal change per tell using `references/fixes.md`; prefer shared tokens/components | Yes (explicit paths only) |

Report format the skill mirrors:

```text
slop  src/Hero.tsx:12   indigo→violet gradient        → one solid accent
slop  src/Hero.tsx:31   gradient-clip headline        → solid ink, scale up
slop  src/Note.tsx:8    border-l-4 callout ×3         → 1 aside, rest is body
slop  copy.md:1         "not just X — it's Y"         → say the specific thing
→ 4 groups, 11 hits.
```

Then ask which groups to apply, or whether to proceed on all.

## Fix procedure

<Steps>
  <Step title="Hold the fix principles">
    On every change: decide before you decorate; one accent, one voice; hierarchy from scale and space; subtract first; prefer specific copy over punchy copy; decoration only when it is a real signal.
  </Step>
  <Step title="Order of operations (playbook)">
    1. Design tokens / theme first (colors, radius, fonts) — many hits drop at once.  
    2. Shared components, then one-off call sites.  
    3. Copy last.
  </Step>
  <Step title="Map each approved group to a playbook section">
    Look up the tell in `skill/references/fixes.md` (numbered **01–23**). Patterns are **directions**, not find-and-replace rules — adapt to project tokens and framework.
  </Step>
  <Step title="Apply the minimal edit">
    Preserve intent and function. Prefer editing shared tokens/components over every call site. Never invent new brand colors: if palette must change, propose neutrals + the project’s existing accent and let the user confirm. Keep copy meaning; make it specific rather than deleting it.
  </Step>
  <Step title="Confirm the clean alternative">
    Re-run the scanner and note intentional leftovers with reasons. If a dev server exists, compare before/after visually — a green scan is not the same as a better page. Optional: match the tell’s field-guide demo (`before` → `after` in `demos.ts`).
  </Step>
</Steps>

### Re-scan commands

```bash
node scripts/scan.mjs <root>          # human-readable grouped report
node scripts/scan.mjs <root> --json   # machine-readable for triage
```

Success signal: hit count for the fixed tells drops; remaining hits are either unapproved groups or intentional keeps with a stated reason.

## Map scanner hits → remediation

Use the tell name from the report (or taxonomy id) as the key into `references/fixes.md`. Summary of the playbook direction and the clean outcome:

| Tell | Remediation direction | Clean outcome |
| --- | --- | --- |
| **01** Indigo→violet gradient | Solid accent class/token; drop colored glow shadow; if gradient kept, single-hue, low contrast, justified | One solid, chosen accent |
| **02** Gradient headline text | Solid ink; use scale/weight for impact | Solid heading, no `bg-clip-text` default |
| **03** Warm “cozy” palette | Near-neutral paper/ink/rule; one warm accent only; propose neutrals, confirm before global apply | Neutral base + one accent |
| **04** Default semantic palette | Neutrals + at most one–two intentional semantic colours (not stock blue/green/amber/red set) | Coherent chips from brand palette |
| **05** One-hue status box | State in a word; neutral surface + border; one muted accent | Neutral alert, not mono-hue wash |
| **06** Gradients as atmosphere | Flat background; hairline/border for depth; glow only if it points at one element | Flat held surfaces |
| **07** Serif-italic on one word | Emphasize by weight/position, one voice | Bold (or structure), not serif/italic span in sans heading |
| **08** Serif where sans belongs | UI sans in font tokens; serif only for genuine editorial product voice | Sans UI/body unless editorial |
| **09** Decorative strikes & highlights | Remove decorative `<s>`/`<u>`/`<mark>`; keep real edits, links, annotations | Structure carries emphasis |
| **10** Highlighted keywords | Specific prose; at most one accented phrase | No multi-color keyword soup |
| **11** AI copywriting voice | Rewrite for specifics; delete triads and em-dash drama | Concrete claims, not “not just X — it’s Y” |
| **12** Emoji everywhere | Remove from headings/buttons/bullets; keep only if real status info | Plain chrome labels |
| **13** Glowing status dot | Flat dot + word; no ping/pulse/glow shadow | Small flat status marker |
| **14** Rounded card, colored left border | Collapse stacked callouts to body; at most one real `<aside>` | Prose + one aside |
| **15** Rounded-square icon tiles | Labelled list with real specifics; drop decorative tiles | Specific feature lines |
| **16** Max radius + glassmorphism | One small radius token; solid surfaces instead of blur panes | Solid card, consistent radius |
| **17** Oversized drop shadow | Tight elevation or hairline; colorless; never larger than the element | Hairline + tight contact shadow |
| **18** Corners that don’t nest | Inner radius = outer − padding, or no inner radius | Concentric nested corners |
| **19** Badge & pill spam | Delete decorative pills; keep at most a real status/version tag | e.g. `v2.1` only |
| **20** AI-drawn SVG icons | Real designed or refined icon; no crude blob-with-dot-eyes; no bare letter fallback | Crisp on-brand mark |
| **21** Icon in a tint of itself | Icon inherits text color; no tinted tile container | Bare icon (or deliberate opaque surface) |
| **22** All-caps card grid | One important point told fully; drop equal-weight CAPS micro-labels | Lead + supporting prose |
| **23** Tasteful terminal | Monospace for code only; terminal chrome only when product-serving | UI not faux-terminal |

<Note>
Full before→after diffs live in `skill/references/fixes.md`. Detection patterns and false positives live in `skill/references/detection.md` — use them during triage, not as auto-apply rules.
</Note>

### Example: report line → playbook → edit

**Report:** `slop  src/Hero.tsx:12   indigo→violet gradient → one solid accent`

**Playbook (01):**

```diff
- class="bg-gradient-to-r from-indigo-500 to-purple-500 shadow-lg shadow-purple-500/50"
+ class="bg-[--accent]"      /* one solid, chosen accent */
```

**Verify:** re-run scanner on the project root; open Hero in the running app if available.

## Confirm the clean alternative

### 1. Scanner delta

| Check | Expected |
| --- | --- |
| Count for fixed tells | Lower than pre-fix report |
| Leftover hits | Listed with reason (intentional brand / unapproved group) |
| Unrelated files | Untouched (no drive-by reformat) |

### 2. Visual check (when a dev server exists)

Compare the live UI before and after. Prefer this over scan-only success for surfaces that grep poorly (e.g. nested corner radius, AI SVG judgment).

### 3. Field-guide before/after demos

The site encodes the preferred clean outcome as plain HTML pairs in `website/src/data/demos.ts` (`before` / `after`). `website/src/components/BeforeAfter.astro` renders them with a Slop / Clean toggle (`data-show="before" | "after"`). Demo `after` panes follow the same rules the skill enforces: one accent, no gradient chrome, hierarchy from scale + space, mono for code only, no decorative emoji/badges.

| Demo id (`demos.ts`) | Illustrates (approx.) |
| --- | --- |
| `indigo-violet-gradient` | Solid card/button vs gradient chrome |
| `gradient-text` | Solid head vs gradient-clip head |
| `warm-cozy-palette` | Neutral workspace card vs amber wash |
| `default-semantic-palette` | Coherent chips vs stock semantic rainbow |
| `serif-emphasis` | Bold vs serif-italic single word |
| `serif-body-misuse` | Sans panel vs display serif UI |
| `decorative-text-lines` | Plain head vs strike/underline/mark |
| `highlighted-keywords` | Specific copy vs colored keyword spans |
| `ai-copy-tics` | Specific product copy vs AI voice tics |
| `emoji-everywhere` | Specific bullets vs emoji list |
| `status-dot-glow` | Flat dot vs glowing/live status |
| `left-border-callout` | Plain list vs stacked colored callouts |
| `pastel-icon-tiles` | Specific feature list vs icon tiles |
| `over-rounded-glass` | Flat solid card vs glass/pill |
| `oversized-shadow` | Hairline + tight shadow vs room-sized fog |
| `badge-spam` | Version tag vs pill spam |
| `feature-grid` | Focused narrative vs CAPS card grid |

Use demos as a **target shape**, not as pasteable production markup — adapt to the host project’s tokens.

## Guardrails while applying

| Rule | Behavior |
| --- | --- |
| Authorship | Unfamiliar files and deliberate flourishes: ask, don’t strip |
| Diff size | Small, reviewable; never reformat unrelated code |
| Staging | Never `git add -A`; stage explicit files only; leave others’ WIP alone |
| Dependencies | No new packages solely to de-slop |
| Brand colors | Propose neutrals + existing accent; user confirms global palette changes |
| Palette (03) | Propose neutral values; confirm before applying globally |
| Scanner role | Pure Node, no deps, **never edits files** |

## Troubleshooting

| Symptom | Likely cause | Action |
| --- | --- | --- |
| Scan still reports a “fixed” file | Pattern still matches (e.g. leftover utility class) or intentional keep | Re-open file; finish token-level fix or document intentional leave |
| Mass visual regression | Applied without Report approval or edited all call sites | Revert; re-report by group; fix tokens/components first |
| Brand looks wrong after palette swap | Invented colors or global cozy→neutral without confirm | Stop; re-propose neutrals + existing accent |
| Copy became empty or generic | Deleted instead of specified | Restore meaning; rewrite to concrete claims (playbook 11/10) |
| Nested radius still looks off | Same `rounded-*` on outer and inner | Inner ≈ outer − padding (playbook 18) |
| Agent edited without asking | Skipped Report step | Treat as process failure; show report and re-ask groups |

## Related pages

<CardGroup>
  <Card title="Skill workflow" href="/skill-workflow">
    Full lifecycle: scan, triage, report, then propose or apply without silent scanner edits.
  </Card>
  <Card title="Remediation playbook" href="/fixes-playbook">
    Per-tell clean fixes, remove/replace guidance, and before/after directions.
  </Card>
  <Card title="Scan a web project" href="/scan-web-project">
    Point the scanner at a path and interpret grouped vs JSON reports.
  </Card>
  <Card title="Detection patterns" href="/detection-patterns">
    Code-level signals and false positives used when confirming hits.
  </Card>
  <Card title="Use the agent skill" href="/use-agent-skill">
    Invoke kill-ai-slop in a coding agent host after install.
  </Card>
  <Card title="Scanner CLI reference" href="/scanner-cli-reference">
    Invocation, `--json`, and the hard constraint that the scanner never edits files.
  </Card>
</CardGroup>

---

## 10. Run the field guide site

> Develop and preview the multilingual Astro field guide: install, dev server, static build output, and how entries and demos render on the index.

- Page Markdown: https://grok-wiki.com/public/docs/yetone-kill-ai-slop-c0d8c9670cbb/pages/10-run-the-field-guide-site.md
- Generated: 2026-07-11T08:25:13.466Z

### Source Files

- `website/astro.config.mjs`
- `website/src/pages/index.astro`
- `website/src/layouts/Base.astro`
- `website/src/components/SlopEntry.astro`
- `website/src/components/LangToggle.astro`
- `README.md`

---
title: "Run the field guide site"
description: "Develop and preview the multilingual Astro field guide: install, dev server, static build output, and how entries and demos render on the index."
---

The field guide lives under `website/` as a static Astro app: multilingual content (English, Chinese, Japanese, Korean), zero-JS-by-default, and a single-page index that renders the 23-tell catalogue from `website/src/data/catalogue.ts`. Live production is `https://killaislop.com`; local work is install → `npm run dev` → optional `npm run build` into `dist/`.

## Surface and layout

| Path | Role |
|------|------|
| `website/` | Astro field guide (multilingual, static) |
| `website/astro.config.mjs` | Site URL and lean build options |
| `website/src/pages/index.astro` | Index: hero, definition, catalogue section, principles data |
| `website/src/layouts/Base.astro` | Document shell, SEO, pre-paint prefs, Nav/Footer |
| `website/src/components/SlopEntry.astro` | One catalogue entry (copy, demo, signals) |
| `website/src/components/LangToggle.astro` | Language menu → `html[data-lang]` |
| `website/src/data/catalogue.ts` | Taxonomy / entry source of truth (shared with the skill) |
| `website/src/styles/tokens.css` | Design self-constraints (paper/ink, one accent) |

Repo split from the root README: `website/` is the guide; `skill/` is the agent skill and scanner (separate runtime).

## Prerequisites

- Node.js and npm available on the machine.
- Working tree that includes the `website/` package (clone of `yetone/kill-ai-slop` or equivalent).

No Astro integrations are configured. `astro.config.mjs` is intentionally dependency-light: `site` plus `build.inlineStylesheets: 'auto'` only.

## Install and run

<Steps>
  <Step title="Install website dependencies">
    From the repository root:

```bash
cd website
npm install
```

  </Step>
  <Step title="Start the dev server">
```bash
npm run dev
```

    Open **http://localhost:4321**. Success signal: the field guide index loads with the hero kicker, definition section, and catalogue heading for 23 tells.
  </Step>
  <Step title="Build static output (optional)">
```bash
npm run build
```

    Output goes to **`dist/`** (static files; deploy anywhere static hosting accepts).
  </Step>
</Steps>

<RequestExample>
```bash
cd website
npm install
npm run dev        # http://localhost:4321
npm run build      # → dist/
```
</RequestExample>

<Check>
Dev server on port **4321** and a populated **`dist/`** after build are the primary local success signals documented for the website.
</Check>

## Astro configuration

`website/astro.config.mjs`:

| Key | Value | Notes |
|-----|--------|--------|
| `site` | `https://killaislop.com` | Used for absolute canonical/OG URLs in `Base.astro` |
| `build.inlineStylesheets` | `'auto'` | Stylesheet inlining policy |
| Integrations | none | Comment in config: no integrations by design; keep the build artifact lean |

Canonical and Open Graph image URLs in the layout are built as `new URL(Astro.url.pathname, Astro.site)` and `new URL("/og.png", Astro.site)`.

## Index page structure

`website/src/pages/index.astro` wraps content in `Base` and imports `catalogue` plus `SlopEntry`. Documented sections on the index include:

| Anchor | Content |
|--------|---------|
| `#top` | Hero: multilingual kicker, title variants per language, lede, CTAs |
| `#what` | Definition of AI slop (`data-index="00"`) |
| `#catalogue` | Catalogue header (`data-index="01"`): 23 tells, before → after pairs in plain HTML |
| `#skill` | Linked from hero ghost CTA (“Get the cleanup skill”) |

Hero CTAs:

- Primary → `#catalogue` (“See the catalogue”)
- Ghost → `#skill` (“Get the cleanup skill”)

Frontmatter also defines a `principles` array (six multilingual `head` / `body` pairs: decide before decorate, one accent, hierarchy from scale/space, subtract first, specific beats loud, decoration must mean something). Those strings are co-located on the index page for the site’s anti-slop messaging.

Copy on the page is mostly rendered through the `<T>` component with `en` / `zh` / `ja` / `ko` props (hero title uses `data-t` spans for the four locales).

## How catalogue entries and demos render

Each tell is an `Entry` from `catalogue`. `SlopEntry` is the presentational unit:

```astro
<article class="entry" id={entry.id}>
  <!-- number, group tag, title, what -->
  {entry.demo && <BeforeAfter id={entry.demo} />}
  <!-- Why it's slop / The fix -->
  <!-- Code signals: entry.detect as <code> chips -->
</article>
```

### Entry chrome

| Element | Behavior |
|---------|----------|
| `id={entry.id}` | Deep-link target for `/#entry-id` |
| Number | `String(entry.n).padStart(2, "0")`; permalink control |
| Group tag | `<T {...GROUPS[entry.group]} />` with tier class `t${entry.tier}` (tier `2` is inverted ink-on-paper styling) |
| Title / what | `<T {...entry.title} />`, `<T {...entry.what} />` |
| Demo | If `entry.demo` is set, `<BeforeAfter id={entry.demo} />` |
| Why / fix | Multilingual labels + `entry.why` / `entry.fix` |
| Code signals | `entry.detect` list items as `<code>` |

Demos are plain-HTML rebuilds of the slop tell and the clean alternative (README: interactive before → after; catalogue lede: click to switch). They exist for commentary and education, not as live scrapes of third-party products.

### Permalink interaction

Clicking `a.num.permalink`:

1. `preventDefault`
2. `history.replaceState` to `#${id}` (no extra history entries)
3. Smooth-scrolls the entry into view
4. Copies `origin + pathname + #id` to the clipboard when available, then flashes a `copied` class (~1.4s) so the affordance shows `✓`

Sticky-nav offset for deep links is handled globally (`html { scroll-padding-top }`); entries do not double-offset themselves.

## Multilingual runtime

Languages supported in UI chrome and pre-paint resolution: **en**, **zh**, **ja**, **ko**.

### Pre-paint (`Base.astro` inline scripts)

| Storage key | Default / resolution | Effect |
|-------------|----------------------|--------|
| `kas-lang` | English default; if unset/invalid, map `navigator.language` prefix `zh`/`ja`/`ko`, else `en` | Sets `documentElement.dataset.lang` and `lang` (`en`, `zh-Hans`, `ja`, `ko`) |
| `kas-sound` | On unless stored `"off"` | `dataset.sound` = `on` \| `off` (avoids muted users hearing stray sweep sound) |
| `kas-theme` | Unset follows OS `@media`; only explicit `"light"` or `"dark"` stored | `dataset.theme` when set |

Language choice is the source of truth for `<T>` and global CSS selectors on `html[data-lang]`.

### Language menu (`LangToggle.astro`)

- Custom dropdown (not native `<select>`), labels: EN / 中文 / 日本語 / 한국어.
- On select: `localStorage.setItem("kas-lang", lang)`, then `apply(lang)` updates `data-lang`, `lang`, trigger label, and `aria-checked` on options.
- Reflects whatever the head pre-paint script already resolved (`apply(root.dataset.lang || "en")`).

Open Graph locales advertised: `en_US` plus alternates `zh_CN`, `ja_JP`, `ko_KR`.

## Document shell and deep links

`Base.astro` defaults:

| Prop | Default |
|------|---------|
| `title` | `Kill AI Slop — 杀死 AI slop` |
| `description` | Field-guide bilingual blurb (EN + ZH) |

Also sets: `color-scheme: light dark`, canonical URL, OG/Twitter large image (`/og.png`, 1200×630), favicon `/favicon.svg`, skip link to `#main`, `Nav` above `<main id="main">`, `Footer` after.

Deep-link landing script:

- On load, if `location.hash` is present, scrolls the matching element with `block: "start"` (instant, before smooth nav is enabled).
- Then, unless `prefers-reduced-motion: reduce`, adds class `nav-ready` so later in-page navigation can use smooth scrolling.

## Design constraints (site as rebuttal)

The site is intentionally not “slop”: paper + ink, **one** editorial accent (proofreader’s pen), hierarchy from scale and space, hairline rules; no gradients / emoji / glass / badges as the house style. Self-rules live in `website/src/styles/tokens.css`. Taxonomy and entry data live in `website/src/data/catalogue.ts` (shared language with the skill).

Astro comment in config: the build artifact should stay as lean as the aesthetic the site argues for.

## Verification checklist

| Check | Expected |
|-------|----------|
| `npm run dev` | Site at `http://localhost:4321` |
| Hero | Multilingual field-guide kicker; CTAs to catalogue and skill |
| `#catalogue` | Copy claims **23** tells, each a before → after HTML demo |
| Language menu | Switching updates chrome and persisted `kas-lang` without full reload flash (pre-paint + dropdown) |
| Entry permalink | URL hash updates; clipboard may receive shareable `#id` URL |
| `npm run build` | Static tree under `website/dist/` |

## Troubleshooting

| Symptom | What to check |
|---------|----------------|
| Wrong language on first paint | Clear or set `localStorage.kas-lang`; confirm browser language mapping only applies when no valid stored key |
| Flash of wrong theme | Only stored `light`/`dark` force theme; otherwise OS media query applies—ensure `kas-theme` is not stale |
| Hash link lands under sticky nav | Rely on global `scroll-padding-top`; deep-link script re-scrolls on `load` for layout shift |
| Demo missing on an entry | `SlopEntry` only mounts `BeforeAfter` when `entry.demo` is truthy |
| Clipboard / ✓ flash fails | Permalink still updates hash and scrolls; clipboard is best-effort (`.catch(() => {})`) |

## Related pages

<CardGroup>
  <Card title="Installation" href="/installation">
    Install website dependencies and the kill-ai-slop skill for local work.
  </Card>
  <Card title="Build and deploy" href="/build-and-deploy">
    Static `dist/` output, deploy-anywhere assumptions, zero-JS-by-default ops notes.
  </Card>
  <Card title="Catalogue model" href="/catalogue-model">
    How `catalogue.ts` is the single source of truth and how demos/i18n attach.
  </Card>
  <Card title="Catalogue and demos data" href="/catalogue-data-reference">
    Fields and shapes for entries, locale copy, and demo HTML payloads.
  </Card>
  <Card title="Design tokens" href="/design-tokens">
    Paper/ink palette, single editorial accent, hierarchy rules, banned defaults.
  </Card>
  <Card title="Extend the catalogue" href="/extend-catalogue">
    Add or update a tell end-to-end on the site and skill taxonomy.
  </Card>
  <Card title="Quickstart" href="/quickstart">
    Shortest path to a first scanner report and a local field-guide run.
  </Card>
</CardGroup>

---

## 11. Extend the catalogue

> Add or update a tell: catalogue entry, i18n strings, plain-HTML demo, and alignment with skill taxonomy, detection, and fix references.

- Page Markdown: https://grok-wiki.com/public/docs/yetone-kill-ai-slop-c0d8c9670cbb/pages/11-extend-the-catalogue.md
- Generated: 2026-07-11T08:25:45.848Z

### Source Files

- `website/src/data/catalogue.ts`
- `website/src/data/catalogue.i18n.ts`
- `website/src/data/demos.ts`
- `skill/references/taxonomy.md`
- `skill/references/detection.md`
- `skill/references/fixes.md`

---
title: "Extend the catalogue"
description: "Add or update a tell: catalogue entry, i18n strings, plain-HTML demo, and alignment with skill taxonomy, detection, and fix references."
---

Extending a tell in **yetone/kill-ai-slop** means keeping six surfaces in lockstep: `website/src/data/catalogue.ts` (site + skill catalogue SSoT), `website/src/data/catalogue.i18n.ts` (`ja`/`ko`), `website/src/data/demos.ts` (plain-HTML before→after), `styles/demos.css` (scoped under `.demo-<id>`), and the skill references `skill/references/taxonomy.md`, `detection.md`, and `fixes.md` (plus `scripts/scan.mjs`, which encodes detection patterns). Catalogue copy is numbered by array position; skill docs use matching ordinals (`01`, `02`, …). Inserting an entry renumbers later catalogue `n` values automatically.

## Surfaces to change

| Surface | Path | Role |
| --- | --- | --- |
| Catalogue entry | `website/src/data/catalogue.ts` | Single source of truth for tells: id, tier, group, `title`/`what`/`why`/`fix`, `detect[]`, optional `demo` key |
| JA/KO copy | `website/src/data/catalogue.i18n.ts` | Per-id `ja`/`ko` for `title` \| `what` \| `why` \| `fix`; missing fields fall back to English at the `<T>` layer |
| Demo HTML | `website/src/data/demos.ts` | `Record<string, { before: string; after: string }>` keyed by the catalogue `demo` string |
| Demo styles | `styles/demos.css` | Styles for demos, scoped under `.demo-<id>` |
| Taxonomy | `skill/references/taxonomy.md` | Human taxonomy: 23 tells, two tiers; what / why / fix in prose |
| Detection | `skill/references/detection.md` | Human + widen-able patterns; `scripts/scan.mjs` encodes these |
| Fixes | `skill/references/fixes.md` | Before→after directions (not blind find-and-replace) |

```text
website/src/data/
  catalogue.ts        ← Entry (en + zh inline), Groups, rawEntries → n
  catalogue.i18n.ts   ← ja/ko keyed by entry id
  demos.ts            ← before / after HTML by demo key
styles/
  demos.css           ← .demo-<id> …
skill/references/
  taxonomy.md         ← ###-style **NN · Name**
  detection.md        ← ### NN Name + rg patterns
  fixes.md            ← ### NN Name + diff directions
scripts/
  scan.mjs            ← encodes detection.md patterns
```

<Note>
Earlier catalogue drafts used annotated screenshots of a reference product. Those were removed in favour of live HTML demos so the comparison stays precise and does not drift.
</Note>

## Catalogue entry shape

`catalogue.ts` defines the website catalogue and the spec the skill enforces.

### Types

| Name | Shape |
| --- | --- |
| `Group` | `"color" \| "type" \| "copy" \| "component" \| "layout" \| "evolved"` |
| `Bi` | `{ en: string; zh: string; ja?: string; ko?: string }` — English is always present; `zh` is written inline in `catalogue.ts`; `ja`/`ko` are merged from `catalogue.i18n.ts` |
| `Entry` | `id`, `n`, `tier` (`1` \| `2`), `group`, `title`/`what`/`why`/`fix` as `Bi`, `detect: string[]`, optional `demo?: string` |

`rawEntries` is `Omit<Entry, "n">[]`. Entries are numbered by position in that array; inserting renumbers the rest.

### Required fields when adding a tell

| Field | Constraint |
| --- | --- |
| `id` | Stable kebab-case string used across i18n and demos (e.g. `indigo-violet-gradient`, `mono-hue-alert`) |
| `tier` | `1` classic (widely recognised) or `2` evolved (newer templated defaults) |
| `group` | One of the `Group` keys; drives site grouping via `GROUPS` |
| `title`, `what`, `why`, `fix` | At least `en` and `zh` on each `Bi` in `catalogue.ts` |
| `detect` | Short code-level signal strings (mono chips + skill heuristics), not full `rg` scripts |
| `demo` | Key into `demos.ts` / `.demo-<id>` styles; omit only if there is intentionally no live demo |

### Example entry (from catalogue)

```ts
// website/src/data/catalogue.ts — pattern for a rawEntries item
{
  id: "indigo-violet-gradient",
  tier: 1,
  group: "color",
  title: { zh: "蓝紫渐变", en: "The indigo→violet gradient" },
  what: {
    zh: "从 #6366f1 到 #a855f7 的紫色对角渐变，按钮、光晕、hero 背景，无处不在。",
    en: "That #6366f1→#a855f7 diagonal on buttons, glows, and hero backgrounds.",
  },
  why: { /* en + zh */ },
  fix: { /* en + zh */ },
  detect: [
    "from-indigo-500 to-purple-500",
    "#6366f1 → #a855f7",
    "bg-gradient-to-r via-purple",
    "shadow-purple-500/50",
  ],
  demo: "indigo-violet-gradient",
}
```

### Groups

| `group` | English label (`GROUPS`) |
| --- | --- |
| `color` | Color |
| `type` | Type |
| `copy` | Copy |
| `component` | Components |
| `layout` | Layout |
| `evolved` | Evolved slop |

## Skill ↔ site id alignment

Taxonomy, detection, and fixes are ordered **01–N** with human titles. The site uses **stable string ids**. Keep ordinals, titles, and ids consistent when you insert or reorder.

| Ordinal (skill refs) | Catalogue / demo id (examples) |
| --- | --- |
| 01 Indigo→violet gradient | `indigo-violet-gradient` |
| 02 Gradient headline text | `gradient-text` |
| 03 Warm "cozy" palette | `warm-cozy-palette` |
| 04 Default semantic palette | `default-semantic-palette` |
| 05 One-hue status box | `mono-hue-alert` |
| 07 Serif-italic on one word | `serif-emphasis` |
| 08 Serif where sans belongs | `serif-body-misuse` |
| 09 Decorative strikes & highlights | `decorative-text-lines` |
| 10 Highlighted keywords | `highlighted-keywords` |
| 11 AI copywriting voice | `ai-copy-tics` |
| 12 Emoji everywhere | `emoji-everywhere` |
| 13 Glowing status dot | `status-dot-glow` |
| 14 Rounded card, colored left border | `left-border-callout` |
| 15 Rounded-square icon tiles | `pastel-icon-tiles` |
| 16 Max radius + glassmorphism | `over-rounded-glass` |

Taxonomy states **23 tells** in two tiers. Detection and fixes use the same numbering scheme; detection notes that every match is a **lead, not a verdict**, and that `scan.mjs` encodes the patterns while the markdown is the place to widen stack-specific signals.

## Add a new tell

<Steps>
  <Step title="Define the tell in the shared language">
    Write what it is, why it reads as machine-made (default / absence of a decision), and the clean move. Taxonomy rule: the same element chosen and defended is not slop.
  </Step>
  <Step title="Insert `rawEntries` in `catalogue.ts`">
    Place the object in the correct group section. Supply `id`, `tier`, `group`, `en`+`zh` for `title`/`what`/`why`/`fix`, `detect[]`, and `demo` key when shipping a live comparison. Do not set `n` by hand — position assigns it.
  </Step>
  <Step title="Add JA/KO in `catalogue.i18n.ts`">
    Key by the same `id`. Shape:

```ts
// website/src/data/catalogue.i18n.ts
export interface EntryI18n {
  ja?: LangText; // Partial<record of title|what|why|fix>
  ko?: LangText;
}

// i18n: Record<string, EntryI18n>
"indigo-violet-gradient": {
  ja: { title: "…", what: "…", why: "…", fix: "…" },
  ko: { title: "…", what: "…", why: "…", fix: "…" },
},
```

    Partial translations are safe: missing fields fall back to English at `<T>`.
  </Step>
  <Step title="Add `before` / `after` HTML in `demos.ts`">
    Key must match catalogue `demo`. Styles live under `.demo-<id>` in `styles/demos.css`. Demo copy stays short and neutral.
  </Step>
  <Step title="Update skill references">
    - `taxonomy.md` — new **NN · Name** under the right section (Color / Type / Copy / Components / …), with what, why, and *Fix*.
    - `detection.md` — `### NN Name`, `rg` (or hard-to-grep) signals, false-positive / confirm notes. Scan scope remains frontend extensions listed in that file; skip dirs like `node_modules`, `dist`, lockfiles, `*.min.*`.
    - `fixes.md` — `### NN Name`, directional `diff` examples. Prefer token/theme fixes first, then components, then call sites, then copy.
    - Encode new patterns in `scripts/scan.mjs` to match `detection.md`.
  </Step>
  <Step title="Renumber skill ordinals if you inserted mid-list">
    Catalogue `n` follows array order. Skill files use explicit `01`… labels — keep them aligned with catalogue position after insert/delete.
  </Step>
</Steps>

## Update an existing tell

| Change | Touch |
| --- | --- |
| English or Chinese wording | `catalogue.ts` only (`en` / `zh`) |
| Japanese or Korean | `catalogue.i18n.ts` for that `id` |
| Detection chips on the site | `detect[]` in `catalogue.ts` **and** patterns in `detection.md` / `scan.mjs` |
| Remediation guidance | `fix` copy in catalogue + i18n **and** `fixes.md` |
| Live comparison | `demos.ts` + `.demo-<id>` CSS |
| Rename `id` | Update catalogue entry, i18n key, demos key, `demo` field, and CSS scope together — ids are the join key |

## Copy and voice rules

Catalogue and i18n share one voice contract (site argues against slop, so it must not commit it):

- Terse, plain, specific.
- No punchy three-word triads.
- No “not just X, it’s Y”.
- No exclamation-driven hype.

`what` is one line: what the tell is. `why` explains machine-made defaults. `fix` is the clean move (tokens/components preferred over mass call-site edits — same order as `fixes.md`).

## Demo requirements

`demos.ts` rebuilds each tell in plain HTML:

| Pane | Constraint |
| --- | --- |
| `before` | Illustrates the tell (gradient chrome, emoji chrome, glass pills, etc.) |
| `after` | Held to site/skill rules: one accent, no gradient chrome, hierarchy from scale + space, mono for code only, no decorative emoji/badges |

Example structure:

```ts
// website/src/data/demos.ts
export const demos: Record<string, { before: string; after: string }> = {
  "gradient-text": {
    before: `<h5 class="grad-head">Your changelog, automated</h5>
      <p class="sub">It writes release notes from merged PRs.</p>`,
    after: `<h5 class="solid-head">Your changelog, automated</h5>
      <p class="sub">It writes release notes from merged PRs.</p>`,
  },
  // …
};
```

`after` for copy tells should prefer specifics (numbers, nouns, consequences) over triads and em-dash drama — same direction as fix **11** / id `ai-copy-tics`.

## Detection and fixes alignment

### Detection (`detection.md` → `scan.mjs`)

- Patterns are concrete `rg` (or similar) signals per tell.
- Scope: `.html .css .scss .tsx .jsx .ts .js .vue .svelte .astro .md .mdx` plus `tailwind.config.*`; skip build/vendor/min/lock paths listed in the file.
- Document false positives and “confirm” notes next to the patterns.
- Catalogue `detect[]` should read as short human chips that match the same signals (e.g. `bg-clip-text text-transparent`, not a full multi-line script).

### Fixes (`fixes.md`)

General order of operations:

1. Design tokens / theme (colors, radius, fonts) — many hits disappear at once.
2. Components, then one-off call sites.
3. Copy last.

Fixes are **directions** adapted to the project’s tokens and framework, not mechanical replace-all rules. Cross-link related tells where the playbook already does (e.g. oversized shadow vs purple glow vs status-dot halo).

## Verification checklist

After an add or update:

| Check | Pass signal |
| --- | --- |
| Catalogue | New/updated object in `rawEntries`; `id` unique; `tier`/`group` valid; `en`+`zh` complete |
| Numbering | Site order and skill `### NN` / `**NN ·` labels still correspond after insert |
| i18n | `i18n[id]` present for `ja`/`ko` or intentional English fallback |
| Demo join | `entry.demo` equals a key in `demos` (when set); `.demo-<id>` styles exist for the HTML classes used |
| Demo quality | `after` has no decorative gradient chrome, emoji spam, glass/pill max-radius as the default, or multi-hue keyword highlighting |
| Detection | `detection.md` section exists; `scan.mjs` encodes equivalent signals; false-positive notes written |
| Fixes | `fixes.md` section exists with directional before→after |
| Taxonomy | `taxonomy.md` prose matches catalogue `what`/`why`/`fix` intent |

<Warning>
Do not treat catalogue `detect` chips or scanner hits as verdicts. Detection reference: every match is a lead — open the file and confirm.
</Warning>

## Common failure modes

| Failure | Effect |
| --- | --- |
| New catalogue row without skill ordinals | Field guide shows the tell; skill/scanner language drifts |
| Skill section without catalogue `id` | Agents detect/fix a tell the site does not list |
| `demo` key typo | Missing or empty before/after pane |
| i18n key ≠ `id` | JA/KO never attach; silent English fallback |
| Insert mid-array without renumbering skill files | Wrong tell mapped to wrong detection/fix block |
| Sloppy i18n/demo copy (triads, “not just…”) | Site contradicts its own taxonomy |
| Detection only in markdown, not `scan.mjs` | Human reference and scanner diverge |

## Related pages

<CardGroup>
  <Card title="Catalogue model" href="/catalogue-model">
    How `catalogue.ts` is the single source of truth, how demos and i18n attach, and site vs skill boundaries.
  </Card>
  <Card title="Catalogue and demos data" href="/catalogue-data-reference">
    Field-level shapes for `catalogue.ts`, `catalogue.i18n.ts`, and `demos.ts`.
  </Card>
  <Card title="Slop taxonomy" href="/slop-taxonomy">
    Categories, named signals, and shared language between field guide and skill.
  </Card>
  <Card title="Detection patterns" href="/detection-patterns">
    Code-level signals per tell and how findings map to taxonomy ids.
  </Card>
  <Card title="Remediation playbook" href="/fixes-playbook">
    Per-tell clean fixes and how before/after demos illustrate the preferred outcome.
  </Card>
  <Card title="Run the field guide site" href="/run-field-guide-site">
    Local Astro preview so new entries and demos render on the index.
  </Card>
  <Card title="Contributing" href="/contributing">
    Where to change skill references, scanner logic, catalogue data, or site components without breaking alignment.
  </Card>
</CardGroup>

---

## 12. Scanner CLI reference

> Invocation, path argument, --json mode, walk/scan behavior, console formatting helpers, and hard constraint that the scanner never edits files.

- Page Markdown: https://grok-wiki.com/public/docs/yetone-kill-ai-slop-c0d8c9670cbb/pages/12-scanner-cli-reference.md
- Generated: 2026-07-11T08:25:36.193Z

### Source Files

- `skill/scripts/scan.mjs`
- `skill/README.md`
- `skill/references/detection.md`
- `README.md`

---
title: "Scanner CLI reference"
description: "Invocation, path argument, --json mode, walk/scan behavior, console formatting helpers, and hard constraint that the scanner never edits files."
---

`skill/scripts/scan.mjs` is a dependency-free Node CLI that walks frontend source under a root path, matches line-level patterns for 23 AI-slop tells, and prints either a grouped console report or JSON. It only uses `node:fs` and `node:path`, and its header states it **NEVER edits files**.

## Invocation

```bash
node skill/scripts/scan.mjs [root] [--json] [--no-color]
```

From inside the installed skill directory (paths relative to `skill/`):

```bash
node scripts/scan.mjs path/to/src          # human-readable report
node scripts/scan.mjs path/to/src --json   # machine-readable
```

From the repository root (as in the project README):

```bash
node skill/scripts/scan.mjs path/to/project
node skill/scripts/scan.mjs path/to/project --json
```

The script shebang is `#!/usr/bin/env node`. No npm packages, install step, or build are required.

## Arguments and flags

| Input | Type | Default | Behavior |
|---|---|---|---|
| `[root]` | path (non-flag argv) | `"."` | First `process.argv` entry that does not start with `-`. Directory tree root for `walk()`. |
| `--json` | flag | off | Emit a single JSON document on stdout; skip ANSI color and the human report. Exit with `process.exit(0)` after print. |
| `--no-color` | flag | off | Force plain text even on a TTY (when not in `--json`). |

<ParamField body="root" type="string" default=".">
First non-flag argument. Used as the walk root and as the base for `path.relative` when recording hit file paths.
</ParamField>

<ParamField body="--json" type="boolean" default="false">
When present (`args.includes("--json")`), sets `asJson` and disables color.
</ParamField>

<ParamField body="--no-color" type="boolean" default="false">
When present, or when stdout is not a TTY, or when `--json` is set, ANSI helpers become no-ops.
</ParamField>

Color enablement is exact:

```js
const useColor =
  !args.includes("--no-color") && process.stdout.isTTY && !asJson;
```

## Hard constraint: read-only

<Warning>
The scanner never writes, renames, or deletes project files. The script header, root README, and skill README all state that it only reads and reports.
</Warning>

| Surface | Edit behavior |
|---|---|
| `scripts/scan.mjs` alone | Read-only: `readdirSync`, `statSync`, `readFileSync`, `console.log`. |
| Agent skill host | Scan → triage → report → propose/apply fixes is the skill workflow in `SKILL.md` / host agent — not this CLI. |

Hits are leads to confirm in the source, not automatic remediations. A gradient, serif, or emoji may be an intentional design choice.

## Walk behavior

`walk(dir, files = [])` recursively collects candidate absolute paths.

### Skipped directories (`SKIP_DIRS`)

```
node_modules  .git  dist  build  out  .next  .astro
.output  .svelte-kit  .nuxt  coverage  vendor  .cache
.vercel  .turbo
```

Directory names in this set are not entered. If `readdirSync` throws, `walk` returns the `files` array unchanged.

### Included files

A file is pushed when:

1. Basename is **not** `*.min.js` / `*.min.css`
2. Basename is **not** a lockfile match: `package-lock`, `pnpm-lock`, or `yarn.lock`
3. Extension is in `EXTS`, **or** basename matches `/^tailwind\.config\./`

`EXTS`:

| Category | Extensions |
|---|---|
| Markup / style | `.html` `.css` `.scss` `.sass` `.less` |
| Script / components | `.tsx` `.jsx` `.ts` `.js` `.mjs` `.cjs` `.vue` `.svelte` `.astro` |
| Prose | `.md` `.mdx` |

`skill/references/detection.md` documents the same frontend-only intent; the executable skip set and extension list in `scan.mjs` are slightly broader (for example `.sass`, `.less`, `.mjs`, `.cjs`, and extra tool dirs such as `.turbo`).

## Scan behavior

`scanFile(path)` returns an array of hit objects (or `[]` on skip/error).

| Guard | Rule |
|---|---|
| Size | Skip if `statSync(path).size > 512 * 1024` (512 KiB). |
| Read errors | `catch` → `[]`. |
| Line length | Skip any line with `line.length > 2000` (minified-ish). |
| Code vs copy | `isCode = ![".md", ".mdx"].includes(extname(path))`. Tells **without** `copy: true` are skipped on prose files (`if (!tell.copy && !isCode) continue`). |
| Matching | For each remaining line and each tell, if `tell.patterns.some((re) => re.test(line))`, record a hit. |

Per-hit shape from scanning and aggregation:

| Field | Source |
|---|---|
| `line` | 1-based index (`i + 1`) |
| `text` | `line.trim().slice(0, 100)` |
| `file` (aggregated) | `relative(root, f) \|\| f` |

Aggregation: hits bucket into `Map` by `tell.id`, then sorted with `a.tell.id.localeCompare(b.tell.id)`.

### Copy-scoped tells

Only these embedded tell records set `copy: true` (also match `.md` / `.mdx`):

| id | name |
|---|---|
| `10` | highlighted keywords |
| `11` | AI copywriting voice |
| `12` | emoji everywhere |

All other tells are code/style-only relative to prose files.

## Embedded tell catalogue

The CLI encodes 23 tells inline as `TELLS` (ids `"01"`–`"23"`). Each entry has `id`, `group`, `name`, `fix`, `patterns` (array of `RegExp`), and optional `copy`.

| id | group | name | fix (one-line) |
|---|---|---|---|
| 01 | color | indigo→violet gradient | one solid, chosen accent |
| 02 | color | gradient-clip headline | solid ink, scale up |
| 03 | color | warm ‘cozy’ palette | neutral base + one warm accent |
| 04 | color | default semantic palette | one palette: neutrals + a couple of chosen states |
| 05 | color | one-hue status box | state in words; one muted accent on neutral |
| 06 | color | gradients as atmosphere | one flat bg; depth from a hairline |
| 07 | type | serif-italic emphasis | emphasise by weight, one voice |
| 08 | type | serif where sans belongs | one legible UI sans |
| 09 | type | decorative strikes & highlights | strike for edits, underline for links |
| 10 | copy | highlighted keywords | let structure carry emphasis |
| 11 | copy | AI copywriting voice | say the specific thing |
| 12 | copy | emoji everywhere | cut emoji from product copy |
| 13 | component | glowing status dot | flat dot + a word; no halo |
| 14 | component | left-border callout | one aside, rest is body |
| 15 | component | pastel icon tiles | labelled list with specifics |
| 16 | component | max-radius / glassmorphism | one small radius, solid surfaces |
| 17 | component | oversized drop shadow | tight elevation, never bigger than the element |
| 18 | component | corners that don't nest | inner = outer − padding |
| 19 | component | badge / pill spam | badges only for real status |
| 20 | component | AI-drawn SVG icon | a real, high-quality icon (a designer, or a strong image model) |
| 21 | component | icon in a tint of itself | no tinted tile; inherit text color |
| 22 | layout | all-caps card grid | show the one key thing fully |
| 23 | evolved | tasteful-terminal | mono for code only |

Human-readable pattern notes and false positives live in `skill/references/detection.md`; the regexes that actually run are those in `TELLS` inside `scan.mjs`.

## Output modes

### Grouped console report (default)

When `asJson` is false:

1. Header:  
   `kill-ai-slop — scanned ${files.length} files under ${root}`  
   (`kill-ai-slop` bold when color is on).
2. If no tell groups:  
   `No slop signals found. (Still trust your eyes — open the pages.)`  
   then `process.exit(0)`.
3. Else, for each group (sorted by tell id):  
   - Line: `slop` (red) + bold `id` + `name` + dim `→ ${fix}`  
   - Hit list limited with `g.hits.slice(0, 12)` (at most 12 hits printed per tell).  
   - Loop over those hits starts at `for (const h of shown)`; each aggregated hit carries `file`, `line`, and `text`. The script header describes the product output as a grouped report of **file:line** hits.

### JSON mode (`--json`)

Pretty-printed (`JSON.stringify(..., null, 2)`), then `process.exit(0)`.

```json
{
  "root": "<scan root path>",
  "filesScanned": 0,
  "groups": 0,
  "hits": 0,
  "findings": [
    {
      "id": "01",
      "group": "color",
      "name": "indigo→violet gradient",
      "fix": "one solid, chosen accent",
      "hits": [
        { "file": "src/App.tsx", "line": 42, "text": "..." }
      ]
    }
  ]
}
```

| Field | Meaning |
|---|---|
| `root` | Walk root string used for this run |
| `filesScanned` | `files.length` from `walk(root)` |
| `groups` | Number of tell ids with ≥1 hit |
| `hits` | Total hit count across groups |
| `findings[]` | One object per matched tell, sorted by `id` |
| `findings[].hits[]` | `{ file, line, text }` (relative path, 1-based line, ≤100-char snippet) |

Color is always off in this mode (`useColor` requires `!asJson`).

## Console formatting helpers

Used only for the human report path (after the `--json` early exit):

```js
const c = (code, s) => (useColor ? `\x1b[${code}m${s}\x1b[0m` : s);
const red = (s) => c("31", s);   // "slop" label
const dim = (s) => c("2", s);    // "→ " + fix
const bold = (s) => c("1", s);   // product name, tell id
```

When `useColor` is false, helpers return the string unchanged.

## Exit behavior

| Condition | Exit |
|---|---|
| `--json` after printing payload | `process.exit(0)` |
| Human report, zero tell groups | `process.exit(0)` after empty message |
| Human report with findings | Prints groups (≤12 hits each); no non-zero status is defined in the available script body for this path |

There is no flag that enables writing fixes from this CLI.

## Runtime shape

```text
argv → root / --json / --no-color
        │
        ▼
   walk(root)  ── skip SKIP_DIRS, lockfiles, *.min.*, size/ext filters
        │
        ▼
   scanFile(f) ── line regexes over TELLS (copy vs code)
        │
        ▼
   byTell Map ── sort by tell id
        │
   ┌────┴────┐
   │ --json  │  JSON { root, filesScanned, groups, hits, findings }
   │ default │  ANSI grouped report (header, slop lines, ≤12 hits/tell)
   └─────────┘
        │
        ▼  (read-only; never mutates project files)
```

## Verification signals

| Check | Expected |
|---|---|
| Dependency-free run | `node skill/scripts/scan.mjs .` runs without `npm install` in `skill/` |
| Empty tree / clean UI | Message includes `No slop signals found` |
| Machine pipeline | `--json` parses as object with `findings` array |
| Color off in CI | Non-TTY or `--no-color` or `--json` → no CSI sequences from helpers |
| Scope | Hits only under included extensions / `tailwind.config.*`; not under `node_modules`, `dist`, etc. |

## Related pages

<CardGroup>
  <Card title="Scan a web project" href="/scan-web-project">
    Point the scanner at a project path, read grouped vs JSON reports, and confirm hits against detection rules.
  </Card>
  <Card title="Detection patterns" href="/detection-patterns">
    Human reference for code-level signals per tell and usual false positives.
  </Card>
  <Card title="Skill workflow" href="/skill-workflow">
    How an agent host scans, triages, reports, then proposes or applies fixes without silent scanner edits.
  </Card>
  <Card title="Remediation playbook" href="/fixes-playbook">
    Map tell ids and fix one-liners to clean before/after remediation steps.
  </Card>
  <Card title="Quickstart" href="/quickstart">
    Shortest path to a first scanner report and success signals.
  </Card>
</CardGroup>

---

## 13. Detection patterns

> Code-level signals the skill and scanner look for per tell: patterns, match targets, and how findings map back to taxonomy ids.

- Page Markdown: https://grok-wiki.com/public/docs/yetone-kill-ai-slop-c0d8c9670cbb/pages/13-detection-patterns.md
- Generated: 2026-07-11T08:25:53.544Z

### Source Files

- `skill/references/detection.md`
- `skill/scripts/scan.mjs`
- `skill/references/taxonomy.md`
- `website/src/data/catalogue.ts`

---
title: "Detection patterns"
description: "Code-level signals the skill and scanner look for per tell: patterns, match targets, and how findings map back to taxonomy ids."
---

`skill/references/detection.md` is the human-facing pattern catalogue; `skill/scripts/scan.mjs` encodes the same 23 tells as executable line-level regexes and emits grouped findings. Matches are leads for manual confirmation, never automatic verdicts or file edits.

## Two surfaces, one numbering scheme

| Surface | Path | Role |
| --- | --- | --- |
| Human reference | `skill/references/detection.md` | `rg` recipes, confirm notes, false-positive guidance; place to widen patterns for a stack |
| Scanner runtime | `skill/scripts/scan.mjs` | Walks a project tree, applies `TELLS[].patterns`, prints console or `--json` report |
| Taxonomy names | `skill/references/taxonomy.md` | Numbered **01–23** names, groups, fix one-liners; points at `detection.md` for signals |
| Site chips | `website/src/data/catalogue.ts` → `Entry.detect: string[]` | Short mono-chip strings for the field guide; aligned by tell, not a second matcher |

Scanner tell ids are zero-padded strings `"01"`…`"23"`. Taxonomy uses the same numbers (`**01 · …**`). Catalogue entries use kebab-case string ids (for example `indigo-violet-gradient`) and an auto-assigned position `n`; they do not replace the scanner id in findings.

```text
project tree
    │
    ▼
walk()  →  allowed files only
    │
    ▼
scanFile()  line-by-line regex vs TELLS
    │
    ▼
byTell Map  →  console groups  |  --json findings[]
    │
    ▼
human confirms against detection.md notes
```

## Scan scope and filters

Implementation authority is `scan.mjs` (detection.md states the intent more briefly).

### Included files

- Extensions: `.html`, `.css`, `.scss`, `.sass`, `.less`, `.tsx`, `.jsx`, `.ts`, `.js`, `.mjs`, `.cjs`, `.vue`, `.svelte`, `.astro`, `.md`, `.mdx`
- Also: any basename matching `tailwind.config.*`

### Skipped directories

`node_modules`, `.git`, `dist`, `build`, `out`, `.next`, `.astro`, `.output`, `.svelte-kit`, `.nuxt`, `coverage`, `vendor`, `.cache`, `.vercel`, `.turbo`

### Skipped files

- `*.min.js` / `*.min.css`
- lockfiles matching `package-lock`, `pnpm-lock`, or `yarn.lock`
- files larger than **512 KiB**
- individual lines longer than **2000** characters (treated as minified-ish)

### Code vs copy tells

Most tells run only on non-prose files (`isCode = ext ∉ { .md, .mdx }`).

Tells with `copy: true` also run on Markdown:

| Scanner id | Name | `copy` |
| --- | --- | --- |
| `10` | highlighted keywords | yes |
| `11` | AI copywriting voice | yes |
| `12` | emoji everywhere | yes |

## Tell record shape (scanner)

Each entry in `TELLS` is:

| Field | Type | Purpose |
| --- | --- | --- |
| `id` | string `"01"`–`"23"` | Stable finding key; groups report sort by this |
| `group` | `color` \| `type` \| `copy` \| `component` \| `layout` \| `evolved` | Report / taxonomy group |
| `name` | string | Short human label in console and JSON |
| `fix` | string | One-line remediation hint on the report line |
| `patterns` | `RegExp[]` | Any match on a line counts as a hit |
| `copy` | optional boolean | When true, patterns also apply to `.md` / `.mdx` |

Hit object (internal → report):

| Field | Meaning |
| --- | --- |
| `file` | Path relative to scan root |
| `line` | 1-based line number |
| `text` | Trimmed line, first 100 characters |

## How findings map to taxonomy and catalogue

| Layer | Identifier | Example |
| --- | --- | --- |
| Scanner / detection / taxonomy number | `"05"` / **05** | one-hue status box |
| Scanner report fields | `id`, `group`, `name`, `fix` | `id: "05"`, `group: "color"` |
| Catalogue (site) | kebab-case `id` + `detect[]` chips | `mono-hue-alert` |

Known catalogue id alignment from supplied catalogue entries:

| Scanner / taxonomy | Catalogue `id` |
| --- | --- |
| 01 Indigo→violet gradient | `indigo-violet-gradient` |
| 02 Gradient headline text | `gradient-text` |
| 03 Warm cozy palette | `warm-cozy-palette` |
| 04 Default semantic palette | `default-semantic-palette` |
| 05 One-hue status box | `mono-hue-alert` |
| 06 Gradients as atmosphere | `atmosphere-gradient` |
| 07 Serif-italic on one word | `serif-emphasis` |
| 08 Serif where sans belongs | `serif-body-misuse` |

Catalogue `detect` strings are illustrative chips for the field guide (for example `"bg-clip-text text-transparent"`), not the full scanner regex set. Use `scan.mjs` `patterns` for executable matching and `detection.md` for confirmation criteria.

## Match semantics

1. Walk the tree under `root` (CLI path argument, default `"."`).
2. For each eligible file, split lines and test every tell’s patterns with `RegExp.prototype.test`.
3. First matching pattern on a line is enough; multiple tells can hit the same line.
4. Hits aggregate under tell `id`; console shows up to **12** hits per tell; JSON includes all hits for that tell.
5. No writes: the scanner only reports.

<Warning>
Every match is a **lead**. Open the file and confirm with the per-tell notes below. Brand-true purple, deliberate hero gradient text, real status badges, and intentional monospace chrome are not slop by pattern alone.
</Warning>

### CLI entry

```bash
node skill/scripts/scan.mjs [root] [--json] [--no-color]
```

`--json` shape (fields present in source):

```json
{
  "root": ".",
  "filesScanned": 0,
  "groups": 0,
  "hits": 0,
  "findings": [
    {
      "id": "01",
      "group": "color",
      "name": "indigo→violet gradient",
      "fix": "one solid, chosen accent",
      "hits": [{ "file": "src/App.tsx", "line": 42, "text": "..." }]
    }
  ]
}
```

## Pattern catalogue by tell

Executable patterns are the `scan.mjs` regexes. `detection.md` may list extra `rg` recipes or glob hints used for manual review (for example emoji Unicode ranges, icon library names, extra HTML tags); those are human aids when they differ.

### Color (`01`–`06`)

#### `01` · indigo→violet gradient

| | |
| --- | --- |
| Group | `color` |
| Scanner name / fix | `indigo→violet gradient` → `one solid, chosen accent` |
| Patterns | `from-(indigo\|violet\|purple\|fuchsia)-\d+…to-(purple\|violet\|fuchsia\|pink)-\d+`; `(linear-gradient\|bg-gradient)` near `#6366f1` / `#8b5cf6` / `#a855f7` / `#7c3aed`; `shadow-(purple\|violet\|indigo)-\d+/\d+` |
| Confirm | Slop is the **combination** (purple gradient + glow + pill + “AI-powered” eyebrow), not a genuine brand purple or one-off illustration |

#### `02` · gradient-clip headline

| | |
| --- | --- |
| Group | `color` |
| Scanner name / fix | `gradient-clip headline` → `solid ink, scale up` |
| Patterns | `bg-clip-text` near `text-transparent`; `(?:-webkit-)?background-clip:\s*text`; `-webkit-text-fill-color:\s*transparent` |
| Confirm | False positives: logo wordmark, single deliberate hero. Slop: gradient text as default heading style |

#### `03` · warm cozy palette

| | |
| --- | --- |
| Group | `color` |
| Scanner name / fix | `warm ‘cozy’ palette` → `neutral base + one warm accent` |
| Patterns | `\b(amber\|orange\|stone)-(50\|100\|200\|300)\b`; `bg-[#fdf6ec|fef3e2|faf3e8|fff7ed|fdf4e3]`; `(text\|border)-amber-\d+` |
| Confirm | False positives: food/coffee/craft brand identity. Slop: warm-as-default with no brand reason |

#### `04` · default semantic palette

| | |
| --- | --- |
| Group | `color` |
| Scanner name / fix | `default semantic palette` → `one palette: neutrals + a couple of chosen states` |
| Patterns | `bg-(blue\|indigo)-50`, `bg-amber-50`, `bg-(green\|emerald)-50`, `bg-red-50`; `(info\|success\|warning\|error)` near stock blue/green/amber/red steps |
| Confirm | Three or four stock `-50` / `-600`-style semantic pairs together, unrelated to brand. One deliberate status colour is fine |

#### `05` · one-hue status box

| | |
| --- | --- |
| Group | `color` |
| Scanner name / fix | `one-hue status box` → `state in words; one muted accent on neutral` |
| Patterns | `border-{hue}-\d+` then same hue `text-` (backref); `bg-(red\|amber\|yellow\|green)-\d+/(5\|10\|15\|20)`; `(error\|warning\|success)` near those hues |
| Confirm | Border, text, and `/10`-style background all one hue at three opacities. Single muted accent on neutral is fine |

#### `06` · gradients as atmosphere

| | |
| --- | --- |
| Group | `color` |
| Scanner name / fix | `gradients as atmosphere` → `one flat bg; depth from a hairline` |
| Patterns | `radial-gradient`; `linear-gradient` with `to bottom` / `180deg` / `to top`; `bg-gradient-to-[bt]` near `from-` |
| Confirm | Page-wide radial glow or card fills that are top-to-bottom gradients where a flat colour would do. Directional, purposeful gradients are choices |

### Type (`07`–`09`)

#### `07` · serif-italic emphasis

| | |
| --- | --- |
| Group | `type` |
| Scanner name / fix | `serif-italic emphasis` → `emphasise by weight, one voice` |
| Patterns | `\bfont-serif\b`; `font-family:` Georgia / Playfair / Lora / Cormorant |
| Confirm | Serif/italic span **inside** an otherwise-sans `<h1>` / `<h2>` (hard to prove with grep alone) |

#### `08` · serif where sans belongs

| | |
| --- | --- |
| Group | `type` |
| Scanner name / fix | `serif where sans belongs` → `one legible UI sans` |
| Patterns | `font-family` containing Playfair / Cormorant / Lora / DM Serif / Libre Baskerville; `fontFamily` with those display names |
| Confirm | False positives: editorial/publishing products. Slop: display serif as UI/body on tools or dashboards |

#### `09` · decorative strikes and highlights

| | |
| --- | --- |
| Group | `type` |
| Scanner name / fix | `decorative strikes & highlights` → `strike for edits, underline for links` |
| Patterns | `\bline-through\b`; `<(mark|s|u|del|strike)…>`; `text-decoration: line-through|underline` |
| Confirm | Decoration used for “emphasis,” not real edits, links, or annotation |

### Copy (`10`–`12`, `copy: true`)

#### `10` · highlighted keywords

| | |
| --- | --- |
| Group | `copy` |
| Scanner name / fix | `highlighted keywords` → `let structure carry emphasis` |
| Patterns | `<mark…>`; `text-(primary\|indigo\|purple\|violet)-\d+` |
| Confirm | Multiple colored/semibold spans in one body paragraph. One accented phrase is fine |

#### `11` · AI copywriting voice

| | |
| --- | --- |
| Group | `copy` |
| Scanner name / fix | `AI copywriting voice` → `say the specific thing` |
| Patterns | `not just … it's`; stock phrases (`say goodbye to`, `supercharge`, `unlock the power of`, …); hype adjectives (`blazing-fast`, `seamless`, `game-changer`, …) |
| Confirm | False positives: genuine quotes; docs that discuss the phrases. Also watch three-word sentence stacks and em-dash triplets manually |

#### `12` · emoji everywhere

| | |
| --- | --- |
| Group | `copy` |
| Scanner name / fix | `emoji everywhere` → `cut emoji from product copy` |
| Patterns | `/\p{Extended_Pictographic}/u` (scanner); detection.md also suggests leading 🚀✨⚡🔒🎉 on headings/buttons |
| Confirm | False positives: documented code samples, emoji pickers, UGC. Slop: emoji on every chrome heading/button/bullet |

### Components (`13`–`21`)

#### `13` · glowing status dot

| | |
| --- | --- |
| Patterns | `animate-ping` / `animate-pulse`; green/emerald/lime colored shadows; `(ready\|online\|live)` near `●` or `rounded-full` |
| Fix | `flat dot + a word; no halo` |
| Confirm | Pulsing halo / saturated green “Ready/Online.” Flat dots are fine |

#### `14` · left-border callout

| | |
| --- | --- |
| Patterns | `border-l-4` near `rounded`; `\b(admonition\|callout\|note-box)\b` |
| Fix | `one aside, rest is body` |
| Confirm | Stacked callouts decorating list items, not a scarce semantic aside |

#### `15` · pastel icon tiles

| | |
| --- | --- |
| Patterns | `rounded-(lg\|xl\|2xl) bg-(indigo\|purple\|blue\|green\|amber\|pink)-(50\|100)` |
| Fix | `labelled list with specifics` |
| Confirm | Grid of icon-in-tile features with icons unrelated to content. Manual: icon package imports (lucide, heroicons, …) are detection.md hints only |

#### `16` · max-radius / glassmorphism

| | |
| --- | --- |
| Patterns | `\brounded-full\b`; `backdrop-blur` / `backdrop-filter: blur` / `bg-(white\|black)/(5\|10\|20\|30)`; large `border-radius` (`9999px`, `50%`, `2rem`, `24px`) |
| Fix | `one small radius, solid surfaces` |
| Confirm | Full radius on cards/inputs (not only avatars/pills); blur as default surface |

#### `17` · oversized drop shadow

| | |
| --- | --- |
| Patterns | `box-shadow` / Tailwind arbitrary `shadow-[…]` / `filter: drop-shadow(…)` with blur/spread **≥ 60px** (`[6-9]\d` or `\d{3,}`) |
| Fix | `tight elevation, never bigger than the element` |
| Confirm | Shadow fog larger than the casting element. Proportionate modal/hero shadows and tight elevation are fine |

#### `18` · corners that don't nest

| | |
| --- | --- |
| Patterns | `rounded-(xl\|2xl\|3xl)`; `border-radius` `1rem` / `1.5rem` / `24px` / `32px` |
| Fix | `inner = outer − padding` |
| Confirm | Nested containers sharing the same large radius (non-concentric corners). Hard to prove by regex alone |

#### `19` · badge / pill spam

| | |
| --- | --- |
| Patterns | `rounded-full` near pastel `bg-(indigo\|purple\|green\|amber\|pink)-(50\|100\|200)`; text nodes like `new` / `beta` / `hot` / `popular` / `pro` / `coming soon` (optional leading ✨🔥🎉🚀) |
| Fix | `badges only for real status` |
| Confirm | Several decorative pills in chrome. Real version tags are fine |

#### `20` · AI-drawn SVG icon

| | |
| --- | --- |
| Patterns | `<circle` with `r="[1-9]…"`; `(mascot\|blob).svg` |
| Fix | `a real, high-quality icon (a designer, or a strong image model)` |
| Confirm | Visual judgment: blob-with-dot-eyes / primitive cartoon as product mark. Real icon sets and designed logos are fine |

#### `21` · icon in a tint of itself

| | |
| --- | --- |
| Patterns | same-hue `bg-…/\d+` near `text-…` (and reverse) for indigo/blue/green/amber/red/purple/pink opacities 5–20 |
| Fix | `no tinted tile; inherit text color` |
| Confirm | Icon tile wash matches icon hue. Opaque, deliberate button surfaces are fine |

### Layout and evolved (`22`–`23`)

#### `22` · all-caps card grid

| | |
| --- | --- |
| Group | `layout` |
| Patterns | `\bgrid-cols-3\b`; `\buppercase\b` near `text-xs` / `tracking-wide`; marketing stock (`everything you need`, `why you'll love` / `choose` / `teams`) |
| Fix | `show the one key thing fully` |
| Confirm | ALL-CAPS micro-label + number/icon repeated across interchangeable feature/stat cards |

#### `23` · tasteful-terminal (evolved)

| | |
| --- | --- |
| Group | `evolved` |
| Patterns | `\bfont-mono\b`; mono family names (JetBrains, Fira Code, IBM Plex Mono, Geist Mono, …); box-drawing / shade characters `╔╗╚╝║═▓▒░` |
| Fix | `mono for code only` |
| Confirm | Mono on non-code chrome; ASCII as decoration; near-black + single warm accent. Highest judgment load — weigh whether the terminal metaphor serves the product |

## Human vs machine pattern drift

Keep these differences in mind when extending or debugging detection:

| Topic | `detection.md` | `scan.mjs` |
| --- | --- | --- |
| Emoji | Broad Unicode ranges + leading-emoji `rg` | Single `\p{Extended_Pictographic}` |
| Tell 04 | Mentions multiple stock hues near each other | Stock `bg-*-50` + info/success/warning/error near hues |
| Tell 15 | Mentions lucide/heroicons/react-icons | Pastel rounded tile classes only |
| Tell 20 | `<svg` greps + visual judgment | Circle radius + `mascot`/`blob`.svg only |
| Scope lists | Slightly shorter skip/ext lists | Authoritative `SKIP_DIRS` / `EXTS` |

When widening stack-specific signals, update **both** the human recipes and the `TELLS` regexes so reports stay aligned with the skill references.

## Verification signals

| Signal | Expected |
| --- | --- |
| Empty project / clean UI | Console: `No slop signals found. (Still trust your eyes — open the pages.)` |
| Known Tailwind indigo hero | Finding group `01` with file:line and snippet |
| Markdown with “supercharge” | Finding under `11` when `copy: true` path includes `.md` |
| Scanner contract | Process never writes or rewrites project files |

## Related pages

<CardGroup>
  <Card title="Slop taxonomy" href="/slop-taxonomy">
    Numbered tells, groups, and the shared language for classic vs evolved slop.
  </Card>
  <Card title="Catalogue model" href="/catalogue-model">
    How `catalogue.ts` attaches `detect` chips and demos without owning the matcher.
  </Card>
  <Card title="Scan a web project" href="/scan-web-project">
    Point the scanner at a path and interpret grouped vs JSON reports against these rules.
  </Card>
  <Card title="Scanner CLI reference" href="/scanner-cli-reference">
    Invocation, flags, walk behavior, and the never-edit constraint.
  </Card>
  <Card title="Remediation playbook" href="/fixes-playbook">
    Map confirmed hits to clean replacements per tell.
  </Card>
  <Card title="Extend the catalogue" href="/extend-catalogue">
    Add a tell end-to-end: catalogue, demos, and skill detection alignment.
  </Card>
</CardGroup>

---

## 14. Remediation playbook

> Per-tell clean fixes, what to remove or replace, and how before or after demos illustrate the preferred outcome.

- Page Markdown: https://grok-wiki.com/public/docs/yetone-kill-ai-slop-c0d8c9670cbb/pages/14-remediation-playbook.md
- Generated: 2026-07-11T08:25:44.528Z

### Source Files

- `skill/references/fixes.md`
- `skill/references/taxonomy.md`
- `website/src/data/demos.ts`
- `website/src/components/BeforeAfter.astro`
- `skill/SKILL.md`

---
title: "Remediation playbook"
description: "Per-tell clean fixes, what to remove or replace, and how before or after demos illustrate the preferred outcome."
---

`skill/references/fixes.md` is the remediation source for kill-ai-slop: 23 numbered before→after patterns the agent skill applies in workflow step **5. Fix**, after scan, triage, and a user-visible report. Patterns are directions, not find-and-replace rules—adapt to project tokens and framework, and prefer one shared token or component edit over every call site.

<Note>
The standalone scanner (`node scripts/scan.mjs`) never edits files. Remediation runs only through the agent skill (propose or apply after the user chooses groups). Re-run the scanner after fixes to confirm hit counts drop, and note intentional leftovers with a reason.
</Note>

## Role in the skill workflow

| Stage | Surface | Remediation role |
| --- | --- | --- |
| Scan | `scripts/scan.mjs` | Map hits only; no edits |
| Triage | `references/taxonomy.md`, `references/detection.md` | Slop vs intentional; false positives |
| Report | Skill output | Tell + `file:line` + one-line proposed fix; wait for user |
| Fix | **`references/fixes.md`** | Minimal change that removes the tell |

Report lines already point at the fix direction, for example:

```text
slop  src/Hero.tsx:12   indigo→violet gradient        → one solid accent
slop  src/Hero.tsx:31   gradient-clip headline        → solid ink, scale up
slop  src/Note.tsx:8    border-l-4 callout ×3         → 1 aside, rest is body
slop  copy.md:1         "not just X — it's Y"         → say the specific thing
```

## Order of operations

From `fixes.md`:

1. **Design tokens / theme first** — colors, radius, fonts. Many hits disappear at once.
2. **Components**, then one-off call sites.
3. **Copy** last.

Skill-level constraints while applying fixes:

- Prefer shared tokens/components over every call site.
- Never invent new brand colors; if a palette must change, propose neutrals + the project’s existing accent and let the user confirm.
- Keep copy meaning; make it specific, do not only delete.
- Small, reviewable diffs; no new dependencies; no mass-edit before the report is accepted.
- Verify visually when a dev server exists—a cleaner scan is not the same as a better page.

## Principles on every fix

Held by `skill/SKILL.md` for every remediation:

1. Decide before you decorate.
2. One accent, one voice.
3. Hierarchy from scale and space (not colored words or font swaps).
4. Subtract first.
5. Specific beats punchy in copy.
6. Decoration (icons, badges, callouts) must mean something.

## Before / after demos (field guide)

The Astro field guide illustrates preferred outcomes with plain-HTML specimens in `website/src/data/demos.ts`. Each entry is `{ before, after }` keyed by demo id. Styles live under `.demo-<id>` in `styles/demos.css`.

`website/src/components/BeforeAfter.astro` loads `demos[id]` and renders a Slop / Clean toggle:

- Props: `id` — must exist in the demos map or the component throws `No demo for id "…"`.
- Stage shows one pane at a time (`data-show="before" | "after"`); both panes share a grid cell so height does not jump.
- Labels: **Slop** / **Clean** (localized via `<T>`); tags **SLOP** / **CLEAN** on the stage.
- `after` panes follow the same rules as the skill: one accent, no gradient chrome, hierarchy from scale + space, mono for code only, no decorative emoji/badges.

| Demo id (`demos.ts`) | Tell # | Taxonomy name |
| --- | --- | --- |
| `indigo-violet-gradient` | 01 | Indigo→violet gradient |
| `gradient-text` | 02 | Gradient headline text |
| `warm-cozy-palette` | 03 | Warm "cozy" palette |
| `default-semantic-palette` | 04 | Default semantic palette |
| `serif-emphasis` | 07 | Serif-italic on one word |
| `serif-body-misuse` | 08 | Serif where sans belongs |
| `decorative-text-lines` | 09 | Decorative strikes & highlights |
| `highlighted-keywords` | 10 | Highlighted keywords |
| `ai-copy-tics` | 11 | AI copywriting voice |
| `emoji-everywhere` | 12 | Emoji everywhere |
| `status-dot-glow` | 13 | Glowing status dot |
| `left-border-callout` | 14 | Rounded card, colored left border |
| `pastel-icon-tiles` | 15 | Rounded-square icon tiles |
| `over-rounded-glass` | 16 | Max radius + glassmorphism |
| `oversized-shadow` | 17 | Oversized drop shadow |
| `badge-spam` | 19 | Badge & pill spam |
| `feature-grid` | 22 | All-caps card grid |

Tells **05, 06, 18, 20, 21, 23** have fix patterns in `fixes.md` / taxonomy but no demo keys in the supplied `demos.ts` record.

## Per-tell clean fixes

Patterns below are condensed from `skill/references/fixes.md` and the taxonomy fix lines. Diffs use Tailwind-style class examples; rewrite to CSS variables, design tokens, or framework equivalents as needed.

### Color

#### 01 · Indigo→violet gradient

| | |
| --- | --- |
| **Remove / replace** | `from-indigo-* to-purple/violet/*` chrome; colored glow shadows (`shadow-purple-500/50`) |
| **Clean** | One solid accent (`bg-[--accent]`) |
| **If a gradient stays** | Single hue, low contrast, justified; drop the glow |

```diff
- class="bg-gradient-to-r from-indigo-500 to-purple-500 shadow-lg shadow-purple-500/50"
+ class="bg-[--accent]"
```

**Demo:** `indigo-violet-gradient` — gradient CTA + “✨ AI-POWERED” → solid card, plain eyebrow, solid button.

#### 02 · Gradient headline text

| | |
| --- | --- |
| **Remove** | `bg-clip-text text-transparent` rainbow fills on headings |
| **Clean** | Solid ink; impact via size/weight, not fill |

```diff
- <h1 class="bg-gradient-to-r from-indigo-500 to-pink-500 bg-clip-text text-transparent">
+ <h1 class="text-[--ink]">
```

**Demo:** `gradient-text` — gradient heading → solid heading; subcopy unchanged.

#### 03 · Warm "cozy" palette

| | |
| --- | --- |
| **Remove** | Amber/stone wash (`bg-[#fdf6ec]`, `text-amber-900`, `border-amber-200`) as the base |
| **Clean** | Near-neutral paper/ink/rule; one warm accent on a single element |
| **Process** | Propose neutrals; user confirms before global apply |

```diff
- bg-[#fdf6ec] text-amber-900 border-amber-200
+ bg-[--paper] text-[--ink] border-[--rule]
```

**Demo:** `warm-cozy-palette` — amber “cozy workspace” card → neutral workspace with specific subcopy.

#### 04 · Default semantic palette

| | |
| --- | --- |
| **Remove** | Framework rainbow chips (`blue-50/700`, `green-50/700`, `amber-50/700`, `red-50/700`) as unrelated candy colors |
| **Clean** | Neutrals + at most one or two intentional semantics from the brand palette |

```diff
- <span class="bg-blue-50 text-blue-700">Info</span>
- <span class="bg-green-50 text-green-700">Success</span>
- <span class="bg-amber-50 text-amber-700">Warning</span>
- <span class="bg-red-50 text-red-700">Error</span>
+ <span class="chip">Info</span> <span class="chip">Warning</span>
+ <span class="chip chip--ok">Success</span>
+ <span class="chip chip--danger">Error</span>
```

**Demo:** `default-semantic-palette` — multi-color chips → neutral chips with sparse ok/err markers.

#### 05 · One-hue status box

| | |
| --- | --- |
| **Remove** | Border + text + tint all one hue (`border-red-500 bg-red-500/10 text-red-500`) |
| **Clean** | Neutral surface + rule; state in a bold word; one muted accent optional |

```diff
- <div class="border border-red-500 bg-red-500/10 text-red-500 rounded p-3">
-   Something went wrong.
- </div>
+ <div class="border border-[--rule] bg-[--surface] text-[--ink] rounded p-3">
+   <b>Error</b> — something went wrong.
+ </div>
```

#### 06 · Gradients as atmosphere

| | |
| --- | --- |
| **Remove** | Page-level radial/atmosphere gradients; gradient card surfaces |
| **Clean** | One flat background; depth via hairline border (and restrained shadow if needed) |
| **If a glow stays** | Point it at one element, not fill the void |

```diff
- <body class="bg-[radial-gradient(circle_at_top,#1e293b,#020617)]">
-   <div class="rounded-2xl bg-gradient-to-b from-white/10 to-white/0 …">
+ <body class="bg-[--bg]">
+   <div class="rounded-[--radius] bg-[--card] border border-[--rule]">
```

### Type

#### 07 · Serif-italic on one word

| | |
| --- | --- |
| **Remove** | Mixed voice: serif italic accent word in a sans headline |
| **Clean** | Weight/position emphasis; one family voice |

```diff
- The editor that <em class="font-serif italic text-indigo-600">actually</em> ships.
+ The editor that <b>ships</b>.
```

**Demo:** `serif-emphasis` — `<em>200ms</em>` → `<b>200ms</b>`.

#### 08 · Serif where sans belongs

| | |
| --- | --- |
| **Remove** | Display serif (e.g. Playfair) as UI/body on tools/SaaS |
| **Clean** | Project UI sans tokens; text serif only for a true editorial voice |

```diff
- font-family: "Playfair Display", serif;
+ font-family: var(--font-sans);
```

**Demo:** `serif-body-misuse` — serif metrics panel → sans panel; numbers unchanged.

#### 09 · Decorative strikes & highlights

| | |
| --- | --- |
| **Remove** | `<s>`, decorative `<u>`, `<mark>` used as emphasis, not real edit/link/annotation |
| **Clean** | Plain heading; structure carries emphasis |
| **Keep when legitimate** | Strike for real edits, underline for links, highlight for real annotation |

```diff
- <h1>The <s>old</s> <mark>new</mark> way to <u>ship</u>.</h1>
+ <h1>A faster way to ship.</h1>
```

**Demo:** `decorative-text-lines` — strike/underline/mark headline → plain specific headline.

### Copy

#### 10 · Highlighted keywords

| | |
| --- | --- |
| **Remove** | Scattered colored/bold mid-sentence keywords |
| **Clean** | Specific sentences; at most one accented phrase |

```diff
- Our <span class="text-indigo-600 font-semibold">revolutionary</span> platform helps
- <span class="text-pink-600 font-semibold">ambitious</span> teams move faster.
+ A project tracker for engineering teams. It updates issues from your commits.
```

**Demo:** `highlighted-keywords` — multi-span hype paragraph → concrete product description.

#### 11 · AI copywriting voice

| | |
| --- | --- |
| **Remove** | “It’s not just X — it’s Y”, “Say goodbye to…”, punchy triads, em-dash drama without specifics |
| **Clean** | Concrete nouns, numbers, consequences |

```diff
- It's not just an editor — it's a movement. Say goodbye to friction.
+ A code editor. Opens in under a second, ~half the memory of Electron editors.
```

**Demo:** `ai-copy-tics` — movement/friction/triad block → measured product facts.

#### 12 · Emoji everywhere

| | |
| --- | --- |
| **Remove** | Emoji on every heading, button, bullet |
| **Clean** | No decorative emoji; keep one only when it carries real information (e.g. status) |

```diff
- <h2>🚀 Why you'll love it</h2>
+ <h2>Why teams pick it</h2>
```

**Demo:** `emoji-everywhere` — emoji list → specific measurable bullets.

### Components

#### 13 · Glowing status dot

| | |
| --- | --- |
| **Remove** | `animate-ping` halo, glow shadow, inflated gem for a binary state |
| **Clean** | Small flat single-color dot + word |

```diff
- <span class="relative flex h-3 w-3">
-   <span class="animate-ping absolute … bg-green-400 opacity-75"></span>
-   <span class="relative rounded-full h-3 w-3 bg-green-500 shadow-lg shadow-green-500/50"></span>
- </span> Ready
+ <span class="inline-block h-2 w-2 rounded-full bg-[--ok]"></span> Ready
```

**Demo:** `status-dot-glow` — glowing live indicator → flat dot + “Online”.

#### 14 · Rounded card, colored left border

| | |
| --- | --- |
| **Remove** | Stacked `border-l-4` rounded callouts used as universal decoration |
| **Clean** | Body prose for list content; at most one real `<aside>` |

```diff
- <div class="border-l-4 border-indigo-500 rounded-lg bg-indigo-50 p-4">Note …</div>
- <div class="border-l-4 border-amber-500 rounded-lg bg-amber-50 p-4">Tip …</div>
+ <p>… the note, inline as normal prose …</p>
+ <aside class="note">Beta: exports may change format before 1.0.</aside>
```

**Demo:** `left-border-callout` — four colored call rows → plain list with the same facts.

#### 15 · Rounded-square icon tiles

| | |
| --- | --- |
| **Remove** | Decorative rounded tile + vague one-liner feature grid |
| **Clean** | Labelled list with real specifics; icon only if it carries meaning |

```diff
- <div class="rounded-xl bg-indigo-100 p-2"><Icon/></div><h3>Fast</h3><p>Very fast.</p>
+ <li><b>Fast</b> — cold start in 180 ms, measured on a 2020 laptop.</li>
```

**Demo:** `pastel-icon-tiles` — three glyph tiles → plain list with measurements.

#### 16 · Max radius + glassmorphism

| | |
| --- | --- |
| **Remove** | `rounded-full`, `backdrop-blur`, translucent panes as default chrome |
| **Clean** | One small site-wide radius; solid card + rule border |

```diff
- class="rounded-full backdrop-blur bg-white/10 border border-white/20"
+ class="rounded-[--radius] bg-[--card] border border-[--rule]"
```

**Demo:** `over-rounded-glass` — glass pill “Upgrade now” → flat card, specific plan copy, solid CTA with price.

#### 17 · Oversized drop shadow

| | |
| --- | --- |
| **Remove** | Room-sized soft shadows (`0 16px 80px…`); tinted glow shadows |
| **Clean** | Hairline and/or tight contact shadow; colorless; never larger than the element |

```diff
- box-shadow: 0 16px 80px 10px rgba(0,0,0,0.36);
+ border: 1px solid var(--rule);
+ box-shadow: 0 1px 2px rgba(0,0,0,0.06), 0 4px 10px -6px rgba(0,0,0,0.1);
```

Related: tell **01** purple glow-shadow; tell **13** status-dot halo.

**Demo:** `oversized-shadow` — fog panel → hairline + tight contact shadow caption.

#### 18 · Corners that don't nest

| | |
| --- | --- |
| **Remove** | Same large radius on outer and inner children |
| **Clean** | `inner ≈ outer − padding`, or no inner rounding |

```diff
- <div class="rounded-2xl p-3"><div class="rounded-2xl">…</div></div>
+ <div class="rounded-2xl p-3"><div class="rounded-lg">…</div></div>
```

#### 19 · Badge & pill spam

| | |
| --- | --- |
| **Remove** | Decorative “✨ New / 🔥 Popular / β Beta / PRO” pills |
| **Clean** | At most a real status (e.g. version) |

```diff
- <h1>Dashboard</h1><Pill>✨ New</Pill><Pill>🔥 Popular</Pill><Pill>β Beta</Pill>
+ <h1>Dashboard</h1><span class="ver">v2.1</span>
```

**Demo:** `badge-spam` — four pills → `v2.1` only.

#### 20 · AI-drawn SVG icons

| | |
| --- | --- |
| **Remove** | Crude model-sketched SVG blobs / primitive mascots shipped as the mark |
| **Clean** | Real icon (designer or refined image-model asset); no bare letter fallback as the brand |

```diff
- <svg viewBox="0 0 48 48"><circle cx="24" cy="24" r="20"/><circle cx="18" cy="20" r="2"/>…</svg>
+ <img src="/icon.svg" alt="" />
```

#### 21 · Icon in a tint of itself

| | |
| --- | --- |
| **Remove** | `bg-{color}/10` tile wrapping `text-{color}` icon |
| **Clean** | Icon inherits ink; if a container is needed, use a deliberate opaque surface |

```diff
- <div class="rounded-lg bg-blue-500/10 p-2"><Icon class="text-blue-500"/></div>
+ <Icon class="text-[--ink]"/>
```

#### 22 · The all-caps card grid

| | |
| --- | --- |
| **Remove** | Equal-weight icon + ALL-CAPS label + one-liner card grids |
| **Clean** | Lead with the single most important point, fully told |

```diff
- <div class="grid grid-cols-3 gap-8"> …6 icon+CAPS-label+one-liner cards… </div>
+ <p class="lead">It replaces your standups.</p>
+ <p>Every morning it reads yesterday's commits and PRs and writes the team a
+ three-line summary.</p>
```

**Demo:** `feature-grid` — caps feature cards (FAST / SECURE / SIMPLE / SCALABLE…) as the slop specimen.

#### 23 · The tasteful terminal

| | |
| --- | --- |
| **Remove** | Site-wide mono + near-black + amber “terminal UI” chrome and decorative ASCII frames |
| **Clean** | Monospace reserved for code; terminal metaphor only when the product needs it |

```diff
- <body class="font-mono bg-[#0a0a0a] text-amber-400">
-   <pre>  ╔══════════════╗
-          ║  WELCOME  ║
-          ╚══════════════╝…
```

## Quick lookup: remove → replace

| # | Tell | Primary remove | Primary replace |
| --- | --- | --- | --- |
| 01 | Indigo→violet gradient | Multi-hue gradient + glow | Solid `--accent` |
| 02 | Gradient headline | `bg-clip-text` rainbow | Solid `--ink`, scale/weight |
| 03 | Warm cozy palette | Amber/stone base wash | Neutral paper/ink + one accent |
| 04 | Default semantic palette | Framework color chips | Palette-derived chips |
| 05 | One-hue status box | Mono-hue border/bg/text | Neutral box + word state |
| 06 | Atmosphere gradients | Page/card gradient fog | Flat bg + hairline |
| 07 | Serif-italic word | Mixed serif italic | Bold / structure |
| 08 | Serif as UI | Display serif body | `--font-sans` |
| 09 | Decorative marks | `<s>`/`<u>`/`<mark>` drama | Plain structure |
| 10 | Highlighted keywords | Scattered color spans | Specific prose |
| 11 | AI copy voice | Not-just-X / triads | Concrete facts |
| 12 | Emoji everywhere | Decorative emoji | Specific labels |
| 13 | Glowing status dot | Ping + halo shadow | Flat dot + word |
| 14 | Left-border callouts | Stacked admonition cards | List / one aside |
| 15 | Pastel icon tiles | Tile + vague line | Specific list items |
| 16 | Over-round glass | Full radius + blur pane | Small radius solid |
| 17 | Oversized shadow | Huge soft blur | Hairline / tight shadow |
| 18 | Nested corners | Same radius all layers | outer − padding |
| 19 | Badge spam | Decorative pills | Real status only |
| 20 | AI SVG icons | Crude generated SVG | Refined real icon |
| 21 | Icon self-tint | Tint tile wrapper | Ink icon alone |
| 22 | Caps card grid | Equal CAPS cards | One lead story |
| 23 | Tasteful terminal | Mono site chrome | Mono for code only |

## Verification after apply

<Steps>
  <Step title="Re-scan">
    Run `node scripts/scan.mjs <root>` (or `--json`) and confirm targeted tell counts dropped.
  </Step>
  <Step title="Account for intentional hits">
    Document any remaining hits kept on purpose (brand gradient, deliberate emoji status, real annotation markup).
  </Step>
  <Step title="Visual check">
    If a dev server exists, compare the live UI to the field-guide Clean demos for the same tell—scan pass ≠ better page.
  </Step>
</Steps>

## Related pages

<CardGroup>
  <Card title="Apply clean fixes" href="/apply-clean-fixes">
    Map scanner hits to this playbook, choose propose vs apply in an agent host, and confirm the clean alternative.
  </Card>
  <Card title="Detection patterns" href="/detection-patterns">
    Code-level signals that produce the hits this playbook remediates.
  </Card>
  <Card title="Slop taxonomy" href="/slop-taxonomy">
    What each tell is, why it reads as machine-made, and shared taxonomy language.
  </Card>
  <Card title="Skill workflow" href="/skill-workflow">
    Scan → triage → report → fix lifecycle and the no silent-edit rule for the scanner.
  </Card>
  <Card title="Catalogue and demos data" href="/catalogue-data-reference">
    Demo HTML payloads and catalogue shapes used by `BeforeAfter` and the field guide.
  </Card>
  <Card title="Run the field guide site" href="/run-field-guide-site">
    Preview Slop/Clean demos locally via the Astro field guide.
  </Card>
</CardGroup>

---

## 15. Catalogue and demos data

> Fields and shapes in catalogue.ts, catalogue.i18n.ts, and demos.ts: tell ids, copy locales, and demo HTML payloads used by site components.

- Page Markdown: https://grok-wiki.com/public/docs/yetone-kill-ai-slop-c0d8c9670cbb/pages/15-catalogue-and-demos-data.md
- Generated: 2026-07-11T08:26:08.409Z

### Source Files

- `website/src/data/catalogue.ts`
- `website/src/data/catalogue.i18n.ts`
- `website/src/data/demos.ts`
- `website/src/components/SlopEntry.astro`
- `website/src/components/T.astro`
- `website/src/styles/demos.css`

---
title: "Catalogue and demos data"
description: "Fields and shapes in catalogue.ts, catalogue.i18n.ts, and demos.ts: tell ids, copy locales, and demo HTML payloads used by site components."
---

`website/src/data/catalogue.ts` defines the field-guide tell records (`Entry`, `GROUPS`, `Bi`) that `SlopEntry.astro` renders. Japanese and Korean copy attach from `catalogue.i18n.ts` by entry `id`. Optional before/after HTML lives in `demos.ts` under the same key family, styled in `styles/demos.css` under `.demo-<id>`.

## Data files

:::files
website/src/data/
  catalogue.ts        # Entry types, GROUPS, rawEntries (en + zh copy)
  catalogue.i18n.ts   # ja/ko partials keyed by entry id
  demos.ts            # before/after HTML strings keyed by demo id
website/src/styles/
  demos.css           # .ba-stage + .demo-<id> scopes
website/src/components/
  SlopEntry.astro     # Entry → page article
  T.astro             # Bi/locale spans (en/zh/ja/ko)
  BeforeAfter.astro   # consumes entry.demo id
:::

| File | Export / surface | Role |
|------|------------------|------|
| `catalogue.ts` | `Group`, `Bi`, `Entry`, `GROUPS`, `rawEntries` | Single source of tell ids, tiers, groups, en/zh copy, `detect[]`, optional `demo` |
| `catalogue.i18n.ts` | `EntryI18n`, `i18n` | Optional `ja` / `ko` strings for `title` \| `what` \| `why` \| `fix` |
| `demos.ts` | `demos` | Plain-HTML `before` / `after` payloads per demo id |
| `demos.css` | `.ba-stage`, `.demo-<id>` | Shared primitives + per-demo styles; generic class names do not leak site-wide |

Catalogue header comments state this catalogue is the website source of truth and the spec the kill-ai-slop skill enforces. Demos replaced earlier screenshot annotations so comparisons stay rebuilt HTML rather than pinned images.

## Locale model

| Locale | Where defined | Required? |
|--------|---------------|-----------|
| `en` | `catalogue.ts` (`Bi.en`, `GROUPS`) | Yes — source of truth |
| `zh` | `catalogue.ts` inline (`Bi.zh`) | Yes on `Bi` |
| `ja` | `catalogue.i18n.ts` (optional fields) | No — fallback to English |
| `ko` | `catalogue.i18n.ts` (optional fields) | No — fallback to English |

`T.astro` renders four spans (`data-t="en|zh|ja|ko"`). Only `en` is required on props; `zh` / `ja` / `ko` use `?? en` when missing. Active language is selected via `<html data-lang>` (global CSS), not by omitting spans.

i18n file comments: partial translations are safe; voice must stay terse and non-slop in every language (no punchy triads, no “not just X, it’s Y”, no exclamation).

## Types

### `Group`

```ts
export type Group =
  | "color"
  | "type"
  | "copy"
  | "component"
  | "layout"
  | "evolved";
```

### `Bi` (localized string)

```ts
export interface Bi {
  en: string;
  zh: string;
  ja?: string;
  ko?: string;
}
```

### `Entry`

```ts
export interface Entry {
  id: string;
  n: number;
  tier: 1 | 2;
  group: Group;
  title: Bi;
  what: Bi;
  why: Bi;
  fix: Bi;
  detect: string[];
  demo?: string;
}
```

### `EntryI18n` / `i18n`

```ts
type Field = "title" | "what" | "why" | "fix";
type LangText = Partial<Record<Field, string>>;

export interface EntryI18n {
  ja?: LangText;
  ko?: LangText;
}

export const i18n: Record<string, EntryI18n>;
```

### `demos`

```ts
export const demos: Record<string, { before: string; after: string }>;
```

## Entry fields

Source records use `const rawEntries: Omit<Entry, "n">[]`. Comments state display numbers are assigned by array position so inserts renumber automatically (`n` is not hand-edited on each object).

<ParamField body="id" type="string" required>
Stable slug used as article `id`, hash deep-link (`#${entry.id}`), and key into `i18n`.
</ParamField>

<ParamField body="n" type="number" required>
1-based-style display index after position mapping. `SlopEntry` shows `String(entry.n).padStart(2, "0")`.
</ParamField>

<ParamField body="tier" type="1 | 2" required>
`1` classic slop; `2` evolved slop. CSS class `t${entry.tier}` on the group tag; tier `2` uses inverted ink/paper styling (`.tag.group.t2`).
</ParamField>

<ParamField body="group" type="Group" required>
Category key into `GROUPS`. Rendered as the uppercase group tag via `<T {...GROUPS[entry.group]} />`.
</ParamField>

<ParamField body="title" type="Bi" required>
Tell name in the entry heading.
</ParamField>

<ParamField body="what" type="Bi" required>
One-line description of the tell.
</ParamField>

<ParamField body="why" type="Bi" required>
Why the pattern reads as machine-made.
</ParamField>

<ParamField body="fix" type="Bi" required>
Clean remediation guidance shown under “The fix”.
</ParamField>

<ParamField body="detect" type="string[]" required>
Code-level signal chips (also skill heuristics). Each string renders as a mono `<code>` list item.
</ParamField>

<ParamField body="demo" type="string" optional>
Key into `demos` / `demos.css` / `BeforeAfter`. When set, `SlopEntry` mounts `<BeforeAfter id={entry.demo} />`.
</ParamField>

### Tiers (catalogue comments)

| Tier | Label | Meaning |
|------|--------|---------|
| `1` | classic | Tells most people already recognise |
| `2` | evolved | Newer defaults that already read as templated (“friendly-AI-app” look) |

### `GROUPS` labels

| Key | en | zh | ja | ko |
|-----|----|----|----|-----|
| `color` | Color | 配色 | カラー | 색상 |
| `type` | Type | 字体 | 書体 | 타이포 |
| `copy` | Copy | 文案 | コピー | 카피 |
| `component` | Components | 组件 | コンポーネント | 컴포넌트 |
| `layout` | Layout | 版式 | レイアウト | 레이아웃 |
| `evolved` | Evolved slop | 进化型 slop | 進化型 slop | 진화형 slop |

## How `SlopEntry` consumes an entry

| UI region | Source |
|-----------|--------|
| `article.id`, permalink `#id` | `entry.id` |
| Zero-padded number | `entry.n` |
| Group tag + tier class | `GROUPS[entry.group]`, `entry.tier` |
| Title / what | `entry.title`, `entry.what` |
| Before/after demo | `entry.demo` → `BeforeAfter` when truthy |
| Why / fix notes | `entry.why`, `entry.fix` |
| Code signals | `entry.detect[]` as `<code>` chips |

Static section labels (“Why it’s slop”, “The fix”, “Code signals”) are hardcoded multilingual props on `T`, not catalogue fields.

## Demo payloads

Each `demos[id]` is two HTML string fragments:

| Field | Content rules (file header) |
|-------|-----------------------------|
| `before` | Rebuilds the slop tell in plain HTML |
| `after` | Clean counterpart; same rules the site and skill enforce: one accent, no gradient chrome, hierarchy from scale + space, mono for code only, no decorative emoji/badges |

Demo copy is illustrative, short, and neutral. Styles:

- Shared under `.ba-stage` (`h5`, `.ey`, `.sub`, buttons, etc.)
- Per-demo under `.demo-<id>` so generic class names (`card`, `btn`, `sem`) do not leak into the rest of the site
- “Before” panes intentionally reproduce slop; “after” panes obey site rules

Example shape (`indigo-violet-gradient`):

```ts
"indigo-violet-gradient": {
  before: `
    <div class="card slop-grad">
      <p class="ey">✨ AI-POWERED</p>
      <h5>Deploys on git push</h5>
      <p class="sub">Connect a repo; every commit to main ships.</p>
      <button class="btn grad">Get started →</button>
    </div>`,
  after: `
    <div class="card clean">
      <p class="ey">Continuous deploy</p>
      <h5>Deploys on git push</h5>
      <p class="sub">Connect a repo; every commit to main ships.</p>
      <button class="btn solid">Get started</button>
    </div>`,
},
```

## Key inventory (from data exports)

Ids are the join keys across catalogue, i18n, and demos. Alignment is by string equality; `demo` may equal `id` or be omitted.

### Catalogue `rawEntries` ids present in source fragment

| `id` | `tier` | `group` | `demo` (when present) |
|------|--------|---------|------------------------|
| `indigo-violet-gradient` | `1` | `color` | `indigo-violet-gradient` |
| `gradient-text` | `1` | `color` | `gradient-text` |
| `warm-cozy-palette` | `1` | `color` | `warm-cozy-palette` |
| `default-semantic-palette` | `1` | `color` | `default-semantic-palette` |
| `mono-hue-alert` | `1` | `color` | (not shown in truncated fragment) |

The array continues after `mono-hue-alert` in the full file; only these objects appear in the supplied catalogue fragment.

### Example `detect` chips (color group)

| `id` | `detect` values |
|------|-----------------|
| `indigo-violet-gradient` | `from-indigo-500 to-purple-500`, `#6366f1 → #a855f7`, `bg-gradient-to-r via-purple`, `shadow-purple-500/50` |
| `gradient-text` | `bg-clip-text text-transparent`, `background-clip: text`, `-webkit-text-fill-color: transparent` |
| `warm-cozy-palette` | `amber-50 / stone-100 / orange-400`, `bg-[#fdf6ec] text-amber-900`, `border-amber-200` |
| `default-semantic-palette` | `bg-blue-50 / bg-amber-50 / bg-green-50 together`, `-50 bg + -600 text semantic set`, `default info/warn/success/error hues` |

### `i18n` keys present

`indigo-violet-gradient`, `gradient-text`, `warm-cozy-palette`, `default-semantic-palette`, `serif-emphasis`, `serif-body-misuse`, `decorative-text-lines`, `highlighted-keywords`, `ai-copy-tics`, `emoji-everywhere`, `status-dot-glow`, `left-border-callout` (file continues past this key in full source).

Each key holds optional `ja` / `ko` objects with any of `title`, `what`, `why`, `fix`.

### `demos` keys present

| Demo id | Notes |
|---------|--------|
| `status-dot-glow` | Glowing live dot → flat status + label |
| `indigo-violet-gradient` | Gradient CTA card → solid card |
| `gradient-text` | Clipped gradient head → solid head |
| `warm-cozy-palette` | Amber cozy card → neutral card |
| `default-semantic-palette` | Rainbow chips → neutral chips + small dots |
| `serif-emphasis` | Mixed serif italic → single-voice bold |
| `serif-body-misuse` | Display-serif panel → sans panel |
| `decorative-text-lines` | `s` / `u` / `mark` ornament → plain claim |
| `highlighted-keywords` | Multi-span keyword paint → concrete paragraph |
| `ai-copy-tics` | Triads / “not just” copy → concrete copy |
| `emoji-everywhere` | Emoji list → numeric/plain list |
| `left-border-callout` | Colored left-bar cards → plain list |
| `pastel-icon-tiles` | Pastel icon feature tiles → measured feature list |
| `over-rounded-glass` | Glassmorphism plan card → flat card (payload truncated in evidence) |

### Cross-file join sketch

```text
rawEntries[i].id  ──►  i18n[id].{ja,ko}.{title,what,why,fix}
       │
       └── demo?  ──►  demos[demo].{before,after}
                       styles .demo-<demo>  (+ shared .ba-stage)
       │
       └── detect[] ──► mono chips in SlopEntry (+ skill heuristics)
```

<Note>
`demo` is optional. `mono-hue-alert` appears in `rawEntries` without a confirmed `demo` in the catalogue fragment; demos and i18n maps can include keys for tells whose full catalogue objects live later in the file (e.g. `serif-emphasis`, `status-dot-glow`).
</Note>

## Constraints

| Rule | Detail |
|------|--------|
| English authority | `Bi.en` / `T` `en` prop is required; missing locales fall back to English |
| zh location | Chinese copy lives in `catalogue.ts`, not `catalogue.i18n.ts` |
| ja/ko location | Isolated reviewable block in `catalogue.i18n.ts` |
| Numbering | Do not hardcode permanent numbers; position in `rawEntries` drives `n` |
| Demo/CSS lockstep | New demo needs `demos[id]`, `.demo-<id>` rules, and matching `entry.demo` |
| After-pane rules | One accent; no gradient chrome; hierarchy via scale + space; mono for code only; no decorative emoji/badges |
| CSS isolation | Scope under `.ba-stage` or `.demo-<id>` only |
| Copy voice (all locales) | Terse, plain, specific — site must not commit the slop it catalogues |
| `T` styling | `T` emits bare spans only; parent owns element + classes (no `as` / `class` on `T`) |

## Verification signals

When editing these files, confirm:

1. Every `entry.demo` string exists as a key in `demos` (and has `.demo-<id>` styles when that demo uses custom CSS).
2. `i18n` keys match real `entry.id` values (orphans only waste bytes; missing keys silently fall back to English).
3. Each `Bi` has both `en` and `zh`; optional `ja`/`ko` either complete the four fields you care about or omit them intentionally.
4. `detect` strings are short enough for mono chips and useful as skill/scanner heuristics.
5. `group` is one of the six `Group` keys and has a `GROUPS` label.
6. `tier` is only `1` or `2`.
7. On the field guide, the entry renders title/what/why/fix for each `data-lang`, demo panes when `demo` is set, and code-signal chips from `detect`.

## Related pages

<CardGroup>
  <Card title="Catalogue model" href="/catalogue-model">
    How catalogue.ts is the single source of truth and how demos and i18n attach.
  </Card>
  <Card title="Extend the catalogue" href="/extend-catalogue">
    Add or update a tell: entry, i18n, HTML demo, skill alignment.
  </Card>
  <Card title="Slop taxonomy" href="/slop-taxonomy">
    Categories, named signals, shared language with the skill.
  </Card>
  <Card title="Detection patterns" href="/detection-patterns">
    How `detect` strings and scanner rules map back to tell ids.
  </Card>
  <Card title="Remediation playbook" href="/fixes-playbook">
    Per-tell clean fixes and before/after outcomes.
  </Card>
  <Card title="Run the field guide site" href="/run-field-guide-site">
    How entries and demos render on the Astro index.
  </Card>
  <Card title="Design tokens" href="/design-tokens">
    Site self-constraints that “after” panes should obey.
  </Card>
</CardGroup>

---

## 16. Design tokens

> Site self-constraints in tokens and global styles: paper and ink palette, single editorial red, hierarchy rules, and banned slop defaults.

- Page Markdown: https://grok-wiki.com/public/docs/yetone-kill-ai-slop-c0d8c9670cbb/pages/16-design-tokens.md
- Generated: 2026-07-11T08:26:02.377Z

### Source Files

- `website/src/styles/tokens.css`
- `website/src/styles/global.css`
- `website/src/styles/demos.css`
- `website/src/layouts/Base.astro`
- `website/src/components/ThemeToggle.astro`

---
title: "Design tokens"
description: "Site self-constraints in tokens and global styles: paper and ink palette, single editorial red, hierarchy rules, and banned slop defaults."
---

The field-guide site encodes its anti-slop rules as CSS custom properties in `website/src/styles/tokens.css`, imported first by `website/src/styles/global.css` (then `demos.css`). `website/src/layouts/Base.astro` loads `global.css` for every page. Tokens define paper/ink surfaces, the two intentional accent colors (`--mark`, `--slop`), type scale, spacing, radius, hairlines, and elevation; global rules and clean demo panes consume them. Slop demo panes intentionally hard-code banned defaults (gradients, pills, rainbow semantics) outside the token set.

## File surface

```text
website/src/
├── layouts/Base.astro          # imports global.css; pre-paint theme/lang
├── components/ThemeToggle.astro
└── styles/
    ├── tokens.css              # :root design tokens + dark overrides
    ├── global.css              # @import tokens + demos; base type/layout
    └── demos.css               # .ba-stage / .demo-* before→after styles
```

| Path | Role |
|------|------|
| `tokens.css` | Canonical token definitions and dark-mode overrides |
| `global.css` | Reset, body chrome, heading scale, layout primitives, locale visibility |
| `demos.css` | Scoped before/after demo styles; clean sides use tokens; slop sides hard-code anti-patterns |
| `Base.astro` | Imports `global.css`; pre-paint `kas-theme` / `kas-lang` / `kas-sound` |
| `ThemeToggle.astro` | Forces `data-theme` light/dark; persists `localStorage` key `kas-theme` |

## Self-constraints (token contract)

Comments in `tokens.css` state the rules the site holds itself to:

| Rule | Implementation |
|------|----------------|
| Monochrome base | Ink on paper: structure, nav, numbers stay ink; no decorative color on chrome |
| Color only for verdict | `--mark` (pine green) flags slop sparingly; `--slop` (specimen coral) colors the “before” side in demos; clean is unmarked |
| No gradient / cozy / rainbow defaults | Banned as site defaults; only appear inside slop demo panes |
| Hierarchy without serif swaps or mid-sentence color | Scale, weight, and space only |
| Modest radius + hairlines | `--radius` / `--radius-lg`, `--hair`, `--rule` — not pill chrome or diffuse glow |
| Mono for code only | `--font-mono` on `code` / `kbd` / `samp` / `pre`; not UI chrome |

## Color tokens

### Light defaults (`:root`)

| Token | Value | Use |
|-------|--------|-----|
| `--paper` | `#f2f4f6` | Page background |
| `--paper-2` | `#e9ebed` | Recessed panels |
| `--card` | `#fafcfe` | Soft card surface (not pure `#fff`) |
| `--ink` | `#1a1b1d` | Primary text / solid chrome |
| `--ink-2` | `#5e5f61` | Secondary text |
| `--ink-3` | `#8e8f91` | Meta, captions, eyebrows |
| `--rule` | `#e1e3e5` | Hairline borders |
| `--rule-strong` | `#c5c7c9` | Stronger rules / link underlines |
| `--mark` | `#246a50` | Deep emerald-pine proof-mark (verdict / flag) |
| `--mark-soft` | `#dde7e0` | Faint green wash |
| `--slop` | `#ff5c5c` | Specimen coral — commentary color on slop “before” panes |

### Dark overrides

Dark applies when:

1. `prefers-color-scheme: dark` **and** `:root` is not `[data-theme="light"]`, or  
2. `:root[data-theme="dark"]` is set explicitly.

Both selectors carry the **identical** dark token set (CSS cannot OR a media query with a selector).

| Token | Dark value |
|-------|------------|
| `--paper` | `#131316` |
| `--paper-2` | `#1b1c20` |
| `--card` | `#202127` |
| `--ink` | `#ecebe6` |
| `--ink-2` | `#a9a8a2` |
| `--ink-3` | `#74736e` |
| `--rule` | `#2c2d33` |
| `--rule-strong` | `#3d3e45` |
| `--mark` | `#6faa8e` |
| `--mark-soft` | `#1e2f28` |
| `--shadow-e1` | `0 1px 1px rgba(0, 0, 0, 0.4)` |
| `--shadow-e2` | `0 1px 1px rgba(0, 0, 0, 0.5), 0 4px 4px -1px rgba(0, 0, 0, 0.3)` |

`--slop` is not redefined in dark mode; it stays `#ff5c5c`. Dark mode remains paper-and-ink logic inverted: same mark accent, no neon glow.

### `color-scheme`

| Selector | `color-scheme` |
|----------|----------------|
| `:root` (default) | `light dark` |
| `:root[data-theme="light"]` | `light` |
| `:root[data-theme="dark"]` | `dark` |

Native controls (e.g. language `<select>` options, scrollbars) follow the forced scheme.

## Type tokens

| Token | Value |
|-------|--------|
| `--font-sans` | `ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", sans-serif` |
| `--font-mono` | `ui-monospace, "SF Mono", "JetBrains Mono", "Cascadia Code", Menlo, Consolas, monospace` |

Modular scale (~1.2), display caps kept modest:

| Token | Clamp |
|-------|--------|
| `--step--1` | `clamp(0.78rem, 0.76rem + 0.08vw, 0.82rem)` |
| `--step-0` | `clamp(0.94rem, 0.92rem + 0.1vw, 1rem)` |
| `--step-1` | `clamp(1.05rem, 1rem + 0.24vw, 1.18rem)` |
| `--step-2` | `clamp(1.25rem, 1.14rem + 0.5vw, 1.55rem)` |
| `--step-3` | `clamp(1.5rem, 1.3rem + 0.9vw, 2rem)` |
| `--step-4` | `clamp(1.85rem, 1.5rem + 1.5vw, 2.6rem)` |
| `--step-5` | `clamp(2.2rem, 1.75rem + 2.2vw, 3.2rem)` |

## Space and structure tokens

| Token | Value | Notes |
|-------|--------|--------|
| `--s-1` … `--s-9` | `0.25rem` … `7rem` | 8px-base spacing ladder |
| `--measure` | `68ch` | Readable prose width (`.measure`) |
| `--container` | `76rem` | Page max width (`.container`) |
| `--radius` | `8px` | Control / button radius (not pills) |
| `--radius-lg` | `12px` | Larger surfaces / clean demo cards |
| `--hair` | `1px` | Hairline rules |
| `--shadow-e1` | tight 1px contact | Light default |
| `--shadow-e2` | ring + tight lift | Clean elevated panels |
| `--ease` | `cubic-bezier(0.2, 0, 0, 1)` | Motion easing |

Shadows are contact shadows (small blur, negative spread), not diffuse drops or glows.

## Theme resolution

```text
localStorage "kas-theme"
        │
        ├─ "light" | "dark"  →  documentElement.dataset.theme  (pre-paint in Base.astro)
        └─ unset             →  data-theme absent; @media prefers-color-scheme drives dark tokens

ThemeToggle click
        → effective() = explicit data-theme OR OS
        → flip light ↔ dark
        → set data-theme + localStorage kas-theme
```

| Storage key | Values | Default behavior |
|-------------|--------|------------------|
| `kas-theme` | `"light"` \| `"dark"` | Unset → follow OS via media query |
| `kas-lang` | `en` \| `zh` \| `ja` \| `ko` | Unset → OS language if supported, else `en` |
| `kas-sound` | `"off"` or other | Default `"on"` unless stored `"off"` |

Theme toggle UI: sun icon in light, moon in dark; icons driven by global CSS on effective theme (`prefers-color-scheme` + `data-theme`). Toggle chrome uses `var(--ink-3)` / hover `var(--ink)`.

## Global styles that enforce hierarchy

`global.css` applies tokens to base chrome:

| Element / class | Token / rule |
|-----------------|--------------|
| `body` | `background: var(--paper)`; `color: var(--ink)`; `font-family: var(--font-sans)`; `font-size: var(--step-0)`; `line-height: 1.6` |
| `h1` | `var(--step-5)`, weight `620`, letter-spacing `-0.038em` |
| `h2` | `var(--step-3)`, letter-spacing `-0.028em` |
| `h3` | `var(--step-1)`, letter-spacing `-0.018em` |
| `h1–h4` (default) | `line-height: 1.04`, weight `640`, `text-wrap: balance` |
| CJK headings (`[data-lang="zh"|"ja"|"ko"]`) | `line-height: 1.4` |
| `a` | inherit color; underline `var(--rule-strong)`; hover `var(--ink)` |
| `code, kbd, samp, pre` | `var(--font-mono)` |
| `:focus-visible` | `2px solid var(--ink)`, `border-radius: 0` |
| `::selection` | `background: var(--ink)`; `color: var(--paper)` |
| `.container` | `max-width: var(--container)` + fluid inline padding |
| `.measure` | `max-width: var(--measure)` |
| `.section` | fluid block padding; `border-top: var(--hair) solid var(--rule)` |
| `.eyebrow` | `var(--step--1)`, tracked uppercase, `var(--ink-3)`; index via `data-index` in `var(--ink)` |
| `.mark-hl` | empty rule — emphasis by weight/structure, not underline/highlight |
| `.lede` | `var(--step-2)`, weight `480`; CJK locales `line-height: 1.5` |

Reduced motion: under `prefers-reduced-motion: reduce`, animations/transitions collapse to `0.01ms`; scroll stays `auto`. Smooth scroll only after `.nav-ready` is added post-load (and not when reduced motion is preferred).

## Banned slop defaults (demo contrast)

Clean demo panes reuse site tokens. Slop panes hard-code anti-patterns the tokens ban. Representative mappings in `demos.css`:

| Tell (demo id) | Slop (hard-coded) | Clean (tokens) |
|----------------|-------------------|----------------|
| `demo-indigo-violet-gradient` | `linear-gradient(135deg, #6366f1, #a855f7)`, purple glow, pill button | `var(--card)`, `var(--rule)`, solid `var(--ink)` / `var(--paper)` button |
| `demo-gradient-text` | multi-stop indigo→pink→amber clipped text | solid `var(--ink)` heading |
| `demo-warm-cozy-palette` | amber wash `#fdf6ec`, coral button, `9999px` pill | `var(--card)` + `var(--rule)` neutral card |
| `demo-default-semantic-palette` | five candy status chips (indigo/green/amber/red/violet) | neutral chips (`var(--ink)` mix + `var(--rule)`); semantic color only in small dots |
| `demo-serif-emphasis` | Georgia italic mid-phrase in `var(--slop)` | single sans weight hierarchy |
| `demo-serif-body-misuse` | Georgia body rows | `var(--font-sans)` body; mono tabular nums for numbers |
| Shared clean cards | — | `var(--radius-lg)` + `var(--shadow-e2)` (hairline + tight lift) |

Shared demo primitives under `.ba-stage` also use steps, ink tiers, and `var(--radius)` for clean controls.

## Consuming tokens in components

Use variables only — do not reintroduce banned hard-coded hues on site chrome:

```css
.example {
  background: var(--card);
  color: var(--ink);
  border: var(--hair) solid var(--rule);
  border-radius: var(--radius);
  box-shadow: var(--shadow-e1);
  font-size: var(--step--1);
  padding: var(--s-4);
}
```

Verdict / proof-mark color:

```css
.flag {
  color: var(--mark);
  background: var(--mark-soft);
}
```

Slop commentary (demos only):

```css
.slop-comment {
  color: var(--slop);
}
```

## Verification checklist

When changing tokens or site chrome:

1. **Monochrome chrome** — numbers, nav, structure stay ink; no new accent on chrome.
2. **Verdict colors only** — `--mark` / `--slop` (and soft mark wash); clean remains unmarked.
3. **No new gradients / pills / rainbow semantics** on non-demo UI.
4. **Radius** — prefer `--radius` (8px) or `--radius-lg` (12px); avoid `9999px` outside slop demos.
5. **Elevation** — hairline + `--shadow-e1` / `--shadow-e2`; no diffuse glow.
6. **Theme** — light `:root` defaults; dark via media **or** `data-theme="dark"`; force-light via `data-theme="light"`; pre-paint still reads `kas-theme`.
7. **CJK** — heading/lede line-heights still apply under `[data-lang="zh"|"ja"|"ko"]`.
8. **Demos** — slop panes may hard-code banned styles; clean panes must stay on tokens.

## Related pages

<CardGroup>
  <Card title="Run the field guide site" href="/run-field-guide-site">
    Install, dev server, and static build for the Astro field guide that consumes these tokens.
  </Card>
  <Card title="Build and deploy" href="/build-and-deploy">
    Static `dist` output and deploy-anywhere notes for the zero-JS-by-default site.
  </Card>
  <Card title="Fixes playbook" href="/fixes-playbook">
    Per-tell clean remediations that match the clean side of before/after demos.
  </Card>
  <Card title="Slop taxonomy" href="/slop-taxonomy">
    Named tells the demos and skill share; visual anti-patterns tokens deliberately reject.
  </Card>
  <Card title="Contributing" href="/contributing">
    Where to change site styles vs skill references while keeping taxonomy aligned.
  </Card>
</CardGroup>

---

## 17. Build and deploy

> Static site build to dist, deploy-anywhere assumptions, and operational notes for the zero-JS-by-default Astro field guide.

- Page Markdown: https://grok-wiki.com/public/docs/yetone-kill-ai-slop-c0d8c9670cbb/pages/17-build-and-deploy.md
- Generated: 2026-07-11T08:25:59.514Z

### Source Files

- `website/astro.config.mjs`
- `website/src/pages/index.astro`
- `website/src/layouts/Base.astro`
- `README.md`
- `website/src/styles/global.css`

---
title: "Build and deploy"
description: "Static site build to dist, deploy-anywhere assumptions, and operational notes for the zero-JS-by-default Astro field guide."
---

The field guide lives under `website/` as a single Astro content site. Production output is a static `dist/` tree: `npm run build` writes files you can host on any static origin. Live site: **https://killaislop.com**.

## What gets built

| Surface | Path / role |
| --- | --- |
| Site root | `website/` — multilingual field guide (en, zh, ja, ko) |
| Config | `website/astro.config.mjs` — `site`, `build.inlineStylesheets` only; no integrations |
| Entry page | `website/src/pages/index.astro` — hero, catalogue, principles, skill sections |
| Layout shell | `website/src/layouts/Base.astro` — document head, pre-paint scripts, `Nav` / `Footer` |
| Styles | `website/src/styles/global.css` (imports tokens + demos) |
| Skill package | `skill/` — **not** part of the site build; install and run separately |

Repo layout (from the project README):

```text
website/   Astro site, the field guide (multilingual, static, zero-JS-by-default)
skill/     the kill-ai-slop Agent Skill (SKILL.md + references + scanner)
```

## Astro configuration

`website/astro.config.mjs` is intentionally minimal: static, dependency-light, no Astro integrations.

```js
import { defineConfig } from 'astro/config';

// Kill AI Spop is a single, static, dependency-light content site.
// No integrations by design — the build artifact should be as lean as the
// aesthetic it argues for.
export default defineConfig({
  site: 'https://killaislop.com',
  build: {
    inlineStylesheets: 'auto',
  },
});
```

| Key | Value | Effect |
| --- | --- | --- |
| `site` | `https://killaislop.com` | Base for absolute URLs (`Astro.site`) used in canonical and Open Graph metadata |
| `build.inlineStylesheets` | `'auto'` | Lets Astro decide when stylesheets are inlined into HTML |
| Integrations / adapters | none | No SSR adapter; build is static HTML/CSS/assets |

<Note>
If you fork and deploy under a different public origin, update `site` so `canonical`, `og:url`, and `og:image` stay correct. Absolute share URLs are built from `Astro.site` in `Base.astro`.
</Note>

## Prerequisites

- Node.js with `npm` available
- Working directory: `website/`
- Dependencies installed once: `npm install`

No host-specific CLIs, env files, or CI config are required by the site source as documented.

## Build commands

From the repository root:

```bash
cd website
npm install
npm run dev        # http://localhost:4321
npm run build      # → dist/  (static, deploy anywhere)
```

| Command | Purpose | Success signal |
| --- | --- | --- |
| `npm install` | Install site dependencies | Completes without install errors |
| `npm run dev` | Local Astro dev server | Serves at `http://localhost:4321` |
| `npm run build` | Production static build | Writes `dist/` (static; deploy anywhere) |

<Steps>
  <Step title="Install">
    ```bash
    cd website
    npm install
    ```
  </Step>
  <Step title="Build">
    ```bash
    npm run build
    ```
    Expect a static artifact under `dist/` relative to `website/`.
  </Step>
  <Step title="Deploy">
    Publish the contents of `dist/` to any static host (object storage + CDN, Pages, Netlify, nginx, etc.). No Node server or Astro adapter is required for the production artifact described in the README.
  </Step>
</Steps>

## Deploy-anywhere assumptions

The README states the build is **static** and can be **deployed anywhere**. Operational constraints that follow from the evidence:

1. **Static origin only** — Serve the built files over HTTPS (or HTTP in private previews). No server-side rendering or API routes are configured.
2. **Root-relative assets** — Head links use root paths such as `/favicon.svg` and `/og.png`. Host `dist/` at the site root of the public origin (or ensure those paths resolve if you change layout).
3. **Canonical site URL** — `site: 'https://killaislop.com'` drives absolute metadata. Mismatched deploy hostname vs `site` yields wrong OG/canonical URLs, not a failed HTML serve.
4. **No build-time env vars** — Language, theme, and sound preferences are client `localStorage` keys (`kas-lang`, `kas-theme`, `kas-sound`), not deploy-time secrets.
5. **Skill is out of band** — Deploying the field guide does not install or run `skill/`. Scanner and agent skill install are separate (`npx skills add yetone/kill-ai-slop` or manual copy).

```text
  source (website/)
        │
        │  npm run build
        ▼
     dist/   static HTML + CSS + assets
        │
        │  any static host
        ▼
  public origin (e.g. killaislop.com)
```

## Runtime behavior baked into the static pages

“Zero-JS-by-default” means no framework client islands or integrations in config. `Base.astro` still ships small **inline** head scripts for pre-paint preferences (no flash):

| Concern | Storage key | Behavior |
| --- | --- | --- |
| Language | `kas-lang` | Valid: `en`, `zh`, `ja`, `ko`. Missing/invalid → derive from `navigator.language` (zh/ja/ko prefixes) else `en`. Sets `data-lang` and `lang` on `<html>`. |
| Sound | `kas-sound` | `"off"` → `data-sound="off"`; otherwise `"on"` (default). |
| Theme | `kas-theme` | Only `"light"` or `"dark"` set `data-theme`; otherwise unset so CSS follows OS via `@media`. |
| Deep links | (none) | On load, if `location.hash` matches an id, scroll to it; then may add `.nav-ready` for smooth scrolling unless `prefers-reduced-motion: reduce`. |

All locales are present in the HTML; visibility is CSS-driven:

```css
/* global.css — every language is rendered; only the active data-lang shows */
[data-lang="en"] [data-t]:not([data-t="en"]),
[data-lang="zh"] [data-t]:not([data-t="zh"]),
[data-lang="ja"] [data-t]:not([data-t="ja"]),
[data-lang="ko"] [data-t]:not([data-t="ko"]) {
  display: none;
}
```

Static hosts must not strip inline `<script>` tags if language/theme/sound pre-paint is required.

## Share metadata and static assets

`Base.astro` builds absolute metadata from `Astro.site`:

| Field | Construction |
| --- | --- |
| Canonical | `new URL(Astro.url.pathname, Astro.site)` |
| OG / Twitter image | `new URL("/og.png", Astro.site)` → `https://killaislop.com/og.png` at production site |
| Favicon | `/favicon.svg` (`type="image/svg+xml"`) |
| OG size | width `1200`, height `630`, type `image/png` |
| Locales in OG | `en_US` plus alternates `zh_CN`, `ja_JP`, `ko_KR` |

Default document title/description (overridable via layout props):

- **title:** `Kill AI Slop — 杀死 AI slop`
- **description:** bilingual field-guide blurb (EN + ZH in the default string)

OG art source is noted in comments as `capture/og/og.html` (authoring reference for the share card); production serves `/og.png`.

## Verification checklist

After build and deploy:

| Check | Expected |
| --- | --- |
| `npm run build` | Completes; `dist/` present under `website/` |
| Open site root | Index loads (hero, catalogue of 23 tells, principles, skill CTAs) |
| View source / network | Static assets; favicon at `/favicon.svg` |
| Share card fetch | `/og.png` returns 1200×630 PNG when present on host |
| Language | First paint respects stored `kas-lang` or browser language among en/zh/ja/ko; CSS hides inactive `[data-t]` |
| Hash link | `/#catalogue` (or another entry id) lands on the section without long smooth-scroll from top on first load |

## Operational notes and limits

- **No package manager matrix in repo docs** — only `npm install` / `npm run dev` / `npm run build` are documented.
- **No host recipe** — no Netlify, Vercel, GitHub Pages, or nginx config is part of the supplied site surface; treat “deploy anywhere” as copy `dist/` to a static file root.
- **Subpath hosting not configured** — config has no `base` path; root deployment matches current absolute asset and `site` usage.
- **Do not couple skill deploy to site deploy** — scanner remains `node skill/scripts/scan.mjs …` and never edits files; it is not produced by `npm run build`.

## Related pages

<CardGroup>
  <Card title="Run the field guide site" href="/run-field-guide-site">
    Install, dev server, static build output, and how catalogue entries and demos render on the index.
  </Card>
  <Card title="Installation" href="/installation">
    Site dependencies for local development and skill install options.
  </Card>
  <Card title="Design tokens" href="/design-tokens">
    Paper/ink palette, single accent, and self-imposed style rules shipped with the site.
  </Card>
  <Card title="Contributing" href="/contributing">
    Where to change site components, catalogue data, or skill references while keeping taxonomy aligned.
  </Card>
</CardGroup>

---

## 18. Contributing

> Where to change skill references, scanner logic, catalogue data, or site components while keeping skill and website taxonomy aligned.

- Page Markdown: https://grok-wiki.com/public/docs/yetone-kill-ai-slop-c0d8c9670cbb/pages/18-contributing.md
- Generated: 2026-07-11T08:26:28.672Z

### Source Files

- `README.md`
- `skill/SKILL.md`
- `skill/scripts/scan.mjs`
- `website/src/data/catalogue.ts`
- `skill/references/taxonomy.md`
- `website/src/pages/index.astro`

---
title: "Contributing"
description: "Where to change skill references, scanner logic, catalogue data, or site components while keeping skill and website taxonomy aligned."
---

Kill AI Slop is two sibling trees under one repo: `website/` (Astro field guide) and `skill/` (`kill-ai-slop` agent skill + dependency-free scanner). Taxonomy is shared in language and intent, but **not** generated from a single runtime module—site data lives in `website/src/data/catalogue.ts`, while the skill enforces the same 23 tells through `skill/references/*` and the `TELLS` table in `skill/scripts/scan.mjs`. Contributions that touch a tell must update every layer that still carries it.

## Repository surfaces

```
website/   Astro site, the field guide (multilingual, static, zero-JS-by-default)
skill/     the kill-ai-slop Agent Skill (SKILL.md + references + scanner)
```

| Surface | Role | Primary paths |
| --- | --- | --- |
| Field guide | Catalogues 23 tells with before→after HTML demos; locales EN / ZH / JA / KO | `website/src/data/catalogue.ts`, `website/src/pages/index.astro`, styles under `website/src/styles/` |
| Agent skill | Scan → triage → report → fix workflow for coding agents | `skill/SKILL.md`, `skill/references/`, `skill/scripts/scan.mjs` |
| Standalone scanner | Greps code-level signals; **never edits files** | `skill/scripts/scan.mjs` (also invoked as `node skill/scripts/scan.mjs <path>` from repo root) |

`website/src/data/catalogue.ts` is documented as the **single source of truth for the website** and the **spec the skill enforces**. The skill still keeps its own prose and pattern files; do not assume editing the catalogue alone updates detection or remediation.

## Where to change what

| Intent | Edit these | Leave alone unless needed |
| --- | --- | --- |
| Tell copy, groups, tiers, detect chips (site) | `website/src/data/catalogue.ts` (`Entry`, `GROUPS`, `rawEntries`) | Scanner patterns until detection actually changes |
| JA / KO catalogue strings | `catalogue.i18n.ts` (merged in; `zh` stays inline in `catalogue.ts`) | English-only demo HTML unless copy is in the demo |
| Before→after demo | Demo payload keyed by `Entry.demo` (catalogue comments: demos / BeforeAfter data) | Skill workflow |
| What / why / fix narrative for agents | `skill/references/taxonomy.md` | Site components |
| Regex / greppable signals | `skill/scripts/scan.mjs` `TELLS[].patterns` **and** `skill/references/detection.md` | UI chrome |
| Remediation before→after for agents | `skill/references/fixes.md` | Scanner (unless pattern list changes) |
| Skill lifecycle, guardrails, report format | `skill/SKILL.md` | Catalogue entry fields |
| Field-guide page structure, principles block, CTAs | `website/src/pages/index.astro` (`Base`, `T`, `SlopEntry`, `catalogue` import) | Scanner |
| Design self-constraints (paper/ink, one editorial red, no gradient/emoji/glass/badge defaults) | `website/src/styles/tokens.css` (and related global styles) | Tell taxonomy unless a new visual rule becomes a tell |

### Catalogue entry shape (site)

```ts
export type Group = "color" | "type" | "copy" | "component" | "layout" | "evolved";

export interface Bi {
  en: string;
  zh: string;
  ja?: string;
  ko?: string;
}

export interface Entry {
  id: string;       // slug, e.g. "indigo-violet-gradient"
  n: number;        // assigned by position in rawEntries
  tier: 1 | 2;      // classic vs evolved
  group: Group;
  title: Bi;
  what: Bi;
  why: Bi;
  fix: Bi;
  detect: string[]; // mono chips + skill heuristics text
  demo?: string;    // key into demos / BeforeAfter data
}
```

- English is always required on `Bi`; other locales fall back to English at the `<T>` layer.
- `n` is renumbered from array order—inserting an entry renumbers later tells automatically on the site.
- `detect` chips are human-readable signals (for example `"bg-clip-text text-transparent"`), not the same structure as scanner regexes.

### Scanner tell shape (skill)

Each scanner tell is an object in the `TELLS` array inside `skill/scripts/scan.mjs`:

| Field | Meaning |
| --- | --- |
| `id` | Zero-padded numeric string (`"01"` …), aligned with taxonomy numbering |
| `group` | e.g. `color`, `type`, `copy`, `component`, `layout` |
| `name` | Short human label for reports |
| `fix` | One-line clean alternative |
| `patterns` | Line-level regexes |
| `copy: true` | Optional; copy tells also scan prose-oriented files |

CLI (from skill directory or via repo-root path):

```bash
node scan.mjs [root] [--json] [--no-color]
# repo-root form:
node skill/scripts/scan.mjs path/to/project
node skill/scripts/scan.mjs path/to/project --json
```

Hard constraints encoded in the scanner header and skill workflow:

- Pure Node—no dependencies.
- **Never edits files**; every hit is a lead to confirm by reading code.
- Default root is `.` if omitted.
- Skips dirs such as `node_modules`, `.git`, `dist`, `build`, `out`, `.next`, `.astro`, coverage/vendor/cache deploy caches.
- Scans extensions including `.html`, `.css`, framework SFC/JS/TS, `.md`, `.mdx`.

## Keep taxonomy aligned

There are **two ID systems** that must stay mappable for the same tell:

| Layer | Identifier style | Example |
| --- | --- | --- |
| Site catalogue | Kebab slug | `indigo-violet-gradient`, `gradient-text`, `mono-hue-alert` |
| Taxonomy + scanner | Two-digit ordinal | `01` indigo→violet gradient, `02` gradient-clip headline |
| Groups | Shared vocabulary | `color`, `type`, `copy`, `component`, `layout` (+ site `evolved` group / tier 2) |

```text
  website/src/data/catalogue.ts     skill/references/taxonomy.md
  id: "indigo-violet-gradient"  ↔   **01 · Indigo→violet gradient**
  detect: [chips...]            ↔   skill/references/detection.md
  fix: Bi copy                  ↔   skill/references/fixes.md
  demo: "indigo-violet-gradient"    skill/scripts/scan.mjs
                                    id: "01", patterns: [...]
```

<Warning>
Updating only `catalogue.ts` or only `scan.mjs` desyncs the field guide from the agent skill. Treat a tell as a cross-package unit: site entry + demo + i18n, taxonomy prose, detection patterns, fix playbook, and scanner `TELLS` row.
</Warning>

### Alignment checklist for one tell

When adding or materially changing a tell:

1. **Site SSOT** — `rawEntries` row: stable `id`, `tier`, `group`, `title` / `what` / `why` / `fix` (`en` + `zh`), `detect[]`, `demo` key.
2. **Locales** — JA/KO in `catalogue.i18n.ts` if those locales should not fall back to English.
3. **Demo** — plain-HTML before→after for that `demo` key (site rebuilds tells in HTML; no reliance on live product screenshots).
4. **Skill taxonomy** — matching numbered entry in `skill/references/taxonomy.md` (what / why / fix; same decision rule: slop is absence of a decision).
5. **Detection** — concrete patterns in `skill/references/detection.md` and regexes in `TELLS` for the same ordinal `id`.
6. **Fixes** — before→after remediation in `skill/references/fixes.md` consistent with catalogue `fix` and site demo “after”.
7. **Principles** — if the change alters a global principle, update both `skill/SKILL.md` principles and the `principles` array in `website/src/pages/index.astro` (they currently mirror each other).

## Change recipes

### Add or update a catalogue tell (site + skill)

<Steps>
  <Step title="Define the site entry">
    Append or edit an object in `rawEntries` in `website/src/data/catalogue.ts`. Prefer a stable slug `id`. Set `tier` (`1` classic / `2` evolved) and `group`. Fill `detect` with the same code-level signals agents and scanners should recognize.
  </Step>
  <Step title="Attach i18n and demo">
    Keep `en` complete. Put `zh` inline; merge `ja` / `ko` via `catalogue.i18n.ts`. Point `demo` at a plain-HTML before→after pair used by the index catalogue section.
  </Step>
  <Step title="Mirror into the skill">
    Add or revise the matching **NN** entry in `references/taxonomy.md`, pattern notes in `references/detection.md`, remediation in `references/fixes.md`, and a `TELLS` object with the same ordinal `id` and regexes in `scripts/scan.mjs`.
  </Step>
  <Step title="Wire the field guide">
    `website/src/pages/index.astro` already imports `{ catalogue }` and renders entries through `SlopEntry`. Prefer data changes over hardcoding a one-off tell on the page.
  </Step>
  <Step title="Verify both surfaces">
    Run the site and the scanner (commands below). Confirm the new tell appears in the catalogue UI and produces expected hits on a fixture path—or zero hits on a clean control.
  </Step>
</Steps>

### Change detection only

Edit:

1. `skill/scripts/scan.mjs` — `TELLS[n].patterns` (and `copy: true` if the tell is copy-oriented).
2. `skill/references/detection.md` — human pattern list + false positives.
3. Optionally `Entry.detect` chips in `catalogue.ts` so the field guide still matches what agents look for.

Do **not** change scanner I/O flags or claim file mutation. Re-run:

```bash
node skill/scripts/scan.mjs path/to/project
node skill/scripts/scan.mjs path/to/project --json
```

### Change skill workflow or guardrails

Edit `skill/SKILL.md` only when changing host behavior:

| Section | Contract |
| --- | --- |
| Workflow 1–5 | Scope → Scan → Triage → Report → Fix; **no mass-edit before the user sees the report** |
| Scan command | `node scripts/scan.mjs <root>` / `--json`; pure Node; never edits |
| Triage | Slop vs intentional; keep defended brand choices |
| Report format | Grouped `slop  file:line  tell  → fix` then ask which groups to apply |
| Guardrails | Respect authorship; small diffs; no `git add -A`; no new dependencies; visual verify when possible |
| References | Points at `taxonomy.md`, `detection.md`, `fixes.md`, `scripts/scan.mjs` |

Install paths for consumers (document, don’t reinvent):

```bash
npx skills add yetone/kill-ai-slop
```

Manual: copy everything under `skill/` into a `kill-ai-slop/` folder in the agent’s skills directory (see root README / `skill/README.md`).

### Change field-guide UI or principles

| Piece | Path |
| --- | --- |
| Page sections (hero, definition, catalogue, skill CTA) | `website/src/pages/index.astro` |
| Layout / i18n component / entry card | `Base.astro`, `T.astro`, `SlopEntry.astro` (imported from the index) |
| Catalogue data binding | `import { catalogue } from "../data/catalogue"` |
| Design tokens | `website/src/styles/tokens.css` — paper + ink, **one** editorial red, hierarchy from scale/space, hairline rules; no gradients / emoji / glass / badges |

Local site loop:

```bash
cd website
npm install
npm run dev        # http://localhost:4321
npm run build      # → dist/  (static, deploy anywhere)
```

## Local verification signals

| Change | Success signal | Failure / recovery |
| --- | --- | --- |
| Catalogue / site | `npm run dev` serves index; catalogue section lists 23 tells with working before→after toggles | Fix data shape / missing `demo` key; rebuild after i18n merge issues |
| Scanner patterns | Grouped report or `--json` shows expected `file:line` for fixtures; count drops after intentional clean fixes | Confirm hits by reading code—scanner is a map, not gospel; tighten false positives in patterns + `detection.md` |
| Skill docs | Workflow still forbids silent bulk edits; references still resolve under `skill/references/` | Restore report-before-fix ordering in `SKILL.md` |
| Taxonomy sync | Same tell name/group/fix intent across catalogue `fix`, taxonomy, fixes, and scanner `fix` one-liner | Diff the four layers for that ordinal/slug pair |

<Check>
After any tell change, re-run the scanner on a known-sloppy fixture and a clean control, and open the local field guide entry for the same tell. Site demo “after” and `fixes.md` should describe the same clean move.
</Check>

## Contribution constraints (repo-encoded)

- **Scanner never writes files.** Fixes go through an agent host following `SKILL.md`, or through human edits—not through `scan.mjs`.
- **No new dependencies** for skill/scanner work; site deps stay under `website/` via `npm install`.
- **Demos are reconstructions** in plain HTML for education—not dunks on specific products.
- **Slop vs intentional:** a tell is only slop when it is an unchosen default; keep defended brand choices.
- **Design system of the guide** must not reintroduce catalogued slop (gradients, emoji spam, glass, badge walls, multi-hue candy semantics).

## What this page does not define

Evidence here does not include PR templates, CI, license text, or automated tests that gate merges. Treat alignment as a maintainer checklist against the paths above until such automation appears in-repo.

## Related pages

<CardGroup>
  <Card title="Catalogue model" href="/catalogue-model">
    How catalogue.ts acts as site SSOT, how demos and i18n attach, and boundaries with skill references.
  </Card>
  <Card title="Extend the catalogue" href="/extend-catalogue">
    Step-level add/update path for a tell: data, i18n, demo, skill taxonomy, detection, and fixes.
  </Card>
  <Card title="Detection patterns" href="/detection-patterns">
    Code-level signals and how findings map back to taxonomy ids.
  </Card>
  <Card title="Scanner CLI reference" href="/scanner-cli-reference">
    Invocation, flags, walk/scan behavior, and the no-edit constraint.
  </Card>
  <Card title="Remediation playbook" href="/fixes-playbook">
    Per-tell clean fixes and how demos illustrate preferred outcomes.
  </Card>
  <Card title="Design tokens" href="/design-tokens">
    Paper/ink palette, single editorial red, and banned slop defaults for the site itself.
  </Card>
  <Card title="Build and deploy" href="/build-and-deploy">
    Static build to dist and deploy-anywhere assumptions for the field guide.
  </Card>
</CardGroup>

---
