-
Notifications
You must be signed in to change notification settings - Fork 7
Release Notes v3
Released: 2026-05-28
Status: Stable
GitHub Release: https://github.com/Laith0003/ux-skill/releases/tag/v3.0.0
Tag: v3.0.0
ux-skill v3.0 makes brand specs training data, not templates. A 7-axis synthesizer compiles a novel design language per brief. A local decisions ledger drives the recommender's re-rank. Closed feedback loop. Offline. Deterministic. No LLM. 223 tests pass.
- New module
engine.synthesizer - 7 continuous axes: warmth · contrast · density · geometry · formality · motion · type_personality
- Same brief → same axes → same output. Reproducible across machines, filesystems, Python versions.
- See Synthesizer-7-axes for the full math.
-
strict_brand— 100% named brand tokens (fastest path, 0.4ms median) -
brand_anchor— 70% named + 30% axis-adapted siblings -
pure_synthesis— 8 axis-matching exemplars distilled into a novel design language - See Three-Modes-Explained for use-case decisions.
- New module
engine.synthesizer.interactions - Explicit conflict resolution between competing axes
- Documented functions:
spacing_base_for,radius_base_px_for,motion_timing_for,accent_register_for - Real-world archetypes pinned (Bloomberg / luxury / NYT / Glossier)
- See Axis-Interaction-Matrix for the full table.
- New module
engine.decisions - Schema locked at
_v: 1. Column names are a public contract. - File locations:
.ux/decisions.jsonl(project) +~/.uxskill/decisions.jsonl(user) - Privacy:
UXSKILL_NO_LOG=1env var +--no-logflag - Recommender re-ranks candidates by past wins in same
(industry, ui_type)bucket - Cold-start safe (≥3 priors required)
- Only counts
lint_score >= 80 AND user_accepted = truedecisions - See Decisions-Ledger-and-Learning for schema + API.
- New module
engine.evolve - New slash command
/ux-evolve - Auto-iterates lint → polish → re-lint up to 5 rounds
- Stops on target_hit (≥90) / plateau (delta < 5) / max_rounds / gate_failed
- Quality gate at 65 — below that, refuses to ship unless
--force - 6 idempotent polish passes (strip inline styles, normalize spacing, replace generic CTAs, swap placeholder URLs, strip Lorem, fontweight numeric)
- See Evolve-Loop-and-Quality-Gate.
- New module
engine.layout - 7 primitives: stack / cluster / grid / sidebar / cover / frame / split
- All use
auto-fit minmax(min(N, 100%), 1fr)+ container queries - Zero size-based
@mediaqueries required - Broken layouts cannot be emitted
- New module
engine.typography - Modular scale ratio picked from contrast (1.200 / 1.250 / 1.333)
- 9-step size ladder caption → hero
- Weight curves from
type_personality + contrast - Tracking + line-heights from
formality + density - CSS emission via
scale.to_css()
- New module
engine.evaluator - 7 axes: linter_score / hierarchy / layout_coherence / spacing / readability / tone_match / uniqueness
- All deterministic
- Composite = mean of 7 axes
-
tone_matchdecoupled from synthesizer (uses raw brief tags, not derived axes)
-
engine.linter.compute_score()— severity-weighted penalty per file -
uxskill lint --score-onlyfor shell pipes / CI -
LintReport.scorefield added (purely additive, v2 callers unaffected)
- New module
engine.decisions.stats_html - Writes
.ux/stats.html— self-contained single-file dashboard - Shows: total decisions, lint score median, by_command, by_mode, top_brands, by_industry, by_ui_type, accept rate
- No telemetry. No global aggregate. Your install's local view.
-
ux_synthesize— emit a synthesized design language over stdio -
ux_decisions_query— filter the local decisions ledger -
ux_decisions_stats— aggregate stats over local ledger
v2 imports still work. New v3 imports:
from engine import synthesize, compute_axes
from engine import synthesize_layout, compute_type_scale
from engine import evaluate, evolve, THRESHOLDAll v2 commands still work. New v3 commands:
uxskill synthesize ...
uxskill evolve <file>
uxskill stats --decisions
uxskill stats --html
uxskill lint --score-only
uxskill lint --no-log- 223 tests total (was 134 in v2.0)
- New test files:
test_decisions,test_synthesizer,test_layout,test_typography,test_evaluator,test_evolve,test_v3_fixes - Existing v2 tests still pass
| Rejected idea | Why |
|---|---|
| "Burn the catalogue for infinite space" | Kept all 1,182 entries; achieved infinity by making COMBINATIONS continuous |
| "LLM-judged subjective aesthetic axes" | Replaced with deterministic heuristics + cosine distance |
| "Multi-candidate generation + genetic mutation" | Pure research project; replaced with single-candidate + /ux-evolve polish loop |
| "Rename commands to generate:ui / mutate:ui" | Kept all 22; added 1 new (/ux-evolve) |
| "Anthropic-fine-tuned model in the engine" | Kept zero LLM calls in the engine |
| Metric | Count |
|---|---|
| Slash commands | 23 |
| Sub-agents | 5 |
| MCP tools | 18 |
| Structured entries | 1,182 |
| Anti-pattern rules | 145 |
| Brand DESIGN specs | 160 |
| IDEs supported | 17 |
| Locale homepages + READMEs | 17 |
| Tests passing | 223 |
| LLM calls in engine | 0 |
| Telemetry events | 0 |
These came from a deliberate code review by ChatGPT (T) before v3.0 stable cut:
Before: pick_exemplars_by_axes() sorted by axis distance only. Ties broken by filesystem order (load_brands() output) — not deterministic across machines.
Fix: Added secondary sort key on brand id (alphabetical). Now reproducible.
Before: When density and formality competed for the spacing token (dense + corporate vs airy + corporate), whichever axis the primitive consulted first won silently.
Fix: New engine.synthesizer.interactions module with 4 documented conflict-resolution functions. DOCUMENTED_INTERACTIONS tuple locks the public contract.
Before: score_tone_match compared synth_axes against derived brief_axes. Both came from the same compute_axes() function. The synthesizer was grading its own homework.
Fix: Added brief_tags parameter to score_tone_match. Uses an independent expectation table mapping raw tone tags (warm / bold / minimal) to expected axis ranges. Independent ground truth.
Before: v2.1 alpha shipped the ledger module but the recommender never consumed it. Decisions logged but no behavior change.
Fix: Added _rerank_from_decisions() and _rerank_brands_from_decisions(). Wired into 5 ranking lanes (_lane_style, _lane_palette, _lane_type, _lane_motion, _lane_brands). Cold-start safe at ≥3 priors. The intelligence loop is now actually closed.
See Migration-v2-to-v3 for the full migration guide.
TL;DR for most users: zero effort. v3 is additive. Set UXSKILL_NO_LOG=1 if you want pure v2 ranking behavior.
pip install uxskill # PyPI (Python)
npx uxskill init # npm (npx wrapper)
# OR for Claude Code:
/plugin marketplace add Laith0003/ux-skill
/plugin install ux@ux-skill- Full launch blog post
- Brand specs are training data, not templates
- A deterministic design engine that learns offline
- What closed-loop actually means
- The 7 axes explained
- 5-minute quickstart
- vs UI/UX Pro Max — honest scorecard
Tentative scope, subject to change:
- Fix 2 documented linter rule bugs (heading-skip alternative 3, scroll-passive lookahead) — found during the dogfood landing build
- Rewrite
scripts/i18n-strings.jsonagainst the new homepage structure (89 of 111 keys are no-op against the new layout) - Public
/decisions.htmlpage once installs accrue ≥100 logged decisions globally (currently kept local-only) - Round 7 anti-patterns 145 → 170
- Round 7 brand specs 160 → 200
- Expand wiki to 15 pages
Pin to v3.0.0 if you want stability:
pip install uxskill==3.0.0MIT. Use it. Fork it. No attribution required (but appreciated).
- ChatGPT (T) — sharp code review before v3.0 stable cut. The 4 critical bug categories above came directly from T's analysis.
- Claude Code — the canonical IDE we dogfood against.
- 160 brands in the catalogue whose published design systems became training data for the synthesizer.
- Bricolage Grotesque — the variable font used in the wordmark + display copy. Open source. Excellent.
- v3-The-Brain — architectural shift in one page
- Synthesizer-7-axes
- Axis-Interaction-Matrix
- Three-Modes-Explained
- Decisions-Ledger-and-Learning
- Evolve-Loop-and-Quality-Gate
- Migration-v2-to-v3