mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-11 21:57:14 +03:00
Compare commits
16
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
831cabee8b | ||
|
|
bb7663ecfb | ||
|
|
707fb6061c | ||
|
|
044a04fd0d | ||
|
|
0ac0b6866f | ||
|
|
2a9957589c | ||
|
|
4bee58d89e | ||
|
|
a443ec0d8f | ||
|
|
94d8611af6 | ||
|
|
6e61113e3c | ||
|
|
381d52b38f | ||
|
|
eebfb7c2ce | ||
|
|
8dac6ae7e0 | ||
|
|
46ffe5caa2 | ||
|
|
b077f6f0e4 | ||
|
|
641ff95502 |
@@ -1,7 +1,7 @@
|
||||
---
|
||||
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.
|
||||
version: 4.2.0
|
||||
version: 4.2.1
|
||||
license: Apache 2.0
|
||||
allowed-tools:
|
||||
- Bash(npx impeccable *)
|
||||
@@ -69,7 +69,8 @@ Choose the mode from the requested surface, not the product, and persist it only
|
||||
Routing:
|
||||
|
||||
- **No argument:** read [routing.md](reference/routing.md) and present its context-aware menu; never auto-run a command.
|
||||
- **Explicit or clearly implied command:** load its reference (native variant on native platforms) and follow it. Ask once if two commands fit.
|
||||
- **Explicit or clearly implied request to run a command:** load its reference (native variant on native platforms) and follow it. Ask once if two commands fit.
|
||||
- **Workflow or command-selection question:** read [Workflow questions](reference/routing.md#workflow-questions).
|
||||
- **Otherwise:** treat the request as general design work. Missing PRODUCT.md routes a new surface or replacement world through init, then new-work; a narrow refinement of existing code proceeds on the incumbent implementation as `impeccable context` directs, offering init afterward rather than blocking on it.
|
||||
- `teach` aliases `init`. `craft` is a deprecated alias for ordinary new-work and adds nothing. `shape` owns task discovery, then enters new-work only for visual-world and surface-concept decisions.
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ const __impeccableLiveDev =
|
||||
process.env.NODE_ENV === "development" ? ["http://localhost:8400"] : [];
|
||||
```
|
||||
|
||||
Per-framework: Next.js + monorepo helper: edit the *app's* `next.config.*` (not the shared helper), appending to `additionalScriptSrc` / `additionalConnectSrc`. SvelteKit: `svelte.config.js`, `kit.csp.directives['script-src']` and `['connect-src']`. Nuxt + nuxt-security: `nuxt.config.*`, `security.headers.contentSecurityPolicy['script-src']` and `['connect-src']`. Reference outputs: `tests/framework-fixtures/nextjs-turborepo/expected-after-patch.ts`, `tests/framework-fixtures/sveltekit-csp/expected-after-patch.js`. Idempotency: if `__impeccableLiveDev` already exists in the file, the patch is applied; just mark `cspChecked: true`.
|
||||
Per-framework: Next.js + monorepo helper: edit the *app's* `next.config.*` (not the shared helper), appending to `additionalScriptSrc` / `additionalConnectSrc`. SvelteKit: `svelte.config.js`, `kit.csp.directives['script-src']` and `['connect-src']`. Nuxt + nuxt-security: `nuxt.config.*`, `security.headers.contentSecurityPolicy['script-src']` and `['connect-src']`. Reference outputs: [nextjs-turborepo/expected-after-patch.ts](https://github.com/pbakaus/impeccable/blob/8dac6ae7e020c43ab10ce9b41939f6fd42627b96/tests/framework-fixtures/nextjs-turborepo/expected-after-patch.ts), [sveltekit-csp/expected-after-patch.js](https://github.com/pbakaus/impeccable/blob/8dac6ae7e020c43ab10ce9b41939f6fd42627b96/tests/framework-fixtures/sveltekit-csp/expected-after-patch.js). Idempotency: if `__impeccableLiveDev` already exists in the file, the patch is applied; just mark `cspChecked: true`.
|
||||
|
||||
### append-string
|
||||
|
||||
@@ -93,7 +93,7 @@ const __impeccableLiveDev =
|
||||
- `script-src 'self' 'unsafe-inline'` becomes `` `script-src 'self' 'unsafe-inline'${__impeccableLiveDev}` ``
|
||||
- `connect-src 'self'` becomes `` `connect-src 'self'${__impeccableLiveDev}` ``
|
||||
|
||||
Per-framework: Next.js inline `headers()` in `next.config.*`; Nuxt `routeRules['/**'].headers['Content-Security-Policy']` in `nuxt.config.*`. Reference outputs: `tests/framework-fixtures/nextjs-inline-csp/expected-after-patch.js`, `tests/framework-fixtures/nuxt-csp/expected-after-patch.ts`.
|
||||
Per-framework: Next.js inline `headers()` in `next.config.*`; Nuxt `routeRules['/**'].headers['Content-Security-Policy']` in `nuxt.config.*`. Reference outputs: [nextjs-inline-csp/expected-after-patch.js](https://github.com/pbakaus/impeccable/blob/8dac6ae7e020c43ab10ce9b41939f6fd42627b96/tests/framework-fixtures/nextjs-inline-csp/expected-after-patch.js), [nuxt-csp/expected-after-patch.ts](https://github.com/pbakaus/impeccable/blob/8dac6ae7e020c43ab10ce9b41939f6fd42627b96/tests/framework-fixtures/nuxt-csp/expected-after-patch.ts).
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
|
||||
@@ -196,7 +196,7 @@ Complete HTML replacement of the original element per variant, not a CSS-only pa
|
||||
|
||||
Replace the style opening tag with `cssAuthoring.styleTag` when the tool returns a different one. **Each variant div contains exactly one top-level element**, same tag as the original; loose siblings break outline tracking and accept. First variant visible, all others `display: none`. The browser's MutationObserver accepts atomic or progressive arrival; accepting an arrived variant fences the worker, so later publications are rejected.
|
||||
|
||||
For `styleMode: "scoped"`, author every `:scope` rule with a descendant combinator: the `@scope` boundary is the variant wrapper div, not your element, so a bare `:scope { ... }` styles a `display: contents` shell. Always step in (`:scope > .card`, `:scope .hero-title`). The fake test agent's CSS in `tests/live-e2e/agent.mjs` is a faithful template.
|
||||
For `styleMode: "scoped"`, author every `:scope` rule with a descendant combinator: the `@scope` boundary is the variant wrapper div, not your element, so a bare `:scope { ... }` styles a `display: contents` shell. Always step in (`:scope > .card`, `:scope .hero-title`). The fake test agent's CSS in the [repo agent template](https://github.com/pbakaus/impeccable/blob/8dac6ae7e020c43ab10ce9b41939f6fd42627b96/tests/live-e2e/agent.mjs) is a faithful template.
|
||||
|
||||
**JSX / TSX targets:** wrap `<style>` content in a template literal (CSS braces would parse as JSX), use `className=` / `style={{…}}`, keep `data-impeccable-*` attributes as plain strings:
|
||||
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
# No-argument routing: the context-aware menu
|
||||
# Command guidance
|
||||
|
||||
## Workflow questions
|
||||
|
||||
Give advice without executing commands; the menu below is only for bare invocations. Consult relevant command references as needed for prerequisites and scope. Link to the [docs](https://impeccable.style/docs/) for the broader workflow guide. If the user also requests execution, follow that request.
|
||||
|
||||
## No-argument routing: the context-aware menu
|
||||
|
||||
Read this when the user invokes `/impeccable` with no argument. They are asking "what should I do?" Make the menu context-aware instead of static.
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
0.1.0
|
||||
0.1.2
|
||||
|
||||
@@ -96,6 +96,19 @@ fetch_url() {
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
check_download() {
|
||||
download_file=${1:-$tmp}
|
||||
if [ ! -f "$download_file" ]; then
|
||||
rm -f "$tmp.sha256"
|
||||
echo "impeccable: download completed but the file was removed before execution: $url; check your antivirus quarantine or logs. Refusing to continue; do not disable protection." >&2
|
||||
exit 127
|
||||
fi
|
||||
if [ ! -s "$download_file" ]; then
|
||||
rm -f "$download_file" "$tmp.sha256"
|
||||
echo "impeccable: downloaded file is empty: $url; refusing the unverified download" >&2
|
||||
exit 127
|
||||
fi
|
||||
}
|
||||
if [ -n "$probing" ]; then
|
||||
# Inside another launcher's probe: no download, fail fast and quiet.
|
||||
exit 127
|
||||
@@ -116,6 +129,7 @@ if [ -n "$version" ] && [ "$os" != unknown ] && [ "$arch" != unknown ]; then
|
||||
fetch_url "$url" && fetched=1
|
||||
fi
|
||||
if [ "$fetched" = 1 ]; then
|
||||
check_download
|
||||
# Fail closed: a freshly downloaded binary runs only after verifying
|
||||
# against its .sha256 sidecar. A sidecar that cannot be fetched, or a
|
||||
# machine with no sha256 tool, refuses the download instead of exec'ing
|
||||
@@ -127,15 +141,20 @@ if [ -n "$version" ] && [ "$os" != unknown ] && [ "$arch" != unknown ]; then
|
||||
elif command -v wget >/dev/null 2>&1; then
|
||||
wget -q -O "$tmp.sha256" "$url.sha256" 2>/dev/null && sidecar_ok=1
|
||||
fi
|
||||
check_download
|
||||
expected=""
|
||||
[ "$sidecar_ok" = 1 ] && expected=$(cut -d' ' -f1 < "$tmp.sha256")
|
||||
actual=""
|
||||
if command -v shasum >/dev/null 2>&1; then actual=$(shasum -a 256 "$tmp" | cut -d' ' -f1)
|
||||
elif command -v sha256sum >/dev/null 2>&1; then actual=$(sha256sum "$tmp" | cut -d' ' -f1); fi
|
||||
if command -v shasum >/dev/null 2>&1; then
|
||||
if digest=$(shasum -a 256 "$tmp" 2>/dev/null); then actual=${digest%% *}; fi
|
||||
elif command -v sha256sum >/dev/null 2>&1; then
|
||||
if digest=$(sha256sum "$tmp" 2>/dev/null); then actual=${digest%% *}; fi
|
||||
fi
|
||||
check_download
|
||||
rm -f "$tmp.sha256"
|
||||
if [ -z "$expected" ] || [ -z "$actual" ]; then
|
||||
rm -f "$tmp"
|
||||
echo "impeccable: cannot verify $url against $url.sha256 (sidecar unavailable or no sha256 tool); refusing the unverified download" >&2
|
||||
echo "impeccable: cannot verify $url against $url.sha256 (sidecar unavailable or hashing failed); refusing the unverified download" >&2
|
||||
exit 127
|
||||
fi
|
||||
if [ "$actual" != "$expected" ]; then
|
||||
@@ -143,8 +162,22 @@ if [ -n "$version" ] && [ "$os" != unknown ] && [ "$arch" != unknown ]; then
|
||||
echo "impeccable: checksum mismatch downloading $url" >&2
|
||||
exit 127
|
||||
fi
|
||||
chmod +x "$tmp" 2>/dev/null
|
||||
mv -f "$tmp" "$cached" && exec "$cached" "$@"
|
||||
check_download
|
||||
if ! chmod +x "$tmp" 2>/dev/null; then
|
||||
check_download
|
||||
rm -f "$tmp"
|
||||
echo "impeccable: could not make the verified download executable: $url" >&2
|
||||
exit 127
|
||||
fi
|
||||
check_download
|
||||
if ! mv -f "$tmp" "$cached" 2>/dev/null; then
|
||||
check_download
|
||||
rm -f "$tmp"
|
||||
echo "impeccable: could not cache the verified download: $url" >&2
|
||||
exit 127
|
||||
fi
|
||||
check_download "$cached"
|
||||
exec "$cached" "$@"
|
||||
fi
|
||||
rm -f "$tmp" 2>/dev/null
|
||||
fi
|
||||
|
||||
@@ -82,6 +82,8 @@ curl.exe -fsSL -o "%cached%.part" "%url%" >nul 2>nul
|
||||
if errorlevel 1 goto fail
|
||||
|
||||
:verify
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
rem Mirrors the sh launcher and fails closed: a freshly downloaded binary
|
||||
rem runs only after verifying against its .sha256 sidecar. A sidecar that
|
||||
rem cannot be fetched, or an empty certutil result, refuses the download
|
||||
@@ -91,8 +93,16 @@ if errorlevel 1 goto verify_refuse
|
||||
set "expected="
|
||||
set /p expected=<"%cached%.sha256"
|
||||
for /f "tokens=1" %%h in ("%expected%") do set "expected=%%h"
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
set "actual="
|
||||
for /f "skip=1 delims=" %%h in ('certutil -hashfile "%cached%.part" SHA256 2^>nul') do if not defined actual set "actual=%%h"
|
||||
rem Reuse the sidecar staging file after reading expected. Check certutil's
|
||||
rem status before parsing: its error text on stdout is not a digest.
|
||||
certutil -hashfile "%cached%.part" SHA256 >"%cached%.sha256" 2>nul
|
||||
if errorlevel 1 goto verify_refuse
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
for /f "usebackq skip=1 delims=" %%h in ("%cached%.sha256") do if not defined actual set "actual=%%h"
|
||||
del "%cached%.sha256" >nul 2>nul
|
||||
if not defined expected goto verify_refuse
|
||||
if not defined actual goto verify_refuse
|
||||
@@ -103,17 +113,48 @@ echo impeccable: checksum mismatch downloading %url% 1>&2
|
||||
exit /b 127
|
||||
|
||||
:verify_refuse
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
del "%cached%.part" >nul 2>nul
|
||||
del "%cached%.sha256" >nul 2>nul
|
||||
echo impeccable: cannot verify %url% against %url%.sha256; refusing the unverified download 1>&2
|
||||
exit /b 127
|
||||
|
||||
:check_download
|
||||
set "download_file=%~1"
|
||||
if not defined download_file set "download_file=%cached%.part"
|
||||
if not exist "%download_file%" goto download_missing
|
||||
for %%f in ("%download_file%") do if %%~zf==0 goto download_empty
|
||||
exit /b 0
|
||||
|
||||
:download_missing
|
||||
del "%cached%.sha256" >nul 2>nul
|
||||
echo impeccable: download completed but the file was removed before execution: %url%; check your antivirus quarantine or logs. Refusing to continue; do not disable protection. 1>&2
|
||||
exit /b 127
|
||||
|
||||
:download_empty
|
||||
del "%download_file%" >nul 2>nul
|
||||
del "%cached%.sha256" >nul 2>nul
|
||||
echo impeccable: downloaded file is empty: %url%; refusing the unverified download 1>&2
|
||||
exit /b 127
|
||||
|
||||
:place
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
move /y "%cached%.part" "%cached%" >nul 2>nul
|
||||
if not exist "%cached%" goto fail
|
||||
if errorlevel 1 goto place_failed
|
||||
call :check_download "%cached%"
|
||||
if errorlevel 1 exit /b 127
|
||||
set "run=%cached%"
|
||||
goto run
|
||||
|
||||
:place_failed
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
del "%cached%.part" >nul 2>nul
|
||||
echo impeccable: could not cache the verified download: %url% 1>&2
|
||||
exit /b 127
|
||||
|
||||
:run
|
||||
"%run%" %*
|
||||
exit /b
|
||||
|
||||
@@ -7834,7 +7834,6 @@
|
||||
if (editBadgeEl && editBadgeEl.style.display !== 'none') renderEditBadge('idle-disabled');
|
||||
showBar('generating');
|
||||
saveSession();
|
||||
sendCheckpoint('generate_started');
|
||||
writeScrollY(window.scrollY);
|
||||
if (variantObserver) variantObserver.disconnect();
|
||||
variantObserver = startVariantObserver(currentSessionId);
|
||||
@@ -7916,7 +7915,6 @@
|
||||
showBar('generating');
|
||||
startScrollTracking();
|
||||
saveSession();
|
||||
sendCheckpoint('generate_started');
|
||||
writeScrollY(window.scrollY);
|
||||
if (variantObserver) variantObserver.disconnect();
|
||||
variantObserver = startVariantObserver(currentSessionId);
|
||||
@@ -8238,7 +8236,8 @@
|
||||
// rasterization from delaying the fetch itself.
|
||||
if (!hasAnnotations) {
|
||||
basePayload.clientSentAt = Date.now();
|
||||
await sendEvent(basePayload);
|
||||
const created = await sendEvent(basePayload);
|
||||
if (created?.ok && currentSessionId === basePayload.id) sendCheckpoint('generate_started');
|
||||
}
|
||||
|
||||
let screenshotPath;
|
||||
@@ -8279,7 +8278,10 @@
|
||||
// is semantic input. Plain requests were already dispatched above.
|
||||
if (hasAnnotations) {
|
||||
basePayload.clientSentAt = Date.now();
|
||||
sendEvent(screenshotPath ? { ...basePayload, screenshotPath } : basePayload);
|
||||
const created = await sendEvent(screenshotPath ? { ...basePayload, screenshotPath } : basePayload);
|
||||
// Capture/upload can take seconds. Progress before this acknowledgment
|
||||
// refers to an unknown session and would clear our own active work.
|
||||
if (created?.ok && currentSessionId === basePayload.id) sendCheckpoint('generate_started');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
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.
|
||||
metadata:
|
||||
version: 4.2.0
|
||||
version: 4.2.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.
|
||||
@@ -66,7 +66,8 @@ Choose the mode from the requested surface, not the product, and persist it only
|
||||
Routing:
|
||||
|
||||
- **No argument:** read [routing.md](reference/routing.md) and present its context-aware menu; never auto-run a command.
|
||||
- **Explicit or clearly implied command:** load its reference (native variant on native platforms) and follow it. Ask once if two commands fit.
|
||||
- **Explicit or clearly implied request to run a command:** load its reference (native variant on native platforms) and follow it. Ask once if two commands fit.
|
||||
- **Workflow or command-selection question:** read [Workflow questions](reference/routing.md#workflow-questions).
|
||||
- **Otherwise:** treat the request as general design work. Missing PRODUCT.md routes a new surface or replacement world through init, then new-work; a narrow refinement of existing code proceeds on the incumbent implementation as `impeccable context` directs, offering init afterward rather than blocking on it.
|
||||
- `teach` aliases `init`. `craft` is a deprecated alias for ordinary new-work and adds nothing. `shape` owns task discovery, then enters new-work only for visual-world and surface-concept decisions.
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ const __impeccableLiveDev =
|
||||
process.env.NODE_ENV === "development" ? ["http://localhost:8400"] : [];
|
||||
```
|
||||
|
||||
Per-framework: Next.js + monorepo helper: edit the *app's* `next.config.*` (not the shared helper), appending to `additionalScriptSrc` / `additionalConnectSrc`. SvelteKit: `svelte.config.js`, `kit.csp.directives['script-src']` and `['connect-src']`. Nuxt + nuxt-security: `nuxt.config.*`, `security.headers.contentSecurityPolicy['script-src']` and `['connect-src']`. Reference outputs: `tests/framework-fixtures/nextjs-turborepo/expected-after-patch.ts`, `tests/framework-fixtures/sveltekit-csp/expected-after-patch.js`. Idempotency: if `__impeccableLiveDev` already exists in the file, the patch is applied; just mark `cspChecked: true`.
|
||||
Per-framework: Next.js + monorepo helper: edit the *app's* `next.config.*` (not the shared helper), appending to `additionalScriptSrc` / `additionalConnectSrc`. SvelteKit: `svelte.config.js`, `kit.csp.directives['script-src']` and `['connect-src']`. Nuxt + nuxt-security: `nuxt.config.*`, `security.headers.contentSecurityPolicy['script-src']` and `['connect-src']`. Reference outputs: [nextjs-turborepo/expected-after-patch.ts](https://github.com/pbakaus/impeccable/blob/8dac6ae7e020c43ab10ce9b41939f6fd42627b96/tests/framework-fixtures/nextjs-turborepo/expected-after-patch.ts), [sveltekit-csp/expected-after-patch.js](https://github.com/pbakaus/impeccable/blob/8dac6ae7e020c43ab10ce9b41939f6fd42627b96/tests/framework-fixtures/sveltekit-csp/expected-after-patch.js). Idempotency: if `__impeccableLiveDev` already exists in the file, the patch is applied; just mark `cspChecked: true`.
|
||||
|
||||
### append-string
|
||||
|
||||
@@ -93,7 +93,7 @@ const __impeccableLiveDev =
|
||||
- `script-src 'self' 'unsafe-inline'` becomes `` `script-src 'self' 'unsafe-inline'${__impeccableLiveDev}` ``
|
||||
- `connect-src 'self'` becomes `` `connect-src 'self'${__impeccableLiveDev}` ``
|
||||
|
||||
Per-framework: Next.js inline `headers()` in `next.config.*`; Nuxt `routeRules['/**'].headers['Content-Security-Policy']` in `nuxt.config.*`. Reference outputs: `tests/framework-fixtures/nextjs-inline-csp/expected-after-patch.js`, `tests/framework-fixtures/nuxt-csp/expected-after-patch.ts`.
|
||||
Per-framework: Next.js inline `headers()` in `next.config.*`; Nuxt `routeRules['/**'].headers['Content-Security-Policy']` in `nuxt.config.*`. Reference outputs: [nextjs-inline-csp/expected-after-patch.js](https://github.com/pbakaus/impeccable/blob/8dac6ae7e020c43ab10ce9b41939f6fd42627b96/tests/framework-fixtures/nextjs-inline-csp/expected-after-patch.js), [nuxt-csp/expected-after-patch.ts](https://github.com/pbakaus/impeccable/blob/8dac6ae7e020c43ab10ce9b41939f6fd42627b96/tests/framework-fixtures/nuxt-csp/expected-after-patch.ts).
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
|
||||
@@ -198,7 +198,7 @@ Complete HTML replacement of the original element per variant, not a CSS-only pa
|
||||
|
||||
Replace the style opening tag with `cssAuthoring.styleTag` when the tool returns a different one. **Each variant div contains exactly one top-level element**, same tag as the original; loose siblings break outline tracking and accept. First variant visible, all others `display: none`. The browser's MutationObserver accepts atomic or progressive arrival; accepting an arrived variant fences the worker, so later publications are rejected.
|
||||
|
||||
For `styleMode: "scoped"`, author every `:scope` rule with a descendant combinator: the `@scope` boundary is the variant wrapper div, not your element, so a bare `:scope { ... }` styles a `display: contents` shell. Always step in (`:scope > .card`, `:scope .hero-title`). The fake test agent's CSS in `tests/live-e2e/agent.mjs` is a faithful template.
|
||||
For `styleMode: "scoped"`, author every `:scope` rule with a descendant combinator: the `@scope` boundary is the variant wrapper div, not your element, so a bare `:scope { ... }` styles a `display: contents` shell. Always step in (`:scope > .card`, `:scope .hero-title`). The fake test agent's CSS in the [repo agent template](https://github.com/pbakaus/impeccable/blob/8dac6ae7e020c43ab10ce9b41939f6fd42627b96/tests/live-e2e/agent.mjs) is a faithful template.
|
||||
|
||||
**JSX / TSX targets:** wrap `<style>` content in a template literal (CSS braces would parse as JSX), use `className=` / `style={{…}}`, keep `data-impeccable-*` attributes as plain strings:
|
||||
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
# No-argument routing: the context-aware menu
|
||||
# Command guidance
|
||||
|
||||
## Workflow questions
|
||||
|
||||
Give advice without executing commands; the menu below is only for bare invocations. Consult relevant command references as needed for prerequisites and scope. Link to the [docs](https://impeccable.style/docs/) for the broader workflow guide. If the user also requests execution, follow that request.
|
||||
|
||||
## No-argument routing: the context-aware menu
|
||||
|
||||
Read this when the user invokes `$impeccable` with no argument. They are asking "what should I do?" Make the menu context-aware instead of static.
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
0.1.0
|
||||
0.1.2
|
||||
|
||||
@@ -96,6 +96,19 @@ fetch_url() {
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
check_download() {
|
||||
download_file=${1:-$tmp}
|
||||
if [ ! -f "$download_file" ]; then
|
||||
rm -f "$tmp.sha256"
|
||||
echo "impeccable: download completed but the file was removed before execution: $url; check your antivirus quarantine or logs. Refusing to continue; do not disable protection." >&2
|
||||
exit 127
|
||||
fi
|
||||
if [ ! -s "$download_file" ]; then
|
||||
rm -f "$download_file" "$tmp.sha256"
|
||||
echo "impeccable: downloaded file is empty: $url; refusing the unverified download" >&2
|
||||
exit 127
|
||||
fi
|
||||
}
|
||||
if [ -n "$probing" ]; then
|
||||
# Inside another launcher's probe: no download, fail fast and quiet.
|
||||
exit 127
|
||||
@@ -116,6 +129,7 @@ if [ -n "$version" ] && [ "$os" != unknown ] && [ "$arch" != unknown ]; then
|
||||
fetch_url "$url" && fetched=1
|
||||
fi
|
||||
if [ "$fetched" = 1 ]; then
|
||||
check_download
|
||||
# Fail closed: a freshly downloaded binary runs only after verifying
|
||||
# against its .sha256 sidecar. A sidecar that cannot be fetched, or a
|
||||
# machine with no sha256 tool, refuses the download instead of exec'ing
|
||||
@@ -127,15 +141,20 @@ if [ -n "$version" ] && [ "$os" != unknown ] && [ "$arch" != unknown ]; then
|
||||
elif command -v wget >/dev/null 2>&1; then
|
||||
wget -q -O "$tmp.sha256" "$url.sha256" 2>/dev/null && sidecar_ok=1
|
||||
fi
|
||||
check_download
|
||||
expected=""
|
||||
[ "$sidecar_ok" = 1 ] && expected=$(cut -d' ' -f1 < "$tmp.sha256")
|
||||
actual=""
|
||||
if command -v shasum >/dev/null 2>&1; then actual=$(shasum -a 256 "$tmp" | cut -d' ' -f1)
|
||||
elif command -v sha256sum >/dev/null 2>&1; then actual=$(sha256sum "$tmp" | cut -d' ' -f1); fi
|
||||
if command -v shasum >/dev/null 2>&1; then
|
||||
if digest=$(shasum -a 256 "$tmp" 2>/dev/null); then actual=${digest%% *}; fi
|
||||
elif command -v sha256sum >/dev/null 2>&1; then
|
||||
if digest=$(sha256sum "$tmp" 2>/dev/null); then actual=${digest%% *}; fi
|
||||
fi
|
||||
check_download
|
||||
rm -f "$tmp.sha256"
|
||||
if [ -z "$expected" ] || [ -z "$actual" ]; then
|
||||
rm -f "$tmp"
|
||||
echo "impeccable: cannot verify $url against $url.sha256 (sidecar unavailable or no sha256 tool); refusing the unverified download" >&2
|
||||
echo "impeccable: cannot verify $url against $url.sha256 (sidecar unavailable or hashing failed); refusing the unverified download" >&2
|
||||
exit 127
|
||||
fi
|
||||
if [ "$actual" != "$expected" ]; then
|
||||
@@ -143,8 +162,22 @@ if [ -n "$version" ] && [ "$os" != unknown ] && [ "$arch" != unknown ]; then
|
||||
echo "impeccable: checksum mismatch downloading $url" >&2
|
||||
exit 127
|
||||
fi
|
||||
chmod +x "$tmp" 2>/dev/null
|
||||
mv -f "$tmp" "$cached" && exec "$cached" "$@"
|
||||
check_download
|
||||
if ! chmod +x "$tmp" 2>/dev/null; then
|
||||
check_download
|
||||
rm -f "$tmp"
|
||||
echo "impeccable: could not make the verified download executable: $url" >&2
|
||||
exit 127
|
||||
fi
|
||||
check_download
|
||||
if ! mv -f "$tmp" "$cached" 2>/dev/null; then
|
||||
check_download
|
||||
rm -f "$tmp"
|
||||
echo "impeccable: could not cache the verified download: $url" >&2
|
||||
exit 127
|
||||
fi
|
||||
check_download "$cached"
|
||||
exec "$cached" "$@"
|
||||
fi
|
||||
rm -f "$tmp" 2>/dev/null
|
||||
fi
|
||||
|
||||
@@ -82,6 +82,8 @@ curl.exe -fsSL -o "%cached%.part" "%url%" >nul 2>nul
|
||||
if errorlevel 1 goto fail
|
||||
|
||||
:verify
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
rem Mirrors the sh launcher and fails closed: a freshly downloaded binary
|
||||
rem runs only after verifying against its .sha256 sidecar. A sidecar that
|
||||
rem cannot be fetched, or an empty certutil result, refuses the download
|
||||
@@ -91,8 +93,16 @@ if errorlevel 1 goto verify_refuse
|
||||
set "expected="
|
||||
set /p expected=<"%cached%.sha256"
|
||||
for /f "tokens=1" %%h in ("%expected%") do set "expected=%%h"
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
set "actual="
|
||||
for /f "skip=1 delims=" %%h in ('certutil -hashfile "%cached%.part" SHA256 2^>nul') do if not defined actual set "actual=%%h"
|
||||
rem Reuse the sidecar staging file after reading expected. Check certutil's
|
||||
rem status before parsing: its error text on stdout is not a digest.
|
||||
certutil -hashfile "%cached%.part" SHA256 >"%cached%.sha256" 2>nul
|
||||
if errorlevel 1 goto verify_refuse
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
for /f "usebackq skip=1 delims=" %%h in ("%cached%.sha256") do if not defined actual set "actual=%%h"
|
||||
del "%cached%.sha256" >nul 2>nul
|
||||
if not defined expected goto verify_refuse
|
||||
if not defined actual goto verify_refuse
|
||||
@@ -103,17 +113,48 @@ echo impeccable: checksum mismatch downloading %url% 1>&2
|
||||
exit /b 127
|
||||
|
||||
:verify_refuse
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
del "%cached%.part" >nul 2>nul
|
||||
del "%cached%.sha256" >nul 2>nul
|
||||
echo impeccable: cannot verify %url% against %url%.sha256; refusing the unverified download 1>&2
|
||||
exit /b 127
|
||||
|
||||
:check_download
|
||||
set "download_file=%~1"
|
||||
if not defined download_file set "download_file=%cached%.part"
|
||||
if not exist "%download_file%" goto download_missing
|
||||
for %%f in ("%download_file%") do if %%~zf==0 goto download_empty
|
||||
exit /b 0
|
||||
|
||||
:download_missing
|
||||
del "%cached%.sha256" >nul 2>nul
|
||||
echo impeccable: download completed but the file was removed before execution: %url%; check your antivirus quarantine or logs. Refusing to continue; do not disable protection. 1>&2
|
||||
exit /b 127
|
||||
|
||||
:download_empty
|
||||
del "%download_file%" >nul 2>nul
|
||||
del "%cached%.sha256" >nul 2>nul
|
||||
echo impeccable: downloaded file is empty: %url%; refusing the unverified download 1>&2
|
||||
exit /b 127
|
||||
|
||||
:place
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
move /y "%cached%.part" "%cached%" >nul 2>nul
|
||||
if not exist "%cached%" goto fail
|
||||
if errorlevel 1 goto place_failed
|
||||
call :check_download "%cached%"
|
||||
if errorlevel 1 exit /b 127
|
||||
set "run=%cached%"
|
||||
goto run
|
||||
|
||||
:place_failed
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
del "%cached%.part" >nul 2>nul
|
||||
echo impeccable: could not cache the verified download: %url% 1>&2
|
||||
exit /b 127
|
||||
|
||||
:run
|
||||
"%run%" %*
|
||||
exit /b
|
||||
|
||||
@@ -7834,7 +7834,6 @@
|
||||
if (editBadgeEl && editBadgeEl.style.display !== 'none') renderEditBadge('idle-disabled');
|
||||
showBar('generating');
|
||||
saveSession();
|
||||
sendCheckpoint('generate_started');
|
||||
writeScrollY(window.scrollY);
|
||||
if (variantObserver) variantObserver.disconnect();
|
||||
variantObserver = startVariantObserver(currentSessionId);
|
||||
@@ -7916,7 +7915,6 @@
|
||||
showBar('generating');
|
||||
startScrollTracking();
|
||||
saveSession();
|
||||
sendCheckpoint('generate_started');
|
||||
writeScrollY(window.scrollY);
|
||||
if (variantObserver) variantObserver.disconnect();
|
||||
variantObserver = startVariantObserver(currentSessionId);
|
||||
@@ -8238,7 +8236,8 @@
|
||||
// rasterization from delaying the fetch itself.
|
||||
if (!hasAnnotations) {
|
||||
basePayload.clientSentAt = Date.now();
|
||||
await sendEvent(basePayload);
|
||||
const created = await sendEvent(basePayload);
|
||||
if (created?.ok && currentSessionId === basePayload.id) sendCheckpoint('generate_started');
|
||||
}
|
||||
|
||||
let screenshotPath;
|
||||
@@ -8279,7 +8278,10 @@
|
||||
// is semantic input. Plain requests were already dispatched above.
|
||||
if (hasAnnotations) {
|
||||
basePayload.clientSentAt = Date.now();
|
||||
sendEvent(screenshotPath ? { ...basePayload, screenshotPath } : basePayload);
|
||||
const created = await sendEvent(screenshotPath ? { ...basePayload, screenshotPath } : basePayload);
|
||||
// Capture/upload can take seconds. Progress before this acknowledgment
|
||||
// refers to an unknown session and would clear our own active work.
|
||||
if (created?.ok && currentSessionId === basePayload.id) sendCheckpoint('generate_started');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
{
|
||||
"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.",
|
||||
"version": "4.2.0",
|
||||
"version": "4.2.1",
|
||||
"author": {
|
||||
"name": "Paul Bakaus",
|
||||
"email": "paul@paulbakaus.com"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"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.",
|
||||
"version": "4.2.0",
|
||||
"version": "4.2.1",
|
||||
"author": {
|
||||
"name": "Paul Bakaus",
|
||||
"email": "paul@paulbakaus.com"
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
---
|
||||
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.
|
||||
version: 4.2.0
|
||||
version: 4.2.1
|
||||
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]"
|
||||
license: Apache 2.0
|
||||
allowed-tools:
|
||||
- Bash(npx impeccable *)
|
||||
- Bash(.claude/skills/impeccable/scripts/impeccable *)
|
||||
---
|
||||
|
||||
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.
|
||||
@@ -71,7 +68,8 @@ Choose the mode from the requested surface, not the product, and persist it only
|
||||
Routing:
|
||||
|
||||
- **No argument:** read [routing.md](reference/routing.md) and present its context-aware menu; never auto-run a command.
|
||||
- **Explicit or clearly implied command:** load its reference (native variant on native platforms) and follow it. Ask once if two commands fit.
|
||||
- **Explicit or clearly implied request to run a command:** load its reference (native variant on native platforms) and follow it. Ask once if two commands fit.
|
||||
- **Workflow or command-selection question:** read [Workflow questions](reference/routing.md#workflow-questions).
|
||||
- **Otherwise:** treat the request as general design work. Missing PRODUCT.md routes a new surface or replacement world through init, then new-work; a narrow refinement of existing code proceeds on the incumbent implementation as `impeccable context` directs, offering init afterward rather than blocking on it.
|
||||
- `teach` aliases `init`. `craft` is a deprecated alias for ordinary new-work and adds nothing. `shape` owns task discovery, then enters new-work only for visual-world and surface-concept decisions.
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ const __impeccableLiveDev =
|
||||
process.env.NODE_ENV === "development" ? ["http://localhost:8400"] : [];
|
||||
```
|
||||
|
||||
Per-framework: Next.js + monorepo helper: edit the *app's* `next.config.*` (not the shared helper), appending to `additionalScriptSrc` / `additionalConnectSrc`. SvelteKit: `svelte.config.js`, `kit.csp.directives['script-src']` and `['connect-src']`. Nuxt + nuxt-security: `nuxt.config.*`, `security.headers.contentSecurityPolicy['script-src']` and `['connect-src']`. Reference outputs: `tests/framework-fixtures/nextjs-turborepo/expected-after-patch.ts`, `tests/framework-fixtures/sveltekit-csp/expected-after-patch.js`. Idempotency: if `__impeccableLiveDev` already exists in the file, the patch is applied; just mark `cspChecked: true`.
|
||||
Per-framework: Next.js + monorepo helper: edit the *app's* `next.config.*` (not the shared helper), appending to `additionalScriptSrc` / `additionalConnectSrc`. SvelteKit: `svelte.config.js`, `kit.csp.directives['script-src']` and `['connect-src']`. Nuxt + nuxt-security: `nuxt.config.*`, `security.headers.contentSecurityPolicy['script-src']` and `['connect-src']`. Reference outputs: [nextjs-turborepo/expected-after-patch.ts](https://github.com/pbakaus/impeccable/blob/8dac6ae7e020c43ab10ce9b41939f6fd42627b96/tests/framework-fixtures/nextjs-turborepo/expected-after-patch.ts), [sveltekit-csp/expected-after-patch.js](https://github.com/pbakaus/impeccable/blob/8dac6ae7e020c43ab10ce9b41939f6fd42627b96/tests/framework-fixtures/sveltekit-csp/expected-after-patch.js). Idempotency: if `__impeccableLiveDev` already exists in the file, the patch is applied; just mark `cspChecked: true`.
|
||||
|
||||
### append-string
|
||||
|
||||
@@ -93,7 +93,7 @@ const __impeccableLiveDev =
|
||||
- `script-src 'self' 'unsafe-inline'` becomes `` `script-src 'self' 'unsafe-inline'${__impeccableLiveDev}` ``
|
||||
- `connect-src 'self'` becomes `` `connect-src 'self'${__impeccableLiveDev}` ``
|
||||
|
||||
Per-framework: Next.js inline `headers()` in `next.config.*`; Nuxt `routeRules['/**'].headers['Content-Security-Policy']` in `nuxt.config.*`. Reference outputs: `tests/framework-fixtures/nextjs-inline-csp/expected-after-patch.js`, `tests/framework-fixtures/nuxt-csp/expected-after-patch.ts`.
|
||||
Per-framework: Next.js inline `headers()` in `next.config.*`; Nuxt `routeRules['/**'].headers['Content-Security-Policy']` in `nuxt.config.*`. Reference outputs: [nextjs-inline-csp/expected-after-patch.js](https://github.com/pbakaus/impeccable/blob/8dac6ae7e020c43ab10ce9b41939f6fd42627b96/tests/framework-fixtures/nextjs-inline-csp/expected-after-patch.js), [nuxt-csp/expected-after-patch.ts](https://github.com/pbakaus/impeccable/blob/8dac6ae7e020c43ab10ce9b41939f6fd42627b96/tests/framework-fixtures/nuxt-csp/expected-after-patch.ts).
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
|
||||
@@ -196,7 +196,7 @@ Complete HTML replacement of the original element per variant, not a CSS-only pa
|
||||
|
||||
Replace the style opening tag with `cssAuthoring.styleTag` when the tool returns a different one. **Each variant div contains exactly one top-level element**, same tag as the original; loose siblings break outline tracking and accept. First variant visible, all others `display: none`. The browser's MutationObserver accepts atomic or progressive arrival; accepting an arrived variant fences the worker, so later publications are rejected.
|
||||
|
||||
For `styleMode: "scoped"`, author every `:scope` rule with a descendant combinator: the `@scope` boundary is the variant wrapper div, not your element, so a bare `:scope { ... }` styles a `display: contents` shell. Always step in (`:scope > .card`, `:scope .hero-title`). The fake test agent's CSS in `tests/live-e2e/agent.mjs` is a faithful template.
|
||||
For `styleMode: "scoped"`, author every `:scope` rule with a descendant combinator: the `@scope` boundary is the variant wrapper div, not your element, so a bare `:scope { ... }` styles a `display: contents` shell. Always step in (`:scope > .card`, `:scope .hero-title`). The fake test agent's CSS in the [repo agent template](https://github.com/pbakaus/impeccable/blob/8dac6ae7e020c43ab10ce9b41939f6fd42627b96/tests/live-e2e/agent.mjs) is a faithful template.
|
||||
|
||||
**JSX / TSX targets:** wrap `<style>` content in a template literal (CSS braces would parse as JSX), use `className=` / `style={{…}}`, keep `data-impeccable-*` attributes as plain strings:
|
||||
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
# No-argument routing: the context-aware menu
|
||||
# Command guidance
|
||||
|
||||
## Workflow questions
|
||||
|
||||
Give advice without executing commands; the menu below is only for bare invocations. Consult relevant command references as needed for prerequisites and scope. Link to the [docs](https://impeccable.style/docs/) for the broader workflow guide. If the user also requests execution, follow that request.
|
||||
|
||||
## No-argument routing: the context-aware menu
|
||||
|
||||
Read this when the user invokes `/impeccable` with no argument. They are asking "what should I do?" Make the menu context-aware instead of static.
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
0.1.0
|
||||
0.1.2
|
||||
|
||||
@@ -96,6 +96,19 @@ fetch_url() {
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
check_download() {
|
||||
download_file=${1:-$tmp}
|
||||
if [ ! -f "$download_file" ]; then
|
||||
rm -f "$tmp.sha256"
|
||||
echo "impeccable: download completed but the file was removed before execution: $url; check your antivirus quarantine or logs. Refusing to continue; do not disable protection." >&2
|
||||
exit 127
|
||||
fi
|
||||
if [ ! -s "$download_file" ]; then
|
||||
rm -f "$download_file" "$tmp.sha256"
|
||||
echo "impeccable: downloaded file is empty: $url; refusing the unverified download" >&2
|
||||
exit 127
|
||||
fi
|
||||
}
|
||||
if [ -n "$probing" ]; then
|
||||
# Inside another launcher's probe: no download, fail fast and quiet.
|
||||
exit 127
|
||||
@@ -116,6 +129,7 @@ if [ -n "$version" ] && [ "$os" != unknown ] && [ "$arch" != unknown ]; then
|
||||
fetch_url "$url" && fetched=1
|
||||
fi
|
||||
if [ "$fetched" = 1 ]; then
|
||||
check_download
|
||||
# Fail closed: a freshly downloaded binary runs only after verifying
|
||||
# against its .sha256 sidecar. A sidecar that cannot be fetched, or a
|
||||
# machine with no sha256 tool, refuses the download instead of exec'ing
|
||||
@@ -127,15 +141,20 @@ if [ -n "$version" ] && [ "$os" != unknown ] && [ "$arch" != unknown ]; then
|
||||
elif command -v wget >/dev/null 2>&1; then
|
||||
wget -q -O "$tmp.sha256" "$url.sha256" 2>/dev/null && sidecar_ok=1
|
||||
fi
|
||||
check_download
|
||||
expected=""
|
||||
[ "$sidecar_ok" = 1 ] && expected=$(cut -d' ' -f1 < "$tmp.sha256")
|
||||
actual=""
|
||||
if command -v shasum >/dev/null 2>&1; then actual=$(shasum -a 256 "$tmp" | cut -d' ' -f1)
|
||||
elif command -v sha256sum >/dev/null 2>&1; then actual=$(sha256sum "$tmp" | cut -d' ' -f1); fi
|
||||
if command -v shasum >/dev/null 2>&1; then
|
||||
if digest=$(shasum -a 256 "$tmp" 2>/dev/null); then actual=${digest%% *}; fi
|
||||
elif command -v sha256sum >/dev/null 2>&1; then
|
||||
if digest=$(sha256sum "$tmp" 2>/dev/null); then actual=${digest%% *}; fi
|
||||
fi
|
||||
check_download
|
||||
rm -f "$tmp.sha256"
|
||||
if [ -z "$expected" ] || [ -z "$actual" ]; then
|
||||
rm -f "$tmp"
|
||||
echo "impeccable: cannot verify $url against $url.sha256 (sidecar unavailable or no sha256 tool); refusing the unverified download" >&2
|
||||
echo "impeccable: cannot verify $url against $url.sha256 (sidecar unavailable or hashing failed); refusing the unverified download" >&2
|
||||
exit 127
|
||||
fi
|
||||
if [ "$actual" != "$expected" ]; then
|
||||
@@ -143,8 +162,22 @@ if [ -n "$version" ] && [ "$os" != unknown ] && [ "$arch" != unknown ]; then
|
||||
echo "impeccable: checksum mismatch downloading $url" >&2
|
||||
exit 127
|
||||
fi
|
||||
chmod +x "$tmp" 2>/dev/null
|
||||
mv -f "$tmp" "$cached" && exec "$cached" "$@"
|
||||
check_download
|
||||
if ! chmod +x "$tmp" 2>/dev/null; then
|
||||
check_download
|
||||
rm -f "$tmp"
|
||||
echo "impeccable: could not make the verified download executable: $url" >&2
|
||||
exit 127
|
||||
fi
|
||||
check_download
|
||||
if ! mv -f "$tmp" "$cached" 2>/dev/null; then
|
||||
check_download
|
||||
rm -f "$tmp"
|
||||
echo "impeccable: could not cache the verified download: $url" >&2
|
||||
exit 127
|
||||
fi
|
||||
check_download "$cached"
|
||||
exec "$cached" "$@"
|
||||
fi
|
||||
rm -f "$tmp" 2>/dev/null
|
||||
fi
|
||||
|
||||
@@ -82,6 +82,8 @@ curl.exe -fsSL -o "%cached%.part" "%url%" >nul 2>nul
|
||||
if errorlevel 1 goto fail
|
||||
|
||||
:verify
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
rem Mirrors the sh launcher and fails closed: a freshly downloaded binary
|
||||
rem runs only after verifying against its .sha256 sidecar. A sidecar that
|
||||
rem cannot be fetched, or an empty certutil result, refuses the download
|
||||
@@ -91,8 +93,16 @@ if errorlevel 1 goto verify_refuse
|
||||
set "expected="
|
||||
set /p expected=<"%cached%.sha256"
|
||||
for /f "tokens=1" %%h in ("%expected%") do set "expected=%%h"
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
set "actual="
|
||||
for /f "skip=1 delims=" %%h in ('certutil -hashfile "%cached%.part" SHA256 2^>nul') do if not defined actual set "actual=%%h"
|
||||
rem Reuse the sidecar staging file after reading expected. Check certutil's
|
||||
rem status before parsing: its error text on stdout is not a digest.
|
||||
certutil -hashfile "%cached%.part" SHA256 >"%cached%.sha256" 2>nul
|
||||
if errorlevel 1 goto verify_refuse
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
for /f "usebackq skip=1 delims=" %%h in ("%cached%.sha256") do if not defined actual set "actual=%%h"
|
||||
del "%cached%.sha256" >nul 2>nul
|
||||
if not defined expected goto verify_refuse
|
||||
if not defined actual goto verify_refuse
|
||||
@@ -103,17 +113,48 @@ echo impeccable: checksum mismatch downloading %url% 1>&2
|
||||
exit /b 127
|
||||
|
||||
:verify_refuse
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
del "%cached%.part" >nul 2>nul
|
||||
del "%cached%.sha256" >nul 2>nul
|
||||
echo impeccable: cannot verify %url% against %url%.sha256; refusing the unverified download 1>&2
|
||||
exit /b 127
|
||||
|
||||
:check_download
|
||||
set "download_file=%~1"
|
||||
if not defined download_file set "download_file=%cached%.part"
|
||||
if not exist "%download_file%" goto download_missing
|
||||
for %%f in ("%download_file%") do if %%~zf==0 goto download_empty
|
||||
exit /b 0
|
||||
|
||||
:download_missing
|
||||
del "%cached%.sha256" >nul 2>nul
|
||||
echo impeccable: download completed but the file was removed before execution: %url%; check your antivirus quarantine or logs. Refusing to continue; do not disable protection. 1>&2
|
||||
exit /b 127
|
||||
|
||||
:download_empty
|
||||
del "%download_file%" >nul 2>nul
|
||||
del "%cached%.sha256" >nul 2>nul
|
||||
echo impeccable: downloaded file is empty: %url%; refusing the unverified download 1>&2
|
||||
exit /b 127
|
||||
|
||||
:place
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
move /y "%cached%.part" "%cached%" >nul 2>nul
|
||||
if not exist "%cached%" goto fail
|
||||
if errorlevel 1 goto place_failed
|
||||
call :check_download "%cached%"
|
||||
if errorlevel 1 exit /b 127
|
||||
set "run=%cached%"
|
||||
goto run
|
||||
|
||||
:place_failed
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
del "%cached%.part" >nul 2>nul
|
||||
echo impeccable: could not cache the verified download: %url% 1>&2
|
||||
exit /b 127
|
||||
|
||||
:run
|
||||
"%run%" %*
|
||||
exit /b
|
||||
|
||||
@@ -7834,7 +7834,6 @@
|
||||
if (editBadgeEl && editBadgeEl.style.display !== 'none') renderEditBadge('idle-disabled');
|
||||
showBar('generating');
|
||||
saveSession();
|
||||
sendCheckpoint('generate_started');
|
||||
writeScrollY(window.scrollY);
|
||||
if (variantObserver) variantObserver.disconnect();
|
||||
variantObserver = startVariantObserver(currentSessionId);
|
||||
@@ -7916,7 +7915,6 @@
|
||||
showBar('generating');
|
||||
startScrollTracking();
|
||||
saveSession();
|
||||
sendCheckpoint('generate_started');
|
||||
writeScrollY(window.scrollY);
|
||||
if (variantObserver) variantObserver.disconnect();
|
||||
variantObserver = startVariantObserver(currentSessionId);
|
||||
@@ -8238,7 +8236,8 @@
|
||||
// rasterization from delaying the fetch itself.
|
||||
if (!hasAnnotations) {
|
||||
basePayload.clientSentAt = Date.now();
|
||||
await sendEvent(basePayload);
|
||||
const created = await sendEvent(basePayload);
|
||||
if (created?.ok && currentSessionId === basePayload.id) sendCheckpoint('generate_started');
|
||||
}
|
||||
|
||||
let screenshotPath;
|
||||
@@ -8279,7 +8278,10 @@
|
||||
// is semantic input. Plain requests were already dispatched above.
|
||||
if (hasAnnotations) {
|
||||
basePayload.clientSentAt = Date.now();
|
||||
sendEvent(screenshotPath ? { ...basePayload, screenshotPath } : basePayload);
|
||||
const created = await sendEvent(screenshotPath ? { ...basePayload, screenshotPath } : basePayload);
|
||||
// Capture/upload can take seconds. Progress before this acknowledgment
|
||||
// refers to an unknown session and would clear our own active work.
|
||||
if (created?.ok && currentSessionId === basePayload.id) sendCheckpoint('generate_started');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
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.
|
||||
version: 4.2.0
|
||||
version: 4.2.1
|
||||
license: Apache 2.0
|
||||
---
|
||||
|
||||
@@ -66,7 +66,8 @@ Choose the mode from the requested surface, not the product, and persist it only
|
||||
Routing:
|
||||
|
||||
- **No argument:** read [routing.md](reference/routing.md) and present its context-aware menu; never auto-run a command.
|
||||
- **Explicit or clearly implied command:** load its reference (native variant on native platforms) and follow it. Ask once if two commands fit.
|
||||
- **Explicit or clearly implied request to run a command:** load its reference (native variant on native platforms) and follow it. Ask once if two commands fit.
|
||||
- **Workflow or command-selection question:** read [Workflow questions](reference/routing.md#workflow-questions).
|
||||
- **Otherwise:** treat the request as general design work. Missing PRODUCT.md routes a new surface or replacement world through init, then new-work; a narrow refinement of existing code proceeds on the incumbent implementation as `impeccable context` directs, offering init afterward rather than blocking on it.
|
||||
- `teach` aliases `init`. `craft` is a deprecated alias for ordinary new-work and adds nothing. `shape` owns task discovery, then enters new-work only for visual-world and surface-concept decisions.
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ const __impeccableLiveDev =
|
||||
process.env.NODE_ENV === "development" ? ["http://localhost:8400"] : [];
|
||||
```
|
||||
|
||||
Per-framework: Next.js + monorepo helper: edit the *app's* `next.config.*` (not the shared helper), appending to `additionalScriptSrc` / `additionalConnectSrc`. SvelteKit: `svelte.config.js`, `kit.csp.directives['script-src']` and `['connect-src']`. Nuxt + nuxt-security: `nuxt.config.*`, `security.headers.contentSecurityPolicy['script-src']` and `['connect-src']`. Reference outputs: `tests/framework-fixtures/nextjs-turborepo/expected-after-patch.ts`, `tests/framework-fixtures/sveltekit-csp/expected-after-patch.js`. Idempotency: if `__impeccableLiveDev` already exists in the file, the patch is applied; just mark `cspChecked: true`.
|
||||
Per-framework: Next.js + monorepo helper: edit the *app's* `next.config.*` (not the shared helper), appending to `additionalScriptSrc` / `additionalConnectSrc`. SvelteKit: `svelte.config.js`, `kit.csp.directives['script-src']` and `['connect-src']`. Nuxt + nuxt-security: `nuxt.config.*`, `security.headers.contentSecurityPolicy['script-src']` and `['connect-src']`. Reference outputs: [nextjs-turborepo/expected-after-patch.ts](https://github.com/pbakaus/impeccable/blob/8dac6ae7e020c43ab10ce9b41939f6fd42627b96/tests/framework-fixtures/nextjs-turborepo/expected-after-patch.ts), [sveltekit-csp/expected-after-patch.js](https://github.com/pbakaus/impeccable/blob/8dac6ae7e020c43ab10ce9b41939f6fd42627b96/tests/framework-fixtures/sveltekit-csp/expected-after-patch.js). Idempotency: if `__impeccableLiveDev` already exists in the file, the patch is applied; just mark `cspChecked: true`.
|
||||
|
||||
### append-string
|
||||
|
||||
@@ -93,7 +93,7 @@ const __impeccableLiveDev =
|
||||
- `script-src 'self' 'unsafe-inline'` becomes `` `script-src 'self' 'unsafe-inline'${__impeccableLiveDev}` ``
|
||||
- `connect-src 'self'` becomes `` `connect-src 'self'${__impeccableLiveDev}` ``
|
||||
|
||||
Per-framework: Next.js inline `headers()` in `next.config.*`; Nuxt `routeRules['/**'].headers['Content-Security-Policy']` in `nuxt.config.*`. Reference outputs: `tests/framework-fixtures/nextjs-inline-csp/expected-after-patch.js`, `tests/framework-fixtures/nuxt-csp/expected-after-patch.ts`.
|
||||
Per-framework: Next.js inline `headers()` in `next.config.*`; Nuxt `routeRules['/**'].headers['Content-Security-Policy']` in `nuxt.config.*`. Reference outputs: [nextjs-inline-csp/expected-after-patch.js](https://github.com/pbakaus/impeccable/blob/8dac6ae7e020c43ab10ce9b41939f6fd42627b96/tests/framework-fixtures/nextjs-inline-csp/expected-after-patch.js), [nuxt-csp/expected-after-patch.ts](https://github.com/pbakaus/impeccable/blob/8dac6ae7e020c43ab10ce9b41939f6fd42627b96/tests/framework-fixtures/nuxt-csp/expected-after-patch.ts).
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
|
||||
@@ -196,7 +196,7 @@ Complete HTML replacement of the original element per variant, not a CSS-only pa
|
||||
|
||||
Replace the style opening tag with `cssAuthoring.styleTag` when the tool returns a different one. **Each variant div contains exactly one top-level element**, same tag as the original; loose siblings break outline tracking and accept. First variant visible, all others `display: none`. The browser's MutationObserver accepts atomic or progressive arrival; accepting an arrived variant fences the worker, so later publications are rejected.
|
||||
|
||||
For `styleMode: "scoped"`, author every `:scope` rule with a descendant combinator: the `@scope` boundary is the variant wrapper div, not your element, so a bare `:scope { ... }` styles a `display: contents` shell. Always step in (`:scope > .card`, `:scope .hero-title`). The fake test agent's CSS in `tests/live-e2e/agent.mjs` is a faithful template.
|
||||
For `styleMode: "scoped"`, author every `:scope` rule with a descendant combinator: the `@scope` boundary is the variant wrapper div, not your element, so a bare `:scope { ... }` styles a `display: contents` shell. Always step in (`:scope > .card`, `:scope .hero-title`). The fake test agent's CSS in the [repo agent template](https://github.com/pbakaus/impeccable/blob/8dac6ae7e020c43ab10ce9b41939f6fd42627b96/tests/live-e2e/agent.mjs) is a faithful template.
|
||||
|
||||
**JSX / TSX targets:** wrap `<style>` content in a template literal (CSS braces would parse as JSX), use `className=` / `style={{…}}`, keep `data-impeccable-*` attributes as plain strings:
|
||||
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
# No-argument routing: the context-aware menu
|
||||
# Command guidance
|
||||
|
||||
## Workflow questions
|
||||
|
||||
Give advice without executing commands; the menu below is only for bare invocations. Consult relevant command references as needed for prerequisites and scope. Link to the [docs](https://impeccable.style/docs/) for the broader workflow guide. If the user also requests execution, follow that request.
|
||||
|
||||
## No-argument routing: the context-aware menu
|
||||
|
||||
Read this when the user invokes `/impeccable` with no argument. They are asking "what should I do?" Make the menu context-aware instead of static.
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
0.1.0
|
||||
0.1.2
|
||||
|
||||
@@ -96,6 +96,19 @@ fetch_url() {
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
check_download() {
|
||||
download_file=${1:-$tmp}
|
||||
if [ ! -f "$download_file" ]; then
|
||||
rm -f "$tmp.sha256"
|
||||
echo "impeccable: download completed but the file was removed before execution: $url; check your antivirus quarantine or logs. Refusing to continue; do not disable protection." >&2
|
||||
exit 127
|
||||
fi
|
||||
if [ ! -s "$download_file" ]; then
|
||||
rm -f "$download_file" "$tmp.sha256"
|
||||
echo "impeccable: downloaded file is empty: $url; refusing the unverified download" >&2
|
||||
exit 127
|
||||
fi
|
||||
}
|
||||
if [ -n "$probing" ]; then
|
||||
# Inside another launcher's probe: no download, fail fast and quiet.
|
||||
exit 127
|
||||
@@ -116,6 +129,7 @@ if [ -n "$version" ] && [ "$os" != unknown ] && [ "$arch" != unknown ]; then
|
||||
fetch_url "$url" && fetched=1
|
||||
fi
|
||||
if [ "$fetched" = 1 ]; then
|
||||
check_download
|
||||
# Fail closed: a freshly downloaded binary runs only after verifying
|
||||
# against its .sha256 sidecar. A sidecar that cannot be fetched, or a
|
||||
# machine with no sha256 tool, refuses the download instead of exec'ing
|
||||
@@ -127,15 +141,20 @@ if [ -n "$version" ] && [ "$os" != unknown ] && [ "$arch" != unknown ]; then
|
||||
elif command -v wget >/dev/null 2>&1; then
|
||||
wget -q -O "$tmp.sha256" "$url.sha256" 2>/dev/null && sidecar_ok=1
|
||||
fi
|
||||
check_download
|
||||
expected=""
|
||||
[ "$sidecar_ok" = 1 ] && expected=$(cut -d' ' -f1 < "$tmp.sha256")
|
||||
actual=""
|
||||
if command -v shasum >/dev/null 2>&1; then actual=$(shasum -a 256 "$tmp" | cut -d' ' -f1)
|
||||
elif command -v sha256sum >/dev/null 2>&1; then actual=$(sha256sum "$tmp" | cut -d' ' -f1); fi
|
||||
if command -v shasum >/dev/null 2>&1; then
|
||||
if digest=$(shasum -a 256 "$tmp" 2>/dev/null); then actual=${digest%% *}; fi
|
||||
elif command -v sha256sum >/dev/null 2>&1; then
|
||||
if digest=$(sha256sum "$tmp" 2>/dev/null); then actual=${digest%% *}; fi
|
||||
fi
|
||||
check_download
|
||||
rm -f "$tmp.sha256"
|
||||
if [ -z "$expected" ] || [ -z "$actual" ]; then
|
||||
rm -f "$tmp"
|
||||
echo "impeccable: cannot verify $url against $url.sha256 (sidecar unavailable or no sha256 tool); refusing the unverified download" >&2
|
||||
echo "impeccable: cannot verify $url against $url.sha256 (sidecar unavailable or hashing failed); refusing the unverified download" >&2
|
||||
exit 127
|
||||
fi
|
||||
if [ "$actual" != "$expected" ]; then
|
||||
@@ -143,8 +162,22 @@ if [ -n "$version" ] && [ "$os" != unknown ] && [ "$arch" != unknown ]; then
|
||||
echo "impeccable: checksum mismatch downloading $url" >&2
|
||||
exit 127
|
||||
fi
|
||||
chmod +x "$tmp" 2>/dev/null
|
||||
mv -f "$tmp" "$cached" && exec "$cached" "$@"
|
||||
check_download
|
||||
if ! chmod +x "$tmp" 2>/dev/null; then
|
||||
check_download
|
||||
rm -f "$tmp"
|
||||
echo "impeccable: could not make the verified download executable: $url" >&2
|
||||
exit 127
|
||||
fi
|
||||
check_download
|
||||
if ! mv -f "$tmp" "$cached" 2>/dev/null; then
|
||||
check_download
|
||||
rm -f "$tmp"
|
||||
echo "impeccable: could not cache the verified download: $url" >&2
|
||||
exit 127
|
||||
fi
|
||||
check_download "$cached"
|
||||
exec "$cached" "$@"
|
||||
fi
|
||||
rm -f "$tmp" 2>/dev/null
|
||||
fi
|
||||
|
||||
@@ -82,6 +82,8 @@ curl.exe -fsSL -o "%cached%.part" "%url%" >nul 2>nul
|
||||
if errorlevel 1 goto fail
|
||||
|
||||
:verify
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
rem Mirrors the sh launcher and fails closed: a freshly downloaded binary
|
||||
rem runs only after verifying against its .sha256 sidecar. A sidecar that
|
||||
rem cannot be fetched, or an empty certutil result, refuses the download
|
||||
@@ -91,8 +93,16 @@ if errorlevel 1 goto verify_refuse
|
||||
set "expected="
|
||||
set /p expected=<"%cached%.sha256"
|
||||
for /f "tokens=1" %%h in ("%expected%") do set "expected=%%h"
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
set "actual="
|
||||
for /f "skip=1 delims=" %%h in ('certutil -hashfile "%cached%.part" SHA256 2^>nul') do if not defined actual set "actual=%%h"
|
||||
rem Reuse the sidecar staging file after reading expected. Check certutil's
|
||||
rem status before parsing: its error text on stdout is not a digest.
|
||||
certutil -hashfile "%cached%.part" SHA256 >"%cached%.sha256" 2>nul
|
||||
if errorlevel 1 goto verify_refuse
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
for /f "usebackq skip=1 delims=" %%h in ("%cached%.sha256") do if not defined actual set "actual=%%h"
|
||||
del "%cached%.sha256" >nul 2>nul
|
||||
if not defined expected goto verify_refuse
|
||||
if not defined actual goto verify_refuse
|
||||
@@ -103,17 +113,48 @@ echo impeccable: checksum mismatch downloading %url% 1>&2
|
||||
exit /b 127
|
||||
|
||||
:verify_refuse
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
del "%cached%.part" >nul 2>nul
|
||||
del "%cached%.sha256" >nul 2>nul
|
||||
echo impeccable: cannot verify %url% against %url%.sha256; refusing the unverified download 1>&2
|
||||
exit /b 127
|
||||
|
||||
:check_download
|
||||
set "download_file=%~1"
|
||||
if not defined download_file set "download_file=%cached%.part"
|
||||
if not exist "%download_file%" goto download_missing
|
||||
for %%f in ("%download_file%") do if %%~zf==0 goto download_empty
|
||||
exit /b 0
|
||||
|
||||
:download_missing
|
||||
del "%cached%.sha256" >nul 2>nul
|
||||
echo impeccable: download completed but the file was removed before execution: %url%; check your antivirus quarantine or logs. Refusing to continue; do not disable protection. 1>&2
|
||||
exit /b 127
|
||||
|
||||
:download_empty
|
||||
del "%download_file%" >nul 2>nul
|
||||
del "%cached%.sha256" >nul 2>nul
|
||||
echo impeccable: downloaded file is empty: %url%; refusing the unverified download 1>&2
|
||||
exit /b 127
|
||||
|
||||
:place
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
move /y "%cached%.part" "%cached%" >nul 2>nul
|
||||
if not exist "%cached%" goto fail
|
||||
if errorlevel 1 goto place_failed
|
||||
call :check_download "%cached%"
|
||||
if errorlevel 1 exit /b 127
|
||||
set "run=%cached%"
|
||||
goto run
|
||||
|
||||
:place_failed
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
del "%cached%.part" >nul 2>nul
|
||||
echo impeccable: could not cache the verified download: %url% 1>&2
|
||||
exit /b 127
|
||||
|
||||
:run
|
||||
"%run%" %*
|
||||
exit /b
|
||||
|
||||
@@ -7834,7 +7834,6 @@
|
||||
if (editBadgeEl && editBadgeEl.style.display !== 'none') renderEditBadge('idle-disabled');
|
||||
showBar('generating');
|
||||
saveSession();
|
||||
sendCheckpoint('generate_started');
|
||||
writeScrollY(window.scrollY);
|
||||
if (variantObserver) variantObserver.disconnect();
|
||||
variantObserver = startVariantObserver(currentSessionId);
|
||||
@@ -7916,7 +7915,6 @@
|
||||
showBar('generating');
|
||||
startScrollTracking();
|
||||
saveSession();
|
||||
sendCheckpoint('generate_started');
|
||||
writeScrollY(window.scrollY);
|
||||
if (variantObserver) variantObserver.disconnect();
|
||||
variantObserver = startVariantObserver(currentSessionId);
|
||||
@@ -8238,7 +8236,8 @@
|
||||
// rasterization from delaying the fetch itself.
|
||||
if (!hasAnnotations) {
|
||||
basePayload.clientSentAt = Date.now();
|
||||
await sendEvent(basePayload);
|
||||
const created = await sendEvent(basePayload);
|
||||
if (created?.ok && currentSessionId === basePayload.id) sendCheckpoint('generate_started');
|
||||
}
|
||||
|
||||
let screenshotPath;
|
||||
@@ -8279,7 +8278,10 @@
|
||||
// is semantic input. Plain requests were already dispatched above.
|
||||
if (hasAnnotations) {
|
||||
basePayload.clientSentAt = Date.now();
|
||||
sendEvent(screenshotPath ? { ...basePayload, screenshotPath } : basePayload);
|
||||
const created = await sendEvent(screenshotPath ? { ...basePayload, screenshotPath } : basePayload);
|
||||
// Capture/upload can take seconds. Progress before this acknowledgment
|
||||
// refers to an unknown session and would clear our own active work.
|
||||
if (created?.ok && currentSessionId === basePayload.id) sendCheckpoint('generate_started');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
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.
|
||||
version: 4.2.0
|
||||
version: 4.2.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.
|
||||
@@ -65,7 +65,8 @@ Choose the mode from the requested surface, not the product, and persist it only
|
||||
Routing:
|
||||
|
||||
- **No argument:** read [routing.md](reference/routing.md) and present its context-aware menu; never auto-run a command.
|
||||
- **Explicit or clearly implied command:** load its reference (native variant on native platforms) and follow it. Ask once if two commands fit.
|
||||
- **Explicit or clearly implied request to run a command:** load its reference (native variant on native platforms) and follow it. Ask once if two commands fit.
|
||||
- **Workflow or command-selection question:** read [Workflow questions](reference/routing.md#workflow-questions).
|
||||
- **Otherwise:** treat the request as general design work. Missing PRODUCT.md routes a new surface or replacement world through init, then new-work; a narrow refinement of existing code proceeds on the incumbent implementation as `impeccable context` directs, offering init afterward rather than blocking on it.
|
||||
- `teach` aliases `init`. `craft` is a deprecated alias for ordinary new-work and adds nothing. `shape` owns task discovery, then enters new-work only for visual-world and surface-concept decisions.
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ const __impeccableLiveDev =
|
||||
process.env.NODE_ENV === "development" ? ["http://localhost:8400"] : [];
|
||||
```
|
||||
|
||||
Per-framework: Next.js + monorepo helper: edit the *app's* `next.config.*` (not the shared helper), appending to `additionalScriptSrc` / `additionalConnectSrc`. SvelteKit: `svelte.config.js`, `kit.csp.directives['script-src']` and `['connect-src']`. Nuxt + nuxt-security: `nuxt.config.*`, `security.headers.contentSecurityPolicy['script-src']` and `['connect-src']`. Reference outputs: `tests/framework-fixtures/nextjs-turborepo/expected-after-patch.ts`, `tests/framework-fixtures/sveltekit-csp/expected-after-patch.js`. Idempotency: if `__impeccableLiveDev` already exists in the file, the patch is applied; just mark `cspChecked: true`.
|
||||
Per-framework: Next.js + monorepo helper: edit the *app's* `next.config.*` (not the shared helper), appending to `additionalScriptSrc` / `additionalConnectSrc`. SvelteKit: `svelte.config.js`, `kit.csp.directives['script-src']` and `['connect-src']`. Nuxt + nuxt-security: `nuxt.config.*`, `security.headers.contentSecurityPolicy['script-src']` and `['connect-src']`. Reference outputs: [nextjs-turborepo/expected-after-patch.ts](https://github.com/pbakaus/impeccable/blob/8dac6ae7e020c43ab10ce9b41939f6fd42627b96/tests/framework-fixtures/nextjs-turborepo/expected-after-patch.ts), [sveltekit-csp/expected-after-patch.js](https://github.com/pbakaus/impeccable/blob/8dac6ae7e020c43ab10ce9b41939f6fd42627b96/tests/framework-fixtures/sveltekit-csp/expected-after-patch.js). Idempotency: if `__impeccableLiveDev` already exists in the file, the patch is applied; just mark `cspChecked: true`.
|
||||
|
||||
### append-string
|
||||
|
||||
@@ -93,7 +93,7 @@ const __impeccableLiveDev =
|
||||
- `script-src 'self' 'unsafe-inline'` becomes `` `script-src 'self' 'unsafe-inline'${__impeccableLiveDev}` ``
|
||||
- `connect-src 'self'` becomes `` `connect-src 'self'${__impeccableLiveDev}` ``
|
||||
|
||||
Per-framework: Next.js inline `headers()` in `next.config.*`; Nuxt `routeRules['/**'].headers['Content-Security-Policy']` in `nuxt.config.*`. Reference outputs: `tests/framework-fixtures/nextjs-inline-csp/expected-after-patch.js`, `tests/framework-fixtures/nuxt-csp/expected-after-patch.ts`.
|
||||
Per-framework: Next.js inline `headers()` in `next.config.*`; Nuxt `routeRules['/**'].headers['Content-Security-Policy']` in `nuxt.config.*`. Reference outputs: [nextjs-inline-csp/expected-after-patch.js](https://github.com/pbakaus/impeccable/blob/8dac6ae7e020c43ab10ce9b41939f6fd42627b96/tests/framework-fixtures/nextjs-inline-csp/expected-after-patch.js), [nuxt-csp/expected-after-patch.ts](https://github.com/pbakaus/impeccable/blob/8dac6ae7e020c43ab10ce9b41939f6fd42627b96/tests/framework-fixtures/nuxt-csp/expected-after-patch.ts).
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
|
||||
@@ -196,7 +196,7 @@ Complete HTML replacement of the original element per variant, not a CSS-only pa
|
||||
|
||||
Replace the style opening tag with `cssAuthoring.styleTag` when the tool returns a different one. **Each variant div contains exactly one top-level element**, same tag as the original; loose siblings break outline tracking and accept. First variant visible, all others `display: none`. The browser's MutationObserver accepts atomic or progressive arrival; accepting an arrived variant fences the worker, so later publications are rejected.
|
||||
|
||||
For `styleMode: "scoped"`, author every `:scope` rule with a descendant combinator: the `@scope` boundary is the variant wrapper div, not your element, so a bare `:scope { ... }` styles a `display: contents` shell. Always step in (`:scope > .card`, `:scope .hero-title`). The fake test agent's CSS in `tests/live-e2e/agent.mjs` is a faithful template.
|
||||
For `styleMode: "scoped"`, author every `:scope` rule with a descendant combinator: the `@scope` boundary is the variant wrapper div, not your element, so a bare `:scope { ... }` styles a `display: contents` shell. Always step in (`:scope > .card`, `:scope .hero-title`). The fake test agent's CSS in the [repo agent template](https://github.com/pbakaus/impeccable/blob/8dac6ae7e020c43ab10ce9b41939f6fd42627b96/tests/live-e2e/agent.mjs) is a faithful template.
|
||||
|
||||
**JSX / TSX targets:** wrap `<style>` content in a template literal (CSS braces would parse as JSX), use `className=` / `style={{…}}`, keep `data-impeccable-*` attributes as plain strings:
|
||||
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
# No-argument routing: the context-aware menu
|
||||
# Command guidance
|
||||
|
||||
## Workflow questions
|
||||
|
||||
Give advice without executing commands; the menu below is only for bare invocations. Consult relevant command references as needed for prerequisites and scope. Link to the [docs](https://impeccable.style/docs/) for the broader workflow guide. If the user also requests execution, follow that request.
|
||||
|
||||
## No-argument routing: the context-aware menu
|
||||
|
||||
Read this when the user invokes `/impeccable` with no argument. They are asking "what should I do?" Make the menu context-aware instead of static.
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
0.1.0
|
||||
0.1.2
|
||||
|
||||
@@ -96,6 +96,19 @@ fetch_url() {
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
check_download() {
|
||||
download_file=${1:-$tmp}
|
||||
if [ ! -f "$download_file" ]; then
|
||||
rm -f "$tmp.sha256"
|
||||
echo "impeccable: download completed but the file was removed before execution: $url; check your antivirus quarantine or logs. Refusing to continue; do not disable protection." >&2
|
||||
exit 127
|
||||
fi
|
||||
if [ ! -s "$download_file" ]; then
|
||||
rm -f "$download_file" "$tmp.sha256"
|
||||
echo "impeccable: downloaded file is empty: $url; refusing the unverified download" >&2
|
||||
exit 127
|
||||
fi
|
||||
}
|
||||
if [ -n "$probing" ]; then
|
||||
# Inside another launcher's probe: no download, fail fast and quiet.
|
||||
exit 127
|
||||
@@ -116,6 +129,7 @@ if [ -n "$version" ] && [ "$os" != unknown ] && [ "$arch" != unknown ]; then
|
||||
fetch_url "$url" && fetched=1
|
||||
fi
|
||||
if [ "$fetched" = 1 ]; then
|
||||
check_download
|
||||
# Fail closed: a freshly downloaded binary runs only after verifying
|
||||
# against its .sha256 sidecar. A sidecar that cannot be fetched, or a
|
||||
# machine with no sha256 tool, refuses the download instead of exec'ing
|
||||
@@ -127,15 +141,20 @@ if [ -n "$version" ] && [ "$os" != unknown ] && [ "$arch" != unknown ]; then
|
||||
elif command -v wget >/dev/null 2>&1; then
|
||||
wget -q -O "$tmp.sha256" "$url.sha256" 2>/dev/null && sidecar_ok=1
|
||||
fi
|
||||
check_download
|
||||
expected=""
|
||||
[ "$sidecar_ok" = 1 ] && expected=$(cut -d' ' -f1 < "$tmp.sha256")
|
||||
actual=""
|
||||
if command -v shasum >/dev/null 2>&1; then actual=$(shasum -a 256 "$tmp" | cut -d' ' -f1)
|
||||
elif command -v sha256sum >/dev/null 2>&1; then actual=$(sha256sum "$tmp" | cut -d' ' -f1); fi
|
||||
if command -v shasum >/dev/null 2>&1; then
|
||||
if digest=$(shasum -a 256 "$tmp" 2>/dev/null); then actual=${digest%% *}; fi
|
||||
elif command -v sha256sum >/dev/null 2>&1; then
|
||||
if digest=$(sha256sum "$tmp" 2>/dev/null); then actual=${digest%% *}; fi
|
||||
fi
|
||||
check_download
|
||||
rm -f "$tmp.sha256"
|
||||
if [ -z "$expected" ] || [ -z "$actual" ]; then
|
||||
rm -f "$tmp"
|
||||
echo "impeccable: cannot verify $url against $url.sha256 (sidecar unavailable or no sha256 tool); refusing the unverified download" >&2
|
||||
echo "impeccable: cannot verify $url against $url.sha256 (sidecar unavailable or hashing failed); refusing the unverified download" >&2
|
||||
exit 127
|
||||
fi
|
||||
if [ "$actual" != "$expected" ]; then
|
||||
@@ -143,8 +162,22 @@ if [ -n "$version" ] && [ "$os" != unknown ] && [ "$arch" != unknown ]; then
|
||||
echo "impeccable: checksum mismatch downloading $url" >&2
|
||||
exit 127
|
||||
fi
|
||||
chmod +x "$tmp" 2>/dev/null
|
||||
mv -f "$tmp" "$cached" && exec "$cached" "$@"
|
||||
check_download
|
||||
if ! chmod +x "$tmp" 2>/dev/null; then
|
||||
check_download
|
||||
rm -f "$tmp"
|
||||
echo "impeccable: could not make the verified download executable: $url" >&2
|
||||
exit 127
|
||||
fi
|
||||
check_download
|
||||
if ! mv -f "$tmp" "$cached" 2>/dev/null; then
|
||||
check_download
|
||||
rm -f "$tmp"
|
||||
echo "impeccable: could not cache the verified download: $url" >&2
|
||||
exit 127
|
||||
fi
|
||||
check_download "$cached"
|
||||
exec "$cached" "$@"
|
||||
fi
|
||||
rm -f "$tmp" 2>/dev/null
|
||||
fi
|
||||
|
||||
@@ -82,6 +82,8 @@ curl.exe -fsSL -o "%cached%.part" "%url%" >nul 2>nul
|
||||
if errorlevel 1 goto fail
|
||||
|
||||
:verify
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
rem Mirrors the sh launcher and fails closed: a freshly downloaded binary
|
||||
rem runs only after verifying against its .sha256 sidecar. A sidecar that
|
||||
rem cannot be fetched, or an empty certutil result, refuses the download
|
||||
@@ -91,8 +93,16 @@ if errorlevel 1 goto verify_refuse
|
||||
set "expected="
|
||||
set /p expected=<"%cached%.sha256"
|
||||
for /f "tokens=1" %%h in ("%expected%") do set "expected=%%h"
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
set "actual="
|
||||
for /f "skip=1 delims=" %%h in ('certutil -hashfile "%cached%.part" SHA256 2^>nul') do if not defined actual set "actual=%%h"
|
||||
rem Reuse the sidecar staging file after reading expected. Check certutil's
|
||||
rem status before parsing: its error text on stdout is not a digest.
|
||||
certutil -hashfile "%cached%.part" SHA256 >"%cached%.sha256" 2>nul
|
||||
if errorlevel 1 goto verify_refuse
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
for /f "usebackq skip=1 delims=" %%h in ("%cached%.sha256") do if not defined actual set "actual=%%h"
|
||||
del "%cached%.sha256" >nul 2>nul
|
||||
if not defined expected goto verify_refuse
|
||||
if not defined actual goto verify_refuse
|
||||
@@ -103,17 +113,48 @@ echo impeccable: checksum mismatch downloading %url% 1>&2
|
||||
exit /b 127
|
||||
|
||||
:verify_refuse
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
del "%cached%.part" >nul 2>nul
|
||||
del "%cached%.sha256" >nul 2>nul
|
||||
echo impeccable: cannot verify %url% against %url%.sha256; refusing the unverified download 1>&2
|
||||
exit /b 127
|
||||
|
||||
:check_download
|
||||
set "download_file=%~1"
|
||||
if not defined download_file set "download_file=%cached%.part"
|
||||
if not exist "%download_file%" goto download_missing
|
||||
for %%f in ("%download_file%") do if %%~zf==0 goto download_empty
|
||||
exit /b 0
|
||||
|
||||
:download_missing
|
||||
del "%cached%.sha256" >nul 2>nul
|
||||
echo impeccable: download completed but the file was removed before execution: %url%; check your antivirus quarantine or logs. Refusing to continue; do not disable protection. 1>&2
|
||||
exit /b 127
|
||||
|
||||
:download_empty
|
||||
del "%download_file%" >nul 2>nul
|
||||
del "%cached%.sha256" >nul 2>nul
|
||||
echo impeccable: downloaded file is empty: %url%; refusing the unverified download 1>&2
|
||||
exit /b 127
|
||||
|
||||
:place
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
move /y "%cached%.part" "%cached%" >nul 2>nul
|
||||
if not exist "%cached%" goto fail
|
||||
if errorlevel 1 goto place_failed
|
||||
call :check_download "%cached%"
|
||||
if errorlevel 1 exit /b 127
|
||||
set "run=%cached%"
|
||||
goto run
|
||||
|
||||
:place_failed
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
del "%cached%.part" >nul 2>nul
|
||||
echo impeccable: could not cache the verified download: %url% 1>&2
|
||||
exit /b 127
|
||||
|
||||
:run
|
||||
"%run%" %*
|
||||
exit /b
|
||||
|
||||
@@ -7834,7 +7834,6 @@
|
||||
if (editBadgeEl && editBadgeEl.style.display !== 'none') renderEditBadge('idle-disabled');
|
||||
showBar('generating');
|
||||
saveSession();
|
||||
sendCheckpoint('generate_started');
|
||||
writeScrollY(window.scrollY);
|
||||
if (variantObserver) variantObserver.disconnect();
|
||||
variantObserver = startVariantObserver(currentSessionId);
|
||||
@@ -7916,7 +7915,6 @@
|
||||
showBar('generating');
|
||||
startScrollTracking();
|
||||
saveSession();
|
||||
sendCheckpoint('generate_started');
|
||||
writeScrollY(window.scrollY);
|
||||
if (variantObserver) variantObserver.disconnect();
|
||||
variantObserver = startVariantObserver(currentSessionId);
|
||||
@@ -8238,7 +8236,8 @@
|
||||
// rasterization from delaying the fetch itself.
|
||||
if (!hasAnnotations) {
|
||||
basePayload.clientSentAt = Date.now();
|
||||
await sendEvent(basePayload);
|
||||
const created = await sendEvent(basePayload);
|
||||
if (created?.ok && currentSessionId === basePayload.id) sendCheckpoint('generate_started');
|
||||
}
|
||||
|
||||
let screenshotPath;
|
||||
@@ -8279,7 +8278,10 @@
|
||||
// is semantic input. Plain requests were already dispatched above.
|
||||
if (hasAnnotations) {
|
||||
basePayload.clientSentAt = Date.now();
|
||||
sendEvent(screenshotPath ? { ...basePayload, screenshotPath } : basePayload);
|
||||
const created = await sendEvent(screenshotPath ? { ...basePayload, screenshotPath } : basePayload);
|
||||
// Capture/upload can take seconds. Progress before this acknowledgment
|
||||
// refers to an unknown session and would clear our own active work.
|
||||
if (created?.ok && currentSessionId === basePayload.id) sendCheckpoint('generate_started');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
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.
|
||||
version: 4.2.0
|
||||
version: 4.2.1
|
||||
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]"
|
||||
license: Apache 2.0
|
||||
@@ -68,7 +68,8 @@ Choose the mode from the requested surface, not the product, and persist it only
|
||||
Routing:
|
||||
|
||||
- **No argument:** read [routing.md](reference/routing.md) and present its context-aware menu; never auto-run a command.
|
||||
- **Explicit or clearly implied command:** load its reference (native variant on native platforms) and follow it. Ask once if two commands fit.
|
||||
- **Explicit or clearly implied request to run a command:** load its reference (native variant on native platforms) and follow it. Ask once if two commands fit.
|
||||
- **Workflow or command-selection question:** read [Workflow questions](reference/routing.md#workflow-questions).
|
||||
- **Otherwise:** treat the request as general design work. Missing PRODUCT.md routes a new surface or replacement world through init, then new-work; a narrow refinement of existing code proceeds on the incumbent implementation as `impeccable context` directs, offering init afterward rather than blocking on it.
|
||||
- `teach` aliases `init`. `craft` is a deprecated alias for ordinary new-work and adds nothing. `shape` owns task discovery, then enters new-work only for visual-world and surface-concept decisions.
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ const __impeccableLiveDev =
|
||||
process.env.NODE_ENV === "development" ? ["http://localhost:8400"] : [];
|
||||
```
|
||||
|
||||
Per-framework: Next.js + monorepo helper: edit the *app's* `next.config.*` (not the shared helper), appending to `additionalScriptSrc` / `additionalConnectSrc`. SvelteKit: `svelte.config.js`, `kit.csp.directives['script-src']` and `['connect-src']`. Nuxt + nuxt-security: `nuxt.config.*`, `security.headers.contentSecurityPolicy['script-src']` and `['connect-src']`. Reference outputs: `tests/framework-fixtures/nextjs-turborepo/expected-after-patch.ts`, `tests/framework-fixtures/sveltekit-csp/expected-after-patch.js`. Idempotency: if `__impeccableLiveDev` already exists in the file, the patch is applied; just mark `cspChecked: true`.
|
||||
Per-framework: Next.js + monorepo helper: edit the *app's* `next.config.*` (not the shared helper), appending to `additionalScriptSrc` / `additionalConnectSrc`. SvelteKit: `svelte.config.js`, `kit.csp.directives['script-src']` and `['connect-src']`. Nuxt + nuxt-security: `nuxt.config.*`, `security.headers.contentSecurityPolicy['script-src']` and `['connect-src']`. Reference outputs: [nextjs-turborepo/expected-after-patch.ts](https://github.com/pbakaus/impeccable/blob/8dac6ae7e020c43ab10ce9b41939f6fd42627b96/tests/framework-fixtures/nextjs-turborepo/expected-after-patch.ts), [sveltekit-csp/expected-after-patch.js](https://github.com/pbakaus/impeccable/blob/8dac6ae7e020c43ab10ce9b41939f6fd42627b96/tests/framework-fixtures/sveltekit-csp/expected-after-patch.js). Idempotency: if `__impeccableLiveDev` already exists in the file, the patch is applied; just mark `cspChecked: true`.
|
||||
|
||||
### append-string
|
||||
|
||||
@@ -93,7 +93,7 @@ const __impeccableLiveDev =
|
||||
- `script-src 'self' 'unsafe-inline'` becomes `` `script-src 'self' 'unsafe-inline'${__impeccableLiveDev}` ``
|
||||
- `connect-src 'self'` becomes `` `connect-src 'self'${__impeccableLiveDev}` ``
|
||||
|
||||
Per-framework: Next.js inline `headers()` in `next.config.*`; Nuxt `routeRules['/**'].headers['Content-Security-Policy']` in `nuxt.config.*`. Reference outputs: `tests/framework-fixtures/nextjs-inline-csp/expected-after-patch.js`, `tests/framework-fixtures/nuxt-csp/expected-after-patch.ts`.
|
||||
Per-framework: Next.js inline `headers()` in `next.config.*`; Nuxt `routeRules['/**'].headers['Content-Security-Policy']` in `nuxt.config.*`. Reference outputs: [nextjs-inline-csp/expected-after-patch.js](https://github.com/pbakaus/impeccable/blob/8dac6ae7e020c43ab10ce9b41939f6fd42627b96/tests/framework-fixtures/nextjs-inline-csp/expected-after-patch.js), [nuxt-csp/expected-after-patch.ts](https://github.com/pbakaus/impeccable/blob/8dac6ae7e020c43ab10ce9b41939f6fd42627b96/tests/framework-fixtures/nuxt-csp/expected-after-patch.ts).
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
|
||||
@@ -196,7 +196,7 @@ Complete HTML replacement of the original element per variant, not a CSS-only pa
|
||||
|
||||
Replace the style opening tag with `cssAuthoring.styleTag` when the tool returns a different one. **Each variant div contains exactly one top-level element**, same tag as the original; loose siblings break outline tracking and accept. First variant visible, all others `display: none`. The browser's MutationObserver accepts atomic or progressive arrival; accepting an arrived variant fences the worker, so later publications are rejected.
|
||||
|
||||
For `styleMode: "scoped"`, author every `:scope` rule with a descendant combinator: the `@scope` boundary is the variant wrapper div, not your element, so a bare `:scope { ... }` styles a `display: contents` shell. Always step in (`:scope > .card`, `:scope .hero-title`). The fake test agent's CSS in `tests/live-e2e/agent.mjs` is a faithful template.
|
||||
For `styleMode: "scoped"`, author every `:scope` rule with a descendant combinator: the `@scope` boundary is the variant wrapper div, not your element, so a bare `:scope { ... }` styles a `display: contents` shell. Always step in (`:scope > .card`, `:scope .hero-title`). The fake test agent's CSS in the [repo agent template](https://github.com/pbakaus/impeccable/blob/8dac6ae7e020c43ab10ce9b41939f6fd42627b96/tests/live-e2e/agent.mjs) is a faithful template.
|
||||
|
||||
**JSX / TSX targets:** wrap `<style>` content in a template literal (CSS braces would parse as JSX), use `className=` / `style={{…}}`, keep `data-impeccable-*` attributes as plain strings:
|
||||
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
# No-argument routing: the context-aware menu
|
||||
# Command guidance
|
||||
|
||||
## Workflow questions
|
||||
|
||||
Give advice without executing commands; the menu below is only for bare invocations. Consult relevant command references as needed for prerequisites and scope. Link to the [docs](https://impeccable.style/docs/) for the broader workflow guide. If the user also requests execution, follow that request.
|
||||
|
||||
## No-argument routing: the context-aware menu
|
||||
|
||||
Read this when the user invokes `/impeccable` with no argument. They are asking "what should I do?" Make the menu context-aware instead of static.
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
0.1.0
|
||||
0.1.2
|
||||
|
||||
@@ -96,6 +96,19 @@ fetch_url() {
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
check_download() {
|
||||
download_file=${1:-$tmp}
|
||||
if [ ! -f "$download_file" ]; then
|
||||
rm -f "$tmp.sha256"
|
||||
echo "impeccable: download completed but the file was removed before execution: $url; check your antivirus quarantine or logs. Refusing to continue; do not disable protection." >&2
|
||||
exit 127
|
||||
fi
|
||||
if [ ! -s "$download_file" ]; then
|
||||
rm -f "$download_file" "$tmp.sha256"
|
||||
echo "impeccable: downloaded file is empty: $url; refusing the unverified download" >&2
|
||||
exit 127
|
||||
fi
|
||||
}
|
||||
if [ -n "$probing" ]; then
|
||||
# Inside another launcher's probe: no download, fail fast and quiet.
|
||||
exit 127
|
||||
@@ -116,6 +129,7 @@ if [ -n "$version" ] && [ "$os" != unknown ] && [ "$arch" != unknown ]; then
|
||||
fetch_url "$url" && fetched=1
|
||||
fi
|
||||
if [ "$fetched" = 1 ]; then
|
||||
check_download
|
||||
# Fail closed: a freshly downloaded binary runs only after verifying
|
||||
# against its .sha256 sidecar. A sidecar that cannot be fetched, or a
|
||||
# machine with no sha256 tool, refuses the download instead of exec'ing
|
||||
@@ -127,15 +141,20 @@ if [ -n "$version" ] && [ "$os" != unknown ] && [ "$arch" != unknown ]; then
|
||||
elif command -v wget >/dev/null 2>&1; then
|
||||
wget -q -O "$tmp.sha256" "$url.sha256" 2>/dev/null && sidecar_ok=1
|
||||
fi
|
||||
check_download
|
||||
expected=""
|
||||
[ "$sidecar_ok" = 1 ] && expected=$(cut -d' ' -f1 < "$tmp.sha256")
|
||||
actual=""
|
||||
if command -v shasum >/dev/null 2>&1; then actual=$(shasum -a 256 "$tmp" | cut -d' ' -f1)
|
||||
elif command -v sha256sum >/dev/null 2>&1; then actual=$(sha256sum "$tmp" | cut -d' ' -f1); fi
|
||||
if command -v shasum >/dev/null 2>&1; then
|
||||
if digest=$(shasum -a 256 "$tmp" 2>/dev/null); then actual=${digest%% *}; fi
|
||||
elif command -v sha256sum >/dev/null 2>&1; then
|
||||
if digest=$(sha256sum "$tmp" 2>/dev/null); then actual=${digest%% *}; fi
|
||||
fi
|
||||
check_download
|
||||
rm -f "$tmp.sha256"
|
||||
if [ -z "$expected" ] || [ -z "$actual" ]; then
|
||||
rm -f "$tmp"
|
||||
echo "impeccable: cannot verify $url against $url.sha256 (sidecar unavailable or no sha256 tool); refusing the unverified download" >&2
|
||||
echo "impeccable: cannot verify $url against $url.sha256 (sidecar unavailable or hashing failed); refusing the unverified download" >&2
|
||||
exit 127
|
||||
fi
|
||||
if [ "$actual" != "$expected" ]; then
|
||||
@@ -143,8 +162,22 @@ if [ -n "$version" ] && [ "$os" != unknown ] && [ "$arch" != unknown ]; then
|
||||
echo "impeccable: checksum mismatch downloading $url" >&2
|
||||
exit 127
|
||||
fi
|
||||
chmod +x "$tmp" 2>/dev/null
|
||||
mv -f "$tmp" "$cached" && exec "$cached" "$@"
|
||||
check_download
|
||||
if ! chmod +x "$tmp" 2>/dev/null; then
|
||||
check_download
|
||||
rm -f "$tmp"
|
||||
echo "impeccable: could not make the verified download executable: $url" >&2
|
||||
exit 127
|
||||
fi
|
||||
check_download
|
||||
if ! mv -f "$tmp" "$cached" 2>/dev/null; then
|
||||
check_download
|
||||
rm -f "$tmp"
|
||||
echo "impeccable: could not cache the verified download: $url" >&2
|
||||
exit 127
|
||||
fi
|
||||
check_download "$cached"
|
||||
exec "$cached" "$@"
|
||||
fi
|
||||
rm -f "$tmp" 2>/dev/null
|
||||
fi
|
||||
|
||||
@@ -82,6 +82,8 @@ curl.exe -fsSL -o "%cached%.part" "%url%" >nul 2>nul
|
||||
if errorlevel 1 goto fail
|
||||
|
||||
:verify
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
rem Mirrors the sh launcher and fails closed: a freshly downloaded binary
|
||||
rem runs only after verifying against its .sha256 sidecar. A sidecar that
|
||||
rem cannot be fetched, or an empty certutil result, refuses the download
|
||||
@@ -91,8 +93,16 @@ if errorlevel 1 goto verify_refuse
|
||||
set "expected="
|
||||
set /p expected=<"%cached%.sha256"
|
||||
for /f "tokens=1" %%h in ("%expected%") do set "expected=%%h"
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
set "actual="
|
||||
for /f "skip=1 delims=" %%h in ('certutil -hashfile "%cached%.part" SHA256 2^>nul') do if not defined actual set "actual=%%h"
|
||||
rem Reuse the sidecar staging file after reading expected. Check certutil's
|
||||
rem status before parsing: its error text on stdout is not a digest.
|
||||
certutil -hashfile "%cached%.part" SHA256 >"%cached%.sha256" 2>nul
|
||||
if errorlevel 1 goto verify_refuse
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
for /f "usebackq skip=1 delims=" %%h in ("%cached%.sha256") do if not defined actual set "actual=%%h"
|
||||
del "%cached%.sha256" >nul 2>nul
|
||||
if not defined expected goto verify_refuse
|
||||
if not defined actual goto verify_refuse
|
||||
@@ -103,17 +113,48 @@ echo impeccable: checksum mismatch downloading %url% 1>&2
|
||||
exit /b 127
|
||||
|
||||
:verify_refuse
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
del "%cached%.part" >nul 2>nul
|
||||
del "%cached%.sha256" >nul 2>nul
|
||||
echo impeccable: cannot verify %url% against %url%.sha256; refusing the unverified download 1>&2
|
||||
exit /b 127
|
||||
|
||||
:check_download
|
||||
set "download_file=%~1"
|
||||
if not defined download_file set "download_file=%cached%.part"
|
||||
if not exist "%download_file%" goto download_missing
|
||||
for %%f in ("%download_file%") do if %%~zf==0 goto download_empty
|
||||
exit /b 0
|
||||
|
||||
:download_missing
|
||||
del "%cached%.sha256" >nul 2>nul
|
||||
echo impeccable: download completed but the file was removed before execution: %url%; check your antivirus quarantine or logs. Refusing to continue; do not disable protection. 1>&2
|
||||
exit /b 127
|
||||
|
||||
:download_empty
|
||||
del "%download_file%" >nul 2>nul
|
||||
del "%cached%.sha256" >nul 2>nul
|
||||
echo impeccable: downloaded file is empty: %url%; refusing the unverified download 1>&2
|
||||
exit /b 127
|
||||
|
||||
:place
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
move /y "%cached%.part" "%cached%" >nul 2>nul
|
||||
if not exist "%cached%" goto fail
|
||||
if errorlevel 1 goto place_failed
|
||||
call :check_download "%cached%"
|
||||
if errorlevel 1 exit /b 127
|
||||
set "run=%cached%"
|
||||
goto run
|
||||
|
||||
:place_failed
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
del "%cached%.part" >nul 2>nul
|
||||
echo impeccable: could not cache the verified download: %url% 1>&2
|
||||
exit /b 127
|
||||
|
||||
:run
|
||||
"%run%" %*
|
||||
exit /b
|
||||
|
||||
@@ -7834,7 +7834,6 @@
|
||||
if (editBadgeEl && editBadgeEl.style.display !== 'none') renderEditBadge('idle-disabled');
|
||||
showBar('generating');
|
||||
saveSession();
|
||||
sendCheckpoint('generate_started');
|
||||
writeScrollY(window.scrollY);
|
||||
if (variantObserver) variantObserver.disconnect();
|
||||
variantObserver = startVariantObserver(currentSessionId);
|
||||
@@ -7916,7 +7915,6 @@
|
||||
showBar('generating');
|
||||
startScrollTracking();
|
||||
saveSession();
|
||||
sendCheckpoint('generate_started');
|
||||
writeScrollY(window.scrollY);
|
||||
if (variantObserver) variantObserver.disconnect();
|
||||
variantObserver = startVariantObserver(currentSessionId);
|
||||
@@ -8238,7 +8236,8 @@
|
||||
// rasterization from delaying the fetch itself.
|
||||
if (!hasAnnotations) {
|
||||
basePayload.clientSentAt = Date.now();
|
||||
await sendEvent(basePayload);
|
||||
const created = await sendEvent(basePayload);
|
||||
if (created?.ok && currentSessionId === basePayload.id) sendCheckpoint('generate_started');
|
||||
}
|
||||
|
||||
let screenshotPath;
|
||||
@@ -8279,7 +8278,10 @@
|
||||
// is semantic input. Plain requests were already dispatched above.
|
||||
if (hasAnnotations) {
|
||||
basePayload.clientSentAt = Date.now();
|
||||
sendEvent(screenshotPath ? { ...basePayload, screenshotPath } : basePayload);
|
||||
const created = await sendEvent(screenshotPath ? { ...basePayload, screenshotPath } : basePayload);
|
||||
// Capture/upload can take seconds. Progress before this acknowledgment
|
||||
// refers to an unknown session and would clear our own active work.
|
||||
if (created?.ok && currentSessionId === basePayload.id) sendCheckpoint('generate_started');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -188,6 +188,20 @@ jobs:
|
||||
- run: cargo build --workspace --all-targets
|
||||
- run: cargo test --workspace --no-fail-fast
|
||||
|
||||
launcher-windows:
|
||||
runs-on: windows-latest
|
||||
needs: changes
|
||||
if: needs.changes.outputs.core == 'true'
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v7
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v7
|
||||
with:
|
||||
node-version: 24
|
||||
- name: Exercise Windows launcher downloads and verification
|
||||
run: node --test tests/launcher-download.test.mjs
|
||||
|
||||
# Behavior gate: replays the tests/oracle/ goldens against a release build
|
||||
# of the engine from THIS checkout (so a PR is judged on its own source,
|
||||
# not on the last published binary). Without this job the oracle only ever
|
||||
|
||||
@@ -11,8 +11,10 @@ name: release-engine
|
||||
on:
|
||||
push:
|
||||
tags: ['engine-v*']
|
||||
# Same-run artifact transfers use ACTIONS_RUNTIME_TOKEN, not GITHUB_TOKEN;
|
||||
# they do not require actions: read/write. Keep downloads scoped to this run.
|
||||
permissions:
|
||||
contents: write
|
||||
contents: read
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
@@ -53,15 +55,79 @@ jobs:
|
||||
run: target/${{ matrix.target }}/release/impeccable${{ runner.os == 'Windows' && '.exe' || '' }} engine-probe
|
||||
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: impeccable-${{ matrix.short }}
|
||||
# Keep unsigned Windows output outside the publish job's pattern.
|
||||
name: ${{ matrix.short == 'windows-x64' && 'unsigned-windows-x64' || format('impeccable-{0}', matrix.short) }}
|
||||
path: target/${{ matrix.target }}/release/impeccable${{ runner.os == 'Windows' && '.exe' || '' }}
|
||||
if-no-files-found: error
|
||||
publish:
|
||||
sign-windows:
|
||||
needs: build
|
||||
runs-on: windows-latest
|
||||
timeout-minutes: 15
|
||||
environment: windows-signing
|
||||
permissions:
|
||||
contents: read
|
||||
id-token: write
|
||||
steps:
|
||||
# A fresh runner signs only this run's engine. It does not check out or
|
||||
# execute repository code with the Azure identity available.
|
||||
- uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
|
||||
with:
|
||||
name: unsigned-windows-x64
|
||||
path: unsigned
|
||||
- name: Azure login (OIDC)
|
||||
uses: azure/login@7ddb5af1ef8758cf1353cf3b42f940aee27ba21c # v3
|
||||
with:
|
||||
client-id: ${{ vars.AZURE_CLIENT_ID }}
|
||||
tenant-id: ${{ vars.AZURE_TENANT_ID }}
|
||||
subscription-id: ${{ vars.AZURE_SUBSCRIPTION_ID }}
|
||||
- name: Sign Windows engine
|
||||
uses: azure/artifact-signing-action@c7ab2a863ab5f9a846ddb8265964877ef296ee82 # v2
|
||||
with:
|
||||
endpoint: https://eus.codesigning.azure.net/
|
||||
signing-account-name: impeccable-signing
|
||||
certificate-profile-name: impeccable-windows
|
||||
files: ${{ github.workspace }}\unsigned\impeccable.exe
|
||||
file-digest: SHA256
|
||||
timestamp-rfc3161: http://timestamp.acs.microsoft.com
|
||||
timestamp-digest: SHA256
|
||||
description: Impeccable engine
|
||||
description-url: https://impeccable.style
|
||||
exclude-environment-credential: true
|
||||
# Only the preceding OIDC Azure CLI login is used. Other credential
|
||||
# types are excluded by this pinned action's defaults.
|
||||
exclude-azure-cli-credential: false
|
||||
cache-dependencies: false
|
||||
- name: Verify signed engine
|
||||
shell: pwsh
|
||||
run: |
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$signature = Get-AuthenticodeSignature -LiteralPath 'unsigned/impeccable.exe'
|
||||
if ($signature.Status -ne 'Valid') {
|
||||
throw "Invalid Windows signature: $($signature.Status) — $($signature.StatusMessage)"
|
||||
}
|
||||
$publisher = $signature.SignerCertificate.GetNameInfo([System.Security.Cryptography.X509Certificates.X509NameType]::SimpleName, $false)
|
||||
if ($publisher -cne 'Renaissance Geek, Inc.') {
|
||||
throw "Unexpected Windows publisher: $publisher"
|
||||
}
|
||||
if ($null -eq $signature.TimeStamperCertificate) {
|
||||
throw 'The Windows signature has no timestamp.'
|
||||
}
|
||||
Write-Output "Verified publisher: $publisher; certificate: $($signature.SignerCertificate.Thumbprint)"
|
||||
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: impeccable-windows-x64
|
||||
path: unsigned/impeccable.exe
|
||||
if-no-files-found: error
|
||||
publish:
|
||||
needs: [build, sign-windows]
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
|
||||
with: { path: artifacts }
|
||||
with:
|
||||
pattern: impeccable-*
|
||||
path: artifacts
|
||||
- name: Lay out release assets with checksums
|
||||
run: |
|
||||
set -e
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
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.
|
||||
version: 4.2.0
|
||||
version: 4.2.1
|
||||
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]"
|
||||
license: Apache 2.0
|
||||
@@ -71,7 +71,8 @@ Choose the mode from the requested surface, not the product, and persist it only
|
||||
Routing:
|
||||
|
||||
- **No argument:** read [routing.md](reference/routing.md) and present its context-aware menu; never auto-run a command.
|
||||
- **Explicit or clearly implied command:** load its reference (native variant on native platforms) and follow it. Ask once if two commands fit.
|
||||
- **Explicit or clearly implied request to run a command:** load its reference (native variant on native platforms) and follow it. Ask once if two commands fit.
|
||||
- **Workflow or command-selection question:** read [Workflow questions](reference/routing.md#workflow-questions).
|
||||
- **Otherwise:** treat the request as general design work. Missing PRODUCT.md routes a new surface or replacement world through init, then new-work; a narrow refinement of existing code proceeds on the incumbent implementation as `impeccable context` directs, offering init afterward rather than blocking on it.
|
||||
- `teach` aliases `init`. `craft` is a deprecated alias for ordinary new-work and adds nothing. `shape` owns task discovery, then enters new-work only for visual-world and surface-concept decisions.
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ const __impeccableLiveDev =
|
||||
process.env.NODE_ENV === "development" ? ["http://localhost:8400"] : [];
|
||||
```
|
||||
|
||||
Per-framework: Next.js + monorepo helper: edit the *app's* `next.config.*` (not the shared helper), appending to `additionalScriptSrc` / `additionalConnectSrc`. SvelteKit: `svelte.config.js`, `kit.csp.directives['script-src']` and `['connect-src']`. Nuxt + nuxt-security: `nuxt.config.*`, `security.headers.contentSecurityPolicy['script-src']` and `['connect-src']`. Reference outputs: `tests/framework-fixtures/nextjs-turborepo/expected-after-patch.ts`, `tests/framework-fixtures/sveltekit-csp/expected-after-patch.js`. Idempotency: if `__impeccableLiveDev` already exists in the file, the patch is applied; just mark `cspChecked: true`.
|
||||
Per-framework: Next.js + monorepo helper: edit the *app's* `next.config.*` (not the shared helper), appending to `additionalScriptSrc` / `additionalConnectSrc`. SvelteKit: `svelte.config.js`, `kit.csp.directives['script-src']` and `['connect-src']`. Nuxt + nuxt-security: `nuxt.config.*`, `security.headers.contentSecurityPolicy['script-src']` and `['connect-src']`. Reference outputs: [nextjs-turborepo/expected-after-patch.ts](https://github.com/pbakaus/impeccable/blob/8dac6ae7e020c43ab10ce9b41939f6fd42627b96/tests/framework-fixtures/nextjs-turborepo/expected-after-patch.ts), [sveltekit-csp/expected-after-patch.js](https://github.com/pbakaus/impeccable/blob/8dac6ae7e020c43ab10ce9b41939f6fd42627b96/tests/framework-fixtures/sveltekit-csp/expected-after-patch.js). Idempotency: if `__impeccableLiveDev` already exists in the file, the patch is applied; just mark `cspChecked: true`.
|
||||
|
||||
### append-string
|
||||
|
||||
@@ -93,7 +93,7 @@ const __impeccableLiveDev =
|
||||
- `script-src 'self' 'unsafe-inline'` becomes `` `script-src 'self' 'unsafe-inline'${__impeccableLiveDev}` ``
|
||||
- `connect-src 'self'` becomes `` `connect-src 'self'${__impeccableLiveDev}` ``
|
||||
|
||||
Per-framework: Next.js inline `headers()` in `next.config.*`; Nuxt `routeRules['/**'].headers['Content-Security-Policy']` in `nuxt.config.*`. Reference outputs: `tests/framework-fixtures/nextjs-inline-csp/expected-after-patch.js`, `tests/framework-fixtures/nuxt-csp/expected-after-patch.ts`.
|
||||
Per-framework: Next.js inline `headers()` in `next.config.*`; Nuxt `routeRules['/**'].headers['Content-Security-Policy']` in `nuxt.config.*`. Reference outputs: [nextjs-inline-csp/expected-after-patch.js](https://github.com/pbakaus/impeccable/blob/8dac6ae7e020c43ab10ce9b41939f6fd42627b96/tests/framework-fixtures/nextjs-inline-csp/expected-after-patch.js), [nuxt-csp/expected-after-patch.ts](https://github.com/pbakaus/impeccable/blob/8dac6ae7e020c43ab10ce9b41939f6fd42627b96/tests/framework-fixtures/nuxt-csp/expected-after-patch.ts).
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
|
||||
@@ -196,7 +196,7 @@ Complete HTML replacement of the original element per variant, not a CSS-only pa
|
||||
|
||||
Replace the style opening tag with `cssAuthoring.styleTag` when the tool returns a different one. **Each variant div contains exactly one top-level element**, same tag as the original; loose siblings break outline tracking and accept. First variant visible, all others `display: none`. The browser's MutationObserver accepts atomic or progressive arrival; accepting an arrived variant fences the worker, so later publications are rejected.
|
||||
|
||||
For `styleMode: "scoped"`, author every `:scope` rule with a descendant combinator: the `@scope` boundary is the variant wrapper div, not your element, so a bare `:scope { ... }` styles a `display: contents` shell. Always step in (`:scope > .card`, `:scope .hero-title`). The fake test agent's CSS in `tests/live-e2e/agent.mjs` is a faithful template.
|
||||
For `styleMode: "scoped"`, author every `:scope` rule with a descendant combinator: the `@scope` boundary is the variant wrapper div, not your element, so a bare `:scope { ... }` styles a `display: contents` shell. Always step in (`:scope > .card`, `:scope .hero-title`). The fake test agent's CSS in the [repo agent template](https://github.com/pbakaus/impeccable/blob/8dac6ae7e020c43ab10ce9b41939f6fd42627b96/tests/live-e2e/agent.mjs) is a faithful template.
|
||||
|
||||
**JSX / TSX targets:** wrap `<style>` content in a template literal (CSS braces would parse as JSX), use `className=` / `style={{…}}`, keep `data-impeccable-*` attributes as plain strings:
|
||||
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
# No-argument routing: the context-aware menu
|
||||
# Command guidance
|
||||
|
||||
## Workflow questions
|
||||
|
||||
Give advice without executing commands; the menu below is only for bare invocations. Consult relevant command references as needed for prerequisites and scope. Link to the [docs](https://impeccable.style/docs/) for the broader workflow guide. If the user also requests execution, follow that request.
|
||||
|
||||
## No-argument routing: the context-aware menu
|
||||
|
||||
Read this when the user invokes `/impeccable` with no argument. They are asking "what should I do?" Make the menu context-aware instead of static.
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
0.1.0
|
||||
0.1.2
|
||||
|
||||
@@ -96,6 +96,19 @@ fetch_url() {
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
check_download() {
|
||||
download_file=${1:-$tmp}
|
||||
if [ ! -f "$download_file" ]; then
|
||||
rm -f "$tmp.sha256"
|
||||
echo "impeccable: download completed but the file was removed before execution: $url; check your antivirus quarantine or logs. Refusing to continue; do not disable protection." >&2
|
||||
exit 127
|
||||
fi
|
||||
if [ ! -s "$download_file" ]; then
|
||||
rm -f "$download_file" "$tmp.sha256"
|
||||
echo "impeccable: downloaded file is empty: $url; refusing the unverified download" >&2
|
||||
exit 127
|
||||
fi
|
||||
}
|
||||
if [ -n "$probing" ]; then
|
||||
# Inside another launcher's probe: no download, fail fast and quiet.
|
||||
exit 127
|
||||
@@ -116,6 +129,7 @@ if [ -n "$version" ] && [ "$os" != unknown ] && [ "$arch" != unknown ]; then
|
||||
fetch_url "$url" && fetched=1
|
||||
fi
|
||||
if [ "$fetched" = 1 ]; then
|
||||
check_download
|
||||
# Fail closed: a freshly downloaded binary runs only after verifying
|
||||
# against its .sha256 sidecar. A sidecar that cannot be fetched, or a
|
||||
# machine with no sha256 tool, refuses the download instead of exec'ing
|
||||
@@ -127,15 +141,20 @@ if [ -n "$version" ] && [ "$os" != unknown ] && [ "$arch" != unknown ]; then
|
||||
elif command -v wget >/dev/null 2>&1; then
|
||||
wget -q -O "$tmp.sha256" "$url.sha256" 2>/dev/null && sidecar_ok=1
|
||||
fi
|
||||
check_download
|
||||
expected=""
|
||||
[ "$sidecar_ok" = 1 ] && expected=$(cut -d' ' -f1 < "$tmp.sha256")
|
||||
actual=""
|
||||
if command -v shasum >/dev/null 2>&1; then actual=$(shasum -a 256 "$tmp" | cut -d' ' -f1)
|
||||
elif command -v sha256sum >/dev/null 2>&1; then actual=$(sha256sum "$tmp" | cut -d' ' -f1); fi
|
||||
if command -v shasum >/dev/null 2>&1; then
|
||||
if digest=$(shasum -a 256 "$tmp" 2>/dev/null); then actual=${digest%% *}; fi
|
||||
elif command -v sha256sum >/dev/null 2>&1; then
|
||||
if digest=$(sha256sum "$tmp" 2>/dev/null); then actual=${digest%% *}; fi
|
||||
fi
|
||||
check_download
|
||||
rm -f "$tmp.sha256"
|
||||
if [ -z "$expected" ] || [ -z "$actual" ]; then
|
||||
rm -f "$tmp"
|
||||
echo "impeccable: cannot verify $url against $url.sha256 (sidecar unavailable or no sha256 tool); refusing the unverified download" >&2
|
||||
echo "impeccable: cannot verify $url against $url.sha256 (sidecar unavailable or hashing failed); refusing the unverified download" >&2
|
||||
exit 127
|
||||
fi
|
||||
if [ "$actual" != "$expected" ]; then
|
||||
@@ -143,8 +162,22 @@ if [ -n "$version" ] && [ "$os" != unknown ] && [ "$arch" != unknown ]; then
|
||||
echo "impeccable: checksum mismatch downloading $url" >&2
|
||||
exit 127
|
||||
fi
|
||||
chmod +x "$tmp" 2>/dev/null
|
||||
mv -f "$tmp" "$cached" && exec "$cached" "$@"
|
||||
check_download
|
||||
if ! chmod +x "$tmp" 2>/dev/null; then
|
||||
check_download
|
||||
rm -f "$tmp"
|
||||
echo "impeccable: could not make the verified download executable: $url" >&2
|
||||
exit 127
|
||||
fi
|
||||
check_download
|
||||
if ! mv -f "$tmp" "$cached" 2>/dev/null; then
|
||||
check_download
|
||||
rm -f "$tmp"
|
||||
echo "impeccable: could not cache the verified download: $url" >&2
|
||||
exit 127
|
||||
fi
|
||||
check_download "$cached"
|
||||
exec "$cached" "$@"
|
||||
fi
|
||||
rm -f "$tmp" 2>/dev/null
|
||||
fi
|
||||
|
||||
@@ -82,6 +82,8 @@ curl.exe -fsSL -o "%cached%.part" "%url%" >nul 2>nul
|
||||
if errorlevel 1 goto fail
|
||||
|
||||
:verify
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
rem Mirrors the sh launcher and fails closed: a freshly downloaded binary
|
||||
rem runs only after verifying against its .sha256 sidecar. A sidecar that
|
||||
rem cannot be fetched, or an empty certutil result, refuses the download
|
||||
@@ -91,8 +93,16 @@ if errorlevel 1 goto verify_refuse
|
||||
set "expected="
|
||||
set /p expected=<"%cached%.sha256"
|
||||
for /f "tokens=1" %%h in ("%expected%") do set "expected=%%h"
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
set "actual="
|
||||
for /f "skip=1 delims=" %%h in ('certutil -hashfile "%cached%.part" SHA256 2^>nul') do if not defined actual set "actual=%%h"
|
||||
rem Reuse the sidecar staging file after reading expected. Check certutil's
|
||||
rem status before parsing: its error text on stdout is not a digest.
|
||||
certutil -hashfile "%cached%.part" SHA256 >"%cached%.sha256" 2>nul
|
||||
if errorlevel 1 goto verify_refuse
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
for /f "usebackq skip=1 delims=" %%h in ("%cached%.sha256") do if not defined actual set "actual=%%h"
|
||||
del "%cached%.sha256" >nul 2>nul
|
||||
if not defined expected goto verify_refuse
|
||||
if not defined actual goto verify_refuse
|
||||
@@ -103,17 +113,48 @@ echo impeccable: checksum mismatch downloading %url% 1>&2
|
||||
exit /b 127
|
||||
|
||||
:verify_refuse
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
del "%cached%.part" >nul 2>nul
|
||||
del "%cached%.sha256" >nul 2>nul
|
||||
echo impeccable: cannot verify %url% against %url%.sha256; refusing the unverified download 1>&2
|
||||
exit /b 127
|
||||
|
||||
:check_download
|
||||
set "download_file=%~1"
|
||||
if not defined download_file set "download_file=%cached%.part"
|
||||
if not exist "%download_file%" goto download_missing
|
||||
for %%f in ("%download_file%") do if %%~zf==0 goto download_empty
|
||||
exit /b 0
|
||||
|
||||
:download_missing
|
||||
del "%cached%.sha256" >nul 2>nul
|
||||
echo impeccable: download completed but the file was removed before execution: %url%; check your antivirus quarantine or logs. Refusing to continue; do not disable protection. 1>&2
|
||||
exit /b 127
|
||||
|
||||
:download_empty
|
||||
del "%download_file%" >nul 2>nul
|
||||
del "%cached%.sha256" >nul 2>nul
|
||||
echo impeccable: downloaded file is empty: %url%; refusing the unverified download 1>&2
|
||||
exit /b 127
|
||||
|
||||
:place
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
move /y "%cached%.part" "%cached%" >nul 2>nul
|
||||
if not exist "%cached%" goto fail
|
||||
if errorlevel 1 goto place_failed
|
||||
call :check_download "%cached%"
|
||||
if errorlevel 1 exit /b 127
|
||||
set "run=%cached%"
|
||||
goto run
|
||||
|
||||
:place_failed
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
del "%cached%.part" >nul 2>nul
|
||||
echo impeccable: could not cache the verified download: %url% 1>&2
|
||||
exit /b 127
|
||||
|
||||
:run
|
||||
"%run%" %*
|
||||
exit /b
|
||||
|
||||
@@ -7834,7 +7834,6 @@
|
||||
if (editBadgeEl && editBadgeEl.style.display !== 'none') renderEditBadge('idle-disabled');
|
||||
showBar('generating');
|
||||
saveSession();
|
||||
sendCheckpoint('generate_started');
|
||||
writeScrollY(window.scrollY);
|
||||
if (variantObserver) variantObserver.disconnect();
|
||||
variantObserver = startVariantObserver(currentSessionId);
|
||||
@@ -7916,7 +7915,6 @@
|
||||
showBar('generating');
|
||||
startScrollTracking();
|
||||
saveSession();
|
||||
sendCheckpoint('generate_started');
|
||||
writeScrollY(window.scrollY);
|
||||
if (variantObserver) variantObserver.disconnect();
|
||||
variantObserver = startVariantObserver(currentSessionId);
|
||||
@@ -8238,7 +8236,8 @@
|
||||
// rasterization from delaying the fetch itself.
|
||||
if (!hasAnnotations) {
|
||||
basePayload.clientSentAt = Date.now();
|
||||
await sendEvent(basePayload);
|
||||
const created = await sendEvent(basePayload);
|
||||
if (created?.ok && currentSessionId === basePayload.id) sendCheckpoint('generate_started');
|
||||
}
|
||||
|
||||
let screenshotPath;
|
||||
@@ -8279,7 +8278,10 @@
|
||||
// is semantic input. Plain requests were already dispatched above.
|
||||
if (hasAnnotations) {
|
||||
basePayload.clientSentAt = Date.now();
|
||||
sendEvent(screenshotPath ? { ...basePayload, screenshotPath } : basePayload);
|
||||
const created = await sendEvent(screenshotPath ? { ...basePayload, screenshotPath } : basePayload);
|
||||
// Capture/upload can take seconds. Progress before this acknowledgment
|
||||
// refers to an unknown session and would clear our own active work.
|
||||
if (created?.ok && currentSessionId === basePayload.id) sendCheckpoint('generate_started');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
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.
|
||||
version: 4.2.0
|
||||
version: 4.2.1
|
||||
license: Apache 2.0
|
||||
---
|
||||
|
||||
@@ -66,7 +66,8 @@ Choose the mode from the requested surface, not the product, and persist it only
|
||||
Routing:
|
||||
|
||||
- **No argument:** read [routing.md](reference/routing.md) and present its context-aware menu; never auto-run a command.
|
||||
- **Explicit or clearly implied command:** load its reference (native variant on native platforms) and follow it. Ask once if two commands fit.
|
||||
- **Explicit or clearly implied request to run a command:** load its reference (native variant on native platforms) and follow it. Ask once if two commands fit.
|
||||
- **Workflow or command-selection question:** read [Workflow questions](reference/routing.md#workflow-questions).
|
||||
- **Otherwise:** treat the request as general design work. Missing PRODUCT.md routes a new surface or replacement world through init, then new-work; a narrow refinement of existing code proceeds on the incumbent implementation as `impeccable context` directs, offering init afterward rather than blocking on it.
|
||||
- `teach` aliases `init`. `craft` is a deprecated alias for ordinary new-work and adds nothing. `shape` owns task discovery, then enters new-work only for visual-world and surface-concept decisions.
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ const __impeccableLiveDev =
|
||||
process.env.NODE_ENV === "development" ? ["http://localhost:8400"] : [];
|
||||
```
|
||||
|
||||
Per-framework: Next.js + monorepo helper: edit the *app's* `next.config.*` (not the shared helper), appending to `additionalScriptSrc` / `additionalConnectSrc`. SvelteKit: `svelte.config.js`, `kit.csp.directives['script-src']` and `['connect-src']`. Nuxt + nuxt-security: `nuxt.config.*`, `security.headers.contentSecurityPolicy['script-src']` and `['connect-src']`. Reference outputs: `tests/framework-fixtures/nextjs-turborepo/expected-after-patch.ts`, `tests/framework-fixtures/sveltekit-csp/expected-after-patch.js`. Idempotency: if `__impeccableLiveDev` already exists in the file, the patch is applied; just mark `cspChecked: true`.
|
||||
Per-framework: Next.js + monorepo helper: edit the *app's* `next.config.*` (not the shared helper), appending to `additionalScriptSrc` / `additionalConnectSrc`. SvelteKit: `svelte.config.js`, `kit.csp.directives['script-src']` and `['connect-src']`. Nuxt + nuxt-security: `nuxt.config.*`, `security.headers.contentSecurityPolicy['script-src']` and `['connect-src']`. Reference outputs: [nextjs-turborepo/expected-after-patch.ts](https://github.com/pbakaus/impeccable/blob/8dac6ae7e020c43ab10ce9b41939f6fd42627b96/tests/framework-fixtures/nextjs-turborepo/expected-after-patch.ts), [sveltekit-csp/expected-after-patch.js](https://github.com/pbakaus/impeccable/blob/8dac6ae7e020c43ab10ce9b41939f6fd42627b96/tests/framework-fixtures/sveltekit-csp/expected-after-patch.js). Idempotency: if `__impeccableLiveDev` already exists in the file, the patch is applied; just mark `cspChecked: true`.
|
||||
|
||||
### append-string
|
||||
|
||||
@@ -93,7 +93,7 @@ const __impeccableLiveDev =
|
||||
- `script-src 'self' 'unsafe-inline'` becomes `` `script-src 'self' 'unsafe-inline'${__impeccableLiveDev}` ``
|
||||
- `connect-src 'self'` becomes `` `connect-src 'self'${__impeccableLiveDev}` ``
|
||||
|
||||
Per-framework: Next.js inline `headers()` in `next.config.*`; Nuxt `routeRules['/**'].headers['Content-Security-Policy']` in `nuxt.config.*`. Reference outputs: `tests/framework-fixtures/nextjs-inline-csp/expected-after-patch.js`, `tests/framework-fixtures/nuxt-csp/expected-after-patch.ts`.
|
||||
Per-framework: Next.js inline `headers()` in `next.config.*`; Nuxt `routeRules['/**'].headers['Content-Security-Policy']` in `nuxt.config.*`. Reference outputs: [nextjs-inline-csp/expected-after-patch.js](https://github.com/pbakaus/impeccable/blob/8dac6ae7e020c43ab10ce9b41939f6fd42627b96/tests/framework-fixtures/nextjs-inline-csp/expected-after-patch.js), [nuxt-csp/expected-after-patch.ts](https://github.com/pbakaus/impeccable/blob/8dac6ae7e020c43ab10ce9b41939f6fd42627b96/tests/framework-fixtures/nuxt-csp/expected-after-patch.ts).
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
|
||||
@@ -196,7 +196,7 @@ Complete HTML replacement of the original element per variant, not a CSS-only pa
|
||||
|
||||
Replace the style opening tag with `cssAuthoring.styleTag` when the tool returns a different one. **Each variant div contains exactly one top-level element**, same tag as the original; loose siblings break outline tracking and accept. First variant visible, all others `display: none`. The browser's MutationObserver accepts atomic or progressive arrival; accepting an arrived variant fences the worker, so later publications are rejected.
|
||||
|
||||
For `styleMode: "scoped"`, author every `:scope` rule with a descendant combinator: the `@scope` boundary is the variant wrapper div, not your element, so a bare `:scope { ... }` styles a `display: contents` shell. Always step in (`:scope > .card`, `:scope .hero-title`). The fake test agent's CSS in `tests/live-e2e/agent.mjs` is a faithful template.
|
||||
For `styleMode: "scoped"`, author every `:scope` rule with a descendant combinator: the `@scope` boundary is the variant wrapper div, not your element, so a bare `:scope { ... }` styles a `display: contents` shell. Always step in (`:scope > .card`, `:scope .hero-title`). The fake test agent's CSS in the [repo agent template](https://github.com/pbakaus/impeccable/blob/8dac6ae7e020c43ab10ce9b41939f6fd42627b96/tests/live-e2e/agent.mjs) is a faithful template.
|
||||
|
||||
**JSX / TSX targets:** wrap `<style>` content in a template literal (CSS braces would parse as JSX), use `className=` / `style={{…}}`, keep `data-impeccable-*` attributes as plain strings:
|
||||
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
# No-argument routing: the context-aware menu
|
||||
# Command guidance
|
||||
|
||||
## Workflow questions
|
||||
|
||||
Give advice without executing commands; the menu below is only for bare invocations. Consult relevant command references as needed for prerequisites and scope. Link to the [docs](https://impeccable.style/docs/) for the broader workflow guide. If the user also requests execution, follow that request.
|
||||
|
||||
## No-argument routing: the context-aware menu
|
||||
|
||||
Read this when the user invokes `/impeccable` with no argument. They are asking "what should I do?" Make the menu context-aware instead of static.
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
0.1.0
|
||||
0.1.2
|
||||
|
||||
@@ -96,6 +96,19 @@ fetch_url() {
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
check_download() {
|
||||
download_file=${1:-$tmp}
|
||||
if [ ! -f "$download_file" ]; then
|
||||
rm -f "$tmp.sha256"
|
||||
echo "impeccable: download completed but the file was removed before execution: $url; check your antivirus quarantine or logs. Refusing to continue; do not disable protection." >&2
|
||||
exit 127
|
||||
fi
|
||||
if [ ! -s "$download_file" ]; then
|
||||
rm -f "$download_file" "$tmp.sha256"
|
||||
echo "impeccable: downloaded file is empty: $url; refusing the unverified download" >&2
|
||||
exit 127
|
||||
fi
|
||||
}
|
||||
if [ -n "$probing" ]; then
|
||||
# Inside another launcher's probe: no download, fail fast and quiet.
|
||||
exit 127
|
||||
@@ -116,6 +129,7 @@ if [ -n "$version" ] && [ "$os" != unknown ] && [ "$arch" != unknown ]; then
|
||||
fetch_url "$url" && fetched=1
|
||||
fi
|
||||
if [ "$fetched" = 1 ]; then
|
||||
check_download
|
||||
# Fail closed: a freshly downloaded binary runs only after verifying
|
||||
# against its .sha256 sidecar. A sidecar that cannot be fetched, or a
|
||||
# machine with no sha256 tool, refuses the download instead of exec'ing
|
||||
@@ -127,15 +141,20 @@ if [ -n "$version" ] && [ "$os" != unknown ] && [ "$arch" != unknown ]; then
|
||||
elif command -v wget >/dev/null 2>&1; then
|
||||
wget -q -O "$tmp.sha256" "$url.sha256" 2>/dev/null && sidecar_ok=1
|
||||
fi
|
||||
check_download
|
||||
expected=""
|
||||
[ "$sidecar_ok" = 1 ] && expected=$(cut -d' ' -f1 < "$tmp.sha256")
|
||||
actual=""
|
||||
if command -v shasum >/dev/null 2>&1; then actual=$(shasum -a 256 "$tmp" | cut -d' ' -f1)
|
||||
elif command -v sha256sum >/dev/null 2>&1; then actual=$(sha256sum "$tmp" | cut -d' ' -f1); fi
|
||||
if command -v shasum >/dev/null 2>&1; then
|
||||
if digest=$(shasum -a 256 "$tmp" 2>/dev/null); then actual=${digest%% *}; fi
|
||||
elif command -v sha256sum >/dev/null 2>&1; then
|
||||
if digest=$(sha256sum "$tmp" 2>/dev/null); then actual=${digest%% *}; fi
|
||||
fi
|
||||
check_download
|
||||
rm -f "$tmp.sha256"
|
||||
if [ -z "$expected" ] || [ -z "$actual" ]; then
|
||||
rm -f "$tmp"
|
||||
echo "impeccable: cannot verify $url against $url.sha256 (sidecar unavailable or no sha256 tool); refusing the unverified download" >&2
|
||||
echo "impeccable: cannot verify $url against $url.sha256 (sidecar unavailable or hashing failed); refusing the unverified download" >&2
|
||||
exit 127
|
||||
fi
|
||||
if [ "$actual" != "$expected" ]; then
|
||||
@@ -143,8 +162,22 @@ if [ -n "$version" ] && [ "$os" != unknown ] && [ "$arch" != unknown ]; then
|
||||
echo "impeccable: checksum mismatch downloading $url" >&2
|
||||
exit 127
|
||||
fi
|
||||
chmod +x "$tmp" 2>/dev/null
|
||||
mv -f "$tmp" "$cached" && exec "$cached" "$@"
|
||||
check_download
|
||||
if ! chmod +x "$tmp" 2>/dev/null; then
|
||||
check_download
|
||||
rm -f "$tmp"
|
||||
echo "impeccable: could not make the verified download executable: $url" >&2
|
||||
exit 127
|
||||
fi
|
||||
check_download
|
||||
if ! mv -f "$tmp" "$cached" 2>/dev/null; then
|
||||
check_download
|
||||
rm -f "$tmp"
|
||||
echo "impeccable: could not cache the verified download: $url" >&2
|
||||
exit 127
|
||||
fi
|
||||
check_download "$cached"
|
||||
exec "$cached" "$@"
|
||||
fi
|
||||
rm -f "$tmp" 2>/dev/null
|
||||
fi
|
||||
|
||||
@@ -82,6 +82,8 @@ curl.exe -fsSL -o "%cached%.part" "%url%" >nul 2>nul
|
||||
if errorlevel 1 goto fail
|
||||
|
||||
:verify
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
rem Mirrors the sh launcher and fails closed: a freshly downloaded binary
|
||||
rem runs only after verifying against its .sha256 sidecar. A sidecar that
|
||||
rem cannot be fetched, or an empty certutil result, refuses the download
|
||||
@@ -91,8 +93,16 @@ if errorlevel 1 goto verify_refuse
|
||||
set "expected="
|
||||
set /p expected=<"%cached%.sha256"
|
||||
for /f "tokens=1" %%h in ("%expected%") do set "expected=%%h"
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
set "actual="
|
||||
for /f "skip=1 delims=" %%h in ('certutil -hashfile "%cached%.part" SHA256 2^>nul') do if not defined actual set "actual=%%h"
|
||||
rem Reuse the sidecar staging file after reading expected. Check certutil's
|
||||
rem status before parsing: its error text on stdout is not a digest.
|
||||
certutil -hashfile "%cached%.part" SHA256 >"%cached%.sha256" 2>nul
|
||||
if errorlevel 1 goto verify_refuse
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
for /f "usebackq skip=1 delims=" %%h in ("%cached%.sha256") do if not defined actual set "actual=%%h"
|
||||
del "%cached%.sha256" >nul 2>nul
|
||||
if not defined expected goto verify_refuse
|
||||
if not defined actual goto verify_refuse
|
||||
@@ -103,17 +113,48 @@ echo impeccable: checksum mismatch downloading %url% 1>&2
|
||||
exit /b 127
|
||||
|
||||
:verify_refuse
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
del "%cached%.part" >nul 2>nul
|
||||
del "%cached%.sha256" >nul 2>nul
|
||||
echo impeccable: cannot verify %url% against %url%.sha256; refusing the unverified download 1>&2
|
||||
exit /b 127
|
||||
|
||||
:check_download
|
||||
set "download_file=%~1"
|
||||
if not defined download_file set "download_file=%cached%.part"
|
||||
if not exist "%download_file%" goto download_missing
|
||||
for %%f in ("%download_file%") do if %%~zf==0 goto download_empty
|
||||
exit /b 0
|
||||
|
||||
:download_missing
|
||||
del "%cached%.sha256" >nul 2>nul
|
||||
echo impeccable: download completed but the file was removed before execution: %url%; check your antivirus quarantine or logs. Refusing to continue; do not disable protection. 1>&2
|
||||
exit /b 127
|
||||
|
||||
:download_empty
|
||||
del "%download_file%" >nul 2>nul
|
||||
del "%cached%.sha256" >nul 2>nul
|
||||
echo impeccable: downloaded file is empty: %url%; refusing the unverified download 1>&2
|
||||
exit /b 127
|
||||
|
||||
:place
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
move /y "%cached%.part" "%cached%" >nul 2>nul
|
||||
if not exist "%cached%" goto fail
|
||||
if errorlevel 1 goto place_failed
|
||||
call :check_download "%cached%"
|
||||
if errorlevel 1 exit /b 127
|
||||
set "run=%cached%"
|
||||
goto run
|
||||
|
||||
:place_failed
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
del "%cached%.part" >nul 2>nul
|
||||
echo impeccable: could not cache the verified download: %url% 1>&2
|
||||
exit /b 127
|
||||
|
||||
:run
|
||||
"%run%" %*
|
||||
exit /b
|
||||
|
||||
@@ -7834,7 +7834,6 @@
|
||||
if (editBadgeEl && editBadgeEl.style.display !== 'none') renderEditBadge('idle-disabled');
|
||||
showBar('generating');
|
||||
saveSession();
|
||||
sendCheckpoint('generate_started');
|
||||
writeScrollY(window.scrollY);
|
||||
if (variantObserver) variantObserver.disconnect();
|
||||
variantObserver = startVariantObserver(currentSessionId);
|
||||
@@ -7916,7 +7915,6 @@
|
||||
showBar('generating');
|
||||
startScrollTracking();
|
||||
saveSession();
|
||||
sendCheckpoint('generate_started');
|
||||
writeScrollY(window.scrollY);
|
||||
if (variantObserver) variantObserver.disconnect();
|
||||
variantObserver = startVariantObserver(currentSessionId);
|
||||
@@ -8238,7 +8236,8 @@
|
||||
// rasterization from delaying the fetch itself.
|
||||
if (!hasAnnotations) {
|
||||
basePayload.clientSentAt = Date.now();
|
||||
await sendEvent(basePayload);
|
||||
const created = await sendEvent(basePayload);
|
||||
if (created?.ok && currentSessionId === basePayload.id) sendCheckpoint('generate_started');
|
||||
}
|
||||
|
||||
let screenshotPath;
|
||||
@@ -8279,7 +8278,10 @@
|
||||
// is semantic input. Plain requests were already dispatched above.
|
||||
if (hasAnnotations) {
|
||||
basePayload.clientSentAt = Date.now();
|
||||
sendEvent(screenshotPath ? { ...basePayload, screenshotPath } : basePayload);
|
||||
const created = await sendEvent(screenshotPath ? { ...basePayload, screenshotPath } : basePayload);
|
||||
// Capture/upload can take seconds. Progress before this acknowledgment
|
||||
// refers to an unknown session and would clear our own active work.
|
||||
if (created?.ok && currentSessionId === basePayload.id) sendCheckpoint('generate_started');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
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.
|
||||
version: 4.2.0
|
||||
version: 4.2.1
|
||||
license: Apache 2.0
|
||||
---
|
||||
|
||||
@@ -66,7 +66,8 @@ Choose the mode from the requested surface, not the product, and persist it only
|
||||
Routing:
|
||||
|
||||
- **No argument:** read [routing.md](reference/routing.md) and present its context-aware menu; never auto-run a command.
|
||||
- **Explicit or clearly implied command:** load its reference (native variant on native platforms) and follow it. Ask once if two commands fit.
|
||||
- **Explicit or clearly implied request to run a command:** load its reference (native variant on native platforms) and follow it. Ask once if two commands fit.
|
||||
- **Workflow or command-selection question:** read [Workflow questions](reference/routing.md#workflow-questions).
|
||||
- **Otherwise:** treat the request as general design work. Missing PRODUCT.md routes a new surface or replacement world through init, then new-work; a narrow refinement of existing code proceeds on the incumbent implementation as `impeccable context` directs, offering init afterward rather than blocking on it.
|
||||
- `teach` aliases `init`. `craft` is a deprecated alias for ordinary new-work and adds nothing. `shape` owns task discovery, then enters new-work only for visual-world and surface-concept decisions.
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ const __impeccableLiveDev =
|
||||
process.env.NODE_ENV === "development" ? ["http://localhost:8400"] : [];
|
||||
```
|
||||
|
||||
Per-framework: Next.js + monorepo helper: edit the *app's* `next.config.*` (not the shared helper), appending to `additionalScriptSrc` / `additionalConnectSrc`. SvelteKit: `svelte.config.js`, `kit.csp.directives['script-src']` and `['connect-src']`. Nuxt + nuxt-security: `nuxt.config.*`, `security.headers.contentSecurityPolicy['script-src']` and `['connect-src']`. Reference outputs: `tests/framework-fixtures/nextjs-turborepo/expected-after-patch.ts`, `tests/framework-fixtures/sveltekit-csp/expected-after-patch.js`. Idempotency: if `__impeccableLiveDev` already exists in the file, the patch is applied; just mark `cspChecked: true`.
|
||||
Per-framework: Next.js + monorepo helper: edit the *app's* `next.config.*` (not the shared helper), appending to `additionalScriptSrc` / `additionalConnectSrc`. SvelteKit: `svelte.config.js`, `kit.csp.directives['script-src']` and `['connect-src']`. Nuxt + nuxt-security: `nuxt.config.*`, `security.headers.contentSecurityPolicy['script-src']` and `['connect-src']`. Reference outputs: [nextjs-turborepo/expected-after-patch.ts](https://github.com/pbakaus/impeccable/blob/8dac6ae7e020c43ab10ce9b41939f6fd42627b96/tests/framework-fixtures/nextjs-turborepo/expected-after-patch.ts), [sveltekit-csp/expected-after-patch.js](https://github.com/pbakaus/impeccable/blob/8dac6ae7e020c43ab10ce9b41939f6fd42627b96/tests/framework-fixtures/sveltekit-csp/expected-after-patch.js). Idempotency: if `__impeccableLiveDev` already exists in the file, the patch is applied; just mark `cspChecked: true`.
|
||||
|
||||
### append-string
|
||||
|
||||
@@ -93,7 +93,7 @@ const __impeccableLiveDev =
|
||||
- `script-src 'self' 'unsafe-inline'` becomes `` `script-src 'self' 'unsafe-inline'${__impeccableLiveDev}` ``
|
||||
- `connect-src 'self'` becomes `` `connect-src 'self'${__impeccableLiveDev}` ``
|
||||
|
||||
Per-framework: Next.js inline `headers()` in `next.config.*`; Nuxt `routeRules['/**'].headers['Content-Security-Policy']` in `nuxt.config.*`. Reference outputs: `tests/framework-fixtures/nextjs-inline-csp/expected-after-patch.js`, `tests/framework-fixtures/nuxt-csp/expected-after-patch.ts`.
|
||||
Per-framework: Next.js inline `headers()` in `next.config.*`; Nuxt `routeRules['/**'].headers['Content-Security-Policy']` in `nuxt.config.*`. Reference outputs: [nextjs-inline-csp/expected-after-patch.js](https://github.com/pbakaus/impeccable/blob/8dac6ae7e020c43ab10ce9b41939f6fd42627b96/tests/framework-fixtures/nextjs-inline-csp/expected-after-patch.js), [nuxt-csp/expected-after-patch.ts](https://github.com/pbakaus/impeccable/blob/8dac6ae7e020c43ab10ce9b41939f6fd42627b96/tests/framework-fixtures/nuxt-csp/expected-after-patch.ts).
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
|
||||
@@ -196,7 +196,7 @@ Complete HTML replacement of the original element per variant, not a CSS-only pa
|
||||
|
||||
Replace the style opening tag with `cssAuthoring.styleTag` when the tool returns a different one. **Each variant div contains exactly one top-level element**, same tag as the original; loose siblings break outline tracking and accept. First variant visible, all others `display: none`. The browser's MutationObserver accepts atomic or progressive arrival; accepting an arrived variant fences the worker, so later publications are rejected.
|
||||
|
||||
For `styleMode: "scoped"`, author every `:scope` rule with a descendant combinator: the `@scope` boundary is the variant wrapper div, not your element, so a bare `:scope { ... }` styles a `display: contents` shell. Always step in (`:scope > .card`, `:scope .hero-title`). The fake test agent's CSS in `tests/live-e2e/agent.mjs` is a faithful template.
|
||||
For `styleMode: "scoped"`, author every `:scope` rule with a descendant combinator: the `@scope` boundary is the variant wrapper div, not your element, so a bare `:scope { ... }` styles a `display: contents` shell. Always step in (`:scope > .card`, `:scope .hero-title`). The fake test agent's CSS in the [repo agent template](https://github.com/pbakaus/impeccable/blob/8dac6ae7e020c43ab10ce9b41939f6fd42627b96/tests/live-e2e/agent.mjs) is a faithful template.
|
||||
|
||||
**JSX / TSX targets:** wrap `<style>` content in a template literal (CSS braces would parse as JSX), use `className=` / `style={{…}}`, keep `data-impeccable-*` attributes as plain strings:
|
||||
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
# No-argument routing: the context-aware menu
|
||||
# Command guidance
|
||||
|
||||
## Workflow questions
|
||||
|
||||
Give advice without executing commands; the menu below is only for bare invocations. Consult relevant command references as needed for prerequisites and scope. Link to the [docs](https://impeccable.style/docs/) for the broader workflow guide. If the user also requests execution, follow that request.
|
||||
|
||||
## No-argument routing: the context-aware menu
|
||||
|
||||
Read this when the user invokes `/impeccable` with no argument. They are asking "what should I do?" Make the menu context-aware instead of static.
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
0.1.0
|
||||
0.1.2
|
||||
|
||||
@@ -96,6 +96,19 @@ fetch_url() {
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
check_download() {
|
||||
download_file=${1:-$tmp}
|
||||
if [ ! -f "$download_file" ]; then
|
||||
rm -f "$tmp.sha256"
|
||||
echo "impeccable: download completed but the file was removed before execution: $url; check your antivirus quarantine or logs. Refusing to continue; do not disable protection." >&2
|
||||
exit 127
|
||||
fi
|
||||
if [ ! -s "$download_file" ]; then
|
||||
rm -f "$download_file" "$tmp.sha256"
|
||||
echo "impeccable: downloaded file is empty: $url; refusing the unverified download" >&2
|
||||
exit 127
|
||||
fi
|
||||
}
|
||||
if [ -n "$probing" ]; then
|
||||
# Inside another launcher's probe: no download, fail fast and quiet.
|
||||
exit 127
|
||||
@@ -116,6 +129,7 @@ if [ -n "$version" ] && [ "$os" != unknown ] && [ "$arch" != unknown ]; then
|
||||
fetch_url "$url" && fetched=1
|
||||
fi
|
||||
if [ "$fetched" = 1 ]; then
|
||||
check_download
|
||||
# Fail closed: a freshly downloaded binary runs only after verifying
|
||||
# against its .sha256 sidecar. A sidecar that cannot be fetched, or a
|
||||
# machine with no sha256 tool, refuses the download instead of exec'ing
|
||||
@@ -127,15 +141,20 @@ if [ -n "$version" ] && [ "$os" != unknown ] && [ "$arch" != unknown ]; then
|
||||
elif command -v wget >/dev/null 2>&1; then
|
||||
wget -q -O "$tmp.sha256" "$url.sha256" 2>/dev/null && sidecar_ok=1
|
||||
fi
|
||||
check_download
|
||||
expected=""
|
||||
[ "$sidecar_ok" = 1 ] && expected=$(cut -d' ' -f1 < "$tmp.sha256")
|
||||
actual=""
|
||||
if command -v shasum >/dev/null 2>&1; then actual=$(shasum -a 256 "$tmp" | cut -d' ' -f1)
|
||||
elif command -v sha256sum >/dev/null 2>&1; then actual=$(sha256sum "$tmp" | cut -d' ' -f1); fi
|
||||
if command -v shasum >/dev/null 2>&1; then
|
||||
if digest=$(shasum -a 256 "$tmp" 2>/dev/null); then actual=${digest%% *}; fi
|
||||
elif command -v sha256sum >/dev/null 2>&1; then
|
||||
if digest=$(sha256sum "$tmp" 2>/dev/null); then actual=${digest%% *}; fi
|
||||
fi
|
||||
check_download
|
||||
rm -f "$tmp.sha256"
|
||||
if [ -z "$expected" ] || [ -z "$actual" ]; then
|
||||
rm -f "$tmp"
|
||||
echo "impeccable: cannot verify $url against $url.sha256 (sidecar unavailable or no sha256 tool); refusing the unverified download" >&2
|
||||
echo "impeccable: cannot verify $url against $url.sha256 (sidecar unavailable or hashing failed); refusing the unverified download" >&2
|
||||
exit 127
|
||||
fi
|
||||
if [ "$actual" != "$expected" ]; then
|
||||
@@ -143,8 +162,22 @@ if [ -n "$version" ] && [ "$os" != unknown ] && [ "$arch" != unknown ]; then
|
||||
echo "impeccable: checksum mismatch downloading $url" >&2
|
||||
exit 127
|
||||
fi
|
||||
chmod +x "$tmp" 2>/dev/null
|
||||
mv -f "$tmp" "$cached" && exec "$cached" "$@"
|
||||
check_download
|
||||
if ! chmod +x "$tmp" 2>/dev/null; then
|
||||
check_download
|
||||
rm -f "$tmp"
|
||||
echo "impeccable: could not make the verified download executable: $url" >&2
|
||||
exit 127
|
||||
fi
|
||||
check_download
|
||||
if ! mv -f "$tmp" "$cached" 2>/dev/null; then
|
||||
check_download
|
||||
rm -f "$tmp"
|
||||
echo "impeccable: could not cache the verified download: $url" >&2
|
||||
exit 127
|
||||
fi
|
||||
check_download "$cached"
|
||||
exec "$cached" "$@"
|
||||
fi
|
||||
rm -f "$tmp" 2>/dev/null
|
||||
fi
|
||||
|
||||
@@ -82,6 +82,8 @@ curl.exe -fsSL -o "%cached%.part" "%url%" >nul 2>nul
|
||||
if errorlevel 1 goto fail
|
||||
|
||||
:verify
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
rem Mirrors the sh launcher and fails closed: a freshly downloaded binary
|
||||
rem runs only after verifying against its .sha256 sidecar. A sidecar that
|
||||
rem cannot be fetched, or an empty certutil result, refuses the download
|
||||
@@ -91,8 +93,16 @@ if errorlevel 1 goto verify_refuse
|
||||
set "expected="
|
||||
set /p expected=<"%cached%.sha256"
|
||||
for /f "tokens=1" %%h in ("%expected%") do set "expected=%%h"
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
set "actual="
|
||||
for /f "skip=1 delims=" %%h in ('certutil -hashfile "%cached%.part" SHA256 2^>nul') do if not defined actual set "actual=%%h"
|
||||
rem Reuse the sidecar staging file after reading expected. Check certutil's
|
||||
rem status before parsing: its error text on stdout is not a digest.
|
||||
certutil -hashfile "%cached%.part" SHA256 >"%cached%.sha256" 2>nul
|
||||
if errorlevel 1 goto verify_refuse
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
for /f "usebackq skip=1 delims=" %%h in ("%cached%.sha256") do if not defined actual set "actual=%%h"
|
||||
del "%cached%.sha256" >nul 2>nul
|
||||
if not defined expected goto verify_refuse
|
||||
if not defined actual goto verify_refuse
|
||||
@@ -103,17 +113,48 @@ echo impeccable: checksum mismatch downloading %url% 1>&2
|
||||
exit /b 127
|
||||
|
||||
:verify_refuse
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
del "%cached%.part" >nul 2>nul
|
||||
del "%cached%.sha256" >nul 2>nul
|
||||
echo impeccable: cannot verify %url% against %url%.sha256; refusing the unverified download 1>&2
|
||||
exit /b 127
|
||||
|
||||
:check_download
|
||||
set "download_file=%~1"
|
||||
if not defined download_file set "download_file=%cached%.part"
|
||||
if not exist "%download_file%" goto download_missing
|
||||
for %%f in ("%download_file%") do if %%~zf==0 goto download_empty
|
||||
exit /b 0
|
||||
|
||||
:download_missing
|
||||
del "%cached%.sha256" >nul 2>nul
|
||||
echo impeccable: download completed but the file was removed before execution: %url%; check your antivirus quarantine or logs. Refusing to continue; do not disable protection. 1>&2
|
||||
exit /b 127
|
||||
|
||||
:download_empty
|
||||
del "%download_file%" >nul 2>nul
|
||||
del "%cached%.sha256" >nul 2>nul
|
||||
echo impeccable: downloaded file is empty: %url%; refusing the unverified download 1>&2
|
||||
exit /b 127
|
||||
|
||||
:place
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
move /y "%cached%.part" "%cached%" >nul 2>nul
|
||||
if not exist "%cached%" goto fail
|
||||
if errorlevel 1 goto place_failed
|
||||
call :check_download "%cached%"
|
||||
if errorlevel 1 exit /b 127
|
||||
set "run=%cached%"
|
||||
goto run
|
||||
|
||||
:place_failed
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
del "%cached%.part" >nul 2>nul
|
||||
echo impeccable: could not cache the verified download: %url% 1>&2
|
||||
exit /b 127
|
||||
|
||||
:run
|
||||
"%run%" %*
|
||||
exit /b
|
||||
|
||||
@@ -7834,7 +7834,6 @@
|
||||
if (editBadgeEl && editBadgeEl.style.display !== 'none') renderEditBadge('idle-disabled');
|
||||
showBar('generating');
|
||||
saveSession();
|
||||
sendCheckpoint('generate_started');
|
||||
writeScrollY(window.scrollY);
|
||||
if (variantObserver) variantObserver.disconnect();
|
||||
variantObserver = startVariantObserver(currentSessionId);
|
||||
@@ -7916,7 +7915,6 @@
|
||||
showBar('generating');
|
||||
startScrollTracking();
|
||||
saveSession();
|
||||
sendCheckpoint('generate_started');
|
||||
writeScrollY(window.scrollY);
|
||||
if (variantObserver) variantObserver.disconnect();
|
||||
variantObserver = startVariantObserver(currentSessionId);
|
||||
@@ -8238,7 +8236,8 @@
|
||||
// rasterization from delaying the fetch itself.
|
||||
if (!hasAnnotations) {
|
||||
basePayload.clientSentAt = Date.now();
|
||||
await sendEvent(basePayload);
|
||||
const created = await sendEvent(basePayload);
|
||||
if (created?.ok && currentSessionId === basePayload.id) sendCheckpoint('generate_started');
|
||||
}
|
||||
|
||||
let screenshotPath;
|
||||
@@ -8279,7 +8278,10 @@
|
||||
// is semantic input. Plain requests were already dispatched above.
|
||||
if (hasAnnotations) {
|
||||
basePayload.clientSentAt = Date.now();
|
||||
sendEvent(screenshotPath ? { ...basePayload, screenshotPath } : basePayload);
|
||||
const created = await sendEvent(screenshotPath ? { ...basePayload, screenshotPath } : basePayload);
|
||||
// Capture/upload can take seconds. Progress before this acknowledgment
|
||||
// refers to an unknown session and would clear our own active work.
|
||||
if (created?.ok && currentSessionId === basePayload.id) sendCheckpoint('generate_started');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
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.
|
||||
version: 4.2.0
|
||||
version: 4.2.1
|
||||
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]"
|
||||
license: Apache 2.0
|
||||
@@ -71,7 +71,8 @@ Choose the mode from the requested surface, not the product, and persist it only
|
||||
Routing:
|
||||
|
||||
- **No argument:** read [routing.md](reference/routing.md) and present its context-aware menu; never auto-run a command.
|
||||
- **Explicit or clearly implied command:** load its reference (native variant on native platforms) and follow it. Ask once if two commands fit.
|
||||
- **Explicit or clearly implied request to run a command:** load its reference (native variant on native platforms) and follow it. Ask once if two commands fit.
|
||||
- **Workflow or command-selection question:** read [Workflow questions](reference/routing.md#workflow-questions).
|
||||
- **Otherwise:** treat the request as general design work. Missing PRODUCT.md routes a new surface or replacement world through init, then new-work; a narrow refinement of existing code proceeds on the incumbent implementation as `impeccable context` directs, offering init afterward rather than blocking on it.
|
||||
- `teach` aliases `init`. `craft` is a deprecated alias for ordinary new-work and adds nothing. `shape` owns task discovery, then enters new-work only for visual-world and surface-concept decisions.
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ const __impeccableLiveDev =
|
||||
process.env.NODE_ENV === "development" ? ["http://localhost:8400"] : [];
|
||||
```
|
||||
|
||||
Per-framework: Next.js + monorepo helper: edit the *app's* `next.config.*` (not the shared helper), appending to `additionalScriptSrc` / `additionalConnectSrc`. SvelteKit: `svelte.config.js`, `kit.csp.directives['script-src']` and `['connect-src']`. Nuxt + nuxt-security: `nuxt.config.*`, `security.headers.contentSecurityPolicy['script-src']` and `['connect-src']`. Reference outputs: `tests/framework-fixtures/nextjs-turborepo/expected-after-patch.ts`, `tests/framework-fixtures/sveltekit-csp/expected-after-patch.js`. Idempotency: if `__impeccableLiveDev` already exists in the file, the patch is applied; just mark `cspChecked: true`.
|
||||
Per-framework: Next.js + monorepo helper: edit the *app's* `next.config.*` (not the shared helper), appending to `additionalScriptSrc` / `additionalConnectSrc`. SvelteKit: `svelte.config.js`, `kit.csp.directives['script-src']` and `['connect-src']`. Nuxt + nuxt-security: `nuxt.config.*`, `security.headers.contentSecurityPolicy['script-src']` and `['connect-src']`. Reference outputs: [nextjs-turborepo/expected-after-patch.ts](https://github.com/pbakaus/impeccable/blob/8dac6ae7e020c43ab10ce9b41939f6fd42627b96/tests/framework-fixtures/nextjs-turborepo/expected-after-patch.ts), [sveltekit-csp/expected-after-patch.js](https://github.com/pbakaus/impeccable/blob/8dac6ae7e020c43ab10ce9b41939f6fd42627b96/tests/framework-fixtures/sveltekit-csp/expected-after-patch.js). Idempotency: if `__impeccableLiveDev` already exists in the file, the patch is applied; just mark `cspChecked: true`.
|
||||
|
||||
### append-string
|
||||
|
||||
@@ -93,7 +93,7 @@ const __impeccableLiveDev =
|
||||
- `script-src 'self' 'unsafe-inline'` becomes `` `script-src 'self' 'unsafe-inline'${__impeccableLiveDev}` ``
|
||||
- `connect-src 'self'` becomes `` `connect-src 'self'${__impeccableLiveDev}` ``
|
||||
|
||||
Per-framework: Next.js inline `headers()` in `next.config.*`; Nuxt `routeRules['/**'].headers['Content-Security-Policy']` in `nuxt.config.*`. Reference outputs: `tests/framework-fixtures/nextjs-inline-csp/expected-after-patch.js`, `tests/framework-fixtures/nuxt-csp/expected-after-patch.ts`.
|
||||
Per-framework: Next.js inline `headers()` in `next.config.*`; Nuxt `routeRules['/**'].headers['Content-Security-Policy']` in `nuxt.config.*`. Reference outputs: [nextjs-inline-csp/expected-after-patch.js](https://github.com/pbakaus/impeccable/blob/8dac6ae7e020c43ab10ce9b41939f6fd42627b96/tests/framework-fixtures/nextjs-inline-csp/expected-after-patch.js), [nuxt-csp/expected-after-patch.ts](https://github.com/pbakaus/impeccable/blob/8dac6ae7e020c43ab10ce9b41939f6fd42627b96/tests/framework-fixtures/nuxt-csp/expected-after-patch.ts).
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
|
||||
@@ -196,7 +196,7 @@ Complete HTML replacement of the original element per variant, not a CSS-only pa
|
||||
|
||||
Replace the style opening tag with `cssAuthoring.styleTag` when the tool returns a different one. **Each variant div contains exactly one top-level element**, same tag as the original; loose siblings break outline tracking and accept. First variant visible, all others `display: none`. The browser's MutationObserver accepts atomic or progressive arrival; accepting an arrived variant fences the worker, so later publications are rejected.
|
||||
|
||||
For `styleMode: "scoped"`, author every `:scope` rule with a descendant combinator: the `@scope` boundary is the variant wrapper div, not your element, so a bare `:scope { ... }` styles a `display: contents` shell. Always step in (`:scope > .card`, `:scope .hero-title`). The fake test agent's CSS in `tests/live-e2e/agent.mjs` is a faithful template.
|
||||
For `styleMode: "scoped"`, author every `:scope` rule with a descendant combinator: the `@scope` boundary is the variant wrapper div, not your element, so a bare `:scope { ... }` styles a `display: contents` shell. Always step in (`:scope > .card`, `:scope .hero-title`). The fake test agent's CSS in the [repo agent template](https://github.com/pbakaus/impeccable/blob/8dac6ae7e020c43ab10ce9b41939f6fd42627b96/tests/live-e2e/agent.mjs) is a faithful template.
|
||||
|
||||
**JSX / TSX targets:** wrap `<style>` content in a template literal (CSS braces would parse as JSX), use `className=` / `style={{…}}`, keep `data-impeccable-*` attributes as plain strings:
|
||||
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
# No-argument routing: the context-aware menu
|
||||
# Command guidance
|
||||
|
||||
## Workflow questions
|
||||
|
||||
Give advice without executing commands; the menu below is only for bare invocations. Consult relevant command references as needed for prerequisites and scope. Link to the [docs](https://impeccable.style/docs/) for the broader workflow guide. If the user also requests execution, follow that request.
|
||||
|
||||
## No-argument routing: the context-aware menu
|
||||
|
||||
Read this when the user invokes `/impeccable` with no argument. They are asking "what should I do?" Make the menu context-aware instead of static.
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
0.1.0
|
||||
0.1.2
|
||||
|
||||
@@ -96,6 +96,19 @@ fetch_url() {
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
check_download() {
|
||||
download_file=${1:-$tmp}
|
||||
if [ ! -f "$download_file" ]; then
|
||||
rm -f "$tmp.sha256"
|
||||
echo "impeccable: download completed but the file was removed before execution: $url; check your antivirus quarantine or logs. Refusing to continue; do not disable protection." >&2
|
||||
exit 127
|
||||
fi
|
||||
if [ ! -s "$download_file" ]; then
|
||||
rm -f "$download_file" "$tmp.sha256"
|
||||
echo "impeccable: downloaded file is empty: $url; refusing the unverified download" >&2
|
||||
exit 127
|
||||
fi
|
||||
}
|
||||
if [ -n "$probing" ]; then
|
||||
# Inside another launcher's probe: no download, fail fast and quiet.
|
||||
exit 127
|
||||
@@ -116,6 +129,7 @@ if [ -n "$version" ] && [ "$os" != unknown ] && [ "$arch" != unknown ]; then
|
||||
fetch_url "$url" && fetched=1
|
||||
fi
|
||||
if [ "$fetched" = 1 ]; then
|
||||
check_download
|
||||
# Fail closed: a freshly downloaded binary runs only after verifying
|
||||
# against its .sha256 sidecar. A sidecar that cannot be fetched, or a
|
||||
# machine with no sha256 tool, refuses the download instead of exec'ing
|
||||
@@ -127,15 +141,20 @@ if [ -n "$version" ] && [ "$os" != unknown ] && [ "$arch" != unknown ]; then
|
||||
elif command -v wget >/dev/null 2>&1; then
|
||||
wget -q -O "$tmp.sha256" "$url.sha256" 2>/dev/null && sidecar_ok=1
|
||||
fi
|
||||
check_download
|
||||
expected=""
|
||||
[ "$sidecar_ok" = 1 ] && expected=$(cut -d' ' -f1 < "$tmp.sha256")
|
||||
actual=""
|
||||
if command -v shasum >/dev/null 2>&1; then actual=$(shasum -a 256 "$tmp" | cut -d' ' -f1)
|
||||
elif command -v sha256sum >/dev/null 2>&1; then actual=$(sha256sum "$tmp" | cut -d' ' -f1); fi
|
||||
if command -v shasum >/dev/null 2>&1; then
|
||||
if digest=$(shasum -a 256 "$tmp" 2>/dev/null); then actual=${digest%% *}; fi
|
||||
elif command -v sha256sum >/dev/null 2>&1; then
|
||||
if digest=$(sha256sum "$tmp" 2>/dev/null); then actual=${digest%% *}; fi
|
||||
fi
|
||||
check_download
|
||||
rm -f "$tmp.sha256"
|
||||
if [ -z "$expected" ] || [ -z "$actual" ]; then
|
||||
rm -f "$tmp"
|
||||
echo "impeccable: cannot verify $url against $url.sha256 (sidecar unavailable or no sha256 tool); refusing the unverified download" >&2
|
||||
echo "impeccable: cannot verify $url against $url.sha256 (sidecar unavailable or hashing failed); refusing the unverified download" >&2
|
||||
exit 127
|
||||
fi
|
||||
if [ "$actual" != "$expected" ]; then
|
||||
@@ -143,8 +162,22 @@ if [ -n "$version" ] && [ "$os" != unknown ] && [ "$arch" != unknown ]; then
|
||||
echo "impeccable: checksum mismatch downloading $url" >&2
|
||||
exit 127
|
||||
fi
|
||||
chmod +x "$tmp" 2>/dev/null
|
||||
mv -f "$tmp" "$cached" && exec "$cached" "$@"
|
||||
check_download
|
||||
if ! chmod +x "$tmp" 2>/dev/null; then
|
||||
check_download
|
||||
rm -f "$tmp"
|
||||
echo "impeccable: could not make the verified download executable: $url" >&2
|
||||
exit 127
|
||||
fi
|
||||
check_download
|
||||
if ! mv -f "$tmp" "$cached" 2>/dev/null; then
|
||||
check_download
|
||||
rm -f "$tmp"
|
||||
echo "impeccable: could not cache the verified download: $url" >&2
|
||||
exit 127
|
||||
fi
|
||||
check_download "$cached"
|
||||
exec "$cached" "$@"
|
||||
fi
|
||||
rm -f "$tmp" 2>/dev/null
|
||||
fi
|
||||
|
||||
@@ -82,6 +82,8 @@ curl.exe -fsSL -o "%cached%.part" "%url%" >nul 2>nul
|
||||
if errorlevel 1 goto fail
|
||||
|
||||
:verify
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
rem Mirrors the sh launcher and fails closed: a freshly downloaded binary
|
||||
rem runs only after verifying against its .sha256 sidecar. A sidecar that
|
||||
rem cannot be fetched, or an empty certutil result, refuses the download
|
||||
@@ -91,8 +93,16 @@ if errorlevel 1 goto verify_refuse
|
||||
set "expected="
|
||||
set /p expected=<"%cached%.sha256"
|
||||
for /f "tokens=1" %%h in ("%expected%") do set "expected=%%h"
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
set "actual="
|
||||
for /f "skip=1 delims=" %%h in ('certutil -hashfile "%cached%.part" SHA256 2^>nul') do if not defined actual set "actual=%%h"
|
||||
rem Reuse the sidecar staging file after reading expected. Check certutil's
|
||||
rem status before parsing: its error text on stdout is not a digest.
|
||||
certutil -hashfile "%cached%.part" SHA256 >"%cached%.sha256" 2>nul
|
||||
if errorlevel 1 goto verify_refuse
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
for /f "usebackq skip=1 delims=" %%h in ("%cached%.sha256") do if not defined actual set "actual=%%h"
|
||||
del "%cached%.sha256" >nul 2>nul
|
||||
if not defined expected goto verify_refuse
|
||||
if not defined actual goto verify_refuse
|
||||
@@ -103,17 +113,48 @@ echo impeccable: checksum mismatch downloading %url% 1>&2
|
||||
exit /b 127
|
||||
|
||||
:verify_refuse
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
del "%cached%.part" >nul 2>nul
|
||||
del "%cached%.sha256" >nul 2>nul
|
||||
echo impeccable: cannot verify %url% against %url%.sha256; refusing the unverified download 1>&2
|
||||
exit /b 127
|
||||
|
||||
:check_download
|
||||
set "download_file=%~1"
|
||||
if not defined download_file set "download_file=%cached%.part"
|
||||
if not exist "%download_file%" goto download_missing
|
||||
for %%f in ("%download_file%") do if %%~zf==0 goto download_empty
|
||||
exit /b 0
|
||||
|
||||
:download_missing
|
||||
del "%cached%.sha256" >nul 2>nul
|
||||
echo impeccable: download completed but the file was removed before execution: %url%; check your antivirus quarantine or logs. Refusing to continue; do not disable protection. 1>&2
|
||||
exit /b 127
|
||||
|
||||
:download_empty
|
||||
del "%download_file%" >nul 2>nul
|
||||
del "%cached%.sha256" >nul 2>nul
|
||||
echo impeccable: downloaded file is empty: %url%; refusing the unverified download 1>&2
|
||||
exit /b 127
|
||||
|
||||
:place
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
move /y "%cached%.part" "%cached%" >nul 2>nul
|
||||
if not exist "%cached%" goto fail
|
||||
if errorlevel 1 goto place_failed
|
||||
call :check_download "%cached%"
|
||||
if errorlevel 1 exit /b 127
|
||||
set "run=%cached%"
|
||||
goto run
|
||||
|
||||
:place_failed
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
del "%cached%.part" >nul 2>nul
|
||||
echo impeccable: could not cache the verified download: %url% 1>&2
|
||||
exit /b 127
|
||||
|
||||
:run
|
||||
"%run%" %*
|
||||
exit /b
|
||||
|
||||
@@ -7834,7 +7834,6 @@
|
||||
if (editBadgeEl && editBadgeEl.style.display !== 'none') renderEditBadge('idle-disabled');
|
||||
showBar('generating');
|
||||
saveSession();
|
||||
sendCheckpoint('generate_started');
|
||||
writeScrollY(window.scrollY);
|
||||
if (variantObserver) variantObserver.disconnect();
|
||||
variantObserver = startVariantObserver(currentSessionId);
|
||||
@@ -7916,7 +7915,6 @@
|
||||
showBar('generating');
|
||||
startScrollTracking();
|
||||
saveSession();
|
||||
sendCheckpoint('generate_started');
|
||||
writeScrollY(window.scrollY);
|
||||
if (variantObserver) variantObserver.disconnect();
|
||||
variantObserver = startVariantObserver(currentSessionId);
|
||||
@@ -8238,7 +8236,8 @@
|
||||
// rasterization from delaying the fetch itself.
|
||||
if (!hasAnnotations) {
|
||||
basePayload.clientSentAt = Date.now();
|
||||
await sendEvent(basePayload);
|
||||
const created = await sendEvent(basePayload);
|
||||
if (created?.ok && currentSessionId === basePayload.id) sendCheckpoint('generate_started');
|
||||
}
|
||||
|
||||
let screenshotPath;
|
||||
@@ -8279,7 +8278,10 @@
|
||||
// is semantic input. Plain requests were already dispatched above.
|
||||
if (hasAnnotations) {
|
||||
basePayload.clientSentAt = Date.now();
|
||||
sendEvent(screenshotPath ? { ...basePayload, screenshotPath } : basePayload);
|
||||
const created = await sendEvent(screenshotPath ? { ...basePayload, screenshotPath } : basePayload);
|
||||
// Capture/upload can take seconds. Progress before this acknowledgment
|
||||
// refers to an unknown session and would clear our own active work.
|
||||
if (created?.ok && currentSessionId === basePayload.id) sendCheckpoint('generate_started');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
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.
|
||||
version: 4.2.0
|
||||
version: 4.2.1
|
||||
license: Apache 2.0
|
||||
allowed-tools:
|
||||
- Bash(npx impeccable *)
|
||||
@@ -69,7 +69,8 @@ Choose the mode from the requested surface, not the product, and persist it only
|
||||
Routing:
|
||||
|
||||
- **No argument:** read [routing.md](reference/routing.md) and present its context-aware menu; never auto-run a command.
|
||||
- **Explicit or clearly implied command:** load its reference (native variant on native platforms) and follow it. Ask once if two commands fit.
|
||||
- **Explicit or clearly implied request to run a command:** load its reference (native variant on native platforms) and follow it. Ask once if two commands fit.
|
||||
- **Workflow or command-selection question:** read [Workflow questions](reference/routing.md#workflow-questions).
|
||||
- **Otherwise:** treat the request as general design work. Missing PRODUCT.md routes a new surface or replacement world through init, then new-work; a narrow refinement of existing code proceeds on the incumbent implementation as `impeccable context` directs, offering init afterward rather than blocking on it.
|
||||
- `teach` aliases `init`. `craft` is a deprecated alias for ordinary new-work and adds nothing. `shape` owns task discovery, then enters new-work only for visual-world and surface-concept decisions.
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ const __impeccableLiveDev =
|
||||
process.env.NODE_ENV === "development" ? ["http://localhost:8400"] : [];
|
||||
```
|
||||
|
||||
Per-framework: Next.js + monorepo helper: edit the *app's* `next.config.*` (not the shared helper), appending to `additionalScriptSrc` / `additionalConnectSrc`. SvelteKit: `svelte.config.js`, `kit.csp.directives['script-src']` and `['connect-src']`. Nuxt + nuxt-security: `nuxt.config.*`, `security.headers.contentSecurityPolicy['script-src']` and `['connect-src']`. Reference outputs: `tests/framework-fixtures/nextjs-turborepo/expected-after-patch.ts`, `tests/framework-fixtures/sveltekit-csp/expected-after-patch.js`. Idempotency: if `__impeccableLiveDev` already exists in the file, the patch is applied; just mark `cspChecked: true`.
|
||||
Per-framework: Next.js + monorepo helper: edit the *app's* `next.config.*` (not the shared helper), appending to `additionalScriptSrc` / `additionalConnectSrc`. SvelteKit: `svelte.config.js`, `kit.csp.directives['script-src']` and `['connect-src']`. Nuxt + nuxt-security: `nuxt.config.*`, `security.headers.contentSecurityPolicy['script-src']` and `['connect-src']`. Reference outputs: [nextjs-turborepo/expected-after-patch.ts](https://github.com/pbakaus/impeccable/blob/8dac6ae7e020c43ab10ce9b41939f6fd42627b96/tests/framework-fixtures/nextjs-turborepo/expected-after-patch.ts), [sveltekit-csp/expected-after-patch.js](https://github.com/pbakaus/impeccable/blob/8dac6ae7e020c43ab10ce9b41939f6fd42627b96/tests/framework-fixtures/sveltekit-csp/expected-after-patch.js). Idempotency: if `__impeccableLiveDev` already exists in the file, the patch is applied; just mark `cspChecked: true`.
|
||||
|
||||
### append-string
|
||||
|
||||
@@ -93,7 +93,7 @@ const __impeccableLiveDev =
|
||||
- `script-src 'self' 'unsafe-inline'` becomes `` `script-src 'self' 'unsafe-inline'${__impeccableLiveDev}` ``
|
||||
- `connect-src 'self'` becomes `` `connect-src 'self'${__impeccableLiveDev}` ``
|
||||
|
||||
Per-framework: Next.js inline `headers()` in `next.config.*`; Nuxt `routeRules['/**'].headers['Content-Security-Policy']` in `nuxt.config.*`. Reference outputs: `tests/framework-fixtures/nextjs-inline-csp/expected-after-patch.js`, `tests/framework-fixtures/nuxt-csp/expected-after-patch.ts`.
|
||||
Per-framework: Next.js inline `headers()` in `next.config.*`; Nuxt `routeRules['/**'].headers['Content-Security-Policy']` in `nuxt.config.*`. Reference outputs: [nextjs-inline-csp/expected-after-patch.js](https://github.com/pbakaus/impeccable/blob/8dac6ae7e020c43ab10ce9b41939f6fd42627b96/tests/framework-fixtures/nextjs-inline-csp/expected-after-patch.js), [nuxt-csp/expected-after-patch.ts](https://github.com/pbakaus/impeccable/blob/8dac6ae7e020c43ab10ce9b41939f6fd42627b96/tests/framework-fixtures/nuxt-csp/expected-after-patch.ts).
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
|
||||
@@ -196,7 +196,7 @@ Complete HTML replacement of the original element per variant, not a CSS-only pa
|
||||
|
||||
Replace the style opening tag with `cssAuthoring.styleTag` when the tool returns a different one. **Each variant div contains exactly one top-level element**, same tag as the original; loose siblings break outline tracking and accept. First variant visible, all others `display: none`. The browser's MutationObserver accepts atomic or progressive arrival; accepting an arrived variant fences the worker, so later publications are rejected.
|
||||
|
||||
For `styleMode: "scoped"`, author every `:scope` rule with a descendant combinator: the `@scope` boundary is the variant wrapper div, not your element, so a bare `:scope { ... }` styles a `display: contents` shell. Always step in (`:scope > .card`, `:scope .hero-title`). The fake test agent's CSS in `tests/live-e2e/agent.mjs` is a faithful template.
|
||||
For `styleMode: "scoped"`, author every `:scope` rule with a descendant combinator: the `@scope` boundary is the variant wrapper div, not your element, so a bare `:scope { ... }` styles a `display: contents` shell. Always step in (`:scope > .card`, `:scope .hero-title`). The fake test agent's CSS in the [repo agent template](https://github.com/pbakaus/impeccable/blob/8dac6ae7e020c43ab10ce9b41939f6fd42627b96/tests/live-e2e/agent.mjs) is a faithful template.
|
||||
|
||||
**JSX / TSX targets:** wrap `<style>` content in a template literal (CSS braces would parse as JSX), use `className=` / `style={{…}}`, keep `data-impeccable-*` attributes as plain strings:
|
||||
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
# No-argument routing: the context-aware menu
|
||||
# Command guidance
|
||||
|
||||
## Workflow questions
|
||||
|
||||
Give advice without executing commands; the menu below is only for bare invocations. Consult relevant command references as needed for prerequisites and scope. Link to the [docs](https://impeccable.style/docs/) for the broader workflow guide. If the user also requests execution, follow that request.
|
||||
|
||||
## No-argument routing: the context-aware menu
|
||||
|
||||
Read this when the user invokes `/impeccable` with no argument. They are asking "what should I do?" Make the menu context-aware instead of static.
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
0.1.0
|
||||
0.1.2
|
||||
|
||||
@@ -96,6 +96,19 @@ fetch_url() {
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
check_download() {
|
||||
download_file=${1:-$tmp}
|
||||
if [ ! -f "$download_file" ]; then
|
||||
rm -f "$tmp.sha256"
|
||||
echo "impeccable: download completed but the file was removed before execution: $url; check your antivirus quarantine or logs. Refusing to continue; do not disable protection." >&2
|
||||
exit 127
|
||||
fi
|
||||
if [ ! -s "$download_file" ]; then
|
||||
rm -f "$download_file" "$tmp.sha256"
|
||||
echo "impeccable: downloaded file is empty: $url; refusing the unverified download" >&2
|
||||
exit 127
|
||||
fi
|
||||
}
|
||||
if [ -n "$probing" ]; then
|
||||
# Inside another launcher's probe: no download, fail fast and quiet.
|
||||
exit 127
|
||||
@@ -116,6 +129,7 @@ if [ -n "$version" ] && [ "$os" != unknown ] && [ "$arch" != unknown ]; then
|
||||
fetch_url "$url" && fetched=1
|
||||
fi
|
||||
if [ "$fetched" = 1 ]; then
|
||||
check_download
|
||||
# Fail closed: a freshly downloaded binary runs only after verifying
|
||||
# against its .sha256 sidecar. A sidecar that cannot be fetched, or a
|
||||
# machine with no sha256 tool, refuses the download instead of exec'ing
|
||||
@@ -127,15 +141,20 @@ if [ -n "$version" ] && [ "$os" != unknown ] && [ "$arch" != unknown ]; then
|
||||
elif command -v wget >/dev/null 2>&1; then
|
||||
wget -q -O "$tmp.sha256" "$url.sha256" 2>/dev/null && sidecar_ok=1
|
||||
fi
|
||||
check_download
|
||||
expected=""
|
||||
[ "$sidecar_ok" = 1 ] && expected=$(cut -d' ' -f1 < "$tmp.sha256")
|
||||
actual=""
|
||||
if command -v shasum >/dev/null 2>&1; then actual=$(shasum -a 256 "$tmp" | cut -d' ' -f1)
|
||||
elif command -v sha256sum >/dev/null 2>&1; then actual=$(sha256sum "$tmp" | cut -d' ' -f1); fi
|
||||
if command -v shasum >/dev/null 2>&1; then
|
||||
if digest=$(shasum -a 256 "$tmp" 2>/dev/null); then actual=${digest%% *}; fi
|
||||
elif command -v sha256sum >/dev/null 2>&1; then
|
||||
if digest=$(sha256sum "$tmp" 2>/dev/null); then actual=${digest%% *}; fi
|
||||
fi
|
||||
check_download
|
||||
rm -f "$tmp.sha256"
|
||||
if [ -z "$expected" ] || [ -z "$actual" ]; then
|
||||
rm -f "$tmp"
|
||||
echo "impeccable: cannot verify $url against $url.sha256 (sidecar unavailable or no sha256 tool); refusing the unverified download" >&2
|
||||
echo "impeccable: cannot verify $url against $url.sha256 (sidecar unavailable or hashing failed); refusing the unverified download" >&2
|
||||
exit 127
|
||||
fi
|
||||
if [ "$actual" != "$expected" ]; then
|
||||
@@ -143,8 +162,22 @@ if [ -n "$version" ] && [ "$os" != unknown ] && [ "$arch" != unknown ]; then
|
||||
echo "impeccable: checksum mismatch downloading $url" >&2
|
||||
exit 127
|
||||
fi
|
||||
chmod +x "$tmp" 2>/dev/null
|
||||
mv -f "$tmp" "$cached" && exec "$cached" "$@"
|
||||
check_download
|
||||
if ! chmod +x "$tmp" 2>/dev/null; then
|
||||
check_download
|
||||
rm -f "$tmp"
|
||||
echo "impeccable: could not make the verified download executable: $url" >&2
|
||||
exit 127
|
||||
fi
|
||||
check_download
|
||||
if ! mv -f "$tmp" "$cached" 2>/dev/null; then
|
||||
check_download
|
||||
rm -f "$tmp"
|
||||
echo "impeccable: could not cache the verified download: $url" >&2
|
||||
exit 127
|
||||
fi
|
||||
check_download "$cached"
|
||||
exec "$cached" "$@"
|
||||
fi
|
||||
rm -f "$tmp" 2>/dev/null
|
||||
fi
|
||||
|
||||
@@ -82,6 +82,8 @@ curl.exe -fsSL -o "%cached%.part" "%url%" >nul 2>nul
|
||||
if errorlevel 1 goto fail
|
||||
|
||||
:verify
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
rem Mirrors the sh launcher and fails closed: a freshly downloaded binary
|
||||
rem runs only after verifying against its .sha256 sidecar. A sidecar that
|
||||
rem cannot be fetched, or an empty certutil result, refuses the download
|
||||
@@ -91,8 +93,16 @@ if errorlevel 1 goto verify_refuse
|
||||
set "expected="
|
||||
set /p expected=<"%cached%.sha256"
|
||||
for /f "tokens=1" %%h in ("%expected%") do set "expected=%%h"
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
set "actual="
|
||||
for /f "skip=1 delims=" %%h in ('certutil -hashfile "%cached%.part" SHA256 2^>nul') do if not defined actual set "actual=%%h"
|
||||
rem Reuse the sidecar staging file after reading expected. Check certutil's
|
||||
rem status before parsing: its error text on stdout is not a digest.
|
||||
certutil -hashfile "%cached%.part" SHA256 >"%cached%.sha256" 2>nul
|
||||
if errorlevel 1 goto verify_refuse
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
for /f "usebackq skip=1 delims=" %%h in ("%cached%.sha256") do if not defined actual set "actual=%%h"
|
||||
del "%cached%.sha256" >nul 2>nul
|
||||
if not defined expected goto verify_refuse
|
||||
if not defined actual goto verify_refuse
|
||||
@@ -103,17 +113,48 @@ echo impeccable: checksum mismatch downloading %url% 1>&2
|
||||
exit /b 127
|
||||
|
||||
:verify_refuse
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
del "%cached%.part" >nul 2>nul
|
||||
del "%cached%.sha256" >nul 2>nul
|
||||
echo impeccable: cannot verify %url% against %url%.sha256; refusing the unverified download 1>&2
|
||||
exit /b 127
|
||||
|
||||
:check_download
|
||||
set "download_file=%~1"
|
||||
if not defined download_file set "download_file=%cached%.part"
|
||||
if not exist "%download_file%" goto download_missing
|
||||
for %%f in ("%download_file%") do if %%~zf==0 goto download_empty
|
||||
exit /b 0
|
||||
|
||||
:download_missing
|
||||
del "%cached%.sha256" >nul 2>nul
|
||||
echo impeccable: download completed but the file was removed before execution: %url%; check your antivirus quarantine or logs. Refusing to continue; do not disable protection. 1>&2
|
||||
exit /b 127
|
||||
|
||||
:download_empty
|
||||
del "%download_file%" >nul 2>nul
|
||||
del "%cached%.sha256" >nul 2>nul
|
||||
echo impeccable: downloaded file is empty: %url%; refusing the unverified download 1>&2
|
||||
exit /b 127
|
||||
|
||||
:place
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
move /y "%cached%.part" "%cached%" >nul 2>nul
|
||||
if not exist "%cached%" goto fail
|
||||
if errorlevel 1 goto place_failed
|
||||
call :check_download "%cached%"
|
||||
if errorlevel 1 exit /b 127
|
||||
set "run=%cached%"
|
||||
goto run
|
||||
|
||||
:place_failed
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
del "%cached%.part" >nul 2>nul
|
||||
echo impeccable: could not cache the verified download: %url% 1>&2
|
||||
exit /b 127
|
||||
|
||||
:run
|
||||
"%run%" %*
|
||||
exit /b
|
||||
|
||||
@@ -7834,7 +7834,6 @@
|
||||
if (editBadgeEl && editBadgeEl.style.display !== 'none') renderEditBadge('idle-disabled');
|
||||
showBar('generating');
|
||||
saveSession();
|
||||
sendCheckpoint('generate_started');
|
||||
writeScrollY(window.scrollY);
|
||||
if (variantObserver) variantObserver.disconnect();
|
||||
variantObserver = startVariantObserver(currentSessionId);
|
||||
@@ -7916,7 +7915,6 @@
|
||||
showBar('generating');
|
||||
startScrollTracking();
|
||||
saveSession();
|
||||
sendCheckpoint('generate_started');
|
||||
writeScrollY(window.scrollY);
|
||||
if (variantObserver) variantObserver.disconnect();
|
||||
variantObserver = startVariantObserver(currentSessionId);
|
||||
@@ -8238,7 +8236,8 @@
|
||||
// rasterization from delaying the fetch itself.
|
||||
if (!hasAnnotations) {
|
||||
basePayload.clientSentAt = Date.now();
|
||||
await sendEvent(basePayload);
|
||||
const created = await sendEvent(basePayload);
|
||||
if (created?.ok && currentSessionId === basePayload.id) sendCheckpoint('generate_started');
|
||||
}
|
||||
|
||||
let screenshotPath;
|
||||
@@ -8279,7 +8278,10 @@
|
||||
// is semantic input. Plain requests were already dispatched above.
|
||||
if (hasAnnotations) {
|
||||
basePayload.clientSentAt = Date.now();
|
||||
sendEvent(screenshotPath ? { ...basePayload, screenshotPath } : basePayload);
|
||||
const created = await sendEvent(screenshotPath ? { ...basePayload, screenshotPath } : basePayload);
|
||||
// Capture/upload can take seconds. Progress before this acknowledgment
|
||||
// refers to an unknown session and would clear our own active work.
|
||||
if (created?.ok && currentSessionId === basePayload.id) sendCheckpoint('generate_started');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
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.
|
||||
version: 4.2.0
|
||||
version: 4.2.1
|
||||
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]"
|
||||
license: Apache 2.0
|
||||
@@ -71,7 +71,8 @@ Choose the mode from the requested surface, not the product, and persist it only
|
||||
Routing:
|
||||
|
||||
- **No argument:** read [routing.md](reference/routing.md) and present its context-aware menu; never auto-run a command.
|
||||
- **Explicit or clearly implied command:** load its reference (native variant on native platforms) and follow it. Ask once if two commands fit.
|
||||
- **Explicit or clearly implied request to run a command:** load its reference (native variant on native platforms) and follow it. Ask once if two commands fit.
|
||||
- **Workflow or command-selection question:** read [Workflow questions](reference/routing.md#workflow-questions).
|
||||
- **Otherwise:** treat the request as general design work. Missing PRODUCT.md routes a new surface or replacement world through init, then new-work; a narrow refinement of existing code proceeds on the incumbent implementation as `impeccable context` directs, offering init afterward rather than blocking on it.
|
||||
- `teach` aliases `init`. `craft` is a deprecated alias for ordinary new-work and adds nothing. `shape` owns task discovery, then enters new-work only for visual-world and surface-concept decisions.
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ const __impeccableLiveDev =
|
||||
process.env.NODE_ENV === "development" ? ["http://localhost:8400"] : [];
|
||||
```
|
||||
|
||||
Per-framework: Next.js + monorepo helper: edit the *app's* `next.config.*` (not the shared helper), appending to `additionalScriptSrc` / `additionalConnectSrc`. SvelteKit: `svelte.config.js`, `kit.csp.directives['script-src']` and `['connect-src']`. Nuxt + nuxt-security: `nuxt.config.*`, `security.headers.contentSecurityPolicy['script-src']` and `['connect-src']`. Reference outputs: `tests/framework-fixtures/nextjs-turborepo/expected-after-patch.ts`, `tests/framework-fixtures/sveltekit-csp/expected-after-patch.js`. Idempotency: if `__impeccableLiveDev` already exists in the file, the patch is applied; just mark `cspChecked: true`.
|
||||
Per-framework: Next.js + monorepo helper: edit the *app's* `next.config.*` (not the shared helper), appending to `additionalScriptSrc` / `additionalConnectSrc`. SvelteKit: `svelte.config.js`, `kit.csp.directives['script-src']` and `['connect-src']`. Nuxt + nuxt-security: `nuxt.config.*`, `security.headers.contentSecurityPolicy['script-src']` and `['connect-src']`. Reference outputs: [nextjs-turborepo/expected-after-patch.ts](https://github.com/pbakaus/impeccable/blob/8dac6ae7e020c43ab10ce9b41939f6fd42627b96/tests/framework-fixtures/nextjs-turborepo/expected-after-patch.ts), [sveltekit-csp/expected-after-patch.js](https://github.com/pbakaus/impeccable/blob/8dac6ae7e020c43ab10ce9b41939f6fd42627b96/tests/framework-fixtures/sveltekit-csp/expected-after-patch.js). Idempotency: if `__impeccableLiveDev` already exists in the file, the patch is applied; just mark `cspChecked: true`.
|
||||
|
||||
### append-string
|
||||
|
||||
@@ -93,7 +93,7 @@ const __impeccableLiveDev =
|
||||
- `script-src 'self' 'unsafe-inline'` becomes `` `script-src 'self' 'unsafe-inline'${__impeccableLiveDev}` ``
|
||||
- `connect-src 'self'` becomes `` `connect-src 'self'${__impeccableLiveDev}` ``
|
||||
|
||||
Per-framework: Next.js inline `headers()` in `next.config.*`; Nuxt `routeRules['/**'].headers['Content-Security-Policy']` in `nuxt.config.*`. Reference outputs: `tests/framework-fixtures/nextjs-inline-csp/expected-after-patch.js`, `tests/framework-fixtures/nuxt-csp/expected-after-patch.ts`.
|
||||
Per-framework: Next.js inline `headers()` in `next.config.*`; Nuxt `routeRules['/**'].headers['Content-Security-Policy']` in `nuxt.config.*`. Reference outputs: [nextjs-inline-csp/expected-after-patch.js](https://github.com/pbakaus/impeccable/blob/8dac6ae7e020c43ab10ce9b41939f6fd42627b96/tests/framework-fixtures/nextjs-inline-csp/expected-after-patch.js), [nuxt-csp/expected-after-patch.ts](https://github.com/pbakaus/impeccable/blob/8dac6ae7e020c43ab10ce9b41939f6fd42627b96/tests/framework-fixtures/nuxt-csp/expected-after-patch.ts).
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
|
||||
@@ -196,7 +196,7 @@ Complete HTML replacement of the original element per variant, not a CSS-only pa
|
||||
|
||||
Replace the style opening tag with `cssAuthoring.styleTag` when the tool returns a different one. **Each variant div contains exactly one top-level element**, same tag as the original; loose siblings break outline tracking and accept. First variant visible, all others `display: none`. The browser's MutationObserver accepts atomic or progressive arrival; accepting an arrived variant fences the worker, so later publications are rejected.
|
||||
|
||||
For `styleMode: "scoped"`, author every `:scope` rule with a descendant combinator: the `@scope` boundary is the variant wrapper div, not your element, so a bare `:scope { ... }` styles a `display: contents` shell. Always step in (`:scope > .card`, `:scope .hero-title`). The fake test agent's CSS in `tests/live-e2e/agent.mjs` is a faithful template.
|
||||
For `styleMode: "scoped"`, author every `:scope` rule with a descendant combinator: the `@scope` boundary is the variant wrapper div, not your element, so a bare `:scope { ... }` styles a `display: contents` shell. Always step in (`:scope > .card`, `:scope .hero-title`). The fake test agent's CSS in the [repo agent template](https://github.com/pbakaus/impeccable/blob/8dac6ae7e020c43ab10ce9b41939f6fd42627b96/tests/live-e2e/agent.mjs) is a faithful template.
|
||||
|
||||
**JSX / TSX targets:** wrap `<style>` content in a template literal (CSS braces would parse as JSX), use `className=` / `style={{…}}`, keep `data-impeccable-*` attributes as plain strings:
|
||||
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
# No-argument routing: the context-aware menu
|
||||
# Command guidance
|
||||
|
||||
## Workflow questions
|
||||
|
||||
Give advice without executing commands; the menu below is only for bare invocations. Consult relevant command references as needed for prerequisites and scope. Link to the [docs](https://impeccable.style/docs/) for the broader workflow guide. If the user also requests execution, follow that request.
|
||||
|
||||
## No-argument routing: the context-aware menu
|
||||
|
||||
Read this when the user invokes `/impeccable` with no argument. They are asking "what should I do?" Make the menu context-aware instead of static.
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
0.1.0
|
||||
0.1.2
|
||||
|
||||
@@ -96,6 +96,19 @@ fetch_url() {
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
check_download() {
|
||||
download_file=${1:-$tmp}
|
||||
if [ ! -f "$download_file" ]; then
|
||||
rm -f "$tmp.sha256"
|
||||
echo "impeccable: download completed but the file was removed before execution: $url; check your antivirus quarantine or logs. Refusing to continue; do not disable protection." >&2
|
||||
exit 127
|
||||
fi
|
||||
if [ ! -s "$download_file" ]; then
|
||||
rm -f "$download_file" "$tmp.sha256"
|
||||
echo "impeccable: downloaded file is empty: $url; refusing the unverified download" >&2
|
||||
exit 127
|
||||
fi
|
||||
}
|
||||
if [ -n "$probing" ]; then
|
||||
# Inside another launcher's probe: no download, fail fast and quiet.
|
||||
exit 127
|
||||
@@ -116,6 +129,7 @@ if [ -n "$version" ] && [ "$os" != unknown ] && [ "$arch" != unknown ]; then
|
||||
fetch_url "$url" && fetched=1
|
||||
fi
|
||||
if [ "$fetched" = 1 ]; then
|
||||
check_download
|
||||
# Fail closed: a freshly downloaded binary runs only after verifying
|
||||
# against its .sha256 sidecar. A sidecar that cannot be fetched, or a
|
||||
# machine with no sha256 tool, refuses the download instead of exec'ing
|
||||
@@ -127,15 +141,20 @@ if [ -n "$version" ] && [ "$os" != unknown ] && [ "$arch" != unknown ]; then
|
||||
elif command -v wget >/dev/null 2>&1; then
|
||||
wget -q -O "$tmp.sha256" "$url.sha256" 2>/dev/null && sidecar_ok=1
|
||||
fi
|
||||
check_download
|
||||
expected=""
|
||||
[ "$sidecar_ok" = 1 ] && expected=$(cut -d' ' -f1 < "$tmp.sha256")
|
||||
actual=""
|
||||
if command -v shasum >/dev/null 2>&1; then actual=$(shasum -a 256 "$tmp" | cut -d' ' -f1)
|
||||
elif command -v sha256sum >/dev/null 2>&1; then actual=$(sha256sum "$tmp" | cut -d' ' -f1); fi
|
||||
if command -v shasum >/dev/null 2>&1; then
|
||||
if digest=$(shasum -a 256 "$tmp" 2>/dev/null); then actual=${digest%% *}; fi
|
||||
elif command -v sha256sum >/dev/null 2>&1; then
|
||||
if digest=$(sha256sum "$tmp" 2>/dev/null); then actual=${digest%% *}; fi
|
||||
fi
|
||||
check_download
|
||||
rm -f "$tmp.sha256"
|
||||
if [ -z "$expected" ] || [ -z "$actual" ]; then
|
||||
rm -f "$tmp"
|
||||
echo "impeccable: cannot verify $url against $url.sha256 (sidecar unavailable or no sha256 tool); refusing the unverified download" >&2
|
||||
echo "impeccable: cannot verify $url against $url.sha256 (sidecar unavailable or hashing failed); refusing the unverified download" >&2
|
||||
exit 127
|
||||
fi
|
||||
if [ "$actual" != "$expected" ]; then
|
||||
@@ -143,8 +162,22 @@ if [ -n "$version" ] && [ "$os" != unknown ] && [ "$arch" != unknown ]; then
|
||||
echo "impeccable: checksum mismatch downloading $url" >&2
|
||||
exit 127
|
||||
fi
|
||||
chmod +x "$tmp" 2>/dev/null
|
||||
mv -f "$tmp" "$cached" && exec "$cached" "$@"
|
||||
check_download
|
||||
if ! chmod +x "$tmp" 2>/dev/null; then
|
||||
check_download
|
||||
rm -f "$tmp"
|
||||
echo "impeccable: could not make the verified download executable: $url" >&2
|
||||
exit 127
|
||||
fi
|
||||
check_download
|
||||
if ! mv -f "$tmp" "$cached" 2>/dev/null; then
|
||||
check_download
|
||||
rm -f "$tmp"
|
||||
echo "impeccable: could not cache the verified download: $url" >&2
|
||||
exit 127
|
||||
fi
|
||||
check_download "$cached"
|
||||
exec "$cached" "$@"
|
||||
fi
|
||||
rm -f "$tmp" 2>/dev/null
|
||||
fi
|
||||
|
||||
@@ -82,6 +82,8 @@ curl.exe -fsSL -o "%cached%.part" "%url%" >nul 2>nul
|
||||
if errorlevel 1 goto fail
|
||||
|
||||
:verify
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
rem Mirrors the sh launcher and fails closed: a freshly downloaded binary
|
||||
rem runs only after verifying against its .sha256 sidecar. A sidecar that
|
||||
rem cannot be fetched, or an empty certutil result, refuses the download
|
||||
@@ -91,8 +93,16 @@ if errorlevel 1 goto verify_refuse
|
||||
set "expected="
|
||||
set /p expected=<"%cached%.sha256"
|
||||
for /f "tokens=1" %%h in ("%expected%") do set "expected=%%h"
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
set "actual="
|
||||
for /f "skip=1 delims=" %%h in ('certutil -hashfile "%cached%.part" SHA256 2^>nul') do if not defined actual set "actual=%%h"
|
||||
rem Reuse the sidecar staging file after reading expected. Check certutil's
|
||||
rem status before parsing: its error text on stdout is not a digest.
|
||||
certutil -hashfile "%cached%.part" SHA256 >"%cached%.sha256" 2>nul
|
||||
if errorlevel 1 goto verify_refuse
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
for /f "usebackq skip=1 delims=" %%h in ("%cached%.sha256") do if not defined actual set "actual=%%h"
|
||||
del "%cached%.sha256" >nul 2>nul
|
||||
if not defined expected goto verify_refuse
|
||||
if not defined actual goto verify_refuse
|
||||
@@ -103,17 +113,48 @@ echo impeccable: checksum mismatch downloading %url% 1>&2
|
||||
exit /b 127
|
||||
|
||||
:verify_refuse
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
del "%cached%.part" >nul 2>nul
|
||||
del "%cached%.sha256" >nul 2>nul
|
||||
echo impeccable: cannot verify %url% against %url%.sha256; refusing the unverified download 1>&2
|
||||
exit /b 127
|
||||
|
||||
:check_download
|
||||
set "download_file=%~1"
|
||||
if not defined download_file set "download_file=%cached%.part"
|
||||
if not exist "%download_file%" goto download_missing
|
||||
for %%f in ("%download_file%") do if %%~zf==0 goto download_empty
|
||||
exit /b 0
|
||||
|
||||
:download_missing
|
||||
del "%cached%.sha256" >nul 2>nul
|
||||
echo impeccable: download completed but the file was removed before execution: %url%; check your antivirus quarantine or logs. Refusing to continue; do not disable protection. 1>&2
|
||||
exit /b 127
|
||||
|
||||
:download_empty
|
||||
del "%download_file%" >nul 2>nul
|
||||
del "%cached%.sha256" >nul 2>nul
|
||||
echo impeccable: downloaded file is empty: %url%; refusing the unverified download 1>&2
|
||||
exit /b 127
|
||||
|
||||
:place
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
move /y "%cached%.part" "%cached%" >nul 2>nul
|
||||
if not exist "%cached%" goto fail
|
||||
if errorlevel 1 goto place_failed
|
||||
call :check_download "%cached%"
|
||||
if errorlevel 1 exit /b 127
|
||||
set "run=%cached%"
|
||||
goto run
|
||||
|
||||
:place_failed
|
||||
call :check_download
|
||||
if errorlevel 1 exit /b 127
|
||||
del "%cached%.part" >nul 2>nul
|
||||
echo impeccable: could not cache the verified download: %url% 1>&2
|
||||
exit /b 127
|
||||
|
||||
:run
|
||||
"%run%" %*
|
||||
exit /b
|
||||
|
||||
@@ -7834,7 +7834,6 @@
|
||||
if (editBadgeEl && editBadgeEl.style.display !== 'none') renderEditBadge('idle-disabled');
|
||||
showBar('generating');
|
||||
saveSession();
|
||||
sendCheckpoint('generate_started');
|
||||
writeScrollY(window.scrollY);
|
||||
if (variantObserver) variantObserver.disconnect();
|
||||
variantObserver = startVariantObserver(currentSessionId);
|
||||
@@ -7916,7 +7915,6 @@
|
||||
showBar('generating');
|
||||
startScrollTracking();
|
||||
saveSession();
|
||||
sendCheckpoint('generate_started');
|
||||
writeScrollY(window.scrollY);
|
||||
if (variantObserver) variantObserver.disconnect();
|
||||
variantObserver = startVariantObserver(currentSessionId);
|
||||
@@ -8238,7 +8236,8 @@
|
||||
// rasterization from delaying the fetch itself.
|
||||
if (!hasAnnotations) {
|
||||
basePayload.clientSentAt = Date.now();
|
||||
await sendEvent(basePayload);
|
||||
const created = await sendEvent(basePayload);
|
||||
if (created?.ok && currentSessionId === basePayload.id) sendCheckpoint('generate_started');
|
||||
}
|
||||
|
||||
let screenshotPath;
|
||||
@@ -8279,7 +8278,10 @@
|
||||
// is semantic input. Plain requests were already dispatched above.
|
||||
if (hasAnnotations) {
|
||||
basePayload.clientSentAt = Date.now();
|
||||
sendEvent(screenshotPath ? { ...basePayload, screenshotPath } : basePayload);
|
||||
const created = await sendEvent(screenshotPath ? { ...basePayload, screenshotPath } : basePayload);
|
||||
// Capture/upload can take seconds. Progress before this acknowledgment
|
||||
// refers to an unknown session and would clear our own active work.
|
||||
if (created?.ok && currentSessionId === basePayload.id) sendCheckpoint('generate_started');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user