diff options
| author | Craig Jennings <c@cjennings.net> | 2026-06-08 08:56:47 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-06-08 08:57:05 -0500 |
| commit | 7f57c6467054f6762a40b683d6585ee0a2b5527c (patch) | |
| tree | d787bae9ba1c958b00b0f31cd868f252b4ddcaeb | |
| parent | 3e8d5651a3fddcf4afccd46a382ab12d915bbd8c (diff) | |
| download | dotemacs-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.el | 8 | ||||
| -rw-r--r-- | todo.org | 26 |
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." @@ -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. |
