Add design-simplification anchor docs and subagents

DESIGN.md v0.3 (token source = ui/src/index.css, scoped Run 1 gates),
GOAL-PROMPT.md v2 (phases 0-2 only, consolidation/rename split out),
PRIOR-ART.md (PAP-280 audit findings), KNOWN-DUPLICATES.md seed,
.claude/agents/{token-auditor,codemod-runner}.md, AGENTS.md link.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
scotttong 2026-07-06 12:59:26 -07:00
parent 903886bc79
commit 0b09f72bdf
7 changed files with 231 additions and 0 deletions

View File

@ -0,0 +1,17 @@
---
name: codemod-runner
description: Writes and runs codemod scripts that replace hardcoded visual values with token references in ui/src/index.css. Use for Phase 2 of the design simplification run — mechanical refactors only.
tools: Read, Write, Edit, Bash, Glob, Grep
model: sonnet
---
You perform mechanical refactors via scripts, never hand-edits. Follow DESIGN.md at the repo root.
Rules:
- The token destination is ui/src/index.css (Tailwind v4), optionally a tokens.css imported by it. NEVER create a parallel token source. Tokens that must be runtime-tunable go in a NON-inline block — `@theme inline` bakes literals at build time.
- Where a hardcoded value EXACTLY matches an existing token, replace it with that token reference. Otherwise extract the value into a new token VERBATIM — no normalizing, rounding, or inventing a scale. Ugly values stay ugly.
- Every rewrite happens through a codemod script committed to scripts/ before it is run. Scripts must be idempotent and reviewable.
- Third-party style overrides that cannot use tokens go on a documented allowlist in the token source, each with an inline comment saying why.
- Verify after every script run: rg gates (zero hardcoded hex, zero arbitrary px/bracket values in ui/src/components/** and ui/src/pages/** outside the allowlist), pnpm typecheck, and the Storybook snapshot suite. Snapshots must match the Phase 0 baseline exactly.
- If a replacement cannot be made without visual change, skip it and record it in TOKEN-AUDIT.md under "Needs human decision".

View File

@ -0,0 +1,16 @@
---
name: token-auditor
description: Scans ui/src/ for hardcoded visual values, duplicate components, and shadcn replacement candidates; produces TOKEN-AUDIT.md and COMPONENT-INVENTORY.md. Read-only on source — never modifies component files. Use for Phase 1 of the design simplification run.
tools: Read, Grep, Glob, Bash
model: sonnet
---
You inventory design-system debt in this repository. Follow DESIGN.md at the repo root; read PRIOR-ART.md first — a previous audit found only 6 of ~220 drift sites were exact-value-mappable to existing tokens, so expect most hardcoded values to need new verbatim tokens.
Your outputs (written to the repo root):
1. TOKEN-AUDIT.md — every hardcoded color/spacing/radius/type/shadow value in ui/src/, with frequency, file locations, and near-duplicate clusters (e.g. 13/14/15px used interchangeably). For each value, note whether it EXACTLY matches one of the ~80 existing tokens in ui/src/index.css (semantic / brand / domain tiers — see DESIGN.md). Flag clusters for human review; never merge or normalize them. Include a "Needs human decision" section.
2. COMPONENT-INVENTORY.md — all components under ui/src/components/ (24 primitives in ui/, ~277 feature components), their variants, and suspected duplicates with evidence (similar props, similar rendered output, copy-pasted origins). Include a "shadcn candidates" section: (a) custom components duplicating an available shadcn primitive, (b) installed shadcn components that drifted from the registry (npx shadcn@latest diff where available), (c) raw Radix/plain elements where an installed shadcn wrapper exists. For each, state the recommended replacement and expected visual impact. Recommendations only — merges and swaps happen in later human-approved runs, never this one.
Never modify source files. Bash access is for read-only commands (rg, find, npx shadcn diff) and writing the two report files only.

View File

@ -220,3 +220,7 @@ PR #2218 (`feat/external-adapter-phase1`) adds external adapter support. See roo
- `createServerAdapter()` must include ALL optional fields (especially `detectModel`)
- Built-in UI adapters can shadow external plugin parsers; external override pause/resume should restore the built-in parser.
- Reference external adapters: Droid (npm); Hermes can also be tested as an override package.
## Design system
`DESIGN.md` at the repo root is the source of truth for UI design decisions. The token-only rule applies to all `ui/` changes: every color, spacing, radius, type, shadow, and motion value comes from the token layer in `ui/src/index.css` — no hex, raw px, or arbitrary Tailwind bracket values in components.

56
DESIGN.md Normal file
View File

@ -0,0 +1,56 @@
# Paperclip Design Principles
**Status:** v0.3 — anchor document for design-language simplification. Governs structure, not brand. Brand values (color, type, iconography) are intentionally unspecified: they are being redesigned and will land as token values only. Nothing in `ui/` may hardcode them. Spacing/radius scales are likewise TBD pending the token audit (see Principle 3).
Changes from v0.2: token layer location corrected to the repo's real source (`ui/src/index.css`); existing token tiers inventoried; snapshot-coverage scope bounded for Run 1; the issue→task copy rename moved out of the zero-visual-change run.
## What this document is for
Agents and humans modifying `ui/` treat this file as the source of truth for design decisions. Storybook is the verification surface — it documents the system; it does not define it. If a change conflicts with this document, change this document first (with review) or change the code.
## Product stance
Paperclip is an operational control plane: org charts, tasks, heartbeat runs, budgets, approvals, audit logs. The user is an operator scanning state and making decisions. Every screen should answer, in order: *what is happening, does it need me, what do I do about it.* Density in service of scanning beats whitespace in service of aesthetics — but density comes from information, never from chrome.
## The token layer (where visual values live)
The single token source is **`ui/src/index.css`** (Tailwind v4; there is no tailwind config file — tokens are CSS custom properties consumed via `@theme`). Do NOT create a parallel token source such as `ui/src/tokens/` — that would produce two sources of truth. If index.css grows unwieldy, extracted values may live in a `tokens.css` **imported by index.css** so the pipeline still has one root.
Tailwind v4 gotcha: `@theme inline` bakes literal values at build time. Any token that must be runtime-tunable (theme editor, dark mode overrides) must be defined in a NON-inline block.
Existing tiers already in index.css (~80+ tokens) — extraction maps to these on **exact value match** before minting anything new:
1. **Semantic tier** — shadcn core set: `--background`, `--foreground`, `--card`, `--primary`, `--secondary`, `--muted`, `--accent`, `--destructive`, `--border`, `--input`, `--ring`, `--sidebar-*`, `--chart-1..5` (OKLCH, light/dark overrides).
2. **Brand tier** — agent gradients `--agent-1a/1b..10a/10b` (fixed hex) and status hues `--status-task-*` / `--status-agent-*` (WCAG-tuned; see inline comments).
3. **Domain tier** — match-chip tokens `--chip-match-*`, annotation highlights `--paperclip-doc-annotation-highlight-*`, plus motion/typography tokens.
## Principles
1. **One way to say each thing.** One component per job. One Button, one Card, one Badge, one Table, one EmptyState. Variants are props, not new components. Before creating a component, prove no existing one covers the job.
2. **Tokens are the only source of visual values.** All color, spacing, radius, type size/weight, shadow, and motion values come from the token layer. No hex, no raw px, no ad-hoc Tailwind arbitrary values (`p-[13px]`) in components. If a needed value doesn't exist, add a token — don't inline it.
3. **Spacing routes through tokens; the scale comes later.** During simplification, extract every spacing and radius value verbatim into tokens — do not normalize, round, or invent a scale. The final scale is a design decision made by a human after reviewing the token audit. Structural rules apply now: vertical rhythm within a container uses one gap value, not per-element margins, and siblings never carry both margin and gap.
4. **Hierarchy through structure, not decoration.** Prefer position, size, and weight over borders, backgrounds, and dividers. Every border, divider, and background fill must justify itself; when in doubt, remove it. A screen should survive the removal of one visual layer.
5. **Status is systematic.** States like running / paused / blocked / awaiting-approval / over-budget map to a single semantic status token set used identically everywhere (badge, row, chart, log). An operator learns the vocabulary once.
6. **Machine values look machine-made.** IDs, costs, token counts, timestamps, and log output use the monospace token and consistent formatting helpers. Never format these ad hoc per screen.
7. **Words are part of the system.** One name per concept across the entire UI — the canonical term is *task* (never *issue* or *ticket* in copy, labels, or empty states). Buttons name the action ("Approve hire," not "Submit"). Errors say what happened and what to do. Empty states say what to do first. **Note:** enforcing the task rename is a visible change and is explicitly OUT of the zero-visual-change extraction run; it happens in its own follow-up run.
8. **Agent-modifiable by design.** The system must be changeable via instructions: single token source, lint rules that enforce it, and this document kept current. A correct change should be expressible as "edit tokens + run checks," not "visit 40 files."
## Enforcement (what "compliant" means for the extraction run)
- **Zero visual change is proven, not promised:** Storybook visual snapshots are baselined before any refactor, and all snapshots match baseline after it. A change that alters rendered output must be intentional and human-approved.
- **Baseline scope for Run 1:** the shared primitives in `ui/src/components/ui/` (each gets a story if missing — there are only ~24) plus the ~46 existing stories under `ui/storybook/stories/`. Do NOT attempt a story for every feature component (~277) in this run; full coverage is a later effort.
- Mechanical rewrites (value extraction, renames) are done via committed codemod scripts in `scripts/`, not hand-edits — reviewable once, repeatable forever.
- Token layer is the single source (`ui/src/index.css`, per above) consumed via CSS variables / Tailwind theme — never values copied into components.
- Lint/grep gates pass: zero hardcoded hex values, zero arbitrary spacing values, zero raw font-size declarations in `ui/src/components/**` and `ui/src/pages/**` outside the token layer and a documented allowlist (third-party overrides, intentional opt-outs commented inline).
- `pnpm build`, `pnpm typecheck`, and `pnpm build-storybook` pass.
- AGENTS.md links here and states the token-only rule.
Aspirational (NOT gating this run): no duplicate components; every component has exactly one story covering its variants; all UI copy says "task".
## Out of scope (do not do during simplification)
No visual redesign, no new colors or typefaces, no layout restructuring, no new dependencies beyond snapshot tooling, no component consolidation/merges (audit + recommend only), no copy renames, no changes to server code or app logic. Simplification means fewer parts, same product.
## Prior art (read before auditing)
See `PRIOR-ART.md` — a previous audit pass (PAP-280/283/284, on the `PAP-282-playground` branch, NOT on master) found that of ~220 hardcoded drift sites, only 6 were exact-value-mappable to existing tokens; expect the verbatim extraction to mint many new tokens that the human scale-collapse step later merges. It also drafted usage rules (radius tiers, CTA tiers, named type styles) that are good candidates for the post-audit scale decision.

103
GOAL-PROMPT.md Normal file
View File

@ -0,0 +1,103 @@
# /goal Prompt — Design Language Simplification, Run 1 (v2)
Paste everything inside the code block below into Claude Code after typing `/goal`, from inside this worktree. Prerequisites already satisfied on this branch: DESIGN.md, PRIOR-ART.md, KNOWN-DUPLICATES.md at repo root; token-auditor + codemod-runner in `.claude/agents/`.
v2 changes vs v1: token destination corrected to `ui/src/index.css`; Phase 0 snapshot scope bounded; component consolidation (old Phase 3) and the issue→task rename REMOVED from this run (they become their own human-gated follow-up runs); DONE-WHEN expressed as runnable commands.
```
Refactor Paperclip's UI so every visual value flows through the single
existing token layer, with provably zero visual change, working in this
isolated git worktree. DESIGN.md at the repo root is the source of truth
for all design decisions; follow it exactly. Read PRIOR-ART.md before
auditing.
SETUP
You are already inside a dedicated git worktree on branch
design/token-extraction. All work happens here. Never touch master,
switch branches, create new worktrees, or modify other working trees.
Commit after each phase and in small, reviewable steps within phases,
with descriptive messages.
WORK IN PHASES, IN ORDER
Delegate Phase 1 to the token-auditor subagent and Phase 2 to the
codemod-runner subagent (defined in .claude/agents/). Handle Phase 0
yourself. Hand context between phases through the committed report
files, not conversation memory.
Phase 0 — Baseline (before changing ANY component):
- Set up Storybook visual snapshot testing (Storybook test-runner with
image snapshots, or equivalent already-compatible tooling; Storybook
lives at ui/storybook/, launched via `pnpm storybook`).
- Coverage scope: the shared primitives in ui/src/components/ui/ (add a
minimal story for any of the ~24 that lack one) plus all existing
stories under ui/storybook/stories/. Do NOT write stories for the
~277 feature components in this run.
- Commit passing baseline snapshots. Every later phase must keep
snapshots matching this baseline.
Phase 1 — Audit (no code changes):
- Produce TOKEN-AUDIT.md at the repo root: every hardcoded
color/spacing/radius/type/shadow value in ui/src/, its frequency,
file locations, and near-duplicate clusters (e.g. 13/14/15px used
interchangeably). Flag clusters for human review — do NOT merge them.
Cross-reference the existing ~80 tokens in ui/src/index.css: for each
hardcoded value, note whether it exactly matches an existing token.
- Produce COMPONENT-INVENTORY.md: all components, their variants, and
suspected duplicates with evidence (similar props, similar rendered
output, copy-pasted origins). Include a "shadcn candidates" section:
(a) custom components duplicating an available shadcn primitive,
(b) installed shadcn components drifted from the registry
(npx shadcn@latest diff where available), (c) raw Radix/plain
elements where an installed shadcn wrapper exists. For each, state
the recommended replacement and expected visual impact.
ALL consolidation and swap items are RECOMMENDATIONS ONLY — no
merges, no swaps, no deletions in this run.
Phase 2 — Extraction (mechanical, via codemod):
- Token destination is ui/src/index.css (Tailwind v4; optionally a
tokens.css imported by index.css). Do NOT create a parallel token
source. Tokens that must be runtime-tunable go in a NON-inline
@theme/:root block (inline @theme bakes literals).
- Where a hardcoded value EXACTLY matches an existing token, replace it
with that token. Otherwise add a new token containing the audited
value VERBATIM — no normalizing, rounding, or inventing a scale.
Ugly values stay ugly; they are the audit.
- Write codemod scripts, committed to scripts/, that perform the
replacements. Run them. Do not hand-edit values file-by-file.
- Third-party style overrides that cannot use tokens go on a documented
allowlist in the token source, each with an inline comment saying why.
DONE WHEN (all verified in this worktree)
1. The snapshot suite passes against the Phase 0 baseline — zero
visual change.
2. ui/src/index.css (plus any imported tokens.css) is the only token
source; components consume values only through it.
3. rg gates pass: zero hex color literals, zero arbitrary
px/bracket-value Tailwind classes, zero raw font-size declarations
in ui/src/components/** and ui/src/pages/** outside the documented
allowlist.
4. TOKEN-AUDIT.md and COMPONENT-INVENTORY.md exist, are current, and
each has a "Needs human decision" section (even if empty).
5. pnpm build, pnpm typecheck, and pnpm build-storybook all exit 0.
GUARDRAILS
- Preserve rendered output exactly. If a replacement cannot be made
without visual change, skip it and record it in TOKEN-AUDIT.md under
"Needs human decision", and move on.
- No redesign, no layout changes, no new colors/typefaces, no component
merges or deletions, no copy renames (including issue→task — that is
a separate later run), no new dependencies beyond snapshot tooling,
no server/app-logic changes.
- If reality conflicts with DESIGN.md, note the conflict in
TOKEN-AUDIT.md instead of guessing.
- If a phase cannot be completed, stop and report rather than partially
applying it.
```
## After the run (human steps)
1. Eyeball pass: `pnpm storybook` here and in the master tree (`-p 6007`), flip between tabs.
2. Read TOKEN-AUDIT.md; choose the real spacing/radius scale (PRIOR-ART.md has drafted rules to start from).
3. Tune tokens; snapshots now fail intentionally — the diff folders are your design-review contact sheet. This is also where the ui.shadcn.com/create preset lands, as token-value edits.
4. Review COMPONENT-INVENTORY.md; approve a merge list and shadcn-swap list → those become Run 2 and Run 3, each its own /goal.
5. Merge to master when satisfied (rebase first if master moved). Scrap path: `git worktree remove ../paperclip-design-simplify --force`.

14
KNOWN-DUPLICATES.md Normal file
View File

@ -0,0 +1,14 @@
# Known duplicates & off-limits areas (human-maintained)
Seed list for the audit. Add components you already believe are redundant, and any screens the run must not touch. The auditor treats entries here as leads to verify, not verdicts.
## Suspected duplicates / overlap (leads)
- Chat composers: the shared `ChatComposer` vs `MarkdownEditor`-based task composer — deliberately NOT unified in a prior pass (PAP-101); audit the overlap but flag as "Needs human decision".
- Agent bubble action rows: `AgentBubbleActionRow.tsx` had two parallel implementations created by concurrent work at one point — verify only one remains.
- Status glyphs/chips: `StatusIcon` vs inline-mention chips vs task chips — intentionally separate systems per prior work; document, don't merge.
## Off-limits in this run
- `ui/src/components/theme-editor/` and anything under experimental theme/playground paths, if present on this branch.
- Server code, adapters, CLI — everything outside `ui/`.

21
PRIOR-ART.md Normal file
View File

@ -0,0 +1,21 @@
# Prior art: PAP-280 design-token audit (branch `PAP-282-playground`, not on master)
A previous audit/relink pass ran against this codebase in mid-2026. Its code never merged to master, but its findings are directly reusable by the token audit. Read this before Phase 1.
## Key findings to inherit
- **Drift is mostly NOT same-value-mappable.** The relink pass (commit `032d6c8db` on the branch) attempted to swap hardcoded values for existing semantic tokens *without visual change* and found only **6 exact-value swaps** possible (`text-muted-fg`, `rounded-md`) out of ~220 audited drift sites (~193 color / 23 radius / 7 type). Implication for Phase 2: expect to mint many new verbatim tokens; do not force-fit near-misses onto existing tokens — that changes pixels.
- **Token gap clusters identified** (commit `96689351d`): recurring un-tokenized needs were a code-surface background, an accent blue, and a muted feed text color — these became `--surface-code`, `--accent-blue`-style gap tokens on the branch. Audit should check whether the same clusters still dominate.
- **Tailwind v4 tunability gotcha** (learned the hard way): `@theme inline` bakes literals at build time; tunable tokens must live in a non-inline block.
## Drafted usage rules (branch commit `6ba86cd4f` — candidates for the human scale decision, NOT current master state)
- **Radius:** one monotonic scale `sm 6 / md 8 / lg 10 / xl 14 / 2xl 16 / full`. Assignments: sm=chips/badges/pills; md=buttons/inputs/menu items (default); lg=cards/popovers/panels; xl=dialogs/sheets/overlays; 2xl=hero/onboarding only; full=avatars/dots/capsules. Nested elements step down one tier from their container. (Master's current values differ — verify in the audit.)
- **CTA tiers:** three-tier button prominence — Primary (`default`/`destructive`): the single commit action per view; Secondary (`secondary`/`outline`): supporting actions; Tertiary (`ghost`/`link`): row actions, cancels, toolbar icons.
- **Type styles:** nine named intent styles (backed by `--text-*` tokens incl. `micro` 11px / `nano` 10px) instead of re-deriving `text-lg font-semibold` per call site. Color is a separate axis.
- **Drift-prevention contract:** no raw hex for chrome — use `background / card / muted / accent / border / muted-foreground`; when a needed value has no token, add a semantic token; intentional opt-outs (code/terminal blocks) carry a comment saying why, so a future re-link pass leaves them alone.
## Reusable machinery on the branch
- A theme playground / theme editor with portable `*.theme.json` export-import (whole-app live retheme, A/B compare). Useful later for the human scale-collapse and brand/preset tune steps — not needed for the extraction run.
- `.claude/skills/design-guide/` skill + `ui/src/pages/DesignGuide.tsx` showcase page (branch versions are richer than master's).