aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-06-08 08:56:47 -0500
committerCraig Jennings <c@cjennings.net>2026-06-08 08:57:05 -0500
commit7f57c6467054f6762a40b683d6585ee0a2b5527c (patch)
treed787bae9ba1c958b00b0f31cd868f252b4ddcaeb
parent3e8d5651a3fddcf4afccd46a382ab12d915bbd8c (diff)
downloaddotemacs-7f57c6467054f6762a40b683d6585ee0a2b5527c.tar.gz
dotemacs-7f57c6467054f6762a40b683d6585ee0a2b5527c.zip
refactor(theme-studio): rename theme-selector to theme-studio
The tool authors themes from scratch -- palette, faces across every tier, live preview, export to a loadable deftheme. It never selects among existing themes, so "selector" mis-described it. Renamed the directory, the generated HTML and its title, the design spec, and every reference in the code, README, tests, and todo. No behavior change.
-rw-r--r--docs/design/theme-studio-package-faces-spec.org (renamed from docs/design/theme-selector-package-faces-spec.org)18
-rw-r--r--scripts/theme-studio/README.md (renamed from scripts/theme-selector/README.md)14
-rw-r--r--scripts/theme-studio/build-inventory.el (renamed from scripts/theme-selector/build-inventory.el)6
-rw-r--r--scripts/theme-studio/build-theme.el (renamed from scripts/theme-selector/build-theme.el)14
-rw-r--r--scripts/theme-studio/generate.py (renamed from scripts/theme-selector/generate.py)4
-rw-r--r--scripts/theme-studio/package-inventory.json (renamed from scripts/theme-selector/package-inventory.json)0
-rw-r--r--scripts/theme-studio/samples.py (renamed from scripts/theme-selector/samples.py)0
-rw-r--r--scripts/theme-studio/theme-studio.html (renamed from scripts/theme-selector/theme-selector.html)2
-rw-r--r--tests/test-build-theme.el8
-rw-r--r--todo.org26
10 files changed, 46 insertions, 46 deletions
diff --git a/docs/design/theme-selector-package-faces-spec.org b/docs/design/theme-studio-package-faces-spec.org
index def6a430f..7f00b3279 100644
--- a/docs/design/theme-selector-package-faces-spec.org
+++ b/docs/design/theme-studio-package-faces-spec.org
@@ -1,11 +1,11 @@
-#+TITLE: theme-selector — package faces (tier 3), starting with org-mode
+#+TITLE: theme-studio — package faces (tier 3), starting with org-mode
#+AUTHOR: Craig Jennings
#+DATE: 2026-06-07
* Status
Spec / Craig's first-round answers folded in (2026-06-07). Proposes a third tier
-for the theme-selector (scripts/theme-selector/) that lets a theme colorize
+for the theme-studio (scripts/theme-studio/) that lets a theme colorize
package-specific faces, built one application at a time. v1 apps: org-mode
(incl. org-agenda), magit, elfeed. Codex review incorporated (2026-06-07): added
implementation phases, acceptance criteria, the package-face inventory source
@@ -18,7 +18,7 @@ Implementation tasks live in =todo.org=.
* Background — the three tiers
-The theme-selector already models two tiers of faces:
+The theme-studio already models two tiers of faces:
1. *Syntax* — the font-lock / tree-sitter categories (keyword, string, type,
comment, etc.), in the "code/color assignments" table.
@@ -374,7 +374,7 @@ inherited value.
previews, the fallback visibly labeled as generic.
- A palette color update propagates to package faces the same way it does to
syntax / ui faces.
-- =python3 scripts/theme-selector/generate.py= rebuilds =theme-selector.html=.
+- =python3 scripts/theme-studio/generate.py= rebuilds =theme-studio.html=.
- README documents the =packages= schema, inheritance, and the inventory source.
* Extensibility (adding the next app)
@@ -482,9 +482,9 @@ Decided (Craig, 2026-06-08): after tier 3, as its own task.
* Files touched
-- =scripts/theme-selector/generate.py= — the section, =APPS= data, the package
+- =scripts/theme-studio/generate.py= — the section, =APPS= data, the package
face table, =renderOrgPreview()=, export/import of =packages=.
-- =scripts/theme-selector/theme-selector.html= — regenerated.
+- =scripts/theme-studio/theme-studio.html= — regenerated.
- (later) the =theme.json= -> =dupre-*.el= converter (Elisp) — consumes
=packages=.
@@ -531,7 +531,7 @@ generalized face-control helper, package style kept inside the package object,
growth was his explicit call on the curated set.
- *Artifacts:* This spec. The converter language (Elisp) confirmed by Craig.
Note: Craig referenced a Codex spec review, but no
- =theme-selector-package-faces-review.org= (or any =*-review.org=) exists in the
+ =theme-studio-package-faces-review.org= (or any =*-review.org=) exists in the
repo — the review file could not be found, so only the author-side cj-comment
fold was done; the Codex review remains to be processed when its file is
located.
@@ -544,7 +544,7 @@ generalized face-control helper, package style kept inside the package object,
- *Why:* The direction is coherent and the first-round decisions are folded in,
but v1 now depends on behavior that is not yet implementable from the current
static generator without a defined inventory and state/export contract.
-- *Artifacts:* [[file:theme-selector-package-faces-spec-review.org][theme-selector-package-faces-spec-review.org]]
+- *Artifacts:* [[file:theme-studio-package-faces-spec-review.org][theme-studio-package-faces-spec-review.org]]
** 2026-06-07 Sun @ 18:28:02 -0500 — Claude Code (emacs-d) — responder
- *What:* Ran spec-response against the Codex review. Added Implementation
@@ -583,4 +583,4 @@ generalized face-control helper, package style kept inside the package object,
- *Why:* Craig asked to fold height in — it matters for org headings above all.
Font *family* stays in =modules/font-config.el=; the theme owns relative size
and the fixed-pitch inherit relationships only.
-- *Artifacts:* This spec; =scripts/theme-selector/generate.py= phase-1 plumbing.
+- *Artifacts:* This spec; =scripts/theme-studio/generate.py= phase-1 plumbing.
diff --git a/scripts/theme-selector/README.md b/scripts/theme-studio/README.md
index 8f63383c1..620340396 100644
--- a/scripts/theme-selector/README.md
+++ b/scripts/theme-studio/README.md
@@ -1,4 +1,4 @@
-# theme-selector
+# theme-studio
A self-contained tool for designing Emacs color themes by eye. One generated
HTML page drives the whole theme: a palette, the syntax (font-lock /
@@ -11,13 +11,13 @@ readouts, then export a `theme.json` that a build step turns into
## Run
```bash
-python3 generate.py # writes theme-selector.html beside this script
+python3 generate.py # writes theme-studio.html beside this script
```
Then open it in Chrome (Firefox had color-rendering flakiness during design):
```bash
-WAYLAND_DISPLAY=wayland-1 google-chrome-stable theme-selector.html
+WAYLAND_DISPLAY=wayland-1 google-chrome-stable theme-studio.html
```
During color work, disable Hyprland inactive-window dimming so colors read true:
@@ -37,7 +37,7 @@ hyprctl keyword decoration:dim_inactive false
faces it defines (see Package faces below). A committed data artifact.
- `build-inventory.el` — refreshes `package-inventory.json` from a running
Emacs.
-- `theme-selector.html` — generated output. Regenerate; don't hand-edit.
+- `theme-studio.html` — generated output. Regenerate; don't hand-edit.
## What it captures
@@ -95,7 +95,7 @@ The reachable packages come from `package-inventory.json`. Regenerate it from a
running Emacs (so it reflects what's actually installed), then rebuild the HTML:
```bash
-emacsclient -e '(load "/home/cjennings/.emacs.d/scripts/theme-selector/build-inventory.el")'
+emacsclient -e '(load "/home/cjennings/.emacs.d/scripts/theme-studio/build-inventory.el")'
python3 generate.py
```
@@ -149,8 +149,8 @@ the UI faces passed through, and the package faces with `:inherit`/`:height`
and weight/slant written.
```bash
-emacs --batch -l scripts/theme-selector/build-theme.el \
- --eval '(build-theme/convert-file "scripts/theme-selector/dupre-revised.json" "themes")'
+emacs --batch -l scripts/theme-studio/build-theme.el \
+ --eval '(build-theme/convert-file "scripts/theme-studio/dupre-revised.json" "themes")'
```
Output is a flat generated deftheme, not the palette/faces/theme trio the
diff --git a/scripts/theme-selector/build-inventory.el b/scripts/theme-studio/build-inventory.el
index 52e14baa1..04d821453 100644
--- a/scripts/theme-selector/build-inventory.el
+++ b/scripts/theme-studio/build-inventory.el
@@ -1,10 +1,10 @@
-;;; build-inventory.el --- emit package->faces inventory for theme-selector -*- lexical-binding: t -*-
+;;; build-inventory.el --- emit package->faces inventory for theme-studio -*- lexical-binding: t -*-
;;; Commentary:
;; Loaded into a running Emacs (emacsclient -e '(load ".../build-inventory.el")')
;; to write package-inventory.json next to itself: a JSON object mapping each
;; installed (elpa/straight) package to the faces it defines, grouped by the
;; package that owns the face's definition file. Built-in faces are skipped.
-;; generate.py embeds the JSON so the theme-selector dropdown can reach every
+;; generate.py embeds the JSON so the theme-studio dropdown can reach every
;; installed package (tier-3 phase 6, the "theme every package" path).
;;; Code:
@@ -23,7 +23,7 @@
(with-temp-file (expand-file-name
"package-inventory.json"
(file-name-directory (or load-file-name buffer-file-name
- "~/.emacs.d/scripts/theme-selector/")))
+ "~/.emacs.d/scripts/theme-studio/")))
(let ((json-encoding-pretty-print t))
(insert (json-encode al) "\n")))))
diff --git a/scripts/theme-selector/build-theme.el b/scripts/theme-studio/build-theme.el
index fe080c0d1..c869dea18 100644
--- a/scripts/theme-selector/build-theme.el
+++ b/scripts/theme-studio/build-theme.el
@@ -1,12 +1,12 @@
-;;; build-theme.el --- Convert a theme-selector theme.json into a deftheme -*- lexical-binding: t -*-
+;;; build-theme.el --- Convert a theme-studio theme.json into a deftheme -*- lexical-binding: t -*-
;; Author: Craig Jennings <c@cjennings.net>
;;; Commentary:
-;; The last link in the theme-selector pipeline: turn a theme.json exported by
-;; the tool (see scripts/theme-selector/README.md and
-;; docs/design/theme-selector-package-faces-spec.org) into a single,
+;; The last link in the theme-studio pipeline: turn a theme.json exported by
+;; the tool (see scripts/theme-studio/README.md and
+;; docs/design/theme-studio-package-faces-spec.org) into a single,
;; self-contained, loadable Emacs deftheme written to themes/<name>-theme.el.
;;
;; Four tiers come out of the JSON:
@@ -190,12 +190,12 @@ the font-lock faces in `build-theme/--syntax-face-map'."
(defun build-theme/--render (name specs)
"Render a deftheme file body for theme NAME from face SPECS, as a string."
(concat
- (format ";;; %s-theme.el --- Generated by theme-selector -*- lexical-binding: t -*-\n" name)
+ (format ";;; %s-theme.el --- Generated by theme-studio -*- lexical-binding: t -*-\n" name)
"\n;;; Commentary:\n"
- (format ";; Generated from %s.json by scripts/theme-selector/build-theme.el.\n" name)
+ (format ";; Generated from %s.json by scripts/theme-studio/build-theme.el.\n" name)
";; Do not hand-edit; re-run the converter.\n"
"\n;;; Code:\n\n"
- (format "(deftheme %s\n \"Generated by theme-selector.\")\n\n" name)
+ (format "(deftheme %s\n \"Generated by theme-studio.\")\n\n" name)
(format "(custom-theme-set-faces\n '%s\n" name)
;; Each spec is quoted: custom-theme-set-faces is a function, so an
;; unquoted (face ((t ...))) would be evaluated as a call. Specs hold
diff --git a/scripts/theme-selector/generate.py b/scripts/theme-studio/generate.py
index 8e76c1740..405ce150a 100644
--- a/scripts/theme-selector/generate.py
+++ b/scripts/theme-studio/generate.py
@@ -369,7 +369,7 @@ if os.path.exists(_inv_path):
APPS[_pkg]={"label":_pkg,"preview":"generic","faces":[
[f,(f[len(_pkg)+1:] if f.startswith(_pkg+"-") else f).replace("-face","").replace("-"," "),{}]
for f in _INV[_pkg]]}
-HTML = """<!doctype html><meta charset=utf-8><title>theme-selector</title>
+HTML = """<!doctype html><meta charset=utf-8><title>theme-studio</title>
<style>
body{background:#0d0b0a;color:#cdced1;font:15px/1.55 monospace;margin:20px}
h1{font-size:22px;font-weight:normal;color:#e8bd30;margin:26px 0 10px;border-bottom:1px solid #252321;padding-bottom:6px}
@@ -1111,6 +1111,6 @@ HTML=(HTML.replace("SAMPLES_J",json.dumps(SAMPLES))
.replace("PALETTE_J",json.dumps(PALETTE)).replace("CATS_J",json.dumps(CATS))
.replace("UIFACES_J",json.dumps(UI_FACES)).replace("UIMAP_J",json.dumps(UIMAP)).replace("APPS_J",json.dumps(APPS))
.replace("BOLD_J",json.dumps(BOLD)).replace("MAP_J",json.dumps(MAP)))
-OUT=os.path.join(HERE,'theme-selector.html')
+OUT=os.path.join(HERE,'theme-studio.html')
open(OUT,"w").write(HTML)
print("wrote",OUT)
diff --git a/scripts/theme-selector/package-inventory.json b/scripts/theme-studio/package-inventory.json
index 18fd7aa25..18fd7aa25 100644
--- a/scripts/theme-selector/package-inventory.json
+++ b/scripts/theme-studio/package-inventory.json
diff --git a/scripts/theme-selector/samples.py b/scripts/theme-studio/samples.py
index e487cc5e9..e487cc5e9 100644
--- a/scripts/theme-selector/samples.py
+++ b/scripts/theme-studio/samples.py
diff --git a/scripts/theme-selector/theme-selector.html b/scripts/theme-studio/theme-studio.html
index 30279c745..61466d420 100644
--- a/scripts/theme-selector/theme-selector.html
+++ b/scripts/theme-studio/theme-studio.html
@@ -1,4 +1,4 @@
-<!doctype html><meta charset=utf-8><title>theme-selector</title>
+<!doctype html><meta charset=utf-8><title>theme-studio</title>
<style>
body{background:#0d0b0a;color:#cdced1;font:15px/1.55 monospace;margin:20px}
h1{font-size:22px;font-weight:normal;color:#e8bd30;margin:26px 0 10px;border-bottom:1px solid #252321;padding-bottom:6px}
diff --git a/tests/test-build-theme.el b/tests/test-build-theme.el
index 954e95425..f74b94173 100644
--- a/tests/test-build-theme.el
+++ b/tests/test-build-theme.el
@@ -2,8 +2,8 @@
;;; Commentary:
-;; ERT tests for scripts/theme-selector/build-theme.el, the converter that
-;; turns a theme.json exported by the theme-selector into a loadable Emacs
+;; ERT tests for scripts/theme-studio/build-theme.el, the converter that
+;; turns a theme.json exported by the theme-studio into a loadable Emacs
;; deftheme file. This is the correctness-sensitive end of the pipeline, so
;; it is covered Normal / Boundary / Error per category.
@@ -18,7 +18,7 @@
(eval-and-compile
(add-to-list 'load-path
(expand-file-name
- "../scripts/theme-selector"
+ "../scripts/theme-studio"
(file-name-directory
(or load-file-name
(bound-and-true-p byte-compile-current-file)
@@ -55,7 +55,7 @@
"A self-contained theme.json exercising every tier: default, syntax (bold +
italic + the unmappable dec key), UI, and packages (a plain face, an
inherit+height face, and a cleared face). Owned by the test so it can't drift
-the way Craig's downloaded exports under scripts/theme-selector/ can.")
+the way Craig's downloaded exports under scripts/theme-studio/ can.")
(defun test-build-theme--write-fixture (dir)
"Write the fixture JSON into DIR and return its path."
diff --git a/todo.org b/todo.org
index 590885341..642a69e39 100644
--- a/todo.org
+++ b/todo.org
@@ -44,18 +44,18 @@ Tags are additive. For example, a small wrong-behavior fix can be
** TODO [#C] Evaluate jamescherti essential-emacs-packages list :packages:research:
Review [[https://www.jamescherti.com/essential-emacs-packages/][James Cherti's essential Emacs packages]] for anything worth installing. Cross-check each candidate against what is already in the config (=modules/= + =init.el=), skip the ones already present, and shortlist the genuinely new ones with a one-line rationale. Future-installation research, not a commitment to install.
-** DONE [#B] theme-selector comprehensive previews (org/magit/elfeed/ghostel/mu4e/dashboard) :feature:theme:theme-selector:
+** DONE [#B] theme-studio comprehensive previews (org/magit/elfeed/ghostel/mu4e/dashboard) :feature:theme:theme-studio:
CLOSED: [2026-06-08 Mon]
Expanded the bespoke previews to near-complete face coverage and added three new ones. org now exercises 83/88 faces (document + agenda; the 5 skipped are non-visual: org-hide, org-indent, org-clock-overlay, org-default, org-date-selected). magit 97/98 (status buffer + blame/reflog/sequence/bisect/signature sampler rows). elfeed 13/13. New bespoke previews: ghostel 19/19 (mock terminal, 16 ANSI colors + default + fake cursor), mu4e 37/37 (curated face list, not in the generated inventory; headers list + message view + compose), dashboard 8/8. So clicking a face row flashes a real preview element for nearly every face. Originally filed as just the org preview.
-** DONE [#A] theme-selector theme.json -> dupre-*.el converter :feature:theme:theme-selector:
+** DONE [#A] theme-studio theme.json -> dupre-*.el converter :feature:theme:theme-studio:
CLOSED: [2026-06-08 Mon]
-Built as scripts/theme-selector/build-theme.el (sibling to build-inventory.el), emitting a single self-contained themes/<name>-theme.el deftheme (not the palette/faces/theme trio — a theme.json carries resolved per-face hex, not dupre's semantic layer). All four tiers convert: default from assignments.bg/.p, syntax categories -> font-lock/tree-sitter faces with bold/italic sets, UI passthrough, packages with :inherit/:height/weight/slant. 20 ERT tests in tests/test-build-theme.el (Normal/Boundary/Error + an end-to-end load + a WCAG-AA assertion on the round-tripped result). One mapping limitation documented: the dec (decorator) key has no independent Emacs face (Emacs renders decorators with font-lock-type-face, which ty owns), so dec is omitted and decorators follow the type color.
+Built as scripts/theme-studio/build-theme.el (sibling to build-inventory.el), emitting a single self-contained themes/<name>-theme.el deftheme (not the palette/faces/theme trio — a theme.json carries resolved per-face hex, not dupre's semantic layer). All four tiers convert: default from assignments.bg/.p, syntax categories -> font-lock/tree-sitter faces with bold/italic sets, UI passthrough, packages with :inherit/:height/weight/slant. 20 ERT tests in tests/test-build-theme.el (Normal/Boundary/Error + an end-to-end load + a WCAG-AA assertion on the round-tripped result). One mapping limitation documented: the dec (decorator) key has no independent Emacs face (Emacs renders decorators with font-lock-type-face, which ty owns), so dec is omitted and decorators follow the type color.
-The last link in the pipeline: turn a theme.json exported by the theme-selector into a real loadable Emacs theme. Elisp (per Craig), TDD — this is the correctness-sensitive piece.
+The last link in the pipeline: turn a theme.json exported by the theme-studio into a real loadable Emacs theme. Elisp (per Craig), TDD — this is the correctness-sensitive piece.
Inputs (all on disk; no chat history needed):
-- theme.json contract: =scripts/theme-selector/README.md= (theme.json section) and =docs/design/theme-selector-package-faces-spec.org= (State and export policy, Relative height, Inheritance).
+- theme.json contract: =scripts/theme-studio/README.md= (theme.json section) and =docs/design/theme-studio-package-faces-spec.org= (State and export policy, Relative height, Inheritance).
- Reference face layout: existing =themes/dupre-palette.el= + =themes/dupre-faces.el= + =themes/dupre-theme.el=, and =tests/test-dupre-theme.el= (WCAG-contrast helper to reuse).
- Conventions: =.claude/rules/elisp.md=, =.claude/rules/elisp-testing.md=.
@@ -66,7 +66,7 @@ Scope:
4. Package faces: =packages= -> each face spec, writing =:inherit PARENT= for inherited faces + only the overridden attrs, =:height= when != 1.0, weight/slant.
5. Emit a deftheme file (or palette+faces+theme trio mirroring dupre's layout).
-TDD targets: old-JSON (no packages) loads; every category maps; round-trip of fg/bg/bold/italic/inherit/height into valid face specs; WCAG-contrast assertion on the result. Decide whether the converter lives under =scripts/theme-selector/= (emits to =themes/=) or =themes/=.
+TDD targets: old-JSON (no packages) loads; every category maps; round-trip of fg/bg/bold/italic/inherit/height into valid face specs; WCAG-contrast assertion on the result. Decide whether the converter lives under =scripts/theme-studio/= (emits to =themes/=) or =themes/=.
** TODO [#B] Dupre diff-changed / diff-refine-changed legibility :bug:dupre:
Surfaced 2026-06-07 from a pearl session designing its modified-ticket indicator (pearl marks a changed field by inheriting =diff-changed=). dupre's =diff-refine-changed= is bright gold (#ffd700) under near-white text (#f0fef0) -- WCAG contrast ~1.35, unreadable as a plain background. It only looks fine inside diff-mode because diff-mode overlays its own dark foreground. =diff-changed= (#875f00 amber) is ~5.49, readable but off the modus model. Every modus variant keeps both faces legible (contrast 9-16) by pairing a dark low-saturation background with a hue-matched foreground.
@@ -90,9 +90,9 @@ A full =make test= run (2026-06-07) is green across 516 of 517 files; the only f
Build a new theme (working name "dupre-clear", final name TBD) that takes dupre's color identity and rebuilds it Prot's way: contrast-first, targeting WCAG AAA (~7:1 on the ground), where the in-progress dupre revision is mood/depth-first and lands at AA. Same hues (dupre blue, emerald, gold, terracotta, regal violet, mint) brightened to clear the AAA floor; same modus-style role mapping (blue keywords bold, gold functions, violet types, emerald strings, terracotta constants, silver default, warm-grey comments, metallic greys, navy + regal fills). Build the dupre revision first; this reuses its hue choices as the starting point.
Full design + methodology + starting palette + open questions in the spec: [[file:docs/design/dupre-clear-theme.org][docs/design/dupre-clear-theme.org]]. Key prerequisite/context: the dupre-redesign entry in =.ai/session-context.org= (the AA palette this brightens). Hardest slot: blue keywords (a deep dupre blue can't be AAA on near-black — decide brighten vs keep-AA-exception vs lift-the-ground).
-** DONE [#B] theme-selector tier-3 package faces :feature:theme:theme-selector:
+** DONE [#B] theme-studio tier-3 package faces :feature:theme:theme-studio:
CLOSED: [2026-06-08 Mon]
-Package-specific face editing in the theme-selector: org/magit/elfeed bespoke (complete face tables + live previews) plus a generated all-package inventory so every installed package is themeable. Spec is Ready, all opens resolved: [[file:docs/design/theme-selector-package-faces-spec.org][docs/design/theme-selector-package-faces-spec.org]]. Phases below run in dependency order; phases 1-5 deliver the three high-value apps, phase 6 opens the long tail, phase 7 documents. The =theme.json= -> =dupre-*.el= converter (Elisp) is a separate downstream task.
+Package-specific face editing in the theme-studio: org/magit/elfeed bespoke (complete face tables + live previews) plus a generated all-package inventory so every installed package is themeable. Spec is Ready, all opens resolved: [[file:docs/design/theme-studio-package-faces-spec.org][docs/design/theme-studio-package-faces-spec.org]]. Phases below run in dependency order; phases 1-5 deliver the three high-value apps, phase 6 opens the long tail, phase 7 documents. The =theme.json= -> =dupre-*.el= converter (Elisp) is a separate downstream task.
*** 2026-06-08 Mon @ 00:17:41 -0500 Phase 1 — package state + schema landed
Added =APPS= (org starter) and =PKGMAP= ({app:{face:{fg,bg,bold,italic,inherit,height,source}}}), pure helpers (=seedPkgmap= / =packagesForExport= / =mergePackagesInto=), and wired export/import for the =packages= key with old-JSON compat. The =height= float (relative size, read off the face not cascaded through inherit) and the fixed-pitch inherits are seeded in the org starter. No UI yet (Phase 3). Verified: node-check, plus a guarded =#selftest= harness (headless Chrome) confirming seed->export->import round-trip, old-JSON merge, and inherit/height/source survival — all PASS.
@@ -113,16 +113,16 @@ Bespoke =renderMagitPreview()= (status buffer: head/branches, untracked, a diff
=build-inventory.el= (loaded into a running Emacs) groups every installed package's faces by the defining package and writes =package-inventory.json=. =generate.py= embeds it and merges each package into the dropdown as an editable generic app, leaving org/magit/elfeed bespoke. 40 apps now (3 bespoke + 37 inventory, 643 faces). Committed data artifact, refreshed by reloading the .el; never browser-side discovery. Verified: node, self-test PASS, app count + bespoke-preserved checks.
*** 2026-06-08 Mon @ 02:34:01 -0500 Phase 7 — docs landed
-Rewrote =README.md= for the full tool: three face tiers + palette, the in-page picker (with the AA/AAA mask), package faces (bespoke vs generic previews), modeled inheritance + relative height (family stays in font-config.el), the packages schema with inherit/height/source, export-vs-save, and the inventory-refresh command (=build-inventory.el=) + its loaded-config dependency. Notes =theme-selector.html= is generated. Test-surface fixtures tracked separately below.
+Rewrote =README.md= for the full tool: three face tiers + palette, the in-page picker (with the AA/AAA mask), package faces (bespoke vs generic previews), modeled inheritance + relative height (family stays in font-config.el), the packages schema with inherit/height/source, export-vs-save, and the inventory-refresh command (=build-inventory.el=) + its loaded-config dependency. Notes =theme-studio.html= is generated. Test-surface fixtures tracked separately below.
-*** 2026-06-08 Mon @ 02:40:00 -0500 theme-selector tier 3 — test surface landed
-Extended the guarded =#selftest= harness (headless Chrome) to assert the acceptance criteria against the real emitted code: old-JSON import (no =packages=), full round-trip (fg/bg/bold/italic/inherit/height/source), cleared-state export, unknown-package/face preservation, and inheritance-cycle termination — all PASS. The two DOM-coupled regressions are handled structurally: =updateColor= remaps =PKGMAP= on a palette-color edit, and =PKGMAP= stores hexes so a deleted palette color leaves package refs in the "(gone)" recoverable state. =generate.py= rebuilds =theme-selector.html= each run.
+*** 2026-06-08 Mon @ 02:40:00 -0500 theme-studio tier 3 — test surface landed
+Extended the guarded =#selftest= harness (headless Chrome) to assert the acceptance criteria against the real emitted code: old-JSON import (no =packages=), full round-trip (fg/bg/bold/italic/inherit/height/source), cleared-state export, unknown-package/face preservation, and inheritance-cycle termination — all PASS. The two DOM-coupled regressions are handled structurally: =updateColor= remaps =PKGMAP= on a palette-color edit, and =PKGMAP= stores hexes so a deleted palette color leaves package refs in the "(gone)" recoverable state. =generate.py= rebuilds =theme-studio.html= each run.
-** TODO Manual testing and validation :verify:theme-selector:
+** TODO Manual testing and validation :verify:theme-studio:
Exercised once the phases above land.
*** TODO Seeded package-face defaults look right
What we're verifying: the seeded org/magit/elfeed default colors read well before any tuning.
-- Open =scripts/theme-selector/theme-selector.html= in Chrome
+- Open =scripts/theme-studio/theme-studio.html= in Chrome
- Switch the app selector to org-mode, then magit, then elfeed
- Read each preview pane against the dupre ground
Expected: each package's seeded defaults look coherent and legible; nothing is unreadable or jarring. Override anything off in the tool.