@alexcodeplace/slopgate 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +720 -0
- package/bin/slopgate +44 -0
- package/hooks/baseline-guard.sh +60 -0
- package/hooks/commit-hook.sh +12 -0
- package/hooks/edit-hook.sh +19 -0
- package/hooks/session-start.sh +25 -0
- package/package.json +35 -0
- package/rules/baseline/ast/empty-catch-block-ts.yml +7 -0
- package/rules/baseline/ast/empty-catch-block-tsx.yml +7 -0
- package/rules/baseline/ast/inner-html.yml +9 -0
- package/rules/baseline/ast/slopgate-canary.yml +9 -0
- package/rules/baseline/ast/target-blank-norel.yml +25 -0
- package/rules/baseline/ast/window-in-render.yml +38 -0
- package/rules/baseline/selftest.config.toml +23 -0
- package/rules/ux/ast/ux-anchor-no-href.yml +17 -0
- package/rules/ux/ast/ux-async-onclick-no-disable.yml +17 -0
- package/rules/ux/ast/ux-button-no-type.yml +11 -0
- package/rules/ux/ast/ux-div-onclick.yml +17 -0
- package/rules/ux/ast/ux-img-no-alt.yml +15 -0
- package/rules/ux/ast/ux-img-no-dimensions.yml +15 -0
- package/rules/ux/ast/ux-media-no-dimensions.yml +15 -0
- package/rules/ux/ast/ux-modal-no-close.yml +15 -0
- package/skills/slopgate-improve/SKILL.md +155 -0
- package/skills/slopgate-init/SKILL.md +218 -0
- package/skills/slopgate-ux/SKILL.md +118 -0
- package/vendor/darwin-arm64/slopgate-rs +0 -0
- package/vendor/darwin-x64/slopgate-rs +0 -0
- package/vendor/linux-arm64/slopgate-rs +0 -0
- package/vendor/linux-x64/slopgate-rs +0 -0
- package/vendor/win32-x64/slopgate-rs.exe +0 -0
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: slopgate-init
|
|
3
|
+
description: Onboard any repo to the global slopgate engine. Detect stack, mine the project's OWN local conventions (.claude/skills|agents|commands + CLAUDE.md subtree + editor rules), evaluate which are statically-detectable rule candidates, author the project rule pack, drive violations to zero, wire + verify hooks. Use when adopting slopgate in a new project or re-evaluating an existing project's rules.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# slopgate-init — Project Initialization
|
|
7
|
+
|
|
8
|
+
Bootstraps a repo onto the globally-installed slopgate engine (the `slopgate` CLI on PATH — `npm i -g slopgate`). The engine
|
|
9
|
+
carries zero project knowledge; everything project-specific lives in `<repo>/.slopgate/`. This skill
|
|
10
|
+
produces that directory **from the project's own stated conventions**, not from a generic template.
|
|
11
|
+
|
|
12
|
+
Core idea: a project already documents what it cares about — in its `.claude/skills`, `.claude/agents`,
|
|
13
|
+
`.claude/commands`, its `CLAUDE.md` (+ subtree guides), and editor rule files (`.cursorrules`,
|
|
14
|
+
`.windsurfrules`). Mine those, keep only the conventions a static scanner can enforce, and mechanize them.
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Rule tier model
|
|
19
|
+
|
|
20
|
+
Before authoring any rule, decide which tier it belongs to:
|
|
21
|
+
|
|
22
|
+
| Tier | Lives in | Config key | Who benefits |
|
|
23
|
+
|------|----------|-----------|--------------|
|
|
24
|
+
| **baseline** | built-in (compiled into the engine) | `baseline = ["no-stubs", …]` | Any TypeScript/web project |
|
|
25
|
+
| **stack** | built-in (compiled into the engine) | `stack = ["cloudflare"]` | Projects using that runtime/framework |
|
|
26
|
+
| **project (ast)** | `<repo>/.slopgate/rules/ast/<id>.yml` | `astRules = "./rules/ast"` | This repo only |
|
|
27
|
+
|
|
28
|
+
`baseline`/`stack` packs are engine-internal (compiled-in); a project-setup agent does **not** edit
|
|
29
|
+
their contents — it only enables packs by name in the TOML config. Project-specific rules are authored
|
|
30
|
+
as **ast-grep YAML** in the `astRules` dir. Custom regex rule packs (the old `.mjs` arrays) are **not yet
|
|
31
|
+
supported** by the native engine (planned, PHASE-2); a non-empty `rules = [...]` errors, so `rules` stays `[]`.
|
|
32
|
+
|
|
33
|
+
Assign the **lowest tier** where the rule applies without false positives. Only project-specific business logic belongs in project tier.
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Step 0 — Already initialized?
|
|
38
|
+
|
|
39
|
+
Check if `.slopgate/config.toml` exists in the target repo:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
ls <repo>/.slopgate/config.toml 2>/dev/null
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
If it exists → **stop, invoke `/slopgate-improve` instead.** This skill is for greenfield only.
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## Step 1 — Scaffold (deterministic, the CLI does it)
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
slopgate init <repo-abs-path>
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
This auto-detects source roots (monorepo workspace-aware), exts, and skipDirs; writes a populated
|
|
56
|
+
`.slopgate/config.toml`; emits `.slopgate/convention-sources.json` (the manifest of convention inputs
|
|
57
|
+
to read); and **safe-merges** the edit/commit hooks into the repo's existing `.claude/settings.json`
|
|
58
|
+
(appends, never clobbers — a `.bak` is written). Idempotent: re-running preserves an existing config.
|
|
59
|
+
|
|
60
|
+
Read the printed summary. **Sanity-check the detected `roots`** — fix `config.toml` by hand if the repo
|
|
61
|
+
has an unusual layout the detector missed.
|
|
62
|
+
|
|
63
|
+
## Step 2 — Read the convention sources
|
|
64
|
+
|
|
65
|
+
Open `.slopgate/convention-sources.json`. Read every file it lists: `claudeMd` (root + subtrees),
|
|
66
|
+
`skills`, `agents`, `commands`, `editorRules`, `knowledgeDocs`. These are the project's own rules in
|
|
67
|
+
prose. (For large repos, push the reading to a cursor-agent that returns a candidate table, not file
|
|
68
|
+
dumps — see Step 4 / cursor-orchestrator return-size discipline.)
|
|
69
|
+
|
|
70
|
+
## Step 3 — Evaluate rule candidates (the heart of this skill)
|
|
71
|
+
|
|
72
|
+
For each convention you find, decide if a static scanner can enforce it. Build a candidate table:
|
|
73
|
+
|
|
74
|
+
| field | meaning |
|
|
75
|
+
|-------|---------|
|
|
76
|
+
| `id` | kebab rule id |
|
|
77
|
+
| `source` | which convention file + line stated it |
|
|
78
|
+
| `tier` | `baseline` \| `stack/<name>` \| `project` |
|
|
79
|
+
| `detect` | `regex` \| `ast` \| `none` |
|
|
80
|
+
| `confidence` | high \| med \| low (= false-positive risk, inverted) |
|
|
81
|
+
| `pattern` | the regex / ast pattern (draft) |
|
|
82
|
+
| `exceptGlobs` | legit exceptions (e.g. `**/tokens/**`, PDF/print, generated files) |
|
|
83
|
+
| `severity` | critical \| high \| (lower severities don't gate) |
|
|
84
|
+
|
|
85
|
+
**Detectable (good candidates):**
|
|
86
|
+
- Banned token / element / import — `<table>`, `as any`, `@ts-ignore`, a deprecated primitive import.
|
|
87
|
+
- Hardcoded value where a token is required — hex/rgb/hsl, raw px radius/shadow outside the token file.
|
|
88
|
+
- Required attribute presence — `<img>` without `width`/`height`, missing `alt`.
|
|
89
|
+
- Path-scoped import boundaries — ORM/db import inside `routes/**`, server-only import in client code.
|
|
90
|
+
- File-shape — non-`.webp` image refs, a stub/placeholder/TODO marker.
|
|
91
|
+
|
|
92
|
+
**NOT detectable (skip — do not force a brittle regex):**
|
|
93
|
+
- Semantic / judgment conventions — "use the knowledge-graph tool first", "add delight", "check the
|
|
94
|
+
package before building a new atom", "never duplicate the nav".
|
|
95
|
+
- Runtime behavior, data-shape, or anything needing type information a regex can't see.
|
|
96
|
+
|
|
97
|
+
**Confidence rubric:** high = the pattern matches the violation and almost nothing else; med = some
|
|
98
|
+
false positives expected, needs `exceptGlobs` tuning; low = high FP risk → defer, don't ship noise.
|
|
99
|
+
|
|
100
|
+
**Authoring gotcha (mechanize correctly):** import-membership / import-shape checks are the classic
|
|
101
|
+
regex-rule case — but the native engine does not yet support custom regex rule packs (PHASE-2), so such
|
|
102
|
+
a check is **not currently mechanizable as a project rule**. Do NOT reach for an ast-grep `constraints`
|
|
103
|
+
regex on a spread metavar (`$$$A`) as a substitute — ast-grep constraints do not filter spreads and the
|
|
104
|
+
rule fires on every import. Reserve ast rules for genuine structural patterns (`$X.query($$$)` etc.). If
|
|
105
|
+
a convention truly needs regex (not expressible in ast-grep), defer it as PHASE-2 rather than shipping a
|
|
106
|
+
brittle ast-grep approximation. Never trust a single-line grep's "0 hits" to prove a symbol is absent.
|
|
107
|
+
|
|
108
|
+
## Step 4 — Triage (high-reasoning; the implementer does NOT self-approve)
|
|
109
|
+
|
|
110
|
+
The candidate table is a set of *proposals*. Deciding which to enable — and whether a convention is
|
|
111
|
+
worth a rule at all — is a product-intent call. Per project discipline (cursor-orchestrator / zc-orchestrate),
|
|
112
|
+
an implementing/audit agent **reports** candidates; the orchestrator (+ user for genuine intent calls)
|
|
113
|
+
**decides**. Pick the high-confidence, low-FP candidates to ship now; defer low-confidence ones with a
|
|
114
|
+
one-line reason (never let them silently vanish). Enable baseline packs (`raw-hex`, `kv-ban`, …) only
|
|
115
|
+
when the candidate review shows the project actually wants them.
|
|
116
|
+
|
|
117
|
+
## Step 4b — Offer the UX module (greenfield only)
|
|
118
|
+
|
|
119
|
+
The UX module (a `[ux]` table in config) is **optional and off by default** — UX taste varies, so it is
|
|
120
|
+
never auto-enabled. The scaffold does not emit a `[ux]` table — you add one only on consent. Decide whether to offer it:
|
|
121
|
+
|
|
122
|
+
- **Existing project with substantial UI already written** → do NOT push it. Mention one line
|
|
123
|
+
("UX module available — add a `[ux]` table to config to enable") and move on. Turning it on now would
|
|
124
|
+
flag a pile of pre-existing markup; ratchet absorbs gating violations, but the advisory noise annoys.
|
|
125
|
+
- **Greenfield / "just vibing a new project"** → offer it. These are good-enough defaults for someone
|
|
126
|
+
with no strong UI opinion. Ask the user which sub-modules to enable (don't assume):
|
|
127
|
+
|
|
128
|
+
Sub-modules (`[ux]` keys, value = `"high"` \| `"advisory"` \| `true`; `"advisory"` reports but never blocks, `"high"` gates, `true` = the pack's default severity below):
|
|
129
|
+
| key | catches | default |
|
|
130
|
+
|-----|---------|---------|
|
|
131
|
+
| `a11y` | `<div onClick>`→`<button>`, anchor-no-href, img-no-alt, button-no-type, positive tabIndex (§11) | `high` |
|
|
132
|
+
| `cls` | `<img>`/`<video>`/`<iframe>` without width/height → layout shift (§13) | `high` |
|
|
133
|
+
| `feedback` | async `onClick` button with no `disabled` state → double-submit (§3/§12) | `high` |
|
|
134
|
+
| `taste` | emoji-as-icon, "Trusted by", Lorem ipsum, robotic microcopy, heavy drop-shadow, linear/long motion (§0/§6/§26) | `advisory` |
|
|
135
|
+
| `advisory` | modal-no-close, index-as-key, view-state-not-in-URL — higher false-positive nudges (§10/§14) | `advisory` |
|
|
136
|
+
|
|
137
|
+
Use AskUserQuestion (multi-select sub-modules + a severity choice). On consent, author the
|
|
138
|
+
`[ux]` table in `.slopgate/config.toml`. Opt-out UX is symmetric: deleting a key disables one sub-module,
|
|
139
|
+
deleting the table disables the module. Pair with the `/slopgate-ux` skill (prompt-time design
|
|
140
|
+
directives) for the semantic UX rules a static scanner can't enforce.
|
|
141
|
+
|
|
142
|
+
## Step 5 — Author the approved rules
|
|
143
|
+
|
|
144
|
+
- **Baseline/stack rules** are built into the engine — a project-setup agent does **not** author or edit
|
|
145
|
+
them, it only enables packs by name (`baseline = [...]` / `stack = [...]`) in `config.toml`.
|
|
146
|
+
- **Project regex rules** are **not yet supported** by the native engine (PHASE-2). Do NOT author a `.mjs`
|
|
147
|
+
rule pack and do NOT set `rules = [...]` — a non-empty `rules` errors. Keep `rules = []`. If a convention
|
|
148
|
+
genuinely needs regex (not expressible in ast-grep), defer it with a one-line reason.
|
|
149
|
+
- **Project AST rules** → `.slopgate/rules/ast/<id>.yml` (ast-grep YAML — this is THE project-rule path).
|
|
150
|
+
- Add `.slopgate/fixtures/src/` canary files so `--self-test` proves each rule fires.
|
|
151
|
+
- Keep `astRules = "./rules/ast"` in `config.toml`; leave `rules = []`.
|
|
152
|
+
- To silence a built-in ast rule, list its `id` in `astDisable = [...]`. (Overriding a built-in
|
|
153
|
+
baseline/stack rule's pattern from a project rule pack was a regex-pack feature — deferred to PHASE-2.)
|
|
154
|
+
|
|
155
|
+
## Step 6 — Drive to zero (zero-tolerance before enabling)
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
slopgate --self-test --config .slopgate/config.toml # expect 0
|
|
159
|
+
# full dry-run count per rule id → must reach {}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
**Exit 0 is NOT enough — confirm the self-test actually exercised every path.** A self-test that
|
|
163
|
+
*structurally cannot fail* is worse than none (it hid two real engine bugs behind a green adoption).
|
|
164
|
+
Read the lines, not just the code: every regex rule must print `OK <id>`, and the ast line must read
|
|
165
|
+
`OK ast-grep canary (N fixture violations)` with **N ≥ 1** — a `0`-violation canary, a `WARN ast-grep
|
|
166
|
+
unavailable`, or any `FAIL ast: …` line means the ast path didn't truly run (broken project ast rule,
|
|
167
|
+
missing binary, or wrong scan target). Treat those as a red self-test even if a later `exit=0` slips by.
|
|
168
|
+
|
|
169
|
+
For each non-zero id: fix the offending source (preferred) or, only with **user approval**, add a
|
|
170
|
+
`suppressions.json` entry. Re-run until counts are `{}`. Do not rely on the hooks firing until the
|
|
171
|
+
existing tree is clean — otherwise every later edit trips legacy debt.
|
|
172
|
+
|
|
173
|
+
## Step 7 — Verify hooks live
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
# self-test already green. Prove the PostToolUse wiring end-to-end:
|
|
177
|
+
echo 'export const c = "#ff0044";' > <a-scanned-root>/__slopgate_probe.ts
|
|
178
|
+
echo "{\"tool_input\":{\"file_path\":\"$PWD/<a-scanned-root>/__slopgate_probe.ts\"}}" | "$(npm root -g)/slopgate/hooks/edit-hook.sh"; echo "edit_hook=$?"
|
|
179
|
+
rm <a-scanned-root>/__slopgate_probe.ts
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Expect `edit_hook=2` with the violation printed (only if a hex/hardcoded-value rule is enabled; else use
|
|
183
|
+
any enabled rule's canary). If not 2, the wiring is broken — fix before committing.
|
|
184
|
+
|
|
185
|
+
## Step 8 — Commit runtime config only
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
git add .slopgate/config.toml .slopgate/rules .slopgate/suppressions.json .slopgate/convention-sources.json .claude/settings.json
|
|
189
|
+
git commit -m "feat: adopt slopgate (<project> rule pack + edit/commit hooks)"
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
Commit `.slopgate/**` + `.claude/settings.json` only — the pinned-rules design requires rules to live
|
|
193
|
+
in project git. Do NOT add fixtures-only or `.bak` files unless the repo wants them. If the repo's git
|
|
194
|
+
allow-list rejects `.slopgate/`, STOP and ask the user.
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
198
|
+
## Red flags
|
|
199
|
+
|
|
200
|
+
- Forcing a regex for a semantic convention → noise; if `detect: none`, skip it.
|
|
201
|
+
- ast-grep `constraints` on a `$$$` spread for import checks → mass false positives; regex rule packs are PHASE-2, so defer such a check rather than approximating it with ast-grep.
|
|
202
|
+
- Wiring hooks before the tree is at zero → every edit trips legacy debt.
|
|
203
|
+
- Overwriting an existing `.claude/settings.json` → the CLI safe-merges; never hand-replace it.
|
|
204
|
+
- An implementing agent self-approving which conventions become rules → that's the orchestrator's call.
|
|
205
|
+
- Enabling a baseline pack the candidate review didn't justify (e.g. `kv-ban` in a non-CF repo).
|
|
206
|
+
- Authoring a project rule that belongs in baseline/stack — check existing packs first.
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
## Learned Rules
|
|
211
|
+
|
|
212
|
+
### install-hooks-from-worktree | fired:1 | 2026-06-14
|
|
213
|
+
Running `install-hooks` / agent-hooks install from a temp or verification worktree (`/tmp/*`, `.worktrees/*`) → wrong: writes that worktree's CWD absolute path into global `~/.claude/settings.json` without dedup; deleting the worktree dangles the path → "not found" on every Edit/commit/session, and repeats stack duplicate hook fires (broke unstoppable production sessions, 2026-06-14).
|
|
214
|
+
Prevent: install hooks ONLY from the canonical repo checkout. Verify wiring via direct hook stdin test (Step 7), never a global install from a throwaway tree. After any stray install, `grep ~/.claude/settings.json` for the worktree/tmp path and delete the stale entry across ALL hook groups (PostToolUse/PreToolUse/SessionStart — rot triplicates).
|
|
215
|
+
|
|
216
|
+
### ast-rule-shape | fired:1 | 2026-06-14
|
|
217
|
+
Authoring `.slopgate/rules/ast/*.yml` with a top-level `pattern: |` holding `kind:`/`children:` → wrong: invalid ast-grep, matches nothing. Real shape = top-level `rule:` holding `pattern: '<code-snippet>'` OR structural `kind/has/inside/all/any/not`; slopgate severity/category/resolution live in the JSON `note` field, separate from ast-grep's own `severity:`.
|
|
218
|
+
Prevent: before writing an ast rule, read a shipped one (e.g. `rules/baseline/ast/empty-catch-block-tsx.yml`) and copy its shape. Fixtures = source canaries in `.slopgate/fixtures/src/*.tsx` (Step 5), never `.case`/`.output` JSON. When delegating doc/rule rewrites to a subagent, read the substantive output — diffstat + residual-grep does not catch a fabricated format.
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: slopgate-ux
|
|
3
|
+
description: Inject the ANTI-SLOP UX framework as design directives before generating or modifying any UI. Enforces complete states, action hierarchy, feedback loops, accessibility, performance, and human-centric microcopy — the semantic UX rules a static scanner cannot catch. Use before building or editing components, pages, forms, modals, tables, or any user-facing interface. Complements the slopgate `ux:{}` static rule module (which gates the mechanical subset).
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# slopgate-ux — Anti-Slop UX Directives
|
|
7
|
+
|
|
8
|
+
Prompt-time companion to the slopgate `ux:{}` static module. The static module gates the *mechanical*
|
|
9
|
+
UX slop a scanner can see (`<div onClick>`, `<img>` without dimensions, emoji-as-icon, magic px/hex,
|
|
10
|
+
linear easing). **This skill carries the semantic half** — the cross-component, dataflow, and judgment
|
|
11
|
+
directives no regex/AST rule can enforce. Run the checklist **silently before outputting UI code**; if any
|
|
12
|
+
answer is NO, revise before emitting.
|
|
13
|
+
|
|
14
|
+
> Mission: generate human-centric, intuitive, **complete** interfaces. Avoid "UX slop": lazy, incomplete,
|
|
15
|
+
> or cognitively overwhelming designs optimized only for the happy path.
|
|
16
|
+
|
|
17
|
+
## 0. Generic-AI-slop alarm bells — reject on sight
|
|
18
|
+
Centered hero + two stacked CTAs over a gradient · "Trusted by" logo strip under the hero · bento-box
|
|
19
|
+
grids (3–4 icon/heading/paragraph cards) · emoji as bullets/section markers/icons · decorative
|
|
20
|
+
Lucide/Heroicons filling empty space · floating image cards with heavy drop shadows.
|
|
21
|
+
*(emoji / Trusted-by / drop-shadow are also caught statically by `ux:taste`.)*
|
|
22
|
+
|
|
23
|
+
## 1. Four states (complete states)
|
|
24
|
+
Every data-driven view implements **all four**: **Empty** (one sentence, one action, no illustration,
|
|
25
|
+
written like a person speaks) · **Loading** (skeleton blocks matching final layout, no shimmer, never
|
|
26
|
+
freeze the UI) · **Error** (friendly, actionable, with retry) · **Populated** (happy path).
|
|
27
|
+
|
|
28
|
+
## 2. Hierarchy protocol (no "button soup")
|
|
29
|
+
ONE primary (solid) action per view/section/form. Secondary = outline, tertiary = ghost/text. Tuck
|
|
30
|
+
low-priority actions in kebab menus. Destructive = visually distinct (red) + confirmation.
|
|
31
|
+
|
|
32
|
+
## 3. Action–reaction (feedback loop)
|
|
33
|
+
Every interaction → immediate visual feedback. Distinct hover/focus/active states. During async: disable
|
|
34
|
+
the trigger + inline loading indicator. Completion: explicit success/error toast or inline alert.
|
|
35
|
+
*(async-button-without-disable is partially catchable; the rest is judgment.)*
|
|
36
|
+
|
|
37
|
+
## 4. Friction = risk
|
|
38
|
+
Low-stakes/high-frequency → zero friction (single click). High-stakes/low-frequency → intentional
|
|
39
|
+
friction (confirm modal, or type "DELETE").
|
|
40
|
+
|
|
41
|
+
## 5. Cognitive load (progressive disclosure)
|
|
42
|
+
Group into cards/sections. Tabs/accordions/modals/drill-downs for secondary info. ≤5–7 primary
|
|
43
|
+
actions or major data points per glance.
|
|
44
|
+
|
|
45
|
+
## 6. Microcopy
|
|
46
|
+
Human, conversational ("Save changes", not "Submit Data"). No Lorem ipsum in functional drafts —
|
|
47
|
+
generate realistic, domain-specific placeholder data to test real text wrapping.
|
|
48
|
+
|
|
49
|
+
## 7. Defensive forms
|
|
50
|
+
Validate on type/blur, not only on submit. Accept natural formatting (spaces/dashes in phone/CC),
|
|
51
|
+
strip on the backend. Show input rules up front; don't make the user guess and fail.
|
|
52
|
+
|
|
53
|
+
## 8. Spatial & touch ergonomics
|
|
54
|
+
Min 44×44px touch target regardless of icon size. Physically separate destructive actions (Delete,
|
|
55
|
+
Cancel) from progression actions (Save, Next).
|
|
56
|
+
|
|
57
|
+
## 9. Data density (anti-scroll)
|
|
58
|
+
Any list/table >20 items → pagination / infinite scroll / "Load More". Complex tables get ≥2 parsing
|
|
59
|
+
tools (search, column sort, filter).
|
|
60
|
+
|
|
61
|
+
## 10. Wayfinding (no dead ends)
|
|
62
|
+
Every screen/modal/overlay has explicit Cancel/Close/Back — never rely on browser back. Global nav
|
|
63
|
+
highlights current location. Nesting >2 levels → breadcrumbs. Use an existing breadcrumb primitive;
|
|
64
|
+
if none exists, **create the primitive first** (never inline ad-hoc breadcrumbs).
|
|
65
|
+
|
|
66
|
+
## 11. Functional accessibility
|
|
67
|
+
Semantic HTML first (`<button>`, `<nav>`, `<dialog>`) over `div`+handler. Visible `:focus` on every
|
|
68
|
+
interactive element; logical tab order. Text contrast ≥12:1 (no WCAG-minimum greys). Hairline borders
|
|
69
|
+
within 0.04 L of their surface. Accent color ≤ once per section.
|
|
70
|
+
*(`<div onClick>` is gated statically by `ux:a11y`.)*
|
|
71
|
+
|
|
72
|
+
## 12. State-machine integrity
|
|
73
|
+
Debounce/throttle high-frequency inputs (search, slider). Mutex: once a mutating action fires (submit),
|
|
74
|
+
lock the whole form until the promise resolves — prevent double-submit.
|
|
75
|
+
|
|
76
|
+
## 13. Perceived performance
|
|
77
|
+
Optimistic updates for high-confidence reversible actions (favorite heart); roll back on failure.
|
|
78
|
+
Zero CLS: reserve space via aspect-ratio / fixed min-height so the page never jumps.
|
|
79
|
+
*(`<img>` without dimensions is gated statically by `ux:cls`.)*
|
|
80
|
+
|
|
81
|
+
## 14. URL truth (the refresh test)
|
|
82
|
+
Sync view modifiers — active tab, page index, search query, filters — to URL query params
|
|
83
|
+
(`?tab=billing&page=2`). A copied URL must reproduce the exact view for a colleague.
|
|
84
|
+
|
|
85
|
+
## 15. Tokenization over hardcoding
|
|
86
|
+
Never hardcode hex or px. Use design tokens / CSS vars / utility scale (`var(--color-primary)`,
|
|
87
|
+
`mt-4`). *(raw hex + magic px gated statically by baseline `raw-hex`.)*
|
|
88
|
+
|
|
89
|
+
## 16. Advanced a11y
|
|
90
|
+
Trap focus inside an open modal; return focus to the opener on close. Wrap dynamic announcements
|
|
91
|
+
(toasts, "5 results") in `aria-live="polite"`.
|
|
92
|
+
|
|
93
|
+
## 17–26 — Psychology, flow, ethics
|
|
94
|
+
17 **Undo over permission**: for mid-level destructive acts, execute + show "Undo" toast; hard-confirm
|
|
95
|
+
only catastrophic/irreversible ones. · 18 **Command palette** (Cmd/Ctrl+K) + visible shortcuts for SaaS.
|
|
96
|
+
· 19 **Local-first**: treat offline as normal — queue mutations, subtle "saving…will sync" indicator,
|
|
97
|
+
keep cached data interactive. · 20 **Predictive defaults**: infer timezone, default date ranges,
|
|
98
|
+
`autoFocus` the key input. · 21 **Fitts's law**: reveal row/card actions inline on hover; place context
|
|
99
|
+
menus at the cursor. · 22 **Emotional tone**: never celebrate destructive/stressful actions (no confetti
|
|
100
|
+
on "account deleted"); keep them somber. · 23 **2 AM rule**: scannable, bold key metrics, icons+text;
|
|
101
|
+
never rely on subtle color shifts. · 24 **Chronological grace**: auto-save any >30s process; restore
|
|
102
|
+
unsubmitted state on return. · 25 **Symmetrical effort**: undoing/cancelling costs the same friction as
|
|
103
|
+
doing/starting (no roach-motels). · 26 **Organic motion**: never `linear` easing — spring/bezier,
|
|
104
|
+
200–300ms. *(linear easing gated statically by `ux:taste`.)*
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## Execution checklist (run silently before outputting code)
|
|
109
|
+
- [ ] **State & data** — Empty / Loading / Error handled? Large lists paginated?
|
|
110
|
+
- [ ] **Hierarchy & spatial** — exactly ONE primary action? Touch targets ≥44×44px?
|
|
111
|
+
- [ ] **Feedback & mutex** — immediate feedback? Forms locked during submit?
|
|
112
|
+
- [ ] **Performance** — optimistic where sensible? CLS prevented (reserved space)?
|
|
113
|
+
- [ ] **Routing** — tabs/filters synced to URL (passes the refresh test)?
|
|
114
|
+
- [ ] **Scalability** — design tokens, not magic numbers?
|
|
115
|
+
- [ ] **A11y & focus** — semantic elements? Focus trapped in modals + returned on close? Dynamic alerts via `aria-live`?
|
|
116
|
+
- [ ] **Human empathy** — emotional tone fits the action? Respects the 2 AM rule? Forms auto-save? Motion uses organic easing?
|
|
117
|
+
|
|
118
|
+
**If any answer is NO, revise before emitting the final code.**
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|