mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-11 21:57:14 +03:00
Compare commits
34
Commits
cli-v4.0.4
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cb56ed6c19 | ||
|
|
3e1f67c52c | ||
|
|
0c09f4c7e2 | ||
|
|
7a7579858c | ||
|
|
67d018fe05 | ||
|
|
3bdb9ff06c | ||
|
|
cd12f8660e | ||
|
|
43088d8fbf | ||
|
|
a8ce5962d3 | ||
|
|
7d6c5bdd92 | ||
|
|
73552b79c5 | ||
|
|
73a6f51a54 | ||
|
|
9947af8ca5 | ||
|
|
05ef444b7d | ||
|
|
12ffee04c2 | ||
|
|
d25059e003 | ||
|
|
6496f49a1e | ||
|
|
2bc2879276 | ||
|
|
599de0e949 | ||
|
|
ec0928d786 | ||
|
|
ea8bfc1d99 | ||
|
|
bd6964c35b | ||
|
|
44e825090e | ||
|
|
8b39f41949 | ||
|
|
4957fd7069 | ||
|
|
93bfe70c58 | ||
|
|
4db7f6ba4b | ||
|
|
731e2b1e67 | ||
|
|
dbdc470e70 | ||
|
|
8426ac2f9a | ||
|
|
36e4cea693 | ||
|
|
c4a4f035ed | ||
|
|
457d152292 | ||
|
|
dfb33f7d57 |
@@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
name: impeccable
|
name: impeccable
|
||||||
description: Use when the user wants to design, redesign, shape, critique, audit, polish, clarify, distill, harden, optimize, adapt, animate, colorize, extract, or otherwise improve a frontend interface. Covers websites, landing pages, dashboards, product UI, app shells, components, forms, settings, onboarding, and empty states. Handles UX review, visual hierarchy, information architecture, cognitive load, accessibility, performance, responsive behavior, theming, anti-patterns, typography, fonts, spacing, layout, alignment, color, motion, micro-interactions, UX copy, error states, edge cases, i18n, and reusable design systems or tokens. Also use for bland designs that need to become bolder or more delightful, loud designs that should become quieter, live browser iteration on UI elements, or ambitious visual effects that should feel technically extraordinary. Not for backend-only or non-UI tasks.
|
description: Use when the user wants to design, redesign, shape, critique, audit, polish, clarify, distill, harden, optimize, adapt, animate, colorize, extract, or otherwise improve a frontend interface. Covers websites, landing pages, dashboards, product UI, app shells, components, forms, settings, onboarding, and empty states. Handles UX review, visual hierarchy, information architecture, cognitive load, accessibility, performance, responsive behavior, theming, anti-patterns, typography, fonts, spacing, layout, alignment, color, motion, micro-interactions, UX copy, error states, edge cases, i18n, and reusable design systems or tokens. Also use for bland designs that need to become bolder or more delightful, loud designs that should become quieter, live browser iteration on UI elements, or ambitious visual effects that should feel technically extraordinary. Not for backend-only or non-UI tasks.
|
||||||
version: 4.2.2
|
version: 4.3.1
|
||||||
license: Apache 2.0
|
license: Apache 2.0
|
||||||
allowed-tools:
|
allowed-tools:
|
||||||
- Bash(npx impeccable *)
|
- Bash(npx impeccable *)
|
||||||
@@ -17,9 +17,11 @@ Core principles:
|
|||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
1. Run `<skill-base-dir>/scripts/impeccable context` once per session, where `<skill-base-dir>` is the directory that contains this SKILL.md (the skill folder, not a plugin root two levels above it); keep cwd at the user's project. That base directory resolves every `.agent/skills/impeccable/scripts/impeccable <verb>` command in this skill and its references, and `.agent/skills/impeccable/scripts` is the fallback only when the runtime reports no base directory. On a Windows shell without `sh`, call `.agent/skills/impeccable/scripts/impeccable.cmd` instead. The launcher runs a self-contained binary that ships next to it or is downloaded once on first run; no Node or other runtime is required. Pass a named source file or route as `--target <path>`. It loads PRODUCT.md, DESIGN.md, the matching surface brief, and native-platform guidance when applicable; follow its directives and do not rerun it. If the launcher is refused, missing, or fails, tell the user before editing that context loading did not run. Read existing **PRODUCT.md** and **DESIGN.md** without inventing missing context, then continue with steps 2–3.
|
1. Run `<skill-base-dir>/scripts/impeccable context` once per session, where `<skill-base-dir>` is the directory that contains this SKILL.md (the skill folder, not a plugin root two levels above it); keep cwd at the user's project. That base directory resolves every `.agent/skills/impeccable/scripts/impeccable <verb>` command in this skill and its references, and `.agent/skills/impeccable/scripts` is the fallback only when the runtime reports no base directory. On a Windows shell without `sh`, call `.agent/skills/impeccable/scripts/impeccable.cmd` instead. The launcher runs a self-contained binary that ships next to it or is downloaded once on first run; no Node or other runtime is required. Pass a named source file or route as `--target <path>`. It loads PRODUCT.md, DESIGN.md, the matching surface brief, and native-platform guidance when applicable; follow its directives and do not rerun it.
|
||||||
2. Load the request's playbook: its Commands-table reference for an explicit/implied sub-command, or [reference/new-work.md](reference/new-work.md) for a new surface or replacement visual world. Inspect target and incumbent visual truth before editing. When the app cannot run, start with committed visual-regression goldens or screenshot fixtures; verify target and freshness against current tokens, CSS, components, or assets, resolve conflicts, and compare theme/variant captures.
|
2. Load the request's playbook: its Commands-table reference for an explicit/implied sub-command, or [reference/new-work.md](reference/new-work.md) for a new surface or replacement visual world. Inspect target and incumbent visual truth before editing. When the app cannot run, start with committed visual-regression goldens or screenshot fixtures; verify target and freshness against current tokens, CSS, components, or assets, resolve conflicts, and compare theme/variant captures.
|
||||||
3. After analysis and direction are resolved, load [reference/craft-floor.md](reference/craft-floor.md) immediately before editing UI. It carries the quality floor, the absolute bans, and the reflexes no detector catches. Do not load it for planning-only work.
|
3. After resolving analysis and direction, read [reference/craft-floor.md](reference/craft-floor.md) immediately before any UI edit, including small refinements. It carries the quality floor, the absolute bans, and the reflexes no detector catches. Do not load it for planning-only work.
|
||||||
|
|
||||||
|
**Launcher unavailable:** On refusal or failure, send a separate message **before the next tool call**: “Context loading did not run; I’ll read the existing project context directly.” Then read existing PRODUCT.md and DESIGN.md without inventing missing context, follow applicable steps 2–3, and continue through permitted tools. This applies to planning and editing; launcher failure alone does not block either.
|
||||||
|
|
||||||
## How to design
|
## How to design
|
||||||
|
|
||||||
|
|||||||
@@ -188,6 +188,12 @@ Test thoroughly across contexts:
|
|||||||
- **Edge cases**: Very small screens (320px), very large screens (4K)
|
- **Edge cases**: Very small screens (320px), very large screens (4K)
|
||||||
- **Slow connections**: Test on throttled network
|
- **Slow connections**: Test on throttled network
|
||||||
|
|
||||||
|
**Custom controls** (sliders, drag surfaces, scrollable control strips): a before/after slider can pass every width check above and still refuse to drag on iOS, so exercise each one in scope in the same batched round as the checks above:
|
||||||
|
|
||||||
|
- **Primary gesture**: Tap it and confirm it responds as designed, then drag it with the target input method; the drag must complete, not just start
|
||||||
|
- **Scroll across it**: A swipe along the page's scroll axis across the control scrolls the page or container without activating it; a drag that starts on the control along its axis moves the control, not the page. Neither failure throws an error, so try both
|
||||||
|
- **Evidence**: Say what produced the evidence: an emulated viewport, synthesized touch input through a browser tool, which engine ran it (Chromium is not Safari), or a physical device. Screenshots and resized viewports verify layout, never a gesture. Name what stayed untested and move on; unreachable hardware is a reported gap, not a blocker
|
||||||
|
|
||||||
When the adaptation feels native to each context, hand off to `/impeccable polish` for the final pass.
|
When the adaptation feels native to each context, hand off to `/impeccable polish` for the final pass.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -48,11 +48,12 @@ Run comprehensive checks across 5 dimensions. Score each dimension 0-4 using the
|
|||||||
**Check for**:
|
**Check for**:
|
||||||
- **Fixed widths**: Hard-coded widths that break on mobile
|
- **Fixed widths**: Hard-coded widths that break on mobile
|
||||||
- **Touch targets**: Interactive elements < 44x44px
|
- **Touch targets**: Interactive elements < 44x44px
|
||||||
|
- **Broken touch interaction**: Custom sliders, drag surfaces, and scrollable control strips whose primary gesture fails under touch, that swallow page scroll or lose the drag to it, or that stay stuck after an interrupted gesture. Code tells: mouse-only handlers, no `touch-action` on a pointer-event drag surface, drag state that nothing clears on cancel, lost capture, or blur. Exercise the gesture when a browser tool can synthesize touch (a rendered viewport proves layout, not the gesture), then say what produced the evidence (emulated viewport, synthesized touch, which engine, physical device) and what stayed untested
|
||||||
- **Horizontal scroll**: Content overflow on narrow viewports
|
- **Horizontal scroll**: Content overflow on narrow viewports
|
||||||
- **Text scaling**: Layouts that break when text size increases
|
- **Text scaling**: Layouts that break when text size increases
|
||||||
- **Missing breakpoints**: No mobile/tablet variants
|
- **Missing breakpoints**: No mobile/tablet variants
|
||||||
|
|
||||||
**Score 0-4**: 0=Desktop-only (breaks on mobile), 1=Major issues (some breakpoints, many failures), 2=Partial (works on mobile, rough edges), 3=Good (responsive, minor touch target or overflow issues), 4=Excellent (fluid, all viewports, proper touch targets)
|
**Score 0-4**: 0=Desktop-only (breaks on mobile), 1=Major issues (some breakpoints, many failures), 2=Partial (works on mobile, rough edges), 3=Good (responsive, minor touch target or overflow issues), 4=Excellent (fluid, all viewports, proper touch targets, gestures work under touch)
|
||||||
|
|
||||||
### 5. Implementation Integrity (CRITICAL)
|
### 5. Implementation Integrity (CRITICAL)
|
||||||
|
|
||||||
|
|||||||
@@ -26,12 +26,12 @@ Every region with `medium: raster` in the spec ships as a plate at its `plate` p
|
|||||||
Per region, in the spec's order:
|
Per region, in the spec's order:
|
||||||
|
|
||||||
1. `.agent/skills/impeccable/scripts/impeccable comp-spec --crop <id>` writes the reference crop under `.impeccable/build/crops/`.
|
1. `.agent/skills/impeccable/scripts/impeccable comp-spec --crop <id>` writes the reference crop under `.impeccable/build/crops/`.
|
||||||
2. Produce the plate. With the API fallback: `.agent/skills/impeccable/scripts/impeccable generate-image --plate <id> --quality high` does the whole step (crop as reference, the spec's plate prompt, output size chosen from the region's aspect, the file written to its plate path, prompt embedded, and the plate scored against the crop). With a harness-native image tool: use the crop as the input image and `.agent/skills/impeccable/scripts/impeccable comp-spec --plate-prompt <id>` as the prompt, write the result to the plate path, then run `.agent/skills/impeccable/scripts/impeccable embed-prompt <plate> --prompt "<the exact prompt>"`.
|
2. Choose the background from the approved region: an isolated figure, object, or line drawing on the page ground is a **transparent cutout**; a photograph, full-frame illustration, or texture stays **opaque**. Save `.agent/skills/impeccable/scripts/impeccable comp-spec --plate-prompt <id> --background transparent` to a UTF-8 prompt file for a cutout; use `--background opaque` otherwise. The transparent prompt preserves reference placement and clear margins, white paint, fine edges, and interior holes.
|
||||||
3. Read the score line. `PLATE-SCORE` under 50%, or a `PLATE-WARN`, means the plate does not read as the region: open the plate beside the crop, name what drifted (subject, framing, palette, style), tighten the prompt with that, and regenerate once. Two misses on one region: keep the better plate, mark it `needs_parent_review`, and say why in one line.
|
3. Produce the plate at its exact spec `plate` path. Create the output directory first and choose a supported output size matching the region's aspect, at least 1.5x its pixel dimensions. Prefer the harness-native image tool with the crop as input and the saved prompt; request a transparent PNG for cutouts, then run `.agent/skills/impeccable/scripts/impeccable embed-prompt <plate> --prompt-file <prompt.txt>` (if you refine the prompt, save and embed the exact text sent). With the API fallback, run `.agent/skills/impeccable/scripts/impeccable generate-image --ref <crop.png> --prompt-file <prompt.txt> --out <plate.png> --size <WxH> --quality high --background transparent` for a cutout, or `--background opaque` otherwise. The API fallback embeds the prompt and records the background in the sidecar. The output must be PNG; the fallback requests native alpha and performs no chroma-keying.
|
||||||
4. Transparent cutouts (a figure or object on the page ground): generate on a flat chroma color absent from the subject and key it to alpha before writing the PNG; never ship the keyed background.
|
4. Open the plate beside the crop and compare subject, placement, scale, palette, and style. For cutouts, verify a real alpha channel and inspect composites on light and dark grounds: white paint must stay solid, interior holes must clear, and fine edges must avoid halos. Inspect glass and soft shadows carefully; partial alpha alone does not ensure convincing translucency. Never chroma-key native transparent output or flatten it before saving. If a native tool returns opaque pixels or a painted checkerboard, retry with the API fallback when available; otherwise report the transparency blocker. On a visual miss, tighten the prompt and regenerate once. Two misses on one region: keep the better plate, mark it `needs_parent_review`, and name the drift. The parent runs the plates gate after all assets exist; report `unscored` until a gate score is available.
|
||||||
|
|
||||||
Do not redesign. Do not add objects, restyle, or reinterpret; the comp was approved as it is. Do not touch the page code, the spec, or the comp. Do not produce anything the spec does not list; a region the parent forgot goes back as a one-line note, not a plate.
|
Do not redesign. Do not add objects, restyle, or reinterpret; the comp was approved as it is. Do not touch the page code, the spec, or the comp. Do not produce anything the spec does not list; a region the parent forgot goes back as a one-line note, not a plate.
|
||||||
|
|
||||||
## Output Contract
|
## Output Contract
|
||||||
|
|
||||||
Return one line per raster region: `<id> <plate path> <WxH> <score>% <accepted|needs_parent_review|blocked> <one-line note or ->`. Then `blockers` (missing spec, missing comp, no image capability, exhausted key) and `assumptions`, each global and minimal. Nothing else: no summary, no praise, no implementation advice. The parent runs `impeccable build-phase advance` to verify the plates against the same spec; your line and its line must agree.
|
Return one line per raster region: `<id> <plate path> <WxH> <score%|unscored> <accepted|needs_parent_review|blocked> <one-line note or ->`. Then `blockers` (missing spec, missing comp, no image capability, exhausted key) and `assumptions`, each global and minimal. Nothing else: no summary, no praise, no implementation advice. The parent runs `impeccable build-phase advance` to verify the plates against the same spec; a visual acceptance does not override a failing gate.
|
||||||
@@ -5,7 +5,7 @@ This harness has no subagent capability, so you are running this role inline. St
|
|||||||
|
|
||||||
You record a project's design system after the build is done. Ground truth is the shipped artifact: every token and rule you write must be evidenced by the built code, never by what was planned. Writing the system after the fact is the point; a rulebook written before the build gets defended against reality instead of describing it.
|
You record a project's design system after the build is done. Ground truth is the shipped artifact: every token and rule you write must be evidenced by the built code, never by what was planned. Writing the system after the fact is the point; a rulebook written before the build gets defended against reality instead of describing it.
|
||||||
|
|
||||||
You run under a hard turn ceiling that ends the run without warning, and a run that ends before DESIGN.md is written has recorded nothing. Batch several Reads into each turn, take `reference/document.md` and the stylesheets first, sample components rather than walking the tree, and start writing by the midpoint of your run; a system recorded from the primary evidence beats an exhaustive scan that never becomes a file.
|
Complete the check within your turn ceiling. Batch Reads, take `reference/document.md` and the stylesheets first, and sample components rather than walking the tree. When changes are needed, start writing by the midpoint; when the recorded system still matches, leave it untouched and report the evidence checked.
|
||||||
|
|
||||||
## Input Contract
|
## Input Contract
|
||||||
|
|
||||||
@@ -15,10 +15,10 @@ Expect: the project root; the artifact path(s); the direction contract text (THE
|
|||||||
|
|
||||||
1. Read `reference/document.md` in full; it is the operating spec for DESIGN.md's format, token schema, sidecar, and section order. Follow it exactly.
|
1. Read `reference/document.md` in full; it is the operating spec for DESIGN.md's format, token schema, sidecar, and section order. Follow it exactly.
|
||||||
2. Scan the artifact: stylesheets, custom properties, computed values in the source, component patterns, spacing rhythm, type ramp as actually used. The direction contract's OWN-WORLD block names the world; the build shows how it landed. Where they diverge, the build wins and the prose may note the divergence.
|
2. Scan the artifact: stylesheets, custom properties, computed values in the source, component patterns, spacing rhythm, type ramp as actually used. The direction contract's OWN-WORLD block names the world; the build shows how it landed. Where they diverge, the build wins and the prose may note the divergence.
|
||||||
3. Write DESIGN.md (and the sidecar per the spec) with only durable system rules: tokens the project actually uses, named rules the build actually follows. Skip one-off values; a token used once is not a system.
|
3. For a new world or approved system change, write DESIGN.md and its sidecar from durable, reused rules in the build. Ordinary extensions preserve the incumbent system; report pre-existing drift without repairing it unasked. Do not write merely to prove this pass ran.
|
||||||
4. Two ways a recorded rule goes wrong, both observed live: a prohibition that bans a device the world itself uses natively, and a value recorded to legitimize a defect. Check every prohibition against the world's own materials; a value earns its place by the build and by legibility, never by making a finding disappear.
|
4. Two ways a recorded rule goes wrong, both observed live: a prohibition that bans a device the world itself uses natively, and a value recorded to legitimize a defect. Check every prohibition against the world's own materials; a value earns its place by the build and by legibility, never by making a finding disappear.
|
||||||
5. Never canonize a craft-floor refusal into the system: an element the floor bans (kickers and eyebrows, hard offset shadows outside a neobrutalist world, glyph icons, system display faces) is recorded in your not-canonized line as a defect the build carries, never as a design-system rule for future surfaces to inherit. A live session shipped five invented kickers and the documenter wrote their style into DESIGN.md; that is how one violation becomes the house style.
|
5. Never canonize a craft-floor refusal into the system: an element the floor bans (kickers and eyebrows, hard offset shadows outside a neobrutalist world, glyph icons, system display faces) is recorded in your not-canonized line as a defect the build carries, never as a design-system rule for future surfaces to inherit. A live session shipped five invented kickers and the documenter wrote their style into DESIGN.md; that is how one violation becomes the house style.
|
||||||
|
|
||||||
## Output Contract
|
## Output Contract
|
||||||
|
|
||||||
Return: the file paths written, a five-line summary of the recorded system (palette strategy, type ramp shape, named rules), and one line naming anything in the build you deliberately did not canonize and why. No other prose.
|
Return: paths written, or “No changes” with the source and system files checked; a five-line system summary (palette, type ramp, named rules); and one line naming defects or drift not canonized or repaired, and why. No other prose.
|
||||||
@@ -205,6 +205,11 @@ t('items', { count }) // Handles complex plural rules
|
|||||||
- Optimistic updates with rollback
|
- Optimistic updates with rollback
|
||||||
- Conflict resolution
|
- Conflict resolution
|
||||||
|
|
||||||
|
**Interrupted gestures** (custom sliders, drag surfaces, scrollable control strips):
|
||||||
|
- A second finger or pointer lands mid-drag: the first drag keeps its pointer or ends cleanly, never jumps to the new one
|
||||||
|
- The browser cancels the gesture to scroll (`pointercancel`), capture is lost (`lostpointercapture`), the pointer is released outside the control, or the window loses focus (`blur`) mid-drag: clear the dragging state and release capture
|
||||||
|
- After each of these, the next tap or drag works without a reload
|
||||||
|
|
||||||
**Permission states**:
|
**Permission states**:
|
||||||
- No permission to view
|
- No permission to view
|
||||||
- No permission to edit
|
- No permission to edit
|
||||||
@@ -304,6 +309,7 @@ const throttledScroll = throttle(handleScroll, 100);
|
|||||||
- Unit tests for edge cases
|
- Unit tests for edge cases
|
||||||
- Integration tests for error scenarios
|
- Integration tests for error scenarios
|
||||||
- E2E tests for critical paths
|
- E2E tests for critical paths
|
||||||
|
- A behavioral regression for each confirmed gesture fix, when the project's test runner can drive input
|
||||||
- Visual regression tests
|
- Visual regression tests
|
||||||
- Accessibility tests (axe, WAVE)
|
- Accessibility tests (axe, WAVE)
|
||||||
|
|
||||||
@@ -330,7 +336,10 @@ Test thoroughly with edge cases:
|
|||||||
- **Network issues**: Disable internet, throttle connection
|
- **Network issues**: Disable internet, throttle connection
|
||||||
- **Large datasets**: Test with 1000+ items
|
- **Large datasets**: Test with 1000+ items
|
||||||
- **Concurrent actions**: Click submit 10 times rapidly
|
- **Concurrent actions**: Click submit 10 times rapidly
|
||||||
|
- **Interrupted gestures**: Add a second finger mid-drag, scroll across the control, release outside it, switch windows mid-drag; then drag again
|
||||||
- **Errors**: Force API errors, test all error states
|
- **Errors**: Force API errors, test all error states
|
||||||
- **Empty**: Remove all data, test empty states
|
- **Empty**: Remove all data, test empty states
|
||||||
|
|
||||||
|
For gestures, say what produced the evidence (emulated viewport, synthesized touch, which engine, physical device) and name what stayed untested.
|
||||||
|
|
||||||
When edge cases are covered, hand off to `/impeccable polish` for the final pass.
|
When edge cases are covered, hand off to `/impeccable polish` for the final pass.
|
||||||
|
|||||||
@@ -42,6 +42,8 @@ On every boot the project is scanned for HTML files under common page roots (`pu
|
|||||||
|
|
||||||
## CSP detection (first-time only)
|
## CSP detection (first-time only)
|
||||||
|
|
||||||
|
Keep all allowances below development-only, including manual middleware and meta-tag edits. Do not change a deployed production site's CSP to load the localhost helper; see [live.md](live.md) for production inspection alternatives.
|
||||||
|
|
||||||
If `config.cspChecked === true`, skip this whole section; the user was already asked once.
|
If `config.cspChecked === true`, skip this whole section; the user was already asked once.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ Interactive live variant mode: select elements in the browser, pick a design act
|
|||||||
|
|
||||||
A running dev server with HMR (Vite, Next.js, Bun, etc.), OR a static HTML file open in the browser. If the dev server's default port is busy, the app is very likely ALREADY running; probe the default URL before spawning a second server.
|
A running dev server with HMR (Vite, Next.js, Bun, etc.), OR a static HTML file open in the browser. If the dev server's default port is busy, the app is very likely ALREADY running; probe the default URL before spawning a second server.
|
||||||
|
|
||||||
|
Live editing requires a local checkout; injection into deployed production sites (including HTTPS) is unsupported. For production inspection, use `.agent/skills/impeccable/scripts/impeccable detect <url>` or the browser extension, not the live helper. Do not disable browser security or weaken production CSP to enable live mode.
|
||||||
|
|
||||||
## The contract (read once)
|
## The contract (read once)
|
||||||
|
|
||||||
Execute in order. No step skipped, no step reordered. Every tool output in live mode may carry an `_instructions` field: it is the authoritative next step for that exact situation, with real ids and paths substituted; when it conflicts with your recollection of this document, `_instructions` wins.
|
Execute in order. No step skipped, no step reordered. Every tool output in live mode may carry an `_instructions` field: it is the authoritative next step for that exact situation, with real ids and paths substituted; when it conflicts with your recollection of this document, `_instructions` wins.
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ A section, component, feature, or state inside an established surface inherits t
|
|||||||
|
|
||||||
## 2. Ask what will change the work
|
## 2. Ask what will change the work
|
||||||
|
|
||||||
Ask one round of two or three related questions through the structured question tool when available. Skip settled facts; a precise request may need only a compact confirmation.
|
Before implementation, get the user's answer through the structured question tool when available. Ask two or three related questions; a precise request needs only a compact confirmation. Skip settled facts, not the confirmation: DESIGN.md settles the visual world, not this surface's purpose or concept.
|
||||||
|
|
||||||
- **Persuade:** who must act, what they should believe, which real proof, content, or assets earn that belief.
|
- **Persuade:** who must act, what they should believe, which real proof, content, or assets earn that belief.
|
||||||
- **Operate:** the task, information, important states, frequency, constraints.
|
- **Operate:** the task, information, important states, frequency, constraints.
|
||||||
@@ -68,7 +68,7 @@ Calibration: AI-generated interfaces cluster around a few looks regardless of su
|
|||||||
|
|
||||||
## 5. Record the decision
|
## 5. Record the decision
|
||||||
|
|
||||||
Before code, record the chosen direction as a development-only contract under `## Direction contract` in the relevant surface brief. A direction contract is durable route or artifact strategy, so create or update the brief even when no other surface strategy needs persistence. Keep the contract to six short blocks and 150 words at most. THESIS: the one idea this surface owns and the category-default arrangement it refuses. OWN-WORLD: the palette and component language, specific enough to be recognizable with all content removed. STORY: what the visitor understands, believes, and does. FIRST VIEWPORT: the exact composition, what is where and at what scale, and where the primary action sits. FORM: the chosen form, its position on your ordered list, and the seed key the script printed. Close with one more line, FINISH: the run's exit condition, verbatim "unreviewed and undocumented is unfinished; this build ends with the finish review, the verdict, DESIGN.md, and every shipping raster carrying its provenance". The surface brief is the reminder later agents reload across edits and sessions: a page that looks complete with the FINISH line undischarged is not done, it is abandoned at the finish line. If a block reads like a mood, the direction is not decided yet; the finishing review audits the render against this contract.
|
Before code, record the chosen direction as a development-only contract under `## Direction contract` in the relevant surface brief. A direction contract is durable route or artifact strategy, so create or update the brief even when no other surface strategy needs persistence. Use six short blocks, roughly 150 words; do not spend tool calls counting words. THESIS: the one idea this surface owns and the category-default arrangement it refuses. OWN-WORLD: the palette and component language, specific enough to be recognizable with all content removed. STORY: what the visitor understands, believes, and does. FIRST VIEWPORT: the exact composition, what is where and at what scale, and where the primary action sits. FORM: the chosen form, its position on your ordered list, and the seed key the script printed. Close with one more line, FINISH: the run's exit condition, verbatim "unreviewed and undocumented is unfinished; this build ends with the finish review, the verdict, DESIGN.md, and every shipping raster carrying its provenance". The surface brief is the reminder later agents reload across edits and sessions: a page that looks complete with the FINISH line undischarged is not done, it is abandoned at the finish line. If a block reads like a mood, the direction is not decided yet; the finishing review audits the render against this contract.
|
||||||
|
|
||||||
Never copy the direction contract into implementation source or any browser-delivered artifact. This includes HTML or framework comments, hidden DOM, `<template>` elements, `data-*` attributes, rendered JSX or TSX output, serialized props or state, React Server Component payloads, client bundles, metadata or JSON-LD, accessibility-only text, and files served beside the artifact. A compiler or optimizer removing development metadata is not a safety boundary. Reviewers and documenters receive the contract from the surface brief.
|
Never copy the direction contract into implementation source or any browser-delivered artifact. This includes HTML or framework comments, hidden DOM, `<template>` elements, `data-*` attributes, rendered JSX or TSX output, serialized props or state, React Server Component payloads, client bundles, metadata or JSON-LD, accessibility-only text, and files served beside the artifact. A compiler or optimizer removing development metadata is not a safety boundary. Reviewers and documenters receive the contract from the surface brief.
|
||||||
|
|
||||||
@@ -104,7 +104,7 @@ Then, in order, each closed by `.agent/skills/impeccable/scripts/impeccable buil
|
|||||||
The comp-led path is a frontier-tier job: it asks the builder to hold a measured layout, place plates at their boxes, and act on numeric readings across a dozen attempts. Smaller or faster models produce a recognisable page and stall under the hero gate; if the model in hand is one of those, say so before the direction round and take the code-led path, or expect the run to end at the hero with its readings unmet.
|
The comp-led path is a frontier-tier job: it asks the builder to hold a measured layout, place plates at their boxes, and act on numeric readings across a dozen attempts. Smaller or faster models produce a recognisable page and stall under the hero gate; if the model in hand is one of those, say so before the direction round and take the code-led path, or expect the run to end at the hero with its readings unmet.
|
||||||
|
|
||||||
1. **spec.** Measure the comp: `impeccable comp-spec --comp <comp> --grid` writes a coordinate grid over the comp; open it, name every salient region by grid span in a regions file (text and control regions snap to the largest ink mass inside their span, so a headline named B1:E4 measures as the headline and not the column beside it; `snap: false` keeps the span, and an explicit `box` is taken as drawn) (kind `plate` / `image` / `texture` for anything painted: every illustration, photograph, figure, product object, and material texture; `text` / `control` / `chrome` for what code draws; every region carries a `note` saying what the comp shows there, which the plate prompt and the gate messages read), and run `impeccable comp-spec --comp <comp> --regions <file>`. The spec carries each region's box, sampled palette, and medium; `impeccable comp-spec --print` is the build's reference from here on. Type is measured, not guessed: `impeccable font-match --measure <text region>` reads the comp's cap height, width class, and weight off the pixels, and `impeccable font-match --rank <region> --text "..."` takes its candidates from a fingerprint index of the Google Fonts catalog (the nearest faces to the crop's shape) plus any names you pass with `--candidates`, renders them at that cap height with the region's words, and ranks them by fingerprint distance (its `USE` line is the CSS; its proof sheet shows the comp over the top three); with no browser resolvable it records the catalog's nearest face and says the size is estimated, which is still the choice to build on. Do not install a browser to rank, and never write a `chosen` face into the spec by hand: the gate accepts only what font-match wrote. The spec gate refuses to close until the lead text region is measured and ranked. A region note that describes painted material (a diagram, drawing, photograph, texture) under a code kind is refused at the spec: reclassify it as a plate, or reword the note if code really draws it. The script refuses a regions file that leaves comp ink unnamed (callouts, a parts table, a notes block): what is never named can never be missing, so everything the comp shows gets a region. It also refuses a `text` / `control` / `chrome` region larger than a quarter of the comp: that is a column, not an element, and a column scored as one region hides the plates, tables, and notes inside it. Name each element inside it (`container: true` only when it truly is one undivided element). Anything drawn is a plate: an inline SVG past an icon's budget (a diagram, notation, leader lines with arrows, a "quick approximation" of the artwork) is refused at the hero; icon-sized SVG (under 64px, a few paths) is fine, and a chart the page draws from data at runtime is a chart, not an illustration. Callout lines and arrows that annotate a drawing belong to that drawing's plate, with only their labels set as text. A crop of the comp is never a plate (the plates gate refuses a file that is a resample of the comp region: the comp's grain, its neighbours' edges, and its resolution would ship as the artwork); the crop is the reference the plate is generated from. A plate region's box has to hold its whole artwork with a margin: the spec measures the artwork's contact with the box edges and refuses a box that cuts through it (`bleed: true` only when the page really crops it there), because a plate placed with `object-fit: cover` on such a box shows the artwork minus the side the box lost. Anything not in the spec does not exist on the page: no borders, rules, containers, or chrome the comp does not show. Only three concessions exist: fonts (the closest obtainable face), icon glyphs (close enough, exact if the user chose an icon library; this covers the pictogram only, never a control's chrome, so a chevron, an arrow, a dropdown's border and fill, a button's shape are the comp's), and genuine defects in the comp such as spelling errors.
|
1. **spec.** Measure the comp: `impeccable comp-spec --comp <comp> --grid` writes a coordinate grid over the comp; open it, name every salient region by grid span in a regions file (text and control regions snap to the largest ink mass inside their span, so a headline named B1:E4 measures as the headline and not the column beside it; `snap: false` keeps the span, and an explicit `box` is taken as drawn) (kind `plate` / `image` / `texture` for anything painted: every illustration, photograph, figure, product object, and material texture; `text` / `control` / `chrome` for what code draws; every region carries a `note` saying what the comp shows there, which the plate prompt and the gate messages read), and run `impeccable comp-spec --comp <comp> --regions <file>`. The spec carries each region's box, sampled palette, and medium; `impeccable comp-spec --print` is the build's reference from here on. Type is measured, not guessed: `impeccable font-match --measure <text region>` reads the comp's cap height, width class, and weight off the pixels, and `impeccable font-match --rank <region> --text "..."` takes its candidates from a fingerprint index of the Google Fonts catalog (the nearest faces to the crop's shape) plus any names you pass with `--candidates`, renders them at that cap height with the region's words, and ranks them by fingerprint distance (its `USE` line is the CSS; its proof sheet shows the comp over the top three); with no browser resolvable it records the catalog's nearest face and says the size is estimated, which is still the choice to build on. Do not install a browser to rank, and never write a `chosen` face into the spec by hand: the gate accepts only what font-match wrote. The spec gate refuses to close until the lead text region is measured and ranked. A region note that describes painted material (a diagram, drawing, photograph, texture) under a code kind is refused at the spec: reclassify it as a plate, or reword the note if code really draws it. The script refuses a regions file that leaves comp ink unnamed (callouts, a parts table, a notes block): what is never named can never be missing, so everything the comp shows gets a region. It also refuses a `text` / `control` / `chrome` region larger than a quarter of the comp: that is a column, not an element, and a column scored as one region hides the plates, tables, and notes inside it. Name each element inside it (`container: true` only when it truly is one undivided element). Anything drawn is a plate: an inline SVG past an icon's budget (a diagram, notation, leader lines with arrows, a "quick approximation" of the artwork) is refused at the hero; icon-sized SVG (under 64px, a few paths) is fine, and a chart the page draws from data at runtime is a chart, not an illustration. Callout lines and arrows that annotate a drawing belong to that drawing's plate, with only their labels set as text. A crop of the comp is never a plate (the plates gate refuses a file that is a resample of the comp region: the comp's grain, its neighbours' edges, and its resolution would ship as the artwork); the crop is the reference the plate is generated from. A plate region's box has to hold its whole artwork with a margin: the spec measures the artwork's contact with the box edges and refuses a box that cuts through it (`bleed: true` only when the page really crops it there), because a plate placed with `object-fit: cover` on such a box shows the artwork minus the side the box lost. Anything not in the spec does not exist on the page: no borders, rules, containers, or chrome the comp does not show. Only three concessions exist: fonts (the closest obtainable face), icon glyphs (close enough, exact if the user chose an icon library; this covers the pictogram only, never a control's chrome, so a chevron, an arrow, a dropdown's border and fill, a button's shape are the comp's), and genuine defects in the comp such as spelling errors.
|
||||||
2. **plates.** Every raster region ships as a plate: an illustration, photo, or figure regenerated at asset resolution from its comp crop, UI text removed, at its `plate` path (ink on flat ground is generated on a chroma key and keyed to alpha, so it sits on the page's own ground rather than a second paper); a texture (paper, cloth, grain) is a clean patch of the comp region mirror-tiled to size, generated only when no clean patch exists. `impeccable generate-image --plate <id>` does one region end to end and scores it against the crop; a harness-native image tool takes the crop (`impeccable comp-spec --crop <id>`) as its input image and `impeccable comp-spec --plate-prompt <id>` as its prompt, then `impeccable embed-prompt`. With parallel subagents, spawn the shipped asset producer (`impeccable-asset-producer`; `impeccable_asset_producer` in codex; `/impeccable-asset-producer` in Cursor; on GitHub Copilot say "Use the impeccable-asset-producer agent") with the spec path and let it produce them all; without subagents, produce them here. A crop of the comp is a reference, never a shipping pixel. The gate checks every plate exists, is at least 1.5x the region's size, and reads as the region. Page code waits for this gate: a page written before its plates exist is a page that draws its material in CSS. A single-file deliverable changes nothing here: the plate is produced the same way and inlined as a data URI. `--force` exists for one case only, the user downgrading the comp's authority in words you quote in `--reason`; the script refuses every other reason.
|
2. **plates.** Every raster region ships as a plate: an illustration, photo, or figure regenerated at asset resolution from its comp crop, UI text removed, at its `plate` path (isolated ink, figures, or objects use native transparent PNG so they sit on the page's own ground; photos and textures stay opaque); a texture (paper, cloth, grain) is a clean patch of the comp region mirror-tiled to size, generated only when no clean patch exists. `impeccable comp-spec --crop <id>` writes the reference; save `impeccable comp-spec --plate-prompt <id> --background transparent` to a prompt file for a cutout, or use `--background opaque` otherwise. Prefer the harness-native image tool with that crop and prompt, then `impeccable embed-prompt <plate> --prompt-file <prompt.txt>`. The API fallback is `impeccable generate-image --ref <crop.png> --prompt-file <prompt.txt> --out <plate.png> --size <WxH> --quality high --background transparent` (use `--background opaque` for full-frame assets); create the output directory first. Verify actual alpha, white foregrounds, fine edges, and clear holes on light and dark grounds; do not chroma-key native output. The plates gate scores the assets against the comp; also inspect placement and scale visually. With parallel subagents, spawn the shipped asset producer (`impeccable-asset-producer`; `impeccable_asset_producer` in codex; `/impeccable-asset-producer` in Cursor; on GitHub Copilot say "Use the impeccable-asset-producer agent") with the spec path and let it produce them all; without subagents, produce them here. A crop of the comp is a reference, never a shipping pixel. The gate checks every plate exists, is at least 1.5x the region's size, and reads as the region. Page code waits for this gate: a page written before its plates exist is a page that draws its material in CSS. A single-file deliverable changes nothing here: the plate is produced the same way and inlined as a data URI. `--force` exists for one case only, the user downgrading the comp's authority in words you quote in `--reason`; the script refuses every other reason.
|
||||||
3. **hero.** `impeccable build-phase scaffold` first: it writes the measured layout as CSS custom properties (`.impeccable/build/scaffold/layout.css`: `--r-<id>-x/y/w/h` in % of the comp, plus cap height, font-size, family, and weight where measured) and a reference page (`hero-reference.html`) with every region at its box and every plate placed. Bind the numbers to your own semantic structure, an element per region; the reference is a check on positions, never the page, and overlapping boxes are overlapping boxes. Then build only the first viewport, at the comp's own dimensions, the comp's words copied verbatim (the user approved that comp with those words; rewording is a stated decision after the hero passes, never a silent one inside it), every text region sized from its measured cap height and set in its ranked face, plates first: place every plate at its spec box (`object-fit: cover`, an `<img>`, a background image, or an inlined data URI named for it) before any text or control, capture into `.impeccable/review/hero-repro.png`, run `impeccable build-phase record hero` once so you see the plate regions read as match before any text exists, then lay the semantic layer over the plates from the spec's palette and boxes and advance. The gate first refuses while any plate is unreferenced by the source, then runs `impeccable comp-diff`, writes `.impeccable/review/diff/hero/` (side-by-side, heatmap, one paired crop per region, `report.json`), and passes at 72% overall with no hard veto outstanding (a missing region, a contradicted plate or text block, an SVG illustration, a clipped plate, invented ink block at any score); above the bar, the numeric readings become advisories printed with the pass, and the polish pass before responsive is where they get fixed: the gate also reads each text region's cap height, line count, weight, ink colour, and position against the comp, each chrome strip's height off its rule, and the frame for ink where the comp is calm (a kicker, an extra nav item, a divider), and says each miss as a number ("cap height 78px in the build, 103px in the comp"); those numbers are the edit. When it fails, open the region crops it lists, in order, before editing: a region scored `missing` needs its material, `contradicted` needs its structure re-derived from the spec box, `drift` is where size and spacing edits belong; the gate refuses a third attempt that only nudges values on the same region. This is where the run's ambition is won or lost, and a retry here costs minutes where a rebuild verdict at the finish costs the run.
|
3. **hero.** `impeccable build-phase scaffold` first: it writes the measured layout as CSS custom properties (`.impeccable/build/scaffold/layout.css`: `--r-<id>-x/y/w/h` in % of the comp, plus cap height, font-size, family, and weight where measured) and a reference page (`hero-reference.html`) with every region at its box and every plate placed. Bind the numbers to your own semantic structure, an element per region; the reference is a check on positions, never the page, and overlapping boxes are overlapping boxes. Then build only the first viewport, at the comp's own dimensions, the comp's words copied verbatim (the user approved that comp with those words; rewording is a stated decision after the hero passes, never a silent one inside it), every text region sized from its measured cap height and set in its ranked face, plates first: place every plate at its spec box (`object-fit: cover`, an `<img>`, a background image, or an inlined data URI named for it) before any text or control, capture into `.impeccable/review/hero-repro.png`, run `impeccable build-phase record hero` once so you see the plate regions read as match before any text exists, then lay the semantic layer over the plates from the spec's palette and boxes and advance. The gate first refuses while any plate is unreferenced by the source, then runs `impeccable comp-diff`, writes `.impeccable/review/diff/hero/` (side-by-side, heatmap, one paired crop per region, `report.json`), and passes at 72% overall with no hard veto outstanding (a missing region, a contradicted plate or text block, an SVG illustration, a clipped plate, invented ink block at any score); above the bar, the numeric readings become advisories printed with the pass, and the polish pass before responsive is where they get fixed: the gate also reads each text region's cap height, line count, weight, ink colour, and position against the comp, each chrome strip's height off its rule, and the frame for ink where the comp is calm (a kicker, an extra nav item, a divider), and says each miss as a number ("cap height 78px in the build, 103px in the comp"); those numbers are the edit. When it fails, open the region crops it lists, in order, before editing: a region scored `missing` needs its material, `contradicted` needs its structure re-derived from the spec box, `drift` is where size and spacing edits belong; the gate refuses a third attempt that only nudges values on the same region. This is where the run's ambition is won or lost, and a retry here costs minutes where a rebuild verdict at the finish costs the run.
|
||||||
4. **sections.** Build the rest of the surface inside the spec's system: the same corner language, line weights, and palette, and nothing the comp never shows. Where the comp does not cover a region, it inherits the recorded system.
|
4. **sections.** Build the rest of the surface inside the spec's system: the same corner language, line weights, and palette, and nothing the comp never shows. Where the comp does not cover a region, it inherits the recorded system.
|
||||||
5. **motion.** The signature interaction, reveals, and motion, orchestrated once rather than scattered.
|
5. **motion.** The signature interaction, reveals, and motion, orchestrated once rather than scattered.
|
||||||
@@ -142,4 +142,4 @@ A rebuild and a fix round share one asset rule: a raster either round creates or
|
|||||||
|
|
||||||
Report the final verdict under the reviewer's own disposition word and at its actual scope. A verdict pass scores the listed fixes and nothing else: "the reviewer scored all three fixes resolved" is a claim it supports, "no material issues remain" is not. A table with open material findings is never announced as a pass, never softened, and never dressed as whole-surface approval when only a fix list was scored. When the user answers a ship with evidence against it, their own screenshot, a named mismatch with the comp, that evidence outranks every capture you made: put their material in the packet and spawn a fresh reviewer for a new full review. Patching inline and self-certifying is how a rejected page ships twice.
|
Report the final verdict under the reviewer's own disposition word and at its actual scope. A verdict pass scores the listed fixes and nothing else: "the reviewer scored all three fixes resolved" is a claim it supports, "no material issues remain" is not. A table with open material findings is never announced as a pass, never softened, and never dressed as whole-surface approval when only a fix list was scored. When the user answers a ship with evidence against it, their own screenshot, a named mismatch with the comp, that evidence outranks every capture you made: put their material in the packet and spawn a fresh reviewer for a new full review. Patching inline and self-certifying is how a rejected page ships twice.
|
||||||
|
|
||||||
Then spawn the shipped documenter, `impeccable-documenter` (`impeccable_documenter` in codex), with the project root, the artifact path, the direction contract, PRODUCT.md, the [document.md](document.md) reference path, and the boundary to write at; it records DESIGN.md and the sidecar from the built world, ground truth over intention; without subagents the pass runs from [degraded/documenter.md](degraded/documenter.md). The documenter runs after the last correction lands: when any fix round follows the documentation, re-run the documenter over the changed surface, because a DESIGN.md describing a layout that no longer exists turns defects into system guidance. A clean detector pass is not finished; finished is the contract kept, the comp honored, the review closed, and the system recorded.
|
After the last correction, spawn the shipped documenter, `impeccable-documenter` (`impeccable_documenter` in codex), with the project root, artifact path, direction contract, PRODUCT.md, [document.md](document.md), and write boundary. Without subagents, load [degraded/documenter.md](degraded/documenter.md) and [document.md](document.md) before writing. Verify the outcome: new worlds and approved system changes require token-bearing DESIGN.md **and** `.impeccable/design.json`, not prose alone. Ordinary extensions compare the finished build against the incumbent system, preserve its files, and report the evidence checked; report pre-existing drift without repairing it unasked. Recheck after later edits. Finish only when review and documentation are complete.
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ What the comp shows is measured, not remembered. new-work.md section 6 runs the
|
|||||||
|
|
||||||
## Plates and provenance
|
## Plates and provenance
|
||||||
|
|
||||||
Every raster region's plate is produced in the plates phase, before any page code, by the shipped asset producer or in the current thread (`impeccable generate-image --plate <id>`, or the harness image tool with the crop as input and the spec's plate prompt). Generation context is part of the asset: after generating any image with any tool, run `.agent/skills/impeccable/scripts/impeccable embed-prompt <image> --prompt "<prompt>"` with the exact string the tool received (`impeccable generate-image` does this itself), so the intent lives inside the file; `--read` recovers it, `--scan <dir>` lists rasters still missing one. The embedded prompt plus the region's row in the spec is the raster's **provenance**, and every raster the artifact references carries it; a sourced, stock, or pre-existing raster embeds its origin instead. A raster created or replaced later, in a fix batch or a reviewer's rebuild, is produced the same way; a raster a fix abandons is deleted in the same batch.
|
Every raster region's plate is produced in the plates phase, before any page code, by the shipped asset producer or in the current thread (use `impeccable comp-spec --crop <id>` and save `impeccable comp-spec --plate-prompt <id>` to a prompt file; pass the crop and prompt to the harness image tool, or use `impeccable generate-image --ref <crop.png> --prompt-file <prompt.txt> --out <plate.png> --size <WxH> --quality high`). For isolated cutouts, add `--background transparent` to both the plate-prompt and API generation commands; use native PNG alpha and preserve white paint and clear gaps. Use `--background opaque` for full-frame imagery. Create output directories first and inspect alpha on light and dark grounds. Generation context is part of the asset: after generating any image with any tool, run `.agent/skills/impeccable/scripts/impeccable embed-prompt <image> --prompt "<prompt>"` with the exact string the tool received (`impeccable generate-image` does this itself), so the intent lives inside the file; `--read` recovers it, `--scan <dir>` lists rasters still missing one. The embedded prompt plus the region's row in the spec is the raster's **provenance**, and every raster the artifact references carries it; a sourced, stock, or pre-existing raster embeds its origin instead. A raster created or replaced later, in a fix batch or a reviewer's rebuild, is produced the same way; a raster a fix abandons is deleted in the same batch.
|
||||||
|
|
||||||
Convert images with a converter `impeccable context` reported at boot (the IMAGE_TOOLS line); probe only when it reported none, at most once per session, never per image.
|
Convert images with a converter `impeccable context` reported at boot (the IMAGE_TOOLS line); probe only when it reported none, at most once per session, never per image.
|
||||||
|
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
0.1.3
|
0.1.5
|
||||||
|
|||||||
@@ -87,6 +87,11 @@ fi
|
|||||||
# Last resort: fetch this version's binary for the current platform from the
|
# Last resort: fetch this version's binary for the current platform from the
|
||||||
# public release channel into the user cache. Needs network; sandboxes without
|
# public release channel into the user cache. Needs network; sandboxes without
|
||||||
# egress preinstall the binary on PATH instead.
|
# egress preinstall the binary on PATH instead.
|
||||||
|
setup_help() {
|
||||||
|
echo "Engine $version setup needs network access and write permission to $cache_root/bin/$version." >&2
|
||||||
|
echo "Run this launcher ($0) with engine-probe in a terminal that has those permissions, then retry the original command." >&2
|
||||||
|
echo "Alternatively, set IMPECCABLE_HOME to a writable cache location, or IMPECCABLE_BIN to a preinstalled engine binary." >&2
|
||||||
|
}
|
||||||
fetch_url() {
|
fetch_url() {
|
||||||
if command -v curl >/dev/null 2>&1; then
|
if command -v curl >/dev/null 2>&1; then
|
||||||
curl -fsSL --retry 2 -o "$tmp" "$1" 2>/dev/null
|
curl -fsSL --retry 2 -o "$tmp" "$1" 2>/dev/null
|
||||||
@@ -119,7 +124,18 @@ if [ -n "$version" ] && [ "$os" != unknown ] && [ "$arch" != unknown ]; then
|
|||||||
[ "$os" = windows ] && asset="$asset.exe"
|
[ "$os" = windows ] && asset="$asset.exe"
|
||||||
url="$base/engine-v$version/$asset"
|
url="$base/engine-v$version/$asset"
|
||||||
tmp="$cache_root/bin/$version/.impeccable.part.$$"
|
tmp="$cache_root/bin/$version/.impeccable.part.$$"
|
||||||
mkdir -p "$cache_root/bin/$version" 2>/dev/null
|
if ! mkdir -p "$cache_root/bin/$version" 2>/dev/null; then
|
||||||
|
echo "impeccable: engine $version is not installed; cannot create cache directory: $cache_root/bin/$version" >&2
|
||||||
|
setup_help
|
||||||
|
exit 127
|
||||||
|
fi
|
||||||
|
# Check the actual staging file, not just directory existence: a cache from
|
||||||
|
# an earlier run can be readable but no longer writable inside a sandbox.
|
||||||
|
if ! (umask 077; : > "$tmp") 2>/dev/null; then
|
||||||
|
echo "impeccable: engine $version is not installed; cannot write to cache directory: $cache_root/bin/$version" >&2
|
||||||
|
setup_help
|
||||||
|
exit 127
|
||||||
|
fi
|
||||||
fetched=0
|
fetched=0
|
||||||
if fetch_url "$url"; then
|
if fetch_url "$url"; then
|
||||||
fetched=1
|
fetched=1
|
||||||
@@ -180,6 +196,9 @@ if [ -n "$version" ] && [ "$os" != unknown ] && [ "$arch" != unknown ]; then
|
|||||||
exec "$cached" "$@"
|
exec "$cached" "$@"
|
||||||
fi
|
fi
|
||||||
rm -f "$tmp" 2>/dev/null
|
rm -f "$tmp" 2>/dev/null
|
||||||
|
echo "impeccable: could not download engine $version from $url; check network access, the release URL, and curl or wget availability." >&2
|
||||||
|
setup_help
|
||||||
|
exit 127
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "impeccable: no engine binary for $os-$arch found (looked in $bin, $cached, PATH)." >&2
|
echo "impeccable: no engine binary for $os-$arch found (looked in $bin, $cached, PATH)." >&2
|
||||||
|
|||||||
@@ -68,18 +68,27 @@ rem another launcher's probe: fail fast and quiet instead.
|
|||||||
if defined IMPECCABLE_LAUNCHER_PROBE exit /b 127
|
if defined IMPECCABLE_LAUNCHER_PROBE exit /b 127
|
||||||
if not defined version goto fail
|
if not defined version goto fail
|
||||||
where curl.exe >nul 2>nul
|
where curl.exe >nul 2>nul
|
||||||
if errorlevel 1 goto fail
|
if errorlevel 1 goto curl_missing
|
||||||
if not defined IMPECCABLE_DOWNLOAD_BASE set "IMPECCABLE_DOWNLOAD_BASE=https://github.com/pbakaus/impeccable/releases/download"
|
if not defined IMPECCABLE_DOWNLOAD_BASE set "IMPECCABLE_DOWNLOAD_BASE=https://github.com/pbakaus/impeccable/releases/download"
|
||||||
if not exist "%IMPECCABLE_HOME%\bin\%version%" mkdir "%IMPECCABLE_HOME%\bin\%version%" >nul 2>nul
|
if exist "%IMPECCABLE_HOME%\bin\%version%\" goto cache_ready
|
||||||
|
mkdir "%IMPECCABLE_HOME%\bin\%version%" >nul 2>nul
|
||||||
|
if errorlevel 1 goto cache_directory_failed
|
||||||
|
:cache_ready
|
||||||
|
rem Check the staging file too: an existing directory may be read-only.
|
||||||
|
rem Redirection failures do not reliably update ERRORLEVEL in cmd.exe;
|
||||||
|
rem branch on the command's failure directly. Never treat a directory as a
|
||||||
|
rem staging file (later del cleanup would prompt to delete its contents).
|
||||||
|
if exist "%cached%.part\" goto cache_write_failed
|
||||||
|
(type nul >"%cached%.part") 2>nul || goto cache_write_failed
|
||||||
set "asset=impeccable-windows-%arch%.exe"
|
set "asset=impeccable-windows-%arch%.exe"
|
||||||
set "url=%IMPECCABLE_DOWNLOAD_BASE%/engine-v%version%/%asset%"
|
set "url=%IMPECCABLE_DOWNLOAD_BASE%/engine-v%version%/%asset%"
|
||||||
curl.exe -fsSL -o "%cached%.part" "%url%" >nul 2>nul
|
curl.exe -fsSL -o "%cached%.part" "%url%" >nul 2>nul
|
||||||
if not errorlevel 1 goto verify
|
if not errorlevel 1 goto verify
|
||||||
if not "%arch%"=="arm64" goto fail
|
if not "%arch%"=="arm64" goto download_failed
|
||||||
set "asset=impeccable-windows-x64.exe"
|
set "asset=impeccable-windows-x64.exe"
|
||||||
set "url=%IMPECCABLE_DOWNLOAD_BASE%/engine-v%version%/%asset%"
|
set "url=%IMPECCABLE_DOWNLOAD_BASE%/engine-v%version%/%asset%"
|
||||||
curl.exe -fsSL -o "%cached%.part" "%url%" >nul 2>nul
|
curl.exe -fsSL -o "%cached%.part" "%url%" >nul 2>nul
|
||||||
if errorlevel 1 goto fail
|
if errorlevel 1 goto download_failed
|
||||||
|
|
||||||
:verify
|
:verify
|
||||||
call :check_download
|
call :check_download
|
||||||
@@ -176,6 +185,28 @@ if not errorlevel 1 set "probe_ok=1"
|
|||||||
del "%probe_tmp%" >nul 2>nul
|
del "%probe_tmp%" >nul 2>nul
|
||||||
exit /b 0
|
exit /b 0
|
||||||
|
|
||||||
|
:cache_directory_failed
|
||||||
|
echo impeccable: engine %version% is not installed; cannot create cache directory: "%IMPECCABLE_HOME%\bin\%version%" 1>&2
|
||||||
|
goto setup_failed
|
||||||
|
|
||||||
|
:cache_write_failed
|
||||||
|
echo impeccable: engine %version% is not installed; cannot write to cache directory: "%IMPECCABLE_HOME%\bin\%version%" 1>&2
|
||||||
|
goto setup_failed
|
||||||
|
|
||||||
|
:curl_missing
|
||||||
|
echo impeccable: cannot download engine %version%; curl.exe is unavailable. 1>&2
|
||||||
|
goto setup_failed
|
||||||
|
|
||||||
|
:download_failed
|
||||||
|
del "%cached%.part" >nul 2>nul
|
||||||
|
echo impeccable: could not download engine %version% from %url%; check network access and the release URL. 1>&2
|
||||||
|
|
||||||
|
:setup_failed
|
||||||
|
echo Engine %version% setup needs network access and write permission to "%IMPECCABLE_HOME%\bin\%version%". 1>&2
|
||||||
|
echo Run this launcher ("%~f0") with engine-probe in a terminal that has those permissions, then retry the original command. 1>&2
|
||||||
|
echo Alternatively, set IMPECCABLE_HOME to a writable cache location, or IMPECCABLE_BIN to a preinstalled engine binary. 1>&2
|
||||||
|
exit /b 127
|
||||||
|
|
||||||
:fail
|
:fail
|
||||||
del "%cached%.part" >nul 2>nul
|
del "%cached%.part" >nul 2>nul
|
||||||
echo impeccable: no engine binary found (looked in %bin%, %cached%, PATH). 1>&2
|
echo impeccable: no engine binary found (looked in %bin%, %cached%, PATH). 1>&2
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
name: impeccable
|
name: impeccable
|
||||||
description: Use when the user wants to design, redesign, shape, critique, audit, polish, clarify, distill, harden, optimize, adapt, animate, colorize, extract, or otherwise improve a frontend interface. Covers websites, landing pages, dashboards, product UI, app shells, components, forms, settings, onboarding, and empty states. Handles UX review, visual hierarchy, information architecture, cognitive load, accessibility, performance, responsive behavior, theming, anti-patterns, typography, fonts, spacing, layout, alignment, color, motion, micro-interactions, UX copy, error states, edge cases, i18n, and reusable design systems or tokens. Also use for bland designs that need to become bolder or more delightful, loud designs that should become quieter, live browser iteration on UI elements, or ambitious visual effects that should feel technically extraordinary. Not for backend-only or non-UI tasks.
|
description: Use when the user wants to design, redesign, shape, critique, audit, polish, clarify, distill, harden, optimize, adapt, animate, colorize, extract, or otherwise improve a frontend interface. Covers websites, landing pages, dashboards, product UI, app shells, components, forms, settings, onboarding, and empty states. Handles UX review, visual hierarchy, information architecture, cognitive load, accessibility, performance, responsive behavior, theming, anti-patterns, typography, fonts, spacing, layout, alignment, color, motion, micro-interactions, UX copy, error states, edge cases, i18n, and reusable design systems or tokens. Also use for bland designs that need to become bolder or more delightful, loud designs that should become quieter, live browser iteration on UI elements, or ambitious visual effects that should feel technically extraordinary. Not for backend-only or non-UI tasks.
|
||||||
metadata:
|
metadata:
|
||||||
version: 4.2.2
|
version: 4.3.1
|
||||||
---
|
---
|
||||||
|
|
||||||
This skill gives you the tools and permission to create design that earns to be called out-of-distribution craft: Whereas before, your design work would have been safe, timid and measured, you now approach every design task as an award-winning design director with impeccable understanding for what makes exceptional design work: production-grade code, peak creativity, a clear POV, deep understanding of the needs of the client and users, and exceptional craft.
|
This skill gives you the tools and permission to create design that earns to be called out-of-distribution craft: Whereas before, your design work would have been safe, timid and measured, you now approach every design task as an award-winning design director with impeccable understanding for what makes exceptional design work: production-grade code, peak creativity, a clear POV, deep understanding of the needs of the client and users, and exceptional craft.
|
||||||
@@ -14,9 +14,11 @@ Core principles:
|
|||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
1. Run `<skill-base-dir>/scripts/impeccable context` once per session, where `<skill-base-dir>` is the directory that contains this SKILL.md (the skill folder, not a plugin root two levels above it); keep cwd at the user's project. That base directory resolves every `.agents/skills/impeccable/scripts/impeccable <verb>` command in this skill and its references, and `.agents/skills/impeccable/scripts` is the fallback only when the runtime reports no base directory. On a Windows shell without `sh`, call `.agents/skills/impeccable/scripts/impeccable.cmd` instead. The launcher runs a self-contained binary that ships next to it or is downloaded once on first run; no Node or other runtime is required. Pass a named source file or route as `--target <path>`. It loads PRODUCT.md, DESIGN.md, the matching surface brief, and native-platform guidance when applicable; follow its directives and do not rerun it. If the launcher is refused, missing, or fails, tell the user before editing that context loading did not run. Read existing **PRODUCT.md** and **DESIGN.md** without inventing missing context, then continue with steps 2–3.
|
1. Run `<skill-base-dir>/scripts/impeccable context` once per session, where `<skill-base-dir>` is the directory that contains this SKILL.md (the skill folder, not a plugin root two levels above it); keep cwd at the user's project. That base directory resolves every `.agents/skills/impeccable/scripts/impeccable <verb>` command in this skill and its references, and `.agents/skills/impeccable/scripts` is the fallback only when the runtime reports no base directory. On a Windows shell without `sh`, call `.agents/skills/impeccable/scripts/impeccable.cmd` instead. The launcher runs a self-contained binary that ships next to it or is downloaded once on first run; no Node or other runtime is required. Pass a named source file or route as `--target <path>`. It loads PRODUCT.md, DESIGN.md, the matching surface brief, and native-platform guidance when applicable; follow its directives and do not rerun it.
|
||||||
2. Load the request's playbook: its Commands-table reference for an explicit/implied sub-command, or [reference/new-work.md](reference/new-work.md) for a new surface or replacement visual world. Inspect target and incumbent visual truth before editing. When the app cannot run, start with committed visual-regression goldens or screenshot fixtures; verify target and freshness against current tokens, CSS, components, or assets, resolve conflicts, and compare theme/variant captures.
|
2. Load the request's playbook: its Commands-table reference for an explicit/implied sub-command, or [reference/new-work.md](reference/new-work.md) for a new surface or replacement visual world. Inspect target and incumbent visual truth before editing. When the app cannot run, start with committed visual-regression goldens or screenshot fixtures; verify target and freshness against current tokens, CSS, components, or assets, resolve conflicts, and compare theme/variant captures.
|
||||||
3. After analysis and direction are resolved, load [reference/craft-floor.md](reference/craft-floor.md) immediately before editing UI. It carries the quality floor, the absolute bans, and the reflexes no detector catches. Do not load it for planning-only work.
|
3. After resolving analysis and direction, read [reference/craft-floor.md](reference/craft-floor.md) immediately before any UI edit, including small refinements. It carries the quality floor, the absolute bans, and the reflexes no detector catches. Do not load it for planning-only work.
|
||||||
|
|
||||||
|
**Launcher unavailable:** On refusal or failure, send a separate message **before the next tool call**: “Context loading did not run; I’ll read the existing project context directly.” Then read existing PRODUCT.md and DESIGN.md without inventing missing context, follow applicable steps 2–3, and continue through permitted tools. This applies to planning and editing; launcher failure alone does not block either.
|
||||||
|
|
||||||
## How to design
|
## How to design
|
||||||
|
|
||||||
|
|||||||
@@ -28,9 +28,9 @@ Every region with `medium: raster` in the spec ships as a plate at its `plate` p
|
|||||||
Per region, in the spec's order:
|
Per region, in the spec's order:
|
||||||
|
|
||||||
1. `.agents/skills/impeccable/scripts/impeccable comp-spec --crop <id>` writes the reference crop under `.impeccable/build/crops/`.
|
1. `.agents/skills/impeccable/scripts/impeccable comp-spec --crop <id>` writes the reference crop under `.impeccable/build/crops/`.
|
||||||
2. Produce the plate. With the API fallback: `.agents/skills/impeccable/scripts/impeccable generate-image --plate <id> --quality high` does the whole step (crop as reference, the spec's plate prompt, output size chosen from the region's aspect, the file written to its plate path, prompt embedded, and the plate scored against the crop). With a harness-native image tool: use the crop as the input image and `.agents/skills/impeccable/scripts/impeccable comp-spec --plate-prompt <id>` as the prompt, write the result to the plate path, then run `.agents/skills/impeccable/scripts/impeccable embed-prompt <plate> --prompt "<the exact prompt>"`.
|
2. Choose the background from the approved region: an isolated figure, object, or line drawing on the page ground is a **transparent cutout**; a photograph, full-frame illustration, or texture stays **opaque**. Save `.agents/skills/impeccable/scripts/impeccable comp-spec --plate-prompt <id> --background transparent` to a UTF-8 prompt file for a cutout; use `--background opaque` otherwise. The transparent prompt preserves reference placement and clear margins, white paint, fine edges, and interior holes.
|
||||||
3. Read the score line. `PLATE-SCORE` under 50%, or a `PLATE-WARN`, means the plate does not read as the region: open the plate beside the crop, name what drifted (subject, framing, palette, style), tighten the prompt with that, and regenerate once. Two misses on one region: keep the better plate, mark it `needs_parent_review`, and say why in one line.
|
3. Produce the plate at its exact spec `plate` path. Create the output directory first and choose a supported output size matching the region's aspect, at least 1.5x its pixel dimensions. Prefer the harness-native image tool with the crop as input and the saved prompt; request a transparent PNG for cutouts, then run `.agents/skills/impeccable/scripts/impeccable embed-prompt <plate> --prompt-file <prompt.txt>` (if you refine the prompt, save and embed the exact text sent). With the API fallback, run `.agents/skills/impeccable/scripts/impeccable generate-image --ref <crop.png> --prompt-file <prompt.txt> --out <plate.png> --size <WxH> --quality high --background transparent` for a cutout, or `--background opaque` otherwise. The API fallback embeds the prompt and records the background in the sidecar. The output must be PNG; the fallback requests native alpha and performs no chroma-keying.
|
||||||
4. Transparent cutouts (a figure or object on the page ground): generate on a flat chroma color absent from the subject and key it to alpha before writing the PNG; never ship the keyed background.
|
4. Open the plate beside the crop and compare subject, placement, scale, palette, and style. For cutouts, verify a real alpha channel and inspect composites on light and dark grounds: white paint must stay solid, interior holes must clear, and fine edges must avoid halos. Inspect glass and soft shadows carefully; partial alpha alone does not ensure convincing translucency. Never chroma-key native transparent output or flatten it before saving. If a native tool returns opaque pixels or a painted checkerboard, retry with the API fallback when available; otherwise report the transparency blocker. On a visual miss, tighten the prompt and regenerate once. Two misses on one region: keep the better plate, mark it `needs_parent_review`, and name the drift. The parent runs the plates gate after all assets exist; report `unscored` until a gate score is available.
|
||||||
|
|
||||||
Codex: the imagegen skill's built-in `image_gen` path is the native tool here; prefer it for generation and editing, with the crop as the input image.
|
Codex: the imagegen skill's built-in `image_gen` path is the native tool here; prefer it for generation and editing, with the crop as the input image.
|
||||||
|
|
||||||
@@ -38,5 +38,5 @@ Do not redesign. Do not add objects, restyle, or reinterpret; the comp was appro
|
|||||||
|
|
||||||
## Output Contract
|
## Output Contract
|
||||||
|
|
||||||
Return one line per raster region: `<id> <plate path> <WxH> <score>% <accepted|needs_parent_review|blocked> <one-line note or ->`. Then `blockers` (missing spec, missing comp, no image capability, exhausted key) and `assumptions`, each global and minimal. Nothing else: no summary, no praise, no implementation advice. The parent runs `impeccable build-phase advance` to verify the plates against the same spec; your line and its line must agree.
|
Return one line per raster region: `<id> <plate path> <WxH> <score%|unscored> <accepted|needs_parent_review|blocked> <one-line note or ->`. Then `blockers` (missing spec, missing comp, no image capability, exhausted key) and `assumptions`, each global and minimal. Nothing else: no summary, no praise, no implementation advice. The parent runs `impeccable build-phase advance` to verify the plates against the same spec; a visual acceptance does not override a failing gate.
|
||||||
'''
|
'''
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ developer_instructions = '''
|
|||||||
|
|
||||||
You record a project's design system after the build is done. Ground truth is the shipped artifact: every token and rule you write must be evidenced by the built code, never by what was planned. Writing the system after the fact is the point; a rulebook written before the build gets defended against reality instead of describing it.
|
You record a project's design system after the build is done. Ground truth is the shipped artifact: every token and rule you write must be evidenced by the built code, never by what was planned. Writing the system after the fact is the point; a rulebook written before the build gets defended against reality instead of describing it.
|
||||||
|
|
||||||
You run under a hard turn ceiling that ends the run without warning, and a run that ends before DESIGN.md is written has recorded nothing. Batch several Reads into each turn, take `reference/document.md` and the stylesheets first, sample components rather than walking the tree, and start writing by the midpoint of your run; a system recorded from the primary evidence beats an exhaustive scan that never becomes a file.
|
Complete the check within your turn ceiling. Batch Reads, take `reference/document.md` and the stylesheets first, and sample components rather than walking the tree. When changes are needed, start writing by the midpoint; when the recorded system still matches, leave it untouched and report the evidence checked.
|
||||||
|
|
||||||
## Input Contract
|
## Input Contract
|
||||||
|
|
||||||
@@ -17,11 +17,11 @@ Expect: the project root; the artifact path(s); the direction contract text (THE
|
|||||||
|
|
||||||
1. Read `reference/document.md` in full; it is the operating spec for DESIGN.md's format, token schema, sidecar, and section order. Follow it exactly.
|
1. Read `reference/document.md` in full; it is the operating spec for DESIGN.md's format, token schema, sidecar, and section order. Follow it exactly.
|
||||||
2. Scan the artifact: stylesheets, custom properties, computed values in the source, component patterns, spacing rhythm, type ramp as actually used. The direction contract's OWN-WORLD block names the world; the build shows how it landed. Where they diverge, the build wins and the prose may note the divergence.
|
2. Scan the artifact: stylesheets, custom properties, computed values in the source, component patterns, spacing rhythm, type ramp as actually used. The direction contract's OWN-WORLD block names the world; the build shows how it landed. Where they diverge, the build wins and the prose may note the divergence.
|
||||||
3. Write DESIGN.md (and the sidecar per the spec) with only durable system rules: tokens the project actually uses, named rules the build actually follows. Skip one-off values; a token used once is not a system.
|
3. For a new world or approved system change, write DESIGN.md and its sidecar from durable, reused rules in the build. Ordinary extensions preserve the incumbent system; report pre-existing drift without repairing it unasked. Do not write merely to prove this pass ran.
|
||||||
4. Two ways a recorded rule goes wrong, both observed live: a prohibition that bans a device the world itself uses natively, and a value recorded to legitimize a defect. Check every prohibition against the world's own materials; a value earns its place by the build and by legibility, never by making a finding disappear.
|
4. Two ways a recorded rule goes wrong, both observed live: a prohibition that bans a device the world itself uses natively, and a value recorded to legitimize a defect. Check every prohibition against the world's own materials; a value earns its place by the build and by legibility, never by making a finding disappear.
|
||||||
5. Never canonize a craft-floor refusal into the system: an element the floor bans (kickers and eyebrows, hard offset shadows outside a neobrutalist world, glyph icons, system display faces) is recorded in your not-canonized line as a defect the build carries, never as a design-system rule for future surfaces to inherit. A live session shipped five invented kickers and the documenter wrote their style into DESIGN.md; that is how one violation becomes the house style.
|
5. Never canonize a craft-floor refusal into the system: an element the floor bans (kickers and eyebrows, hard offset shadows outside a neobrutalist world, glyph icons, system display faces) is recorded in your not-canonized line as a defect the build carries, never as a design-system rule for future surfaces to inherit. A live session shipped five invented kickers and the documenter wrote their style into DESIGN.md; that is how one violation becomes the house style.
|
||||||
|
|
||||||
## Output Contract
|
## Output Contract
|
||||||
|
|
||||||
Return: the file paths written, a five-line summary of the recorded system (palette strategy, type ramp shape, named rules), and one line naming anything in the build you deliberately did not canonize and why. No other prose.
|
Return: paths written, or “No changes” with the source and system files checked; a five-line system summary (palette, type ramp, named rules); and one line naming defects or drift not canonized or repaired, and why. No other prose.
|
||||||
'''
|
'''
|
||||||
|
|||||||
@@ -188,6 +188,12 @@ Test thoroughly across contexts:
|
|||||||
- **Edge cases**: Very small screens (320px), very large screens (4K)
|
- **Edge cases**: Very small screens (320px), very large screens (4K)
|
||||||
- **Slow connections**: Test on throttled network
|
- **Slow connections**: Test on throttled network
|
||||||
|
|
||||||
|
**Custom controls** (sliders, drag surfaces, scrollable control strips): a before/after slider can pass every width check above and still refuse to drag on iOS, so exercise each one in scope in the same batched round as the checks above:
|
||||||
|
|
||||||
|
- **Primary gesture**: Tap it and confirm it responds as designed, then drag it with the target input method; the drag must complete, not just start
|
||||||
|
- **Scroll across it**: A swipe along the page's scroll axis across the control scrolls the page or container without activating it; a drag that starts on the control along its axis moves the control, not the page. Neither failure throws an error, so try both
|
||||||
|
- **Evidence**: Say what produced the evidence: an emulated viewport, synthesized touch input through a browser tool, which engine ran it (Chromium is not Safari), or a physical device. Screenshots and resized viewports verify layout, never a gesture. Name what stayed untested and move on; unreachable hardware is a reported gap, not a blocker
|
||||||
|
|
||||||
When the adaptation feels native to each context, hand off to `$impeccable polish` for the final pass.
|
When the adaptation feels native to each context, hand off to `$impeccable polish` for the final pass.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -48,11 +48,12 @@ Run comprehensive checks across 5 dimensions. Score each dimension 0-4 using the
|
|||||||
**Check for**:
|
**Check for**:
|
||||||
- **Fixed widths**: Hard-coded widths that break on mobile
|
- **Fixed widths**: Hard-coded widths that break on mobile
|
||||||
- **Touch targets**: Interactive elements < 44x44px
|
- **Touch targets**: Interactive elements < 44x44px
|
||||||
|
- **Broken touch interaction**: Custom sliders, drag surfaces, and scrollable control strips whose primary gesture fails under touch, that swallow page scroll or lose the drag to it, or that stay stuck after an interrupted gesture. Code tells: mouse-only handlers, no `touch-action` on a pointer-event drag surface, drag state that nothing clears on cancel, lost capture, or blur. Exercise the gesture when a browser tool can synthesize touch (a rendered viewport proves layout, not the gesture), then say what produced the evidence (emulated viewport, synthesized touch, which engine, physical device) and what stayed untested
|
||||||
- **Horizontal scroll**: Content overflow on narrow viewports
|
- **Horizontal scroll**: Content overflow on narrow viewports
|
||||||
- **Text scaling**: Layouts that break when text size increases
|
- **Text scaling**: Layouts that break when text size increases
|
||||||
- **Missing breakpoints**: No mobile/tablet variants
|
- **Missing breakpoints**: No mobile/tablet variants
|
||||||
|
|
||||||
**Score 0-4**: 0=Desktop-only (breaks on mobile), 1=Major issues (some breakpoints, many failures), 2=Partial (works on mobile, rough edges), 3=Good (responsive, minor touch target or overflow issues), 4=Excellent (fluid, all viewports, proper touch targets)
|
**Score 0-4**: 0=Desktop-only (breaks on mobile), 1=Major issues (some breakpoints, many failures), 2=Partial (works on mobile, rough edges), 3=Good (responsive, minor touch target or overflow issues), 4=Excellent (fluid, all viewports, proper touch targets, gestures work under touch)
|
||||||
|
|
||||||
### 5. Implementation Integrity (CRITICAL)
|
### 5. Implementation Integrity (CRITICAL)
|
||||||
|
|
||||||
|
|||||||
@@ -26,9 +26,9 @@ Every region with `medium: raster` in the spec ships as a plate at its `plate` p
|
|||||||
Per region, in the spec's order:
|
Per region, in the spec's order:
|
||||||
|
|
||||||
1. `.agents/skills/impeccable/scripts/impeccable comp-spec --crop <id>` writes the reference crop under `.impeccable/build/crops/`.
|
1. `.agents/skills/impeccable/scripts/impeccable comp-spec --crop <id>` writes the reference crop under `.impeccable/build/crops/`.
|
||||||
2. Produce the plate. With the API fallback: `.agents/skills/impeccable/scripts/impeccable generate-image --plate <id> --quality high` does the whole step (crop as reference, the spec's plate prompt, output size chosen from the region's aspect, the file written to its plate path, prompt embedded, and the plate scored against the crop). With a harness-native image tool: use the crop as the input image and `.agents/skills/impeccable/scripts/impeccable comp-spec --plate-prompt <id>` as the prompt, write the result to the plate path, then run `.agents/skills/impeccable/scripts/impeccable embed-prompt <plate> --prompt "<the exact prompt>"`.
|
2. Choose the background from the approved region: an isolated figure, object, or line drawing on the page ground is a **transparent cutout**; a photograph, full-frame illustration, or texture stays **opaque**. Save `.agents/skills/impeccable/scripts/impeccable comp-spec --plate-prompt <id> --background transparent` to a UTF-8 prompt file for a cutout; use `--background opaque` otherwise. The transparent prompt preserves reference placement and clear margins, white paint, fine edges, and interior holes.
|
||||||
3. Read the score line. `PLATE-SCORE` under 50%, or a `PLATE-WARN`, means the plate does not read as the region: open the plate beside the crop, name what drifted (subject, framing, palette, style), tighten the prompt with that, and regenerate once. Two misses on one region: keep the better plate, mark it `needs_parent_review`, and say why in one line.
|
3. Produce the plate at its exact spec `plate` path. Create the output directory first and choose a supported output size matching the region's aspect, at least 1.5x its pixel dimensions. Prefer the harness-native image tool with the crop as input and the saved prompt; request a transparent PNG for cutouts, then run `.agents/skills/impeccable/scripts/impeccable embed-prompt <plate> --prompt-file <prompt.txt>` (if you refine the prompt, save and embed the exact text sent). With the API fallback, run `.agents/skills/impeccable/scripts/impeccable generate-image --ref <crop.png> --prompt-file <prompt.txt> --out <plate.png> --size <WxH> --quality high --background transparent` for a cutout, or `--background opaque` otherwise. The API fallback embeds the prompt and records the background in the sidecar. The output must be PNG; the fallback requests native alpha and performs no chroma-keying.
|
||||||
4. Transparent cutouts (a figure or object on the page ground): generate on a flat chroma color absent from the subject and key it to alpha before writing the PNG; never ship the keyed background.
|
4. Open the plate beside the crop and compare subject, placement, scale, palette, and style. For cutouts, verify a real alpha channel and inspect composites on light and dark grounds: white paint must stay solid, interior holes must clear, and fine edges must avoid halos. Inspect glass and soft shadows carefully; partial alpha alone does not ensure convincing translucency. Never chroma-key native transparent output or flatten it before saving. If a native tool returns opaque pixels or a painted checkerboard, retry with the API fallback when available; otherwise report the transparency blocker. On a visual miss, tighten the prompt and regenerate once. Two misses on one region: keep the better plate, mark it `needs_parent_review`, and name the drift. The parent runs the plates gate after all assets exist; report `unscored` until a gate score is available.
|
||||||
|
|
||||||
Codex: the imagegen skill's built-in `image_gen` path is the native tool here; prefer it for generation and editing, with the crop as the input image.
|
Codex: the imagegen skill's built-in `image_gen` path is the native tool here; prefer it for generation and editing, with the crop as the input image.
|
||||||
|
|
||||||
@@ -36,4 +36,4 @@ Do not redesign. Do not add objects, restyle, or reinterpret; the comp was appro
|
|||||||
|
|
||||||
## Output Contract
|
## Output Contract
|
||||||
|
|
||||||
Return one line per raster region: `<id> <plate path> <WxH> <score>% <accepted|needs_parent_review|blocked> <one-line note or ->`. Then `blockers` (missing spec, missing comp, no image capability, exhausted key) and `assumptions`, each global and minimal. Nothing else: no summary, no praise, no implementation advice. The parent runs `impeccable build-phase advance` to verify the plates against the same spec; your line and its line must agree.
|
Return one line per raster region: `<id> <plate path> <WxH> <score%|unscored> <accepted|needs_parent_review|blocked> <one-line note or ->`. Then `blockers` (missing spec, missing comp, no image capability, exhausted key) and `assumptions`, each global and minimal. Nothing else: no summary, no praise, no implementation advice. The parent runs `impeccable build-phase advance` to verify the plates against the same spec; a visual acceptance does not override a failing gate.
|
||||||
@@ -5,7 +5,7 @@ This harness has no subagent capability, so you are running this role inline. St
|
|||||||
|
|
||||||
You record a project's design system after the build is done. Ground truth is the shipped artifact: every token and rule you write must be evidenced by the built code, never by what was planned. Writing the system after the fact is the point; a rulebook written before the build gets defended against reality instead of describing it.
|
You record a project's design system after the build is done. Ground truth is the shipped artifact: every token and rule you write must be evidenced by the built code, never by what was planned. Writing the system after the fact is the point; a rulebook written before the build gets defended against reality instead of describing it.
|
||||||
|
|
||||||
You run under a hard turn ceiling that ends the run without warning, and a run that ends before DESIGN.md is written has recorded nothing. Batch several Reads into each turn, take `reference/document.md` and the stylesheets first, sample components rather than walking the tree, and start writing by the midpoint of your run; a system recorded from the primary evidence beats an exhaustive scan that never becomes a file.
|
Complete the check within your turn ceiling. Batch Reads, take `reference/document.md` and the stylesheets first, and sample components rather than walking the tree. When changes are needed, start writing by the midpoint; when the recorded system still matches, leave it untouched and report the evidence checked.
|
||||||
|
|
||||||
## Input Contract
|
## Input Contract
|
||||||
|
|
||||||
@@ -15,10 +15,10 @@ Expect: the project root; the artifact path(s); the direction contract text (THE
|
|||||||
|
|
||||||
1. Read `reference/document.md` in full; it is the operating spec for DESIGN.md's format, token schema, sidecar, and section order. Follow it exactly.
|
1. Read `reference/document.md` in full; it is the operating spec for DESIGN.md's format, token schema, sidecar, and section order. Follow it exactly.
|
||||||
2. Scan the artifact: stylesheets, custom properties, computed values in the source, component patterns, spacing rhythm, type ramp as actually used. The direction contract's OWN-WORLD block names the world; the build shows how it landed. Where they diverge, the build wins and the prose may note the divergence.
|
2. Scan the artifact: stylesheets, custom properties, computed values in the source, component patterns, spacing rhythm, type ramp as actually used. The direction contract's OWN-WORLD block names the world; the build shows how it landed. Where they diverge, the build wins and the prose may note the divergence.
|
||||||
3. Write DESIGN.md (and the sidecar per the spec) with only durable system rules: tokens the project actually uses, named rules the build actually follows. Skip one-off values; a token used once is not a system.
|
3. For a new world or approved system change, write DESIGN.md and its sidecar from durable, reused rules in the build. Ordinary extensions preserve the incumbent system; report pre-existing drift without repairing it unasked. Do not write merely to prove this pass ran.
|
||||||
4. Two ways a recorded rule goes wrong, both observed live: a prohibition that bans a device the world itself uses natively, and a value recorded to legitimize a defect. Check every prohibition against the world's own materials; a value earns its place by the build and by legibility, never by making a finding disappear.
|
4. Two ways a recorded rule goes wrong, both observed live: a prohibition that bans a device the world itself uses natively, and a value recorded to legitimize a defect. Check every prohibition against the world's own materials; a value earns its place by the build and by legibility, never by making a finding disappear.
|
||||||
5. Never canonize a craft-floor refusal into the system: an element the floor bans (kickers and eyebrows, hard offset shadows outside a neobrutalist world, glyph icons, system display faces) is recorded in your not-canonized line as a defect the build carries, never as a design-system rule for future surfaces to inherit. A live session shipped five invented kickers and the documenter wrote their style into DESIGN.md; that is how one violation becomes the house style.
|
5. Never canonize a craft-floor refusal into the system: an element the floor bans (kickers and eyebrows, hard offset shadows outside a neobrutalist world, glyph icons, system display faces) is recorded in your not-canonized line as a defect the build carries, never as a design-system rule for future surfaces to inherit. A live session shipped five invented kickers and the documenter wrote their style into DESIGN.md; that is how one violation becomes the house style.
|
||||||
|
|
||||||
## Output Contract
|
## Output Contract
|
||||||
|
|
||||||
Return: the file paths written, a five-line summary of the recorded system (palette strategy, type ramp shape, named rules), and one line naming anything in the build you deliberately did not canonize and why. No other prose.
|
Return: paths written, or “No changes” with the source and system files checked; a five-line system summary (palette, type ramp, named rules); and one line naming defects or drift not canonized or repaired, and why. No other prose.
|
||||||
@@ -205,6 +205,11 @@ t('items', { count }) // Handles complex plural rules
|
|||||||
- Optimistic updates with rollback
|
- Optimistic updates with rollback
|
||||||
- Conflict resolution
|
- Conflict resolution
|
||||||
|
|
||||||
|
**Interrupted gestures** (custom sliders, drag surfaces, scrollable control strips):
|
||||||
|
- A second finger or pointer lands mid-drag: the first drag keeps its pointer or ends cleanly, never jumps to the new one
|
||||||
|
- The browser cancels the gesture to scroll (`pointercancel`), capture is lost (`lostpointercapture`), the pointer is released outside the control, or the window loses focus (`blur`) mid-drag: clear the dragging state and release capture
|
||||||
|
- After each of these, the next tap or drag works without a reload
|
||||||
|
|
||||||
**Permission states**:
|
**Permission states**:
|
||||||
- No permission to view
|
- No permission to view
|
||||||
- No permission to edit
|
- No permission to edit
|
||||||
@@ -304,6 +309,7 @@ const throttledScroll = throttle(handleScroll, 100);
|
|||||||
- Unit tests for edge cases
|
- Unit tests for edge cases
|
||||||
- Integration tests for error scenarios
|
- Integration tests for error scenarios
|
||||||
- E2E tests for critical paths
|
- E2E tests for critical paths
|
||||||
|
- A behavioral regression for each confirmed gesture fix, when the project's test runner can drive input
|
||||||
- Visual regression tests
|
- Visual regression tests
|
||||||
- Accessibility tests (axe, WAVE)
|
- Accessibility tests (axe, WAVE)
|
||||||
|
|
||||||
@@ -330,7 +336,10 @@ Test thoroughly with edge cases:
|
|||||||
- **Network issues**: Disable internet, throttle connection
|
- **Network issues**: Disable internet, throttle connection
|
||||||
- **Large datasets**: Test with 1000+ items
|
- **Large datasets**: Test with 1000+ items
|
||||||
- **Concurrent actions**: Click submit 10 times rapidly
|
- **Concurrent actions**: Click submit 10 times rapidly
|
||||||
|
- **Interrupted gestures**: Add a second finger mid-drag, scroll across the control, release outside it, switch windows mid-drag; then drag again
|
||||||
- **Errors**: Force API errors, test all error states
|
- **Errors**: Force API errors, test all error states
|
||||||
- **Empty**: Remove all data, test empty states
|
- **Empty**: Remove all data, test empty states
|
||||||
|
|
||||||
|
For gestures, say what produced the evidence (emulated viewport, synthesized touch, which engine, physical device) and name what stayed untested.
|
||||||
|
|
||||||
When edge cases are covered, hand off to `$impeccable polish` for the final pass.
|
When edge cases are covered, hand off to `$impeccable polish` for the final pass.
|
||||||
|
|||||||
@@ -42,6 +42,8 @@ On every boot the project is scanned for HTML files under common page roots (`pu
|
|||||||
|
|
||||||
## CSP detection (first-time only)
|
## CSP detection (first-time only)
|
||||||
|
|
||||||
|
Keep all allowances below development-only, including manual middleware and meta-tag edits. Do not change a deployed production site's CSP to load the localhost helper; see [live.md](live.md) for production inspection alternatives.
|
||||||
|
|
||||||
If `config.cspChecked === true`, skip this whole section; the user was already asked once.
|
If `config.cspChecked === true`, skip this whole section; the user was already asked once.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ Interactive live variant mode: select elements in the browser, pick a design act
|
|||||||
|
|
||||||
A running dev server with HMR (Vite, Next.js, Bun, etc.), OR a static HTML file open in the browser. If the dev server's default port is busy, the app is very likely ALREADY running; probe the default URL before spawning a second server.
|
A running dev server with HMR (Vite, Next.js, Bun, etc.), OR a static HTML file open in the browser. If the dev server's default port is busy, the app is very likely ALREADY running; probe the default URL before spawning a second server.
|
||||||
|
|
||||||
|
Live editing requires a local checkout; injection into deployed production sites (including HTTPS) is unsupported. For production inspection, use `.agents/skills/impeccable/scripts/impeccable detect <url>` or the browser extension, not the live helper. Do not disable browser security or weaken production CSP to enable live mode.
|
||||||
|
|
||||||
Codex: run live helper commands, the app dev server, and any dependency-installing setup with `sandbox_permissions: "require_escalated"` from the start; live mode depends on localhost and package-manager network access that the sandbox blocks.
|
Codex: run live helper commands, the app dev server, and any dependency-installing setup with `sandbox_permissions: "require_escalated"` from the start; live mode depends on localhost and package-manager network access that the sandbox blocks.
|
||||||
|
|
||||||
## The contract (read once)
|
## The contract (read once)
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ A section, component, feature, or state inside an established surface inherits t
|
|||||||
|
|
||||||
## 2. Ask what will change the work
|
## 2. Ask what will change the work
|
||||||
|
|
||||||
Ask one round of two or three related questions through the structured question tool when available. Skip settled facts; a precise request may need only a compact confirmation.
|
Before implementation, get the user's answer through the structured question tool when available. Ask two or three related questions; a precise request needs only a compact confirmation. Skip settled facts, not the confirmation: DESIGN.md settles the visual world, not this surface's purpose or concept.
|
||||||
|
|
||||||
- **Persuade:** who must act, what they should believe, which real proof, content, or assets earn that belief.
|
- **Persuade:** who must act, what they should believe, which real proof, content, or assets earn that belief.
|
||||||
- **Operate:** the task, information, important states, frequency, constraints.
|
- **Operate:** the task, information, important states, frequency, constraints.
|
||||||
@@ -68,7 +68,7 @@ Calibration: AI-generated interfaces cluster around a few looks regardless of su
|
|||||||
|
|
||||||
## 5. Record the decision
|
## 5. Record the decision
|
||||||
|
|
||||||
Before code, record the chosen direction as a development-only contract under `## Direction contract` in the relevant surface brief. A direction contract is durable route or artifact strategy, so create or update the brief even when no other surface strategy needs persistence. Keep the contract to six short blocks and 150 words at most. THESIS: the one idea this surface owns and the category-default arrangement it refuses. OWN-WORLD: the palette and component language, specific enough to be recognizable with all content removed. STORY: what the visitor understands, believes, and does. FIRST VIEWPORT: the exact composition, what is where and at what scale, and where the primary action sits. FORM: the chosen form, its position on your ordered list, and the seed key the script printed. Close with one more line, FINISH: the run's exit condition, verbatim "unreviewed and undocumented is unfinished; this build ends with the finish review, the verdict, DESIGN.md, and every shipping raster carrying its provenance". The surface brief is the reminder later agents reload across edits and sessions: a page that looks complete with the FINISH line undischarged is not done, it is abandoned at the finish line. If a block reads like a mood, the direction is not decided yet; the finishing review audits the render against this contract.
|
Before code, record the chosen direction as a development-only contract under `## Direction contract` in the relevant surface brief. A direction contract is durable route or artifact strategy, so create or update the brief even when no other surface strategy needs persistence. Use six short blocks, roughly 150 words; do not spend tool calls counting words. THESIS: the one idea this surface owns and the category-default arrangement it refuses. OWN-WORLD: the palette and component language, specific enough to be recognizable with all content removed. STORY: what the visitor understands, believes, and does. FIRST VIEWPORT: the exact composition, what is where and at what scale, and where the primary action sits. FORM: the chosen form, its position on your ordered list, and the seed key the script printed. Close with one more line, FINISH: the run's exit condition, verbatim "unreviewed and undocumented is unfinished; this build ends with the finish review, the verdict, DESIGN.md, and every shipping raster carrying its provenance". The surface brief is the reminder later agents reload across edits and sessions: a page that looks complete with the FINISH line undischarged is not done, it is abandoned at the finish line. If a block reads like a mood, the direction is not decided yet; the finishing review audits the render against this contract.
|
||||||
|
|
||||||
Never copy the direction contract into implementation source or any browser-delivered artifact. This includes HTML or framework comments, hidden DOM, `<template>` elements, `data-*` attributes, rendered JSX or TSX output, serialized props or state, React Server Component payloads, client bundles, metadata or JSON-LD, accessibility-only text, and files served beside the artifact. A compiler or optimizer removing development metadata is not a safety boundary. Reviewers and documenters receive the contract from the surface brief.
|
Never copy the direction contract into implementation source or any browser-delivered artifact. This includes HTML or framework comments, hidden DOM, `<template>` elements, `data-*` attributes, rendered JSX or TSX output, serialized props or state, React Server Component payloads, client bundles, metadata or JSON-LD, accessibility-only text, and files served beside the artifact. A compiler or optimizer removing development metadata is not a safety boundary. Reviewers and documenters receive the contract from the surface brief.
|
||||||
|
|
||||||
@@ -104,7 +104,7 @@ Then, in order, each closed by `.agents/skills/impeccable/scripts/impeccable bui
|
|||||||
The comp-led path is a frontier-tier job: it asks the builder to hold a measured layout, place plates at their boxes, and act on numeric readings across a dozen attempts. Smaller or faster models produce a recognisable page and stall under the hero gate; if the model in hand is one of those, say so before the direction round and take the code-led path, or expect the run to end at the hero with its readings unmet.
|
The comp-led path is a frontier-tier job: it asks the builder to hold a measured layout, place plates at their boxes, and act on numeric readings across a dozen attempts. Smaller or faster models produce a recognisable page and stall under the hero gate; if the model in hand is one of those, say so before the direction round and take the code-led path, or expect the run to end at the hero with its readings unmet.
|
||||||
|
|
||||||
1. **spec.** Measure the comp: `impeccable comp-spec --comp <comp> --grid` writes a coordinate grid over the comp; open it, name every salient region by grid span in a regions file (text and control regions snap to the largest ink mass inside their span, so a headline named B1:E4 measures as the headline and not the column beside it; `snap: false` keeps the span, and an explicit `box` is taken as drawn) (kind `plate` / `image` / `texture` for anything painted: every illustration, photograph, figure, product object, and material texture; `text` / `control` / `chrome` for what code draws; every region carries a `note` saying what the comp shows there, which the plate prompt and the gate messages read), and run `impeccable comp-spec --comp <comp> --regions <file>`. The spec carries each region's box, sampled palette, and medium; `impeccable comp-spec --print` is the build's reference from here on. Type is measured, not guessed: `impeccable font-match --measure <text region>` reads the comp's cap height, width class, and weight off the pixels, and `impeccable font-match --rank <region> --text "..."` takes its candidates from a fingerprint index of the Google Fonts catalog (the nearest faces to the crop's shape) plus any names you pass with `--candidates`, renders them at that cap height with the region's words, and ranks them by fingerprint distance (its `USE` line is the CSS; its proof sheet shows the comp over the top three); with no browser resolvable it records the catalog's nearest face and says the size is estimated, which is still the choice to build on. Do not install a browser to rank, and never write a `chosen` face into the spec by hand: the gate accepts only what font-match wrote. The spec gate refuses to close until the lead text region is measured and ranked. A region note that describes painted material (a diagram, drawing, photograph, texture) under a code kind is refused at the spec: reclassify it as a plate, or reword the note if code really draws it. The script refuses a regions file that leaves comp ink unnamed (callouts, a parts table, a notes block): what is never named can never be missing, so everything the comp shows gets a region. It also refuses a `text` / `control` / `chrome` region larger than a quarter of the comp: that is a column, not an element, and a column scored as one region hides the plates, tables, and notes inside it. Name each element inside it (`container: true` only when it truly is one undivided element). Anything drawn is a plate: an inline SVG past an icon's budget (a diagram, notation, leader lines with arrows, a "quick approximation" of the artwork) is refused at the hero; icon-sized SVG (under 64px, a few paths) is fine, and a chart the page draws from data at runtime is a chart, not an illustration. Callout lines and arrows that annotate a drawing belong to that drawing's plate, with only their labels set as text. A crop of the comp is never a plate (the plates gate refuses a file that is a resample of the comp region: the comp's grain, its neighbours' edges, and its resolution would ship as the artwork); the crop is the reference the plate is generated from. A plate region's box has to hold its whole artwork with a margin: the spec measures the artwork's contact with the box edges and refuses a box that cuts through it (`bleed: true` only when the page really crops it there), because a plate placed with `object-fit: cover` on such a box shows the artwork minus the side the box lost. Anything not in the spec does not exist on the page: no borders, rules, containers, or chrome the comp does not show. Only three concessions exist: fonts (the closest obtainable face), icon glyphs (close enough, exact if the user chose an icon library; this covers the pictogram only, never a control's chrome, so a chevron, an arrow, a dropdown's border and fill, a button's shape are the comp's), and genuine defects in the comp such as spelling errors.
|
1. **spec.** Measure the comp: `impeccable comp-spec --comp <comp> --grid` writes a coordinate grid over the comp; open it, name every salient region by grid span in a regions file (text and control regions snap to the largest ink mass inside their span, so a headline named B1:E4 measures as the headline and not the column beside it; `snap: false` keeps the span, and an explicit `box` is taken as drawn) (kind `plate` / `image` / `texture` for anything painted: every illustration, photograph, figure, product object, and material texture; `text` / `control` / `chrome` for what code draws; every region carries a `note` saying what the comp shows there, which the plate prompt and the gate messages read), and run `impeccable comp-spec --comp <comp> --regions <file>`. The spec carries each region's box, sampled palette, and medium; `impeccable comp-spec --print` is the build's reference from here on. Type is measured, not guessed: `impeccable font-match --measure <text region>` reads the comp's cap height, width class, and weight off the pixels, and `impeccable font-match --rank <region> --text "..."` takes its candidates from a fingerprint index of the Google Fonts catalog (the nearest faces to the crop's shape) plus any names you pass with `--candidates`, renders them at that cap height with the region's words, and ranks them by fingerprint distance (its `USE` line is the CSS; its proof sheet shows the comp over the top three); with no browser resolvable it records the catalog's nearest face and says the size is estimated, which is still the choice to build on. Do not install a browser to rank, and never write a `chosen` face into the spec by hand: the gate accepts only what font-match wrote. The spec gate refuses to close until the lead text region is measured and ranked. A region note that describes painted material (a diagram, drawing, photograph, texture) under a code kind is refused at the spec: reclassify it as a plate, or reword the note if code really draws it. The script refuses a regions file that leaves comp ink unnamed (callouts, a parts table, a notes block): what is never named can never be missing, so everything the comp shows gets a region. It also refuses a `text` / `control` / `chrome` region larger than a quarter of the comp: that is a column, not an element, and a column scored as one region hides the plates, tables, and notes inside it. Name each element inside it (`container: true` only when it truly is one undivided element). Anything drawn is a plate: an inline SVG past an icon's budget (a diagram, notation, leader lines with arrows, a "quick approximation" of the artwork) is refused at the hero; icon-sized SVG (under 64px, a few paths) is fine, and a chart the page draws from data at runtime is a chart, not an illustration. Callout lines and arrows that annotate a drawing belong to that drawing's plate, with only their labels set as text. A crop of the comp is never a plate (the plates gate refuses a file that is a resample of the comp region: the comp's grain, its neighbours' edges, and its resolution would ship as the artwork); the crop is the reference the plate is generated from. A plate region's box has to hold its whole artwork with a margin: the spec measures the artwork's contact with the box edges and refuses a box that cuts through it (`bleed: true` only when the page really crops it there), because a plate placed with `object-fit: cover` on such a box shows the artwork minus the side the box lost. Anything not in the spec does not exist on the page: no borders, rules, containers, or chrome the comp does not show. Only three concessions exist: fonts (the closest obtainable face), icon glyphs (close enough, exact if the user chose an icon library; this covers the pictogram only, never a control's chrome, so a chevron, an arrow, a dropdown's border and fill, a button's shape are the comp's), and genuine defects in the comp such as spelling errors.
|
||||||
2. **plates.** Every raster region ships as a plate: an illustration, photo, or figure regenerated at asset resolution from its comp crop, UI text removed, at its `plate` path (ink on flat ground is generated on a chroma key and keyed to alpha, so it sits on the page's own ground rather than a second paper); a texture (paper, cloth, grain) is a clean patch of the comp region mirror-tiled to size, generated only when no clean patch exists. `impeccable generate-image --plate <id>` does one region end to end and scores it against the crop; a harness-native image tool takes the crop (`impeccable comp-spec --crop <id>`) as its input image and `impeccable comp-spec --plate-prompt <id>` as its prompt, then `impeccable embed-prompt`. With parallel subagents, spawn the shipped asset producer (`impeccable-asset-producer`; `impeccable_asset_producer` in codex; `/impeccable-asset-producer` in Cursor; on GitHub Copilot say "Use the impeccable-asset-producer agent") with the spec path and let it produce them all; without subagents, produce them here. A crop of the comp is a reference, never a shipping pixel. The gate checks every plate exists, is at least 1.5x the region's size, and reads as the region. Page code waits for this gate: a page written before its plates exist is a page that draws its material in CSS. A single-file deliverable changes nothing here: the plate is produced the same way and inlined as a data URI. `--force` exists for one case only, the user downgrading the comp's authority in words you quote in `--reason`; the script refuses every other reason.
|
2. **plates.** Every raster region ships as a plate: an illustration, photo, or figure regenerated at asset resolution from its comp crop, UI text removed, at its `plate` path (isolated ink, figures, or objects use native transparent PNG so they sit on the page's own ground; photos and textures stay opaque); a texture (paper, cloth, grain) is a clean patch of the comp region mirror-tiled to size, generated only when no clean patch exists. `impeccable comp-spec --crop <id>` writes the reference; save `impeccable comp-spec --plate-prompt <id> --background transparent` to a prompt file for a cutout, or use `--background opaque` otherwise. Prefer the harness-native image tool with that crop and prompt, then `impeccable embed-prompt <plate> --prompt-file <prompt.txt>`. The API fallback is `impeccable generate-image --ref <crop.png> --prompt-file <prompt.txt> --out <plate.png> --size <WxH> --quality high --background transparent` (use `--background opaque` for full-frame assets); create the output directory first. Verify actual alpha, white foregrounds, fine edges, and clear holes on light and dark grounds; do not chroma-key native output. The plates gate scores the assets against the comp; also inspect placement and scale visually. With parallel subagents, spawn the shipped asset producer (`impeccable-asset-producer`; `impeccable_asset_producer` in codex; `/impeccable-asset-producer` in Cursor; on GitHub Copilot say "Use the impeccable-asset-producer agent") with the spec path and let it produce them all; without subagents, produce them here. A crop of the comp is a reference, never a shipping pixel. The gate checks every plate exists, is at least 1.5x the region's size, and reads as the region. Page code waits for this gate: a page written before its plates exist is a page that draws its material in CSS. A single-file deliverable changes nothing here: the plate is produced the same way and inlined as a data URI. `--force` exists for one case only, the user downgrading the comp's authority in words you quote in `--reason`; the script refuses every other reason.
|
||||||
3. **hero.** `impeccable build-phase scaffold` first: it writes the measured layout as CSS custom properties (`.impeccable/build/scaffold/layout.css`: `--r-<id>-x/y/w/h` in % of the comp, plus cap height, font-size, family, and weight where measured) and a reference page (`hero-reference.html`) with every region at its box and every plate placed. Bind the numbers to your own semantic structure, an element per region; the reference is a check on positions, never the page, and overlapping boxes are overlapping boxes. Then build only the first viewport, at the comp's own dimensions, the comp's words copied verbatim (the user approved that comp with those words; rewording is a stated decision after the hero passes, never a silent one inside it), every text region sized from its measured cap height and set in its ranked face, plates first: place every plate at its spec box (`object-fit: cover`, an `<img>`, a background image, or an inlined data URI named for it) before any text or control, capture into `.impeccable/review/hero-repro.png`, run `impeccable build-phase record hero` once so you see the plate regions read as match before any text exists, then lay the semantic layer over the plates from the spec's palette and boxes and advance. The gate first refuses while any plate is unreferenced by the source, then runs `impeccable comp-diff`, writes `.impeccable/review/diff/hero/` (side-by-side, heatmap, one paired crop per region, `report.json`), and passes at 72% overall with no hard veto outstanding (a missing region, a contradicted plate or text block, an SVG illustration, a clipped plate, invented ink block at any score); above the bar, the numeric readings become advisories printed with the pass, and the polish pass before responsive is where they get fixed: the gate also reads each text region's cap height, line count, weight, ink colour, and position against the comp, each chrome strip's height off its rule, and the frame for ink where the comp is calm (a kicker, an extra nav item, a divider), and says each miss as a number ("cap height 78px in the build, 103px in the comp"); those numbers are the edit. When it fails, open the region crops it lists, in order, before editing: a region scored `missing` needs its material, `contradicted` needs its structure re-derived from the spec box, `drift` is where size and spacing edits belong; the gate refuses a third attempt that only nudges values on the same region. This is where the run's ambition is won or lost, and a retry here costs minutes where a rebuild verdict at the finish costs the run.
|
3. **hero.** `impeccable build-phase scaffold` first: it writes the measured layout as CSS custom properties (`.impeccable/build/scaffold/layout.css`: `--r-<id>-x/y/w/h` in % of the comp, plus cap height, font-size, family, and weight where measured) and a reference page (`hero-reference.html`) with every region at its box and every plate placed. Bind the numbers to your own semantic structure, an element per region; the reference is a check on positions, never the page, and overlapping boxes are overlapping boxes. Then build only the first viewport, at the comp's own dimensions, the comp's words copied verbatim (the user approved that comp with those words; rewording is a stated decision after the hero passes, never a silent one inside it), every text region sized from its measured cap height and set in its ranked face, plates first: place every plate at its spec box (`object-fit: cover`, an `<img>`, a background image, or an inlined data URI named for it) before any text or control, capture into `.impeccable/review/hero-repro.png`, run `impeccable build-phase record hero` once so you see the plate regions read as match before any text exists, then lay the semantic layer over the plates from the spec's palette and boxes and advance. The gate first refuses while any plate is unreferenced by the source, then runs `impeccable comp-diff`, writes `.impeccable/review/diff/hero/` (side-by-side, heatmap, one paired crop per region, `report.json`), and passes at 72% overall with no hard veto outstanding (a missing region, a contradicted plate or text block, an SVG illustration, a clipped plate, invented ink block at any score); above the bar, the numeric readings become advisories printed with the pass, and the polish pass before responsive is where they get fixed: the gate also reads each text region's cap height, line count, weight, ink colour, and position against the comp, each chrome strip's height off its rule, and the frame for ink where the comp is calm (a kicker, an extra nav item, a divider), and says each miss as a number ("cap height 78px in the build, 103px in the comp"); those numbers are the edit. When it fails, open the region crops it lists, in order, before editing: a region scored `missing` needs its material, `contradicted` needs its structure re-derived from the spec box, `drift` is where size and spacing edits belong; the gate refuses a third attempt that only nudges values on the same region. This is where the run's ambition is won or lost, and a retry here costs minutes where a rebuild verdict at the finish costs the run.
|
||||||
4. **sections.** Build the rest of the surface inside the spec's system: the same corner language, line weights, and palette, and nothing the comp never shows. Where the comp does not cover a region, it inherits the recorded system.
|
4. **sections.** Build the rest of the surface inside the spec's system: the same corner language, line weights, and palette, and nothing the comp never shows. Where the comp does not cover a region, it inherits the recorded system.
|
||||||
5. **motion.** The signature interaction, reveals, and motion, orchestrated once rather than scattered.
|
5. **motion.** The signature interaction, reveals, and motion, orchestrated once rather than scattered.
|
||||||
@@ -142,4 +142,4 @@ A rebuild and a fix round share one asset rule: a raster either round creates or
|
|||||||
|
|
||||||
Report the final verdict under the reviewer's own disposition word and at its actual scope. A verdict pass scores the listed fixes and nothing else: "the reviewer scored all three fixes resolved" is a claim it supports, "no material issues remain" is not. A table with open material findings is never announced as a pass, never softened, and never dressed as whole-surface approval when only a fix list was scored. When the user answers a ship with evidence against it, their own screenshot, a named mismatch with the comp, that evidence outranks every capture you made: put their material in the packet and spawn a fresh reviewer for a new full review. Patching inline and self-certifying is how a rejected page ships twice.
|
Report the final verdict under the reviewer's own disposition word and at its actual scope. A verdict pass scores the listed fixes and nothing else: "the reviewer scored all three fixes resolved" is a claim it supports, "no material issues remain" is not. A table with open material findings is never announced as a pass, never softened, and never dressed as whole-surface approval when only a fix list was scored. When the user answers a ship with evidence against it, their own screenshot, a named mismatch with the comp, that evidence outranks every capture you made: put their material in the packet and spawn a fresh reviewer for a new full review. Patching inline and self-certifying is how a rejected page ships twice.
|
||||||
|
|
||||||
Then spawn the shipped documenter, `impeccable-documenter` (`impeccable_documenter` in codex), with the project root, the artifact path, the direction contract, PRODUCT.md, the [document.md](document.md) reference path, and the boundary to write at; it records DESIGN.md and the sidecar from the built world, ground truth over intention; without subagents the pass runs from [degraded/documenter.md](degraded/documenter.md). The documenter runs after the last correction lands: when any fix round follows the documentation, re-run the documenter over the changed surface, because a DESIGN.md describing a layout that no longer exists turns defects into system guidance. A clean detector pass is not finished; finished is the contract kept, the comp honored, the review closed, and the system recorded.
|
After the last correction, spawn the shipped documenter, `impeccable-documenter` (`impeccable_documenter` in codex), with the project root, artifact path, direction contract, PRODUCT.md, [document.md](document.md), and write boundary. Without subagents, load [degraded/documenter.md](degraded/documenter.md) and [document.md](document.md) before writing. Verify the outcome: new worlds and approved system changes require token-bearing DESIGN.md **and** `.impeccable/design.json`, not prose alone. Ordinary extensions compare the finished build against the incumbent system, preserve its files, and report the evidence checked; report pre-existing drift without repairing it unasked. Recheck after later edits. Finish only when review and documentation are complete.
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ What the comp shows is measured, not remembered. new-work.md section 6 runs the
|
|||||||
|
|
||||||
## Plates and provenance
|
## Plates and provenance
|
||||||
|
|
||||||
Every raster region's plate is produced in the plates phase, before any page code, by the shipped asset producer or in the current thread (`impeccable generate-image --plate <id>`, or the harness image tool with the crop as input and the spec's plate prompt). Generation context is part of the asset: after generating any image with any tool, run `.agents/skills/impeccable/scripts/impeccable embed-prompt <image> --prompt "<prompt>"` with the exact string the tool received (`impeccable generate-image` does this itself), so the intent lives inside the file; `--read` recovers it, `--scan <dir>` lists rasters still missing one. The embedded prompt plus the region's row in the spec is the raster's **provenance**, and every raster the artifact references carries it; a sourced, stock, or pre-existing raster embeds its origin instead. A raster created or replaced later, in a fix batch or a reviewer's rebuild, is produced the same way; a raster a fix abandons is deleted in the same batch.
|
Every raster region's plate is produced in the plates phase, before any page code, by the shipped asset producer or in the current thread (use `impeccable comp-spec --crop <id>` and save `impeccable comp-spec --plate-prompt <id>` to a prompt file; pass the crop and prompt to the harness image tool, or use `impeccable generate-image --ref <crop.png> --prompt-file <prompt.txt> --out <plate.png> --size <WxH> --quality high`). For isolated cutouts, add `--background transparent` to both the plate-prompt and API generation commands; use native PNG alpha and preserve white paint and clear gaps. Use `--background opaque` for full-frame imagery. Create output directories first and inspect alpha on light and dark grounds. Generation context is part of the asset: after generating any image with any tool, run `.agents/skills/impeccable/scripts/impeccable embed-prompt <image> --prompt "<prompt>"` with the exact string the tool received (`impeccable generate-image` does this itself), so the intent lives inside the file; `--read` recovers it, `--scan <dir>` lists rasters still missing one. The embedded prompt plus the region's row in the spec is the raster's **provenance**, and every raster the artifact references carries it; a sourced, stock, or pre-existing raster embeds its origin instead. A raster created or replaced later, in a fix batch or a reviewer's rebuild, is produced the same way; a raster a fix abandons is deleted in the same batch.
|
||||||
|
|
||||||
Convert images with a converter `impeccable context` reported at boot (the IMAGE_TOOLS line); probe only when it reported none, at most once per session, never per image.
|
Convert images with a converter `impeccable context` reported at boot (the IMAGE_TOOLS line); probe only when it reported none, at most once per session, never per image.
|
||||||
|
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
0.1.3
|
0.1.5
|
||||||
|
|||||||
@@ -87,6 +87,11 @@ fi
|
|||||||
# Last resort: fetch this version's binary for the current platform from the
|
# Last resort: fetch this version's binary for the current platform from the
|
||||||
# public release channel into the user cache. Needs network; sandboxes without
|
# public release channel into the user cache. Needs network; sandboxes without
|
||||||
# egress preinstall the binary on PATH instead.
|
# egress preinstall the binary on PATH instead.
|
||||||
|
setup_help() {
|
||||||
|
echo "Engine $version setup needs network access and write permission to $cache_root/bin/$version." >&2
|
||||||
|
echo "Run this launcher ($0) with engine-probe in a terminal that has those permissions, then retry the original command." >&2
|
||||||
|
echo "Alternatively, set IMPECCABLE_HOME to a writable cache location, or IMPECCABLE_BIN to a preinstalled engine binary." >&2
|
||||||
|
}
|
||||||
fetch_url() {
|
fetch_url() {
|
||||||
if command -v curl >/dev/null 2>&1; then
|
if command -v curl >/dev/null 2>&1; then
|
||||||
curl -fsSL --retry 2 -o "$tmp" "$1" 2>/dev/null
|
curl -fsSL --retry 2 -o "$tmp" "$1" 2>/dev/null
|
||||||
@@ -119,7 +124,18 @@ if [ -n "$version" ] && [ "$os" != unknown ] && [ "$arch" != unknown ]; then
|
|||||||
[ "$os" = windows ] && asset="$asset.exe"
|
[ "$os" = windows ] && asset="$asset.exe"
|
||||||
url="$base/engine-v$version/$asset"
|
url="$base/engine-v$version/$asset"
|
||||||
tmp="$cache_root/bin/$version/.impeccable.part.$$"
|
tmp="$cache_root/bin/$version/.impeccable.part.$$"
|
||||||
mkdir -p "$cache_root/bin/$version" 2>/dev/null
|
if ! mkdir -p "$cache_root/bin/$version" 2>/dev/null; then
|
||||||
|
echo "impeccable: engine $version is not installed; cannot create cache directory: $cache_root/bin/$version" >&2
|
||||||
|
setup_help
|
||||||
|
exit 127
|
||||||
|
fi
|
||||||
|
# Check the actual staging file, not just directory existence: a cache from
|
||||||
|
# an earlier run can be readable but no longer writable inside a sandbox.
|
||||||
|
if ! (umask 077; : > "$tmp") 2>/dev/null; then
|
||||||
|
echo "impeccable: engine $version is not installed; cannot write to cache directory: $cache_root/bin/$version" >&2
|
||||||
|
setup_help
|
||||||
|
exit 127
|
||||||
|
fi
|
||||||
fetched=0
|
fetched=0
|
||||||
if fetch_url "$url"; then
|
if fetch_url "$url"; then
|
||||||
fetched=1
|
fetched=1
|
||||||
@@ -180,6 +196,9 @@ if [ -n "$version" ] && [ "$os" != unknown ] && [ "$arch" != unknown ]; then
|
|||||||
exec "$cached" "$@"
|
exec "$cached" "$@"
|
||||||
fi
|
fi
|
||||||
rm -f "$tmp" 2>/dev/null
|
rm -f "$tmp" 2>/dev/null
|
||||||
|
echo "impeccable: could not download engine $version from $url; check network access, the release URL, and curl or wget availability." >&2
|
||||||
|
setup_help
|
||||||
|
exit 127
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "impeccable: no engine binary for $os-$arch found (looked in $bin, $cached, PATH)." >&2
|
echo "impeccable: no engine binary for $os-$arch found (looked in $bin, $cached, PATH)." >&2
|
||||||
|
|||||||
@@ -68,18 +68,27 @@ rem another launcher's probe: fail fast and quiet instead.
|
|||||||
if defined IMPECCABLE_LAUNCHER_PROBE exit /b 127
|
if defined IMPECCABLE_LAUNCHER_PROBE exit /b 127
|
||||||
if not defined version goto fail
|
if not defined version goto fail
|
||||||
where curl.exe >nul 2>nul
|
where curl.exe >nul 2>nul
|
||||||
if errorlevel 1 goto fail
|
if errorlevel 1 goto curl_missing
|
||||||
if not defined IMPECCABLE_DOWNLOAD_BASE set "IMPECCABLE_DOWNLOAD_BASE=https://github.com/pbakaus/impeccable/releases/download"
|
if not defined IMPECCABLE_DOWNLOAD_BASE set "IMPECCABLE_DOWNLOAD_BASE=https://github.com/pbakaus/impeccable/releases/download"
|
||||||
if not exist "%IMPECCABLE_HOME%\bin\%version%" mkdir "%IMPECCABLE_HOME%\bin\%version%" >nul 2>nul
|
if exist "%IMPECCABLE_HOME%\bin\%version%\" goto cache_ready
|
||||||
|
mkdir "%IMPECCABLE_HOME%\bin\%version%" >nul 2>nul
|
||||||
|
if errorlevel 1 goto cache_directory_failed
|
||||||
|
:cache_ready
|
||||||
|
rem Check the staging file too: an existing directory may be read-only.
|
||||||
|
rem Redirection failures do not reliably update ERRORLEVEL in cmd.exe;
|
||||||
|
rem branch on the command's failure directly. Never treat a directory as a
|
||||||
|
rem staging file (later del cleanup would prompt to delete its contents).
|
||||||
|
if exist "%cached%.part\" goto cache_write_failed
|
||||||
|
(type nul >"%cached%.part") 2>nul || goto cache_write_failed
|
||||||
set "asset=impeccable-windows-%arch%.exe"
|
set "asset=impeccable-windows-%arch%.exe"
|
||||||
set "url=%IMPECCABLE_DOWNLOAD_BASE%/engine-v%version%/%asset%"
|
set "url=%IMPECCABLE_DOWNLOAD_BASE%/engine-v%version%/%asset%"
|
||||||
curl.exe -fsSL -o "%cached%.part" "%url%" >nul 2>nul
|
curl.exe -fsSL -o "%cached%.part" "%url%" >nul 2>nul
|
||||||
if not errorlevel 1 goto verify
|
if not errorlevel 1 goto verify
|
||||||
if not "%arch%"=="arm64" goto fail
|
if not "%arch%"=="arm64" goto download_failed
|
||||||
set "asset=impeccable-windows-x64.exe"
|
set "asset=impeccable-windows-x64.exe"
|
||||||
set "url=%IMPECCABLE_DOWNLOAD_BASE%/engine-v%version%/%asset%"
|
set "url=%IMPECCABLE_DOWNLOAD_BASE%/engine-v%version%/%asset%"
|
||||||
curl.exe -fsSL -o "%cached%.part" "%url%" >nul 2>nul
|
curl.exe -fsSL -o "%cached%.part" "%url%" >nul 2>nul
|
||||||
if errorlevel 1 goto fail
|
if errorlevel 1 goto download_failed
|
||||||
|
|
||||||
:verify
|
:verify
|
||||||
call :check_download
|
call :check_download
|
||||||
@@ -176,6 +185,28 @@ if not errorlevel 1 set "probe_ok=1"
|
|||||||
del "%probe_tmp%" >nul 2>nul
|
del "%probe_tmp%" >nul 2>nul
|
||||||
exit /b 0
|
exit /b 0
|
||||||
|
|
||||||
|
:cache_directory_failed
|
||||||
|
echo impeccable: engine %version% is not installed; cannot create cache directory: "%IMPECCABLE_HOME%\bin\%version%" 1>&2
|
||||||
|
goto setup_failed
|
||||||
|
|
||||||
|
:cache_write_failed
|
||||||
|
echo impeccable: engine %version% is not installed; cannot write to cache directory: "%IMPECCABLE_HOME%\bin\%version%" 1>&2
|
||||||
|
goto setup_failed
|
||||||
|
|
||||||
|
:curl_missing
|
||||||
|
echo impeccable: cannot download engine %version%; curl.exe is unavailable. 1>&2
|
||||||
|
goto setup_failed
|
||||||
|
|
||||||
|
:download_failed
|
||||||
|
del "%cached%.part" >nul 2>nul
|
||||||
|
echo impeccable: could not download engine %version% from %url%; check network access and the release URL. 1>&2
|
||||||
|
|
||||||
|
:setup_failed
|
||||||
|
echo Engine %version% setup needs network access and write permission to "%IMPECCABLE_HOME%\bin\%version%". 1>&2
|
||||||
|
echo Run this launcher ("%~f0") with engine-probe in a terminal that has those permissions, then retry the original command. 1>&2
|
||||||
|
echo Alternatively, set IMPECCABLE_HOME to a writable cache location, or IMPECCABLE_BIN to a preinstalled engine binary. 1>&2
|
||||||
|
exit /b 127
|
||||||
|
|
||||||
:fail
|
:fail
|
||||||
del "%cached%.part" >nul 2>nul
|
del "%cached%.part" >nul 2>nul
|
||||||
echo impeccable: no engine binary found (looked in %bin%, %cached%, PATH). 1>&2
|
echo impeccable: no engine binary found (looked in %bin%, %cached%, PATH). 1>&2
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
{
|
{
|
||||||
"name": "impeccable",
|
"name": "impeccable",
|
||||||
"description": "Design fluency for frontend development. 1 skill with 23 commands (/impeccable polish, /impeccable audit, /impeccable critique, etc.) and curated anti-pattern detection.",
|
"description": "Design fluency for frontend development. 1 skill with 23 commands (/impeccable polish, /impeccable audit, /impeccable critique, etc.) and curated anti-pattern detection.",
|
||||||
"version": "4.2.2",
|
"version": "4.3.1",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Paul Bakaus",
|
"name": "Paul Bakaus",
|
||||||
"email": "paul@paulbakaus.com"
|
"email": "paul@paulbakaus.com"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "impeccable",
|
"name": "impeccable",
|
||||||
"description": "Design fluency for frontend development. 1 skill with 23 commands (/impeccable polish, /impeccable audit, /impeccable critique, etc.) and curated anti-pattern detection.",
|
"description": "Design fluency for frontend development. 1 skill with 23 commands (/impeccable polish, /impeccable audit, /impeccable critique, etc.) and curated anti-pattern detection.",
|
||||||
"version": "4.2.2",
|
"version": "4.3.1",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Paul Bakaus",
|
"name": "Paul Bakaus",
|
||||||
"email": "paul@paulbakaus.com"
|
"email": "paul@paulbakaus.com"
|
||||||
|
|||||||
@@ -31,12 +31,12 @@ Every region with `medium: raster` in the spec ships as a plate at its `plate` p
|
|||||||
Per region, in the spec's order:
|
Per region, in the spec's order:
|
||||||
|
|
||||||
1. `.claude/skills/impeccable/scripts/impeccable comp-spec --crop <id>` writes the reference crop under `.impeccable/build/crops/`.
|
1. `.claude/skills/impeccable/scripts/impeccable comp-spec --crop <id>` writes the reference crop under `.impeccable/build/crops/`.
|
||||||
2. Produce the plate. With the API fallback: `.claude/skills/impeccable/scripts/impeccable generate-image --plate <id> --quality high` does the whole step (crop as reference, the spec's plate prompt, output size chosen from the region's aspect, the file written to its plate path, prompt embedded, and the plate scored against the crop). With a harness-native image tool: use the crop as the input image and `.claude/skills/impeccable/scripts/impeccable comp-spec --plate-prompt <id>` as the prompt, write the result to the plate path, then run `.claude/skills/impeccable/scripts/impeccable embed-prompt <plate> --prompt "<the exact prompt>"`.
|
2. Choose the background from the approved region: an isolated figure, object, or line drawing on the page ground is a **transparent cutout**; a photograph, full-frame illustration, or texture stays **opaque**. Save `.claude/skills/impeccable/scripts/impeccable comp-spec --plate-prompt <id> --background transparent` to a UTF-8 prompt file for a cutout; use `--background opaque` otherwise. The transparent prompt preserves reference placement and clear margins, white paint, fine edges, and interior holes.
|
||||||
3. Read the score line. `PLATE-SCORE` under 50%, or a `PLATE-WARN`, means the plate does not read as the region: open the plate beside the crop, name what drifted (subject, framing, palette, style), tighten the prompt with that, and regenerate once. Two misses on one region: keep the better plate, mark it `needs_parent_review`, and say why in one line.
|
3. Produce the plate at its exact spec `plate` path. Create the output directory first and choose a supported output size matching the region's aspect, at least 1.5x its pixel dimensions. Prefer the harness-native image tool with the crop as input and the saved prompt; request a transparent PNG for cutouts, then run `.claude/skills/impeccable/scripts/impeccable embed-prompt <plate> --prompt-file <prompt.txt>` (if you refine the prompt, save and embed the exact text sent). With the API fallback, run `.claude/skills/impeccable/scripts/impeccable generate-image --ref <crop.png> --prompt-file <prompt.txt> --out <plate.png> --size <WxH> --quality high --background transparent` for a cutout, or `--background opaque` otherwise. The API fallback embeds the prompt and records the background in the sidecar. The output must be PNG; the fallback requests native alpha and performs no chroma-keying.
|
||||||
4. Transparent cutouts (a figure or object on the page ground): generate on a flat chroma color absent from the subject and key it to alpha before writing the PNG; never ship the keyed background.
|
4. Open the plate beside the crop and compare subject, placement, scale, palette, and style. For cutouts, verify a real alpha channel and inspect composites on light and dark grounds: white paint must stay solid, interior holes must clear, and fine edges must avoid halos. Inspect glass and soft shadows carefully; partial alpha alone does not ensure convincing translucency. Never chroma-key native transparent output or flatten it before saving. If a native tool returns opaque pixels or a painted checkerboard, retry with the API fallback when available; otherwise report the transparency blocker. On a visual miss, tighten the prompt and regenerate once. Two misses on one region: keep the better plate, mark it `needs_parent_review`, and name the drift. The parent runs the plates gate after all assets exist; report `unscored` until a gate score is available.
|
||||||
|
|
||||||
Do not redesign. Do not add objects, restyle, or reinterpret; the comp was approved as it is. Do not touch the page code, the spec, or the comp. Do not produce anything the spec does not list; a region the parent forgot goes back as a one-line note, not a plate.
|
Do not redesign. Do not add objects, restyle, or reinterpret; the comp was approved as it is. Do not touch the page code, the spec, or the comp. Do not produce anything the spec does not list; a region the parent forgot goes back as a one-line note, not a plate.
|
||||||
|
|
||||||
## Output Contract
|
## Output Contract
|
||||||
|
|
||||||
Return one line per raster region: `<id> <plate path> <WxH> <score>% <accepted|needs_parent_review|blocked> <one-line note or ->`. Then `blockers` (missing spec, missing comp, no image capability, exhausted key) and `assumptions`, each global and minimal. Nothing else: no summary, no praise, no implementation advice. The parent runs `impeccable build-phase advance` to verify the plates against the same spec; your line and its line must agree.
|
Return one line per raster region: `<id> <plate path> <WxH> <score%|unscored> <accepted|needs_parent_review|blocked> <one-line note or ->`. Then `blockers` (missing spec, missing comp, no image capability, exhausted key) and `assumptions`, each global and minimal. Nothing else: no summary, no praise, no implementation advice. The parent runs `impeccable build-phase advance` to verify the plates against the same spec; a visual acceptance does not override a failing gate.
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ maxTurns: 30
|
|||||||
|
|
||||||
You record a project's design system after the build is done. Ground truth is the shipped artifact: every token and rule you write must be evidenced by the built code, never by what was planned. Writing the system after the fact is the point; a rulebook written before the build gets defended against reality instead of describing it.
|
You record a project's design system after the build is done. Ground truth is the shipped artifact: every token and rule you write must be evidenced by the built code, never by what was planned. Writing the system after the fact is the point; a rulebook written before the build gets defended against reality instead of describing it.
|
||||||
|
|
||||||
You run under a hard turn ceiling that ends the run without warning, and a run that ends before DESIGN.md is written has recorded nothing. Batch several Reads into each turn, take `reference/document.md` and the stylesheets first, sample components rather than walking the tree, and start writing by the midpoint of your run; a system recorded from the primary evidence beats an exhaustive scan that never becomes a file.
|
Complete the check within your turn ceiling. Batch Reads, take `reference/document.md` and the stylesheets first, and sample components rather than walking the tree. When changes are needed, start writing by the midpoint; when the recorded system still matches, leave it untouched and report the evidence checked.
|
||||||
|
|
||||||
## Input Contract
|
## Input Contract
|
||||||
|
|
||||||
@@ -20,10 +20,10 @@ Expect: the project root; the artifact path(s); the direction contract text (THE
|
|||||||
|
|
||||||
1. Read `reference/document.md` in full; it is the operating spec for DESIGN.md's format, token schema, sidecar, and section order. Follow it exactly.
|
1. Read `reference/document.md` in full; it is the operating spec for DESIGN.md's format, token schema, sidecar, and section order. Follow it exactly.
|
||||||
2. Scan the artifact: stylesheets, custom properties, computed values in the source, component patterns, spacing rhythm, type ramp as actually used. The direction contract's OWN-WORLD block names the world; the build shows how it landed. Where they diverge, the build wins and the prose may note the divergence.
|
2. Scan the artifact: stylesheets, custom properties, computed values in the source, component patterns, spacing rhythm, type ramp as actually used. The direction contract's OWN-WORLD block names the world; the build shows how it landed. Where they diverge, the build wins and the prose may note the divergence.
|
||||||
3. Write DESIGN.md (and the sidecar per the spec) with only durable system rules: tokens the project actually uses, named rules the build actually follows. Skip one-off values; a token used once is not a system.
|
3. For a new world or approved system change, write DESIGN.md and its sidecar from durable, reused rules in the build. Ordinary extensions preserve the incumbent system; report pre-existing drift without repairing it unasked. Do not write merely to prove this pass ran.
|
||||||
4. Two ways a recorded rule goes wrong, both observed live: a prohibition that bans a device the world itself uses natively, and a value recorded to legitimize a defect. Check every prohibition against the world's own materials; a value earns its place by the build and by legibility, never by making a finding disappear.
|
4. Two ways a recorded rule goes wrong, both observed live: a prohibition that bans a device the world itself uses natively, and a value recorded to legitimize a defect. Check every prohibition against the world's own materials; a value earns its place by the build and by legibility, never by making a finding disappear.
|
||||||
5. Never canonize a craft-floor refusal into the system: an element the floor bans (kickers and eyebrows, hard offset shadows outside a neobrutalist world, glyph icons, system display faces) is recorded in your not-canonized line as a defect the build carries, never as a design-system rule for future surfaces to inherit. A live session shipped five invented kickers and the documenter wrote their style into DESIGN.md; that is how one violation becomes the house style.
|
5. Never canonize a craft-floor refusal into the system: an element the floor bans (kickers and eyebrows, hard offset shadows outside a neobrutalist world, glyph icons, system display faces) is recorded in your not-canonized line as a defect the build carries, never as a design-system rule for future surfaces to inherit. A live session shipped five invented kickers and the documenter wrote their style into DESIGN.md; that is how one violation becomes the house style.
|
||||||
|
|
||||||
## Output Contract
|
## Output Contract
|
||||||
|
|
||||||
Return: the file paths written, a five-line summary of the recorded system (palette strategy, type ramp shape, named rules), and one line naming anything in the build you deliberately did not canonize and why. No other prose.
|
Return: paths written, or “No changes” with the source and system files checked; a five-line system summary (palette, type ramp, named rules); and one line naming defects or drift not canonized or repaired, and why. No other prose.
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
name: impeccable
|
name: impeccable
|
||||||
description: Use when the user wants to design, redesign, shape, critique, audit, polish, clarify, distill, harden, optimize, adapt, animate, colorize, extract, or otherwise improve a frontend interface. Covers websites, landing pages, dashboards, product UI, app shells, components, forms, settings, onboarding, and empty states. Handles UX review, visual hierarchy, information architecture, cognitive load, accessibility, performance, responsive behavior, theming, anti-patterns, typography, fonts, spacing, layout, alignment, color, motion, micro-interactions, UX copy, error states, edge cases, i18n, and reusable design systems or tokens. Also use for bland designs that need to become bolder or more delightful, loud designs that should become quieter, live browser iteration on UI elements, or ambitious visual effects that should feel technically extraordinary. Not for backend-only or non-UI tasks.
|
description: Use when the user wants to design, redesign, shape, critique, audit, polish, clarify, distill, harden, optimize, adapt, animate, colorize, extract, or otherwise improve a frontend interface. Covers websites, landing pages, dashboards, product UI, app shells, components, forms, settings, onboarding, and empty states. Handles UX review, visual hierarchy, information architecture, cognitive load, accessibility, performance, responsive behavior, theming, anti-patterns, typography, fonts, spacing, layout, alignment, color, motion, micro-interactions, UX copy, error states, edge cases, i18n, and reusable design systems or tokens. Also use for bland designs that need to become bolder or more delightful, loud designs that should become quieter, live browser iteration on UI elements, or ambitious visual effects that should feel technically extraordinary. Not for backend-only or non-UI tasks.
|
||||||
version: 4.2.2
|
version: 4.3.1
|
||||||
user-invocable: true
|
user-invocable: true
|
||||||
argument-hint: "[shape · audit|critique · animate|bolder|colorize|delight|layout|overdrive|quieter|typeset · adapt|clarify|distill · harden|onboard|optimize|polish · init|document|extract|live] [target]"
|
argument-hint: "[shape · audit|critique · animate|bolder|colorize|delight|layout|overdrive|quieter|typeset · adapt|clarify|distill · harden|onboard|optimize|polish · init|document|extract|live] [target]"
|
||||||
license: Apache 2.0
|
license: Apache 2.0
|
||||||
@@ -16,9 +16,11 @@ Core principles:
|
|||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
1. Run `<skill-base-dir>/scripts/impeccable context` once per session, where `<skill-base-dir>` is the directory that contains this SKILL.md (the skill folder, not a plugin root two levels above it); keep cwd at the user's project. That base directory resolves every `.claude/skills/impeccable/scripts/impeccable <verb>` command in this skill and its references, and `.claude/skills/impeccable/scripts` is the fallback only when the runtime reports no base directory. On a Windows shell without `sh`, call `.claude/skills/impeccable/scripts/impeccable.cmd` instead. The launcher runs a self-contained binary that ships next to it or is downloaded once on first run; no Node or other runtime is required. Pass a named source file or route as `--target <path>`. It loads PRODUCT.md, DESIGN.md, the matching surface brief, and native-platform guidance when applicable; follow its directives and do not rerun it. If the launcher is refused, missing, or fails, tell the user before editing that context loading did not run. Read existing **PRODUCT.md** and **DESIGN.md** without inventing missing context, then continue with steps 2–3.
|
1. Run `<skill-base-dir>/scripts/impeccable context` once per session, where `<skill-base-dir>` is the directory that contains this SKILL.md (the skill folder, not a plugin root two levels above it); keep cwd at the user's project. That base directory resolves every `.claude/skills/impeccable/scripts/impeccable <verb>` command in this skill and its references, and `.claude/skills/impeccable/scripts` is the fallback only when the runtime reports no base directory. On a Windows shell without `sh`, call `.claude/skills/impeccable/scripts/impeccable.cmd` instead. The launcher runs a self-contained binary that ships next to it or is downloaded once on first run; no Node or other runtime is required. Pass a named source file or route as `--target <path>`. It loads PRODUCT.md, DESIGN.md, the matching surface brief, and native-platform guidance when applicable; follow its directives and do not rerun it.
|
||||||
2. Load the request's playbook: its Commands-table reference for an explicit/implied sub-command, or [reference/new-work.md](reference/new-work.md) for a new surface or replacement visual world. Inspect target and incumbent visual truth before editing. When the app cannot run, start with committed visual-regression goldens or screenshot fixtures; verify target and freshness against current tokens, CSS, components, or assets, resolve conflicts, and compare theme/variant captures.
|
2. Load the request's playbook: its Commands-table reference for an explicit/implied sub-command, or [reference/new-work.md](reference/new-work.md) for a new surface or replacement visual world. Inspect target and incumbent visual truth before editing. When the app cannot run, start with committed visual-regression goldens or screenshot fixtures; verify target and freshness against current tokens, CSS, components, or assets, resolve conflicts, and compare theme/variant captures.
|
||||||
3. After analysis and direction are resolved, load [reference/craft-floor.md](reference/craft-floor.md) immediately before editing UI. It carries the quality floor, the absolute bans, and the reflexes no detector catches. Do not load it for planning-only work.
|
3. After resolving analysis and direction, read [reference/craft-floor.md](reference/craft-floor.md) immediately before any UI edit, including small refinements. It carries the quality floor, the absolute bans, and the reflexes no detector catches. Do not load it for planning-only work.
|
||||||
|
|
||||||
|
**Launcher unavailable:** On refusal or failure, send a separate message **before the next tool call**: “Context loading did not run; I’ll read the existing project context directly.” Then read existing PRODUCT.md and DESIGN.md without inventing missing context, follow applicable steps 2–3, and continue through permitted tools. This applies to planning and editing; launcher failure alone does not block either.
|
||||||
|
|
||||||
## How to design
|
## How to design
|
||||||
|
|
||||||
|
|||||||
@@ -188,6 +188,12 @@ Test thoroughly across contexts:
|
|||||||
- **Edge cases**: Very small screens (320px), very large screens (4K)
|
- **Edge cases**: Very small screens (320px), very large screens (4K)
|
||||||
- **Slow connections**: Test on throttled network
|
- **Slow connections**: Test on throttled network
|
||||||
|
|
||||||
|
**Custom controls** (sliders, drag surfaces, scrollable control strips): a before/after slider can pass every width check above and still refuse to drag on iOS, so exercise each one in scope in the same batched round as the checks above:
|
||||||
|
|
||||||
|
- **Primary gesture**: Tap it and confirm it responds as designed, then drag it with the target input method; the drag must complete, not just start
|
||||||
|
- **Scroll across it**: A swipe along the page's scroll axis across the control scrolls the page or container without activating it; a drag that starts on the control along its axis moves the control, not the page. Neither failure throws an error, so try both
|
||||||
|
- **Evidence**: Say what produced the evidence: an emulated viewport, synthesized touch input through a browser tool, which engine ran it (Chromium is not Safari), or a physical device. Screenshots and resized viewports verify layout, never a gesture. Name what stayed untested and move on; unreachable hardware is a reported gap, not a blocker
|
||||||
|
|
||||||
When the adaptation feels native to each context, hand off to `/impeccable polish` for the final pass.
|
When the adaptation feels native to each context, hand off to `/impeccable polish` for the final pass.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -48,11 +48,12 @@ Run comprehensive checks across 5 dimensions. Score each dimension 0-4 using the
|
|||||||
**Check for**:
|
**Check for**:
|
||||||
- **Fixed widths**: Hard-coded widths that break on mobile
|
- **Fixed widths**: Hard-coded widths that break on mobile
|
||||||
- **Touch targets**: Interactive elements < 44x44px
|
- **Touch targets**: Interactive elements < 44x44px
|
||||||
|
- **Broken touch interaction**: Custom sliders, drag surfaces, and scrollable control strips whose primary gesture fails under touch, that swallow page scroll or lose the drag to it, or that stay stuck after an interrupted gesture. Code tells: mouse-only handlers, no `touch-action` on a pointer-event drag surface, drag state that nothing clears on cancel, lost capture, or blur. Exercise the gesture when a browser tool can synthesize touch (a rendered viewport proves layout, not the gesture), then say what produced the evidence (emulated viewport, synthesized touch, which engine, physical device) and what stayed untested
|
||||||
- **Horizontal scroll**: Content overflow on narrow viewports
|
- **Horizontal scroll**: Content overflow on narrow viewports
|
||||||
- **Text scaling**: Layouts that break when text size increases
|
- **Text scaling**: Layouts that break when text size increases
|
||||||
- **Missing breakpoints**: No mobile/tablet variants
|
- **Missing breakpoints**: No mobile/tablet variants
|
||||||
|
|
||||||
**Score 0-4**: 0=Desktop-only (breaks on mobile), 1=Major issues (some breakpoints, many failures), 2=Partial (works on mobile, rough edges), 3=Good (responsive, minor touch target or overflow issues), 4=Excellent (fluid, all viewports, proper touch targets)
|
**Score 0-4**: 0=Desktop-only (breaks on mobile), 1=Major issues (some breakpoints, many failures), 2=Partial (works on mobile, rough edges), 3=Good (responsive, minor touch target or overflow issues), 4=Excellent (fluid, all viewports, proper touch targets, gestures work under touch)
|
||||||
|
|
||||||
### 5. Implementation Integrity (CRITICAL)
|
### 5. Implementation Integrity (CRITICAL)
|
||||||
|
|
||||||
|
|||||||
@@ -26,12 +26,12 @@ Every region with `medium: raster` in the spec ships as a plate at its `plate` p
|
|||||||
Per region, in the spec's order:
|
Per region, in the spec's order:
|
||||||
|
|
||||||
1. `.claude/skills/impeccable/scripts/impeccable comp-spec --crop <id>` writes the reference crop under `.impeccable/build/crops/`.
|
1. `.claude/skills/impeccable/scripts/impeccable comp-spec --crop <id>` writes the reference crop under `.impeccable/build/crops/`.
|
||||||
2. Produce the plate. With the API fallback: `.claude/skills/impeccable/scripts/impeccable generate-image --plate <id> --quality high` does the whole step (crop as reference, the spec's plate prompt, output size chosen from the region's aspect, the file written to its plate path, prompt embedded, and the plate scored against the crop). With a harness-native image tool: use the crop as the input image and `.claude/skills/impeccable/scripts/impeccable comp-spec --plate-prompt <id>` as the prompt, write the result to the plate path, then run `.claude/skills/impeccable/scripts/impeccable embed-prompt <plate> --prompt "<the exact prompt>"`.
|
2. Choose the background from the approved region: an isolated figure, object, or line drawing on the page ground is a **transparent cutout**; a photograph, full-frame illustration, or texture stays **opaque**. Save `.claude/skills/impeccable/scripts/impeccable comp-spec --plate-prompt <id> --background transparent` to a UTF-8 prompt file for a cutout; use `--background opaque` otherwise. The transparent prompt preserves reference placement and clear margins, white paint, fine edges, and interior holes.
|
||||||
3. Read the score line. `PLATE-SCORE` under 50%, or a `PLATE-WARN`, means the plate does not read as the region: open the plate beside the crop, name what drifted (subject, framing, palette, style), tighten the prompt with that, and regenerate once. Two misses on one region: keep the better plate, mark it `needs_parent_review`, and say why in one line.
|
3. Produce the plate at its exact spec `plate` path. Create the output directory first and choose a supported output size matching the region's aspect, at least 1.5x its pixel dimensions. Prefer the harness-native image tool with the crop as input and the saved prompt; request a transparent PNG for cutouts, then run `.claude/skills/impeccable/scripts/impeccable embed-prompt <plate> --prompt-file <prompt.txt>` (if you refine the prompt, save and embed the exact text sent). With the API fallback, run `.claude/skills/impeccable/scripts/impeccable generate-image --ref <crop.png> --prompt-file <prompt.txt> --out <plate.png> --size <WxH> --quality high --background transparent` for a cutout, or `--background opaque` otherwise. The API fallback embeds the prompt and records the background in the sidecar. The output must be PNG; the fallback requests native alpha and performs no chroma-keying.
|
||||||
4. Transparent cutouts (a figure or object on the page ground): generate on a flat chroma color absent from the subject and key it to alpha before writing the PNG; never ship the keyed background.
|
4. Open the plate beside the crop and compare subject, placement, scale, palette, and style. For cutouts, verify a real alpha channel and inspect composites on light and dark grounds: white paint must stay solid, interior holes must clear, and fine edges must avoid halos. Inspect glass and soft shadows carefully; partial alpha alone does not ensure convincing translucency. Never chroma-key native transparent output or flatten it before saving. If a native tool returns opaque pixels or a painted checkerboard, retry with the API fallback when available; otherwise report the transparency blocker. On a visual miss, tighten the prompt and regenerate once. Two misses on one region: keep the better plate, mark it `needs_parent_review`, and name the drift. The parent runs the plates gate after all assets exist; report `unscored` until a gate score is available.
|
||||||
|
|
||||||
Do not redesign. Do not add objects, restyle, or reinterpret; the comp was approved as it is. Do not touch the page code, the spec, or the comp. Do not produce anything the spec does not list; a region the parent forgot goes back as a one-line note, not a plate.
|
Do not redesign. Do not add objects, restyle, or reinterpret; the comp was approved as it is. Do not touch the page code, the spec, or the comp. Do not produce anything the spec does not list; a region the parent forgot goes back as a one-line note, not a plate.
|
||||||
|
|
||||||
## Output Contract
|
## Output Contract
|
||||||
|
|
||||||
Return one line per raster region: `<id> <plate path> <WxH> <score>% <accepted|needs_parent_review|blocked> <one-line note or ->`. Then `blockers` (missing spec, missing comp, no image capability, exhausted key) and `assumptions`, each global and minimal. Nothing else: no summary, no praise, no implementation advice. The parent runs `impeccable build-phase advance` to verify the plates against the same spec; your line and its line must agree.
|
Return one line per raster region: `<id> <plate path> <WxH> <score%|unscored> <accepted|needs_parent_review|blocked> <one-line note or ->`. Then `blockers` (missing spec, missing comp, no image capability, exhausted key) and `assumptions`, each global and minimal. Nothing else: no summary, no praise, no implementation advice. The parent runs `impeccable build-phase advance` to verify the plates against the same spec; a visual acceptance does not override a failing gate.
|
||||||
@@ -5,7 +5,7 @@ This harness has no subagent capability, so you are running this role inline. St
|
|||||||
|
|
||||||
You record a project's design system after the build is done. Ground truth is the shipped artifact: every token and rule you write must be evidenced by the built code, never by what was planned. Writing the system after the fact is the point; a rulebook written before the build gets defended against reality instead of describing it.
|
You record a project's design system after the build is done. Ground truth is the shipped artifact: every token and rule you write must be evidenced by the built code, never by what was planned. Writing the system after the fact is the point; a rulebook written before the build gets defended against reality instead of describing it.
|
||||||
|
|
||||||
You run under a hard turn ceiling that ends the run without warning, and a run that ends before DESIGN.md is written has recorded nothing. Batch several Reads into each turn, take `reference/document.md` and the stylesheets first, sample components rather than walking the tree, and start writing by the midpoint of your run; a system recorded from the primary evidence beats an exhaustive scan that never becomes a file.
|
Complete the check within your turn ceiling. Batch Reads, take `reference/document.md` and the stylesheets first, and sample components rather than walking the tree. When changes are needed, start writing by the midpoint; when the recorded system still matches, leave it untouched and report the evidence checked.
|
||||||
|
|
||||||
## Input Contract
|
## Input Contract
|
||||||
|
|
||||||
@@ -15,10 +15,10 @@ Expect: the project root; the artifact path(s); the direction contract text (THE
|
|||||||
|
|
||||||
1. Read `reference/document.md` in full; it is the operating spec for DESIGN.md's format, token schema, sidecar, and section order. Follow it exactly.
|
1. Read `reference/document.md` in full; it is the operating spec for DESIGN.md's format, token schema, sidecar, and section order. Follow it exactly.
|
||||||
2. Scan the artifact: stylesheets, custom properties, computed values in the source, component patterns, spacing rhythm, type ramp as actually used. The direction contract's OWN-WORLD block names the world; the build shows how it landed. Where they diverge, the build wins and the prose may note the divergence.
|
2. Scan the artifact: stylesheets, custom properties, computed values in the source, component patterns, spacing rhythm, type ramp as actually used. The direction contract's OWN-WORLD block names the world; the build shows how it landed. Where they diverge, the build wins and the prose may note the divergence.
|
||||||
3. Write DESIGN.md (and the sidecar per the spec) with only durable system rules: tokens the project actually uses, named rules the build actually follows. Skip one-off values; a token used once is not a system.
|
3. For a new world or approved system change, write DESIGN.md and its sidecar from durable, reused rules in the build. Ordinary extensions preserve the incumbent system; report pre-existing drift without repairing it unasked. Do not write merely to prove this pass ran.
|
||||||
4. Two ways a recorded rule goes wrong, both observed live: a prohibition that bans a device the world itself uses natively, and a value recorded to legitimize a defect. Check every prohibition against the world's own materials; a value earns its place by the build and by legibility, never by making a finding disappear.
|
4. Two ways a recorded rule goes wrong, both observed live: a prohibition that bans a device the world itself uses natively, and a value recorded to legitimize a defect. Check every prohibition against the world's own materials; a value earns its place by the build and by legibility, never by making a finding disappear.
|
||||||
5. Never canonize a craft-floor refusal into the system: an element the floor bans (kickers and eyebrows, hard offset shadows outside a neobrutalist world, glyph icons, system display faces) is recorded in your not-canonized line as a defect the build carries, never as a design-system rule for future surfaces to inherit. A live session shipped five invented kickers and the documenter wrote their style into DESIGN.md; that is how one violation becomes the house style.
|
5. Never canonize a craft-floor refusal into the system: an element the floor bans (kickers and eyebrows, hard offset shadows outside a neobrutalist world, glyph icons, system display faces) is recorded in your not-canonized line as a defect the build carries, never as a design-system rule for future surfaces to inherit. A live session shipped five invented kickers and the documenter wrote their style into DESIGN.md; that is how one violation becomes the house style.
|
||||||
|
|
||||||
## Output Contract
|
## Output Contract
|
||||||
|
|
||||||
Return: the file paths written, a five-line summary of the recorded system (palette strategy, type ramp shape, named rules), and one line naming anything in the build you deliberately did not canonize and why. No other prose.
|
Return: paths written, or “No changes” with the source and system files checked; a five-line system summary (palette, type ramp, named rules); and one line naming defects or drift not canonized or repaired, and why. No other prose.
|
||||||
@@ -205,6 +205,11 @@ t('items', { count }) // Handles complex plural rules
|
|||||||
- Optimistic updates with rollback
|
- Optimistic updates with rollback
|
||||||
- Conflict resolution
|
- Conflict resolution
|
||||||
|
|
||||||
|
**Interrupted gestures** (custom sliders, drag surfaces, scrollable control strips):
|
||||||
|
- A second finger or pointer lands mid-drag: the first drag keeps its pointer or ends cleanly, never jumps to the new one
|
||||||
|
- The browser cancels the gesture to scroll (`pointercancel`), capture is lost (`lostpointercapture`), the pointer is released outside the control, or the window loses focus (`blur`) mid-drag: clear the dragging state and release capture
|
||||||
|
- After each of these, the next tap or drag works without a reload
|
||||||
|
|
||||||
**Permission states**:
|
**Permission states**:
|
||||||
- No permission to view
|
- No permission to view
|
||||||
- No permission to edit
|
- No permission to edit
|
||||||
@@ -304,6 +309,7 @@ const throttledScroll = throttle(handleScroll, 100);
|
|||||||
- Unit tests for edge cases
|
- Unit tests for edge cases
|
||||||
- Integration tests for error scenarios
|
- Integration tests for error scenarios
|
||||||
- E2E tests for critical paths
|
- E2E tests for critical paths
|
||||||
|
- A behavioral regression for each confirmed gesture fix, when the project's test runner can drive input
|
||||||
- Visual regression tests
|
- Visual regression tests
|
||||||
- Accessibility tests (axe, WAVE)
|
- Accessibility tests (axe, WAVE)
|
||||||
|
|
||||||
@@ -330,7 +336,10 @@ Test thoroughly with edge cases:
|
|||||||
- **Network issues**: Disable internet, throttle connection
|
- **Network issues**: Disable internet, throttle connection
|
||||||
- **Large datasets**: Test with 1000+ items
|
- **Large datasets**: Test with 1000+ items
|
||||||
- **Concurrent actions**: Click submit 10 times rapidly
|
- **Concurrent actions**: Click submit 10 times rapidly
|
||||||
|
- **Interrupted gestures**: Add a second finger mid-drag, scroll across the control, release outside it, switch windows mid-drag; then drag again
|
||||||
- **Errors**: Force API errors, test all error states
|
- **Errors**: Force API errors, test all error states
|
||||||
- **Empty**: Remove all data, test empty states
|
- **Empty**: Remove all data, test empty states
|
||||||
|
|
||||||
|
For gestures, say what produced the evidence (emulated viewport, synthesized touch, which engine, physical device) and name what stayed untested.
|
||||||
|
|
||||||
When edge cases are covered, hand off to `/impeccable polish` for the final pass.
|
When edge cases are covered, hand off to `/impeccable polish` for the final pass.
|
||||||
|
|||||||
@@ -42,6 +42,8 @@ On every boot the project is scanned for HTML files under common page roots (`pu
|
|||||||
|
|
||||||
## CSP detection (first-time only)
|
## CSP detection (first-time only)
|
||||||
|
|
||||||
|
Keep all allowances below development-only, including manual middleware and meta-tag edits. Do not change a deployed production site's CSP to load the localhost helper; see [live.md](live.md) for production inspection alternatives.
|
||||||
|
|
||||||
If `config.cspChecked === true`, skip this whole section; the user was already asked once.
|
If `config.cspChecked === true`, skip this whole section; the user was already asked once.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ Interactive live variant mode: select elements in the browser, pick a design act
|
|||||||
|
|
||||||
A running dev server with HMR (Vite, Next.js, Bun, etc.), OR a static HTML file open in the browser. If the dev server's default port is busy, the app is very likely ALREADY running; probe the default URL before spawning a second server.
|
A running dev server with HMR (Vite, Next.js, Bun, etc.), OR a static HTML file open in the browser. If the dev server's default port is busy, the app is very likely ALREADY running; probe the default URL before spawning a second server.
|
||||||
|
|
||||||
|
Live editing requires a local checkout; injection into deployed production sites (including HTTPS) is unsupported. For production inspection, use `.claude/skills/impeccable/scripts/impeccable detect <url>` or the browser extension, not the live helper. Do not disable browser security or weaken production CSP to enable live mode.
|
||||||
|
|
||||||
## The contract (read once)
|
## The contract (read once)
|
||||||
|
|
||||||
Execute in order. No step skipped, no step reordered. Every tool output in live mode may carry an `_instructions` field: it is the authoritative next step for that exact situation, with real ids and paths substituted; when it conflicts with your recollection of this document, `_instructions` wins.
|
Execute in order. No step skipped, no step reordered. Every tool output in live mode may carry an `_instructions` field: it is the authoritative next step for that exact situation, with real ids and paths substituted; when it conflicts with your recollection of this document, `_instructions` wins.
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ A section, component, feature, or state inside an established surface inherits t
|
|||||||
|
|
||||||
## 2. Ask what will change the work
|
## 2. Ask what will change the work
|
||||||
|
|
||||||
Ask one round of two or three related questions through the structured question tool when available. Skip settled facts; a precise request may need only a compact confirmation.
|
Before implementation, get the user's answer through the structured question tool when available. Ask two or three related questions; a precise request needs only a compact confirmation. Skip settled facts, not the confirmation: DESIGN.md settles the visual world, not this surface's purpose or concept.
|
||||||
|
|
||||||
- **Persuade:** who must act, what they should believe, which real proof, content, or assets earn that belief.
|
- **Persuade:** who must act, what they should believe, which real proof, content, or assets earn that belief.
|
||||||
- **Operate:** the task, information, important states, frequency, constraints.
|
- **Operate:** the task, information, important states, frequency, constraints.
|
||||||
@@ -70,7 +70,7 @@ Your measured rendition prior: warm, bookish, family, and child-facing subjects
|
|||||||
|
|
||||||
## 5. Record the decision
|
## 5. Record the decision
|
||||||
|
|
||||||
Before code, record the chosen direction as a development-only contract under `## Direction contract` in the relevant surface brief. A direction contract is durable route or artifact strategy, so create or update the brief even when no other surface strategy needs persistence. Keep the contract to six short blocks and 150 words at most. THESIS: the one idea this surface owns and the category-default arrangement it refuses. OWN-WORLD: the palette and component language, specific enough to be recognizable with all content removed. STORY: what the visitor understands, believes, and does. FIRST VIEWPORT: the exact composition, what is where and at what scale, and where the primary action sits. FORM: the chosen form, its position on your ordered list, and the seed key the script printed. Close with one more line, FINISH: the run's exit condition, verbatim "unreviewed and undocumented is unfinished; this build ends with the finish review, the verdict, DESIGN.md, and every shipping raster carrying its provenance". The surface brief is the reminder later agents reload across edits and sessions: a page that looks complete with the FINISH line undischarged is not done, it is abandoned at the finish line. If a block reads like a mood, the direction is not decided yet; the finishing review audits the render against this contract.
|
Before code, record the chosen direction as a development-only contract under `## Direction contract` in the relevant surface brief. A direction contract is durable route or artifact strategy, so create or update the brief even when no other surface strategy needs persistence. Use six short blocks, roughly 150 words; do not spend tool calls counting words. THESIS: the one idea this surface owns and the category-default arrangement it refuses. OWN-WORLD: the palette and component language, specific enough to be recognizable with all content removed. STORY: what the visitor understands, believes, and does. FIRST VIEWPORT: the exact composition, what is where and at what scale, and where the primary action sits. FORM: the chosen form, its position on your ordered list, and the seed key the script printed. Close with one more line, FINISH: the run's exit condition, verbatim "unreviewed and undocumented is unfinished; this build ends with the finish review, the verdict, DESIGN.md, and every shipping raster carrying its provenance". The surface brief is the reminder later agents reload across edits and sessions: a page that looks complete with the FINISH line undischarged is not done, it is abandoned at the finish line. If a block reads like a mood, the direction is not decided yet; the finishing review audits the render against this contract.
|
||||||
|
|
||||||
Never copy the direction contract into implementation source or any browser-delivered artifact. This includes HTML or framework comments, hidden DOM, `<template>` elements, `data-*` attributes, rendered JSX or TSX output, serialized props or state, React Server Component payloads, client bundles, metadata or JSON-LD, accessibility-only text, and files served beside the artifact. A compiler or optimizer removing development metadata is not a safety boundary. Reviewers and documenters receive the contract from the surface brief.
|
Never copy the direction contract into implementation source or any browser-delivered artifact. This includes HTML or framework comments, hidden DOM, `<template>` elements, `data-*` attributes, rendered JSX or TSX output, serialized props or state, React Server Component payloads, client bundles, metadata or JSON-LD, accessibility-only text, and files served beside the artifact. A compiler or optimizer removing development metadata is not a safety boundary. Reviewers and documenters receive the contract from the surface brief.
|
||||||
|
|
||||||
@@ -106,7 +106,7 @@ Then, in order, each closed by `.claude/skills/impeccable/scripts/impeccable bui
|
|||||||
The comp-led path is a frontier-tier job: it asks the builder to hold a measured layout, place plates at their boxes, and act on numeric readings across a dozen attempts. Smaller or faster models produce a recognisable page and stall under the hero gate; if the model in hand is one of those, say so before the direction round and take the code-led path, or expect the run to end at the hero with its readings unmet.
|
The comp-led path is a frontier-tier job: it asks the builder to hold a measured layout, place plates at their boxes, and act on numeric readings across a dozen attempts. Smaller or faster models produce a recognisable page and stall under the hero gate; if the model in hand is one of those, say so before the direction round and take the code-led path, or expect the run to end at the hero with its readings unmet.
|
||||||
|
|
||||||
1. **spec.** Measure the comp: `impeccable comp-spec --comp <comp> --grid` writes a coordinate grid over the comp; open it, name every salient region by grid span in a regions file (text and control regions snap to the largest ink mass inside their span, so a headline named B1:E4 measures as the headline and not the column beside it; `snap: false` keeps the span, and an explicit `box` is taken as drawn) (kind `plate` / `image` / `texture` for anything painted: every illustration, photograph, figure, product object, and material texture; `text` / `control` / `chrome` for what code draws; every region carries a `note` saying what the comp shows there, which the plate prompt and the gate messages read), and run `impeccable comp-spec --comp <comp> --regions <file>`. The spec carries each region's box, sampled palette, and medium; `impeccable comp-spec --print` is the build's reference from here on. Type is measured, not guessed: `impeccable font-match --measure <text region>` reads the comp's cap height, width class, and weight off the pixels, and `impeccable font-match --rank <region> --text "..."` takes its candidates from a fingerprint index of the Google Fonts catalog (the nearest faces to the crop's shape) plus any names you pass with `--candidates`, renders them at that cap height with the region's words, and ranks them by fingerprint distance (its `USE` line is the CSS; its proof sheet shows the comp over the top three); with no browser resolvable it records the catalog's nearest face and says the size is estimated, which is still the choice to build on. Do not install a browser to rank, and never write a `chosen` face into the spec by hand: the gate accepts only what font-match wrote. The spec gate refuses to close until the lead text region is measured and ranked. A region note that describes painted material (a diagram, drawing, photograph, texture) under a code kind is refused at the spec: reclassify it as a plate, or reword the note if code really draws it. The script refuses a regions file that leaves comp ink unnamed (callouts, a parts table, a notes block): what is never named can never be missing, so everything the comp shows gets a region. It also refuses a `text` / `control` / `chrome` region larger than a quarter of the comp: that is a column, not an element, and a column scored as one region hides the plates, tables, and notes inside it. Name each element inside it (`container: true` only when it truly is one undivided element). Anything drawn is a plate: an inline SVG past an icon's budget (a diagram, notation, leader lines with arrows, a "quick approximation" of the artwork) is refused at the hero; icon-sized SVG (under 64px, a few paths) is fine, and a chart the page draws from data at runtime is a chart, not an illustration. Callout lines and arrows that annotate a drawing belong to that drawing's plate, with only their labels set as text. A crop of the comp is never a plate (the plates gate refuses a file that is a resample of the comp region: the comp's grain, its neighbours' edges, and its resolution would ship as the artwork); the crop is the reference the plate is generated from. A plate region's box has to hold its whole artwork with a margin: the spec measures the artwork's contact with the box edges and refuses a box that cuts through it (`bleed: true` only when the page really crops it there), because a plate placed with `object-fit: cover` on such a box shows the artwork minus the side the box lost. Anything not in the spec does not exist on the page: no borders, rules, containers, or chrome the comp does not show. Only three concessions exist: fonts (the closest obtainable face), icon glyphs (close enough, exact if the user chose an icon library; this covers the pictogram only, never a control's chrome, so a chevron, an arrow, a dropdown's border and fill, a button's shape are the comp's), and genuine defects in the comp such as spelling errors.
|
1. **spec.** Measure the comp: `impeccable comp-spec --comp <comp> --grid` writes a coordinate grid over the comp; open it, name every salient region by grid span in a regions file (text and control regions snap to the largest ink mass inside their span, so a headline named B1:E4 measures as the headline and not the column beside it; `snap: false` keeps the span, and an explicit `box` is taken as drawn) (kind `plate` / `image` / `texture` for anything painted: every illustration, photograph, figure, product object, and material texture; `text` / `control` / `chrome` for what code draws; every region carries a `note` saying what the comp shows there, which the plate prompt and the gate messages read), and run `impeccable comp-spec --comp <comp> --regions <file>`. The spec carries each region's box, sampled palette, and medium; `impeccable comp-spec --print` is the build's reference from here on. Type is measured, not guessed: `impeccable font-match --measure <text region>` reads the comp's cap height, width class, and weight off the pixels, and `impeccable font-match --rank <region> --text "..."` takes its candidates from a fingerprint index of the Google Fonts catalog (the nearest faces to the crop's shape) plus any names you pass with `--candidates`, renders them at that cap height with the region's words, and ranks them by fingerprint distance (its `USE` line is the CSS; its proof sheet shows the comp over the top three); with no browser resolvable it records the catalog's nearest face and says the size is estimated, which is still the choice to build on. Do not install a browser to rank, and never write a `chosen` face into the spec by hand: the gate accepts only what font-match wrote. The spec gate refuses to close until the lead text region is measured and ranked. A region note that describes painted material (a diagram, drawing, photograph, texture) under a code kind is refused at the spec: reclassify it as a plate, or reword the note if code really draws it. The script refuses a regions file that leaves comp ink unnamed (callouts, a parts table, a notes block): what is never named can never be missing, so everything the comp shows gets a region. It also refuses a `text` / `control` / `chrome` region larger than a quarter of the comp: that is a column, not an element, and a column scored as one region hides the plates, tables, and notes inside it. Name each element inside it (`container: true` only when it truly is one undivided element). Anything drawn is a plate: an inline SVG past an icon's budget (a diagram, notation, leader lines with arrows, a "quick approximation" of the artwork) is refused at the hero; icon-sized SVG (under 64px, a few paths) is fine, and a chart the page draws from data at runtime is a chart, not an illustration. Callout lines and arrows that annotate a drawing belong to that drawing's plate, with only their labels set as text. A crop of the comp is never a plate (the plates gate refuses a file that is a resample of the comp region: the comp's grain, its neighbours' edges, and its resolution would ship as the artwork); the crop is the reference the plate is generated from. A plate region's box has to hold its whole artwork with a margin: the spec measures the artwork's contact with the box edges and refuses a box that cuts through it (`bleed: true` only when the page really crops it there), because a plate placed with `object-fit: cover` on such a box shows the artwork minus the side the box lost. Anything not in the spec does not exist on the page: no borders, rules, containers, or chrome the comp does not show. Only three concessions exist: fonts (the closest obtainable face), icon glyphs (close enough, exact if the user chose an icon library; this covers the pictogram only, never a control's chrome, so a chevron, an arrow, a dropdown's border and fill, a button's shape are the comp's), and genuine defects in the comp such as spelling errors.
|
||||||
2. **plates.** Every raster region ships as a plate: an illustration, photo, or figure regenerated at asset resolution from its comp crop, UI text removed, at its `plate` path (ink on flat ground is generated on a chroma key and keyed to alpha, so it sits on the page's own ground rather than a second paper); a texture (paper, cloth, grain) is a clean patch of the comp region mirror-tiled to size, generated only when no clean patch exists. `impeccable generate-image --plate <id>` does one region end to end and scores it against the crop; a harness-native image tool takes the crop (`impeccable comp-spec --crop <id>`) as its input image and `impeccable comp-spec --plate-prompt <id>` as its prompt, then `impeccable embed-prompt`. With parallel subagents, spawn the shipped asset producer (`impeccable-asset-producer`; `impeccable_asset_producer` in codex; `/impeccable-asset-producer` in Cursor; on GitHub Copilot say "Use the impeccable-asset-producer agent") with the spec path and let it produce them all; without subagents, produce them here. A crop of the comp is a reference, never a shipping pixel. The gate checks every plate exists, is at least 1.5x the region's size, and reads as the region. Page code waits for this gate: a page written before its plates exist is a page that draws its material in CSS. A single-file deliverable changes nothing here: the plate is produced the same way and inlined as a data URI. `--force` exists for one case only, the user downgrading the comp's authority in words you quote in `--reason`; the script refuses every other reason.
|
2. **plates.** Every raster region ships as a plate: an illustration, photo, or figure regenerated at asset resolution from its comp crop, UI text removed, at its `plate` path (isolated ink, figures, or objects use native transparent PNG so they sit on the page's own ground; photos and textures stay opaque); a texture (paper, cloth, grain) is a clean patch of the comp region mirror-tiled to size, generated only when no clean patch exists. `impeccable comp-spec --crop <id>` writes the reference; save `impeccable comp-spec --plate-prompt <id> --background transparent` to a prompt file for a cutout, or use `--background opaque` otherwise. Prefer the harness-native image tool with that crop and prompt, then `impeccable embed-prompt <plate> --prompt-file <prompt.txt>`. The API fallback is `impeccable generate-image --ref <crop.png> --prompt-file <prompt.txt> --out <plate.png> --size <WxH> --quality high --background transparent` (use `--background opaque` for full-frame assets); create the output directory first. Verify actual alpha, white foregrounds, fine edges, and clear holes on light and dark grounds; do not chroma-key native output. The plates gate scores the assets against the comp; also inspect placement and scale visually. With parallel subagents, spawn the shipped asset producer (`impeccable-asset-producer`; `impeccable_asset_producer` in codex; `/impeccable-asset-producer` in Cursor; on GitHub Copilot say "Use the impeccable-asset-producer agent") with the spec path and let it produce them all; without subagents, produce them here. A crop of the comp is a reference, never a shipping pixel. The gate checks every plate exists, is at least 1.5x the region's size, and reads as the region. Page code waits for this gate: a page written before its plates exist is a page that draws its material in CSS. A single-file deliverable changes nothing here: the plate is produced the same way and inlined as a data URI. `--force` exists for one case only, the user downgrading the comp's authority in words you quote in `--reason`; the script refuses every other reason.
|
||||||
3. **hero.** `impeccable build-phase scaffold` first: it writes the measured layout as CSS custom properties (`.impeccable/build/scaffold/layout.css`: `--r-<id>-x/y/w/h` in % of the comp, plus cap height, font-size, family, and weight where measured) and a reference page (`hero-reference.html`) with every region at its box and every plate placed. Bind the numbers to your own semantic structure, an element per region; the reference is a check on positions, never the page, and overlapping boxes are overlapping boxes. Then build only the first viewport, at the comp's own dimensions, the comp's words copied verbatim (the user approved that comp with those words; rewording is a stated decision after the hero passes, never a silent one inside it), every text region sized from its measured cap height and set in its ranked face, plates first: place every plate at its spec box (`object-fit: cover`, an `<img>`, a background image, or an inlined data URI named for it) before any text or control, capture into `.impeccable/review/hero-repro.png`, run `impeccable build-phase record hero` once so you see the plate regions read as match before any text exists, then lay the semantic layer over the plates from the spec's palette and boxes and advance. The gate first refuses while any plate is unreferenced by the source, then runs `impeccable comp-diff`, writes `.impeccable/review/diff/hero/` (side-by-side, heatmap, one paired crop per region, `report.json`), and passes at 72% overall with no hard veto outstanding (a missing region, a contradicted plate or text block, an SVG illustration, a clipped plate, invented ink block at any score); above the bar, the numeric readings become advisories printed with the pass, and the polish pass before responsive is where they get fixed: the gate also reads each text region's cap height, line count, weight, ink colour, and position against the comp, each chrome strip's height off its rule, and the frame for ink where the comp is calm (a kicker, an extra nav item, a divider), and says each miss as a number ("cap height 78px in the build, 103px in the comp"); those numbers are the edit. When it fails, open the region crops it lists, in order, before editing: a region scored `missing` needs its material, `contradicted` needs its structure re-derived from the spec box, `drift` is where size and spacing edits belong; the gate refuses a third attempt that only nudges values on the same region. This is where the run's ambition is won or lost, and a retry here costs minutes where a rebuild verdict at the finish costs the run.
|
3. **hero.** `impeccable build-phase scaffold` first: it writes the measured layout as CSS custom properties (`.impeccable/build/scaffold/layout.css`: `--r-<id>-x/y/w/h` in % of the comp, plus cap height, font-size, family, and weight where measured) and a reference page (`hero-reference.html`) with every region at its box and every plate placed. Bind the numbers to your own semantic structure, an element per region; the reference is a check on positions, never the page, and overlapping boxes are overlapping boxes. Then build only the first viewport, at the comp's own dimensions, the comp's words copied verbatim (the user approved that comp with those words; rewording is a stated decision after the hero passes, never a silent one inside it), every text region sized from its measured cap height and set in its ranked face, plates first: place every plate at its spec box (`object-fit: cover`, an `<img>`, a background image, or an inlined data URI named for it) before any text or control, capture into `.impeccable/review/hero-repro.png`, run `impeccable build-phase record hero` once so you see the plate regions read as match before any text exists, then lay the semantic layer over the plates from the spec's palette and boxes and advance. The gate first refuses while any plate is unreferenced by the source, then runs `impeccable comp-diff`, writes `.impeccable/review/diff/hero/` (side-by-side, heatmap, one paired crop per region, `report.json`), and passes at 72% overall with no hard veto outstanding (a missing region, a contradicted plate or text block, an SVG illustration, a clipped plate, invented ink block at any score); above the bar, the numeric readings become advisories printed with the pass, and the polish pass before responsive is where they get fixed: the gate also reads each text region's cap height, line count, weight, ink colour, and position against the comp, each chrome strip's height off its rule, and the frame for ink where the comp is calm (a kicker, an extra nav item, a divider), and says each miss as a number ("cap height 78px in the build, 103px in the comp"); those numbers are the edit. When it fails, open the region crops it lists, in order, before editing: a region scored `missing` needs its material, `contradicted` needs its structure re-derived from the spec box, `drift` is where size and spacing edits belong; the gate refuses a third attempt that only nudges values on the same region. This is where the run's ambition is won or lost, and a retry here costs minutes where a rebuild verdict at the finish costs the run.
|
||||||
4. **sections.** Build the rest of the surface inside the spec's system: the same corner language, line weights, and palette, and nothing the comp never shows. Where the comp does not cover a region, it inherits the recorded system.
|
4. **sections.** Build the rest of the surface inside the spec's system: the same corner language, line weights, and palette, and nothing the comp never shows. Where the comp does not cover a region, it inherits the recorded system.
|
||||||
5. **motion.** The signature interaction, reveals, and motion, orchestrated once rather than scattered.
|
5. **motion.** The signature interaction, reveals, and motion, orchestrated once rather than scattered.
|
||||||
@@ -144,4 +144,4 @@ A rebuild and a fix round share one asset rule: a raster either round creates or
|
|||||||
|
|
||||||
Report the final verdict under the reviewer's own disposition word and at its actual scope. A verdict pass scores the listed fixes and nothing else: "the reviewer scored all three fixes resolved" is a claim it supports, "no material issues remain" is not. A table with open material findings is never announced as a pass, never softened, and never dressed as whole-surface approval when only a fix list was scored. When the user answers a ship with evidence against it, their own screenshot, a named mismatch with the comp, that evidence outranks every capture you made: put their material in the packet and spawn a fresh reviewer for a new full review. Patching inline and self-certifying is how a rejected page ships twice.
|
Report the final verdict under the reviewer's own disposition word and at its actual scope. A verdict pass scores the listed fixes and nothing else: "the reviewer scored all three fixes resolved" is a claim it supports, "no material issues remain" is not. A table with open material findings is never announced as a pass, never softened, and never dressed as whole-surface approval when only a fix list was scored. When the user answers a ship with evidence against it, their own screenshot, a named mismatch with the comp, that evidence outranks every capture you made: put their material in the packet and spawn a fresh reviewer for a new full review. Patching inline and self-certifying is how a rejected page ships twice.
|
||||||
|
|
||||||
Then spawn the shipped documenter, `impeccable-documenter` (`impeccable_documenter` in codex), with the project root, the artifact path, the direction contract, PRODUCT.md, the [document.md](document.md) reference path, and the boundary to write at; it records DESIGN.md and the sidecar from the built world, ground truth over intention; without subagents the pass runs from [degraded/documenter.md](degraded/documenter.md). The documenter runs after the last correction lands: when any fix round follows the documentation, re-run the documenter over the changed surface, because a DESIGN.md describing a layout that no longer exists turns defects into system guidance. A clean detector pass is not finished; finished is the contract kept, the comp honored, the review closed, and the system recorded.
|
After the last correction, spawn the shipped documenter, `impeccable-documenter` (`impeccable_documenter` in codex), with the project root, artifact path, direction contract, PRODUCT.md, [document.md](document.md), and write boundary. Without subagents, load [degraded/documenter.md](degraded/documenter.md) and [document.md](document.md) before writing. Verify the outcome: new worlds and approved system changes require token-bearing DESIGN.md **and** `.impeccable/design.json`, not prose alone. Ordinary extensions compare the finished build against the incumbent system, preserve its files, and report the evidence checked; report pre-existing drift without repairing it unasked. Recheck after later edits. Finish only when review and documentation are complete.
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ What the comp shows is measured, not remembered. new-work.md section 6 runs the
|
|||||||
|
|
||||||
## Plates and provenance
|
## Plates and provenance
|
||||||
|
|
||||||
Every raster region's plate is produced in the plates phase, before any page code, by the shipped asset producer or in the current thread (`impeccable generate-image --plate <id>`, or the harness image tool with the crop as input and the spec's plate prompt). Generation context is part of the asset: after generating any image with any tool, run `.claude/skills/impeccable/scripts/impeccable embed-prompt <image> --prompt "<prompt>"` with the exact string the tool received (`impeccable generate-image` does this itself), so the intent lives inside the file; `--read` recovers it, `--scan <dir>` lists rasters still missing one. The embedded prompt plus the region's row in the spec is the raster's **provenance**, and every raster the artifact references carries it; a sourced, stock, or pre-existing raster embeds its origin instead. A raster created or replaced later, in a fix batch or a reviewer's rebuild, is produced the same way; a raster a fix abandons is deleted in the same batch.
|
Every raster region's plate is produced in the plates phase, before any page code, by the shipped asset producer or in the current thread (use `impeccable comp-spec --crop <id>` and save `impeccable comp-spec --plate-prompt <id>` to a prompt file; pass the crop and prompt to the harness image tool, or use `impeccable generate-image --ref <crop.png> --prompt-file <prompt.txt> --out <plate.png> --size <WxH> --quality high`). For isolated cutouts, add `--background transparent` to both the plate-prompt and API generation commands; use native PNG alpha and preserve white paint and clear gaps. Use `--background opaque` for full-frame imagery. Create output directories first and inspect alpha on light and dark grounds. Generation context is part of the asset: after generating any image with any tool, run `.claude/skills/impeccable/scripts/impeccable embed-prompt <image> --prompt "<prompt>"` with the exact string the tool received (`impeccable generate-image` does this itself), so the intent lives inside the file; `--read` recovers it, `--scan <dir>` lists rasters still missing one. The embedded prompt plus the region's row in the spec is the raster's **provenance**, and every raster the artifact references carries it; a sourced, stock, or pre-existing raster embeds its origin instead. A raster created or replaced later, in a fix batch or a reviewer's rebuild, is produced the same way; a raster a fix abandons is deleted in the same batch.
|
||||||
|
|
||||||
Convert images with a converter `impeccable context` reported at boot (the IMAGE_TOOLS line); probe only when it reported none, at most once per session, never per image.
|
Convert images with a converter `impeccable context` reported at boot (the IMAGE_TOOLS line); probe only when it reported none, at most once per session, never per image.
|
||||||
|
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
0.1.3
|
0.1.5
|
||||||
|
|||||||
@@ -87,6 +87,11 @@ fi
|
|||||||
# Last resort: fetch this version's binary for the current platform from the
|
# Last resort: fetch this version's binary for the current platform from the
|
||||||
# public release channel into the user cache. Needs network; sandboxes without
|
# public release channel into the user cache. Needs network; sandboxes without
|
||||||
# egress preinstall the binary on PATH instead.
|
# egress preinstall the binary on PATH instead.
|
||||||
|
setup_help() {
|
||||||
|
echo "Engine $version setup needs network access and write permission to $cache_root/bin/$version." >&2
|
||||||
|
echo "Run this launcher ($0) with engine-probe in a terminal that has those permissions, then retry the original command." >&2
|
||||||
|
echo "Alternatively, set IMPECCABLE_HOME to a writable cache location, or IMPECCABLE_BIN to a preinstalled engine binary." >&2
|
||||||
|
}
|
||||||
fetch_url() {
|
fetch_url() {
|
||||||
if command -v curl >/dev/null 2>&1; then
|
if command -v curl >/dev/null 2>&1; then
|
||||||
curl -fsSL --retry 2 -o "$tmp" "$1" 2>/dev/null
|
curl -fsSL --retry 2 -o "$tmp" "$1" 2>/dev/null
|
||||||
@@ -119,7 +124,18 @@ if [ -n "$version" ] && [ "$os" != unknown ] && [ "$arch" != unknown ]; then
|
|||||||
[ "$os" = windows ] && asset="$asset.exe"
|
[ "$os" = windows ] && asset="$asset.exe"
|
||||||
url="$base/engine-v$version/$asset"
|
url="$base/engine-v$version/$asset"
|
||||||
tmp="$cache_root/bin/$version/.impeccable.part.$$"
|
tmp="$cache_root/bin/$version/.impeccable.part.$$"
|
||||||
mkdir -p "$cache_root/bin/$version" 2>/dev/null
|
if ! mkdir -p "$cache_root/bin/$version" 2>/dev/null; then
|
||||||
|
echo "impeccable: engine $version is not installed; cannot create cache directory: $cache_root/bin/$version" >&2
|
||||||
|
setup_help
|
||||||
|
exit 127
|
||||||
|
fi
|
||||||
|
# Check the actual staging file, not just directory existence: a cache from
|
||||||
|
# an earlier run can be readable but no longer writable inside a sandbox.
|
||||||
|
if ! (umask 077; : > "$tmp") 2>/dev/null; then
|
||||||
|
echo "impeccable: engine $version is not installed; cannot write to cache directory: $cache_root/bin/$version" >&2
|
||||||
|
setup_help
|
||||||
|
exit 127
|
||||||
|
fi
|
||||||
fetched=0
|
fetched=0
|
||||||
if fetch_url "$url"; then
|
if fetch_url "$url"; then
|
||||||
fetched=1
|
fetched=1
|
||||||
@@ -180,6 +196,9 @@ if [ -n "$version" ] && [ "$os" != unknown ] && [ "$arch" != unknown ]; then
|
|||||||
exec "$cached" "$@"
|
exec "$cached" "$@"
|
||||||
fi
|
fi
|
||||||
rm -f "$tmp" 2>/dev/null
|
rm -f "$tmp" 2>/dev/null
|
||||||
|
echo "impeccable: could not download engine $version from $url; check network access, the release URL, and curl or wget availability." >&2
|
||||||
|
setup_help
|
||||||
|
exit 127
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "impeccable: no engine binary for $os-$arch found (looked in $bin, $cached, PATH)." >&2
|
echo "impeccable: no engine binary for $os-$arch found (looked in $bin, $cached, PATH)." >&2
|
||||||
|
|||||||
@@ -68,18 +68,27 @@ rem another launcher's probe: fail fast and quiet instead.
|
|||||||
if defined IMPECCABLE_LAUNCHER_PROBE exit /b 127
|
if defined IMPECCABLE_LAUNCHER_PROBE exit /b 127
|
||||||
if not defined version goto fail
|
if not defined version goto fail
|
||||||
where curl.exe >nul 2>nul
|
where curl.exe >nul 2>nul
|
||||||
if errorlevel 1 goto fail
|
if errorlevel 1 goto curl_missing
|
||||||
if not defined IMPECCABLE_DOWNLOAD_BASE set "IMPECCABLE_DOWNLOAD_BASE=https://github.com/pbakaus/impeccable/releases/download"
|
if not defined IMPECCABLE_DOWNLOAD_BASE set "IMPECCABLE_DOWNLOAD_BASE=https://github.com/pbakaus/impeccable/releases/download"
|
||||||
if not exist "%IMPECCABLE_HOME%\bin\%version%" mkdir "%IMPECCABLE_HOME%\bin\%version%" >nul 2>nul
|
if exist "%IMPECCABLE_HOME%\bin\%version%\" goto cache_ready
|
||||||
|
mkdir "%IMPECCABLE_HOME%\bin\%version%" >nul 2>nul
|
||||||
|
if errorlevel 1 goto cache_directory_failed
|
||||||
|
:cache_ready
|
||||||
|
rem Check the staging file too: an existing directory may be read-only.
|
||||||
|
rem Redirection failures do not reliably update ERRORLEVEL in cmd.exe;
|
||||||
|
rem branch on the command's failure directly. Never treat a directory as a
|
||||||
|
rem staging file (later del cleanup would prompt to delete its contents).
|
||||||
|
if exist "%cached%.part\" goto cache_write_failed
|
||||||
|
(type nul >"%cached%.part") 2>nul || goto cache_write_failed
|
||||||
set "asset=impeccable-windows-%arch%.exe"
|
set "asset=impeccable-windows-%arch%.exe"
|
||||||
set "url=%IMPECCABLE_DOWNLOAD_BASE%/engine-v%version%/%asset%"
|
set "url=%IMPECCABLE_DOWNLOAD_BASE%/engine-v%version%/%asset%"
|
||||||
curl.exe -fsSL -o "%cached%.part" "%url%" >nul 2>nul
|
curl.exe -fsSL -o "%cached%.part" "%url%" >nul 2>nul
|
||||||
if not errorlevel 1 goto verify
|
if not errorlevel 1 goto verify
|
||||||
if not "%arch%"=="arm64" goto fail
|
if not "%arch%"=="arm64" goto download_failed
|
||||||
set "asset=impeccable-windows-x64.exe"
|
set "asset=impeccable-windows-x64.exe"
|
||||||
set "url=%IMPECCABLE_DOWNLOAD_BASE%/engine-v%version%/%asset%"
|
set "url=%IMPECCABLE_DOWNLOAD_BASE%/engine-v%version%/%asset%"
|
||||||
curl.exe -fsSL -o "%cached%.part" "%url%" >nul 2>nul
|
curl.exe -fsSL -o "%cached%.part" "%url%" >nul 2>nul
|
||||||
if errorlevel 1 goto fail
|
if errorlevel 1 goto download_failed
|
||||||
|
|
||||||
:verify
|
:verify
|
||||||
call :check_download
|
call :check_download
|
||||||
@@ -176,6 +185,28 @@ if not errorlevel 1 set "probe_ok=1"
|
|||||||
del "%probe_tmp%" >nul 2>nul
|
del "%probe_tmp%" >nul 2>nul
|
||||||
exit /b 0
|
exit /b 0
|
||||||
|
|
||||||
|
:cache_directory_failed
|
||||||
|
echo impeccable: engine %version% is not installed; cannot create cache directory: "%IMPECCABLE_HOME%\bin\%version%" 1>&2
|
||||||
|
goto setup_failed
|
||||||
|
|
||||||
|
:cache_write_failed
|
||||||
|
echo impeccable: engine %version% is not installed; cannot write to cache directory: "%IMPECCABLE_HOME%\bin\%version%" 1>&2
|
||||||
|
goto setup_failed
|
||||||
|
|
||||||
|
:curl_missing
|
||||||
|
echo impeccable: cannot download engine %version%; curl.exe is unavailable. 1>&2
|
||||||
|
goto setup_failed
|
||||||
|
|
||||||
|
:download_failed
|
||||||
|
del "%cached%.part" >nul 2>nul
|
||||||
|
echo impeccable: could not download engine %version% from %url%; check network access and the release URL. 1>&2
|
||||||
|
|
||||||
|
:setup_failed
|
||||||
|
echo Engine %version% setup needs network access and write permission to "%IMPECCABLE_HOME%\bin\%version%". 1>&2
|
||||||
|
echo Run this launcher ("%~f0") with engine-probe in a terminal that has those permissions, then retry the original command. 1>&2
|
||||||
|
echo Alternatively, set IMPECCABLE_HOME to a writable cache location, or IMPECCABLE_BIN to a preinstalled engine binary. 1>&2
|
||||||
|
exit /b 127
|
||||||
|
|
||||||
:fail
|
:fail
|
||||||
del "%cached%.part" >nul 2>nul
|
del "%cached%.part" >nul 2>nul
|
||||||
echo impeccable: no engine binary found (looked in %bin%, %cached%, PATH). 1>&2
|
echo impeccable: no engine binary found (looked in %bin%, %cached%, PATH). 1>&2
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"name": "impeccable",
|
||||||
|
"owner": { "name": "Renaissance Geek, Inc." },
|
||||||
|
"metadata": { "description": "Impeccable design tools for Cursor" },
|
||||||
|
"plugins": [{ "name": "impeccable", "source": "./cursor-plugin" }]
|
||||||
|
}
|
||||||
@@ -29,12 +29,12 @@ Every region with `medium: raster` in the spec ships as a plate at its `plate` p
|
|||||||
Per region, in the spec's order:
|
Per region, in the spec's order:
|
||||||
|
|
||||||
1. `.cursor/skills/impeccable/scripts/impeccable comp-spec --crop <id>` writes the reference crop under `.impeccable/build/crops/`.
|
1. `.cursor/skills/impeccable/scripts/impeccable comp-spec --crop <id>` writes the reference crop under `.impeccable/build/crops/`.
|
||||||
2. Produce the plate. With the API fallback: `.cursor/skills/impeccable/scripts/impeccable generate-image --plate <id> --quality high` does the whole step (crop as reference, the spec's plate prompt, output size chosen from the region's aspect, the file written to its plate path, prompt embedded, and the plate scored against the crop). With a harness-native image tool: use the crop as the input image and `.cursor/skills/impeccable/scripts/impeccable comp-spec --plate-prompt <id>` as the prompt, write the result to the plate path, then run `.cursor/skills/impeccable/scripts/impeccable embed-prompt <plate> --prompt "<the exact prompt>"`.
|
2. Choose the background from the approved region: an isolated figure, object, or line drawing on the page ground is a **transparent cutout**; a photograph, full-frame illustration, or texture stays **opaque**. Save `.cursor/skills/impeccable/scripts/impeccable comp-spec --plate-prompt <id> --background transparent` to a UTF-8 prompt file for a cutout; use `--background opaque` otherwise. The transparent prompt preserves reference placement and clear margins, white paint, fine edges, and interior holes.
|
||||||
3. Read the score line. `PLATE-SCORE` under 50%, or a `PLATE-WARN`, means the plate does not read as the region: open the plate beside the crop, name what drifted (subject, framing, palette, style), tighten the prompt with that, and regenerate once. Two misses on one region: keep the better plate, mark it `needs_parent_review`, and say why in one line.
|
3. Produce the plate at its exact spec `plate` path. Create the output directory first and choose a supported output size matching the region's aspect, at least 1.5x its pixel dimensions. Prefer the harness-native image tool with the crop as input and the saved prompt; request a transparent PNG for cutouts, then run `.cursor/skills/impeccable/scripts/impeccable embed-prompt <plate> --prompt-file <prompt.txt>` (if you refine the prompt, save and embed the exact text sent). With the API fallback, run `.cursor/skills/impeccable/scripts/impeccable generate-image --ref <crop.png> --prompt-file <prompt.txt> --out <plate.png> --size <WxH> --quality high --background transparent` for a cutout, or `--background opaque` otherwise. The API fallback embeds the prompt and records the background in the sidecar. The output must be PNG; the fallback requests native alpha and performs no chroma-keying.
|
||||||
4. Transparent cutouts (a figure or object on the page ground): generate on a flat chroma color absent from the subject and key it to alpha before writing the PNG; never ship the keyed background.
|
4. Open the plate beside the crop and compare subject, placement, scale, palette, and style. For cutouts, verify a real alpha channel and inspect composites on light and dark grounds: white paint must stay solid, interior holes must clear, and fine edges must avoid halos. Inspect glass and soft shadows carefully; partial alpha alone does not ensure convincing translucency. Never chroma-key native transparent output or flatten it before saving. If a native tool returns opaque pixels or a painted checkerboard, retry with the API fallback when available; otherwise report the transparency blocker. On a visual miss, tighten the prompt and regenerate once. Two misses on one region: keep the better plate, mark it `needs_parent_review`, and name the drift. The parent runs the plates gate after all assets exist; report `unscored` until a gate score is available.
|
||||||
|
|
||||||
Do not redesign. Do not add objects, restyle, or reinterpret; the comp was approved as it is. Do not touch the page code, the spec, or the comp. Do not produce anything the spec does not list; a region the parent forgot goes back as a one-line note, not a plate.
|
Do not redesign. Do not add objects, restyle, or reinterpret; the comp was approved as it is. Do not touch the page code, the spec, or the comp. Do not produce anything the spec does not list; a region the parent forgot goes back as a one-line note, not a plate.
|
||||||
|
|
||||||
## Output Contract
|
## Output Contract
|
||||||
|
|
||||||
Return one line per raster region: `<id> <plate path> <WxH> <score>% <accepted|needs_parent_review|blocked> <one-line note or ->`. Then `blockers` (missing spec, missing comp, no image capability, exhausted key) and `assumptions`, each global and minimal. Nothing else: no summary, no praise, no implementation advice. The parent runs `impeccable build-phase advance` to verify the plates against the same spec; your line and its line must agree.
|
Return one line per raster region: `<id> <plate path> <WxH> <score%|unscored> <accepted|needs_parent_review|blocked> <one-line note or ->`. Then `blockers` (missing spec, missing comp, no image capability, exhausted key) and `assumptions`, each global and minimal. Nothing else: no summary, no praise, no implementation advice. The parent runs `impeccable build-phase advance` to verify the plates against the same spec; a visual acceptance does not override a failing gate.
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ is_background: false
|
|||||||
|
|
||||||
You record a project's design system after the build is done. Ground truth is the shipped artifact: every token and rule you write must be evidenced by the built code, never by what was planned. Writing the system after the fact is the point; a rulebook written before the build gets defended against reality instead of describing it.
|
You record a project's design system after the build is done. Ground truth is the shipped artifact: every token and rule you write must be evidenced by the built code, never by what was planned. Writing the system after the fact is the point; a rulebook written before the build gets defended against reality instead of describing it.
|
||||||
|
|
||||||
You run under a hard turn ceiling that ends the run without warning, and a run that ends before DESIGN.md is written has recorded nothing. Batch several Reads into each turn, take `reference/document.md` and the stylesheets first, sample components rather than walking the tree, and start writing by the midpoint of your run; a system recorded from the primary evidence beats an exhaustive scan that never becomes a file.
|
Complete the check within your turn ceiling. Batch Reads, take `reference/document.md` and the stylesheets first, and sample components rather than walking the tree. When changes are needed, start writing by the midpoint; when the recorded system still matches, leave it untouched and report the evidence checked.
|
||||||
|
|
||||||
## Input Contract
|
## Input Contract
|
||||||
|
|
||||||
@@ -18,10 +18,10 @@ Expect: the project root; the artifact path(s); the direction contract text (THE
|
|||||||
|
|
||||||
1. Read `reference/document.md` in full; it is the operating spec for DESIGN.md's format, token schema, sidecar, and section order. Follow it exactly.
|
1. Read `reference/document.md` in full; it is the operating spec for DESIGN.md's format, token schema, sidecar, and section order. Follow it exactly.
|
||||||
2. Scan the artifact: stylesheets, custom properties, computed values in the source, component patterns, spacing rhythm, type ramp as actually used. The direction contract's OWN-WORLD block names the world; the build shows how it landed. Where they diverge, the build wins and the prose may note the divergence.
|
2. Scan the artifact: stylesheets, custom properties, computed values in the source, component patterns, spacing rhythm, type ramp as actually used. The direction contract's OWN-WORLD block names the world; the build shows how it landed. Where they diverge, the build wins and the prose may note the divergence.
|
||||||
3. Write DESIGN.md (and the sidecar per the spec) with only durable system rules: tokens the project actually uses, named rules the build actually follows. Skip one-off values; a token used once is not a system.
|
3. For a new world or approved system change, write DESIGN.md and its sidecar from durable, reused rules in the build. Ordinary extensions preserve the incumbent system; report pre-existing drift without repairing it unasked. Do not write merely to prove this pass ran.
|
||||||
4. Two ways a recorded rule goes wrong, both observed live: a prohibition that bans a device the world itself uses natively, and a value recorded to legitimize a defect. Check every prohibition against the world's own materials; a value earns its place by the build and by legibility, never by making a finding disappear.
|
4. Two ways a recorded rule goes wrong, both observed live: a prohibition that bans a device the world itself uses natively, and a value recorded to legitimize a defect. Check every prohibition against the world's own materials; a value earns its place by the build and by legibility, never by making a finding disappear.
|
||||||
5. Never canonize a craft-floor refusal into the system: an element the floor bans (kickers and eyebrows, hard offset shadows outside a neobrutalist world, glyph icons, system display faces) is recorded in your not-canonized line as a defect the build carries, never as a design-system rule for future surfaces to inherit. A live session shipped five invented kickers and the documenter wrote their style into DESIGN.md; that is how one violation becomes the house style.
|
5. Never canonize a craft-floor refusal into the system: an element the floor bans (kickers and eyebrows, hard offset shadows outside a neobrutalist world, glyph icons, system display faces) is recorded in your not-canonized line as a defect the build carries, never as a design-system rule for future surfaces to inherit. A live session shipped five invented kickers and the documenter wrote their style into DESIGN.md; that is how one violation becomes the house style.
|
||||||
|
|
||||||
## Output Contract
|
## Output Contract
|
||||||
|
|
||||||
Return: the file paths written, a five-line summary of the recorded system (palette strategy, type ramp shape, named rules), and one line naming anything in the build you deliberately did not canonize and why. No other prose.
|
Return: paths written, or “No changes” with the source and system files checked; a five-line system summary (palette, type ramp, named rules); and one line naming defects or drift not canonized or repaired, and why. No other prose.
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
name: impeccable
|
name: impeccable
|
||||||
description: Use when the user wants to design, redesign, shape, critique, audit, polish, clarify, distill, harden, optimize, adapt, animate, colorize, extract, or otherwise improve a frontend interface. Covers websites, landing pages, dashboards, product UI, app shells, components, forms, settings, onboarding, and empty states. Handles UX review, visual hierarchy, information architecture, cognitive load, accessibility, performance, responsive behavior, theming, anti-patterns, typography, fonts, spacing, layout, alignment, color, motion, micro-interactions, UX copy, error states, edge cases, i18n, and reusable design systems or tokens. Also use for bland designs that need to become bolder or more delightful, loud designs that should become quieter, live browser iteration on UI elements, or ambitious visual effects that should feel technically extraordinary. Not for backend-only or non-UI tasks.
|
description: Use when the user wants to design, redesign, shape, critique, audit, polish, clarify, distill, harden, optimize, adapt, animate, colorize, extract, or otherwise improve a frontend interface. Covers websites, landing pages, dashboards, product UI, app shells, components, forms, settings, onboarding, and empty states. Handles UX review, visual hierarchy, information architecture, cognitive load, accessibility, performance, responsive behavior, theming, anti-patterns, typography, fonts, spacing, layout, alignment, color, motion, micro-interactions, UX copy, error states, edge cases, i18n, and reusable design systems or tokens. Also use for bland designs that need to become bolder or more delightful, loud designs that should become quieter, live browser iteration on UI elements, or ambitious visual effects that should feel technically extraordinary. Not for backend-only or non-UI tasks.
|
||||||
version: 4.2.2
|
version: 4.3.1
|
||||||
license: Apache 2.0
|
license: Apache 2.0
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -14,9 +14,11 @@ Core principles:
|
|||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
1. Run `<skill-base-dir>/scripts/impeccable context` once per session, where `<skill-base-dir>` is the directory that contains this SKILL.md (the skill folder, not a plugin root two levels above it); keep cwd at the user's project. That base directory resolves every `.cursor/skills/impeccable/scripts/impeccable <verb>` command in this skill and its references, and `.cursor/skills/impeccable/scripts` is the fallback only when the runtime reports no base directory. On a Windows shell without `sh`, call `.cursor/skills/impeccable/scripts/impeccable.cmd` instead. The launcher runs a self-contained binary that ships next to it or is downloaded once on first run; no Node or other runtime is required. Pass a named source file or route as `--target <path>`. It loads PRODUCT.md, DESIGN.md, the matching surface brief, and native-platform guidance when applicable; follow its directives and do not rerun it. If the launcher is refused, missing, or fails, tell the user before editing that context loading did not run. Read existing **PRODUCT.md** and **DESIGN.md** without inventing missing context, then continue with steps 2–3.
|
1. Run `<skill-base-dir>/scripts/impeccable context` once per session, where `<skill-base-dir>` is the directory that contains this SKILL.md (the skill folder, not a plugin root two levels above it); keep cwd at the user's project. That base directory resolves every `.cursor/skills/impeccable/scripts/impeccable <verb>` command in this skill and its references, and `.cursor/skills/impeccable/scripts` is the fallback only when the runtime reports no base directory. On a Windows shell without `sh`, call `.cursor/skills/impeccable/scripts/impeccable.cmd` instead. The launcher runs a self-contained binary that ships next to it or is downloaded once on first run; no Node or other runtime is required. Pass a named source file or route as `--target <path>`. It loads PRODUCT.md, DESIGN.md, the matching surface brief, and native-platform guidance when applicable; follow its directives and do not rerun it.
|
||||||
2. Load the request's playbook: its Commands-table reference for an explicit/implied sub-command, or [reference/new-work.md](reference/new-work.md) for a new surface or replacement visual world. Inspect target and incumbent visual truth before editing. When the app cannot run, start with committed visual-regression goldens or screenshot fixtures; verify target and freshness against current tokens, CSS, components, or assets, resolve conflicts, and compare theme/variant captures.
|
2. Load the request's playbook: its Commands-table reference for an explicit/implied sub-command, or [reference/new-work.md](reference/new-work.md) for a new surface or replacement visual world. Inspect target and incumbent visual truth before editing. When the app cannot run, start with committed visual-regression goldens or screenshot fixtures; verify target and freshness against current tokens, CSS, components, or assets, resolve conflicts, and compare theme/variant captures.
|
||||||
3. After analysis and direction are resolved, load [reference/craft-floor.md](reference/craft-floor.md) immediately before editing UI. It carries the quality floor, the absolute bans, and the reflexes no detector catches. Do not load it for planning-only work.
|
3. After resolving analysis and direction, read [reference/craft-floor.md](reference/craft-floor.md) immediately before any UI edit, including small refinements. It carries the quality floor, the absolute bans, and the reflexes no detector catches. Do not load it for planning-only work.
|
||||||
|
|
||||||
|
**Launcher unavailable:** On refusal or failure, send a separate message **before the next tool call**: “Context loading did not run; I’ll read the existing project context directly.” Then read existing PRODUCT.md and DESIGN.md without inventing missing context, follow applicable steps 2–3, and continue through permitted tools. This applies to planning and editing; launcher failure alone does not block either.
|
||||||
|
|
||||||
## How to design
|
## How to design
|
||||||
|
|
||||||
|
|||||||
@@ -188,6 +188,12 @@ Test thoroughly across contexts:
|
|||||||
- **Edge cases**: Very small screens (320px), very large screens (4K)
|
- **Edge cases**: Very small screens (320px), very large screens (4K)
|
||||||
- **Slow connections**: Test on throttled network
|
- **Slow connections**: Test on throttled network
|
||||||
|
|
||||||
|
**Custom controls** (sliders, drag surfaces, scrollable control strips): a before/after slider can pass every width check above and still refuse to drag on iOS, so exercise each one in scope in the same batched round as the checks above:
|
||||||
|
|
||||||
|
- **Primary gesture**: Tap it and confirm it responds as designed, then drag it with the target input method; the drag must complete, not just start
|
||||||
|
- **Scroll across it**: A swipe along the page's scroll axis across the control scrolls the page or container without activating it; a drag that starts on the control along its axis moves the control, not the page. Neither failure throws an error, so try both
|
||||||
|
- **Evidence**: Say what produced the evidence: an emulated viewport, synthesized touch input through a browser tool, which engine ran it (Chromium is not Safari), or a physical device. Screenshots and resized viewports verify layout, never a gesture. Name what stayed untested and move on; unreachable hardware is a reported gap, not a blocker
|
||||||
|
|
||||||
When the adaptation feels native to each context, hand off to `/impeccable polish` for the final pass.
|
When the adaptation feels native to each context, hand off to `/impeccable polish` for the final pass.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -48,11 +48,12 @@ Run comprehensive checks across 5 dimensions. Score each dimension 0-4 using the
|
|||||||
**Check for**:
|
**Check for**:
|
||||||
- **Fixed widths**: Hard-coded widths that break on mobile
|
- **Fixed widths**: Hard-coded widths that break on mobile
|
||||||
- **Touch targets**: Interactive elements < 44x44px
|
- **Touch targets**: Interactive elements < 44x44px
|
||||||
|
- **Broken touch interaction**: Custom sliders, drag surfaces, and scrollable control strips whose primary gesture fails under touch, that swallow page scroll or lose the drag to it, or that stay stuck after an interrupted gesture. Code tells: mouse-only handlers, no `touch-action` on a pointer-event drag surface, drag state that nothing clears on cancel, lost capture, or blur. Exercise the gesture when a browser tool can synthesize touch (a rendered viewport proves layout, not the gesture), then say what produced the evidence (emulated viewport, synthesized touch, which engine, physical device) and what stayed untested
|
||||||
- **Horizontal scroll**: Content overflow on narrow viewports
|
- **Horizontal scroll**: Content overflow on narrow viewports
|
||||||
- **Text scaling**: Layouts that break when text size increases
|
- **Text scaling**: Layouts that break when text size increases
|
||||||
- **Missing breakpoints**: No mobile/tablet variants
|
- **Missing breakpoints**: No mobile/tablet variants
|
||||||
|
|
||||||
**Score 0-4**: 0=Desktop-only (breaks on mobile), 1=Major issues (some breakpoints, many failures), 2=Partial (works on mobile, rough edges), 3=Good (responsive, minor touch target or overflow issues), 4=Excellent (fluid, all viewports, proper touch targets)
|
**Score 0-4**: 0=Desktop-only (breaks on mobile), 1=Major issues (some breakpoints, many failures), 2=Partial (works on mobile, rough edges), 3=Good (responsive, minor touch target or overflow issues), 4=Excellent (fluid, all viewports, proper touch targets, gestures work under touch)
|
||||||
|
|
||||||
### 5. Implementation Integrity (CRITICAL)
|
### 5. Implementation Integrity (CRITICAL)
|
||||||
|
|
||||||
|
|||||||
@@ -26,12 +26,12 @@ Every region with `medium: raster` in the spec ships as a plate at its `plate` p
|
|||||||
Per region, in the spec's order:
|
Per region, in the spec's order:
|
||||||
|
|
||||||
1. `.cursor/skills/impeccable/scripts/impeccable comp-spec --crop <id>` writes the reference crop under `.impeccable/build/crops/`.
|
1. `.cursor/skills/impeccable/scripts/impeccable comp-spec --crop <id>` writes the reference crop under `.impeccable/build/crops/`.
|
||||||
2. Produce the plate. With the API fallback: `.cursor/skills/impeccable/scripts/impeccable generate-image --plate <id> --quality high` does the whole step (crop as reference, the spec's plate prompt, output size chosen from the region's aspect, the file written to its plate path, prompt embedded, and the plate scored against the crop). With a harness-native image tool: use the crop as the input image and `.cursor/skills/impeccable/scripts/impeccable comp-spec --plate-prompt <id>` as the prompt, write the result to the plate path, then run `.cursor/skills/impeccable/scripts/impeccable embed-prompt <plate> --prompt "<the exact prompt>"`.
|
2. Choose the background from the approved region: an isolated figure, object, or line drawing on the page ground is a **transparent cutout**; a photograph, full-frame illustration, or texture stays **opaque**. Save `.cursor/skills/impeccable/scripts/impeccable comp-spec --plate-prompt <id> --background transparent` to a UTF-8 prompt file for a cutout; use `--background opaque` otherwise. The transparent prompt preserves reference placement and clear margins, white paint, fine edges, and interior holes.
|
||||||
3. Read the score line. `PLATE-SCORE` under 50%, or a `PLATE-WARN`, means the plate does not read as the region: open the plate beside the crop, name what drifted (subject, framing, palette, style), tighten the prompt with that, and regenerate once. Two misses on one region: keep the better plate, mark it `needs_parent_review`, and say why in one line.
|
3. Produce the plate at its exact spec `plate` path. Create the output directory first and choose a supported output size matching the region's aspect, at least 1.5x its pixel dimensions. Prefer the harness-native image tool with the crop as input and the saved prompt; request a transparent PNG for cutouts, then run `.cursor/skills/impeccable/scripts/impeccable embed-prompt <plate> --prompt-file <prompt.txt>` (if you refine the prompt, save and embed the exact text sent). With the API fallback, run `.cursor/skills/impeccable/scripts/impeccable generate-image --ref <crop.png> --prompt-file <prompt.txt> --out <plate.png> --size <WxH> --quality high --background transparent` for a cutout, or `--background opaque` otherwise. The API fallback embeds the prompt and records the background in the sidecar. The output must be PNG; the fallback requests native alpha and performs no chroma-keying.
|
||||||
4. Transparent cutouts (a figure or object on the page ground): generate on a flat chroma color absent from the subject and key it to alpha before writing the PNG; never ship the keyed background.
|
4. Open the plate beside the crop and compare subject, placement, scale, palette, and style. For cutouts, verify a real alpha channel and inspect composites on light and dark grounds: white paint must stay solid, interior holes must clear, and fine edges must avoid halos. Inspect glass and soft shadows carefully; partial alpha alone does not ensure convincing translucency. Never chroma-key native transparent output or flatten it before saving. If a native tool returns opaque pixels or a painted checkerboard, retry with the API fallback when available; otherwise report the transparency blocker. On a visual miss, tighten the prompt and regenerate once. Two misses on one region: keep the better plate, mark it `needs_parent_review`, and name the drift. The parent runs the plates gate after all assets exist; report `unscored` until a gate score is available.
|
||||||
|
|
||||||
Do not redesign. Do not add objects, restyle, or reinterpret; the comp was approved as it is. Do not touch the page code, the spec, or the comp. Do not produce anything the spec does not list; a region the parent forgot goes back as a one-line note, not a plate.
|
Do not redesign. Do not add objects, restyle, or reinterpret; the comp was approved as it is. Do not touch the page code, the spec, or the comp. Do not produce anything the spec does not list; a region the parent forgot goes back as a one-line note, not a plate.
|
||||||
|
|
||||||
## Output Contract
|
## Output Contract
|
||||||
|
|
||||||
Return one line per raster region: `<id> <plate path> <WxH> <score>% <accepted|needs_parent_review|blocked> <one-line note or ->`. Then `blockers` (missing spec, missing comp, no image capability, exhausted key) and `assumptions`, each global and minimal. Nothing else: no summary, no praise, no implementation advice. The parent runs `impeccable build-phase advance` to verify the plates against the same spec; your line and its line must agree.
|
Return one line per raster region: `<id> <plate path> <WxH> <score%|unscored> <accepted|needs_parent_review|blocked> <one-line note or ->`. Then `blockers` (missing spec, missing comp, no image capability, exhausted key) and `assumptions`, each global and minimal. Nothing else: no summary, no praise, no implementation advice. The parent runs `impeccable build-phase advance` to verify the plates against the same spec; a visual acceptance does not override a failing gate.
|
||||||
@@ -5,7 +5,7 @@ This harness has no subagent capability, so you are running this role inline. St
|
|||||||
|
|
||||||
You record a project's design system after the build is done. Ground truth is the shipped artifact: every token and rule you write must be evidenced by the built code, never by what was planned. Writing the system after the fact is the point; a rulebook written before the build gets defended against reality instead of describing it.
|
You record a project's design system after the build is done. Ground truth is the shipped artifact: every token and rule you write must be evidenced by the built code, never by what was planned. Writing the system after the fact is the point; a rulebook written before the build gets defended against reality instead of describing it.
|
||||||
|
|
||||||
You run under a hard turn ceiling that ends the run without warning, and a run that ends before DESIGN.md is written has recorded nothing. Batch several Reads into each turn, take `reference/document.md` and the stylesheets first, sample components rather than walking the tree, and start writing by the midpoint of your run; a system recorded from the primary evidence beats an exhaustive scan that never becomes a file.
|
Complete the check within your turn ceiling. Batch Reads, take `reference/document.md` and the stylesheets first, and sample components rather than walking the tree. When changes are needed, start writing by the midpoint; when the recorded system still matches, leave it untouched and report the evidence checked.
|
||||||
|
|
||||||
## Input Contract
|
## Input Contract
|
||||||
|
|
||||||
@@ -15,10 +15,10 @@ Expect: the project root; the artifact path(s); the direction contract text (THE
|
|||||||
|
|
||||||
1. Read `reference/document.md` in full; it is the operating spec for DESIGN.md's format, token schema, sidecar, and section order. Follow it exactly.
|
1. Read `reference/document.md` in full; it is the operating spec for DESIGN.md's format, token schema, sidecar, and section order. Follow it exactly.
|
||||||
2. Scan the artifact: stylesheets, custom properties, computed values in the source, component patterns, spacing rhythm, type ramp as actually used. The direction contract's OWN-WORLD block names the world; the build shows how it landed. Where they diverge, the build wins and the prose may note the divergence.
|
2. Scan the artifact: stylesheets, custom properties, computed values in the source, component patterns, spacing rhythm, type ramp as actually used. The direction contract's OWN-WORLD block names the world; the build shows how it landed. Where they diverge, the build wins and the prose may note the divergence.
|
||||||
3. Write DESIGN.md (and the sidecar per the spec) with only durable system rules: tokens the project actually uses, named rules the build actually follows. Skip one-off values; a token used once is not a system.
|
3. For a new world or approved system change, write DESIGN.md and its sidecar from durable, reused rules in the build. Ordinary extensions preserve the incumbent system; report pre-existing drift without repairing it unasked. Do not write merely to prove this pass ran.
|
||||||
4. Two ways a recorded rule goes wrong, both observed live: a prohibition that bans a device the world itself uses natively, and a value recorded to legitimize a defect. Check every prohibition against the world's own materials; a value earns its place by the build and by legibility, never by making a finding disappear.
|
4. Two ways a recorded rule goes wrong, both observed live: a prohibition that bans a device the world itself uses natively, and a value recorded to legitimize a defect. Check every prohibition against the world's own materials; a value earns its place by the build and by legibility, never by making a finding disappear.
|
||||||
5. Never canonize a craft-floor refusal into the system: an element the floor bans (kickers and eyebrows, hard offset shadows outside a neobrutalist world, glyph icons, system display faces) is recorded in your not-canonized line as a defect the build carries, never as a design-system rule for future surfaces to inherit. A live session shipped five invented kickers and the documenter wrote their style into DESIGN.md; that is how one violation becomes the house style.
|
5. Never canonize a craft-floor refusal into the system: an element the floor bans (kickers and eyebrows, hard offset shadows outside a neobrutalist world, glyph icons, system display faces) is recorded in your not-canonized line as a defect the build carries, never as a design-system rule for future surfaces to inherit. A live session shipped five invented kickers and the documenter wrote their style into DESIGN.md; that is how one violation becomes the house style.
|
||||||
|
|
||||||
## Output Contract
|
## Output Contract
|
||||||
|
|
||||||
Return: the file paths written, a five-line summary of the recorded system (palette strategy, type ramp shape, named rules), and one line naming anything in the build you deliberately did not canonize and why. No other prose.
|
Return: paths written, or “No changes” with the source and system files checked; a five-line system summary (palette, type ramp, named rules); and one line naming defects or drift not canonized or repaired, and why. No other prose.
|
||||||
@@ -205,6 +205,11 @@ t('items', { count }) // Handles complex plural rules
|
|||||||
- Optimistic updates with rollback
|
- Optimistic updates with rollback
|
||||||
- Conflict resolution
|
- Conflict resolution
|
||||||
|
|
||||||
|
**Interrupted gestures** (custom sliders, drag surfaces, scrollable control strips):
|
||||||
|
- A second finger or pointer lands mid-drag: the first drag keeps its pointer or ends cleanly, never jumps to the new one
|
||||||
|
- The browser cancels the gesture to scroll (`pointercancel`), capture is lost (`lostpointercapture`), the pointer is released outside the control, or the window loses focus (`blur`) mid-drag: clear the dragging state and release capture
|
||||||
|
- After each of these, the next tap or drag works without a reload
|
||||||
|
|
||||||
**Permission states**:
|
**Permission states**:
|
||||||
- No permission to view
|
- No permission to view
|
||||||
- No permission to edit
|
- No permission to edit
|
||||||
@@ -304,6 +309,7 @@ const throttledScroll = throttle(handleScroll, 100);
|
|||||||
- Unit tests for edge cases
|
- Unit tests for edge cases
|
||||||
- Integration tests for error scenarios
|
- Integration tests for error scenarios
|
||||||
- E2E tests for critical paths
|
- E2E tests for critical paths
|
||||||
|
- A behavioral regression for each confirmed gesture fix, when the project's test runner can drive input
|
||||||
- Visual regression tests
|
- Visual regression tests
|
||||||
- Accessibility tests (axe, WAVE)
|
- Accessibility tests (axe, WAVE)
|
||||||
|
|
||||||
@@ -330,7 +336,10 @@ Test thoroughly with edge cases:
|
|||||||
- **Network issues**: Disable internet, throttle connection
|
- **Network issues**: Disable internet, throttle connection
|
||||||
- **Large datasets**: Test with 1000+ items
|
- **Large datasets**: Test with 1000+ items
|
||||||
- **Concurrent actions**: Click submit 10 times rapidly
|
- **Concurrent actions**: Click submit 10 times rapidly
|
||||||
|
- **Interrupted gestures**: Add a second finger mid-drag, scroll across the control, release outside it, switch windows mid-drag; then drag again
|
||||||
- **Errors**: Force API errors, test all error states
|
- **Errors**: Force API errors, test all error states
|
||||||
- **Empty**: Remove all data, test empty states
|
- **Empty**: Remove all data, test empty states
|
||||||
|
|
||||||
|
For gestures, say what produced the evidence (emulated viewport, synthesized touch, which engine, physical device) and name what stayed untested.
|
||||||
|
|
||||||
When edge cases are covered, hand off to `/impeccable polish` for the final pass.
|
When edge cases are covered, hand off to `/impeccable polish` for the final pass.
|
||||||
|
|||||||
@@ -42,6 +42,8 @@ On every boot the project is scanned for HTML files under common page roots (`pu
|
|||||||
|
|
||||||
## CSP detection (first-time only)
|
## CSP detection (first-time only)
|
||||||
|
|
||||||
|
Keep all allowances below development-only, including manual middleware and meta-tag edits. Do not change a deployed production site's CSP to load the localhost helper; see [live.md](live.md) for production inspection alternatives.
|
||||||
|
|
||||||
If `config.cspChecked === true`, skip this whole section; the user was already asked once.
|
If `config.cspChecked === true`, skip this whole section; the user was already asked once.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ Interactive live variant mode: select elements in the browser, pick a design act
|
|||||||
|
|
||||||
A running dev server with HMR (Vite, Next.js, Bun, etc.), OR a static HTML file open in the browser. If the dev server's default port is busy, the app is very likely ALREADY running; probe the default URL before spawning a second server.
|
A running dev server with HMR (Vite, Next.js, Bun, etc.), OR a static HTML file open in the browser. If the dev server's default port is busy, the app is very likely ALREADY running; probe the default URL before spawning a second server.
|
||||||
|
|
||||||
|
Live editing requires a local checkout; injection into deployed production sites (including HTTPS) is unsupported. For production inspection, use `.cursor/skills/impeccable/scripts/impeccable detect <url>` or the browser extension, not the live helper. Do not disable browser security or weaken production CSP to enable live mode.
|
||||||
|
|
||||||
## The contract (read once)
|
## The contract (read once)
|
||||||
|
|
||||||
Execute in order. No step skipped, no step reordered. Every tool output in live mode may carry an `_instructions` field: it is the authoritative next step for that exact situation, with real ids and paths substituted; when it conflicts with your recollection of this document, `_instructions` wins.
|
Execute in order. No step skipped, no step reordered. Every tool output in live mode may carry an `_instructions` field: it is the authoritative next step for that exact situation, with real ids and paths substituted; when it conflicts with your recollection of this document, `_instructions` wins.
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ A section, component, feature, or state inside an established surface inherits t
|
|||||||
|
|
||||||
## 2. Ask what will change the work
|
## 2. Ask what will change the work
|
||||||
|
|
||||||
Ask one round of two or three related questions through the structured question tool when available. Skip settled facts; a precise request may need only a compact confirmation.
|
Before implementation, get the user's answer through the structured question tool when available. Ask two or three related questions; a precise request needs only a compact confirmation. Skip settled facts, not the confirmation: DESIGN.md settles the visual world, not this surface's purpose or concept.
|
||||||
|
|
||||||
- **Persuade:** who must act, what they should believe, which real proof, content, or assets earn that belief.
|
- **Persuade:** who must act, what they should believe, which real proof, content, or assets earn that belief.
|
||||||
- **Operate:** the task, information, important states, frequency, constraints.
|
- **Operate:** the task, information, important states, frequency, constraints.
|
||||||
@@ -68,7 +68,7 @@ Calibration: AI-generated interfaces cluster around a few looks regardless of su
|
|||||||
|
|
||||||
## 5. Record the decision
|
## 5. Record the decision
|
||||||
|
|
||||||
Before code, record the chosen direction as a development-only contract under `## Direction contract` in the relevant surface brief. A direction contract is durable route or artifact strategy, so create or update the brief even when no other surface strategy needs persistence. Keep the contract to six short blocks and 150 words at most. THESIS: the one idea this surface owns and the category-default arrangement it refuses. OWN-WORLD: the palette and component language, specific enough to be recognizable with all content removed. STORY: what the visitor understands, believes, and does. FIRST VIEWPORT: the exact composition, what is where and at what scale, and where the primary action sits. FORM: the chosen form, its position on your ordered list, and the seed key the script printed. Close with one more line, FINISH: the run's exit condition, verbatim "unreviewed and undocumented is unfinished; this build ends with the finish review, the verdict, DESIGN.md, and every shipping raster carrying its provenance". The surface brief is the reminder later agents reload across edits and sessions: a page that looks complete with the FINISH line undischarged is not done, it is abandoned at the finish line. If a block reads like a mood, the direction is not decided yet; the finishing review audits the render against this contract.
|
Before code, record the chosen direction as a development-only contract under `## Direction contract` in the relevant surface brief. A direction contract is durable route or artifact strategy, so create or update the brief even when no other surface strategy needs persistence. Use six short blocks, roughly 150 words; do not spend tool calls counting words. THESIS: the one idea this surface owns and the category-default arrangement it refuses. OWN-WORLD: the palette and component language, specific enough to be recognizable with all content removed. STORY: what the visitor understands, believes, and does. FIRST VIEWPORT: the exact composition, what is where and at what scale, and where the primary action sits. FORM: the chosen form, its position on your ordered list, and the seed key the script printed. Close with one more line, FINISH: the run's exit condition, verbatim "unreviewed and undocumented is unfinished; this build ends with the finish review, the verdict, DESIGN.md, and every shipping raster carrying its provenance". The surface brief is the reminder later agents reload across edits and sessions: a page that looks complete with the FINISH line undischarged is not done, it is abandoned at the finish line. If a block reads like a mood, the direction is not decided yet; the finishing review audits the render against this contract.
|
||||||
|
|
||||||
Never copy the direction contract into implementation source or any browser-delivered artifact. This includes HTML or framework comments, hidden DOM, `<template>` elements, `data-*` attributes, rendered JSX or TSX output, serialized props or state, React Server Component payloads, client bundles, metadata or JSON-LD, accessibility-only text, and files served beside the artifact. A compiler or optimizer removing development metadata is not a safety boundary. Reviewers and documenters receive the contract from the surface brief.
|
Never copy the direction contract into implementation source or any browser-delivered artifact. This includes HTML or framework comments, hidden DOM, `<template>` elements, `data-*` attributes, rendered JSX or TSX output, serialized props or state, React Server Component payloads, client bundles, metadata or JSON-LD, accessibility-only text, and files served beside the artifact. A compiler or optimizer removing development metadata is not a safety boundary. Reviewers and documenters receive the contract from the surface brief.
|
||||||
|
|
||||||
@@ -104,7 +104,7 @@ Then, in order, each closed by `.cursor/skills/impeccable/scripts/impeccable bui
|
|||||||
The comp-led path is a frontier-tier job: it asks the builder to hold a measured layout, place plates at their boxes, and act on numeric readings across a dozen attempts. Smaller or faster models produce a recognisable page and stall under the hero gate; if the model in hand is one of those, say so before the direction round and take the code-led path, or expect the run to end at the hero with its readings unmet.
|
The comp-led path is a frontier-tier job: it asks the builder to hold a measured layout, place plates at their boxes, and act on numeric readings across a dozen attempts. Smaller or faster models produce a recognisable page and stall under the hero gate; if the model in hand is one of those, say so before the direction round and take the code-led path, or expect the run to end at the hero with its readings unmet.
|
||||||
|
|
||||||
1. **spec.** Measure the comp: `impeccable comp-spec --comp <comp> --grid` writes a coordinate grid over the comp; open it, name every salient region by grid span in a regions file (text and control regions snap to the largest ink mass inside their span, so a headline named B1:E4 measures as the headline and not the column beside it; `snap: false` keeps the span, and an explicit `box` is taken as drawn) (kind `plate` / `image` / `texture` for anything painted: every illustration, photograph, figure, product object, and material texture; `text` / `control` / `chrome` for what code draws; every region carries a `note` saying what the comp shows there, which the plate prompt and the gate messages read), and run `impeccable comp-spec --comp <comp> --regions <file>`. The spec carries each region's box, sampled palette, and medium; `impeccable comp-spec --print` is the build's reference from here on. Type is measured, not guessed: `impeccable font-match --measure <text region>` reads the comp's cap height, width class, and weight off the pixels, and `impeccable font-match --rank <region> --text "..."` takes its candidates from a fingerprint index of the Google Fonts catalog (the nearest faces to the crop's shape) plus any names you pass with `--candidates`, renders them at that cap height with the region's words, and ranks them by fingerprint distance (its `USE` line is the CSS; its proof sheet shows the comp over the top three); with no browser resolvable it records the catalog's nearest face and says the size is estimated, which is still the choice to build on. Do not install a browser to rank, and never write a `chosen` face into the spec by hand: the gate accepts only what font-match wrote. The spec gate refuses to close until the lead text region is measured and ranked. A region note that describes painted material (a diagram, drawing, photograph, texture) under a code kind is refused at the spec: reclassify it as a plate, or reword the note if code really draws it. The script refuses a regions file that leaves comp ink unnamed (callouts, a parts table, a notes block): what is never named can never be missing, so everything the comp shows gets a region. It also refuses a `text` / `control` / `chrome` region larger than a quarter of the comp: that is a column, not an element, and a column scored as one region hides the plates, tables, and notes inside it. Name each element inside it (`container: true` only when it truly is one undivided element). Anything drawn is a plate: an inline SVG past an icon's budget (a diagram, notation, leader lines with arrows, a "quick approximation" of the artwork) is refused at the hero; icon-sized SVG (under 64px, a few paths) is fine, and a chart the page draws from data at runtime is a chart, not an illustration. Callout lines and arrows that annotate a drawing belong to that drawing's plate, with only their labels set as text. A crop of the comp is never a plate (the plates gate refuses a file that is a resample of the comp region: the comp's grain, its neighbours' edges, and its resolution would ship as the artwork); the crop is the reference the plate is generated from. A plate region's box has to hold its whole artwork with a margin: the spec measures the artwork's contact with the box edges and refuses a box that cuts through it (`bleed: true` only when the page really crops it there), because a plate placed with `object-fit: cover` on such a box shows the artwork minus the side the box lost. Anything not in the spec does not exist on the page: no borders, rules, containers, or chrome the comp does not show. Only three concessions exist: fonts (the closest obtainable face), icon glyphs (close enough, exact if the user chose an icon library; this covers the pictogram only, never a control's chrome, so a chevron, an arrow, a dropdown's border and fill, a button's shape are the comp's), and genuine defects in the comp such as spelling errors.
|
1. **spec.** Measure the comp: `impeccable comp-spec --comp <comp> --grid` writes a coordinate grid over the comp; open it, name every salient region by grid span in a regions file (text and control regions snap to the largest ink mass inside their span, so a headline named B1:E4 measures as the headline and not the column beside it; `snap: false` keeps the span, and an explicit `box` is taken as drawn) (kind `plate` / `image` / `texture` for anything painted: every illustration, photograph, figure, product object, and material texture; `text` / `control` / `chrome` for what code draws; every region carries a `note` saying what the comp shows there, which the plate prompt and the gate messages read), and run `impeccable comp-spec --comp <comp> --regions <file>`. The spec carries each region's box, sampled palette, and medium; `impeccable comp-spec --print` is the build's reference from here on. Type is measured, not guessed: `impeccable font-match --measure <text region>` reads the comp's cap height, width class, and weight off the pixels, and `impeccable font-match --rank <region> --text "..."` takes its candidates from a fingerprint index of the Google Fonts catalog (the nearest faces to the crop's shape) plus any names you pass with `--candidates`, renders them at that cap height with the region's words, and ranks them by fingerprint distance (its `USE` line is the CSS; its proof sheet shows the comp over the top three); with no browser resolvable it records the catalog's nearest face and says the size is estimated, which is still the choice to build on. Do not install a browser to rank, and never write a `chosen` face into the spec by hand: the gate accepts only what font-match wrote. The spec gate refuses to close until the lead text region is measured and ranked. A region note that describes painted material (a diagram, drawing, photograph, texture) under a code kind is refused at the spec: reclassify it as a plate, or reword the note if code really draws it. The script refuses a regions file that leaves comp ink unnamed (callouts, a parts table, a notes block): what is never named can never be missing, so everything the comp shows gets a region. It also refuses a `text` / `control` / `chrome` region larger than a quarter of the comp: that is a column, not an element, and a column scored as one region hides the plates, tables, and notes inside it. Name each element inside it (`container: true` only when it truly is one undivided element). Anything drawn is a plate: an inline SVG past an icon's budget (a diagram, notation, leader lines with arrows, a "quick approximation" of the artwork) is refused at the hero; icon-sized SVG (under 64px, a few paths) is fine, and a chart the page draws from data at runtime is a chart, not an illustration. Callout lines and arrows that annotate a drawing belong to that drawing's plate, with only their labels set as text. A crop of the comp is never a plate (the plates gate refuses a file that is a resample of the comp region: the comp's grain, its neighbours' edges, and its resolution would ship as the artwork); the crop is the reference the plate is generated from. A plate region's box has to hold its whole artwork with a margin: the spec measures the artwork's contact with the box edges and refuses a box that cuts through it (`bleed: true` only when the page really crops it there), because a plate placed with `object-fit: cover` on such a box shows the artwork minus the side the box lost. Anything not in the spec does not exist on the page: no borders, rules, containers, or chrome the comp does not show. Only three concessions exist: fonts (the closest obtainable face), icon glyphs (close enough, exact if the user chose an icon library; this covers the pictogram only, never a control's chrome, so a chevron, an arrow, a dropdown's border and fill, a button's shape are the comp's), and genuine defects in the comp such as spelling errors.
|
||||||
2. **plates.** Every raster region ships as a plate: an illustration, photo, or figure regenerated at asset resolution from its comp crop, UI text removed, at its `plate` path (ink on flat ground is generated on a chroma key and keyed to alpha, so it sits on the page's own ground rather than a second paper); a texture (paper, cloth, grain) is a clean patch of the comp region mirror-tiled to size, generated only when no clean patch exists. `impeccable generate-image --plate <id>` does one region end to end and scores it against the crop; a harness-native image tool takes the crop (`impeccable comp-spec --crop <id>`) as its input image and `impeccable comp-spec --plate-prompt <id>` as its prompt, then `impeccable embed-prompt`. With parallel subagents, spawn the shipped asset producer (`impeccable-asset-producer`; `impeccable_asset_producer` in codex; `/impeccable-asset-producer` in Cursor; on GitHub Copilot say "Use the impeccable-asset-producer agent") with the spec path and let it produce them all; without subagents, produce them here. A crop of the comp is a reference, never a shipping pixel. The gate checks every plate exists, is at least 1.5x the region's size, and reads as the region. Page code waits for this gate: a page written before its plates exist is a page that draws its material in CSS. A single-file deliverable changes nothing here: the plate is produced the same way and inlined as a data URI. `--force` exists for one case only, the user downgrading the comp's authority in words you quote in `--reason`; the script refuses every other reason.
|
2. **plates.** Every raster region ships as a plate: an illustration, photo, or figure regenerated at asset resolution from its comp crop, UI text removed, at its `plate` path (isolated ink, figures, or objects use native transparent PNG so they sit on the page's own ground; photos and textures stay opaque); a texture (paper, cloth, grain) is a clean patch of the comp region mirror-tiled to size, generated only when no clean patch exists. `impeccable comp-spec --crop <id>` writes the reference; save `impeccable comp-spec --plate-prompt <id> --background transparent` to a prompt file for a cutout, or use `--background opaque` otherwise. Prefer the harness-native image tool with that crop and prompt, then `impeccable embed-prompt <plate> --prompt-file <prompt.txt>`. The API fallback is `impeccable generate-image --ref <crop.png> --prompt-file <prompt.txt> --out <plate.png> --size <WxH> --quality high --background transparent` (use `--background opaque` for full-frame assets); create the output directory first. Verify actual alpha, white foregrounds, fine edges, and clear holes on light and dark grounds; do not chroma-key native output. The plates gate scores the assets against the comp; also inspect placement and scale visually. With parallel subagents, spawn the shipped asset producer (`impeccable-asset-producer`; `impeccable_asset_producer` in codex; `/impeccable-asset-producer` in Cursor; on GitHub Copilot say "Use the impeccable-asset-producer agent") with the spec path and let it produce them all; without subagents, produce them here. A crop of the comp is a reference, never a shipping pixel. The gate checks every plate exists, is at least 1.5x the region's size, and reads as the region. Page code waits for this gate: a page written before its plates exist is a page that draws its material in CSS. A single-file deliverable changes nothing here: the plate is produced the same way and inlined as a data URI. `--force` exists for one case only, the user downgrading the comp's authority in words you quote in `--reason`; the script refuses every other reason.
|
||||||
3. **hero.** `impeccable build-phase scaffold` first: it writes the measured layout as CSS custom properties (`.impeccable/build/scaffold/layout.css`: `--r-<id>-x/y/w/h` in % of the comp, plus cap height, font-size, family, and weight where measured) and a reference page (`hero-reference.html`) with every region at its box and every plate placed. Bind the numbers to your own semantic structure, an element per region; the reference is a check on positions, never the page, and overlapping boxes are overlapping boxes. Then build only the first viewport, at the comp's own dimensions, the comp's words copied verbatim (the user approved that comp with those words; rewording is a stated decision after the hero passes, never a silent one inside it), every text region sized from its measured cap height and set in its ranked face, plates first: place every plate at its spec box (`object-fit: cover`, an `<img>`, a background image, or an inlined data URI named for it) before any text or control, capture into `.impeccable/review/hero-repro.png`, run `impeccable build-phase record hero` once so you see the plate regions read as match before any text exists, then lay the semantic layer over the plates from the spec's palette and boxes and advance. The gate first refuses while any plate is unreferenced by the source, then runs `impeccable comp-diff`, writes `.impeccable/review/diff/hero/` (side-by-side, heatmap, one paired crop per region, `report.json`), and passes at 72% overall with no hard veto outstanding (a missing region, a contradicted plate or text block, an SVG illustration, a clipped plate, invented ink block at any score); above the bar, the numeric readings become advisories printed with the pass, and the polish pass before responsive is where they get fixed: the gate also reads each text region's cap height, line count, weight, ink colour, and position against the comp, each chrome strip's height off its rule, and the frame for ink where the comp is calm (a kicker, an extra nav item, a divider), and says each miss as a number ("cap height 78px in the build, 103px in the comp"); those numbers are the edit. When it fails, open the region crops it lists, in order, before editing: a region scored `missing` needs its material, `contradicted` needs its structure re-derived from the spec box, `drift` is where size and spacing edits belong; the gate refuses a third attempt that only nudges values on the same region. This is where the run's ambition is won or lost, and a retry here costs minutes where a rebuild verdict at the finish costs the run.
|
3. **hero.** `impeccable build-phase scaffold` first: it writes the measured layout as CSS custom properties (`.impeccable/build/scaffold/layout.css`: `--r-<id>-x/y/w/h` in % of the comp, plus cap height, font-size, family, and weight where measured) and a reference page (`hero-reference.html`) with every region at its box and every plate placed. Bind the numbers to your own semantic structure, an element per region; the reference is a check on positions, never the page, and overlapping boxes are overlapping boxes. Then build only the first viewport, at the comp's own dimensions, the comp's words copied verbatim (the user approved that comp with those words; rewording is a stated decision after the hero passes, never a silent one inside it), every text region sized from its measured cap height and set in its ranked face, plates first: place every plate at its spec box (`object-fit: cover`, an `<img>`, a background image, or an inlined data URI named for it) before any text or control, capture into `.impeccable/review/hero-repro.png`, run `impeccable build-phase record hero` once so you see the plate regions read as match before any text exists, then lay the semantic layer over the plates from the spec's palette and boxes and advance. The gate first refuses while any plate is unreferenced by the source, then runs `impeccable comp-diff`, writes `.impeccable/review/diff/hero/` (side-by-side, heatmap, one paired crop per region, `report.json`), and passes at 72% overall with no hard veto outstanding (a missing region, a contradicted plate or text block, an SVG illustration, a clipped plate, invented ink block at any score); above the bar, the numeric readings become advisories printed with the pass, and the polish pass before responsive is where they get fixed: the gate also reads each text region's cap height, line count, weight, ink colour, and position against the comp, each chrome strip's height off its rule, and the frame for ink where the comp is calm (a kicker, an extra nav item, a divider), and says each miss as a number ("cap height 78px in the build, 103px in the comp"); those numbers are the edit. When it fails, open the region crops it lists, in order, before editing: a region scored `missing` needs its material, `contradicted` needs its structure re-derived from the spec box, `drift` is where size and spacing edits belong; the gate refuses a third attempt that only nudges values on the same region. This is where the run's ambition is won or lost, and a retry here costs minutes where a rebuild verdict at the finish costs the run.
|
||||||
4. **sections.** Build the rest of the surface inside the spec's system: the same corner language, line weights, and palette, and nothing the comp never shows. Where the comp does not cover a region, it inherits the recorded system.
|
4. **sections.** Build the rest of the surface inside the spec's system: the same corner language, line weights, and palette, and nothing the comp never shows. Where the comp does not cover a region, it inherits the recorded system.
|
||||||
5. **motion.** The signature interaction, reveals, and motion, orchestrated once rather than scattered.
|
5. **motion.** The signature interaction, reveals, and motion, orchestrated once rather than scattered.
|
||||||
@@ -142,4 +142,4 @@ A rebuild and a fix round share one asset rule: a raster either round creates or
|
|||||||
|
|
||||||
Report the final verdict under the reviewer's own disposition word and at its actual scope. A verdict pass scores the listed fixes and nothing else: "the reviewer scored all three fixes resolved" is a claim it supports, "no material issues remain" is not. A table with open material findings is never announced as a pass, never softened, and never dressed as whole-surface approval when only a fix list was scored. When the user answers a ship with evidence against it, their own screenshot, a named mismatch with the comp, that evidence outranks every capture you made: put their material in the packet and spawn a fresh reviewer for a new full review. Patching inline and self-certifying is how a rejected page ships twice.
|
Report the final verdict under the reviewer's own disposition word and at its actual scope. A verdict pass scores the listed fixes and nothing else: "the reviewer scored all three fixes resolved" is a claim it supports, "no material issues remain" is not. A table with open material findings is never announced as a pass, never softened, and never dressed as whole-surface approval when only a fix list was scored. When the user answers a ship with evidence against it, their own screenshot, a named mismatch with the comp, that evidence outranks every capture you made: put their material in the packet and spawn a fresh reviewer for a new full review. Patching inline and self-certifying is how a rejected page ships twice.
|
||||||
|
|
||||||
Then spawn the shipped documenter, `impeccable-documenter` (`impeccable_documenter` in codex), with the project root, the artifact path, the direction contract, PRODUCT.md, the [document.md](document.md) reference path, and the boundary to write at; it records DESIGN.md and the sidecar from the built world, ground truth over intention; without subagents the pass runs from [degraded/documenter.md](degraded/documenter.md). The documenter runs after the last correction lands: when any fix round follows the documentation, re-run the documenter over the changed surface, because a DESIGN.md describing a layout that no longer exists turns defects into system guidance. A clean detector pass is not finished; finished is the contract kept, the comp honored, the review closed, and the system recorded.
|
After the last correction, spawn the shipped documenter, `impeccable-documenter` (`impeccable_documenter` in codex), with the project root, artifact path, direction contract, PRODUCT.md, [document.md](document.md), and write boundary. Without subagents, load [degraded/documenter.md](degraded/documenter.md) and [document.md](document.md) before writing. Verify the outcome: new worlds and approved system changes require token-bearing DESIGN.md **and** `.impeccable/design.json`, not prose alone. Ordinary extensions compare the finished build against the incumbent system, preserve its files, and report the evidence checked; report pre-existing drift without repairing it unasked. Recheck after later edits. Finish only when review and documentation are complete.
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ What the comp shows is measured, not remembered. new-work.md section 6 runs the
|
|||||||
|
|
||||||
## Plates and provenance
|
## Plates and provenance
|
||||||
|
|
||||||
Every raster region's plate is produced in the plates phase, before any page code, by the shipped asset producer or in the current thread (`impeccable generate-image --plate <id>`, or the harness image tool with the crop as input and the spec's plate prompt). Generation context is part of the asset: after generating any image with any tool, run `.cursor/skills/impeccable/scripts/impeccable embed-prompt <image> --prompt "<prompt>"` with the exact string the tool received (`impeccable generate-image` does this itself), so the intent lives inside the file; `--read` recovers it, `--scan <dir>` lists rasters still missing one. The embedded prompt plus the region's row in the spec is the raster's **provenance**, and every raster the artifact references carries it; a sourced, stock, or pre-existing raster embeds its origin instead. A raster created or replaced later, in a fix batch or a reviewer's rebuild, is produced the same way; a raster a fix abandons is deleted in the same batch.
|
Every raster region's plate is produced in the plates phase, before any page code, by the shipped asset producer or in the current thread (use `impeccable comp-spec --crop <id>` and save `impeccable comp-spec --plate-prompt <id>` to a prompt file; pass the crop and prompt to the harness image tool, or use `impeccable generate-image --ref <crop.png> --prompt-file <prompt.txt> --out <plate.png> --size <WxH> --quality high`). For isolated cutouts, add `--background transparent` to both the plate-prompt and API generation commands; use native PNG alpha and preserve white paint and clear gaps. Use `--background opaque` for full-frame imagery. Create output directories first and inspect alpha on light and dark grounds. Generation context is part of the asset: after generating any image with any tool, run `.cursor/skills/impeccable/scripts/impeccable embed-prompt <image> --prompt "<prompt>"` with the exact string the tool received (`impeccable generate-image` does this itself), so the intent lives inside the file; `--read` recovers it, `--scan <dir>` lists rasters still missing one. The embedded prompt plus the region's row in the spec is the raster's **provenance**, and every raster the artifact references carries it; a sourced, stock, or pre-existing raster embeds its origin instead. A raster created or replaced later, in a fix batch or a reviewer's rebuild, is produced the same way; a raster a fix abandons is deleted in the same batch.
|
||||||
|
|
||||||
Convert images with a converter `impeccable context` reported at boot (the IMAGE_TOOLS line); probe only when it reported none, at most once per session, never per image.
|
Convert images with a converter `impeccable context` reported at boot (the IMAGE_TOOLS line); probe only when it reported none, at most once per session, never per image.
|
||||||
|
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
0.1.3
|
0.1.5
|
||||||
|
|||||||
@@ -87,6 +87,11 @@ fi
|
|||||||
# Last resort: fetch this version's binary for the current platform from the
|
# Last resort: fetch this version's binary for the current platform from the
|
||||||
# public release channel into the user cache. Needs network; sandboxes without
|
# public release channel into the user cache. Needs network; sandboxes without
|
||||||
# egress preinstall the binary on PATH instead.
|
# egress preinstall the binary on PATH instead.
|
||||||
|
setup_help() {
|
||||||
|
echo "Engine $version setup needs network access and write permission to $cache_root/bin/$version." >&2
|
||||||
|
echo "Run this launcher ($0) with engine-probe in a terminal that has those permissions, then retry the original command." >&2
|
||||||
|
echo "Alternatively, set IMPECCABLE_HOME to a writable cache location, or IMPECCABLE_BIN to a preinstalled engine binary." >&2
|
||||||
|
}
|
||||||
fetch_url() {
|
fetch_url() {
|
||||||
if command -v curl >/dev/null 2>&1; then
|
if command -v curl >/dev/null 2>&1; then
|
||||||
curl -fsSL --retry 2 -o "$tmp" "$1" 2>/dev/null
|
curl -fsSL --retry 2 -o "$tmp" "$1" 2>/dev/null
|
||||||
@@ -119,7 +124,18 @@ if [ -n "$version" ] && [ "$os" != unknown ] && [ "$arch" != unknown ]; then
|
|||||||
[ "$os" = windows ] && asset="$asset.exe"
|
[ "$os" = windows ] && asset="$asset.exe"
|
||||||
url="$base/engine-v$version/$asset"
|
url="$base/engine-v$version/$asset"
|
||||||
tmp="$cache_root/bin/$version/.impeccable.part.$$"
|
tmp="$cache_root/bin/$version/.impeccable.part.$$"
|
||||||
mkdir -p "$cache_root/bin/$version" 2>/dev/null
|
if ! mkdir -p "$cache_root/bin/$version" 2>/dev/null; then
|
||||||
|
echo "impeccable: engine $version is not installed; cannot create cache directory: $cache_root/bin/$version" >&2
|
||||||
|
setup_help
|
||||||
|
exit 127
|
||||||
|
fi
|
||||||
|
# Check the actual staging file, not just directory existence: a cache from
|
||||||
|
# an earlier run can be readable but no longer writable inside a sandbox.
|
||||||
|
if ! (umask 077; : > "$tmp") 2>/dev/null; then
|
||||||
|
echo "impeccable: engine $version is not installed; cannot write to cache directory: $cache_root/bin/$version" >&2
|
||||||
|
setup_help
|
||||||
|
exit 127
|
||||||
|
fi
|
||||||
fetched=0
|
fetched=0
|
||||||
if fetch_url "$url"; then
|
if fetch_url "$url"; then
|
||||||
fetched=1
|
fetched=1
|
||||||
@@ -180,6 +196,9 @@ if [ -n "$version" ] && [ "$os" != unknown ] && [ "$arch" != unknown ]; then
|
|||||||
exec "$cached" "$@"
|
exec "$cached" "$@"
|
||||||
fi
|
fi
|
||||||
rm -f "$tmp" 2>/dev/null
|
rm -f "$tmp" 2>/dev/null
|
||||||
|
echo "impeccable: could not download engine $version from $url; check network access, the release URL, and curl or wget availability." >&2
|
||||||
|
setup_help
|
||||||
|
exit 127
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "impeccable: no engine binary for $os-$arch found (looked in $bin, $cached, PATH)." >&2
|
echo "impeccable: no engine binary for $os-$arch found (looked in $bin, $cached, PATH)." >&2
|
||||||
|
|||||||
@@ -68,18 +68,27 @@ rem another launcher's probe: fail fast and quiet instead.
|
|||||||
if defined IMPECCABLE_LAUNCHER_PROBE exit /b 127
|
if defined IMPECCABLE_LAUNCHER_PROBE exit /b 127
|
||||||
if not defined version goto fail
|
if not defined version goto fail
|
||||||
where curl.exe >nul 2>nul
|
where curl.exe >nul 2>nul
|
||||||
if errorlevel 1 goto fail
|
if errorlevel 1 goto curl_missing
|
||||||
if not defined IMPECCABLE_DOWNLOAD_BASE set "IMPECCABLE_DOWNLOAD_BASE=https://github.com/pbakaus/impeccable/releases/download"
|
if not defined IMPECCABLE_DOWNLOAD_BASE set "IMPECCABLE_DOWNLOAD_BASE=https://github.com/pbakaus/impeccable/releases/download"
|
||||||
if not exist "%IMPECCABLE_HOME%\bin\%version%" mkdir "%IMPECCABLE_HOME%\bin\%version%" >nul 2>nul
|
if exist "%IMPECCABLE_HOME%\bin\%version%\" goto cache_ready
|
||||||
|
mkdir "%IMPECCABLE_HOME%\bin\%version%" >nul 2>nul
|
||||||
|
if errorlevel 1 goto cache_directory_failed
|
||||||
|
:cache_ready
|
||||||
|
rem Check the staging file too: an existing directory may be read-only.
|
||||||
|
rem Redirection failures do not reliably update ERRORLEVEL in cmd.exe;
|
||||||
|
rem branch on the command's failure directly. Never treat a directory as a
|
||||||
|
rem staging file (later del cleanup would prompt to delete its contents).
|
||||||
|
if exist "%cached%.part\" goto cache_write_failed
|
||||||
|
(type nul >"%cached%.part") 2>nul || goto cache_write_failed
|
||||||
set "asset=impeccable-windows-%arch%.exe"
|
set "asset=impeccable-windows-%arch%.exe"
|
||||||
set "url=%IMPECCABLE_DOWNLOAD_BASE%/engine-v%version%/%asset%"
|
set "url=%IMPECCABLE_DOWNLOAD_BASE%/engine-v%version%/%asset%"
|
||||||
curl.exe -fsSL -o "%cached%.part" "%url%" >nul 2>nul
|
curl.exe -fsSL -o "%cached%.part" "%url%" >nul 2>nul
|
||||||
if not errorlevel 1 goto verify
|
if not errorlevel 1 goto verify
|
||||||
if not "%arch%"=="arm64" goto fail
|
if not "%arch%"=="arm64" goto download_failed
|
||||||
set "asset=impeccable-windows-x64.exe"
|
set "asset=impeccable-windows-x64.exe"
|
||||||
set "url=%IMPECCABLE_DOWNLOAD_BASE%/engine-v%version%/%asset%"
|
set "url=%IMPECCABLE_DOWNLOAD_BASE%/engine-v%version%/%asset%"
|
||||||
curl.exe -fsSL -o "%cached%.part" "%url%" >nul 2>nul
|
curl.exe -fsSL -o "%cached%.part" "%url%" >nul 2>nul
|
||||||
if errorlevel 1 goto fail
|
if errorlevel 1 goto download_failed
|
||||||
|
|
||||||
:verify
|
:verify
|
||||||
call :check_download
|
call :check_download
|
||||||
@@ -176,6 +185,28 @@ if not errorlevel 1 set "probe_ok=1"
|
|||||||
del "%probe_tmp%" >nul 2>nul
|
del "%probe_tmp%" >nul 2>nul
|
||||||
exit /b 0
|
exit /b 0
|
||||||
|
|
||||||
|
:cache_directory_failed
|
||||||
|
echo impeccable: engine %version% is not installed; cannot create cache directory: "%IMPECCABLE_HOME%\bin\%version%" 1>&2
|
||||||
|
goto setup_failed
|
||||||
|
|
||||||
|
:cache_write_failed
|
||||||
|
echo impeccable: engine %version% is not installed; cannot write to cache directory: "%IMPECCABLE_HOME%\bin\%version%" 1>&2
|
||||||
|
goto setup_failed
|
||||||
|
|
||||||
|
:curl_missing
|
||||||
|
echo impeccable: cannot download engine %version%; curl.exe is unavailable. 1>&2
|
||||||
|
goto setup_failed
|
||||||
|
|
||||||
|
:download_failed
|
||||||
|
del "%cached%.part" >nul 2>nul
|
||||||
|
echo impeccable: could not download engine %version% from %url%; check network access and the release URL. 1>&2
|
||||||
|
|
||||||
|
:setup_failed
|
||||||
|
echo Engine %version% setup needs network access and write permission to "%IMPECCABLE_HOME%\bin\%version%". 1>&2
|
||||||
|
echo Run this launcher ("%~f0") with engine-probe in a terminal that has those permissions, then retry the original command. 1>&2
|
||||||
|
echo Alternatively, set IMPECCABLE_HOME to a writable cache location, or IMPECCABLE_BIN to a preinstalled engine binary. 1>&2
|
||||||
|
exit /b 127
|
||||||
|
|
||||||
:fail
|
:fail
|
||||||
del "%cached%.part" >nul 2>nul
|
del "%cached%.part" >nul 2>nul
|
||||||
echo impeccable: no engine binary found (looked in %bin%, %cached%, PATH). 1>&2
|
echo impeccable: no engine binary found (looked in %bin%, %cached%, PATH). 1>&2
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
name: impeccable
|
name: impeccable
|
||||||
description: Use when the user wants to design, redesign, shape, critique, audit, polish, clarify, distill, harden, optimize, adapt, animate, colorize, extract, or otherwise improve a frontend interface. Covers websites, landing pages, dashboards, product UI, app shells, components, forms, settings, onboarding, and empty states. Handles UX review, visual hierarchy, information architecture, cognitive load, accessibility, performance, responsive behavior, theming, anti-patterns, typography, fonts, spacing, layout, alignment, color, motion, micro-interactions, UX copy, error states, edge cases, i18n, and reusable design systems or tokens. Also use for bland designs that need to become bolder or more delightful, loud designs that should become quieter, live browser iteration on UI elements, or ambitious visual effects that should feel technically extraordinary. Not for backend-only or non-UI tasks.
|
description: Use when the user wants to design, redesign, shape, critique, audit, polish, clarify, distill, harden, optimize, adapt, animate, colorize, extract, or otherwise improve a frontend interface. Covers websites, landing pages, dashboards, product UI, app shells, components, forms, settings, onboarding, and empty states. Handles UX review, visual hierarchy, information architecture, cognitive load, accessibility, performance, responsive behavior, theming, anti-patterns, typography, fonts, spacing, layout, alignment, color, motion, micro-interactions, UX copy, error states, edge cases, i18n, and reusable design systems or tokens. Also use for bland designs that need to become bolder or more delightful, loud designs that should become quieter, live browser iteration on UI elements, or ambitious visual effects that should feel technically extraordinary. Not for backend-only or non-UI tasks.
|
||||||
version: 4.2.2
|
version: 4.3.1
|
||||||
user-invocable: true
|
user-invocable: true
|
||||||
license: Apache 2.0
|
license: Apache 2.0
|
||||||
---
|
---
|
||||||
@@ -15,9 +15,11 @@ Core principles:
|
|||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
1. Run `<skill-base-dir>/scripts/impeccable context` once per session, where `<skill-base-dir>` is the directory that contains this SKILL.md (the skill folder, not a plugin root two levels above it); keep cwd at the user's project. That base directory resolves every `.dsh/skills/impeccable/scripts/impeccable <verb>` command in this skill and its references, and `.dsh/skills/impeccable/scripts` is the fallback only when the runtime reports no base directory. On a Windows shell without `sh`, call `.dsh/skills/impeccable/scripts/impeccable.cmd` instead. The launcher runs a self-contained binary that ships next to it or is downloaded once on first run; no Node or other runtime is required. Pass a named source file or route as `--target <path>`. It loads PRODUCT.md, DESIGN.md, the matching surface brief, and native-platform guidance when applicable; follow its directives and do not rerun it. If the launcher is refused, missing, or fails, tell the user before editing that context loading did not run. Read existing **PRODUCT.md** and **DESIGN.md** without inventing missing context, then continue with steps 2–3.
|
1. Run `<skill-base-dir>/scripts/impeccable context` once per session, where `<skill-base-dir>` is the directory that contains this SKILL.md (the skill folder, not a plugin root two levels above it); keep cwd at the user's project. That base directory resolves every `.dsh/skills/impeccable/scripts/impeccable <verb>` command in this skill and its references, and `.dsh/skills/impeccable/scripts` is the fallback only when the runtime reports no base directory. On a Windows shell without `sh`, call `.dsh/skills/impeccable/scripts/impeccable.cmd` instead. The launcher runs a self-contained binary that ships next to it or is downloaded once on first run; no Node or other runtime is required. Pass a named source file or route as `--target <path>`. It loads PRODUCT.md, DESIGN.md, the matching surface brief, and native-platform guidance when applicable; follow its directives and do not rerun it.
|
||||||
2. Load the request's playbook: its Commands-table reference for an explicit/implied sub-command, or [reference/new-work.md](reference/new-work.md) for a new surface or replacement visual world. Inspect target and incumbent visual truth before editing. When the app cannot run, start with committed visual-regression goldens or screenshot fixtures; verify target and freshness against current tokens, CSS, components, or assets, resolve conflicts, and compare theme/variant captures.
|
2. Load the request's playbook: its Commands-table reference for an explicit/implied sub-command, or [reference/new-work.md](reference/new-work.md) for a new surface or replacement visual world. Inspect target and incumbent visual truth before editing. When the app cannot run, start with committed visual-regression goldens or screenshot fixtures; verify target and freshness against current tokens, CSS, components, or assets, resolve conflicts, and compare theme/variant captures.
|
||||||
3. After analysis and direction are resolved, load [reference/craft-floor.md](reference/craft-floor.md) immediately before editing UI. It carries the quality floor, the absolute bans, and the reflexes no detector catches. Do not load it for planning-only work.
|
3. After resolving analysis and direction, read [reference/craft-floor.md](reference/craft-floor.md) immediately before any UI edit, including small refinements. It carries the quality floor, the absolute bans, and the reflexes no detector catches. Do not load it for planning-only work.
|
||||||
|
|
||||||
|
**Launcher unavailable:** On refusal or failure, send a separate message **before the next tool call**: “Context loading did not run; I’ll read the existing project context directly.” Then read existing PRODUCT.md and DESIGN.md without inventing missing context, follow applicable steps 2–3, and continue through permitted tools. This applies to planning and editing; launcher failure alone does not block either.
|
||||||
|
|
||||||
## How to design
|
## How to design
|
||||||
|
|
||||||
|
|||||||
@@ -188,6 +188,12 @@ Test thoroughly across contexts:
|
|||||||
- **Edge cases**: Very small screens (320px), very large screens (4K)
|
- **Edge cases**: Very small screens (320px), very large screens (4K)
|
||||||
- **Slow connections**: Test on throttled network
|
- **Slow connections**: Test on throttled network
|
||||||
|
|
||||||
|
**Custom controls** (sliders, drag surfaces, scrollable control strips): a before/after slider can pass every width check above and still refuse to drag on iOS, so exercise each one in scope in the same batched round as the checks above:
|
||||||
|
|
||||||
|
- **Primary gesture**: Tap it and confirm it responds as designed, then drag it with the target input method; the drag must complete, not just start
|
||||||
|
- **Scroll across it**: A swipe along the page's scroll axis across the control scrolls the page or container without activating it; a drag that starts on the control along its axis moves the control, not the page. Neither failure throws an error, so try both
|
||||||
|
- **Evidence**: Say what produced the evidence: an emulated viewport, synthesized touch input through a browser tool, which engine ran it (Chromium is not Safari), or a physical device. Screenshots and resized viewports verify layout, never a gesture. Name what stayed untested and move on; unreachable hardware is a reported gap, not a blocker
|
||||||
|
|
||||||
When the adaptation feels native to each context, hand off to `/impeccable polish` for the final pass.
|
When the adaptation feels native to each context, hand off to `/impeccable polish` for the final pass.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -48,11 +48,12 @@ Run comprehensive checks across 5 dimensions. Score each dimension 0-4 using the
|
|||||||
**Check for**:
|
**Check for**:
|
||||||
- **Fixed widths**: Hard-coded widths that break on mobile
|
- **Fixed widths**: Hard-coded widths that break on mobile
|
||||||
- **Touch targets**: Interactive elements < 44x44px
|
- **Touch targets**: Interactive elements < 44x44px
|
||||||
|
- **Broken touch interaction**: Custom sliders, drag surfaces, and scrollable control strips whose primary gesture fails under touch, that swallow page scroll or lose the drag to it, or that stay stuck after an interrupted gesture. Code tells: mouse-only handlers, no `touch-action` on a pointer-event drag surface, drag state that nothing clears on cancel, lost capture, or blur. Exercise the gesture when a browser tool can synthesize touch (a rendered viewport proves layout, not the gesture), then say what produced the evidence (emulated viewport, synthesized touch, which engine, physical device) and what stayed untested
|
||||||
- **Horizontal scroll**: Content overflow on narrow viewports
|
- **Horizontal scroll**: Content overflow on narrow viewports
|
||||||
- **Text scaling**: Layouts that break when text size increases
|
- **Text scaling**: Layouts that break when text size increases
|
||||||
- **Missing breakpoints**: No mobile/tablet variants
|
- **Missing breakpoints**: No mobile/tablet variants
|
||||||
|
|
||||||
**Score 0-4**: 0=Desktop-only (breaks on mobile), 1=Major issues (some breakpoints, many failures), 2=Partial (works on mobile, rough edges), 3=Good (responsive, minor touch target or overflow issues), 4=Excellent (fluid, all viewports, proper touch targets)
|
**Score 0-4**: 0=Desktop-only (breaks on mobile), 1=Major issues (some breakpoints, many failures), 2=Partial (works on mobile, rough edges), 3=Good (responsive, minor touch target or overflow issues), 4=Excellent (fluid, all viewports, proper touch targets, gestures work under touch)
|
||||||
|
|
||||||
### 5. Implementation Integrity (CRITICAL)
|
### 5. Implementation Integrity (CRITICAL)
|
||||||
|
|
||||||
|
|||||||
@@ -26,12 +26,12 @@ Every region with `medium: raster` in the spec ships as a plate at its `plate` p
|
|||||||
Per region, in the spec's order:
|
Per region, in the spec's order:
|
||||||
|
|
||||||
1. `.dsh/skills/impeccable/scripts/impeccable comp-spec --crop <id>` writes the reference crop under `.impeccable/build/crops/`.
|
1. `.dsh/skills/impeccable/scripts/impeccable comp-spec --crop <id>` writes the reference crop under `.impeccable/build/crops/`.
|
||||||
2. Produce the plate. With the API fallback: `.dsh/skills/impeccable/scripts/impeccable generate-image --plate <id> --quality high` does the whole step (crop as reference, the spec's plate prompt, output size chosen from the region's aspect, the file written to its plate path, prompt embedded, and the plate scored against the crop). With a harness-native image tool: use the crop as the input image and `.dsh/skills/impeccable/scripts/impeccable comp-spec --plate-prompt <id>` as the prompt, write the result to the plate path, then run `.dsh/skills/impeccable/scripts/impeccable embed-prompt <plate> --prompt "<the exact prompt>"`.
|
2. Choose the background from the approved region: an isolated figure, object, or line drawing on the page ground is a **transparent cutout**; a photograph, full-frame illustration, or texture stays **opaque**. Save `.dsh/skills/impeccable/scripts/impeccable comp-spec --plate-prompt <id> --background transparent` to a UTF-8 prompt file for a cutout; use `--background opaque` otherwise. The transparent prompt preserves reference placement and clear margins, white paint, fine edges, and interior holes.
|
||||||
3. Read the score line. `PLATE-SCORE` under 50%, or a `PLATE-WARN`, means the plate does not read as the region: open the plate beside the crop, name what drifted (subject, framing, palette, style), tighten the prompt with that, and regenerate once. Two misses on one region: keep the better plate, mark it `needs_parent_review`, and say why in one line.
|
3. Produce the plate at its exact spec `plate` path. Create the output directory first and choose a supported output size matching the region's aspect, at least 1.5x its pixel dimensions. Prefer the harness-native image tool with the crop as input and the saved prompt; request a transparent PNG for cutouts, then run `.dsh/skills/impeccable/scripts/impeccable embed-prompt <plate> --prompt-file <prompt.txt>` (if you refine the prompt, save and embed the exact text sent). With the API fallback, run `.dsh/skills/impeccable/scripts/impeccable generate-image --ref <crop.png> --prompt-file <prompt.txt> --out <plate.png> --size <WxH> --quality high --background transparent` for a cutout, or `--background opaque` otherwise. The API fallback embeds the prompt and records the background in the sidecar. The output must be PNG; the fallback requests native alpha and performs no chroma-keying.
|
||||||
4. Transparent cutouts (a figure or object on the page ground): generate on a flat chroma color absent from the subject and key it to alpha before writing the PNG; never ship the keyed background.
|
4. Open the plate beside the crop and compare subject, placement, scale, palette, and style. For cutouts, verify a real alpha channel and inspect composites on light and dark grounds: white paint must stay solid, interior holes must clear, and fine edges must avoid halos. Inspect glass and soft shadows carefully; partial alpha alone does not ensure convincing translucency. Never chroma-key native transparent output or flatten it before saving. If a native tool returns opaque pixels or a painted checkerboard, retry with the API fallback when available; otherwise report the transparency blocker. On a visual miss, tighten the prompt and regenerate once. Two misses on one region: keep the better plate, mark it `needs_parent_review`, and name the drift. The parent runs the plates gate after all assets exist; report `unscored` until a gate score is available.
|
||||||
|
|
||||||
Do not redesign. Do not add objects, restyle, or reinterpret; the comp was approved as it is. Do not touch the page code, the spec, or the comp. Do not produce anything the spec does not list; a region the parent forgot goes back as a one-line note, not a plate.
|
Do not redesign. Do not add objects, restyle, or reinterpret; the comp was approved as it is. Do not touch the page code, the spec, or the comp. Do not produce anything the spec does not list; a region the parent forgot goes back as a one-line note, not a plate.
|
||||||
|
|
||||||
## Output Contract
|
## Output Contract
|
||||||
|
|
||||||
Return one line per raster region: `<id> <plate path> <WxH> <score>% <accepted|needs_parent_review|blocked> <one-line note or ->`. Then `blockers` (missing spec, missing comp, no image capability, exhausted key) and `assumptions`, each global and minimal. Nothing else: no summary, no praise, no implementation advice. The parent runs `impeccable build-phase advance` to verify the plates against the same spec; your line and its line must agree.
|
Return one line per raster region: `<id> <plate path> <WxH> <score%|unscored> <accepted|needs_parent_review|blocked> <one-line note or ->`. Then `blockers` (missing spec, missing comp, no image capability, exhausted key) and `assumptions`, each global and minimal. Nothing else: no summary, no praise, no implementation advice. The parent runs `impeccable build-phase advance` to verify the plates against the same spec; a visual acceptance does not override a failing gate.
|
||||||
@@ -5,7 +5,7 @@ This harness has no subagent capability, so you are running this role inline. St
|
|||||||
|
|
||||||
You record a project's design system after the build is done. Ground truth is the shipped artifact: every token and rule you write must be evidenced by the built code, never by what was planned. Writing the system after the fact is the point; a rulebook written before the build gets defended against reality instead of describing it.
|
You record a project's design system after the build is done. Ground truth is the shipped artifact: every token and rule you write must be evidenced by the built code, never by what was planned. Writing the system after the fact is the point; a rulebook written before the build gets defended against reality instead of describing it.
|
||||||
|
|
||||||
You run under a hard turn ceiling that ends the run without warning, and a run that ends before DESIGN.md is written has recorded nothing. Batch several Reads into each turn, take `reference/document.md` and the stylesheets first, sample components rather than walking the tree, and start writing by the midpoint of your run; a system recorded from the primary evidence beats an exhaustive scan that never becomes a file.
|
Complete the check within your turn ceiling. Batch Reads, take `reference/document.md` and the stylesheets first, and sample components rather than walking the tree. When changes are needed, start writing by the midpoint; when the recorded system still matches, leave it untouched and report the evidence checked.
|
||||||
|
|
||||||
## Input Contract
|
## Input Contract
|
||||||
|
|
||||||
@@ -15,10 +15,10 @@ Expect: the project root; the artifact path(s); the direction contract text (THE
|
|||||||
|
|
||||||
1. Read `reference/document.md` in full; it is the operating spec for DESIGN.md's format, token schema, sidecar, and section order. Follow it exactly.
|
1. Read `reference/document.md` in full; it is the operating spec for DESIGN.md's format, token schema, sidecar, and section order. Follow it exactly.
|
||||||
2. Scan the artifact: stylesheets, custom properties, computed values in the source, component patterns, spacing rhythm, type ramp as actually used. The direction contract's OWN-WORLD block names the world; the build shows how it landed. Where they diverge, the build wins and the prose may note the divergence.
|
2. Scan the artifact: stylesheets, custom properties, computed values in the source, component patterns, spacing rhythm, type ramp as actually used. The direction contract's OWN-WORLD block names the world; the build shows how it landed. Where they diverge, the build wins and the prose may note the divergence.
|
||||||
3. Write DESIGN.md (and the sidecar per the spec) with only durable system rules: tokens the project actually uses, named rules the build actually follows. Skip one-off values; a token used once is not a system.
|
3. For a new world or approved system change, write DESIGN.md and its sidecar from durable, reused rules in the build. Ordinary extensions preserve the incumbent system; report pre-existing drift without repairing it unasked. Do not write merely to prove this pass ran.
|
||||||
4. Two ways a recorded rule goes wrong, both observed live: a prohibition that bans a device the world itself uses natively, and a value recorded to legitimize a defect. Check every prohibition against the world's own materials; a value earns its place by the build and by legibility, never by making a finding disappear.
|
4. Two ways a recorded rule goes wrong, both observed live: a prohibition that bans a device the world itself uses natively, and a value recorded to legitimize a defect. Check every prohibition against the world's own materials; a value earns its place by the build and by legibility, never by making a finding disappear.
|
||||||
5. Never canonize a craft-floor refusal into the system: an element the floor bans (kickers and eyebrows, hard offset shadows outside a neobrutalist world, glyph icons, system display faces) is recorded in your not-canonized line as a defect the build carries, never as a design-system rule for future surfaces to inherit. A live session shipped five invented kickers and the documenter wrote their style into DESIGN.md; that is how one violation becomes the house style.
|
5. Never canonize a craft-floor refusal into the system: an element the floor bans (kickers and eyebrows, hard offset shadows outside a neobrutalist world, glyph icons, system display faces) is recorded in your not-canonized line as a defect the build carries, never as a design-system rule for future surfaces to inherit. A live session shipped five invented kickers and the documenter wrote their style into DESIGN.md; that is how one violation becomes the house style.
|
||||||
|
|
||||||
## Output Contract
|
## Output Contract
|
||||||
|
|
||||||
Return: the file paths written, a five-line summary of the recorded system (palette strategy, type ramp shape, named rules), and one line naming anything in the build you deliberately did not canonize and why. No other prose.
|
Return: paths written, or “No changes” with the source and system files checked; a five-line system summary (palette, type ramp, named rules); and one line naming defects or drift not canonized or repaired, and why. No other prose.
|
||||||
@@ -205,6 +205,11 @@ t('items', { count }) // Handles complex plural rules
|
|||||||
- Optimistic updates with rollback
|
- Optimistic updates with rollback
|
||||||
- Conflict resolution
|
- Conflict resolution
|
||||||
|
|
||||||
|
**Interrupted gestures** (custom sliders, drag surfaces, scrollable control strips):
|
||||||
|
- A second finger or pointer lands mid-drag: the first drag keeps its pointer or ends cleanly, never jumps to the new one
|
||||||
|
- The browser cancels the gesture to scroll (`pointercancel`), capture is lost (`lostpointercapture`), the pointer is released outside the control, or the window loses focus (`blur`) mid-drag: clear the dragging state and release capture
|
||||||
|
- After each of these, the next tap or drag works without a reload
|
||||||
|
|
||||||
**Permission states**:
|
**Permission states**:
|
||||||
- No permission to view
|
- No permission to view
|
||||||
- No permission to edit
|
- No permission to edit
|
||||||
@@ -304,6 +309,7 @@ const throttledScroll = throttle(handleScroll, 100);
|
|||||||
- Unit tests for edge cases
|
- Unit tests for edge cases
|
||||||
- Integration tests for error scenarios
|
- Integration tests for error scenarios
|
||||||
- E2E tests for critical paths
|
- E2E tests for critical paths
|
||||||
|
- A behavioral regression for each confirmed gesture fix, when the project's test runner can drive input
|
||||||
- Visual regression tests
|
- Visual regression tests
|
||||||
- Accessibility tests (axe, WAVE)
|
- Accessibility tests (axe, WAVE)
|
||||||
|
|
||||||
@@ -330,7 +336,10 @@ Test thoroughly with edge cases:
|
|||||||
- **Network issues**: Disable internet, throttle connection
|
- **Network issues**: Disable internet, throttle connection
|
||||||
- **Large datasets**: Test with 1000+ items
|
- **Large datasets**: Test with 1000+ items
|
||||||
- **Concurrent actions**: Click submit 10 times rapidly
|
- **Concurrent actions**: Click submit 10 times rapidly
|
||||||
|
- **Interrupted gestures**: Add a second finger mid-drag, scroll across the control, release outside it, switch windows mid-drag; then drag again
|
||||||
- **Errors**: Force API errors, test all error states
|
- **Errors**: Force API errors, test all error states
|
||||||
- **Empty**: Remove all data, test empty states
|
- **Empty**: Remove all data, test empty states
|
||||||
|
|
||||||
|
For gestures, say what produced the evidence (emulated viewport, synthesized touch, which engine, physical device) and name what stayed untested.
|
||||||
|
|
||||||
When edge cases are covered, hand off to `/impeccable polish` for the final pass.
|
When edge cases are covered, hand off to `/impeccable polish` for the final pass.
|
||||||
|
|||||||
@@ -42,6 +42,8 @@ On every boot the project is scanned for HTML files under common page roots (`pu
|
|||||||
|
|
||||||
## CSP detection (first-time only)
|
## CSP detection (first-time only)
|
||||||
|
|
||||||
|
Keep all allowances below development-only, including manual middleware and meta-tag edits. Do not change a deployed production site's CSP to load the localhost helper; see [live.md](live.md) for production inspection alternatives.
|
||||||
|
|
||||||
If `config.cspChecked === true`, skip this whole section; the user was already asked once.
|
If `config.cspChecked === true`, skip this whole section; the user was already asked once.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ Interactive live variant mode: select elements in the browser, pick a design act
|
|||||||
|
|
||||||
A running dev server with HMR (Vite, Next.js, Bun, etc.), OR a static HTML file open in the browser. If the dev server's default port is busy, the app is very likely ALREADY running; probe the default URL before spawning a second server.
|
A running dev server with HMR (Vite, Next.js, Bun, etc.), OR a static HTML file open in the browser. If the dev server's default port is busy, the app is very likely ALREADY running; probe the default URL before spawning a second server.
|
||||||
|
|
||||||
|
Live editing requires a local checkout; injection into deployed production sites (including HTTPS) is unsupported. For production inspection, use `.dsh/skills/impeccable/scripts/impeccable detect <url>` or the browser extension, not the live helper. Do not disable browser security or weaken production CSP to enable live mode.
|
||||||
|
|
||||||
## The contract (read once)
|
## The contract (read once)
|
||||||
|
|
||||||
Execute in order. No step skipped, no step reordered. Every tool output in live mode may carry an `_instructions` field: it is the authoritative next step for that exact situation, with real ids and paths substituted; when it conflicts with your recollection of this document, `_instructions` wins.
|
Execute in order. No step skipped, no step reordered. Every tool output in live mode may carry an `_instructions` field: it is the authoritative next step for that exact situation, with real ids and paths substituted; when it conflicts with your recollection of this document, `_instructions` wins.
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ A section, component, feature, or state inside an established surface inherits t
|
|||||||
|
|
||||||
## 2. Ask what will change the work
|
## 2. Ask what will change the work
|
||||||
|
|
||||||
Ask one round of two or three related questions through the structured question tool when available. Skip settled facts; a precise request may need only a compact confirmation.
|
Before implementation, get the user's answer through the structured question tool when available. Ask two or three related questions; a precise request needs only a compact confirmation. Skip settled facts, not the confirmation: DESIGN.md settles the visual world, not this surface's purpose or concept.
|
||||||
|
|
||||||
- **Persuade:** who must act, what they should believe, which real proof, content, or assets earn that belief.
|
- **Persuade:** who must act, what they should believe, which real proof, content, or assets earn that belief.
|
||||||
- **Operate:** the task, information, important states, frequency, constraints.
|
- **Operate:** the task, information, important states, frequency, constraints.
|
||||||
@@ -68,7 +68,7 @@ Calibration: AI-generated interfaces cluster around a few looks regardless of su
|
|||||||
|
|
||||||
## 5. Record the decision
|
## 5. Record the decision
|
||||||
|
|
||||||
Before code, record the chosen direction as a development-only contract under `## Direction contract` in the relevant surface brief. A direction contract is durable route or artifact strategy, so create or update the brief even when no other surface strategy needs persistence. Keep the contract to six short blocks and 150 words at most. THESIS: the one idea this surface owns and the category-default arrangement it refuses. OWN-WORLD: the palette and component language, specific enough to be recognizable with all content removed. STORY: what the visitor understands, believes, and does. FIRST VIEWPORT: the exact composition, what is where and at what scale, and where the primary action sits. FORM: the chosen form, its position on your ordered list, and the seed key the script printed. Close with one more line, FINISH: the run's exit condition, verbatim "unreviewed and undocumented is unfinished; this build ends with the finish review, the verdict, DESIGN.md, and every shipping raster carrying its provenance". The surface brief is the reminder later agents reload across edits and sessions: a page that looks complete with the FINISH line undischarged is not done, it is abandoned at the finish line. If a block reads like a mood, the direction is not decided yet; the finishing review audits the render against this contract.
|
Before code, record the chosen direction as a development-only contract under `## Direction contract` in the relevant surface brief. A direction contract is durable route or artifact strategy, so create or update the brief even when no other surface strategy needs persistence. Use six short blocks, roughly 150 words; do not spend tool calls counting words. THESIS: the one idea this surface owns and the category-default arrangement it refuses. OWN-WORLD: the palette and component language, specific enough to be recognizable with all content removed. STORY: what the visitor understands, believes, and does. FIRST VIEWPORT: the exact composition, what is where and at what scale, and where the primary action sits. FORM: the chosen form, its position on your ordered list, and the seed key the script printed. Close with one more line, FINISH: the run's exit condition, verbatim "unreviewed and undocumented is unfinished; this build ends with the finish review, the verdict, DESIGN.md, and every shipping raster carrying its provenance". The surface brief is the reminder later agents reload across edits and sessions: a page that looks complete with the FINISH line undischarged is not done, it is abandoned at the finish line. If a block reads like a mood, the direction is not decided yet; the finishing review audits the render against this contract.
|
||||||
|
|
||||||
Never copy the direction contract into implementation source or any browser-delivered artifact. This includes HTML or framework comments, hidden DOM, `<template>` elements, `data-*` attributes, rendered JSX or TSX output, serialized props or state, React Server Component payloads, client bundles, metadata or JSON-LD, accessibility-only text, and files served beside the artifact. A compiler or optimizer removing development metadata is not a safety boundary. Reviewers and documenters receive the contract from the surface brief.
|
Never copy the direction contract into implementation source or any browser-delivered artifact. This includes HTML or framework comments, hidden DOM, `<template>` elements, `data-*` attributes, rendered JSX or TSX output, serialized props or state, React Server Component payloads, client bundles, metadata or JSON-LD, accessibility-only text, and files served beside the artifact. A compiler or optimizer removing development metadata is not a safety boundary. Reviewers and documenters receive the contract from the surface brief.
|
||||||
|
|
||||||
@@ -104,7 +104,7 @@ Then, in order, each closed by `.dsh/skills/impeccable/scripts/impeccable build-
|
|||||||
The comp-led path is a frontier-tier job: it asks the builder to hold a measured layout, place plates at their boxes, and act on numeric readings across a dozen attempts. Smaller or faster models produce a recognisable page and stall under the hero gate; if the model in hand is one of those, say so before the direction round and take the code-led path, or expect the run to end at the hero with its readings unmet.
|
The comp-led path is a frontier-tier job: it asks the builder to hold a measured layout, place plates at their boxes, and act on numeric readings across a dozen attempts. Smaller or faster models produce a recognisable page and stall under the hero gate; if the model in hand is one of those, say so before the direction round and take the code-led path, or expect the run to end at the hero with its readings unmet.
|
||||||
|
|
||||||
1. **spec.** Measure the comp: `impeccable comp-spec --comp <comp> --grid` writes a coordinate grid over the comp; open it, name every salient region by grid span in a regions file (text and control regions snap to the largest ink mass inside their span, so a headline named B1:E4 measures as the headline and not the column beside it; `snap: false` keeps the span, and an explicit `box` is taken as drawn) (kind `plate` / `image` / `texture` for anything painted: every illustration, photograph, figure, product object, and material texture; `text` / `control` / `chrome` for what code draws; every region carries a `note` saying what the comp shows there, which the plate prompt and the gate messages read), and run `impeccable comp-spec --comp <comp> --regions <file>`. The spec carries each region's box, sampled palette, and medium; `impeccable comp-spec --print` is the build's reference from here on. Type is measured, not guessed: `impeccable font-match --measure <text region>` reads the comp's cap height, width class, and weight off the pixels, and `impeccable font-match --rank <region> --text "..."` takes its candidates from a fingerprint index of the Google Fonts catalog (the nearest faces to the crop's shape) plus any names you pass with `--candidates`, renders them at that cap height with the region's words, and ranks them by fingerprint distance (its `USE` line is the CSS; its proof sheet shows the comp over the top three); with no browser resolvable it records the catalog's nearest face and says the size is estimated, which is still the choice to build on. Do not install a browser to rank, and never write a `chosen` face into the spec by hand: the gate accepts only what font-match wrote. The spec gate refuses to close until the lead text region is measured and ranked. A region note that describes painted material (a diagram, drawing, photograph, texture) under a code kind is refused at the spec: reclassify it as a plate, or reword the note if code really draws it. The script refuses a regions file that leaves comp ink unnamed (callouts, a parts table, a notes block): what is never named can never be missing, so everything the comp shows gets a region. It also refuses a `text` / `control` / `chrome` region larger than a quarter of the comp: that is a column, not an element, and a column scored as one region hides the plates, tables, and notes inside it. Name each element inside it (`container: true` only when it truly is one undivided element). Anything drawn is a plate: an inline SVG past an icon's budget (a diagram, notation, leader lines with arrows, a "quick approximation" of the artwork) is refused at the hero; icon-sized SVG (under 64px, a few paths) is fine, and a chart the page draws from data at runtime is a chart, not an illustration. Callout lines and arrows that annotate a drawing belong to that drawing's plate, with only their labels set as text. A crop of the comp is never a plate (the plates gate refuses a file that is a resample of the comp region: the comp's grain, its neighbours' edges, and its resolution would ship as the artwork); the crop is the reference the plate is generated from. A plate region's box has to hold its whole artwork with a margin: the spec measures the artwork's contact with the box edges and refuses a box that cuts through it (`bleed: true` only when the page really crops it there), because a plate placed with `object-fit: cover` on such a box shows the artwork minus the side the box lost. Anything not in the spec does not exist on the page: no borders, rules, containers, or chrome the comp does not show. Only three concessions exist: fonts (the closest obtainable face), icon glyphs (close enough, exact if the user chose an icon library; this covers the pictogram only, never a control's chrome, so a chevron, an arrow, a dropdown's border and fill, a button's shape are the comp's), and genuine defects in the comp such as spelling errors.
|
1. **spec.** Measure the comp: `impeccable comp-spec --comp <comp> --grid` writes a coordinate grid over the comp; open it, name every salient region by grid span in a regions file (text and control regions snap to the largest ink mass inside their span, so a headline named B1:E4 measures as the headline and not the column beside it; `snap: false` keeps the span, and an explicit `box` is taken as drawn) (kind `plate` / `image` / `texture` for anything painted: every illustration, photograph, figure, product object, and material texture; `text` / `control` / `chrome` for what code draws; every region carries a `note` saying what the comp shows there, which the plate prompt and the gate messages read), and run `impeccable comp-spec --comp <comp> --regions <file>`. The spec carries each region's box, sampled palette, and medium; `impeccable comp-spec --print` is the build's reference from here on. Type is measured, not guessed: `impeccable font-match --measure <text region>` reads the comp's cap height, width class, and weight off the pixels, and `impeccable font-match --rank <region> --text "..."` takes its candidates from a fingerprint index of the Google Fonts catalog (the nearest faces to the crop's shape) plus any names you pass with `--candidates`, renders them at that cap height with the region's words, and ranks them by fingerprint distance (its `USE` line is the CSS; its proof sheet shows the comp over the top three); with no browser resolvable it records the catalog's nearest face and says the size is estimated, which is still the choice to build on. Do not install a browser to rank, and never write a `chosen` face into the spec by hand: the gate accepts only what font-match wrote. The spec gate refuses to close until the lead text region is measured and ranked. A region note that describes painted material (a diagram, drawing, photograph, texture) under a code kind is refused at the spec: reclassify it as a plate, or reword the note if code really draws it. The script refuses a regions file that leaves comp ink unnamed (callouts, a parts table, a notes block): what is never named can never be missing, so everything the comp shows gets a region. It also refuses a `text` / `control` / `chrome` region larger than a quarter of the comp: that is a column, not an element, and a column scored as one region hides the plates, tables, and notes inside it. Name each element inside it (`container: true` only when it truly is one undivided element). Anything drawn is a plate: an inline SVG past an icon's budget (a diagram, notation, leader lines with arrows, a "quick approximation" of the artwork) is refused at the hero; icon-sized SVG (under 64px, a few paths) is fine, and a chart the page draws from data at runtime is a chart, not an illustration. Callout lines and arrows that annotate a drawing belong to that drawing's plate, with only their labels set as text. A crop of the comp is never a plate (the plates gate refuses a file that is a resample of the comp region: the comp's grain, its neighbours' edges, and its resolution would ship as the artwork); the crop is the reference the plate is generated from. A plate region's box has to hold its whole artwork with a margin: the spec measures the artwork's contact with the box edges and refuses a box that cuts through it (`bleed: true` only when the page really crops it there), because a plate placed with `object-fit: cover` on such a box shows the artwork minus the side the box lost. Anything not in the spec does not exist on the page: no borders, rules, containers, or chrome the comp does not show. Only three concessions exist: fonts (the closest obtainable face), icon glyphs (close enough, exact if the user chose an icon library; this covers the pictogram only, never a control's chrome, so a chevron, an arrow, a dropdown's border and fill, a button's shape are the comp's), and genuine defects in the comp such as spelling errors.
|
||||||
2. **plates.** Every raster region ships as a plate: an illustration, photo, or figure regenerated at asset resolution from its comp crop, UI text removed, at its `plate` path (ink on flat ground is generated on a chroma key and keyed to alpha, so it sits on the page's own ground rather than a second paper); a texture (paper, cloth, grain) is a clean patch of the comp region mirror-tiled to size, generated only when no clean patch exists. `impeccable generate-image --plate <id>` does one region end to end and scores it against the crop; a harness-native image tool takes the crop (`impeccable comp-spec --crop <id>`) as its input image and `impeccable comp-spec --plate-prompt <id>` as its prompt, then `impeccable embed-prompt`. With parallel subagents, spawn the shipped asset producer (`impeccable-asset-producer`; `impeccable_asset_producer` in codex; `/impeccable-asset-producer` in Cursor; on GitHub Copilot say "Use the impeccable-asset-producer agent") with the spec path and let it produce them all; without subagents, produce them here. A crop of the comp is a reference, never a shipping pixel. The gate checks every plate exists, is at least 1.5x the region's size, and reads as the region. Page code waits for this gate: a page written before its plates exist is a page that draws its material in CSS. A single-file deliverable changes nothing here: the plate is produced the same way and inlined as a data URI. `--force` exists for one case only, the user downgrading the comp's authority in words you quote in `--reason`; the script refuses every other reason.
|
2. **plates.** Every raster region ships as a plate: an illustration, photo, or figure regenerated at asset resolution from its comp crop, UI text removed, at its `plate` path (isolated ink, figures, or objects use native transparent PNG so they sit on the page's own ground; photos and textures stay opaque); a texture (paper, cloth, grain) is a clean patch of the comp region mirror-tiled to size, generated only when no clean patch exists. `impeccable comp-spec --crop <id>` writes the reference; save `impeccable comp-spec --plate-prompt <id> --background transparent` to a prompt file for a cutout, or use `--background opaque` otherwise. Prefer the harness-native image tool with that crop and prompt, then `impeccable embed-prompt <plate> --prompt-file <prompt.txt>`. The API fallback is `impeccable generate-image --ref <crop.png> --prompt-file <prompt.txt> --out <plate.png> --size <WxH> --quality high --background transparent` (use `--background opaque` for full-frame assets); create the output directory first. Verify actual alpha, white foregrounds, fine edges, and clear holes on light and dark grounds; do not chroma-key native output. The plates gate scores the assets against the comp; also inspect placement and scale visually. With parallel subagents, spawn the shipped asset producer (`impeccable-asset-producer`; `impeccable_asset_producer` in codex; `/impeccable-asset-producer` in Cursor; on GitHub Copilot say "Use the impeccable-asset-producer agent") with the spec path and let it produce them all; without subagents, produce them here. A crop of the comp is a reference, never a shipping pixel. The gate checks every plate exists, is at least 1.5x the region's size, and reads as the region. Page code waits for this gate: a page written before its plates exist is a page that draws its material in CSS. A single-file deliverable changes nothing here: the plate is produced the same way and inlined as a data URI. `--force` exists for one case only, the user downgrading the comp's authority in words you quote in `--reason`; the script refuses every other reason.
|
||||||
3. **hero.** `impeccable build-phase scaffold` first: it writes the measured layout as CSS custom properties (`.impeccable/build/scaffold/layout.css`: `--r-<id>-x/y/w/h` in % of the comp, plus cap height, font-size, family, and weight where measured) and a reference page (`hero-reference.html`) with every region at its box and every plate placed. Bind the numbers to your own semantic structure, an element per region; the reference is a check on positions, never the page, and overlapping boxes are overlapping boxes. Then build only the first viewport, at the comp's own dimensions, the comp's words copied verbatim (the user approved that comp with those words; rewording is a stated decision after the hero passes, never a silent one inside it), every text region sized from its measured cap height and set in its ranked face, plates first: place every plate at its spec box (`object-fit: cover`, an `<img>`, a background image, or an inlined data URI named for it) before any text or control, capture into `.impeccable/review/hero-repro.png`, run `impeccable build-phase record hero` once so you see the plate regions read as match before any text exists, then lay the semantic layer over the plates from the spec's palette and boxes and advance. The gate first refuses while any plate is unreferenced by the source, then runs `impeccable comp-diff`, writes `.impeccable/review/diff/hero/` (side-by-side, heatmap, one paired crop per region, `report.json`), and passes at 72% overall with no hard veto outstanding (a missing region, a contradicted plate or text block, an SVG illustration, a clipped plate, invented ink block at any score); above the bar, the numeric readings become advisories printed with the pass, and the polish pass before responsive is where they get fixed: the gate also reads each text region's cap height, line count, weight, ink colour, and position against the comp, each chrome strip's height off its rule, and the frame for ink where the comp is calm (a kicker, an extra nav item, a divider), and says each miss as a number ("cap height 78px in the build, 103px in the comp"); those numbers are the edit. When it fails, open the region crops it lists, in order, before editing: a region scored `missing` needs its material, `contradicted` needs its structure re-derived from the spec box, `drift` is where size and spacing edits belong; the gate refuses a third attempt that only nudges values on the same region. This is where the run's ambition is won or lost, and a retry here costs minutes where a rebuild verdict at the finish costs the run.
|
3. **hero.** `impeccable build-phase scaffold` first: it writes the measured layout as CSS custom properties (`.impeccable/build/scaffold/layout.css`: `--r-<id>-x/y/w/h` in % of the comp, plus cap height, font-size, family, and weight where measured) and a reference page (`hero-reference.html`) with every region at its box and every plate placed. Bind the numbers to your own semantic structure, an element per region; the reference is a check on positions, never the page, and overlapping boxes are overlapping boxes. Then build only the first viewport, at the comp's own dimensions, the comp's words copied verbatim (the user approved that comp with those words; rewording is a stated decision after the hero passes, never a silent one inside it), every text region sized from its measured cap height and set in its ranked face, plates first: place every plate at its spec box (`object-fit: cover`, an `<img>`, a background image, or an inlined data URI named for it) before any text or control, capture into `.impeccable/review/hero-repro.png`, run `impeccable build-phase record hero` once so you see the plate regions read as match before any text exists, then lay the semantic layer over the plates from the spec's palette and boxes and advance. The gate first refuses while any plate is unreferenced by the source, then runs `impeccable comp-diff`, writes `.impeccable/review/diff/hero/` (side-by-side, heatmap, one paired crop per region, `report.json`), and passes at 72% overall with no hard veto outstanding (a missing region, a contradicted plate or text block, an SVG illustration, a clipped plate, invented ink block at any score); above the bar, the numeric readings become advisories printed with the pass, and the polish pass before responsive is where they get fixed: the gate also reads each text region's cap height, line count, weight, ink colour, and position against the comp, each chrome strip's height off its rule, and the frame for ink where the comp is calm (a kicker, an extra nav item, a divider), and says each miss as a number ("cap height 78px in the build, 103px in the comp"); those numbers are the edit. When it fails, open the region crops it lists, in order, before editing: a region scored `missing` needs its material, `contradicted` needs its structure re-derived from the spec box, `drift` is where size and spacing edits belong; the gate refuses a third attempt that only nudges values on the same region. This is where the run's ambition is won or lost, and a retry here costs minutes where a rebuild verdict at the finish costs the run.
|
||||||
4. **sections.** Build the rest of the surface inside the spec's system: the same corner language, line weights, and palette, and nothing the comp never shows. Where the comp does not cover a region, it inherits the recorded system.
|
4. **sections.** Build the rest of the surface inside the spec's system: the same corner language, line weights, and palette, and nothing the comp never shows. Where the comp does not cover a region, it inherits the recorded system.
|
||||||
5. **motion.** The signature interaction, reveals, and motion, orchestrated once rather than scattered.
|
5. **motion.** The signature interaction, reveals, and motion, orchestrated once rather than scattered.
|
||||||
@@ -142,4 +142,4 @@ A rebuild and a fix round share one asset rule: a raster either round creates or
|
|||||||
|
|
||||||
Report the final verdict under the reviewer's own disposition word and at its actual scope. A verdict pass scores the listed fixes and nothing else: "the reviewer scored all three fixes resolved" is a claim it supports, "no material issues remain" is not. A table with open material findings is never announced as a pass, never softened, and never dressed as whole-surface approval when only a fix list was scored. When the user answers a ship with evidence against it, their own screenshot, a named mismatch with the comp, that evidence outranks every capture you made: put their material in the packet and spawn a fresh reviewer for a new full review. Patching inline and self-certifying is how a rejected page ships twice.
|
Report the final verdict under the reviewer's own disposition word and at its actual scope. A verdict pass scores the listed fixes and nothing else: "the reviewer scored all three fixes resolved" is a claim it supports, "no material issues remain" is not. A table with open material findings is never announced as a pass, never softened, and never dressed as whole-surface approval when only a fix list was scored. When the user answers a ship with evidence against it, their own screenshot, a named mismatch with the comp, that evidence outranks every capture you made: put their material in the packet and spawn a fresh reviewer for a new full review. Patching inline and self-certifying is how a rejected page ships twice.
|
||||||
|
|
||||||
Then spawn the shipped documenter, `impeccable-documenter` (`impeccable_documenter` in codex), with the project root, the artifact path, the direction contract, PRODUCT.md, the [document.md](document.md) reference path, and the boundary to write at; it records DESIGN.md and the sidecar from the built world, ground truth over intention; without subagents the pass runs from [degraded/documenter.md](degraded/documenter.md). The documenter runs after the last correction lands: when any fix round follows the documentation, re-run the documenter over the changed surface, because a DESIGN.md describing a layout that no longer exists turns defects into system guidance. A clean detector pass is not finished; finished is the contract kept, the comp honored, the review closed, and the system recorded.
|
After the last correction, spawn the shipped documenter, `impeccable-documenter` (`impeccable_documenter` in codex), with the project root, artifact path, direction contract, PRODUCT.md, [document.md](document.md), and write boundary. Without subagents, load [degraded/documenter.md](degraded/documenter.md) and [document.md](document.md) before writing. Verify the outcome: new worlds and approved system changes require token-bearing DESIGN.md **and** `.impeccable/design.json`, not prose alone. Ordinary extensions compare the finished build against the incumbent system, preserve its files, and report the evidence checked; report pre-existing drift without repairing it unasked. Recheck after later edits. Finish only when review and documentation are complete.
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ What the comp shows is measured, not remembered. new-work.md section 6 runs the
|
|||||||
|
|
||||||
## Plates and provenance
|
## Plates and provenance
|
||||||
|
|
||||||
Every raster region's plate is produced in the plates phase, before any page code, by the shipped asset producer or in the current thread (`impeccable generate-image --plate <id>`, or the harness image tool with the crop as input and the spec's plate prompt). Generation context is part of the asset: after generating any image with any tool, run `.dsh/skills/impeccable/scripts/impeccable embed-prompt <image> --prompt "<prompt>"` with the exact string the tool received (`impeccable generate-image` does this itself), so the intent lives inside the file; `--read` recovers it, `--scan <dir>` lists rasters still missing one. The embedded prompt plus the region's row in the spec is the raster's **provenance**, and every raster the artifact references carries it; a sourced, stock, or pre-existing raster embeds its origin instead. A raster created or replaced later, in a fix batch or a reviewer's rebuild, is produced the same way; a raster a fix abandons is deleted in the same batch.
|
Every raster region's plate is produced in the plates phase, before any page code, by the shipped asset producer or in the current thread (use `impeccable comp-spec --crop <id>` and save `impeccable comp-spec --plate-prompt <id>` to a prompt file; pass the crop and prompt to the harness image tool, or use `impeccable generate-image --ref <crop.png> --prompt-file <prompt.txt> --out <plate.png> --size <WxH> --quality high`). For isolated cutouts, add `--background transparent` to both the plate-prompt and API generation commands; use native PNG alpha and preserve white paint and clear gaps. Use `--background opaque` for full-frame imagery. Create output directories first and inspect alpha on light and dark grounds. Generation context is part of the asset: after generating any image with any tool, run `.dsh/skills/impeccable/scripts/impeccable embed-prompt <image> --prompt "<prompt>"` with the exact string the tool received (`impeccable generate-image` does this itself), so the intent lives inside the file; `--read` recovers it, `--scan <dir>` lists rasters still missing one. The embedded prompt plus the region's row in the spec is the raster's **provenance**, and every raster the artifact references carries it; a sourced, stock, or pre-existing raster embeds its origin instead. A raster created or replaced later, in a fix batch or a reviewer's rebuild, is produced the same way; a raster a fix abandons is deleted in the same batch.
|
||||||
|
|
||||||
Convert images with a converter `impeccable context` reported at boot (the IMAGE_TOOLS line); probe only when it reported none, at most once per session, never per image.
|
Convert images with a converter `impeccable context` reported at boot (the IMAGE_TOOLS line); probe only when it reported none, at most once per session, never per image.
|
||||||
|
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
0.1.3
|
0.1.5
|
||||||
|
|||||||
@@ -87,6 +87,11 @@ fi
|
|||||||
# Last resort: fetch this version's binary for the current platform from the
|
# Last resort: fetch this version's binary for the current platform from the
|
||||||
# public release channel into the user cache. Needs network; sandboxes without
|
# public release channel into the user cache. Needs network; sandboxes without
|
||||||
# egress preinstall the binary on PATH instead.
|
# egress preinstall the binary on PATH instead.
|
||||||
|
setup_help() {
|
||||||
|
echo "Engine $version setup needs network access and write permission to $cache_root/bin/$version." >&2
|
||||||
|
echo "Run this launcher ($0) with engine-probe in a terminal that has those permissions, then retry the original command." >&2
|
||||||
|
echo "Alternatively, set IMPECCABLE_HOME to a writable cache location, or IMPECCABLE_BIN to a preinstalled engine binary." >&2
|
||||||
|
}
|
||||||
fetch_url() {
|
fetch_url() {
|
||||||
if command -v curl >/dev/null 2>&1; then
|
if command -v curl >/dev/null 2>&1; then
|
||||||
curl -fsSL --retry 2 -o "$tmp" "$1" 2>/dev/null
|
curl -fsSL --retry 2 -o "$tmp" "$1" 2>/dev/null
|
||||||
@@ -119,7 +124,18 @@ if [ -n "$version" ] && [ "$os" != unknown ] && [ "$arch" != unknown ]; then
|
|||||||
[ "$os" = windows ] && asset="$asset.exe"
|
[ "$os" = windows ] && asset="$asset.exe"
|
||||||
url="$base/engine-v$version/$asset"
|
url="$base/engine-v$version/$asset"
|
||||||
tmp="$cache_root/bin/$version/.impeccable.part.$$"
|
tmp="$cache_root/bin/$version/.impeccable.part.$$"
|
||||||
mkdir -p "$cache_root/bin/$version" 2>/dev/null
|
if ! mkdir -p "$cache_root/bin/$version" 2>/dev/null; then
|
||||||
|
echo "impeccable: engine $version is not installed; cannot create cache directory: $cache_root/bin/$version" >&2
|
||||||
|
setup_help
|
||||||
|
exit 127
|
||||||
|
fi
|
||||||
|
# Check the actual staging file, not just directory existence: a cache from
|
||||||
|
# an earlier run can be readable but no longer writable inside a sandbox.
|
||||||
|
if ! (umask 077; : > "$tmp") 2>/dev/null; then
|
||||||
|
echo "impeccable: engine $version is not installed; cannot write to cache directory: $cache_root/bin/$version" >&2
|
||||||
|
setup_help
|
||||||
|
exit 127
|
||||||
|
fi
|
||||||
fetched=0
|
fetched=0
|
||||||
if fetch_url "$url"; then
|
if fetch_url "$url"; then
|
||||||
fetched=1
|
fetched=1
|
||||||
@@ -180,6 +196,9 @@ if [ -n "$version" ] && [ "$os" != unknown ] && [ "$arch" != unknown ]; then
|
|||||||
exec "$cached" "$@"
|
exec "$cached" "$@"
|
||||||
fi
|
fi
|
||||||
rm -f "$tmp" 2>/dev/null
|
rm -f "$tmp" 2>/dev/null
|
||||||
|
echo "impeccable: could not download engine $version from $url; check network access, the release URL, and curl or wget availability." >&2
|
||||||
|
setup_help
|
||||||
|
exit 127
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "impeccable: no engine binary for $os-$arch found (looked in $bin, $cached, PATH)." >&2
|
echo "impeccable: no engine binary for $os-$arch found (looked in $bin, $cached, PATH)." >&2
|
||||||
|
|||||||
@@ -68,18 +68,27 @@ rem another launcher's probe: fail fast and quiet instead.
|
|||||||
if defined IMPECCABLE_LAUNCHER_PROBE exit /b 127
|
if defined IMPECCABLE_LAUNCHER_PROBE exit /b 127
|
||||||
if not defined version goto fail
|
if not defined version goto fail
|
||||||
where curl.exe >nul 2>nul
|
where curl.exe >nul 2>nul
|
||||||
if errorlevel 1 goto fail
|
if errorlevel 1 goto curl_missing
|
||||||
if not defined IMPECCABLE_DOWNLOAD_BASE set "IMPECCABLE_DOWNLOAD_BASE=https://github.com/pbakaus/impeccable/releases/download"
|
if not defined IMPECCABLE_DOWNLOAD_BASE set "IMPECCABLE_DOWNLOAD_BASE=https://github.com/pbakaus/impeccable/releases/download"
|
||||||
if not exist "%IMPECCABLE_HOME%\bin\%version%" mkdir "%IMPECCABLE_HOME%\bin\%version%" >nul 2>nul
|
if exist "%IMPECCABLE_HOME%\bin\%version%\" goto cache_ready
|
||||||
|
mkdir "%IMPECCABLE_HOME%\bin\%version%" >nul 2>nul
|
||||||
|
if errorlevel 1 goto cache_directory_failed
|
||||||
|
:cache_ready
|
||||||
|
rem Check the staging file too: an existing directory may be read-only.
|
||||||
|
rem Redirection failures do not reliably update ERRORLEVEL in cmd.exe;
|
||||||
|
rem branch on the command's failure directly. Never treat a directory as a
|
||||||
|
rem staging file (later del cleanup would prompt to delete its contents).
|
||||||
|
if exist "%cached%.part\" goto cache_write_failed
|
||||||
|
(type nul >"%cached%.part") 2>nul || goto cache_write_failed
|
||||||
set "asset=impeccable-windows-%arch%.exe"
|
set "asset=impeccable-windows-%arch%.exe"
|
||||||
set "url=%IMPECCABLE_DOWNLOAD_BASE%/engine-v%version%/%asset%"
|
set "url=%IMPECCABLE_DOWNLOAD_BASE%/engine-v%version%/%asset%"
|
||||||
curl.exe -fsSL -o "%cached%.part" "%url%" >nul 2>nul
|
curl.exe -fsSL -o "%cached%.part" "%url%" >nul 2>nul
|
||||||
if not errorlevel 1 goto verify
|
if not errorlevel 1 goto verify
|
||||||
if not "%arch%"=="arm64" goto fail
|
if not "%arch%"=="arm64" goto download_failed
|
||||||
set "asset=impeccable-windows-x64.exe"
|
set "asset=impeccable-windows-x64.exe"
|
||||||
set "url=%IMPECCABLE_DOWNLOAD_BASE%/engine-v%version%/%asset%"
|
set "url=%IMPECCABLE_DOWNLOAD_BASE%/engine-v%version%/%asset%"
|
||||||
curl.exe -fsSL -o "%cached%.part" "%url%" >nul 2>nul
|
curl.exe -fsSL -o "%cached%.part" "%url%" >nul 2>nul
|
||||||
if errorlevel 1 goto fail
|
if errorlevel 1 goto download_failed
|
||||||
|
|
||||||
:verify
|
:verify
|
||||||
call :check_download
|
call :check_download
|
||||||
@@ -176,6 +185,28 @@ if not errorlevel 1 set "probe_ok=1"
|
|||||||
del "%probe_tmp%" >nul 2>nul
|
del "%probe_tmp%" >nul 2>nul
|
||||||
exit /b 0
|
exit /b 0
|
||||||
|
|
||||||
|
:cache_directory_failed
|
||||||
|
echo impeccable: engine %version% is not installed; cannot create cache directory: "%IMPECCABLE_HOME%\bin\%version%" 1>&2
|
||||||
|
goto setup_failed
|
||||||
|
|
||||||
|
:cache_write_failed
|
||||||
|
echo impeccable: engine %version% is not installed; cannot write to cache directory: "%IMPECCABLE_HOME%\bin\%version%" 1>&2
|
||||||
|
goto setup_failed
|
||||||
|
|
||||||
|
:curl_missing
|
||||||
|
echo impeccable: cannot download engine %version%; curl.exe is unavailable. 1>&2
|
||||||
|
goto setup_failed
|
||||||
|
|
||||||
|
:download_failed
|
||||||
|
del "%cached%.part" >nul 2>nul
|
||||||
|
echo impeccable: could not download engine %version% from %url%; check network access and the release URL. 1>&2
|
||||||
|
|
||||||
|
:setup_failed
|
||||||
|
echo Engine %version% setup needs network access and write permission to "%IMPECCABLE_HOME%\bin\%version%". 1>&2
|
||||||
|
echo Run this launcher ("%~f0") with engine-probe in a terminal that has those permissions, then retry the original command. 1>&2
|
||||||
|
echo Alternatively, set IMPECCABLE_HOME to a writable cache location, or IMPECCABLE_BIN to a preinstalled engine binary. 1>&2
|
||||||
|
exit /b 127
|
||||||
|
|
||||||
:fail
|
:fail
|
||||||
del "%cached%.part" >nul 2>nul
|
del "%cached%.part" >nul 2>nul
|
||||||
echo impeccable: no engine binary found (looked in %bin%, %cached%, PATH). 1>&2
|
echo impeccable: no engine binary found (looked in %bin%, %cached%, PATH). 1>&2
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
name: impeccable
|
name: impeccable
|
||||||
description: Use when the user wants to design, redesign, shape, critique, audit, polish, clarify, distill, harden, optimize, adapt, animate, colorize, extract, or otherwise improve a frontend interface. Covers websites, landing pages, dashboards, product UI, app shells, components, forms, settings, onboarding, and empty states. Handles UX review, visual hierarchy, information architecture, cognitive load, accessibility, performance, responsive behavior, theming, anti-patterns, typography, fonts, spacing, layout, alignment, color, motion, micro-interactions, UX copy, error states, edge cases, i18n, and reusable design systems or tokens. Also use for bland designs that need to become bolder or more delightful, loud designs that should become quieter, live browser iteration on UI elements, or ambitious visual effects that should feel technically extraordinary. Not for backend-only or non-UI tasks.
|
description: Use when the user wants to design, redesign, shape, critique, audit, polish, clarify, distill, harden, optimize, adapt, animate, colorize, extract, or otherwise improve a frontend interface. Covers websites, landing pages, dashboards, product UI, app shells, components, forms, settings, onboarding, and empty states. Handles UX review, visual hierarchy, information architecture, cognitive load, accessibility, performance, responsive behavior, theming, anti-patterns, typography, fonts, spacing, layout, alignment, color, motion, micro-interactions, UX copy, error states, edge cases, i18n, and reusable design systems or tokens. Also use for bland designs that need to become bolder or more delightful, loud designs that should become quieter, live browser iteration on UI elements, or ambitious visual effects that should feel technically extraordinary. Not for backend-only or non-UI tasks.
|
||||||
version: 4.2.2
|
version: 4.3.1
|
||||||
---
|
---
|
||||||
|
|
||||||
This skill gives you the tools and permission to create design that earns to be called out-of-distribution craft: Whereas before, your design work would have been safe, timid and measured, you now approach every design task as an award-winning design director with impeccable understanding for what makes exceptional design work: production-grade code, peak creativity, a clear POV, deep understanding of the needs of the client and users, and exceptional craft.
|
This skill gives you the tools and permission to create design that earns to be called out-of-distribution craft: Whereas before, your design work would have been safe, timid and measured, you now approach every design task as an award-winning design director with impeccable understanding for what makes exceptional design work: production-grade code, peak creativity, a clear POV, deep understanding of the needs of the client and users, and exceptional craft.
|
||||||
@@ -13,9 +13,11 @@ Core principles:
|
|||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
1. Run `<skill-base-dir>/scripts/impeccable context` once per session, where `<skill-base-dir>` is the directory that contains this SKILL.md (the skill folder, not a plugin root two levels above it); keep cwd at the user's project. That base directory resolves every `.gemini/skills/impeccable/scripts/impeccable <verb>` command in this skill and its references, and `.gemini/skills/impeccable/scripts` is the fallback only when the runtime reports no base directory. On a Windows shell without `sh`, call `.gemini/skills/impeccable/scripts/impeccable.cmd` instead. The launcher runs a self-contained binary that ships next to it or is downloaded once on first run; no Node or other runtime is required. Pass a named source file or route as `--target <path>`. It loads PRODUCT.md, DESIGN.md, the matching surface brief, and native-platform guidance when applicable; follow its directives and do not rerun it. If the launcher is refused, missing, or fails, tell the user before editing that context loading did not run. Read existing **PRODUCT.md** and **DESIGN.md** without inventing missing context, then continue with steps 2–3.
|
1. Run `<skill-base-dir>/scripts/impeccable context` once per session, where `<skill-base-dir>` is the directory that contains this SKILL.md (the skill folder, not a plugin root two levels above it); keep cwd at the user's project. That base directory resolves every `.gemini/skills/impeccable/scripts/impeccable <verb>` command in this skill and its references, and `.gemini/skills/impeccable/scripts` is the fallback only when the runtime reports no base directory. On a Windows shell without `sh`, call `.gemini/skills/impeccable/scripts/impeccable.cmd` instead. The launcher runs a self-contained binary that ships next to it or is downloaded once on first run; no Node or other runtime is required. Pass a named source file or route as `--target <path>`. It loads PRODUCT.md, DESIGN.md, the matching surface brief, and native-platform guidance when applicable; follow its directives and do not rerun it.
|
||||||
2. Load the request's playbook: its Commands-table reference for an explicit/implied sub-command, or [reference/new-work.md](reference/new-work.md) for a new surface or replacement visual world. Inspect target and incumbent visual truth before editing. When the app cannot run, start with committed visual-regression goldens or screenshot fixtures; verify target and freshness against current tokens, CSS, components, or assets, resolve conflicts, and compare theme/variant captures.
|
2. Load the request's playbook: its Commands-table reference for an explicit/implied sub-command, or [reference/new-work.md](reference/new-work.md) for a new surface or replacement visual world. Inspect target and incumbent visual truth before editing. When the app cannot run, start with committed visual-regression goldens or screenshot fixtures; verify target and freshness against current tokens, CSS, components, or assets, resolve conflicts, and compare theme/variant captures.
|
||||||
3. After analysis and direction are resolved, load [reference/craft-floor.md](reference/craft-floor.md) immediately before editing UI. It carries the quality floor, the absolute bans, and the reflexes no detector catches. Do not load it for planning-only work.
|
3. After resolving analysis and direction, read [reference/craft-floor.md](reference/craft-floor.md) immediately before any UI edit, including small refinements. It carries the quality floor, the absolute bans, and the reflexes no detector catches. Do not load it for planning-only work.
|
||||||
|
|
||||||
|
**Launcher unavailable:** On refusal or failure, send a separate message **before the next tool call**: “Context loading did not run; I’ll read the existing project context directly.” Then read existing PRODUCT.md and DESIGN.md without inventing missing context, follow applicable steps 2–3, and continue through permitted tools. This applies to planning and editing; launcher failure alone does not block either.
|
||||||
|
|
||||||
## How to design
|
## How to design
|
||||||
|
|
||||||
|
|||||||
@@ -188,6 +188,12 @@ Test thoroughly across contexts:
|
|||||||
- **Edge cases**: Very small screens (320px), very large screens (4K)
|
- **Edge cases**: Very small screens (320px), very large screens (4K)
|
||||||
- **Slow connections**: Test on throttled network
|
- **Slow connections**: Test on throttled network
|
||||||
|
|
||||||
|
**Custom controls** (sliders, drag surfaces, scrollable control strips): a before/after slider can pass every width check above and still refuse to drag on iOS, so exercise each one in scope in the same batched round as the checks above:
|
||||||
|
|
||||||
|
- **Primary gesture**: Tap it and confirm it responds as designed, then drag it with the target input method; the drag must complete, not just start
|
||||||
|
- **Scroll across it**: A swipe along the page's scroll axis across the control scrolls the page or container without activating it; a drag that starts on the control along its axis moves the control, not the page. Neither failure throws an error, so try both
|
||||||
|
- **Evidence**: Say what produced the evidence: an emulated viewport, synthesized touch input through a browser tool, which engine ran it (Chromium is not Safari), or a physical device. Screenshots and resized viewports verify layout, never a gesture. Name what stayed untested and move on; unreachable hardware is a reported gap, not a blocker
|
||||||
|
|
||||||
When the adaptation feels native to each context, hand off to `/impeccable polish` for the final pass.
|
When the adaptation feels native to each context, hand off to `/impeccable polish` for the final pass.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -48,11 +48,12 @@ Run comprehensive checks across 5 dimensions. Score each dimension 0-4 using the
|
|||||||
**Check for**:
|
**Check for**:
|
||||||
- **Fixed widths**: Hard-coded widths that break on mobile
|
- **Fixed widths**: Hard-coded widths that break on mobile
|
||||||
- **Touch targets**: Interactive elements < 44x44px
|
- **Touch targets**: Interactive elements < 44x44px
|
||||||
|
- **Broken touch interaction**: Custom sliders, drag surfaces, and scrollable control strips whose primary gesture fails under touch, that swallow page scroll or lose the drag to it, or that stay stuck after an interrupted gesture. Code tells: mouse-only handlers, no `touch-action` on a pointer-event drag surface, drag state that nothing clears on cancel, lost capture, or blur. Exercise the gesture when a browser tool can synthesize touch (a rendered viewport proves layout, not the gesture), then say what produced the evidence (emulated viewport, synthesized touch, which engine, physical device) and what stayed untested
|
||||||
- **Horizontal scroll**: Content overflow on narrow viewports
|
- **Horizontal scroll**: Content overflow on narrow viewports
|
||||||
- **Text scaling**: Layouts that break when text size increases
|
- **Text scaling**: Layouts that break when text size increases
|
||||||
- **Missing breakpoints**: No mobile/tablet variants
|
- **Missing breakpoints**: No mobile/tablet variants
|
||||||
|
|
||||||
**Score 0-4**: 0=Desktop-only (breaks on mobile), 1=Major issues (some breakpoints, many failures), 2=Partial (works on mobile, rough edges), 3=Good (responsive, minor touch target or overflow issues), 4=Excellent (fluid, all viewports, proper touch targets)
|
**Score 0-4**: 0=Desktop-only (breaks on mobile), 1=Major issues (some breakpoints, many failures), 2=Partial (works on mobile, rough edges), 3=Good (responsive, minor touch target or overflow issues), 4=Excellent (fluid, all viewports, proper touch targets, gestures work under touch)
|
||||||
|
|
||||||
### 5. Implementation Integrity (CRITICAL)
|
### 5. Implementation Integrity (CRITICAL)
|
||||||
|
|
||||||
|
|||||||
@@ -26,12 +26,12 @@ Every region with `medium: raster` in the spec ships as a plate at its `plate` p
|
|||||||
Per region, in the spec's order:
|
Per region, in the spec's order:
|
||||||
|
|
||||||
1. `.gemini/skills/impeccable/scripts/impeccable comp-spec --crop <id>` writes the reference crop under `.impeccable/build/crops/`.
|
1. `.gemini/skills/impeccable/scripts/impeccable comp-spec --crop <id>` writes the reference crop under `.impeccable/build/crops/`.
|
||||||
2. Produce the plate. With the API fallback: `.gemini/skills/impeccable/scripts/impeccable generate-image --plate <id> --quality high` does the whole step (crop as reference, the spec's plate prompt, output size chosen from the region's aspect, the file written to its plate path, prompt embedded, and the plate scored against the crop). With a harness-native image tool: use the crop as the input image and `.gemini/skills/impeccable/scripts/impeccable comp-spec --plate-prompt <id>` as the prompt, write the result to the plate path, then run `.gemini/skills/impeccable/scripts/impeccable embed-prompt <plate> --prompt "<the exact prompt>"`.
|
2. Choose the background from the approved region: an isolated figure, object, or line drawing on the page ground is a **transparent cutout**; a photograph, full-frame illustration, or texture stays **opaque**. Save `.gemini/skills/impeccable/scripts/impeccable comp-spec --plate-prompt <id> --background transparent` to a UTF-8 prompt file for a cutout; use `--background opaque` otherwise. The transparent prompt preserves reference placement and clear margins, white paint, fine edges, and interior holes.
|
||||||
3. Read the score line. `PLATE-SCORE` under 50%, or a `PLATE-WARN`, means the plate does not read as the region: open the plate beside the crop, name what drifted (subject, framing, palette, style), tighten the prompt with that, and regenerate once. Two misses on one region: keep the better plate, mark it `needs_parent_review`, and say why in one line.
|
3. Produce the plate at its exact spec `plate` path. Create the output directory first and choose a supported output size matching the region's aspect, at least 1.5x its pixel dimensions. Prefer the harness-native image tool with the crop as input and the saved prompt; request a transparent PNG for cutouts, then run `.gemini/skills/impeccable/scripts/impeccable embed-prompt <plate> --prompt-file <prompt.txt>` (if you refine the prompt, save and embed the exact text sent). With the API fallback, run `.gemini/skills/impeccable/scripts/impeccable generate-image --ref <crop.png> --prompt-file <prompt.txt> --out <plate.png> --size <WxH> --quality high --background transparent` for a cutout, or `--background opaque` otherwise. The API fallback embeds the prompt and records the background in the sidecar. The output must be PNG; the fallback requests native alpha and performs no chroma-keying.
|
||||||
4. Transparent cutouts (a figure or object on the page ground): generate on a flat chroma color absent from the subject and key it to alpha before writing the PNG; never ship the keyed background.
|
4. Open the plate beside the crop and compare subject, placement, scale, palette, and style. For cutouts, verify a real alpha channel and inspect composites on light and dark grounds: white paint must stay solid, interior holes must clear, and fine edges must avoid halos. Inspect glass and soft shadows carefully; partial alpha alone does not ensure convincing translucency. Never chroma-key native transparent output or flatten it before saving. If a native tool returns opaque pixels or a painted checkerboard, retry with the API fallback when available; otherwise report the transparency blocker. On a visual miss, tighten the prompt and regenerate once. Two misses on one region: keep the better plate, mark it `needs_parent_review`, and name the drift. The parent runs the plates gate after all assets exist; report `unscored` until a gate score is available.
|
||||||
|
|
||||||
Do not redesign. Do not add objects, restyle, or reinterpret; the comp was approved as it is. Do not touch the page code, the spec, or the comp. Do not produce anything the spec does not list; a region the parent forgot goes back as a one-line note, not a plate.
|
Do not redesign. Do not add objects, restyle, or reinterpret; the comp was approved as it is. Do not touch the page code, the spec, or the comp. Do not produce anything the spec does not list; a region the parent forgot goes back as a one-line note, not a plate.
|
||||||
|
|
||||||
## Output Contract
|
## Output Contract
|
||||||
|
|
||||||
Return one line per raster region: `<id> <plate path> <WxH> <score>% <accepted|needs_parent_review|blocked> <one-line note or ->`. Then `blockers` (missing spec, missing comp, no image capability, exhausted key) and `assumptions`, each global and minimal. Nothing else: no summary, no praise, no implementation advice. The parent runs `impeccable build-phase advance` to verify the plates against the same spec; your line and its line must agree.
|
Return one line per raster region: `<id> <plate path> <WxH> <score%|unscored> <accepted|needs_parent_review|blocked> <one-line note or ->`. Then `blockers` (missing spec, missing comp, no image capability, exhausted key) and `assumptions`, each global and minimal. Nothing else: no summary, no praise, no implementation advice. The parent runs `impeccable build-phase advance` to verify the plates against the same spec; a visual acceptance does not override a failing gate.
|
||||||
@@ -5,7 +5,7 @@ This harness has no subagent capability, so you are running this role inline. St
|
|||||||
|
|
||||||
You record a project's design system after the build is done. Ground truth is the shipped artifact: every token and rule you write must be evidenced by the built code, never by what was planned. Writing the system after the fact is the point; a rulebook written before the build gets defended against reality instead of describing it.
|
You record a project's design system after the build is done. Ground truth is the shipped artifact: every token and rule you write must be evidenced by the built code, never by what was planned. Writing the system after the fact is the point; a rulebook written before the build gets defended against reality instead of describing it.
|
||||||
|
|
||||||
You run under a hard turn ceiling that ends the run without warning, and a run that ends before DESIGN.md is written has recorded nothing. Batch several Reads into each turn, take `reference/document.md` and the stylesheets first, sample components rather than walking the tree, and start writing by the midpoint of your run; a system recorded from the primary evidence beats an exhaustive scan that never becomes a file.
|
Complete the check within your turn ceiling. Batch Reads, take `reference/document.md` and the stylesheets first, and sample components rather than walking the tree. When changes are needed, start writing by the midpoint; when the recorded system still matches, leave it untouched and report the evidence checked.
|
||||||
|
|
||||||
## Input Contract
|
## Input Contract
|
||||||
|
|
||||||
@@ -15,10 +15,10 @@ Expect: the project root; the artifact path(s); the direction contract text (THE
|
|||||||
|
|
||||||
1. Read `reference/document.md` in full; it is the operating spec for DESIGN.md's format, token schema, sidecar, and section order. Follow it exactly.
|
1. Read `reference/document.md` in full; it is the operating spec for DESIGN.md's format, token schema, sidecar, and section order. Follow it exactly.
|
||||||
2. Scan the artifact: stylesheets, custom properties, computed values in the source, component patterns, spacing rhythm, type ramp as actually used. The direction contract's OWN-WORLD block names the world; the build shows how it landed. Where they diverge, the build wins and the prose may note the divergence.
|
2. Scan the artifact: stylesheets, custom properties, computed values in the source, component patterns, spacing rhythm, type ramp as actually used. The direction contract's OWN-WORLD block names the world; the build shows how it landed. Where they diverge, the build wins and the prose may note the divergence.
|
||||||
3. Write DESIGN.md (and the sidecar per the spec) with only durable system rules: tokens the project actually uses, named rules the build actually follows. Skip one-off values; a token used once is not a system.
|
3. For a new world or approved system change, write DESIGN.md and its sidecar from durable, reused rules in the build. Ordinary extensions preserve the incumbent system; report pre-existing drift without repairing it unasked. Do not write merely to prove this pass ran.
|
||||||
4. Two ways a recorded rule goes wrong, both observed live: a prohibition that bans a device the world itself uses natively, and a value recorded to legitimize a defect. Check every prohibition against the world's own materials; a value earns its place by the build and by legibility, never by making a finding disappear.
|
4. Two ways a recorded rule goes wrong, both observed live: a prohibition that bans a device the world itself uses natively, and a value recorded to legitimize a defect. Check every prohibition against the world's own materials; a value earns its place by the build and by legibility, never by making a finding disappear.
|
||||||
5. Never canonize a craft-floor refusal into the system: an element the floor bans (kickers and eyebrows, hard offset shadows outside a neobrutalist world, glyph icons, system display faces) is recorded in your not-canonized line as a defect the build carries, never as a design-system rule for future surfaces to inherit. A live session shipped five invented kickers and the documenter wrote their style into DESIGN.md; that is how one violation becomes the house style.
|
5. Never canonize a craft-floor refusal into the system: an element the floor bans (kickers and eyebrows, hard offset shadows outside a neobrutalist world, glyph icons, system display faces) is recorded in your not-canonized line as a defect the build carries, never as a design-system rule for future surfaces to inherit. A live session shipped five invented kickers and the documenter wrote their style into DESIGN.md; that is how one violation becomes the house style.
|
||||||
|
|
||||||
## Output Contract
|
## Output Contract
|
||||||
|
|
||||||
Return: the file paths written, a five-line summary of the recorded system (palette strategy, type ramp shape, named rules), and one line naming anything in the build you deliberately did not canonize and why. No other prose.
|
Return: paths written, or “No changes” with the source and system files checked; a five-line system summary (palette, type ramp, named rules); and one line naming defects or drift not canonized or repaired, and why. No other prose.
|
||||||
@@ -205,6 +205,11 @@ t('items', { count }) // Handles complex plural rules
|
|||||||
- Optimistic updates with rollback
|
- Optimistic updates with rollback
|
||||||
- Conflict resolution
|
- Conflict resolution
|
||||||
|
|
||||||
|
**Interrupted gestures** (custom sliders, drag surfaces, scrollable control strips):
|
||||||
|
- A second finger or pointer lands mid-drag: the first drag keeps its pointer or ends cleanly, never jumps to the new one
|
||||||
|
- The browser cancels the gesture to scroll (`pointercancel`), capture is lost (`lostpointercapture`), the pointer is released outside the control, or the window loses focus (`blur`) mid-drag: clear the dragging state and release capture
|
||||||
|
- After each of these, the next tap or drag works without a reload
|
||||||
|
|
||||||
**Permission states**:
|
**Permission states**:
|
||||||
- No permission to view
|
- No permission to view
|
||||||
- No permission to edit
|
- No permission to edit
|
||||||
@@ -304,6 +309,7 @@ const throttledScroll = throttle(handleScroll, 100);
|
|||||||
- Unit tests for edge cases
|
- Unit tests for edge cases
|
||||||
- Integration tests for error scenarios
|
- Integration tests for error scenarios
|
||||||
- E2E tests for critical paths
|
- E2E tests for critical paths
|
||||||
|
- A behavioral regression for each confirmed gesture fix, when the project's test runner can drive input
|
||||||
- Visual regression tests
|
- Visual regression tests
|
||||||
- Accessibility tests (axe, WAVE)
|
- Accessibility tests (axe, WAVE)
|
||||||
|
|
||||||
@@ -330,7 +336,10 @@ Test thoroughly with edge cases:
|
|||||||
- **Network issues**: Disable internet, throttle connection
|
- **Network issues**: Disable internet, throttle connection
|
||||||
- **Large datasets**: Test with 1000+ items
|
- **Large datasets**: Test with 1000+ items
|
||||||
- **Concurrent actions**: Click submit 10 times rapidly
|
- **Concurrent actions**: Click submit 10 times rapidly
|
||||||
|
- **Interrupted gestures**: Add a second finger mid-drag, scroll across the control, release outside it, switch windows mid-drag; then drag again
|
||||||
- **Errors**: Force API errors, test all error states
|
- **Errors**: Force API errors, test all error states
|
||||||
- **Empty**: Remove all data, test empty states
|
- **Empty**: Remove all data, test empty states
|
||||||
|
|
||||||
|
For gestures, say what produced the evidence (emulated viewport, synthesized touch, which engine, physical device) and name what stayed untested.
|
||||||
|
|
||||||
When edge cases are covered, hand off to `/impeccable polish` for the final pass.
|
When edge cases are covered, hand off to `/impeccable polish` for the final pass.
|
||||||
|
|||||||
@@ -42,6 +42,8 @@ On every boot the project is scanned for HTML files under common page roots (`pu
|
|||||||
|
|
||||||
## CSP detection (first-time only)
|
## CSP detection (first-time only)
|
||||||
|
|
||||||
|
Keep all allowances below development-only, including manual middleware and meta-tag edits. Do not change a deployed production site's CSP to load the localhost helper; see [live.md](live.md) for production inspection alternatives.
|
||||||
|
|
||||||
If `config.cspChecked === true`, skip this whole section; the user was already asked once.
|
If `config.cspChecked === true`, skip this whole section; the user was already asked once.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ Interactive live variant mode: select elements in the browser, pick a design act
|
|||||||
|
|
||||||
A running dev server with HMR (Vite, Next.js, Bun, etc.), OR a static HTML file open in the browser. If the dev server's default port is busy, the app is very likely ALREADY running; probe the default URL before spawning a second server.
|
A running dev server with HMR (Vite, Next.js, Bun, etc.), OR a static HTML file open in the browser. If the dev server's default port is busy, the app is very likely ALREADY running; probe the default URL before spawning a second server.
|
||||||
|
|
||||||
|
Live editing requires a local checkout; injection into deployed production sites (including HTTPS) is unsupported. For production inspection, use `.gemini/skills/impeccable/scripts/impeccable detect <url>` or the browser extension, not the live helper. Do not disable browser security or weaken production CSP to enable live mode.
|
||||||
|
|
||||||
## The contract (read once)
|
## The contract (read once)
|
||||||
|
|
||||||
Execute in order. No step skipped, no step reordered. Every tool output in live mode may carry an `_instructions` field: it is the authoritative next step for that exact situation, with real ids and paths substituted; when it conflicts with your recollection of this document, `_instructions` wins.
|
Execute in order. No step skipped, no step reordered. Every tool output in live mode may carry an `_instructions` field: it is the authoritative next step for that exact situation, with real ids and paths substituted; when it conflicts with your recollection of this document, `_instructions` wins.
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ A section, component, feature, or state inside an established surface inherits t
|
|||||||
|
|
||||||
## 2. Ask what will change the work
|
## 2. Ask what will change the work
|
||||||
|
|
||||||
Ask one round of two or three related questions through the structured question tool when available. Skip settled facts; a precise request may need only a compact confirmation.
|
Before implementation, get the user's answer through the structured question tool when available. Ask two or three related questions; a precise request needs only a compact confirmation. Skip settled facts, not the confirmation: DESIGN.md settles the visual world, not this surface's purpose or concept.
|
||||||
|
|
||||||
- **Persuade:** who must act, what they should believe, which real proof, content, or assets earn that belief.
|
- **Persuade:** who must act, what they should believe, which real proof, content, or assets earn that belief.
|
||||||
- **Operate:** the task, information, important states, frequency, constraints.
|
- **Operate:** the task, information, important states, frequency, constraints.
|
||||||
@@ -68,7 +68,7 @@ Calibration: AI-generated interfaces cluster around a few looks regardless of su
|
|||||||
|
|
||||||
## 5. Record the decision
|
## 5. Record the decision
|
||||||
|
|
||||||
Before code, record the chosen direction as a development-only contract under `## Direction contract` in the relevant surface brief. A direction contract is durable route or artifact strategy, so create or update the brief even when no other surface strategy needs persistence. Keep the contract to six short blocks and 150 words at most. THESIS: the one idea this surface owns and the category-default arrangement it refuses. OWN-WORLD: the palette and component language, specific enough to be recognizable with all content removed. STORY: what the visitor understands, believes, and does. FIRST VIEWPORT: the exact composition, what is where and at what scale, and where the primary action sits. FORM: the chosen form, its position on your ordered list, and the seed key the script printed. Close with one more line, FINISH: the run's exit condition, verbatim "unreviewed and undocumented is unfinished; this build ends with the finish review, the verdict, DESIGN.md, and every shipping raster carrying its provenance". The surface brief is the reminder later agents reload across edits and sessions: a page that looks complete with the FINISH line undischarged is not done, it is abandoned at the finish line. If a block reads like a mood, the direction is not decided yet; the finishing review audits the render against this contract.
|
Before code, record the chosen direction as a development-only contract under `## Direction contract` in the relevant surface brief. A direction contract is durable route or artifact strategy, so create or update the brief even when no other surface strategy needs persistence. Use six short blocks, roughly 150 words; do not spend tool calls counting words. THESIS: the one idea this surface owns and the category-default arrangement it refuses. OWN-WORLD: the palette and component language, specific enough to be recognizable with all content removed. STORY: what the visitor understands, believes, and does. FIRST VIEWPORT: the exact composition, what is where and at what scale, and where the primary action sits. FORM: the chosen form, its position on your ordered list, and the seed key the script printed. Close with one more line, FINISH: the run's exit condition, verbatim "unreviewed and undocumented is unfinished; this build ends with the finish review, the verdict, DESIGN.md, and every shipping raster carrying its provenance". The surface brief is the reminder later agents reload across edits and sessions: a page that looks complete with the FINISH line undischarged is not done, it is abandoned at the finish line. If a block reads like a mood, the direction is not decided yet; the finishing review audits the render against this contract.
|
||||||
|
|
||||||
Never copy the direction contract into implementation source or any browser-delivered artifact. This includes HTML or framework comments, hidden DOM, `<template>` elements, `data-*` attributes, rendered JSX or TSX output, serialized props or state, React Server Component payloads, client bundles, metadata or JSON-LD, accessibility-only text, and files served beside the artifact. A compiler or optimizer removing development metadata is not a safety boundary. Reviewers and documenters receive the contract from the surface brief.
|
Never copy the direction contract into implementation source or any browser-delivered artifact. This includes HTML or framework comments, hidden DOM, `<template>` elements, `data-*` attributes, rendered JSX or TSX output, serialized props or state, React Server Component payloads, client bundles, metadata or JSON-LD, accessibility-only text, and files served beside the artifact. A compiler or optimizer removing development metadata is not a safety boundary. Reviewers and documenters receive the contract from the surface brief.
|
||||||
|
|
||||||
@@ -104,7 +104,7 @@ Then, in order, each closed by `.gemini/skills/impeccable/scripts/impeccable bui
|
|||||||
The comp-led path is a frontier-tier job: it asks the builder to hold a measured layout, place plates at their boxes, and act on numeric readings across a dozen attempts. Smaller or faster models produce a recognisable page and stall under the hero gate; if the model in hand is one of those, say so before the direction round and take the code-led path, or expect the run to end at the hero with its readings unmet.
|
The comp-led path is a frontier-tier job: it asks the builder to hold a measured layout, place plates at their boxes, and act on numeric readings across a dozen attempts. Smaller or faster models produce a recognisable page and stall under the hero gate; if the model in hand is one of those, say so before the direction round and take the code-led path, or expect the run to end at the hero with its readings unmet.
|
||||||
|
|
||||||
1. **spec.** Measure the comp: `impeccable comp-spec --comp <comp> --grid` writes a coordinate grid over the comp; open it, name every salient region by grid span in a regions file (text and control regions snap to the largest ink mass inside their span, so a headline named B1:E4 measures as the headline and not the column beside it; `snap: false` keeps the span, and an explicit `box` is taken as drawn) (kind `plate` / `image` / `texture` for anything painted: every illustration, photograph, figure, product object, and material texture; `text` / `control` / `chrome` for what code draws; every region carries a `note` saying what the comp shows there, which the plate prompt and the gate messages read), and run `impeccable comp-spec --comp <comp> --regions <file>`. The spec carries each region's box, sampled palette, and medium; `impeccable comp-spec --print` is the build's reference from here on. Type is measured, not guessed: `impeccable font-match --measure <text region>` reads the comp's cap height, width class, and weight off the pixels, and `impeccable font-match --rank <region> --text "..."` takes its candidates from a fingerprint index of the Google Fonts catalog (the nearest faces to the crop's shape) plus any names you pass with `--candidates`, renders them at that cap height with the region's words, and ranks them by fingerprint distance (its `USE` line is the CSS; its proof sheet shows the comp over the top three); with no browser resolvable it records the catalog's nearest face and says the size is estimated, which is still the choice to build on. Do not install a browser to rank, and never write a `chosen` face into the spec by hand: the gate accepts only what font-match wrote. The spec gate refuses to close until the lead text region is measured and ranked. A region note that describes painted material (a diagram, drawing, photograph, texture) under a code kind is refused at the spec: reclassify it as a plate, or reword the note if code really draws it. The script refuses a regions file that leaves comp ink unnamed (callouts, a parts table, a notes block): what is never named can never be missing, so everything the comp shows gets a region. It also refuses a `text` / `control` / `chrome` region larger than a quarter of the comp: that is a column, not an element, and a column scored as one region hides the plates, tables, and notes inside it. Name each element inside it (`container: true` only when it truly is one undivided element). Anything drawn is a plate: an inline SVG past an icon's budget (a diagram, notation, leader lines with arrows, a "quick approximation" of the artwork) is refused at the hero; icon-sized SVG (under 64px, a few paths) is fine, and a chart the page draws from data at runtime is a chart, not an illustration. Callout lines and arrows that annotate a drawing belong to that drawing's plate, with only their labels set as text. A crop of the comp is never a plate (the plates gate refuses a file that is a resample of the comp region: the comp's grain, its neighbours' edges, and its resolution would ship as the artwork); the crop is the reference the plate is generated from. A plate region's box has to hold its whole artwork with a margin: the spec measures the artwork's contact with the box edges and refuses a box that cuts through it (`bleed: true` only when the page really crops it there), because a plate placed with `object-fit: cover` on such a box shows the artwork minus the side the box lost. Anything not in the spec does not exist on the page: no borders, rules, containers, or chrome the comp does not show. Only three concessions exist: fonts (the closest obtainable face), icon glyphs (close enough, exact if the user chose an icon library; this covers the pictogram only, never a control's chrome, so a chevron, an arrow, a dropdown's border and fill, a button's shape are the comp's), and genuine defects in the comp such as spelling errors.
|
1. **spec.** Measure the comp: `impeccable comp-spec --comp <comp> --grid` writes a coordinate grid over the comp; open it, name every salient region by grid span in a regions file (text and control regions snap to the largest ink mass inside their span, so a headline named B1:E4 measures as the headline and not the column beside it; `snap: false` keeps the span, and an explicit `box` is taken as drawn) (kind `plate` / `image` / `texture` for anything painted: every illustration, photograph, figure, product object, and material texture; `text` / `control` / `chrome` for what code draws; every region carries a `note` saying what the comp shows there, which the plate prompt and the gate messages read), and run `impeccable comp-spec --comp <comp> --regions <file>`. The spec carries each region's box, sampled palette, and medium; `impeccable comp-spec --print` is the build's reference from here on. Type is measured, not guessed: `impeccable font-match --measure <text region>` reads the comp's cap height, width class, and weight off the pixels, and `impeccable font-match --rank <region> --text "..."` takes its candidates from a fingerprint index of the Google Fonts catalog (the nearest faces to the crop's shape) plus any names you pass with `--candidates`, renders them at that cap height with the region's words, and ranks them by fingerprint distance (its `USE` line is the CSS; its proof sheet shows the comp over the top three); with no browser resolvable it records the catalog's nearest face and says the size is estimated, which is still the choice to build on. Do not install a browser to rank, and never write a `chosen` face into the spec by hand: the gate accepts only what font-match wrote. The spec gate refuses to close until the lead text region is measured and ranked. A region note that describes painted material (a diagram, drawing, photograph, texture) under a code kind is refused at the spec: reclassify it as a plate, or reword the note if code really draws it. The script refuses a regions file that leaves comp ink unnamed (callouts, a parts table, a notes block): what is never named can never be missing, so everything the comp shows gets a region. It also refuses a `text` / `control` / `chrome` region larger than a quarter of the comp: that is a column, not an element, and a column scored as one region hides the plates, tables, and notes inside it. Name each element inside it (`container: true` only when it truly is one undivided element). Anything drawn is a plate: an inline SVG past an icon's budget (a diagram, notation, leader lines with arrows, a "quick approximation" of the artwork) is refused at the hero; icon-sized SVG (under 64px, a few paths) is fine, and a chart the page draws from data at runtime is a chart, not an illustration. Callout lines and arrows that annotate a drawing belong to that drawing's plate, with only their labels set as text. A crop of the comp is never a plate (the plates gate refuses a file that is a resample of the comp region: the comp's grain, its neighbours' edges, and its resolution would ship as the artwork); the crop is the reference the plate is generated from. A plate region's box has to hold its whole artwork with a margin: the spec measures the artwork's contact with the box edges and refuses a box that cuts through it (`bleed: true` only when the page really crops it there), because a plate placed with `object-fit: cover` on such a box shows the artwork minus the side the box lost. Anything not in the spec does not exist on the page: no borders, rules, containers, or chrome the comp does not show. Only three concessions exist: fonts (the closest obtainable face), icon glyphs (close enough, exact if the user chose an icon library; this covers the pictogram only, never a control's chrome, so a chevron, an arrow, a dropdown's border and fill, a button's shape are the comp's), and genuine defects in the comp such as spelling errors.
|
||||||
2. **plates.** Every raster region ships as a plate: an illustration, photo, or figure regenerated at asset resolution from its comp crop, UI text removed, at its `plate` path (ink on flat ground is generated on a chroma key and keyed to alpha, so it sits on the page's own ground rather than a second paper); a texture (paper, cloth, grain) is a clean patch of the comp region mirror-tiled to size, generated only when no clean patch exists. `impeccable generate-image --plate <id>` does one region end to end and scores it against the crop; a harness-native image tool takes the crop (`impeccable comp-spec --crop <id>`) as its input image and `impeccable comp-spec --plate-prompt <id>` as its prompt, then `impeccable embed-prompt`. With parallel subagents, spawn the shipped asset producer (`impeccable-asset-producer`; `impeccable_asset_producer` in codex; `/impeccable-asset-producer` in Cursor; on GitHub Copilot say "Use the impeccable-asset-producer agent") with the spec path and let it produce them all; without subagents, produce them here. A crop of the comp is a reference, never a shipping pixel. The gate checks every plate exists, is at least 1.5x the region's size, and reads as the region. Page code waits for this gate: a page written before its plates exist is a page that draws its material in CSS. A single-file deliverable changes nothing here: the plate is produced the same way and inlined as a data URI. `--force` exists for one case only, the user downgrading the comp's authority in words you quote in `--reason`; the script refuses every other reason.
|
2. **plates.** Every raster region ships as a plate: an illustration, photo, or figure regenerated at asset resolution from its comp crop, UI text removed, at its `plate` path (isolated ink, figures, or objects use native transparent PNG so they sit on the page's own ground; photos and textures stay opaque); a texture (paper, cloth, grain) is a clean patch of the comp region mirror-tiled to size, generated only when no clean patch exists. `impeccable comp-spec --crop <id>` writes the reference; save `impeccable comp-spec --plate-prompt <id> --background transparent` to a prompt file for a cutout, or use `--background opaque` otherwise. Prefer the harness-native image tool with that crop and prompt, then `impeccable embed-prompt <plate> --prompt-file <prompt.txt>`. The API fallback is `impeccable generate-image --ref <crop.png> --prompt-file <prompt.txt> --out <plate.png> --size <WxH> --quality high --background transparent` (use `--background opaque` for full-frame assets); create the output directory first. Verify actual alpha, white foregrounds, fine edges, and clear holes on light and dark grounds; do not chroma-key native output. The plates gate scores the assets against the comp; also inspect placement and scale visually. With parallel subagents, spawn the shipped asset producer (`impeccable-asset-producer`; `impeccable_asset_producer` in codex; `/impeccable-asset-producer` in Cursor; on GitHub Copilot say "Use the impeccable-asset-producer agent") with the spec path and let it produce them all; without subagents, produce them here. A crop of the comp is a reference, never a shipping pixel. The gate checks every plate exists, is at least 1.5x the region's size, and reads as the region. Page code waits for this gate: a page written before its plates exist is a page that draws its material in CSS. A single-file deliverable changes nothing here: the plate is produced the same way and inlined as a data URI. `--force` exists for one case only, the user downgrading the comp's authority in words you quote in `--reason`; the script refuses every other reason.
|
||||||
3. **hero.** `impeccable build-phase scaffold` first: it writes the measured layout as CSS custom properties (`.impeccable/build/scaffold/layout.css`: `--r-<id>-x/y/w/h` in % of the comp, plus cap height, font-size, family, and weight where measured) and a reference page (`hero-reference.html`) with every region at its box and every plate placed. Bind the numbers to your own semantic structure, an element per region; the reference is a check on positions, never the page, and overlapping boxes are overlapping boxes. Then build only the first viewport, at the comp's own dimensions, the comp's words copied verbatim (the user approved that comp with those words; rewording is a stated decision after the hero passes, never a silent one inside it), every text region sized from its measured cap height and set in its ranked face, plates first: place every plate at its spec box (`object-fit: cover`, an `<img>`, a background image, or an inlined data URI named for it) before any text or control, capture into `.impeccable/review/hero-repro.png`, run `impeccable build-phase record hero` once so you see the plate regions read as match before any text exists, then lay the semantic layer over the plates from the spec's palette and boxes and advance. The gate first refuses while any plate is unreferenced by the source, then runs `impeccable comp-diff`, writes `.impeccable/review/diff/hero/` (side-by-side, heatmap, one paired crop per region, `report.json`), and passes at 72% overall with no hard veto outstanding (a missing region, a contradicted plate or text block, an SVG illustration, a clipped plate, invented ink block at any score); above the bar, the numeric readings become advisories printed with the pass, and the polish pass before responsive is where they get fixed: the gate also reads each text region's cap height, line count, weight, ink colour, and position against the comp, each chrome strip's height off its rule, and the frame for ink where the comp is calm (a kicker, an extra nav item, a divider), and says each miss as a number ("cap height 78px in the build, 103px in the comp"); those numbers are the edit. When it fails, open the region crops it lists, in order, before editing: a region scored `missing` needs its material, `contradicted` needs its structure re-derived from the spec box, `drift` is where size and spacing edits belong; the gate refuses a third attempt that only nudges values on the same region. This is where the run's ambition is won or lost, and a retry here costs minutes where a rebuild verdict at the finish costs the run.
|
3. **hero.** `impeccable build-phase scaffold` first: it writes the measured layout as CSS custom properties (`.impeccable/build/scaffold/layout.css`: `--r-<id>-x/y/w/h` in % of the comp, plus cap height, font-size, family, and weight where measured) and a reference page (`hero-reference.html`) with every region at its box and every plate placed. Bind the numbers to your own semantic structure, an element per region; the reference is a check on positions, never the page, and overlapping boxes are overlapping boxes. Then build only the first viewport, at the comp's own dimensions, the comp's words copied verbatim (the user approved that comp with those words; rewording is a stated decision after the hero passes, never a silent one inside it), every text region sized from its measured cap height and set in its ranked face, plates first: place every plate at its spec box (`object-fit: cover`, an `<img>`, a background image, or an inlined data URI named for it) before any text or control, capture into `.impeccable/review/hero-repro.png`, run `impeccable build-phase record hero` once so you see the plate regions read as match before any text exists, then lay the semantic layer over the plates from the spec's palette and boxes and advance. The gate first refuses while any plate is unreferenced by the source, then runs `impeccable comp-diff`, writes `.impeccable/review/diff/hero/` (side-by-side, heatmap, one paired crop per region, `report.json`), and passes at 72% overall with no hard veto outstanding (a missing region, a contradicted plate or text block, an SVG illustration, a clipped plate, invented ink block at any score); above the bar, the numeric readings become advisories printed with the pass, and the polish pass before responsive is where they get fixed: the gate also reads each text region's cap height, line count, weight, ink colour, and position against the comp, each chrome strip's height off its rule, and the frame for ink where the comp is calm (a kicker, an extra nav item, a divider), and says each miss as a number ("cap height 78px in the build, 103px in the comp"); those numbers are the edit. When it fails, open the region crops it lists, in order, before editing: a region scored `missing` needs its material, `contradicted` needs its structure re-derived from the spec box, `drift` is where size and spacing edits belong; the gate refuses a third attempt that only nudges values on the same region. This is where the run's ambition is won or lost, and a retry here costs minutes where a rebuild verdict at the finish costs the run.
|
||||||
4. **sections.** Build the rest of the surface inside the spec's system: the same corner language, line weights, and palette, and nothing the comp never shows. Where the comp does not cover a region, it inherits the recorded system.
|
4. **sections.** Build the rest of the surface inside the spec's system: the same corner language, line weights, and palette, and nothing the comp never shows. Where the comp does not cover a region, it inherits the recorded system.
|
||||||
5. **motion.** The signature interaction, reveals, and motion, orchestrated once rather than scattered.
|
5. **motion.** The signature interaction, reveals, and motion, orchestrated once rather than scattered.
|
||||||
@@ -142,4 +142,4 @@ A rebuild and a fix round share one asset rule: a raster either round creates or
|
|||||||
|
|
||||||
Report the final verdict under the reviewer's own disposition word and at its actual scope. A verdict pass scores the listed fixes and nothing else: "the reviewer scored all three fixes resolved" is a claim it supports, "no material issues remain" is not. A table with open material findings is never announced as a pass, never softened, and never dressed as whole-surface approval when only a fix list was scored. When the user answers a ship with evidence against it, their own screenshot, a named mismatch with the comp, that evidence outranks every capture you made: put their material in the packet and spawn a fresh reviewer for a new full review. Patching inline and self-certifying is how a rejected page ships twice.
|
Report the final verdict under the reviewer's own disposition word and at its actual scope. A verdict pass scores the listed fixes and nothing else: "the reviewer scored all three fixes resolved" is a claim it supports, "no material issues remain" is not. A table with open material findings is never announced as a pass, never softened, and never dressed as whole-surface approval when only a fix list was scored. When the user answers a ship with evidence against it, their own screenshot, a named mismatch with the comp, that evidence outranks every capture you made: put their material in the packet and spawn a fresh reviewer for a new full review. Patching inline and self-certifying is how a rejected page ships twice.
|
||||||
|
|
||||||
Then spawn the shipped documenter, `impeccable-documenter` (`impeccable_documenter` in codex), with the project root, the artifact path, the direction contract, PRODUCT.md, the [document.md](document.md) reference path, and the boundary to write at; it records DESIGN.md and the sidecar from the built world, ground truth over intention; without subagents the pass runs from [degraded/documenter.md](degraded/documenter.md). The documenter runs after the last correction lands: when any fix round follows the documentation, re-run the documenter over the changed surface, because a DESIGN.md describing a layout that no longer exists turns defects into system guidance. A clean detector pass is not finished; finished is the contract kept, the comp honored, the review closed, and the system recorded.
|
After the last correction, spawn the shipped documenter, `impeccable-documenter` (`impeccable_documenter` in codex), with the project root, artifact path, direction contract, PRODUCT.md, [document.md](document.md), and write boundary. Without subagents, load [degraded/documenter.md](degraded/documenter.md) and [document.md](document.md) before writing. Verify the outcome: new worlds and approved system changes require token-bearing DESIGN.md **and** `.impeccable/design.json`, not prose alone. Ordinary extensions compare the finished build against the incumbent system, preserve its files, and report the evidence checked; report pre-existing drift without repairing it unasked. Recheck after later edits. Finish only when review and documentation are complete.
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ What the comp shows is measured, not remembered. new-work.md section 6 runs the
|
|||||||
|
|
||||||
## Plates and provenance
|
## Plates and provenance
|
||||||
|
|
||||||
Every raster region's plate is produced in the plates phase, before any page code, by the shipped asset producer or in the current thread (`impeccable generate-image --plate <id>`, or the harness image tool with the crop as input and the spec's plate prompt). Generation context is part of the asset: after generating any image with any tool, run `.gemini/skills/impeccable/scripts/impeccable embed-prompt <image> --prompt "<prompt>"` with the exact string the tool received (`impeccable generate-image` does this itself), so the intent lives inside the file; `--read` recovers it, `--scan <dir>` lists rasters still missing one. The embedded prompt plus the region's row in the spec is the raster's **provenance**, and every raster the artifact references carries it; a sourced, stock, or pre-existing raster embeds its origin instead. A raster created or replaced later, in a fix batch or a reviewer's rebuild, is produced the same way; a raster a fix abandons is deleted in the same batch.
|
Every raster region's plate is produced in the plates phase, before any page code, by the shipped asset producer or in the current thread (use `impeccable comp-spec --crop <id>` and save `impeccable comp-spec --plate-prompt <id>` to a prompt file; pass the crop and prompt to the harness image tool, or use `impeccable generate-image --ref <crop.png> --prompt-file <prompt.txt> --out <plate.png> --size <WxH> --quality high`). For isolated cutouts, add `--background transparent` to both the plate-prompt and API generation commands; use native PNG alpha and preserve white paint and clear gaps. Use `--background opaque` for full-frame imagery. Create output directories first and inspect alpha on light and dark grounds. Generation context is part of the asset: after generating any image with any tool, run `.gemini/skills/impeccable/scripts/impeccable embed-prompt <image> --prompt "<prompt>"` with the exact string the tool received (`impeccable generate-image` does this itself), so the intent lives inside the file; `--read` recovers it, `--scan <dir>` lists rasters still missing one. The embedded prompt plus the region's row in the spec is the raster's **provenance**, and every raster the artifact references carries it; a sourced, stock, or pre-existing raster embeds its origin instead. A raster created or replaced later, in a fix batch or a reviewer's rebuild, is produced the same way; a raster a fix abandons is deleted in the same batch.
|
||||||
|
|
||||||
Convert images with a converter `impeccable context` reported at boot (the IMAGE_TOOLS line); probe only when it reported none, at most once per session, never per image.
|
Convert images with a converter `impeccable context` reported at boot (the IMAGE_TOOLS line); probe only when it reported none, at most once per session, never per image.
|
||||||
|
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
0.1.3
|
0.1.5
|
||||||
|
|||||||
@@ -87,6 +87,11 @@ fi
|
|||||||
# Last resort: fetch this version's binary for the current platform from the
|
# Last resort: fetch this version's binary for the current platform from the
|
||||||
# public release channel into the user cache. Needs network; sandboxes without
|
# public release channel into the user cache. Needs network; sandboxes without
|
||||||
# egress preinstall the binary on PATH instead.
|
# egress preinstall the binary on PATH instead.
|
||||||
|
setup_help() {
|
||||||
|
echo "Engine $version setup needs network access and write permission to $cache_root/bin/$version." >&2
|
||||||
|
echo "Run this launcher ($0) with engine-probe in a terminal that has those permissions, then retry the original command." >&2
|
||||||
|
echo "Alternatively, set IMPECCABLE_HOME to a writable cache location, or IMPECCABLE_BIN to a preinstalled engine binary." >&2
|
||||||
|
}
|
||||||
fetch_url() {
|
fetch_url() {
|
||||||
if command -v curl >/dev/null 2>&1; then
|
if command -v curl >/dev/null 2>&1; then
|
||||||
curl -fsSL --retry 2 -o "$tmp" "$1" 2>/dev/null
|
curl -fsSL --retry 2 -o "$tmp" "$1" 2>/dev/null
|
||||||
@@ -119,7 +124,18 @@ if [ -n "$version" ] && [ "$os" != unknown ] && [ "$arch" != unknown ]; then
|
|||||||
[ "$os" = windows ] && asset="$asset.exe"
|
[ "$os" = windows ] && asset="$asset.exe"
|
||||||
url="$base/engine-v$version/$asset"
|
url="$base/engine-v$version/$asset"
|
||||||
tmp="$cache_root/bin/$version/.impeccable.part.$$"
|
tmp="$cache_root/bin/$version/.impeccable.part.$$"
|
||||||
mkdir -p "$cache_root/bin/$version" 2>/dev/null
|
if ! mkdir -p "$cache_root/bin/$version" 2>/dev/null; then
|
||||||
|
echo "impeccable: engine $version is not installed; cannot create cache directory: $cache_root/bin/$version" >&2
|
||||||
|
setup_help
|
||||||
|
exit 127
|
||||||
|
fi
|
||||||
|
# Check the actual staging file, not just directory existence: a cache from
|
||||||
|
# an earlier run can be readable but no longer writable inside a sandbox.
|
||||||
|
if ! (umask 077; : > "$tmp") 2>/dev/null; then
|
||||||
|
echo "impeccable: engine $version is not installed; cannot write to cache directory: $cache_root/bin/$version" >&2
|
||||||
|
setup_help
|
||||||
|
exit 127
|
||||||
|
fi
|
||||||
fetched=0
|
fetched=0
|
||||||
if fetch_url "$url"; then
|
if fetch_url "$url"; then
|
||||||
fetched=1
|
fetched=1
|
||||||
@@ -180,6 +196,9 @@ if [ -n "$version" ] && [ "$os" != unknown ] && [ "$arch" != unknown ]; then
|
|||||||
exec "$cached" "$@"
|
exec "$cached" "$@"
|
||||||
fi
|
fi
|
||||||
rm -f "$tmp" 2>/dev/null
|
rm -f "$tmp" 2>/dev/null
|
||||||
|
echo "impeccable: could not download engine $version from $url; check network access, the release URL, and curl or wget availability." >&2
|
||||||
|
setup_help
|
||||||
|
exit 127
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "impeccable: no engine binary for $os-$arch found (looked in $bin, $cached, PATH)." >&2
|
echo "impeccable: no engine binary for $os-$arch found (looked in $bin, $cached, PATH)." >&2
|
||||||
|
|||||||
@@ -68,18 +68,27 @@ rem another launcher's probe: fail fast and quiet instead.
|
|||||||
if defined IMPECCABLE_LAUNCHER_PROBE exit /b 127
|
if defined IMPECCABLE_LAUNCHER_PROBE exit /b 127
|
||||||
if not defined version goto fail
|
if not defined version goto fail
|
||||||
where curl.exe >nul 2>nul
|
where curl.exe >nul 2>nul
|
||||||
if errorlevel 1 goto fail
|
if errorlevel 1 goto curl_missing
|
||||||
if not defined IMPECCABLE_DOWNLOAD_BASE set "IMPECCABLE_DOWNLOAD_BASE=https://github.com/pbakaus/impeccable/releases/download"
|
if not defined IMPECCABLE_DOWNLOAD_BASE set "IMPECCABLE_DOWNLOAD_BASE=https://github.com/pbakaus/impeccable/releases/download"
|
||||||
if not exist "%IMPECCABLE_HOME%\bin\%version%" mkdir "%IMPECCABLE_HOME%\bin\%version%" >nul 2>nul
|
if exist "%IMPECCABLE_HOME%\bin\%version%\" goto cache_ready
|
||||||
|
mkdir "%IMPECCABLE_HOME%\bin\%version%" >nul 2>nul
|
||||||
|
if errorlevel 1 goto cache_directory_failed
|
||||||
|
:cache_ready
|
||||||
|
rem Check the staging file too: an existing directory may be read-only.
|
||||||
|
rem Redirection failures do not reliably update ERRORLEVEL in cmd.exe;
|
||||||
|
rem branch on the command's failure directly. Never treat a directory as a
|
||||||
|
rem staging file (later del cleanup would prompt to delete its contents).
|
||||||
|
if exist "%cached%.part\" goto cache_write_failed
|
||||||
|
(type nul >"%cached%.part") 2>nul || goto cache_write_failed
|
||||||
set "asset=impeccable-windows-%arch%.exe"
|
set "asset=impeccable-windows-%arch%.exe"
|
||||||
set "url=%IMPECCABLE_DOWNLOAD_BASE%/engine-v%version%/%asset%"
|
set "url=%IMPECCABLE_DOWNLOAD_BASE%/engine-v%version%/%asset%"
|
||||||
curl.exe -fsSL -o "%cached%.part" "%url%" >nul 2>nul
|
curl.exe -fsSL -o "%cached%.part" "%url%" >nul 2>nul
|
||||||
if not errorlevel 1 goto verify
|
if not errorlevel 1 goto verify
|
||||||
if not "%arch%"=="arm64" goto fail
|
if not "%arch%"=="arm64" goto download_failed
|
||||||
set "asset=impeccable-windows-x64.exe"
|
set "asset=impeccable-windows-x64.exe"
|
||||||
set "url=%IMPECCABLE_DOWNLOAD_BASE%/engine-v%version%/%asset%"
|
set "url=%IMPECCABLE_DOWNLOAD_BASE%/engine-v%version%/%asset%"
|
||||||
curl.exe -fsSL -o "%cached%.part" "%url%" >nul 2>nul
|
curl.exe -fsSL -o "%cached%.part" "%url%" >nul 2>nul
|
||||||
if errorlevel 1 goto fail
|
if errorlevel 1 goto download_failed
|
||||||
|
|
||||||
:verify
|
:verify
|
||||||
call :check_download
|
call :check_download
|
||||||
@@ -176,6 +185,28 @@ if not errorlevel 1 set "probe_ok=1"
|
|||||||
del "%probe_tmp%" >nul 2>nul
|
del "%probe_tmp%" >nul 2>nul
|
||||||
exit /b 0
|
exit /b 0
|
||||||
|
|
||||||
|
:cache_directory_failed
|
||||||
|
echo impeccable: engine %version% is not installed; cannot create cache directory: "%IMPECCABLE_HOME%\bin\%version%" 1>&2
|
||||||
|
goto setup_failed
|
||||||
|
|
||||||
|
:cache_write_failed
|
||||||
|
echo impeccable: engine %version% is not installed; cannot write to cache directory: "%IMPECCABLE_HOME%\bin\%version%" 1>&2
|
||||||
|
goto setup_failed
|
||||||
|
|
||||||
|
:curl_missing
|
||||||
|
echo impeccable: cannot download engine %version%; curl.exe is unavailable. 1>&2
|
||||||
|
goto setup_failed
|
||||||
|
|
||||||
|
:download_failed
|
||||||
|
del "%cached%.part" >nul 2>nul
|
||||||
|
echo impeccable: could not download engine %version% from %url%; check network access and the release URL. 1>&2
|
||||||
|
|
||||||
|
:setup_failed
|
||||||
|
echo Engine %version% setup needs network access and write permission to "%IMPECCABLE_HOME%\bin\%version%". 1>&2
|
||||||
|
echo Run this launcher ("%~f0") with engine-probe in a terminal that has those permissions, then retry the original command. 1>&2
|
||||||
|
echo Alternatively, set IMPECCABLE_HOME to a writable cache location, or IMPECCABLE_BIN to a preinstalled engine binary. 1>&2
|
||||||
|
exit /b 127
|
||||||
|
|
||||||
:fail
|
:fail
|
||||||
del "%cached%.part" >nul 2>nul
|
del "%cached%.part" >nul 2>nul
|
||||||
echo impeccable: no engine binary found (looked in %bin%, %cached%, PATH). 1>&2
|
echo impeccable: no engine binary found (looked in %bin%, %cached%, PATH). 1>&2
|
||||||
|
|||||||
@@ -27,12 +27,12 @@ Every region with `medium: raster` in the spec ships as a plate at its `plate` p
|
|||||||
Per region, in the spec's order:
|
Per region, in the spec's order:
|
||||||
|
|
||||||
1. `.github/skills/impeccable/scripts/impeccable comp-spec --crop <id>` writes the reference crop under `.impeccable/build/crops/`.
|
1. `.github/skills/impeccable/scripts/impeccable comp-spec --crop <id>` writes the reference crop under `.impeccable/build/crops/`.
|
||||||
2. Produce the plate. With the API fallback: `.github/skills/impeccable/scripts/impeccable generate-image --plate <id> --quality high` does the whole step (crop as reference, the spec's plate prompt, output size chosen from the region's aspect, the file written to its plate path, prompt embedded, and the plate scored against the crop). With a harness-native image tool: use the crop as the input image and `.github/skills/impeccable/scripts/impeccable comp-spec --plate-prompt <id>` as the prompt, write the result to the plate path, then run `.github/skills/impeccable/scripts/impeccable embed-prompt <plate> --prompt "<the exact prompt>"`.
|
2. Choose the background from the approved region: an isolated figure, object, or line drawing on the page ground is a **transparent cutout**; a photograph, full-frame illustration, or texture stays **opaque**. Save `.github/skills/impeccable/scripts/impeccable comp-spec --plate-prompt <id> --background transparent` to a UTF-8 prompt file for a cutout; use `--background opaque` otherwise. The transparent prompt preserves reference placement and clear margins, white paint, fine edges, and interior holes.
|
||||||
3. Read the score line. `PLATE-SCORE` under 50%, or a `PLATE-WARN`, means the plate does not read as the region: open the plate beside the crop, name what drifted (subject, framing, palette, style), tighten the prompt with that, and regenerate once. Two misses on one region: keep the better plate, mark it `needs_parent_review`, and say why in one line.
|
3. Produce the plate at its exact spec `plate` path. Create the output directory first and choose a supported output size matching the region's aspect, at least 1.5x its pixel dimensions. Prefer the harness-native image tool with the crop as input and the saved prompt; request a transparent PNG for cutouts, then run `.github/skills/impeccable/scripts/impeccable embed-prompt <plate> --prompt-file <prompt.txt>` (if you refine the prompt, save and embed the exact text sent). With the API fallback, run `.github/skills/impeccable/scripts/impeccable generate-image --ref <crop.png> --prompt-file <prompt.txt> --out <plate.png> --size <WxH> --quality high --background transparent` for a cutout, or `--background opaque` otherwise. The API fallback embeds the prompt and records the background in the sidecar. The output must be PNG; the fallback requests native alpha and performs no chroma-keying.
|
||||||
4. Transparent cutouts (a figure or object on the page ground): generate on a flat chroma color absent from the subject and key it to alpha before writing the PNG; never ship the keyed background.
|
4. Open the plate beside the crop and compare subject, placement, scale, palette, and style. For cutouts, verify a real alpha channel and inspect composites on light and dark grounds: white paint must stay solid, interior holes must clear, and fine edges must avoid halos. Inspect glass and soft shadows carefully; partial alpha alone does not ensure convincing translucency. Never chroma-key native transparent output or flatten it before saving. If a native tool returns opaque pixels or a painted checkerboard, retry with the API fallback when available; otherwise report the transparency blocker. On a visual miss, tighten the prompt and regenerate once. Two misses on one region: keep the better plate, mark it `needs_parent_review`, and name the drift. The parent runs the plates gate after all assets exist; report `unscored` until a gate score is available.
|
||||||
|
|
||||||
Do not redesign. Do not add objects, restyle, or reinterpret; the comp was approved as it is. Do not touch the page code, the spec, or the comp. Do not produce anything the spec does not list; a region the parent forgot goes back as a one-line note, not a plate.
|
Do not redesign. Do not add objects, restyle, or reinterpret; the comp was approved as it is. Do not touch the page code, the spec, or the comp. Do not produce anything the spec does not list; a region the parent forgot goes back as a one-line note, not a plate.
|
||||||
|
|
||||||
## Output Contract
|
## Output Contract
|
||||||
|
|
||||||
Return one line per raster region: `<id> <plate path> <WxH> <score>% <accepted|needs_parent_review|blocked> <one-line note or ->`. Then `blockers` (missing spec, missing comp, no image capability, exhausted key) and `assumptions`, each global and minimal. Nothing else: no summary, no praise, no implementation advice. The parent runs `impeccable build-phase advance` to verify the plates against the same spec; your line and its line must agree.
|
Return one line per raster region: `<id> <plate path> <WxH> <score%|unscored> <accepted|needs_parent_review|blocked> <one-line note or ->`. Then `blockers` (missing spec, missing comp, no image capability, exhausted key) and `assumptions`, each global and minimal. Nothing else: no summary, no praise, no implementation advice. The parent runs `impeccable build-phase advance` to verify the plates against the same spec; a visual acceptance does not override a failing gate.
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ description: Records DESIGN.md and its sidecar from a finished Impeccable build,
|
|||||||
|
|
||||||
You record a project's design system after the build is done. Ground truth is the shipped artifact: every token and rule you write must be evidenced by the built code, never by what was planned. Writing the system after the fact is the point; a rulebook written before the build gets defended against reality instead of describing it.
|
You record a project's design system after the build is done. Ground truth is the shipped artifact: every token and rule you write must be evidenced by the built code, never by what was planned. Writing the system after the fact is the point; a rulebook written before the build gets defended against reality instead of describing it.
|
||||||
|
|
||||||
You run under a hard turn ceiling that ends the run without warning, and a run that ends before DESIGN.md is written has recorded nothing. Batch several Reads into each turn, take `reference/document.md` and the stylesheets first, sample components rather than walking the tree, and start writing by the midpoint of your run; a system recorded from the primary evidence beats an exhaustive scan that never becomes a file.
|
Complete the check within your turn ceiling. Batch Reads, take `reference/document.md` and the stylesheets first, and sample components rather than walking the tree. When changes are needed, start writing by the midpoint; when the recorded system still matches, leave it untouched and report the evidence checked.
|
||||||
|
|
||||||
## Input Contract
|
## Input Contract
|
||||||
|
|
||||||
@@ -16,10 +16,10 @@ Expect: the project root; the artifact path(s); the direction contract text (THE
|
|||||||
|
|
||||||
1. Read `reference/document.md` in full; it is the operating spec for DESIGN.md's format, token schema, sidecar, and section order. Follow it exactly.
|
1. Read `reference/document.md` in full; it is the operating spec for DESIGN.md's format, token schema, sidecar, and section order. Follow it exactly.
|
||||||
2. Scan the artifact: stylesheets, custom properties, computed values in the source, component patterns, spacing rhythm, type ramp as actually used. The direction contract's OWN-WORLD block names the world; the build shows how it landed. Where they diverge, the build wins and the prose may note the divergence.
|
2. Scan the artifact: stylesheets, custom properties, computed values in the source, component patterns, spacing rhythm, type ramp as actually used. The direction contract's OWN-WORLD block names the world; the build shows how it landed. Where they diverge, the build wins and the prose may note the divergence.
|
||||||
3. Write DESIGN.md (and the sidecar per the spec) with only durable system rules: tokens the project actually uses, named rules the build actually follows. Skip one-off values; a token used once is not a system.
|
3. For a new world or approved system change, write DESIGN.md and its sidecar from durable, reused rules in the build. Ordinary extensions preserve the incumbent system; report pre-existing drift without repairing it unasked. Do not write merely to prove this pass ran.
|
||||||
4. Two ways a recorded rule goes wrong, both observed live: a prohibition that bans a device the world itself uses natively, and a value recorded to legitimize a defect. Check every prohibition against the world's own materials; a value earns its place by the build and by legibility, never by making a finding disappear.
|
4. Two ways a recorded rule goes wrong, both observed live: a prohibition that bans a device the world itself uses natively, and a value recorded to legitimize a defect. Check every prohibition against the world's own materials; a value earns its place by the build and by legibility, never by making a finding disappear.
|
||||||
5. Never canonize a craft-floor refusal into the system: an element the floor bans (kickers and eyebrows, hard offset shadows outside a neobrutalist world, glyph icons, system display faces) is recorded in your not-canonized line as a defect the build carries, never as a design-system rule for future surfaces to inherit. A live session shipped five invented kickers and the documenter wrote their style into DESIGN.md; that is how one violation becomes the house style.
|
5. Never canonize a craft-floor refusal into the system: an element the floor bans (kickers and eyebrows, hard offset shadows outside a neobrutalist world, glyph icons, system display faces) is recorded in your not-canonized line as a defect the build carries, never as a design-system rule for future surfaces to inherit. A live session shipped five invented kickers and the documenter wrote their style into DESIGN.md; that is how one violation becomes the house style.
|
||||||
|
|
||||||
## Output Contract
|
## Output Contract
|
||||||
|
|
||||||
Return: the file paths written, a five-line summary of the recorded system (palette strategy, type ramp shape, named rules), and one line naming anything in the build you deliberately did not canonize and why. No other prose.
|
Return: paths written, or “No changes” with the source and system files checked; a five-line system summary (palette, type ramp, named rules); and one line naming defects or drift not canonized or repaired, and why. No other prose.
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
name: impeccable
|
name: impeccable
|
||||||
description: Use when the user wants to design, redesign, shape, critique, audit, polish, clarify, distill, harden, optimize, adapt, animate, colorize, extract, or otherwise improve a frontend interface. Covers websites, landing pages, dashboards, product UI, app shells, components, forms, settings, onboarding, and empty states. Handles UX review, visual hierarchy, information architecture, cognitive load, accessibility, performance, responsive behavior, theming, anti-patterns, typography, fonts, spacing, layout, alignment, color, motion, micro-interactions, UX copy, error states, edge cases, i18n, and reusable design systems or tokens. Also use for bland designs that need to become bolder or more delightful, loud designs that should become quieter, live browser iteration on UI elements, or ambitious visual effects that should feel technically extraordinary. Not for backend-only or non-UI tasks.
|
description: Use when the user wants to design, redesign, shape, critique, audit, polish, clarify, distill, harden, optimize, adapt, animate, colorize, extract, or otherwise improve a frontend interface. Covers websites, landing pages, dashboards, product UI, app shells, components, forms, settings, onboarding, and empty states. Handles UX review, visual hierarchy, information architecture, cognitive load, accessibility, performance, responsive behavior, theming, anti-patterns, typography, fonts, spacing, layout, alignment, color, motion, micro-interactions, UX copy, error states, edge cases, i18n, and reusable design systems or tokens. Also use for bland designs that need to become bolder or more delightful, loud designs that should become quieter, live browser iteration on UI elements, or ambitious visual effects that should feel technically extraordinary. Not for backend-only or non-UI tasks.
|
||||||
version: 4.2.2
|
version: 4.3.1
|
||||||
user-invocable: true
|
user-invocable: true
|
||||||
argument-hint: "[shape · audit|critique · animate|bolder|colorize|delight|layout|overdrive|quieter|typeset · adapt|clarify|distill · harden|onboard|optimize|polish · init|document|extract|live] [target]"
|
argument-hint: "[shape · audit|critique · animate|bolder|colorize|delight|layout|overdrive|quieter|typeset · adapt|clarify|distill · harden|onboard|optimize|polish · init|document|extract|live] [target]"
|
||||||
license: Apache 2.0
|
license: Apache 2.0
|
||||||
@@ -16,9 +16,11 @@ Core principles:
|
|||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
1. Run `<skill-base-dir>/scripts/impeccable context` once per session, where `<skill-base-dir>` is the directory that contains this SKILL.md (the skill folder, not a plugin root two levels above it); keep cwd at the user's project. That base directory resolves every `.github/skills/impeccable/scripts/impeccable <verb>` command in this skill and its references, and `.github/skills/impeccable/scripts` is the fallback only when the runtime reports no base directory. On a Windows shell without `sh`, call `.github/skills/impeccable/scripts/impeccable.cmd` instead. The launcher runs a self-contained binary that ships next to it or is downloaded once on first run; no Node or other runtime is required. Pass a named source file or route as `--target <path>`. It loads PRODUCT.md, DESIGN.md, the matching surface brief, and native-platform guidance when applicable; follow its directives and do not rerun it. If the launcher is refused, missing, or fails, tell the user before editing that context loading did not run. Read existing **PRODUCT.md** and **DESIGN.md** without inventing missing context, then continue with steps 2–3.
|
1. Run `<skill-base-dir>/scripts/impeccable context` once per session, where `<skill-base-dir>` is the directory that contains this SKILL.md (the skill folder, not a plugin root two levels above it); keep cwd at the user's project. That base directory resolves every `.github/skills/impeccable/scripts/impeccable <verb>` command in this skill and its references, and `.github/skills/impeccable/scripts` is the fallback only when the runtime reports no base directory. On a Windows shell without `sh`, call `.github/skills/impeccable/scripts/impeccable.cmd` instead. The launcher runs a self-contained binary that ships next to it or is downloaded once on first run; no Node or other runtime is required. Pass a named source file or route as `--target <path>`. It loads PRODUCT.md, DESIGN.md, the matching surface brief, and native-platform guidance when applicable; follow its directives and do not rerun it.
|
||||||
2. Load the request's playbook: its Commands-table reference for an explicit/implied sub-command, or [reference/new-work.md](reference/new-work.md) for a new surface or replacement visual world. Inspect target and incumbent visual truth before editing. When the app cannot run, start with committed visual-regression goldens or screenshot fixtures; verify target and freshness against current tokens, CSS, components, or assets, resolve conflicts, and compare theme/variant captures.
|
2. Load the request's playbook: its Commands-table reference for an explicit/implied sub-command, or [reference/new-work.md](reference/new-work.md) for a new surface or replacement visual world. Inspect target and incumbent visual truth before editing. When the app cannot run, start with committed visual-regression goldens or screenshot fixtures; verify target and freshness against current tokens, CSS, components, or assets, resolve conflicts, and compare theme/variant captures.
|
||||||
3. After analysis and direction are resolved, load [reference/craft-floor.md](reference/craft-floor.md) immediately before editing UI. It carries the quality floor, the absolute bans, and the reflexes no detector catches. Do not load it for planning-only work.
|
3. After resolving analysis and direction, read [reference/craft-floor.md](reference/craft-floor.md) immediately before any UI edit, including small refinements. It carries the quality floor, the absolute bans, and the reflexes no detector catches. Do not load it for planning-only work.
|
||||||
|
|
||||||
|
**Launcher unavailable:** On refusal or failure, send a separate message **before the next tool call**: “Context loading did not run; I’ll read the existing project context directly.” Then read existing PRODUCT.md and DESIGN.md without inventing missing context, follow applicable steps 2–3, and continue through permitted tools. This applies to planning and editing; launcher failure alone does not block either.
|
||||||
|
|
||||||
## How to design
|
## How to design
|
||||||
|
|
||||||
|
|||||||
@@ -188,6 +188,12 @@ Test thoroughly across contexts:
|
|||||||
- **Edge cases**: Very small screens (320px), very large screens (4K)
|
- **Edge cases**: Very small screens (320px), very large screens (4K)
|
||||||
- **Slow connections**: Test on throttled network
|
- **Slow connections**: Test on throttled network
|
||||||
|
|
||||||
|
**Custom controls** (sliders, drag surfaces, scrollable control strips): a before/after slider can pass every width check above and still refuse to drag on iOS, so exercise each one in scope in the same batched round as the checks above:
|
||||||
|
|
||||||
|
- **Primary gesture**: Tap it and confirm it responds as designed, then drag it with the target input method; the drag must complete, not just start
|
||||||
|
- **Scroll across it**: A swipe along the page's scroll axis across the control scrolls the page or container without activating it; a drag that starts on the control along its axis moves the control, not the page. Neither failure throws an error, so try both
|
||||||
|
- **Evidence**: Say what produced the evidence: an emulated viewport, synthesized touch input through a browser tool, which engine ran it (Chromium is not Safari), or a physical device. Screenshots and resized viewports verify layout, never a gesture. Name what stayed untested and move on; unreachable hardware is a reported gap, not a blocker
|
||||||
|
|
||||||
When the adaptation feels native to each context, hand off to `/impeccable polish` for the final pass.
|
When the adaptation feels native to each context, hand off to `/impeccable polish` for the final pass.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -48,11 +48,12 @@ Run comprehensive checks across 5 dimensions. Score each dimension 0-4 using the
|
|||||||
**Check for**:
|
**Check for**:
|
||||||
- **Fixed widths**: Hard-coded widths that break on mobile
|
- **Fixed widths**: Hard-coded widths that break on mobile
|
||||||
- **Touch targets**: Interactive elements < 44x44px
|
- **Touch targets**: Interactive elements < 44x44px
|
||||||
|
- **Broken touch interaction**: Custom sliders, drag surfaces, and scrollable control strips whose primary gesture fails under touch, that swallow page scroll or lose the drag to it, or that stay stuck after an interrupted gesture. Code tells: mouse-only handlers, no `touch-action` on a pointer-event drag surface, drag state that nothing clears on cancel, lost capture, or blur. Exercise the gesture when a browser tool can synthesize touch (a rendered viewport proves layout, not the gesture), then say what produced the evidence (emulated viewport, synthesized touch, which engine, physical device) and what stayed untested
|
||||||
- **Horizontal scroll**: Content overflow on narrow viewports
|
- **Horizontal scroll**: Content overflow on narrow viewports
|
||||||
- **Text scaling**: Layouts that break when text size increases
|
- **Text scaling**: Layouts that break when text size increases
|
||||||
- **Missing breakpoints**: No mobile/tablet variants
|
- **Missing breakpoints**: No mobile/tablet variants
|
||||||
|
|
||||||
**Score 0-4**: 0=Desktop-only (breaks on mobile), 1=Major issues (some breakpoints, many failures), 2=Partial (works on mobile, rough edges), 3=Good (responsive, minor touch target or overflow issues), 4=Excellent (fluid, all viewports, proper touch targets)
|
**Score 0-4**: 0=Desktop-only (breaks on mobile), 1=Major issues (some breakpoints, many failures), 2=Partial (works on mobile, rough edges), 3=Good (responsive, minor touch target or overflow issues), 4=Excellent (fluid, all viewports, proper touch targets, gestures work under touch)
|
||||||
|
|
||||||
### 5. Implementation Integrity (CRITICAL)
|
### 5. Implementation Integrity (CRITICAL)
|
||||||
|
|
||||||
|
|||||||
@@ -26,12 +26,12 @@ Every region with `medium: raster` in the spec ships as a plate at its `plate` p
|
|||||||
Per region, in the spec's order:
|
Per region, in the spec's order:
|
||||||
|
|
||||||
1. `.github/skills/impeccable/scripts/impeccable comp-spec --crop <id>` writes the reference crop under `.impeccable/build/crops/`.
|
1. `.github/skills/impeccable/scripts/impeccable comp-spec --crop <id>` writes the reference crop under `.impeccable/build/crops/`.
|
||||||
2. Produce the plate. With the API fallback: `.github/skills/impeccable/scripts/impeccable generate-image --plate <id> --quality high` does the whole step (crop as reference, the spec's plate prompt, output size chosen from the region's aspect, the file written to its plate path, prompt embedded, and the plate scored against the crop). With a harness-native image tool: use the crop as the input image and `.github/skills/impeccable/scripts/impeccable comp-spec --plate-prompt <id>` as the prompt, write the result to the plate path, then run `.github/skills/impeccable/scripts/impeccable embed-prompt <plate> --prompt "<the exact prompt>"`.
|
2. Choose the background from the approved region: an isolated figure, object, or line drawing on the page ground is a **transparent cutout**; a photograph, full-frame illustration, or texture stays **opaque**. Save `.github/skills/impeccable/scripts/impeccable comp-spec --plate-prompt <id> --background transparent` to a UTF-8 prompt file for a cutout; use `--background opaque` otherwise. The transparent prompt preserves reference placement and clear margins, white paint, fine edges, and interior holes.
|
||||||
3. Read the score line. `PLATE-SCORE` under 50%, or a `PLATE-WARN`, means the plate does not read as the region: open the plate beside the crop, name what drifted (subject, framing, palette, style), tighten the prompt with that, and regenerate once. Two misses on one region: keep the better plate, mark it `needs_parent_review`, and say why in one line.
|
3. Produce the plate at its exact spec `plate` path. Create the output directory first and choose a supported output size matching the region's aspect, at least 1.5x its pixel dimensions. Prefer the harness-native image tool with the crop as input and the saved prompt; request a transparent PNG for cutouts, then run `.github/skills/impeccable/scripts/impeccable embed-prompt <plate> --prompt-file <prompt.txt>` (if you refine the prompt, save and embed the exact text sent). With the API fallback, run `.github/skills/impeccable/scripts/impeccable generate-image --ref <crop.png> --prompt-file <prompt.txt> --out <plate.png> --size <WxH> --quality high --background transparent` for a cutout, or `--background opaque` otherwise. The API fallback embeds the prompt and records the background in the sidecar. The output must be PNG; the fallback requests native alpha and performs no chroma-keying.
|
||||||
4. Transparent cutouts (a figure or object on the page ground): generate on a flat chroma color absent from the subject and key it to alpha before writing the PNG; never ship the keyed background.
|
4. Open the plate beside the crop and compare subject, placement, scale, palette, and style. For cutouts, verify a real alpha channel and inspect composites on light and dark grounds: white paint must stay solid, interior holes must clear, and fine edges must avoid halos. Inspect glass and soft shadows carefully; partial alpha alone does not ensure convincing translucency. Never chroma-key native transparent output or flatten it before saving. If a native tool returns opaque pixels or a painted checkerboard, retry with the API fallback when available; otherwise report the transparency blocker. On a visual miss, tighten the prompt and regenerate once. Two misses on one region: keep the better plate, mark it `needs_parent_review`, and name the drift. The parent runs the plates gate after all assets exist; report `unscored` until a gate score is available.
|
||||||
|
|
||||||
Do not redesign. Do not add objects, restyle, or reinterpret; the comp was approved as it is. Do not touch the page code, the spec, or the comp. Do not produce anything the spec does not list; a region the parent forgot goes back as a one-line note, not a plate.
|
Do not redesign. Do not add objects, restyle, or reinterpret; the comp was approved as it is. Do not touch the page code, the spec, or the comp. Do not produce anything the spec does not list; a region the parent forgot goes back as a one-line note, not a plate.
|
||||||
|
|
||||||
## Output Contract
|
## Output Contract
|
||||||
|
|
||||||
Return one line per raster region: `<id> <plate path> <WxH> <score>% <accepted|needs_parent_review|blocked> <one-line note or ->`. Then `blockers` (missing spec, missing comp, no image capability, exhausted key) and `assumptions`, each global and minimal. Nothing else: no summary, no praise, no implementation advice. The parent runs `impeccable build-phase advance` to verify the plates against the same spec; your line and its line must agree.
|
Return one line per raster region: `<id> <plate path> <WxH> <score%|unscored> <accepted|needs_parent_review|blocked> <one-line note or ->`. Then `blockers` (missing spec, missing comp, no image capability, exhausted key) and `assumptions`, each global and minimal. Nothing else: no summary, no praise, no implementation advice. The parent runs `impeccable build-phase advance` to verify the plates against the same spec; a visual acceptance does not override a failing gate.
|
||||||
@@ -5,7 +5,7 @@ This harness has no subagent capability, so you are running this role inline. St
|
|||||||
|
|
||||||
You record a project's design system after the build is done. Ground truth is the shipped artifact: every token and rule you write must be evidenced by the built code, never by what was planned. Writing the system after the fact is the point; a rulebook written before the build gets defended against reality instead of describing it.
|
You record a project's design system after the build is done. Ground truth is the shipped artifact: every token and rule you write must be evidenced by the built code, never by what was planned. Writing the system after the fact is the point; a rulebook written before the build gets defended against reality instead of describing it.
|
||||||
|
|
||||||
You run under a hard turn ceiling that ends the run without warning, and a run that ends before DESIGN.md is written has recorded nothing. Batch several Reads into each turn, take `reference/document.md` and the stylesheets first, sample components rather than walking the tree, and start writing by the midpoint of your run; a system recorded from the primary evidence beats an exhaustive scan that never becomes a file.
|
Complete the check within your turn ceiling. Batch Reads, take `reference/document.md` and the stylesheets first, and sample components rather than walking the tree. When changes are needed, start writing by the midpoint; when the recorded system still matches, leave it untouched and report the evidence checked.
|
||||||
|
|
||||||
## Input Contract
|
## Input Contract
|
||||||
|
|
||||||
@@ -15,10 +15,10 @@ Expect: the project root; the artifact path(s); the direction contract text (THE
|
|||||||
|
|
||||||
1. Read `reference/document.md` in full; it is the operating spec for DESIGN.md's format, token schema, sidecar, and section order. Follow it exactly.
|
1. Read `reference/document.md` in full; it is the operating spec for DESIGN.md's format, token schema, sidecar, and section order. Follow it exactly.
|
||||||
2. Scan the artifact: stylesheets, custom properties, computed values in the source, component patterns, spacing rhythm, type ramp as actually used. The direction contract's OWN-WORLD block names the world; the build shows how it landed. Where they diverge, the build wins and the prose may note the divergence.
|
2. Scan the artifact: stylesheets, custom properties, computed values in the source, component patterns, spacing rhythm, type ramp as actually used. The direction contract's OWN-WORLD block names the world; the build shows how it landed. Where they diverge, the build wins and the prose may note the divergence.
|
||||||
3. Write DESIGN.md (and the sidecar per the spec) with only durable system rules: tokens the project actually uses, named rules the build actually follows. Skip one-off values; a token used once is not a system.
|
3. For a new world or approved system change, write DESIGN.md and its sidecar from durable, reused rules in the build. Ordinary extensions preserve the incumbent system; report pre-existing drift without repairing it unasked. Do not write merely to prove this pass ran.
|
||||||
4. Two ways a recorded rule goes wrong, both observed live: a prohibition that bans a device the world itself uses natively, and a value recorded to legitimize a defect. Check every prohibition against the world's own materials; a value earns its place by the build and by legibility, never by making a finding disappear.
|
4. Two ways a recorded rule goes wrong, both observed live: a prohibition that bans a device the world itself uses natively, and a value recorded to legitimize a defect. Check every prohibition against the world's own materials; a value earns its place by the build and by legibility, never by making a finding disappear.
|
||||||
5. Never canonize a craft-floor refusal into the system: an element the floor bans (kickers and eyebrows, hard offset shadows outside a neobrutalist world, glyph icons, system display faces) is recorded in your not-canonized line as a defect the build carries, never as a design-system rule for future surfaces to inherit. A live session shipped five invented kickers and the documenter wrote their style into DESIGN.md; that is how one violation becomes the house style.
|
5. Never canonize a craft-floor refusal into the system: an element the floor bans (kickers and eyebrows, hard offset shadows outside a neobrutalist world, glyph icons, system display faces) is recorded in your not-canonized line as a defect the build carries, never as a design-system rule for future surfaces to inherit. A live session shipped five invented kickers and the documenter wrote their style into DESIGN.md; that is how one violation becomes the house style.
|
||||||
|
|
||||||
## Output Contract
|
## Output Contract
|
||||||
|
|
||||||
Return: the file paths written, a five-line summary of the recorded system (palette strategy, type ramp shape, named rules), and one line naming anything in the build you deliberately did not canonize and why. No other prose.
|
Return: paths written, or “No changes” with the source and system files checked; a five-line system summary (palette, type ramp, named rules); and one line naming defects or drift not canonized or repaired, and why. No other prose.
|
||||||
@@ -205,6 +205,11 @@ t('items', { count }) // Handles complex plural rules
|
|||||||
- Optimistic updates with rollback
|
- Optimistic updates with rollback
|
||||||
- Conflict resolution
|
- Conflict resolution
|
||||||
|
|
||||||
|
**Interrupted gestures** (custom sliders, drag surfaces, scrollable control strips):
|
||||||
|
- A second finger or pointer lands mid-drag: the first drag keeps its pointer or ends cleanly, never jumps to the new one
|
||||||
|
- The browser cancels the gesture to scroll (`pointercancel`), capture is lost (`lostpointercapture`), the pointer is released outside the control, or the window loses focus (`blur`) mid-drag: clear the dragging state and release capture
|
||||||
|
- After each of these, the next tap or drag works without a reload
|
||||||
|
|
||||||
**Permission states**:
|
**Permission states**:
|
||||||
- No permission to view
|
- No permission to view
|
||||||
- No permission to edit
|
- No permission to edit
|
||||||
@@ -304,6 +309,7 @@ const throttledScroll = throttle(handleScroll, 100);
|
|||||||
- Unit tests for edge cases
|
- Unit tests for edge cases
|
||||||
- Integration tests for error scenarios
|
- Integration tests for error scenarios
|
||||||
- E2E tests for critical paths
|
- E2E tests for critical paths
|
||||||
|
- A behavioral regression for each confirmed gesture fix, when the project's test runner can drive input
|
||||||
- Visual regression tests
|
- Visual regression tests
|
||||||
- Accessibility tests (axe, WAVE)
|
- Accessibility tests (axe, WAVE)
|
||||||
|
|
||||||
@@ -330,7 +336,10 @@ Test thoroughly with edge cases:
|
|||||||
- **Network issues**: Disable internet, throttle connection
|
- **Network issues**: Disable internet, throttle connection
|
||||||
- **Large datasets**: Test with 1000+ items
|
- **Large datasets**: Test with 1000+ items
|
||||||
- **Concurrent actions**: Click submit 10 times rapidly
|
- **Concurrent actions**: Click submit 10 times rapidly
|
||||||
|
- **Interrupted gestures**: Add a second finger mid-drag, scroll across the control, release outside it, switch windows mid-drag; then drag again
|
||||||
- **Errors**: Force API errors, test all error states
|
- **Errors**: Force API errors, test all error states
|
||||||
- **Empty**: Remove all data, test empty states
|
- **Empty**: Remove all data, test empty states
|
||||||
|
|
||||||
|
For gestures, say what produced the evidence (emulated viewport, synthesized touch, which engine, physical device) and name what stayed untested.
|
||||||
|
|
||||||
When edge cases are covered, hand off to `/impeccable polish` for the final pass.
|
When edge cases are covered, hand off to `/impeccable polish` for the final pass.
|
||||||
|
|||||||
@@ -42,6 +42,8 @@ On every boot the project is scanned for HTML files under common page roots (`pu
|
|||||||
|
|
||||||
## CSP detection (first-time only)
|
## CSP detection (first-time only)
|
||||||
|
|
||||||
|
Keep all allowances below development-only, including manual middleware and meta-tag edits. Do not change a deployed production site's CSP to load the localhost helper; see [live.md](live.md) for production inspection alternatives.
|
||||||
|
|
||||||
If `config.cspChecked === true`, skip this whole section; the user was already asked once.
|
If `config.cspChecked === true`, skip this whole section; the user was already asked once.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ Interactive live variant mode: select elements in the browser, pick a design act
|
|||||||
|
|
||||||
A running dev server with HMR (Vite, Next.js, Bun, etc.), OR a static HTML file open in the browser. If the dev server's default port is busy, the app is very likely ALREADY running; probe the default URL before spawning a second server.
|
A running dev server with HMR (Vite, Next.js, Bun, etc.), OR a static HTML file open in the browser. If the dev server's default port is busy, the app is very likely ALREADY running; probe the default URL before spawning a second server.
|
||||||
|
|
||||||
|
Live editing requires a local checkout; injection into deployed production sites (including HTTPS) is unsupported. For production inspection, use `.github/skills/impeccable/scripts/impeccable detect <url>` or the browser extension, not the live helper. Do not disable browser security or weaken production CSP to enable live mode.
|
||||||
|
|
||||||
## The contract (read once)
|
## The contract (read once)
|
||||||
|
|
||||||
Execute in order. No step skipped, no step reordered. Every tool output in live mode may carry an `_instructions` field: it is the authoritative next step for that exact situation, with real ids and paths substituted; when it conflicts with your recollection of this document, `_instructions` wins.
|
Execute in order. No step skipped, no step reordered. Every tool output in live mode may carry an `_instructions` field: it is the authoritative next step for that exact situation, with real ids and paths substituted; when it conflicts with your recollection of this document, `_instructions` wins.
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ A section, component, feature, or state inside an established surface inherits t
|
|||||||
|
|
||||||
## 2. Ask what will change the work
|
## 2. Ask what will change the work
|
||||||
|
|
||||||
Ask one round of two or three related questions through the structured question tool when available. Skip settled facts; a precise request may need only a compact confirmation.
|
Before implementation, get the user's answer through the structured question tool when available. Ask two or three related questions; a precise request needs only a compact confirmation. Skip settled facts, not the confirmation: DESIGN.md settles the visual world, not this surface's purpose or concept.
|
||||||
|
|
||||||
- **Persuade:** who must act, what they should believe, which real proof, content, or assets earn that belief.
|
- **Persuade:** who must act, what they should believe, which real proof, content, or assets earn that belief.
|
||||||
- **Operate:** the task, information, important states, frequency, constraints.
|
- **Operate:** the task, information, important states, frequency, constraints.
|
||||||
@@ -68,7 +68,7 @@ Calibration: AI-generated interfaces cluster around a few looks regardless of su
|
|||||||
|
|
||||||
## 5. Record the decision
|
## 5. Record the decision
|
||||||
|
|
||||||
Before code, record the chosen direction as a development-only contract under `## Direction contract` in the relevant surface brief. A direction contract is durable route or artifact strategy, so create or update the brief even when no other surface strategy needs persistence. Keep the contract to six short blocks and 150 words at most. THESIS: the one idea this surface owns and the category-default arrangement it refuses. OWN-WORLD: the palette and component language, specific enough to be recognizable with all content removed. STORY: what the visitor understands, believes, and does. FIRST VIEWPORT: the exact composition, what is where and at what scale, and where the primary action sits. FORM: the chosen form, its position on your ordered list, and the seed key the script printed. Close with one more line, FINISH: the run's exit condition, verbatim "unreviewed and undocumented is unfinished; this build ends with the finish review, the verdict, DESIGN.md, and every shipping raster carrying its provenance". The surface brief is the reminder later agents reload across edits and sessions: a page that looks complete with the FINISH line undischarged is not done, it is abandoned at the finish line. If a block reads like a mood, the direction is not decided yet; the finishing review audits the render against this contract.
|
Before code, record the chosen direction as a development-only contract under `## Direction contract` in the relevant surface brief. A direction contract is durable route or artifact strategy, so create or update the brief even when no other surface strategy needs persistence. Use six short blocks, roughly 150 words; do not spend tool calls counting words. THESIS: the one idea this surface owns and the category-default arrangement it refuses. OWN-WORLD: the palette and component language, specific enough to be recognizable with all content removed. STORY: what the visitor understands, believes, and does. FIRST VIEWPORT: the exact composition, what is where and at what scale, and where the primary action sits. FORM: the chosen form, its position on your ordered list, and the seed key the script printed. Close with one more line, FINISH: the run's exit condition, verbatim "unreviewed and undocumented is unfinished; this build ends with the finish review, the verdict, DESIGN.md, and every shipping raster carrying its provenance". The surface brief is the reminder later agents reload across edits and sessions: a page that looks complete with the FINISH line undischarged is not done, it is abandoned at the finish line. If a block reads like a mood, the direction is not decided yet; the finishing review audits the render against this contract.
|
||||||
|
|
||||||
Never copy the direction contract into implementation source or any browser-delivered artifact. This includes HTML or framework comments, hidden DOM, `<template>` elements, `data-*` attributes, rendered JSX or TSX output, serialized props or state, React Server Component payloads, client bundles, metadata or JSON-LD, accessibility-only text, and files served beside the artifact. A compiler or optimizer removing development metadata is not a safety boundary. Reviewers and documenters receive the contract from the surface brief.
|
Never copy the direction contract into implementation source or any browser-delivered artifact. This includes HTML or framework comments, hidden DOM, `<template>` elements, `data-*` attributes, rendered JSX or TSX output, serialized props or state, React Server Component payloads, client bundles, metadata or JSON-LD, accessibility-only text, and files served beside the artifact. A compiler or optimizer removing development metadata is not a safety boundary. Reviewers and documenters receive the contract from the surface brief.
|
||||||
|
|
||||||
@@ -104,7 +104,7 @@ Then, in order, each closed by `.github/skills/impeccable/scripts/impeccable bui
|
|||||||
The comp-led path is a frontier-tier job: it asks the builder to hold a measured layout, place plates at their boxes, and act on numeric readings across a dozen attempts. Smaller or faster models produce a recognisable page and stall under the hero gate; if the model in hand is one of those, say so before the direction round and take the code-led path, or expect the run to end at the hero with its readings unmet.
|
The comp-led path is a frontier-tier job: it asks the builder to hold a measured layout, place plates at their boxes, and act on numeric readings across a dozen attempts. Smaller or faster models produce a recognisable page and stall under the hero gate; if the model in hand is one of those, say so before the direction round and take the code-led path, or expect the run to end at the hero with its readings unmet.
|
||||||
|
|
||||||
1. **spec.** Measure the comp: `impeccable comp-spec --comp <comp> --grid` writes a coordinate grid over the comp; open it, name every salient region by grid span in a regions file (text and control regions snap to the largest ink mass inside their span, so a headline named B1:E4 measures as the headline and not the column beside it; `snap: false` keeps the span, and an explicit `box` is taken as drawn) (kind `plate` / `image` / `texture` for anything painted: every illustration, photograph, figure, product object, and material texture; `text` / `control` / `chrome` for what code draws; every region carries a `note` saying what the comp shows there, which the plate prompt and the gate messages read), and run `impeccable comp-spec --comp <comp> --regions <file>`. The spec carries each region's box, sampled palette, and medium; `impeccable comp-spec --print` is the build's reference from here on. Type is measured, not guessed: `impeccable font-match --measure <text region>` reads the comp's cap height, width class, and weight off the pixels, and `impeccable font-match --rank <region> --text "..."` takes its candidates from a fingerprint index of the Google Fonts catalog (the nearest faces to the crop's shape) plus any names you pass with `--candidates`, renders them at that cap height with the region's words, and ranks them by fingerprint distance (its `USE` line is the CSS; its proof sheet shows the comp over the top three); with no browser resolvable it records the catalog's nearest face and says the size is estimated, which is still the choice to build on. Do not install a browser to rank, and never write a `chosen` face into the spec by hand: the gate accepts only what font-match wrote. The spec gate refuses to close until the lead text region is measured and ranked. A region note that describes painted material (a diagram, drawing, photograph, texture) under a code kind is refused at the spec: reclassify it as a plate, or reword the note if code really draws it. The script refuses a regions file that leaves comp ink unnamed (callouts, a parts table, a notes block): what is never named can never be missing, so everything the comp shows gets a region. It also refuses a `text` / `control` / `chrome` region larger than a quarter of the comp: that is a column, not an element, and a column scored as one region hides the plates, tables, and notes inside it. Name each element inside it (`container: true` only when it truly is one undivided element). Anything drawn is a plate: an inline SVG past an icon's budget (a diagram, notation, leader lines with arrows, a "quick approximation" of the artwork) is refused at the hero; icon-sized SVG (under 64px, a few paths) is fine, and a chart the page draws from data at runtime is a chart, not an illustration. Callout lines and arrows that annotate a drawing belong to that drawing's plate, with only their labels set as text. A crop of the comp is never a plate (the plates gate refuses a file that is a resample of the comp region: the comp's grain, its neighbours' edges, and its resolution would ship as the artwork); the crop is the reference the plate is generated from. A plate region's box has to hold its whole artwork with a margin: the spec measures the artwork's contact with the box edges and refuses a box that cuts through it (`bleed: true` only when the page really crops it there), because a plate placed with `object-fit: cover` on such a box shows the artwork minus the side the box lost. Anything not in the spec does not exist on the page: no borders, rules, containers, or chrome the comp does not show. Only three concessions exist: fonts (the closest obtainable face), icon glyphs (close enough, exact if the user chose an icon library; this covers the pictogram only, never a control's chrome, so a chevron, an arrow, a dropdown's border and fill, a button's shape are the comp's), and genuine defects in the comp such as spelling errors.
|
1. **spec.** Measure the comp: `impeccable comp-spec --comp <comp> --grid` writes a coordinate grid over the comp; open it, name every salient region by grid span in a regions file (text and control regions snap to the largest ink mass inside their span, so a headline named B1:E4 measures as the headline and not the column beside it; `snap: false` keeps the span, and an explicit `box` is taken as drawn) (kind `plate` / `image` / `texture` for anything painted: every illustration, photograph, figure, product object, and material texture; `text` / `control` / `chrome` for what code draws; every region carries a `note` saying what the comp shows there, which the plate prompt and the gate messages read), and run `impeccable comp-spec --comp <comp> --regions <file>`. The spec carries each region's box, sampled palette, and medium; `impeccable comp-spec --print` is the build's reference from here on. Type is measured, not guessed: `impeccable font-match --measure <text region>` reads the comp's cap height, width class, and weight off the pixels, and `impeccable font-match --rank <region> --text "..."` takes its candidates from a fingerprint index of the Google Fonts catalog (the nearest faces to the crop's shape) plus any names you pass with `--candidates`, renders them at that cap height with the region's words, and ranks them by fingerprint distance (its `USE` line is the CSS; its proof sheet shows the comp over the top three); with no browser resolvable it records the catalog's nearest face and says the size is estimated, which is still the choice to build on. Do not install a browser to rank, and never write a `chosen` face into the spec by hand: the gate accepts only what font-match wrote. The spec gate refuses to close until the lead text region is measured and ranked. A region note that describes painted material (a diagram, drawing, photograph, texture) under a code kind is refused at the spec: reclassify it as a plate, or reword the note if code really draws it. The script refuses a regions file that leaves comp ink unnamed (callouts, a parts table, a notes block): what is never named can never be missing, so everything the comp shows gets a region. It also refuses a `text` / `control` / `chrome` region larger than a quarter of the comp: that is a column, not an element, and a column scored as one region hides the plates, tables, and notes inside it. Name each element inside it (`container: true` only when it truly is one undivided element). Anything drawn is a plate: an inline SVG past an icon's budget (a diagram, notation, leader lines with arrows, a "quick approximation" of the artwork) is refused at the hero; icon-sized SVG (under 64px, a few paths) is fine, and a chart the page draws from data at runtime is a chart, not an illustration. Callout lines and arrows that annotate a drawing belong to that drawing's plate, with only their labels set as text. A crop of the comp is never a plate (the plates gate refuses a file that is a resample of the comp region: the comp's grain, its neighbours' edges, and its resolution would ship as the artwork); the crop is the reference the plate is generated from. A plate region's box has to hold its whole artwork with a margin: the spec measures the artwork's contact with the box edges and refuses a box that cuts through it (`bleed: true` only when the page really crops it there), because a plate placed with `object-fit: cover` on such a box shows the artwork minus the side the box lost. Anything not in the spec does not exist on the page: no borders, rules, containers, or chrome the comp does not show. Only three concessions exist: fonts (the closest obtainable face), icon glyphs (close enough, exact if the user chose an icon library; this covers the pictogram only, never a control's chrome, so a chevron, an arrow, a dropdown's border and fill, a button's shape are the comp's), and genuine defects in the comp such as spelling errors.
|
||||||
2. **plates.** Every raster region ships as a plate: an illustration, photo, or figure regenerated at asset resolution from its comp crop, UI text removed, at its `plate` path (ink on flat ground is generated on a chroma key and keyed to alpha, so it sits on the page's own ground rather than a second paper); a texture (paper, cloth, grain) is a clean patch of the comp region mirror-tiled to size, generated only when no clean patch exists. `impeccable generate-image --plate <id>` does one region end to end and scores it against the crop; a harness-native image tool takes the crop (`impeccable comp-spec --crop <id>`) as its input image and `impeccable comp-spec --plate-prompt <id>` as its prompt, then `impeccable embed-prompt`. With parallel subagents, spawn the shipped asset producer (`impeccable-asset-producer`; `impeccable_asset_producer` in codex; `/impeccable-asset-producer` in Cursor; on GitHub Copilot say "Use the impeccable-asset-producer agent") with the spec path and let it produce them all; without subagents, produce them here. A crop of the comp is a reference, never a shipping pixel. The gate checks every plate exists, is at least 1.5x the region's size, and reads as the region. Page code waits for this gate: a page written before its plates exist is a page that draws its material in CSS. A single-file deliverable changes nothing here: the plate is produced the same way and inlined as a data URI. `--force` exists for one case only, the user downgrading the comp's authority in words you quote in `--reason`; the script refuses every other reason.
|
2. **plates.** Every raster region ships as a plate: an illustration, photo, or figure regenerated at asset resolution from its comp crop, UI text removed, at its `plate` path (isolated ink, figures, or objects use native transparent PNG so they sit on the page's own ground; photos and textures stay opaque); a texture (paper, cloth, grain) is a clean patch of the comp region mirror-tiled to size, generated only when no clean patch exists. `impeccable comp-spec --crop <id>` writes the reference; save `impeccable comp-spec --plate-prompt <id> --background transparent` to a prompt file for a cutout, or use `--background opaque` otherwise. Prefer the harness-native image tool with that crop and prompt, then `impeccable embed-prompt <plate> --prompt-file <prompt.txt>`. The API fallback is `impeccable generate-image --ref <crop.png> --prompt-file <prompt.txt> --out <plate.png> --size <WxH> --quality high --background transparent` (use `--background opaque` for full-frame assets); create the output directory first. Verify actual alpha, white foregrounds, fine edges, and clear holes on light and dark grounds; do not chroma-key native output. The plates gate scores the assets against the comp; also inspect placement and scale visually. With parallel subagents, spawn the shipped asset producer (`impeccable-asset-producer`; `impeccable_asset_producer` in codex; `/impeccable-asset-producer` in Cursor; on GitHub Copilot say "Use the impeccable-asset-producer agent") with the spec path and let it produce them all; without subagents, produce them here. A crop of the comp is a reference, never a shipping pixel. The gate checks every plate exists, is at least 1.5x the region's size, and reads as the region. Page code waits for this gate: a page written before its plates exist is a page that draws its material in CSS. A single-file deliverable changes nothing here: the plate is produced the same way and inlined as a data URI. `--force` exists for one case only, the user downgrading the comp's authority in words you quote in `--reason`; the script refuses every other reason.
|
||||||
3. **hero.** `impeccable build-phase scaffold` first: it writes the measured layout as CSS custom properties (`.impeccable/build/scaffold/layout.css`: `--r-<id>-x/y/w/h` in % of the comp, plus cap height, font-size, family, and weight where measured) and a reference page (`hero-reference.html`) with every region at its box and every plate placed. Bind the numbers to your own semantic structure, an element per region; the reference is a check on positions, never the page, and overlapping boxes are overlapping boxes. Then build only the first viewport, at the comp's own dimensions, the comp's words copied verbatim (the user approved that comp with those words; rewording is a stated decision after the hero passes, never a silent one inside it), every text region sized from its measured cap height and set in its ranked face, plates first: place every plate at its spec box (`object-fit: cover`, an `<img>`, a background image, or an inlined data URI named for it) before any text or control, capture into `.impeccable/review/hero-repro.png`, run `impeccable build-phase record hero` once so you see the plate regions read as match before any text exists, then lay the semantic layer over the plates from the spec's palette and boxes and advance. The gate first refuses while any plate is unreferenced by the source, then runs `impeccable comp-diff`, writes `.impeccable/review/diff/hero/` (side-by-side, heatmap, one paired crop per region, `report.json`), and passes at 72% overall with no hard veto outstanding (a missing region, a contradicted plate or text block, an SVG illustration, a clipped plate, invented ink block at any score); above the bar, the numeric readings become advisories printed with the pass, and the polish pass before responsive is where they get fixed: the gate also reads each text region's cap height, line count, weight, ink colour, and position against the comp, each chrome strip's height off its rule, and the frame for ink where the comp is calm (a kicker, an extra nav item, a divider), and says each miss as a number ("cap height 78px in the build, 103px in the comp"); those numbers are the edit. When it fails, open the region crops it lists, in order, before editing: a region scored `missing` needs its material, `contradicted` needs its structure re-derived from the spec box, `drift` is where size and spacing edits belong; the gate refuses a third attempt that only nudges values on the same region. This is where the run's ambition is won or lost, and a retry here costs minutes where a rebuild verdict at the finish costs the run.
|
3. **hero.** `impeccable build-phase scaffold` first: it writes the measured layout as CSS custom properties (`.impeccable/build/scaffold/layout.css`: `--r-<id>-x/y/w/h` in % of the comp, plus cap height, font-size, family, and weight where measured) and a reference page (`hero-reference.html`) with every region at its box and every plate placed. Bind the numbers to your own semantic structure, an element per region; the reference is a check on positions, never the page, and overlapping boxes are overlapping boxes. Then build only the first viewport, at the comp's own dimensions, the comp's words copied verbatim (the user approved that comp with those words; rewording is a stated decision after the hero passes, never a silent one inside it), every text region sized from its measured cap height and set in its ranked face, plates first: place every plate at its spec box (`object-fit: cover`, an `<img>`, a background image, or an inlined data URI named for it) before any text or control, capture into `.impeccable/review/hero-repro.png`, run `impeccable build-phase record hero` once so you see the plate regions read as match before any text exists, then lay the semantic layer over the plates from the spec's palette and boxes and advance. The gate first refuses while any plate is unreferenced by the source, then runs `impeccable comp-diff`, writes `.impeccable/review/diff/hero/` (side-by-side, heatmap, one paired crop per region, `report.json`), and passes at 72% overall with no hard veto outstanding (a missing region, a contradicted plate or text block, an SVG illustration, a clipped plate, invented ink block at any score); above the bar, the numeric readings become advisories printed with the pass, and the polish pass before responsive is where they get fixed: the gate also reads each text region's cap height, line count, weight, ink colour, and position against the comp, each chrome strip's height off its rule, and the frame for ink where the comp is calm (a kicker, an extra nav item, a divider), and says each miss as a number ("cap height 78px in the build, 103px in the comp"); those numbers are the edit. When it fails, open the region crops it lists, in order, before editing: a region scored `missing` needs its material, `contradicted` needs its structure re-derived from the spec box, `drift` is where size and spacing edits belong; the gate refuses a third attempt that only nudges values on the same region. This is where the run's ambition is won or lost, and a retry here costs minutes where a rebuild verdict at the finish costs the run.
|
||||||
4. **sections.** Build the rest of the surface inside the spec's system: the same corner language, line weights, and palette, and nothing the comp never shows. Where the comp does not cover a region, it inherits the recorded system.
|
4. **sections.** Build the rest of the surface inside the spec's system: the same corner language, line weights, and palette, and nothing the comp never shows. Where the comp does not cover a region, it inherits the recorded system.
|
||||||
5. **motion.** The signature interaction, reveals, and motion, orchestrated once rather than scattered.
|
5. **motion.** The signature interaction, reveals, and motion, orchestrated once rather than scattered.
|
||||||
@@ -142,4 +142,4 @@ A rebuild and a fix round share one asset rule: a raster either round creates or
|
|||||||
|
|
||||||
Report the final verdict under the reviewer's own disposition word and at its actual scope. A verdict pass scores the listed fixes and nothing else: "the reviewer scored all three fixes resolved" is a claim it supports, "no material issues remain" is not. A table with open material findings is never announced as a pass, never softened, and never dressed as whole-surface approval when only a fix list was scored. When the user answers a ship with evidence against it, their own screenshot, a named mismatch with the comp, that evidence outranks every capture you made: put their material in the packet and spawn a fresh reviewer for a new full review. Patching inline and self-certifying is how a rejected page ships twice.
|
Report the final verdict under the reviewer's own disposition word and at its actual scope. A verdict pass scores the listed fixes and nothing else: "the reviewer scored all three fixes resolved" is a claim it supports, "no material issues remain" is not. A table with open material findings is never announced as a pass, never softened, and never dressed as whole-surface approval when only a fix list was scored. When the user answers a ship with evidence against it, their own screenshot, a named mismatch with the comp, that evidence outranks every capture you made: put their material in the packet and spawn a fresh reviewer for a new full review. Patching inline and self-certifying is how a rejected page ships twice.
|
||||||
|
|
||||||
Then spawn the shipped documenter, `impeccable-documenter` (`impeccable_documenter` in codex), with the project root, the artifact path, the direction contract, PRODUCT.md, the [document.md](document.md) reference path, and the boundary to write at; it records DESIGN.md and the sidecar from the built world, ground truth over intention; without subagents the pass runs from [degraded/documenter.md](degraded/documenter.md). The documenter runs after the last correction lands: when any fix round follows the documentation, re-run the documenter over the changed surface, because a DESIGN.md describing a layout that no longer exists turns defects into system guidance. A clean detector pass is not finished; finished is the contract kept, the comp honored, the review closed, and the system recorded.
|
After the last correction, spawn the shipped documenter, `impeccable-documenter` (`impeccable_documenter` in codex), with the project root, artifact path, direction contract, PRODUCT.md, [document.md](document.md), and write boundary. Without subagents, load [degraded/documenter.md](degraded/documenter.md) and [document.md](document.md) before writing. Verify the outcome: new worlds and approved system changes require token-bearing DESIGN.md **and** `.impeccable/design.json`, not prose alone. Ordinary extensions compare the finished build against the incumbent system, preserve its files, and report the evidence checked; report pre-existing drift without repairing it unasked. Recheck after later edits. Finish only when review and documentation are complete.
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ What the comp shows is measured, not remembered. new-work.md section 6 runs the
|
|||||||
|
|
||||||
## Plates and provenance
|
## Plates and provenance
|
||||||
|
|
||||||
Every raster region's plate is produced in the plates phase, before any page code, by the shipped asset producer or in the current thread (`impeccable generate-image --plate <id>`, or the harness image tool with the crop as input and the spec's plate prompt). Generation context is part of the asset: after generating any image with any tool, run `.github/skills/impeccable/scripts/impeccable embed-prompt <image> --prompt "<prompt>"` with the exact string the tool received (`impeccable generate-image` does this itself), so the intent lives inside the file; `--read` recovers it, `--scan <dir>` lists rasters still missing one. The embedded prompt plus the region's row in the spec is the raster's **provenance**, and every raster the artifact references carries it; a sourced, stock, or pre-existing raster embeds its origin instead. A raster created or replaced later, in a fix batch or a reviewer's rebuild, is produced the same way; a raster a fix abandons is deleted in the same batch.
|
Every raster region's plate is produced in the plates phase, before any page code, by the shipped asset producer or in the current thread (use `impeccable comp-spec --crop <id>` and save `impeccable comp-spec --plate-prompt <id>` to a prompt file; pass the crop and prompt to the harness image tool, or use `impeccable generate-image --ref <crop.png> --prompt-file <prompt.txt> --out <plate.png> --size <WxH> --quality high`). For isolated cutouts, add `--background transparent` to both the plate-prompt and API generation commands; use native PNG alpha and preserve white paint and clear gaps. Use `--background opaque` for full-frame imagery. Create output directories first and inspect alpha on light and dark grounds. Generation context is part of the asset: after generating any image with any tool, run `.github/skills/impeccable/scripts/impeccable embed-prompt <image> --prompt "<prompt>"` with the exact string the tool received (`impeccable generate-image` does this itself), so the intent lives inside the file; `--read` recovers it, `--scan <dir>` lists rasters still missing one. The embedded prompt plus the region's row in the spec is the raster's **provenance**, and every raster the artifact references carries it; a sourced, stock, or pre-existing raster embeds its origin instead. A raster created or replaced later, in a fix batch or a reviewer's rebuild, is produced the same way; a raster a fix abandons is deleted in the same batch.
|
||||||
|
|
||||||
Convert images with a converter `impeccable context` reported at boot (the IMAGE_TOOLS line); probe only when it reported none, at most once per session, never per image.
|
Convert images with a converter `impeccable context` reported at boot (the IMAGE_TOOLS line); probe only when it reported none, at most once per session, never per image.
|
||||||
|
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
0.1.3
|
0.1.5
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user