* Point DESIGN.md spec links at the open-source GitHub spec.
The Stitch docs site is client-rendered and unreliable for agent fetch; the
google-labs-code/design.md repo tracks the latest machine-readable spec.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Sync plugin and harness copies after DESIGN.md spec link update.
build:release copies skill/reference into plugin/ and all harness dirs, so
refresh those generated outputs here instead of leaving plugin/ stale.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Use raw GitHub URL for DESIGN.md spec in agent-facing refs.
The blob URL serves HTML; raw.githubusercontent.com returns plain markdown
that agents can fetch directly.
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
The bundled detector's cli/main.mjs imports ../../lib/impeccable-config.mjs,
which in the source CLI resolves to cli/lib/impeccable-config.mjs. The skill
build only copies cli/engine/** into scripts/detector/**, leaving that
dependency behind, so from the bundled scripts/detector/cli/main.mjs the same
import resolved to scripts/lib/impeccable-config.mjs and failed with
"Cannot find module .../lib/impeccable-config.mjs". /impeccable critique (and
any detector-backed command) crashed on startup for every provider since #252.
Teach the detector bundler to copy out-of-bundle engine dependencies into the
skill's scripts/lib/, and add a build test that walks every bundled script and
asserts each relative import resolves to another bundled file, so a future
out-of-bundle dependency fails the test instead of the user.
Skill v3.7.1 (patch). CLI unchanged — the engine resolves fine in the CLI's
own tree; only the skill bundling was wrong.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* feat(hooks): package design hook in plugin, install to settings.local.json
Three related changes to how the Impeccable design hook is distributed,
plus an unrelated build fix discovered along the way.
Package the hook in the Claude Code plugin
- The marketplace / `/plugin install` path previously shipped the skill and
agents but no hook, so those users never got the design detector. The build
now emits `plugin/hooks/hooks.json` (auto-discovered at the plugin root),
resolving the script via `${CLAUDE_PLUGIN_ROOT}` so it works wherever Claude
Code unpacks the plugin instead of assuming a `.claude/skills/` layout.
CLI installs the hook into settings.local.json, not shared settings.json
- `npx impeccable skills install/update` now writes the Claude hook to the
gitignored `.claude/settings.local.json` (a machine-local install side
effect) rather than the team-shared `settings.json`, which could otherwise
be committed and break for teammates without the skill installed.
- Graceful handling (leave-it-never-duplicate): if our hook already lives in
the shared `settings.json` (a legacy install or a deliberate user move), it
is honored in place and never duplicated into the local override, which
would otherwise run the detector twice per edit.
- The skill's `/impeccable hooks on|off` toggle is unaffected: it only writes
`.impeccable/hook.json`, never the settings files.
Fix universal.zip build failure under archiver v8
- `archiver` was bumped to v8 (now ESM, factory function removed) but
`scripts/lib/zip.js` still used the old `archiver('zip', ...)` API, so every
build silently failed to produce `dist/universal.zip` (the skill-release
artifact). Switched to `new ZipArchive({...})`.
Also folds in a pre-existing local rename of the hook status message
("Scanning design" -> "Checking UI changes") and its regenerated provider
output.
Tests: new coverage for the plugin-packaged hook manifest and the
shared-settings honor-in-place path; existing CLI assertions moved to
settings.local.json. Full suite green.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(cli): detect hook by marker, not file existence (Bugbot)
hookInstalledForProvider treated any existing settings.local.json (or
hooks.json) as proof the hook was installed. Those files commonly hold
unrelated local settings, so the already-installed `skills install` path
would skip repairing a genuinely missing hook that `update` would add.
Detect the Impeccable marker in the file instead of mere existence. Adds a
test for the exact case: a settings.local.json with only permissions still
triggers hook repair and preserves the unrelated content.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* test(build): fail loud on a broken release zip + cover the zip writer
Close the gap that let the archiver v8 break ship a 0-byte universal.zip
with a green test suite:
- createProviderZip no longer swallows failures. It throws on a missing
source, an archive with zero entries, or a 0-byte output, and build() now
exits non-zero on any such rejection. A build that can't produce its release
artifact fails instead of deploying an empty bundle.
- New tests/zip.test.mjs exercises the real zip writer and round-trips through
extract-zip (the unpacker the CLI uses): a valid bundle unpacks to the skill
tree, and the empty/missing-source cases throw. Wired into the core suite so
it runs in `bun run test`.
Why this matters: the prior CLI e2e tests stub the bundle as a local
directory, so they never built, downloaded, or unzipped a real archive. The
zip writer had no coverage and failed soft, so Dependabot's archiver 7->8
major bump merged green and the deploy shipped an unusable bundle.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(cli): scope hook marker scan to the hooks subtree + prune local dupes (Bugbot)
Two follow-ups from Bugbot:
- fileHasImpeccableHookMarker scanned the whole settings file as raw text, so
an unrelated string (e.g. a permissions allow entry that mentions the hook
path) could falsely read as an installed hook and block install/repair or
the shared-settings skip. Now it parses the JSON and scans only the `hooks`
subtree.
- When the hook is honored in the shared settings.json, copyProviderHooks
skipped the local write but left a stale hook in settings.local.json from an
earlier machine-local install, so Claude Code loaded both and ran the
detector twice per edit. It now prunes the local copy (preserving unrelated
local settings, dropping the file if only our scaffolding remained).
Adds tests for both: a permissions string mentioning the hook path still
triggers repair, and a shared hook prunes the stale local duplicate while
keeping unrelated permissions.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* docs: add PRD for design detector hook integration
Plans a PostToolUse hook for Claude Code and Codex that runs the
existing design detector after every relevant file write and feeds
findings back to the agent as advisory system-reminder context. No
implementation in this commit; covers UX, technical design, build
pipeline changes, distribution, coverage tradeoffs, and rollout.
Co-authored-by: Cursor <cursoragent@cursor.com>
* docs: revise hook PRD with best-practices review
Folds in the P0/P1/P2 findings from an online best-practices critique
against the official Claude Code and Codex hook references plus 10+
2026 community guides and similar prior-art tools (claw-hooks,
claude-code-hooks-mastery).
Key changes:
- Exec form everywhere (Codex snippet was shell form), with Windows
rationale.
- Default timeout dropped from 10s to 5s.
- Re-entrancy guard (CLAUDE_HOOK_DEPTH) and per-file edit counter.
- Session-scoped finding dedup promoted from open question to v1.
- Per-language inline-ignore syntax map (HTML/JSX/CSS/JS).
- Hard-skip rules for sensitive paths and generated/lock files.
- Honest framing about Claude Code lacking per-plugin hook disable.
- Honest framing about Bash-written files being invisible in v1.
- Codex Windows-not-supported call-out, feature flag note, trust ceremony detail.
- Optional NDJSON audit log via IMPECCABLE_HOOK_LOG.
- Findings cap lowered 8 → 5 with attention-budget rationale.
- Versioned envelope ([impeccable@1]) on rendered template.
- Expanded test plan, decision log, and stdin payload appendix.
Co-authored-by: Cursor <cursoragent@cursor.com>
* feat(hooks): ship the design detector hook for Claude Code and Codex
Implements docs/hooks-prd.md: a PostToolUse hook that runs the
impeccable design detector after every Edit/Write/MultiEdit on a UI
file and pushes findings into the agent's next-turn context as a
short system reminder. Silent on clean files. Never blocks an edit.
Why this matters: today, design slop (side-tab borders, gradient
text, purple/cyan palettes, bounce easing, etc.) only gets caught
when a human notices or someone explicitly runs /impeccable audit.
The hook closes the loop at the moment slop is written.
What ships in v1
- skill/scripts/hook.mjs: PostToolUse entry. Reads stdin, runs the
detector in-process (no `npx impeccable` cold start), emits
hookSpecificOutput.additionalContext when fresh findings exist.
- skill/scripts/hook-lib.mjs: extracted helpers (config, cache,
filter, render, audit log, runHook orchestrator). 100% unit-testable.
- skill/scripts/hook-session-start.mjs: SessionStart greeting,
gated by a project-scannable probe + 30-day throttle.
- skill/scripts/hook-admin.mjs: backs /impeccable hooks
on/off/status/ignore-rule/ignore-file/reset.
Hardening built in
- Re-entrancy guard (IMPECCABLE_HOOK_DEPTH) so the hook can never
recursively spawn itself.
- Hard-skip regexes for sensitive paths (.env, .pem, id_rsa,
secrets, credentials, .git) and generated/lock/build output. These
fire before the file is even read; cannot be turned off via config.
- Path-traversal check on the inbound file_path.
- Session-scoped dedup keyed by (session, file, rule, line) so the
same finding never lands in context twice. Prevents the ~12.5K
wasted tokens per chatty session called out in the PRD.
- Per-(session, file) edit counter with a one-shot suppression
notice on the 7th edit, silent after.
- Fail-open contract: every error path returns exit 0 with no
stdout. Optional NDJSON audit log via IMPECCABLE_HOOK_LOG.
Three kill switches (precedence high to low):
1. IMPECCABLE_HOOK_DISABLED env var (1/true/yes/on, case-insensitive)
2. .impeccable/hook.json `enabled: false`
3. /impeccable hooks off slash command (writes the JSON)
Inline ignores are language-aware. `// impeccable: ignore <rule>` for
JS/TS, `<!-- impeccable: ignore <rule> -->` for HTML/Vue/Svelte/Astro,
`{/* impeccable: ignore <rule> */}` for JSX/TSX, `/* impeccable:
ignore <rule> */` for CSS. `*` matches any rule. Directive applies
to the next non-blank line. Same shape as ESLint, Stylelint, Biome.
Build pipeline
- scripts/lib/transformers/hooks.js: per-provider hooks.json
builders, plus the slim .codex-plugin/plugin.json manifest.
- providers.js: emitHooks: 'claude' for claude-code, emitHooks:
'codex' for codex and agents. Codex also emits emitCodexPlugin.
- factory.js: emits hooks/hooks.json next to the skills tree.
- build.js: syncs hooks/ into harness roots and into the slim
plugin/ subtree; writes .codex-plugin/plugin.json. Build is
idempotent (verified: 98 staged files unchanged across two runs).
Claude Code wiring uses exec form (command + args) and the
${CLAUDE_PLUGIN_ROOT} placeholder. Matcher: Edit|Write|MultiEdit.
`if:` glob filters to UI extensions before spawning Node. PostToolUse
timeout 5s, SessionStart timeout 3s.
Codex wiring uses ${PLUGIN_ROOT} (Codex's native placeholder),
matcher Edit|Write|apply_patch, no `if:` analog (the script does the
extension filter). macOS and Linux only; hooks are disabled on
Windows in current Codex builds. The trust ceremony and feature flag
are documented in README.md.
Routing
- /impeccable hooks lives outside the 23-command router table on
purpose: it is plumbing, not a design skill. The hidden
routing slot is added to SKILL.md alongside pin/unpin so the LLM
knows to dispatch it. The 23-command count and all stale-count
validators remain happy.
Tests
- tests/hook.test.mjs: 38 unit tests covering env parsing, config
load + defaults + malformed, cache round-trip + GC,
ignoreRules/minSeverity/inline ignores (all four languages),
globbing with **/*/{a,b}, render template with cap + clamp + 0-line
prefix drop, audit log NDJSON, payload event-name parameterization,
re-entrancy, kill switches, sensitive-path + generated-path +
traversal skips, allowlist filter, config ignoreFiles, edit
counter cycle including the 7th-edit notice, MultiEdit and
apply_patch payload shapes, detector throw swallow, malformed
stdin, missing file race.
- tests/hook-build.test.mjs: 18 integration tests covering hook
manifest shape (matcher, timeouts, exec form, if: glob, placeholders),
Codex differences (${PLUGIN_ROOT}, no if:, no SessionStart),
Codex plugin manifest (no inline hooks field to avoid the
duplicate-file error), routing across the hooksJsonFor table, and
presence of all three committed artifacts plus the bundled detector
the runtime relative-import path depends on.
Full suite: 175 bun tests + 186 node tests, all green.
Docs
- README.md: new "Design hook" section explaining default behavior,
per-project / global / inline disable paths, the JSON schema knobs,
the audit log debug flag, and the slop / a11y coverage split.
- HARNESSES.md: flips the `hooks` row for Codex from No -> Yes
(Claude was already Yes), adds a per-harness hook-surface table
with the manifest location and matcher each provider uses.
Open questions from the PRD intentionally deferred to v2: Bash-write
blind spot, effort-aware suppression, Stop-hook session summary,
per-rule severity, async hook mode. None block v1.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Fix Codex hook scanning: apply_patch paths and co-located stylesheets
Parse file targets from Codex apply_patch command bodies, co-scan imported
and sibling CSS when UI components are edited, drop the git-sweep PostToolUse
group, and align Codex SessionStart manifest and trust docs with the official
hooks spec.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Gitignore hook session cache and drop local test HTML
Hook dedup/throttle state in .impeccable/hook.cache.json is per-project
runtime data like other .impeccable/ sidecars. Remove an untracked
bad-nested-flexbox scratch page from site/public/.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Fix Claude Code hook: drop Edit-only if filter so Write/MultiEdit fire
Claude's if permission rule binds to one tool name, so Edit(*.{…}) never
spawned the hook on Write or MultiEdit despite the matcher listing them.
Extension filtering now lives in hook-lib on both Claude and Codex.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Surface Cursor design findings via stop-hook followup
Replace dropped postToolUse additional_context with afterFileEdit recording
and a one-shot stop followup_message so anti-pattern nudges reach the agent.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Fix design hook packaging and scans
* Fix Cursor hook pending bucket fallback
* Fix Sass hook scan coverage
* Fix Cursor hook review findings
* Fix session start dead hook normalization
* Fix hook config and relative scan paths
* Remove SessionStart design hook
* Remove redundant afterFileEdit normalization
* Fix Cursor suppression and module style scans
* Fix sensitive path hook filter
* Fix disabled Cursor stop hook emission
* Refresh hook harness artifacts
* Fix Cursor hook manifest install
* Add hook ignore-value support
* Ignore hook runtime files locally
* Fix Codex plugin hook packaging
* fix: address PR review bot findings
Block numeric hook depth counters from re-entering.
Avoid following stylesheet imports from traversal-looking hook targets.
* fix: gate ignore-value suggestions by supported rules
Only render exact ignore-value commands when the same finding can be suppressed by ignoreValues.
* Package Codex plugin as hook-only
* Remove Codex plugin packaging
* Recover hook install probe plumbing
* Remove Codex hook packaging follow-up doc
* Remove extra hook docs and skill wording changes
* Install real design hooks via skills CLI
* Add provider hook smoke runner
* Fix Cursor hook delivery with preToolUse gate
* Simplify Cursor hook install to preToolUse
* Clarify confirmed hook exceptions
* Persist hook ignores in shared config
* Guard font hook exceptions
* Fix hook install after main rebase
* Fix hook scan target handling
* fix: address hook review findings
* Address hook review feedback
* Stabilize DeepSeek insert live fixture
* Fix Cursor hook Python shell write bypass
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
Copy guidance (em-dash bans, buzzword bans, button-label / link-text
phrasing, aphoristic-cadence) doesn't belong in the main design skill.
It's not design-specific — the skill is trying to do too much. The six
rules being dropped (every-word-earns, no-em-dashes, no-aphoristic-cadence,
no-buzzwords, button-verb-object, link-standalone) are now better served
by:
- The impeccable engine's antipattern detectors (em-dash-overuse,
marketing-buzzword, aphoristic-cadence, copy-slop) for linting at scan
time.
- The /clarify subcommand for surfacing the same checks when reviewing
copy specifically.
The em-dash ban for the SKILL prose itself still lives in STYLE.md and the
build-time prose validator — that's separate from the skill's guidance to
agents.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The v2.1 ablation sweep (n=10 × 4 brand niches × 3 providers, anchored to
commit 54c3a502, ~544 cells) confirmed these four rules carry no weight in
the skill:
- skill-typo-no-all-caps-body — duplicate of brand-ban-all-caps-body; brand
version is more specific (reserves caps for labels + headings)
- skill-typo-codex-hero-ceiling-repeat — the codex-block restatement of
skill-typo-hero-ceiling didn't add reinforcement on top of the universal
rule
- skill-typo-scale-ratio — duplicate of brand-typo-modular-scale; same
signal, brand version carries the clamp() / fluid implementation detail
- skill-typo-font-count — models don't reach for ≥4 font families in any
niche we test, so the rule has no measurable effect
Each deletion is the Agent A / B / C / D Phase-2 audit recommendation;
none of the four ever validated under either prose state.
Adds EMPIRICAL_VALIDATION.md naming the seven cross-provider winners as the
trustworthy core, and documents the systemic findings (self-priming, detector
saturation, vocabulary anchoring) so future skill edits can avoid the same
traps.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(live-inject): preserve the character after an insertAfter anchor
insertTag()'s insertAfter branch sliced the post-anchor remainder by
prefix.length. When the anchor was not already followed by a newline,
prefix is one character longer than the anchor (the appended '\n'), so
content.slice(prefix.length) dropped the first real character after the
anchor — e.g. `<head>X...` lost the `X` during live-mode injection (#227).
Slice the remainder from the original anchor offset instead. The
insertBefore branch and the already-followed-by-newline case are
unchanged. Add a regression test for both the no-trailing-newline and
newline cases, and regenerate the tracked per-agent bundles so the fix
ships everywhere.
Fixes#227. Root-cause analysis from the issue reporter.
* Fix live inject CRLF insertAfter handling
---------
Co-authored-by: Paul Bakaus <paul.bakaus@gmail.com>
Mirrors the 5 prose changes in skill/SKILL.src.md + skill/reference/brand.md
out to every harness directory (`.claude`, `.gemini`, `.cursor`, `.codex`,
`.agents`, etc.) so the staged skill that workers / agents read matches the
source. Auto-generated by `bun run build:skills`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Improve CI test coverage
* Stabilize live E2E harness
* Shard live E2E CI
* Cache live E2E CI dependencies
* Stabilize live E2E smoke CI
* Update generated live browser bundles
* Tighten live E2E smoke runtime
* Prevent live E2E smoke hangs
* Stabilize live E2E CI coverage
* Fix stale accept DOM cleanup
* Regenerate live browser outputs
The verbs/labels/icons were copied three ways: live-browser.js (ICONS + ACTIONS),
VISUAL_ACTIONS in live-event-validation.mjs, and the marketing demo. Collapse
them to one source, skill/scripts/live-vocabulary.mjs (LIVE_COMMANDS + derived
VISUAL_ACTIONS).
- live-event-validation.mjs imports VISUAL_ACTIONS from it.
- live-server.mjs serializes LIVE_COMMANDS into window.__IMPECCABLE_VOCAB__ when
it serves /live.js, next to the token/port. live-browser.js (served raw, can't
import at runtime) builds its ICONS + ACTIONS from that injected vocab instead
of an inline copy — byte-identical icons, zero behaviour change.
- site/components/LiveDemoPalette.astro imports the same module at build time, so
the demo and the real picker can no longer drift.
Adds a /live.js test asserting the injected vocab deep-equals the canonical list.
Harness skill dirs refreshed via build. (Pre-existing, unrelated: `bun run
build:site` fails on an htmlparser2 import in the CLI detector.)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* Fix live preview state for framework components
* Complete stateful live preview coverage
* Record Svelte manual validation
* Fix Svelte live mode adapter
* Fix live Steer apply flow
* Fix Svelte live variant refresh recovery
* Fix live exit bar teardown
* Consolidate Svelte live DeepSeek sweep
* Reconcile Svelte live browser after main rebase
* Fix live accept review regressions
* Fix carbonize column-zero indentation
* Fix live poll lease expiry flake
* Fix Svelte shader preview capture
* fix(home): command-wheel contrast, slop copy, line-length
Address P1/P2/P3 findings from /impeccable critique of the homepage:
- Command wheel (The Language): off-center command names floored at
~1.43:1 contrast were illegible (WCAG 1.4.3 fail) and hid most of the
23-command vocabulary. Raise the fisheye opacity floor 0.25 -> 0.62,
MIN_SCALE 0.35 -> 0.52, and lift the base color from --ks-text-muted to
--ks-text. Off-center now measures >=4.59:1; full list stays scannable
while gold + size + weight still carry focus.
- Slop section copy: rewrite all 7 discipline cards off the uniform
"No X. No Y. No Z." triad into varied cadence with positives, and lead
the section with what Impeccable does instead of the "Skills can't..."
negation pivot. Drops the en-dash joiners too.
- Line length: cap .downloads-rebuild-note (was unbounded, ~102ch) and
tighten the homepage .section-lead 68ch -> 62ch (rendered ~86 actual
chars/line).
The diagonal plinth ramp on the slop grid is intentionally kept per
design preference.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* refactor(home): de-warm and brighten the text ramp
Warmth now lives only in the gold accents and surfaces, not the type.
Body, headings, and the secondary tiers read crisp on lacquer instead of
mushing into the warm floor:
- --ks-champagne 84% .035 82 -> 91% .006 90 (headings/strong, now neutral;
token name kept for compatibility)
- --ks-text 81% .03 82 -> 88% .008 90 (body)
- --ks-text-muted / -faint / -mute-deep lifted and de-warmed to match
DESIGN.md frontmatter + prose synced to the new values.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* refactor(home): outlined testimonials + cleaner hero boundary
Testimonials:
- Flatten the double container: drop the t-plinth shelf wrapper (markup +
CSS); the marquee sits directly in the section and carries its inset.
- Outlined cards: no fill, 1px solid neutral border (oklch .64 0 0 / .22),
no dead drop-shadow. Removes the mushy gray-on-gray blend and the stacked
dotted-divider + gold-hairline chrome.
- Section has no background of its own (rides the body lacquer gradient) and
no top padding, so cards sit right under the hero divider.
Hero:
- Drop the bottom fade and the top nav scrim; the kintsugi art runs at full
strength. A 1px neutral border-bottom (matching the card border) marks the
testimonials boundary instead of a wash.
- "How it works" is the kit ghost link (white), not an outlined button.
Foundation/slop cards: lift the surface 9% -> 15% so they read as raised
specimen cards instead of vanishing into the ground.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* refactor(live): quieter, more refined picker chrome
Gold is reserved for the brand mark and the active control instead of
ringing every container. Applied to the homepage demo, /live-mode, and the
real injected picker (skill/scripts/live-browser.js, rebuilt into the
harness dirs):
- Container: neutral 1px hairline + tight neutral shadow (was a 1.5px gold
border + gold halo ring); radius 10px -> 8px.
- Active toggle: crisp graphite pill with gold text (was a murky kinpaku-dim
wash).
- Internal control borders (action pill / input / count): neutral hairline
(was a warm gold rule); configure-row controls share one 30px baseline.
- Pick outline: crisp 1.5px line, no soft gold glow ring; tighter radius.
- Demo browser chrome: small uniform neutral dots, neutral URL pill, slimmer
bar; frame edge neutral hairline + tighter shadow that registers on dark.
DESIGN.md "Live Mode Picker" spec + "Picker Is Brand Rule" updated.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* refactor(design): neutral default hairline (--ks-rule)
The default border/divider token was a warm gold hairline, used ~200x as
the site-wide default border — so every small label, pill, counter, card,
and divider carried warmth. Redefine it neutral so borders read clean;
gold stays where it signals.
- --ks-rule oklch(58% 0.065 82 / 0.32) -> oklch(78% 0 0 / 0.16)
- --ks-rule-strong (active/focus/brand borders) unchanged, still gold
- GitHub star pill: explicit near-white border (oklch 92% 0 0 / 0.18)
- DESIGN.md hairline mirror + prose synced
Verified across home, /design-system, and /docs.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(home): testimonials separator + visible star-pill border
- Move the dotted accent to the bottom of the testimonials (neutral dots)
as a deliberate separator into the slop section; drop the oversized
bottom padding to 1em so cards sit near the separator.
- Star-counter pill: solid oklch(80% 0 0) border. The previous near-white
at 0.32 alpha rendered as faded mid-gray on the near-black pill; a solid
light border reads as the intended white hairline.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* refactor(design): neutralize body text (--ks-text)
Drop the last bit of warm chroma from the body text token; it still read
slightly warm at 0.008 chroma.
--ks-text oklch(88% 0.008 90) -> oklch(88% 0 0) (pure neutral)
DESIGN.md mirror + prose synced.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* refactor(design): neutral text everywhere
Zero the residual warm chroma across the rest of the text ramp so no text
tier carries warmth (warmth lives only in gold accents + surfaces).
- --ks-champagne 91% .006 90 -> 91% 0 0
- --ks-text-muted 72% .01 90 -> 72% 0 0
- --ks-text-faint 62% .008 90 -> 62% 0 0
- --ks-text-mute-deep 52% .008 90 -> 52% 0 0
(--ks-text was already neutralized.) DESIGN.md mirror + prose synced.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* refactor(home): crisp, neutral Desloppification section
- Foundation card background: oklch(15% .004 95) -> oklch(15% 0 0) (neutral
graphite) so cards read crisp, not warm.
- Plinth hatch: kinpaku gold -> neutral (oklch 80% 0 0 / .07) on a neutral
base; the gold hatch was washing the section champagne.
- Remove the plinth bottom mask-fade so the pedestals end on a clean edge.
Gold stays only on the card icons as the accent.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* refactor(home): drop the homepage warm-token overrides
The homepage redefined --ks-rule, --ks-rule-strong, and --ks-muted to warm
values locally (an old "busier surfaces" tweak), so homepage borders and
secondary text stayed champagne even after the global de-warm. That's why
the Desloppification cards still read warm.
- Remove the --ks-rule / --ks-rule-strong overrides; inherit the global
tokens (neutral default border, gold strong/active border).
- Alias --ks-muted to the global --ks-text-muted (no divergent value);
legacy code still reads the --ks-muted name.
Result: all homepage borders + secondary text are neutral; gold stays on
accents (icons, mark, CTAs, active/focus).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* refactor(design): canonical code tokens (inline + block)
Code styling was all over the place: homepage inline code was gold-on-gold,
the slop CLI was a one-off gold-on-raised-lacquer, downloads used a separate
--card-cmd-* set, docs used yet another. Add one shared token set and point
the canonical surfaces at it.
New :root tokens:
- --ks-code-fg / --ks-code-bg / --ks-code-radius (inline: neutral chip)
- --ks-code-block-fg / -bg / -border / -radius (block/CLI: lacquer terminal)
- --ks-code-cmd (code that's a command link)
Migrated: homepage inline code (was gold -> neutral chip), slop-teaser-cli
(the "weird color" -> neutral terminal), downloads-cmd, and the docs inline +
fenced-block rules (now the token source of truth; block text also neutralized).
Remaining pages (designing, changelog/faq, detector, case studies) swept next.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* refactor(design): sweep remaining pages onto code tokens
Point the rest of the site's code rules at the shared code tokens so inline
code and blocks are consistent everywhere:
- Inline code (designing, changelog, faq): gold -> neutral chip
(--ks-code-fg / --ks-code-bg).
- Detector rule pills + table cells: code text -> --ks-code-fg.
- Neon-mirai case-study code block -> --ks-code-block-* tokens.
Command tags (the gold /command pills: spread-flow-cmd, docs-flow-cmd,
designing-phase-cmd, why-ci-cmd, etc.) are intentionally left as their own
interactive category, not generic code.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* refactor(home): polish "The Language" section
- Command tags (/polish, /adapt): gold command text on a neutral code chip
(--ks-code-cmd / --ks-code-bg), dropping the muddy gold-tint border.
- Commands panel kept as the solid oklch(0.17 0 0) panel (no border).
- Demo preview cleaned up to a single framed split: strip the grid ::before,
the gold-grid/radial-glow container background, and the inner drop-shadow;
before-half inherits the panel, after-half is near-black, with one thin
neutral border on the demo itself (caption sits outside it).
- Periodic table: crisp flat neutral graphite tiles. Removed the JS-inlined
category bg (var(--cat-*-bg)) + 1.5px colored border + hover drop-shadow,
the gold-leaf ::before texture, the ::after accent line, the inset box-shadow,
and the gold hover glow. Now a 1px neutral border, white symbols, readable
neutral names, and a clean neutral-border hover with no shadow.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* refactor(design): roomier inline-code padding
Inline code chips were tight top/bottom (the homepage one was only 0.05em).
Add a --ks-code-pad token (0.3em 0.5em) and point every inline-code rule at
it so the chips have consistent breathing room.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* refactor(home): drop non-steering commands from the command palette
impeccable, init, extract, document, and live are setup/management commands,
not steering verbs. Filter them out of the palette (fisheye + mobile carousel)
via a shared PALETTE_EXCLUDED set. They stay in the periodic table, which is
rendered separately by framework-viz.js.
Palette: 23 -> 18 commands.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(designing): flatten the pre-ship nested box
The pre-ship cards were a box-in-box: a legacy .designing-polish-grid panel
(cream bg + L/R/B border + padding, from docs-visuals.css) wrapping cards that
already have their own border + fill. Override the grid to a plain transparent
layout so the three cards are the only surface.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(designing): remove step counter + flatten design-debt boxes
- Drop the cryptic "03 · 04" pre-ship step counter (.designing-polish-band-meta)
and tighten the band to a single bottom hairline.
- Design-debt: flatten the box-in-box (bento plinth > tile > stage). The
.designing-maintain-stage no longer adds its own border + fill; the demo
sits directly in the bento tile.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(designing): neutralize code/terminal/panel surfaces
The terminal block, surface-cmd chips, command pills, live-frame, and other
dark panels used a slightly-warm dark fill (oklch 1X% 0.006 95). Drop the warm
chroma so they read neutral like the rest of the de-warmed site; the page
ground + deep surfaces stay lacquer-warm.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(designing): neutralize inline code + live-mock picker chrome
- Inline code: the phase-sub and avoid-title code were still gold; point them
at --ks-code-fg so all inline code reads neutral (gold stays only on command
*links*).
- docs-viz-live mock: bring the duplicated picker chrome in line with the
refactored neutral treatment — neutral 1px container borders (no gold halo),
neutral active "Pick" pill (was the kinpaku-dim wash), crisp pick outline
(no glow), tighter radii.
- CTAs (SEND ME ONE, Accept): pale-cream kinpaku-pale -> solid kinpaku gold.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(designing): flatten lanes + avoid sections
- Brand/Product lane mock cards: drop the inner border+fill box; the mock sits
directly in the bento tile, separated by a top hairline (no plinth>tile>mock
nesting).
- "What to avoid" list: flatten the boxed list cards into a clean divided list
(hairline separators, no per-item border/fill).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(designing): clean up the Brand/Product lanes
- Drop the bento plinth (0.17 fill + 8px gutter that drew the weird gutter
"borders") and the tile fill; the two lanes sit on the page split by a single
center hairline.
- Brand mock title used the pinstripe display face at 1.6rem (reads broken at
that size, the "champagne text"); switch it to the clean body face so it
matches the product mock title.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* chore(site): update GitHub star count to 31k
31,188 stars as of now; header pill + aria-label were stale at 30k.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* Add Neo Kinpaku light mode across the site.
Wire theme persistence and a header toggle, then layer light-mode overrides for docs viz contrast, command demos, live-mode pathway cards, and the designing/home surfaces.
Co-authored-by: Cursor <cursoragent@cursor.com>
* fix(designing): replace em dashes flagged by prose validator
Brand/Product lane copy used em dashes ("the deliverable —", "the task —");
swap for colons per STYLE.md so the Cloudflare build's validateProse passes.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(designing): address Cursor bugbot nits
- Fold the duplicate .designing-avoid { gap: 0 } override into the original
rule (the gap: 18px was dead code).
- Drop the leftover el.style.boxShadow = 'none' in the periodic-tile deactivate
handler — activate no longer sets a box-shadow, so this only left a dead
inline none that could suppress a future CSS shadow.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Codex auto-discovers subagents bundled inside an installed skill's own
agents/ folder, so the separate .codex/agents/*.toml sidecar was redundant.
- cli: remove installCodexAgents/isCodexLikely and their install/update calls
- context.mjs: remove the CODEX_AGENT_MISSING self-heal directive
- build: drop codex agentFormat so no top-level .codex/agents is emitted; the
nested in-skill .toml bundling is the whole delivery
- remove the tracked .codex/agents/*.toml and the gitignore exception
- docs + build.test.js updated for the nested layout
- CLI patch version bump; skill version unchanged
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>