aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-06-15 10:24:40 -0500
committerCraig Jennings <c@cjennings.net>2026-06-15 10:24:40 -0500
commit45e0f6e896b2c34de25d5c3aa18474c79d6a1e72 (patch)
tree3f4d822aa5da53f4e6bbebbdc7fb400a2b212189
parenta5c9f48220cd52770f10f7627922b9fc8e2204cc (diff)
downloaddotemacs-45e0f6e896b2c34de25d5c3aa18474c79d6a1e72.tar.gz
dotemacs-45e0f6e896b2c34de25d5c3aa18474c79d6a1e72.zip
docs: move specs to docs/specs/ with lifecycle-status filenames
Separate the 27 formal specs from working notes. Specs move to docs/specs/, notes stay in docs/design/. Each spec carries its lifecycle in the filename (-spec, -spec-doing, -spec-implemented, -spec-superseded) plus an authoritative ID and STATUS property drawer. The status came from checking each spec against the code, not the doc's own field: 6 implemented, 8 in progress, 12 not started, 1 superseded. Inbound links become org-id links so future status renames don't break them; code-comment paths repoint to docs/specs/. Working notes, inventories, reviews, and brainstorms stay in docs/design/.
-rw-r--r--docs/design/ai-kb-shared-roam-brainstorm.org2
-rw-r--r--docs/design/module-inventory.org2
-rw-r--r--docs/design/music-config-without-emms-review.org2
-rw-r--r--docs/design/signal-client-review.org2
-rw-r--r--docs/design/utility-inventory.org6
-rw-r--r--docs/specs/ai-kb-spec.org (renamed from docs/design/ai-kb.org)4
-rw-r--r--docs/specs/ai-vterm-spec-superseded.org (renamed from docs/design/ai-vterm.org)4
-rw-r--r--docs/specs/cache-helper-design-spec-implemented.org (renamed from docs/design/cache-helper-design.org)6
-rw-r--r--docs/specs/company-to-corfu-migration-spec.org (renamed from docs/design/company-to-corfu-migration.org)4
-rw-r--r--docs/specs/coverage-spec-implemented.org (renamed from docs/design/coverage.org)4
-rw-r--r--docs/specs/debug-profiling-spec.org (renamed from docs/design/debug-profiling.org)4
-rw-r--r--docs/specs/dev-setup-project-spec.org (renamed from docs/design/dev-setup-project.org)4
-rw-r--r--docs/specs/dupre-clear-theme-spec.org (renamed from docs/design/dupre-clear-theme.org)4
-rw-r--r--docs/specs/face-font-diagnostic-popup-spec.org (renamed from docs/design/face-font-diagnostic-popup-spec.org)6
-rw-r--r--docs/specs/flycheck-modeline-customization-spec-implemented.org (renamed from docs/design/flycheck-modeline-customization.org)4
-rw-r--r--docs/specs/gloss-spec-doing.org (renamed from docs/design/gloss.org)4
-rw-r--r--docs/specs/gptel-gh-tool-spec.org (renamed from docs/design/gptel-gh-tool.org)6
-rw-r--r--docs/specs/gptel-git-tools-magit-backend-spec.org (renamed from docs/design/gptel-git-tools-magit-backend.org)4
-rw-r--r--docs/specs/gptel-network-tools-spec.org (renamed from docs/design/gptel-network-tools.org)6
-rw-r--r--docs/specs/init-load-graph-spec-doing.org (renamed from docs/design/init-load-graph.org)12
-rw-r--r--docs/specs/keybinding-console-safety-spec-doing.org (renamed from docs/design/keybinding-console-safety-spec.org)8
-rw-r--r--docs/specs/mcp-el-gptel-integration-spec-doing.org (renamed from docs/design/mcp-el-gptel-integration.org)6
-rw-r--r--docs/specs/messenger-unification-spec.org (renamed from docs/design/messenger-unification-spec.org)4
-rw-r--r--docs/specs/music-config-without-emms-spec.org (renamed from docs/design/music-config-without-emms.org)4
-rw-r--r--docs/specs/org-faces-spec-implemented.org (renamed from docs/design/org-faces-spec.org)6
-rw-r--r--docs/specs/signal-client-spec-doing.org (renamed from docs/design/signal-client.org)4
-rw-r--r--docs/specs/theme-studio-package-faces-spec-doing.org (renamed from docs/design/theme-studio-package-faces-spec.org)4
-rw-r--r--docs/specs/theme-studio-perceptual-color-metrics-spec-implemented.org (renamed from docs/design/theme-studio-perceptual-color-metrics-spec.org)4
-rw-r--r--docs/specs/theme-studio-seeding-engine-spec-doing.org (renamed from docs/design/theme-studio-seeding-engine-spec.org)6
-rw-r--r--docs/specs/theme-studio-structured-output-spec.org157
-rw-r--r--docs/specs/utility-consolidation-spec-doing.org (renamed from docs/design/utility-consolidation.org)14
-rw-r--r--docs/specs/vterm-to-ghostel-migration-spec-implemented.org (renamed from docs/design/vterm-to-ghostel-migration-spec.org)6
-rw-r--r--docs/theme-studio-palette-generator-spec.org2
-rw-r--r--docs/theme-studio-semantic-theme-architecture-spec.org2
-rw-r--r--modules/ai-mcp.el2
-rw-r--r--modules/cj-cache-lib.el2
-rw-r--r--modules/coverage-core.el2
-rw-r--r--modules/external-open-lib.el2
-rw-r--r--modules/signal-config.el2
-rw-r--r--scripts/theme-studio/build-theme.el2
-rw-r--r--scripts/theme-studio/theme-coloring-guide.org2
-rw-r--r--tests/run-coverage-file.el2
-rw-r--r--tests/test-cj-cache-lib.el2
-rw-r--r--tests/test-init-module-headers.el2
-rw-r--r--tests/test-modeline-config-flycheck-segment.el2
-rw-r--r--tests/test-signal-config-notify.el2
-rw-r--r--tests/test-signel-notify-function.el2
-rw-r--r--todo.org86
48 files changed, 345 insertions, 84 deletions
diff --git a/docs/design/ai-kb-shared-roam-brainstorm.org b/docs/design/ai-kb-shared-roam-brainstorm.org
index e42e2b006..c2467380b 100644
--- a/docs/design/ai-kb-shared-roam-brainstorm.org
+++ b/docs/design/ai-kb-shared-roam-brainstorm.org
@@ -410,7 +410,7 @@ This layer answers:
* Possible next task
Convert this brainstorm into a concrete design delta for the existing
-=docs/design/ai-kb.org= and the open =Implement ai-kb= task:
+=docs/specs/ai-kb-spec.org= and the open =Implement ai-kb= task:
- add agent query triggers;
- specify personal-roam access boundaries;
diff --git a/docs/design/module-inventory.org b/docs/design/module-inventory.org
index 2d4baf81a..eeb824b57 100644
--- a/docs/design/module-inventory.org
+++ b/docs/design/module-inventory.org
@@ -4,7 +4,7 @@
* Purpose
-Living per-module inventory for the [[file:init-load-graph.org][init.el load-graph refactor]]. The
+Living per-module inventory for the [[id:e1fd137e-e164-42f4-a658-f4d32fbe3228][init.el load-graph refactor]]. The
spec's module-category table is the seed; this file is the per-module truth as
each module is inspected and classified. A module moves from [[*Pending
classification][Pending classification]] into [[*Classified modules][Classified
diff --git a/docs/design/music-config-without-emms-review.org b/docs/design/music-config-without-emms-review.org
index 67ef0d1b8..1aae670d6 100644
--- a/docs/design/music-config-without-emms-review.org
+++ b/docs/design/music-config-without-emms-review.org
@@ -3,7 +3,7 @@
#+DATE: 2026-05-15
#+OPTIONS: toc:nil num:nil
-Spec reviewed: =docs/design/music-config-without-emms.org=
+Spec reviewed: =docs/specs/music-config-without-emms-spec.org=
Third pass. This review answers the single question: is the spec in
shape to start =/start-work= against?
diff --git a/docs/design/signal-client-review.org b/docs/design/signal-client-review.org
index 34b4bbda4..7e8a73e91 100644
--- a/docs/design/signal-client-review.org
+++ b/docs/design/signal-client-review.org
@@ -5,7 +5,7 @@
* Scope reviewed
- =.ai/workflows/spec-review.org=.
-- =docs/design/signal-client.org=, including the base design, open-question dispositions, initiate-message workflow, architecture additions, accepted caveats, test plan, scope summary, and readiness rubric.
+- =docs/specs/signal-client-spec-doing.org=, including the base design, open-question dispositions, initiate-message workflow, architecture additions, accepted caveats, test plan, scope summary, and readiness rubric.
- =modules/signal-config.el=, including =cj/signal--parse-contacts=, notify-suppression helpers, private config loading, and current =use-package signel= wiring.
- =~/code/signel/signel.el=, including =signel-start=, =signel--send-rpc=, =signel--dispatch=, =signel--handle-error=, =signel--handle-receive=, =signel--insert-msg=, =signel--insert-system-msg=, =signel--send-input=, =signel-chat=, and dashboard commands.
- =tests/test-signal-config.el=, covering contact parsing and notify-suppression helpers.
diff --git a/docs/design/utility-inventory.org b/docs/design/utility-inventory.org
index cf4c13bd3..8438a5924 100644
--- a/docs/design/utility-inventory.org
+++ b/docs/design/utility-inventory.org
@@ -4,7 +4,7 @@
* Status
-Living inventory. Phase 1 of [[file:utility-consolidation.org][utility-consolidation.org]]. Records the current state of helpers identified in the spec's Candidate Extraction Table plus any new candidates discovered during module walkthroughs. Decisions become concrete tasks in =todo.org= for Phase 2+.
+Living inventory. Phase 1 of [[id:fc2e3926-b4a1-4b45-92eb-20841e13f655][utility-consolidation-spec-doing.org]]. Records the current state of helpers identified in the spec's Candidate Extraction Table plus any new candidates discovered during module walkthroughs. Decisions become concrete tasks in =todo.org= for Phase 2+.
* Scope
@@ -82,7 +82,7 @@ Caller counts in the inventory below reflect grep results from 2026-05-10. The c
| Symbol | File | Vis | Deps | Side effects | Proposed home / name | Callers (modules) | Tests | Pri | Decision | Rationale |
|--------+------+-----+------+--------------+----------------------+-------------------+-------+-----+----------+-----------|
-| =cj/modeline-vc-cache-*= helpers (key/get/put/clear/valid-p) | =modeline-config.el:108-140= | private | buffer-local vars | mutates buffer-local state | =cj-cache.el= / =cj/cache-valid-p=, =cj/cache-get=, =cj/cache-put=, =cj/cache-clear= | 1 (within file) | =test-modeline-config-vc-cache.el= | Medium | Defer | Good pattern, but variable-local cache shape differs from the agenda/refile caches. Needs design before extraction. Spec calls out a Phase 5 design addendum at =docs/design/cache-helper-design.org=. |
+| =cj/modeline-vc-cache-*= helpers (key/get/put/clear/valid-p) | =modeline-config.el:108-140= | private | buffer-local vars | mutates buffer-local state | =cj-cache.el= / =cj/cache-valid-p=, =cj/cache-get=, =cj/cache-put=, =cj/cache-clear= | 1 (within file) | =test-modeline-config-vc-cache.el= | Medium | Defer | Good pattern, but variable-local cache shape differs from the agenda/refile caches. Needs design before extraction. Spec calls out a Phase 5 design addendum at =docs/specs/cache-helper-design-spec-implemented.org=. |
| agenda/refile cache vars and build flags | =org-agenda-config.el=, =org-refile-config.el= | n/a | timers, file scans | scans filesystem, sets vars | =cj-cache.el= / =cj/cache-value-or-rebuild= | 2 | none | Medium | Defer | TTL/build/invalidate lifecycle; higher risk than the modeline cache. Same Phase 5 work. |
** Logging / Warnings
@@ -144,7 +144,7 @@ These become =todo.org= entries (or update existing ones) as Phase 2 starts.
** Deferred (track in =todo.org= but no commit yet)
-- Cache abstraction (modeline + agenda/refile) -- needs Phase 5 design addendum at =docs/design/cache-helper-design.org=.
+- Cache abstraction (modeline + agenda/refile) -- needs Phase 5 design addendum at =docs/specs/cache-helper-design-spec-implemented.org=.
- =cj/--open-with-is-launcher-p= -- move when external-open ownership is finalized.
- =cj/log-silently= rename -- low value; do during incidental =system-lib= work.
- HTML/text helpers (=strip-html=, =clean-text=) -- defer until a second consumer.
diff --git a/docs/design/ai-kb.org b/docs/specs/ai-kb-spec.org
index 22a9cb9cf..fbd35ca55 100644
--- a/docs/design/ai-kb.org
+++ b/docs/specs/ai-kb-spec.org
@@ -1,3 +1,7 @@
+:PROPERTIES:
+:ID: 03742426-35ce-41c5-aed7-d4e248e91833
+:STATUS: not-started
+:END:
#+TITLE: Design: AI Knowledge Base (ai-kb)
#+AUTHOR: Craig Jennings
#+DATE: 2026-05-24
diff --git a/docs/design/ai-vterm.org b/docs/specs/ai-vterm-spec-superseded.org
index 99526b632..0b6bfb86c 100644
--- a/docs/design/ai-vterm.org
+++ b/docs/specs/ai-vterm-spec-superseded.org
@@ -1,3 +1,7 @@
+:PROPERTIES:
+:ID: 3abd0270-e87c-42b7-9b3a-ef60300db99d
+:STATUS: superseded
+:END:
#+TITLE: Design: ai-vterm — in-Emacs Claude launcher
#+AUTHOR: Craig Jennings
#+DATE: 2026-05-07
diff --git a/docs/design/cache-helper-design.org b/docs/specs/cache-helper-design-spec-implemented.org
index 5de0f348c..27c818dcb 100644
--- a/docs/design/cache-helper-design.org
+++ b/docs/specs/cache-helper-design-spec-implemented.org
@@ -1,10 +1,14 @@
+:PROPERTIES:
+:ID: 647c5101-21c2-47bb-aaa7-72c757f45fb7
+:STATUS: implemented
+:END:
#+TITLE: Cache Helper Design Addendum
#+AUTHOR: Craig Jennings
#+DATE: 2026-05-10
* Status
-Phase 5 design addendum to [[file:utility-consolidation.org][utility-consolidation.org]]. Specifies the cache API to extract before any code moves.
+Phase 5 design addendum to [[id:fc2e3926-b4a1-4b45-92eb-20841e13f655][utility-consolidation-spec-doing.org]]. Specifies the cache API to extract before any code moves.
* Problem
diff --git a/docs/design/company-to-corfu-migration.org b/docs/specs/company-to-corfu-migration-spec.org
index 55da081c8..a7b059a3b 100644
--- a/docs/design/company-to-corfu-migration.org
+++ b/docs/specs/company-to-corfu-migration-spec.org
@@ -1,3 +1,7 @@
+:PROPERTIES:
+:ID: 68733ba2-37a7-4a7b-bfaa-b845d82ff1e7
+:STATUS: not-started
+:END:
#+TITLE: Design: Migrate from Company to Corfu (with prescient integration)
#+AUTHOR: Craig Jennings
#+DATE: 2026-05-15
diff --git a/docs/design/coverage.org b/docs/specs/coverage-spec-implemented.org
index acd8b4c43..65734fb3d 100644
--- a/docs/design/coverage.org
+++ b/docs/specs/coverage-spec-implemented.org
@@ -1,3 +1,7 @@
+:PROPERTIES:
+:ID: 7d7f4486-fad7-4f0a-bd9a-775bd4cd8f7e
+:STATUS: implemented
+:END:
#+TITLE: Design: Coverage Reporting
#+AUTHOR: Craig Jennings
#+DATE: 2026-04-22
diff --git a/docs/design/debug-profiling.org b/docs/specs/debug-profiling-spec.org
index 3f5792501..5961071b8 100644
--- a/docs/design/debug-profiling.org
+++ b/docs/specs/debug-profiling-spec.org
@@ -1,3 +1,7 @@
+:PROPERTIES:
+:ID: c713b431-ae14-498d-aba9-b84d52f981b6
+:STATUS: not-started
+:END:
#+TITLE: Design: debug-profiling.el module
#+AUTHOR: Craig Jennings
#+DATE: 2026-04-26
diff --git a/docs/design/dev-setup-project.org b/docs/specs/dev-setup-project-spec.org
index 280b015b2..5d64f368f 100644
--- a/docs/design/dev-setup-project.org
+++ b/docs/specs/dev-setup-project-spec.org
@@ -1,3 +1,7 @@
+:PROPERTIES:
+:ID: 596fce5d-1bab-46e7-8567-d4a2e0923091
+:STATUS: not-started
+:END:
#+TITLE: Design: cj/dev-setup-project
#+AUTHOR: Craig Jennings
#+DATE: 2026-04-22
diff --git a/docs/design/dupre-clear-theme.org b/docs/specs/dupre-clear-theme-spec.org
index 3b88a7d0f..9594eb3d9 100644
--- a/docs/design/dupre-clear-theme.org
+++ b/docs/specs/dupre-clear-theme-spec.org
@@ -1,3 +1,7 @@
+:PROPERTIES:
+:ID: 20df7f50-4759-47ba-9782-8dd25a2e173e
+:STATUS: not-started
+:END:
#+TITLE: dupre-clear — a contrast-first AAA sibling theme
#+AUTHOR: Craig Jennings
#+DATE: 2026-06-07
diff --git a/docs/design/face-font-diagnostic-popup-spec.org b/docs/specs/face-font-diagnostic-popup-spec.org
index be83a31ab..bbd67e92d 100644
--- a/docs/design/face-font-diagnostic-popup-spec.org
+++ b/docs/specs/face-font-diagnostic-popup-spec.org
@@ -1,3 +1,7 @@
+:PROPERTIES:
+:ID: 98f065cf-8bd5-46a0-ac24-da94d66855ad
+:STATUS: not-started
+:END:
#+TITLE: Face and Font Diagnostic Popup — Spec
#+AUTHOR: Craig Jennings
#+DATE: 2026-06-14
@@ -5,7 +9,7 @@
* Metadata
-| Status | draft |
+| Status | not-started |
|----------+---------------------------------------------------|
| Owner | Craig Jennings |
|----------+---------------------------------------------------|
diff --git a/docs/design/flycheck-modeline-customization.org b/docs/specs/flycheck-modeline-customization-spec-implemented.org
index 25e2c7854..59567be60 100644
--- a/docs/design/flycheck-modeline-customization.org
+++ b/docs/specs/flycheck-modeline-customization-spec-implemented.org
@@ -1,3 +1,7 @@
+:PROPERTIES:
+:ID: 76979608-956e-474f-90a8-8d0c958101a0
+:STATUS: implemented
+:END:
#+TITLE: Design: Flycheck modeline customization
#+AUTHOR: Craig Jennings
#+DATE: 2026-05-15
diff --git a/docs/design/gloss.org b/docs/specs/gloss-spec-doing.org
index 04efc38bf..320b83ebf 100644
--- a/docs/design/gloss.org
+++ b/docs/specs/gloss-spec-doing.org
@@ -1,3 +1,7 @@
+:PROPERTIES:
+:ID: 295f9969-ccef-4df9-945b-9e08d8069daf
+:STATUS: doing
+:END:
#+TITLE: Design — gloss (Glossary Lookup with Online-Sourced Selection)
#+DATE: 2026-04-28
#+STATUS: Draft
diff --git a/docs/design/gptel-gh-tool.org b/docs/specs/gptel-gh-tool-spec.org
index a9ba22bb1..80ecc0ab6 100644
--- a/docs/design/gptel-gh-tool.org
+++ b/docs/specs/gptel-gh-tool-spec.org
@@ -1,3 +1,7 @@
+:PROPERTIES:
+:ID: a124dd0f-1f40-4533-aeb8-595d93e20865
+:STATUS: not-started
+:END:
#+TITLE: Design: Wrap the gh CLI as a GPTel tool
#+AUTHOR: Craig Jennings
#+DATE: 2026-05-16
@@ -1052,7 +1056,7 @@ Items intentionally deferred:
- [[file:gptel-agentic-tool-ideas.org][gptel-agentic-tool-ideas.org]] -- broader agentic-tool design;
=gh= sits alongside the MCP integration as the
collaboration tier.
-- [[file:mcp-el-gptel-integration.org][mcp-el-gptel-integration.org]] -- sibling design; same
+- [[id:b4c274c5-8572-4a7b-b657-d315712bd6af][mcp-el-gptel-integration-spec-doing.org]] -- sibling design; same
confirm-on-write pattern for safety.
- [[https://cli.github.com/manual/][gh CLI manual]] -- subcommand reference.
- =gh --version 2.92.0= help output -- verified flag semantics
diff --git a/docs/design/gptel-git-tools-magit-backend.org b/docs/specs/gptel-git-tools-magit-backend-spec.org
index 94fbb0cec..bd84b0595 100644
--- a/docs/design/gptel-git-tools-magit-backend.org
+++ b/docs/specs/gptel-git-tools-magit-backend-spec.org
@@ -1,3 +1,7 @@
+:PROPERTIES:
+:ID: bd47c9a8-aae1-4a3d-ad5b-b8767f2fd580
+:STATUS: not-started
+:END:
#+TITLE: Design: gptel git tools on a magit backend
#+AUTHOR: Craig Jennings
#+DATE: 2026-05-16
diff --git a/docs/design/gptel-network-tools.org b/docs/specs/gptel-network-tools-spec.org
index aae2cc2a8..c28d54694 100644
--- a/docs/design/gptel-network-tools.org
+++ b/docs/specs/gptel-network-tools-spec.org
@@ -1,3 +1,7 @@
+:PROPERTIES:
+:ID: 6388588c-dac2-4c52-97ad-2343ba1443fc
+:STATUS: not-started
+:END:
#+TITLE: Design: gptel network tools
#+AUTHOR: Craig Jennings
#+DATE: 2026-05-16
@@ -7,7 +11,7 @@
Draft. Brainstorm output captured from a =/brainstorm= session on
2026-05-16. Sibling to
-=docs/design/gptel-git-tools-magit-backend.org= and the broader theme
+=docs/specs/gptel-git-tools-magit-backend-spec.org= and the broader theme
hierarchy under =** TODO [#B] GPTel Tool Work= in =todo.org=.
The conventional vs tail-sample exploration covered three categories
diff --git a/docs/design/init-load-graph.org b/docs/specs/init-load-graph-spec-doing.org
index 3db2fe854..05dd9e0a3 100644
--- a/docs/design/init-load-graph.org
+++ b/docs/specs/init-load-graph-spec-doing.org
@@ -1,3 +1,7 @@
+:PROPERTIES:
+:ID: e1fd137e-e164-42f4-a658-f4d32fbe3228
+:STATUS: doing
+:END:
#+TITLE: Design: Untangle the init.el Load Graph
#+AUTHOR: Craig Jennings
#+DATE: 2026-05-04
@@ -174,7 +178,7 @@ Foundation modules should be able to load in batch mode without package,
network, timer, or UI-package side effects.
Adding a new Layer 1 module requires a coordinated update to the
-=system-lib.el= dependency budget in [[file:utility-consolidation.org][utility-consolidation.org]].
+=system-lib.el= dependency budget in [[id:fc2e3926-b4a1-4b45-92eb-20841e13f655][utility-consolidation-spec-doing.org]].
Topic libraries introduced by the utility project join Layer 1 only when their
first consumer is foundation-eager. Otherwise they are Layer 2 and loaded by an
@@ -391,7 +395,7 @@ Worked example:
;; Runtime requires: user-constants, seq, subr-x.
;; Direct test load: yes (batch-safe; private config is optional).
;;
-;; See also: docs/design/init-load-graph.org, tests/test-calendar-sync.el.
+;; See also: docs/specs/init-load-graph-spec-doing.org, tests/test-calendar-sync.el.
;;
;;; Code:
#+end_src
@@ -448,7 +452,7 @@ Inventory rules:
- Every module required by =init.el= must be represented before Phase 2 starts.
- Discoveries during later phases update the inventory.
- This inventory is independent from the helper inventory owned by
- [[file:utility-consolidation.org][utility-consolidation.org]].
+ [[id:fc2e3926-b4a1-4b45-92eb-20841e13f655][utility-consolidation-spec-doing.org]].
Exit criteria:
@@ -643,7 +647,7 @@ rollback shapes.
This sibling project can run beside Phase 2. When explicit-dependency work finds
a generic duplicated helper, the sibling project owns the extraction commit when
the helper is in scope for that project. See
-[[file:utility-consolidation.org][utility-consolidation.org]] for candidate
+[[id:fc2e3926-b4a1-4b45-92eb-20841e13f655][utility-consolidation-spec-doing.org]] for candidate
helpers, naming rules, dependency budgets, migration phases, and test policy.
* Testing Strategy
diff --git a/docs/design/keybinding-console-safety-spec.org b/docs/specs/keybinding-console-safety-spec-doing.org
index d06c5a279..4a1dec813 100644
--- a/docs/design/keybinding-console-safety-spec.org
+++ b/docs/specs/keybinding-console-safety-spec-doing.org
@@ -1,9 +1,13 @@
+:PROPERTIES:
+:ID: 540bf06b-16b8-46c6-b459-c40d1b9c795d
+:STATUS: doing
+:END:
#+TITLE: Keymap Consolidation — Spec
#+AUTHOR: Craig Jennings
#+DATE: 2026-06-12
* Metadata
-| Status | draft |
+| Status | doing |
|----------+--------------------------------------------------------------------|
| Owner | Craig Jennings |
|----------+--------------------------------------------------------------------|
@@ -890,7 +894,7 @@ translation block being retired). =C-l= appears only minibuffer-local in
- Why: a touched key family broke in GUI and is dead in console; the fix path is
cross-cutting (18 keys, a translation layer to retire, a console-safety
architecture) with real trade-offs, so it clears the spec bar.
-- Artifacts: docs/design/keybinding-console-safety-spec.org; supersedes the
+- Artifacts: docs/specs/keybinding-console-safety-spec-doing.org; supersedes the
pre-template draft docs/design/keybinding-console-safety.org.
** 2026-06-12 Fri @ 18:30:30 -0500 — Craig Jennings — review response
- What: processed Craig's four review comments. Recorded his first-choice
diff --git a/docs/design/mcp-el-gptel-integration.org b/docs/specs/mcp-el-gptel-integration-spec-doing.org
index 6bac77c54..f22e91959 100644
--- a/docs/design/mcp-el-gptel-integration.org
+++ b/docs/specs/mcp-el-gptel-integration-spec-doing.org
@@ -1,3 +1,7 @@
+:PROPERTIES:
+:ID: b4c274c5-8572-4a7b-b657-d315712bd6af
+:STATUS: doing
+:END:
#+TITLE: Design: Wire mcp.el into GPTel for MCP server access
#+AUTHOR: Craig Jennings
#+DATE: 2026-05-16
@@ -1420,7 +1424,7 @@ C= so existing GPTel keys aren't disturbed (rev 3).
- [[file:gptel-tools-shortlist.org][gptel-tools-shortlist.org]] -- local-tools shortlist; MCP servers
slot in as the "external" tier.
- [[file:gptel-agentic-tool-ideas.org][gptel-agentic-tool-ideas.org]] -- broader agentic-tool design.
-- [[file:gptel-gh-tool.org][gptel-gh-tool.org]] -- sibling design; same confirm-on-write
+- [[id:a124dd0f-1f40-4533-aeb8-595d93e20865][gptel-gh-tool-spec.org]] -- sibling design; same confirm-on-write
pattern.
- [[https://github.com/lizqwerscott/mcp.el][lizqwerscott/mcp.el]] -- upstream.
- [[https://github.com/lizqwerscott/gptel-mcp.el][lizqwerscott/gptel-mcp.el]] -- considered and declined; see §
diff --git a/docs/design/messenger-unification-spec.org b/docs/specs/messenger-unification-spec.org
index 7e8780300..f8d3b4734 100644
--- a/docs/design/messenger-unification-spec.org
+++ b/docs/specs/messenger-unification-spec.org
@@ -1,3 +1,7 @@
+:PROPERTIES:
+:ID: 4bfc2011-8ffc-4765-8886-91df12141171
+:STATUS: not-started
+:END:
#+TITLE: Messenger Unification — Shared Window Placement and Key Conventions
#+AUTHOR: Craig Jennings & Claude
#+DATE: 2026-06-11
diff --git a/docs/design/music-config-without-emms.org b/docs/specs/music-config-without-emms-spec.org
index 929423df6..32fd67367 100644
--- a/docs/design/music-config-without-emms.org
+++ b/docs/specs/music-config-without-emms-spec.org
@@ -1,3 +1,7 @@
+:PROPERTIES:
+:ID: 423bc355-18d3-4e39-9e7a-f768b865d95b
+:STATUS: not-started
+:END:
#+TITLE: Design: music-config Without EMMS
#+AUTHOR: Craig Jennings
#+DATE: 2026-05-15
diff --git a/docs/design/org-faces-spec.org b/docs/specs/org-faces-spec-implemented.org
index c81880270..c88559061 100644
--- a/docs/design/org-faces-spec.org
+++ b/docs/specs/org-faces-spec-implemented.org
@@ -1,10 +1,14 @@
+:PROPERTIES:
+:ID: 35578114-8c29-43af-97a2-fdfea01a802e
+:STATUS: implemented
+:END:
#+TITLE: Org Header-Row Faces — Spec
#+AUTHOR: Craig Jennings
#+DATE: 2026-06-15
#+TODO: TODO | DONE SUPERSEDED CANCELLED
* Metadata
-| Status | draft |
+| Status | implemented |
|----------+----------------------------------------------------------------|
| Owner | Craig Jennings |
|----------+----------------------------------------------------------------|
diff --git a/docs/design/signal-client.org b/docs/specs/signal-client-spec-doing.org
index ef946b80c..beee0acf1 100644
--- a/docs/design/signal-client.org
+++ b/docs/specs/signal-client-spec-doing.org
@@ -1,3 +1,7 @@
+:PROPERTIES:
+:ID: 0cabd6ee-c458-47b5-a8af-3ee054b25821
+:STATUS: doing
+:END:
#+TITLE: Design: Signal client in Emacs (forked signel)
#+DATE: 2026-05-26
#+STATUS: Draft
diff --git a/docs/design/theme-studio-package-faces-spec.org b/docs/specs/theme-studio-package-faces-spec-doing.org
index 7f00b3279..566f34db0 100644
--- a/docs/design/theme-studio-package-faces-spec.org
+++ b/docs/specs/theme-studio-package-faces-spec-doing.org
@@ -1,3 +1,7 @@
+:PROPERTIES:
+:ID: 8f37a1fd-cfd3-4b25-92e5-772468092bdc
+:STATUS: doing
+:END:
#+TITLE: theme-studio — package faces (tier 3), starting with org-mode
#+AUTHOR: Craig Jennings
#+DATE: 2026-06-07
diff --git a/docs/design/theme-studio-perceptual-color-metrics-spec.org b/docs/specs/theme-studio-perceptual-color-metrics-spec-implemented.org
index 7e7dedb22..57a4c70bc 100644
--- a/docs/design/theme-studio-perceptual-color-metrics-spec.org
+++ b/docs/specs/theme-studio-perceptual-color-metrics-spec-implemented.org
@@ -1,3 +1,7 @@
+:PROPERTIES:
+:ID: 15db8ae3-fc14-49f3-9ed5-d5ff59790904
+:STATUS: implemented
+:END:
#+TITLE: theme-studio — perceptual color metrics (OKLCH, APCA, ΔE)
#+AUTHOR: Craig Jennings
#+DATE: 2026-06-08
diff --git a/docs/design/theme-studio-seeding-engine-spec.org b/docs/specs/theme-studio-seeding-engine-spec-doing.org
index bcbf43db4..baf9f5b01 100644
--- a/docs/design/theme-studio-seeding-engine-spec.org
+++ b/docs/specs/theme-studio-seeding-engine-spec-doing.org
@@ -1,3 +1,7 @@
+:PROPERTIES:
+:ID: b70b37f2-37df-4c8e-ac2f-1f20d12e33dd
+:STATUS: doing
+:END:
#+TITLE: theme-studio — seeding engine (role table to guide-correct defaults)
#+AUTHOR: Craig Jennings
#+DATE: 2026-06-08
@@ -313,7 +317,7 @@ response resolved; everything else was woven into the body as written.
budget this engine executes.
- =scripts/theme-studio/generate.py= — =CATS=, =UI_FACES=/=UIMAP=, =APPS= /
=seedPkgmap=, =exportObj= (the target shape).
-- =docs/design/theme-studio-perceptual-color-metrics-spec.org= — the
+- =docs/specs/theme-studio-perceptual-color-metrics-spec-implemented.org= — the
=colormath.js= core that v1 OKLCH shade generation uses.
* Review and iteration history
diff --git a/docs/specs/theme-studio-structured-output-spec.org b/docs/specs/theme-studio-structured-output-spec.org
new file mode 100644
index 000000000..ad189b7eb
--- /dev/null
+++ b/docs/specs/theme-studio-structured-output-spec.org
@@ -0,0 +1,157 @@
+:PROPERTIES:
+:ID: eaac7707-ed05-43df-9e51-b17c1d672531
+:STATUS: not-started
+:END:
+#+TITLE: Theme-Studio Structured Theme Output — Spec
+#+AUTHOR: Craig Jennings
+#+DATE: 2026-06-15
+#+TODO: TODO | DONE SUPERSEDED CANCELLED
+
+* Metadata
+| Status | not-started |
+|----------+----------------------------------------------------------------|
+| Owner | Craig Jennings |
+|----------+----------------------------------------------------------------|
+| Reviewer | Craig Jennings |
+|----------+----------------------------------------------------------------|
+| Related | [[file:../../todo.org][todo.org: theme-studio output + dupre retirement]] |
+|----------+----------------------------------------------------------------|
+
+* Summary
+
+Replace build-theme.el's flat deftheme (literal hex on every face) with a structured two-file output: a palette file naming each color, and a theme file whose face assignments reference the palette through a binding. A hue change becomes one edit that propagates to every face on that color, the output reads meaningfully, and the same assignments paired with a different palette make a variant. The hand-authored dupre theme is retired in the same effort: it survives only as the fallback and a structural reference now that a theme-studio export (WIP) is the active theme.
+
+* Problem / Context
+
+build-theme.el converts a theme-studio theme.json into a deftheme, and it does so flat: one =custom-theme-set-faces= with a literal hex per face and no color layer above it (the converter's own header says "Do not hand-edit; re-run the converter"). It is faithful but unreadable, and a single hue change touches every face that used that color, scattered across the file. The structure that made the hand-authored dupre theme maintainable — a palette of named colors, faces referencing those names, organized by category — is discarded at generation time.
+
+dupre carried that structure in a three-file split (theme / palette / faces), and that structure was the value. But it is theme-specific source the user no longer wants to hand-maintain. WIP, a theme-studio export, is already the active theme (=persist/emacs-theme= reads "WIP"); dupre is now only =fallback-theme-name= and a reference. theme.json already carries a named palette — a list of =[hex name family]= triples — so the data needed to generate a structured theme already exists; only the converter throws it away.
+
+The driver: make generated themes inherit dupre's structural virtues in a generated-appropriate shape, and remove dupre.
+
+* Goals and Non-Goals
+
+** Goals
+- build-theme emits two files: =NAME-palette.el= (named colors) and =NAME-theme.el= (deftheme entry plus assignments that reference palette names).
+- A hue change is one edit in theme.json's palette, re-exported, and reaches every face on that color.
+- Assignments are separable from palette, so a palette swap yields a variant theme.
+- Faces are grouped and commented by tier (default, syntax, ui, packages) for readability.
+- Output stays one-way generated (do-not-hand-edit banner); theme.json is canonical.
+- dupre is removed: the three theme files and its test deleted, =fallback-theme-name= moved to a built-in, references and comments updated.
+
+** Non-Goals
+- No semantic-role layer (accent/err/keyword → palette) in v1 — deferred, but the format leaves room for it.
+- No OKLCH ramps, perceptual palette renaming, or auto light/dark variants.
+- No change to theme-studio's editing UI.
+- Not changing the theme-studio model: the palette already exists in theme.json; v1 reads it, it does not redesign it.
+
+** Scope tiers
+- v1: build-theme two-file structured output; the palette file from theme.json's palette list; face assignments referencing palette names via a binding, one-off hexes left literal; tier organization; regenerate the active theme in the new format; retire dupre and move the fallback.
+- vNext: a semantic-role layer; per-face palette-name carriage in theme-studio (preserve intent when two roles share a hex); palette-swap variant tooling.
+
+* Design
+
+** For the user
+Tune in theme-studio and export, as today. The generated theme is now two files. The palette file lists every named color once. The theme file maps each face to a color by name, grouped by area (syntax, UI, packages) so it reads like a description of the theme rather than a hex dump. To shift a hue, change it in theme-studio and re-export; every face on that color moves together. The same theme file paired with a different palette file is a variant — the lineage that took distinguished to dupre, made explicit.
+
+** For the implementer
+build-theme/--render splits into two emitters fed by the parsed theme.json:
+- Palette emitter: from theme.json's =palette= list of =[hex name family]=, write =NAME-palette.el= — a =defconst NAME-palette= (or a set of named constants) mapping name to hex, optionally grouped by family with section comments, ending in =(provide 'NAME-palette)=.
+- Theme emitter: write =NAME-theme.el= — the =deftheme=, =(require 'NAME-palette)=, then =custom-theme-set-faces= wrapped in a binding over the palette names (a =let= built from the palette, mirroring dupre-with-colors) so face specs reference names. Each face's stored hex is reverse-mapped to a palette name by exact match; a hex absent from the palette stays a literal string. Faces grouped by tier with comments. End =(provide-theme 'NAME)=.
+Both files carry the generated/do-not-hand-edit banner. =NAME-theme.el= requires =NAME-palette.el=, so the themes directory must be on the load path at theme-load time (the existing dupre arrangement already does this for the themes dir).
+
+* Alternatives Considered
+
+** Keep the flat per-face-hex output
+- Good: no converter change; the output is trivially correct.
+- Bad: unreadable, and a hue change is scattered across every face — the maintainability problem this spec exists to fix.
+- Neutral: it is generated, so "unreadable" matters only when a human reads or hand-tweaks it, which the structured format is meant to enable.
+
+** Three-file split (theme / palette / faces), exactly like dupre
+- Good: maximal separation; the deftheme boilerplate is isolated.
+- Bad: a generated theme's deftheme wrapper is a few lines — a third file is more ceremony than generated output needs.
+- Neutral: could become warranted in vNext if the assignments file grows unwieldy.
+
+** Carry a palette-name reference per face in theme.json (no reverse-map)
+- Good: preserves the designer's intended name even when two roles share a hex.
+- Bad: a theme-studio model and export change, larger than v1; the reverse-map gets the same readable output from data that already exists.
+- Neutral: the better long-term design; logged as vNext.
+
+* Decisions [6/6]
+
+** DONE Two-file output shape
+- Context: an Emacs theme needs =NAME-theme.el= for discovery; the palette wants to be independently swappable.
+- Decision: Two files — =NAME-palette.el= (named colors) and =NAME-theme.el= (deftheme entry plus assignments). The assignments ride with the deftheme rather than getting a third file.
+- Consequences: easier — palette swaps for variants, one place to retune hues, less ceremony than dupre's three files; harder — the theme file still mixes deftheme boilerplate with assignments.
+
+** DONE Faces reference the palette via a binding
+- Context: faces must name colors, not inline hex, for the one-edit-propagates property.
+- Decision: The theme file wraps =custom-theme-set-faces= in a =let= over the palette names (mirroring dupre-with-colors) and face specs reference the names.
+- Consequences: easier — readable specs, single source of color truth; harder — the converter must build the binding and reverse-map face hexes to names.
+
+** DONE Derive the palette layer by reverse-mapping face hex to palette names
+- Context: theme.json stores resolved hex per face but already carries a named palette list (=[hex name family]=).
+- Decision: build-theme reads the palette list to emit the palette file and reverse-maps each face's hex to a palette name by exact match; a hex with no palette entry stays a literal string.
+- Consequences: easier — no theme-studio model change, uses data that already exists; harder — a hex shared by two intended roles collapses to one name (intent loss), which per-face name carriage would fix in vNext.
+
+** DONE Semantic-role layer deferred
+- Context: dupre had roles (accent/err/keyword → palette) above the palette; the user may want them later.
+- Decision: No role layer in v1. The format keeps the palette binding so a role binding can slot above it later without reshaping the output.
+- Consequences: easier — smaller v1, fewer indirection layers to reason about; harder — role intent is not captured yet, so a role rename is a vNext addition.
+
+** DONE Retire dupre, move the fallback to a built-in
+- Context: WIP (a theme-studio export) is already active; dupre is only =fallback-theme-name= and a reference; the fallback has no further fallback, so it must be guaranteed present.
+- Decision: Delete the three dupre files and =test-dupre-theme.el=; set =fallback-theme-name= to "modus-vivendi" (built-in, always available); update the persistence/commands tests and the stale comments in auto-dim-config.el and org-config.el.
+- Consequences: easier — removes hand-maintained theme source, retires the four already-failing dupre palette tests; harder — the fallback loses chosen dimming colors (acceptable for a rare last resort), and dupre's look survives only in git and in WIP's lineage.
+
+** DONE Generated files stay one-way; theme.json is canonical
+- Context: the current converter already declares its output do-not-hand-edit.
+- Decision: Both generated files keep the generated banner; hue changes and palette swaps happen in theme-studio (or by generating from another theme.json), not by editing the output.
+- Consequences: easier — no source-of-truth ambiguity, regeneration is always safe; harder — a quick hand-tweak to the palette file is overwritten on the next export, so experiments route through theme-studio.
+
+* Implementation phases
+
+** Phase 1 — palette emitter
+Emit =NAME-palette.el= from theme.json's palette list: name→hex constants (grouped by family with comments), =(provide 'NAME-palette)=, generated banner. Done when the palette file loads and exposes every named color.
+
+** Phase 2 — theme emitter with palette references
+Rewrite build-theme/--render to emit =NAME-theme.el=: deftheme, require the palette, =custom-theme-set-faces= inside a =let= over the palette, face specs referencing names (reverse-mapped from hex; literals for one-offs), tier grouping and comments, =provide-theme=. Done when a theme.json round-trips to a loading theme whose faces render identically to the old flat output. Update test-build-theme.el to the two-file shape.
+
+** Phase 3 — regenerate the active theme
+Regenerate WIP (the active theme) in the new format via deploy-wip; confirm it loads and looks unchanged in the live daemon. Done when the round-trip lands with no visible difference.
+
+** Phase 4 — retire dupre
+Set =fallback-theme-name= to "modus-vivendi"; update test-ui-theme-commands.el and test-ui-theme-persistence.el; fix the stale comments in auto-dim-config.el and org-config.el; delete themes/dupre-theme.el, dupre-palette.el, dupre-faces.el and tests/test-dupre-theme.el. Done when the suite is green, startup uses WIP, and the fallback resolves to modus-vivendi. (Independent of Phases 1-3 — can land first since WIP is already active in the old format.)
+
+* Acceptance criteria
+- [ ] build-theme produces =NAME-palette.el= and =NAME-theme.el= for a given theme.json.
+- [ ] The generated theme loads and its faces render identically to the prior flat output for the same theme.json.
+- [ ] Changing one palette color in theme.json and re-exporting updates every face that used it.
+- [ ] The palette file names every distinct palette color; one-off face hexes remain literal.
+- [ ] dupre's files and test are gone; startup uses WIP; =fallback-theme-name= resolves to a present theme; suite green.
+
+* Readiness dimensions
+- Data model & ownership: theme.json (theme-studio) is canonical; the palette list is the color source; build-theme owns the generated files; both are one-way output.
+- Errors, empty states & failure: a face hex absent from the palette falls back to a literal — no failure, just an unnamed color. A missing palette file fails the theme load loudly (require error) rather than silently mis-coloring.
+- Security & privacy: N/A — color data only.
+- Observability: the live theme and theme-studio preview are the visible surface; a wrong reverse-map shows as a wrong color.
+- Performance & scale: N/A — tens of colors, ~150 faces, generated once per export.
+- Reuse & lost opportunities: rides the existing palette list and build-theme tiers; sets up palette-swap variants and a future role layer.
+- Architecture fit & weak points: mirrors dupre's proven palette/faces separation. Weak point is the hex→name reverse-map collapsing shared hexes — bounded by leaving one-offs literal and deferring name carriage to vNext.
+- Config surface: =fallback-theme-name= changes value; the themes load-path must include the generated palette file.
+- Documentation plan: the generated banner plus this spec; no user-facing docs.
+- Dev tooling: existing =make theme-studio-theme=, =deploy-wip=, and the build-theme test suite cover build and round-trip.
+- Rollout, compatibility & rollback: Phase 4 (dupre removal) is independent and reversible via git; Phases 1-3 change only generated output, rollback is reverting build-theme. The active theme (WIP) keeps working in the old format until regenerated.
+- External APIs & deps: =deftheme=, =custom-theme-set-faces=, =provide-theme=, =custom-theme-load-path= — all standard; modus-vivendi is built in.
+
+* Risks, Rabbit Holes, and Drawbacks
+- Reverse-map ambiguity: one hex, several intended roles, collapses to one name. Dodge: leave one-offs literal; defer per-face name carriage to vNext.
+- Identical render is the bar: the structured output must produce the same face attributes as the flat output. Dodge: a converter test that diffs resolved face specs old-vs-new for a fixture theme.json.
+- Load-path for the palette file: =NAME-theme.el= requiring =NAME-palette.el= needs the themes dir on the path at load time. Dodge: reuse dupre's existing arrangement.
+- Scope creep into the role layer or OKLCH work. Dodge: both are explicit Non-Goals / vNext.
+
+* Review and iteration history
+** 2026-06-15 Mon — Craig — author
+- What: initial draft.
+- Why: the dupre retirement turned into a question of what shape theme-studio's generated themes should take; the palette-vs-flat format, the file split, and the reverse-map approach are real trade-offs worth settling before touching build-theme.el.
+- Artifacts: scripts/theme-studio/build-theme.el (current flat renderer), scripts/theme-studio/theme.json (palette list already present), themes/dupre-* (the structural reference being retired).
diff --git a/docs/design/utility-consolidation.org b/docs/specs/utility-consolidation-spec-doing.org
index b84283804..b0a5fe2bd 100644
--- a/docs/design/utility-consolidation.org
+++ b/docs/specs/utility-consolidation-spec-doing.org
@@ -1,3 +1,7 @@
+:PROPERTIES:
+:ID: fc2e3926-b4a1-4b45-92eb-20841e13f655
+:STATUS: doing
+:END:
#+TITLE: Design: Consolidate Shared Utility Helpers
#+AUTHOR: Craig Jennings
#+DATE: 2026-05-04
@@ -6,7 +10,7 @@
Draft. Specification only. No helper extraction is part of this document.
-This is the sibling project to [[file:init-load-graph.org][Untangle the init.el Load Graph]]. The load-graph
+This is the sibling project to [[id:e1fd137e-e164-42f4-a658-f4d32fbe3228][Untangle the init.el Load Graph]]. The load-graph
project decides when modules load and what dependencies they declare. This
project decides which module should own reusable helper behavior.
@@ -291,7 +295,7 @@ Worked =system-lib.el= header:
;; Private helpers rename without alias when all call sites change in the
;; same commit.
;;
-;; See also: docs/design/utility-consolidation.org for design rationale.
+;; See also: docs/specs/utility-consolidation-spec-doing.org for design rationale.
;;
;;; Code:
#+end_src
@@ -328,7 +332,7 @@ Load shape:
- =cj-cache.el= follows the first real cache consumer's layer, likely Layer 2 if
modeline/agenda/refile remain eager or near-eager.
- Coordinate every new topic library with
- [[file:init-load-graph.org][init-load-graph.org]] before migrating its first consumer.
+ [[id:e1fd137e-e164-42f4-a658-f4d32fbe3228][init-load-graph-spec-doing.org]] before migrating its first consumer.
* Naming Rules
@@ -781,7 +785,7 @@ Recommendation:
design addendum proves the API can drive the alignment.
- Then decide whether modeline's buffer-local cache can use the same library or
should remain specialized.
-- Phase 5 step 1 produces =docs/design/cache-helper-design.org=. Until that
+- Phase 5 step 1 produces =docs/specs/cache-helper-design-spec-implemented.org=. Until that
file exists, =cj-cache.el= must not be created. The addendum is the
prerequisite for any cache extraction commit.
@@ -902,7 +906,7 @@ Inventory artifact:
- Treat the inventory as living documentation. Cleared high-priority candidates
may move to Phase 2 before the whole inventory is complete.
- This inventory is independent from the module-shape inventory maintained by
- [[file:init-load-graph.org][init-load-graph.org]]. The two projects may walk the same files, but they
+ [[id:e1fd137e-e164-42f4-a658-f4d32fbe3228][init-load-graph-spec-doing.org]]. The two projects may walk the same files, but they
record different facts in separate artifacts.
For each helper record:
diff --git a/docs/design/vterm-to-ghostel-migration-spec.org b/docs/specs/vterm-to-ghostel-migration-spec-implemented.org
index 5974445ad..1be4fe227 100644
--- a/docs/design/vterm-to-ghostel-migration-spec.org
+++ b/docs/specs/vterm-to-ghostel-migration-spec-implemented.org
@@ -1,3 +1,7 @@
+:PROPERTIES:
+:ID: b54c94a0-d762-4b41-afd7-cf5593ce6675
+:STATUS: implemented
+:END:
#+TITLE: Migration: vterm → ghostel (single terminal engine)
#+AUTHOR: Craig Jennings
#+DATE: 2026-06-04
@@ -171,7 +175,7 @@ Audited file set.
** Docs (active references only — historical notes stay)
- =todo.org= current task link (already updated to this -spec path).
-- =docs/design/module-inventory.org=, =docs/design/init-load-graph.org= —
+- =docs/design/module-inventory.org=, =docs/specs/init-load-graph-spec-doing.org= —
update active =vterm-config= / =ai-vterm= references to the new names.
** Tests (~35 files)
diff --git a/docs/theme-studio-palette-generator-spec.org b/docs/theme-studio-palette-generator-spec.org
index 8139f3d95..fca76b9c1 100644
--- a/docs/theme-studio-palette-generator-spec.org
+++ b/docs/theme-studio-palette-generator-spec.org
@@ -272,7 +272,7 @@ Use the existing Theme Studio test stack:
* References / Appendix
- [[file:design/theme-studio-color-harmony.org][theme-studio color harmony explainer]]
-- [[file:design/theme-studio-perceptual-color-metrics-spec.org][perceptual color metrics spec]]
+- [[id:15db8ae3-fc14-49f3-9ed5-d5ff59790904][perceptual color metrics spec]]
- [[file:theme-studio-palette-ramps-spec.org][palette ramps and contrast safety spec]]
- [[file:theme-studio-palette-columns-spec.org][palette columns spec]]
- [[file:../todo.org::*theme-studio import organization workflow needs a spec][import organization task]]
diff --git a/docs/theme-studio-semantic-theme-architecture-spec.org b/docs/theme-studio-semantic-theme-architecture-spec.org
index 2fa318efb..25bafe9ea 100644
--- a/docs/theme-studio-semantic-theme-architecture-spec.org
+++ b/docs/theme-studio-semantic-theme-architecture-spec.org
@@ -253,7 +253,7 @@ Rollout should keep the current flat output path as the default and add a separa
- Modus Themes source: [[https://github.com/protesilaos/modus-themes][github.com/protesilaos/modus-themes]]
- Current converter: [[file:../scripts/theme-studio/build-theme.el][scripts/theme-studio/build-theme.el]]
- Current Theme Studio README: [[file:../scripts/theme-studio/README.md][scripts/theme-studio/README.md]]
-- Package-face model spec: [[file:design/theme-studio-package-faces-spec.org][theme-studio-package-faces-spec.org]]
+- Package-face model spec: [[id:8f37a1fd-cfd3-4b25-92e5-772468092bdc][theme-studio-package-faces-spec-doing.org]]
* Review and iteration history
** 2026-06-14 Sunday @ 14:37:00 -0500 -- Craig -- author
diff --git a/modules/ai-mcp.el b/modules/ai-mcp.el
index 3b552d8dc..510805be4 100644
--- a/modules/ai-mcp.el
+++ b/modules/ai-mcp.el
@@ -12,7 +12,7 @@
;; google-docs-work, google-keep), with write-confirmation gating and a
;; doctor for diagnosing prerequisites.
;;
-;; Design doc: docs/design/mcp-el-gptel-integration.org
+;; Design doc: docs/specs/mcp-el-gptel-integration-spec-doing.org
;;
;; File organization (seven sections, populated by phases):
;; 1. Constants and defcustoms <- this phase
diff --git a/modules/cj-cache-lib.el b/modules/cj-cache-lib.el
index 9aad51a3d..dc38b4836 100644
--- a/modules/cj-cache-lib.el
+++ b/modules/cj-cache-lib.el
@@ -10,7 +10,7 @@
;;
;; Used by org-agenda-config and org-refile-config which previously
;; carried parallel hand-rolled implementations of this exact shape.
-;; See docs/design/cache-helper-design.org for the API contract,
+;; See docs/specs/cache-helper-design-spec-implemented.org for the API contract,
;; consumer migration shape, and rationale for the deliberate "nil
;; cached value reads as invalid" decision.
;;
diff --git a/modules/coverage-core.el b/modules/coverage-core.el
index 0a8b2464f..687a042fe 100644
--- a/modules/coverage-core.el
+++ b/modules/coverage-core.el
@@ -17,7 +17,7 @@
;; intersects the results, and displays a report buffer. Languages
;; plug in via the backend registry (see `cj/coverage-backends').
;;
-;; See docs/design/coverage.org for the design rationale.
+;; See docs/specs/coverage-spec-implemented.org for the design rationale.
;;; Code:
diff --git a/modules/external-open-lib.el b/modules/external-open-lib.el
index aa90eb67b..d6e70354f 100644
--- a/modules/external-open-lib.el
+++ b/modules/external-open-lib.el
@@ -12,7 +12,7 @@
;; instead of the feature module.
;;
;; Pulled out of `external-open.el' as part of utility-consolidation
-;; Phase 4. See `docs/design/utility-consolidation.org'.
+;; Phase 4. See `docs/specs/utility-consolidation-spec-doing.org'.
;;; Code:
diff --git a/modules/signal-config.el b/modules/signal-config.el
index 7e980b62e..86cb523ce 100644
--- a/modules/signal-config.el
+++ b/modules/signal-config.el
@@ -339,7 +339,7 @@ that on first use."
map)
"Signel \"Messages\" prefix keymap, bound under `C-; M'.
Leaves =l= unbound for now -- the future =cj/signel-link= command lands
-in a later pass. See =docs/design/signal-client.org= scope summary.")
+in a later pass. See =docs/specs/signal-client-spec-doing.org= scope summary.")
;; Register the messages prefix under C-; M via the documented helper.
;; keybindings.el owns cj/custom-keymap; the (require 'keybindings) above
diff --git a/scripts/theme-studio/build-theme.el b/scripts/theme-studio/build-theme.el
index 827129976..f7cd127d1 100644
--- a/scripts/theme-studio/build-theme.el
+++ b/scripts/theme-studio/build-theme.el
@@ -6,7 +6,7 @@
;; 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,
+;; docs/specs/theme-studio-package-faces-spec-doing.org) into a single,
;; self-contained, loadable Emacs deftheme written to themes/<name>-theme.el.
;;
;; Four tiers come out of the JSON:
diff --git a/scripts/theme-studio/theme-coloring-guide.org b/scripts/theme-studio/theme-coloring-guide.org
index 170ad7089..cfeeb3372 100644
--- a/scripts/theme-studio/theme-coloring-guide.org
+++ b/scripts/theme-studio/theme-coloring-guide.org
@@ -433,7 +433,7 @@ The tool is where the rules get applied, by eye and increasingly by metric.
Contrast Algorithm, [[https://github.com/Myndex/apca-w3][Myndex]]), and pairwise ΔE (perceptual color-difference)
diagnostics make "use chroma to express salience" and "low contrast does not
mean low distinguishability" checkable instead of eyeballed. See
- [[file:../../docs/design/theme-studio-perceptual-color-metrics-spec.org][docs/design/theme-studio-perceptual-color-metrics-spec.org]].
+ [[id:15db8ae3-fc14-49f3-9ed5-d5ff59790904][docs/specs/theme-studio-perceptual-color-metrics-spec-implemented.org]].
- *Seeding:* the seed table is the contract the tool seeds from: syntax, UI, and
org tiers each start from guide-correct defaults, leaving you to retune hues
rather than build a theme from blank.
diff --git a/tests/run-coverage-file.el b/tests/run-coverage-file.el
index 6ac65300b..0d96f1918 100644
--- a/tests/run-coverage-file.el
+++ b/tests/run-coverage-file.el
@@ -9,7 +9,7 @@
;; Per-file isolation matches the project's `make test-unit' pattern:
;; each test file runs in its own Emacs process, so tests that work
;; under `make test' will also work under `make coverage'. See
-;; docs/design/coverage.org for the rationale.
+;; docs/specs/coverage-spec-implemented.org for the rationale.
;;; Code:
diff --git a/tests/test-cj-cache-lib.el b/tests/test-cj-cache-lib.el
index aeb329dda..7de7edb8c 100644
--- a/tests/test-cj-cache-lib.el
+++ b/tests/test-cj-cache-lib.el
@@ -4,7 +4,7 @@
;; Unit tests for the TTL+building cache helper. Covers cache-make /
;; cache-valid-p / cache-value-or-rebuild / cache-building-p /
;; cache-invalidate against the contract in
-;; docs/design/cache-helper-design.org.
+;; docs/specs/cache-helper-design-spec-implemented.org.
;;; Code:
diff --git a/tests/test-init-module-headers.el b/tests/test-init-module-headers.el
index bbda23887..a5b331f4d 100644
--- a/tests/test-init-module-headers.el
+++ b/tests/test-init-module-headers.el
@@ -2,7 +2,7 @@
;;; Commentary:
;; Enforces the module load-graph header standard from
-;; docs/design/init-load-graph.org against every module that has been
+;; docs/specs/init-load-graph-spec-doing.org against every module that has been
;; classified so far. Classification proceeds in batches; a module joins
;; `test-init-header--classified-modules' once its header declares the
;; contract. When that list reaches parity with the modules required by
diff --git a/tests/test-modeline-config-flycheck-segment.el b/tests/test-modeline-config-flycheck-segment.el
index 208deaa72..2ae2f5de1 100644
--- a/tests/test-modeline-config-flycheck-segment.el
+++ b/tests/test-modeline-config-flycheck-segment.el
@@ -5,7 +5,7 @@
;; a guarded reference to `flycheck-mode-line-status-text', and that
;; the guard requires both `mode-line-window-selected-p' and
;; `bound-and-true-p flycheck-mode'. See
-;; docs/design/flycheck-modeline-customization.org for the design.
+;; docs/specs/flycheck-modeline-customization-spec-implemented.org for the design.
;;; Code:
diff --git a/tests/test-signal-config-notify.el b/tests/test-signal-config-notify.el
index c4067a663..1a7722893 100644
--- a/tests/test-signal-config-notify.el
+++ b/tests/test-signal-config-notify.el
@@ -6,7 +6,7 @@
;; `cj/signal--notify-body-max') and `cj/signel--notify' routing (the
;; suppression gate, the notify-script path with the sound flag, and
;; the `notifications-notify' fallback). Spec: the "Notification
-;; slice" addendum in docs/design/signal-client.org. No signal-cli or
+;; slice" addendum in docs/specs/signal-client-spec-doing.org. No signal-cli or
;; linked account needed.
;;; Code:
diff --git a/tests/test-signel-notify-function.el b/tests/test-signel-notify-function.el
index cff7f7394..e3d97af51 100644
--- a/tests/test-signel-notify-function.el
+++ b/tests/test-signel-notify-function.el
@@ -3,7 +3,7 @@
;;; Commentary:
;; signel's receive handler (signel.el in the fork at ~/code/signel)
;; raised notifications through a hardwired `notifications-notify'
-;; call. The notification slice (docs/design/signal-client.org,
+;; call. The notification slice (docs/specs/signal-client-spec-doing.org,
;; "Notification slice" addendum) replaces that with
;; `signel-notify-function', a customization point called with
;; CHAT-ID, SENDER, and BODY so a config layer can add suppression or
diff --git a/todo.org b/todo.org
index da54ef434..a52011226 100644
--- a/todo.org
+++ b/todo.org
@@ -45,9 +45,9 @@ Tags are additive. For example, a small wrong-behavior fix can be
=:feature:refactor:=.
* Emacs Open Work
** TODO [#A] Face and font diagnostic popup at point :feature:
-Read-only popup diagnosing why text at point paints as it does (face stack by source, merged attributes, real font vs declared family, theme/config/inherit provenance). Spec: [[file:docs/design/face-font-diagnostic-popup-spec.org][face-font-diagnostic-popup-spec.org]] (draft, one open decision). From the roam inbox — "do this one first."
+Read-only popup diagnosing why text at point paints as it does (face stack by source, merged attributes, real font vs declared family, theme/config/inherit provenance). Spec: [[id:98f065cf-8bd5-46a0-ac24-da94d66855ad][face-font-diagnostic-popup-spec.org]] (draft, one open decision). From the roam inbox — "do this one first."
** TODO [#D] Face diagnostic popup — theme-studio bridge (vNext) :feature:
-vNext for the face/font diagnostic tool: interactivity — "send this face to theme-studio", jump-to-theme-spec, any write path. Deferred per [[file:docs/design/face-font-diagnostic-popup-spec.org][the spec]]'s scope tiers.
+vNext for the face/font diagnostic tool: interactivity — "send this face to theme-studio", jump-to-theme-spec, any write path. Deferred per [[id:98f065cf-8bd5-46a0-ac24-da94d66855ad][the spec]]'s scope tiers.
** TODO [#C] Gold text in auto-dimmed buffers :bug:
Some auto-dimmed document buffers render text in gold; source unknown. Likely a face-remapping or overlay interaction with the theme. Blocked on the face/font diagnostic tool above for diagnosis. From the roam inbox.
** TODO [#A] theme-studio: elfeed ignores theme assignments :bug:
@@ -68,9 +68,9 @@ build-theme.el's UI tier passes inherit=nil to --attrs, so a UI face that relies
The UI table gives the cursor face the full control set (fg, B/I/U/S, box), but Emacs only honors the cursor face's :background. Its shape is cursor-type, not a face attribute, so every other control on that row is a no-op once the theme loads. Restrict the cursor row to just its background swatch so the studio doesn't present controls Emacs drops.
** DONE [#B] org-faces: custom header-row face layer + theme-studio app :feature:theme-studio:spec:
CLOSED: [2026-06-15 Mon]
-Named, theme-agnostic faces for org TODO keywords and priorities, wired via org-todo-keyword-faces / org-priority-faces, plus a dedicated theme-studio "org-faces" app beside elfeed and mu4e. Spec: [[file:docs/design/org-faces-spec.org][org-faces-spec.org]]. All four decisions resolved (prefix org-faces-, real defface defaults, auto-dim repointed to org-faces-*-dim, all 10 keywords). Phase 1 (modules/org-faces-config.el + 5 ERT tests), Phase 2 (auto-dim-config.el repoint), Phase 3 (theme-studio org-faces app) all landed and verified; the build-theme round-trip is confirmed mechanically. Residual visual check is a VERIFY under Manual testing and validation.
+Named, theme-agnostic faces for org TODO keywords and priorities, wired via org-todo-keyword-faces / org-priority-faces, plus a dedicated theme-studio "org-faces" app beside elfeed and mu4e. Spec: [[id:35578114-8c29-43af-97a2-fdfea01a802e][org-faces-spec-implemented.org]]. All four decisions resolved (prefix org-faces-, real defface defaults, auto-dim repointed to org-faces-*-dim, all 10 keywords). Phase 1 (modules/org-faces-config.el + 5 ERT tests), Phase 2 (auto-dim-config.el repoint), Phase 3 (theme-studio org-faces app) all landed and verified; the build-theme round-trip is confirmed mechanically. Residual visual check is a VERIFY under Manual testing and validation.
** TODO [#D] org-faces: dim variants and retire dupre-org-* :feature:theme-studio:
-vNext from the org-faces spec: org-faces-*-dim variants wired into auto-dim so keywords stay legible in unfocused windows, and migrate or retire the legacy dupre-org-* set. [[file:docs/design/org-faces-spec.org][org-faces-spec.org]]
+vNext from the org-faces spec: org-faces-*-dim variants wired into auto-dim so keywords stay legible in unfocused windows, and migrate or retire the legacy dupre-org-* set. [[id:35578114-8c29-43af-97a2-fdfea01a802e][org-faces-spec-implemented.org]]
** TODO [#C] Cursor buffer-state coloring — decide keep-theme-driven vs remove :refactor:
Roam-inbox ask: remove the code that colors the cursor by buffer state (read-only / modified / unmodified) because it interferes with themes and "will never match." Open question: commit 7ccc3f5c reworked this so the cursor color now resolves through theme faces (error/warning/success) and tracks the active theme. Decide whether the theme-driven version satisfies the concern or the buffer-state cursor coloring should be removed entirely. From the roam inbox.
** TODO [#B] Unified popup placement and dismissal rules :feature:
@@ -100,7 +100,7 @@ The ai-term window should dock from whichever edge conserves more screen space,
:PROPERTIES:
:LAST_REVIEWED: 2026-06-13
:END:
-Spec: [[file:docs/design/keybinding-console-safety-spec.org][keybinding-console-safety-spec.org]]. Phase 0 (revert 4a1ecf64) is done and pushed. Decisions D1-D5 are open TODOs in the spec; D2/D4/D5 gate the primary work (Phase 1 prune via Appendix D, Phase 2 consolidate + retire the translation block), while D1/D3 (the console-safe prefix) gate only the optional Phase 3 and can stay open indefinitely. Resolve D2/D4/D5, then run Phase 1-2. Appendix D is the keybinding pruning checklist. Add a =#+TODO: TODO | DONE SUPERSEDED CANCELLED= header line to the spec if adopting those decision keywords (rulesets convention update, 2026-06-12).
+Spec: [[id:540bf06b-16b8-46c6-b459-c40d1b9c795d][keybinding-console-safety-spec-doing.org]]. Phase 0 (revert 4a1ecf64) is done and pushed. Decisions D1-D5 are open TODOs in the spec; D2/D4/D5 gate the primary work (Phase 1 prune via Appendix D, Phase 2 consolidate + retire the translation block), while D1/D3 (the console-safe prefix) gate only the optional Phase 3 and can stay open indefinitely. Resolve D2/D4/D5, then run Phase 1-2. Appendix D is the keybinding pruning checklist. Add a =#+TODO: TODO | DONE SUPERSEDED CANCELLED= header line to the spec if adopting those decision keywords (rulesets convention update, 2026-06-12).
** TODO [#D] Desktop quick-capture: Note + Recipe types :feature:solo:
Deferred 2026-06-13 — build when the need triggers, not ahead of use. Add generic Note (timestamped datetree) and Recipe (skeleton with Ingredients/Instructions + :SOURCE:) capture types to =cj/quick-capture= in =modules/org-capture-config.el=: one template each with an absolute target plus its key in the desktop subset; reuse the existing frame-cleanup. Full design in the archsetup handoff (2026-06-13 note in the inbox/sessions).
@@ -372,14 +372,14 @@ Decided 2026-06-11 (Craig): #0d0b0a is the canonical background — the three dr
:END:
From the color-assignment guide work (2026-06-08): make the tool support the guide without mandating it — everything a seed, an advisory, or a view, never a gate. Two specs to write, both deriving from the rewritten guide and its seed table ([[file:scripts/theme-studio/theme-coloring-guide.org][theme-coloring-guide.org]]).
*** 2026-06-08 Mon @ 19:08:00 -0500 Seeding-engine spec written and Ready
-[[file:docs/design/theme-studio-seeding-engine-spec.org][theme-studio-seeding-engine-spec.org]] — role table + face→role maps for syntax/UI/org, OKLCH shade generation, reseed dupre-revised to the compact mapping. Codex-reviewed, Ready. Implementation tracked under the seeding-engine parent below.
+[[id:b70b37f2-37df-4c8e-ac2f-1f20d12e33dd][theme-studio-seeding-engine-spec-doing.org]] — role table + face→role maps for syntax/UI/org, OKLCH shade generation, reseed dupre-revised to the compact mapping. Codex-reviewed, Ready. Implementation tracked under the seeding-engine parent below.
*** TODO Guide-support views and advisories spec
Five optional surfaces, all dismissible and non-blocking, in one collapsible panel where they advise: (1) CVD-simulation toggle on previews (deuteranopia/protanopia/tritanopia); (2) squint/blur preview toggle; (3) lightness-ramp view + palette advisories (accent count over 6-8, roles separated only by red/green) — depends on the OKLCH/ΔE core; (4) definition-vs-call / weight advisories; (5) state-over-syntax preview (region/search/diff tint over real syntax-colored text). Sequence: rewritten guide reviewed → seeding-engine spec → this. Advisories (3, 4) layer on the perceptual-metrics feature.
** TODO [#B] theme-studio seeding engine :feature:
:PROPERTIES:
:LAST_REVIEWED: 2026-06-13
:END:
-Spec (Ready): [[file:docs/design/theme-studio-seeding-engine-spec.org][spec]]. Role table → guide-correct defaults for syntax/UI/org; reseed dupre-revised.json to the compact mapping; opens seeded with an all-tier reseed button. Depends on the perceptual-metrics colormath.js core for OKLCH shade generation, so it runs after that feature's Phase 1.
+Spec (Ready): [[id:b70b37f2-37df-4c8e-ac2f-1f20d12e33dd][spec]]. Role table → guide-correct defaults for syntax/UI/org; reseed dupre-revised.json to the compact mapping; opens seeded with an all-tier reseed button. Depends on the perceptual-metrics colormath.js core for OKLCH shade generation, so it runs after that feature's Phase 1.
*** TODO Seed model + seed() + #seedtest :solo:
Phase 1. Palette anchors + OKLCH shade generation (reusing colormath.js), the ROLES table, and the three face→role maps as data; pure seed(). Gate: #seedtest asserts representative syntax/UI/org faces resolve correctly (bi→blue-grey, fnd→gold+bold, region bg-only, link underlined, org-level-1 strongest, org-code literal lane) and a non-org bespoke package (magit) keeps its curated seed.
*** TODO Open-seeded + reseed + dupre-revised regen :solo:
@@ -946,7 +946,7 @@ Tie this into the existing coverage work:
:PROPERTIES:
:LAST_REVIEWED: 2026-06-13
:END:
-Spec: [[file:docs/design/messenger-unification-spec.org][messenger-unification-spec.org]] (Draft, 2026-06-11). One library (=cj-messenger-lib.el=) gives every messenger the same shape: chat windows rise from the bottom (the signel rule, generalized), C-c C-c confirms, C-c C-k cancels, C-c C-a attaches — dispatched per backend through a registry + minor mode. Signel already conforms (reference backend); telega and slack join in phases 2-3; ERC later. All eight decisions settled 2026-06-11 (cancel closes an idle window; telega's filter-cancel shadow accepted; slack rooms join the bottom rule). Spec held open — Craig has more ideas to fold in before it's marked Ready.
+Spec: [[id:4bfc2011-8ffc-4765-8886-91df12141171][messenger-unification-spec.org]] (Draft, 2026-06-11). One library (=cj-messenger-lib.el=) gives every messenger the same shape: chat windows rise from the bottom (the signel rule, generalized), C-c C-c confirms, C-c C-k cancels, C-c C-a attaches — dispatched per backend through a registry + minor mode. Signel already conforms (reference backend); telega and slack join in phases 2-3; ERC later. All eight decisions settled 2026-06-11 (cancel closes an idle window; telega's filter-cancel shadow accepted; slack rooms join the bottom rule). Spec held open — Craig has more ideas to fold in before it's marked Ready.
** TODO [#C] cj/undo-kill-buffer skip-visited uses delq (eq) on path strings :bug:quick:solo:
:PROPERTIES:
@@ -1367,10 +1367,10 @@ recommends grouping and naming, explains how the helpers fit into existing
library modules, defines migration phases, and identifies testing/rollback
rules.
-Spec: [[file:docs/design/utility-consolidation.org][docs/design/utility-consolidation.org]]
+Spec: [[id:fc2e3926-b4a1-4b45-92eb-20841e13f655][docs/specs/utility-consolidation-spec-doing.org]]
Verify 2026-05-04:
-- Added [[file:docs/design/utility-consolidation.org][docs/design/utility-consolidation.org]].
+- Added [[id:fc2e3926-b4a1-4b45-92eb-20841e13f655][docs/specs/utility-consolidation-spec-doing.org]].
- Spec includes framing questions, existing library fit, proposed grouping,
concrete pull/rename table, migration phases, test strategy, acceptance
criteria, risks, open questions, and recommended first commits.
@@ -1558,7 +1558,7 @@ almost every module in a fixed order. That makes modules harder to test in
isolation and hides real dependencies behind "loaded earlier in init.el"
assumptions.
-Spec: [[file:docs/design/init-load-graph.org][docs/design/init-load-graph.org]]
+Spec: [[id:e1fd137e-e164-42f4-a658-f4d32fbe3228][docs/specs/init-load-graph-spec-doing.org]]
**** 2026-05-25 Mon @ 07:59:20 -0500 Wrote full design spec for the =init.el= load-graph refactor :refactor:
@@ -1573,7 +1573,7 @@ Review incorporation:
has a clear rule for duplicated helpers found along the way.
Verify 2026-05-04:
-- Added [[file:docs/design/init-load-graph.org][docs/design/init-load-graph.org]].
+- Added [[id:e1fd137e-e164-42f4-a658-f4d32fbe3228][docs/specs/init-load-graph-spec-doing.org]].
- Incorporated review feedback by making utility consolidation an explicit
sibling project with guardrails and candidate helper families.
- Parsed the spec and =todo.org= with =org-element=.
@@ -1654,7 +1654,7 @@ Expected outcome:
:PROPERTIES:
:LAST_REVIEWED: 2026-06-04
:END:
-Replace vterm with ghostel (libghostty-vt) as the single terminal engine across every workflow, and rename ai-vterm → ai-term. References: [[file:docs/2026-05-25-emacs-terminal-comparison.org][docs/2026-05-25-emacs-terminal-comparison.org]] (vterm vs eat vs ghostel research); migration spec [[file:docs/design/vterm-to-ghostel-migration-spec.org][docs/design/vterm-to-ghostel-migration-spec.org]] (READY; external review incorporated 2026-06-04, D1-D7 agreed). Build in 5 phases (0-4); see the spec's Implementation tasks block.
+Replace vterm with ghostel (libghostty-vt) as the single terminal engine across every workflow, and rename ai-vterm → ai-term. References: [[file:docs/2026-05-25-emacs-terminal-comparison.org][docs/2026-05-25-emacs-terminal-comparison.org]] (vterm vs eat vs ghostel research); migration spec [[id:b54c94a0-d762-4b41-afd7-cf5593ce6675][docs/specs/vterm-to-ghostel-migration-spec-implemented.org]] (READY; external review incorporated 2026-06-04, D1-D7 agreed). Build in 5 phases (0-4); see the spec's Implementation tasks block.
Decisions D1-D7 are settled in the spec's Agreed-decisions section. Build order below; each phase stays green (suite + byte-compile) at every step.
@@ -1684,7 +1684,7 @@ Deleted auto-dim's vterm color-advice + redraw integration (~165 lines; D1 — t
=package-delete='d vterm + vterm-toggle from elpa. No vterm refs remain in modules/init except intentional historical comments. Suite green except the 4 pre-existing dupre-theme failures (the popper-config one is now fixed). validate-modules ✓; full early-init+init batch smoke = INIT-SMOKE-OK. The migration parent stays DOING until Craig restarts Emacs and walks the ghostel manual-verify matrix under "Emacs Manual Testing and Validation".
*** 2026-06-05 Fri @ 14:24:02 -0500 Auto-dim revisit cancelled — current no-dim behavior is fine
-Craig confirmed the shipped auto-dim setup works fine as-is: terminal buffers don't participate in unfocused-window dimming (D1), and the rest of auto-dim behaves. That is the measured decision the original task asked for — option (a), keep no-dim — so no rework (the focus-loss palette-blend in option (b) or an upstream per-window hook in option (c)) is needed. Closing without further investigation. Context: [[file:docs/design/vterm-to-ghostel-migration-spec.org][migration spec]] D1.
+Craig confirmed the shipped auto-dim setup works fine as-is: terminal buffers don't participate in unfocused-window dimming (D1), and the rest of auto-dim behaves. That is the measured decision the original task asked for — option (a), keep no-dim — so no rework (the focus-loss palette-blend in option (b) or an upstream per-window hook in option (c)) is needed. Closing without further investigation. Context: [[id:b54c94a0-d762-4b41-afd7-cf5593ce6675][migration spec]] D1.
*** 2026-05-26 Tue @ 15:15:43 -0500 Direction confirmed; Claude Code in eat needs a caveat
Craig confirmed the consolidation: one terminal engine everywhere — eat for standalone terminal buffers (replacing vterm) plus =eat-eshell-mode= as eshell's visual backend, keeping eshell as the shell. Not dropping eshell for eat + zsh.
@@ -1702,13 +1702,13 @@ Task audit found no eval work recorded since the 2026-05-26 direction-confirmed
Direction changed from eat-everyday + ghostel-for-Claude to ghostel-for-everything, and the task is now a migration rather than an eval. Rationale: ghostel is claude-code.el's most-faithful Claude TUI renderer and the fastest engine (81 vs vterm 34 vs eat 4.9 MB/s), and an audit confirmed it exposes an analog for every vterm primitive this config uses (=ghostel-send-string=, =ghostel-keymap-exceptions=, =ghostel-copy-mode=, =ghostel-clear-scrollback=, =ghostel-send-next-key=, =ghostel-next-prompt= / =ghostel-previous-prompt=, =ghostel-max-scrollback=, =ghostel-kill-buffer-on-exit=). eat's washed colors, the scroll-pop / stuck-input bug under Claude Code, and slowest throughput made it the weaker single-engine pick; one engine beats running two. Surface audited: 2 main modules (=vterm-config.el=, =ai-vterm.el=) + 4 satellites (=auto-dim-config.el= is the heavy one) + ~35 test files + init.el. Next: spike ghostel read-only to answer the open migration questions (auto-dim rework — ARCHITECTURE.md forbids the around-redraw color advice vterm uses; tmux pane-id via =process-tty-name= on a ghostel process; buffer naming; TTY-frame behavior; copy-mode keybinding parity), then write the migration spec under =docs/design/= and review it.
*** 2026-06-04 Thu @ 23:17:54 -0500 Spec review: not ready until decisions and handoff shape are closed
-Ran the spec-review workflow against [[file:docs/design/vterm-to-ghostel-migration-spec.org][docs/design/vterm-to-ghostel-migration-spec.org]] and wrote a companion review file (incorporated and deleted 2026-06-04). Verdict: =Not ready=. Direction is sound, but the draft still has open D1-D5 decisions, lacks the workflow-required =Implementation phases= section and acceptance criteria, and needs explicit ghostel package/native-module failure behavior before implementation tasks can be emitted.
+Ran the spec-review workflow against [[id:b54c94a0-d762-4b41-afd7-cf5593ce6675][docs/specs/vterm-to-ghostel-migration-spec-implemented.org]] and wrote a companion review file (incorporated and deleted 2026-06-04). Verdict: =Not ready=. Direction is sound, but the draft still has open D1-D5 decisions, lacks the workflow-required =Implementation phases= section and acceptance criteria, and needs explicit ghostel package/native-module failure behavior before implementation tasks can be emitted.
*** 2026-06-04 Thu @ 23:24:28 -0500 Spec-response: review incorporated, raised to READY
Folded the external review via spec-response. Craig accepted D1-D5; baked them plus D6 (module-failure = degrade-with-warning, modifying the reviewer's fail-loud) and D7 (=ghostel-max-scrollback= 10 MB) into a new Agreed-decisions section. Added Implementation phases (0-4), Acceptance criteria, Dependency/module-failure behavior, Test strategy, per-phase key/menu ownership, the tmux-suppression contract, and an Implementation-tasks drop-in block. Status DRAFT → READY; review file deleted. Build is now unblocked.
*** 2026-06-04 Thu @ 23:30:18 -0500 External re-review: ready
-Re-reviewed [[file:docs/design/vterm-to-ghostel-migration-spec.org][docs/design/vterm-to-ghostel-migration-spec.org]] after incorporation. Verdict: =Ready=. No further blocking review notes; implementation can start from the phase plan and acceptance criteria in the spec.
+Re-reviewed [[id:b54c94a0-d762-4b41-afd7-cf5593ce6675][docs/specs/vterm-to-ghostel-migration-spec-implemented.org]] after incorporation. Verdict: =Ready=. No further blocking review notes; implementation can start from the phase plan and acceptance criteria in the spec.
** DOING [#B] Module-by-module hardening
:PROPERTIES:
@@ -2310,7 +2310,7 @@ Completion review 2026-05-15:
All three children landed: shared cache helper extracted, idle timers gated, and directory-scan failures surfaced instead of hidden.
***** 2026-05-23 Sat @ 04:18:44 -0500 Extracted a shared cache helper
-=cj-cache-lib.el= now provides =cj/cache-valid-p=, =cj/cache-building-p=, and =cj/cache-value-or-rebuild=, consumed by both =org-agenda-config.el= and =org-refile-config.el=; the contract is documented in =docs/design/cache-helper-design.org=. The agenda and refile public commands are unchanged.
+=cj-cache-lib.el= now provides =cj/cache-valid-p=, =cj/cache-building-p=, and =cj/cache-value-or-rebuild=, consumed by both =org-agenda-config.el= and =org-refile-config.el=; the contract is documented in =docs/specs/cache-helper-design-spec-implemented.org=. The agenda and refile public commands are unchanged.
***** 2026-05-24 Sun @ 07:26:31 -0500 Surfaced directory-scan failures instead of hiding/crashing
@@ -3096,7 +3096,7 @@ Review [[https://www.jamescherti.com/essential-emacs-packages/][James Cherti's e
** TODO [#C] dupre-clear theme — contrast-first AAA sibling :feature:
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).
+Full design + methodology + starting palette + open questions in the spec: [[id:20df7f50-4759-47ba-9782-8dd25a2e173e][docs/specs/dupre-clear-theme-spec.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).
** TODO [#C] theme-studio terminal/ANSI colors :feature:
theme-studio represents GUI faces only; terminal colors aren't surfaced at all. Scope decided 2026-06-09: GUI-first faces, NOT full per-face display-class fallback. Two pieces:
@@ -3121,7 +3121,7 @@ Display slack.el message and thread buffers in a dedicated popup window (side or
:LAST_REVIEWED: 2026-06-01
:END:
*** 2026-05-15 Fri @ 19:17:01 -0500 Specification
-Implement the design in [[file:docs/design/music-config-without-emms.org][Design: music-config Without EMMS]].
+Implement the design in [[id:423bc355-18d3-4e39-9e7a-f768b865d95b][Design: music-config Without EMMS]].
The implementation should make =music-config.el= load without EMMS, introduce
package-owned playlist and track state, add a =cj/music-playlist-mode= view,
@@ -3280,13 +3280,13 @@ structured workspace, not a text terminal. Per-theme spec lives in
the task body once written; implementation tasks land as siblings
of the spec heading once the spec is approved. The magit-backend
reimplementation of the shipped git tools is tracked separately in
-[[file:docs/design/gptel-git-tools-magit-backend.org][gptel-git-tools-magit-backend.org]].
+[[id:bd47c9a8-aae1-4a3d-ad5b-b8767f2fd580][gptel-git-tools-magit-backend-spec.org]].
*** TODO [#C] Wire Up MCP.el so That GPTel Has Access to MCP Servers via GPTel Tools
**** 2026-05-16 Sat @ 15:44:36 -0500 Spec
-Design doc: [[file:docs/design/mcp-el-gptel-integration.org][docs/design/mcp-el-gptel-integration.org]]
+Design doc: [[id:b4c274c5-8572-4a7b-b657-d315712bd6af][docs/specs/mcp-el-gptel-integration-spec-doing.org]]
**** 2026-05-17 Sun @ 14:14:34 -0500 Landed ai-mcp.el pure-helper foundation
@@ -3414,7 +3414,7 @@ Commit =54d231be=. Sections 1 (constants + defcustoms) and 3 (pure helpers) of
**** 2026-05-16 Sat @ 16:20:00 -0500 Spec
-Design doc: [[file:docs/design/gptel-gh-tool.org][docs/design/gptel-gh-tool.org]]
+Design doc: [[id:a124dd0f-1f40-4533-aeb8-595d93e20865][docs/specs/gptel-gh-tool-spec.org]]
*** TODO [#C] GPTel should autosave regularly after a conversation is saved
*** TODO [#B] Org Workflow Related Tools
@@ -3790,7 +3790,7 @@ These may override useful defaults - review and pick better bindings:
- M-S-y yank-media (was overriding yank-pop)
- M-S-z undo-kill-buffer (was overriding zap-to-char)
-** TODO [#C] Build cj/dev-setup-project helper (per docs/design/dev-setup-project.org) :feature:
+** TODO [#C] Build cj/dev-setup-project helper (per docs/specs/dev-setup-project-spec.org) :feature:
:PROPERTIES:
:LAST_REVIEWED: 2026-06-01
:END:
@@ -3798,7 +3798,7 @@ These may override useful defaults - review and pick better bindings:
Interactive command that opens a review buffer with proposed per-subdirectory .dir-locals.el contents (projectile compile/run/test + cj/coverage-backend), optional starter Makefile when none exists, and gitignore updates. User edits inline, C-c C-c writes all files.
-Design: [[file:docs/design/dev-setup-project.org][docs/design/dev-setup-project.org]]
+Design: [[id:596fce5d-1bab-46e7-8567-d4a2e0923091][docs/specs/dev-setup-project-spec.org]]
Scope of v1:
- modules/dev-setup-config.el (command + review-buffer major mode)
@@ -3946,7 +3946,7 @@ Do this after the F-key rework ticket ships so F5 is the only hole left.
Reusable profiling infrastructure for targeted slow-command investigation. Consolidates scattered profiler bindings (currently in =modules/config-utilities.el=) and adds two pure-helper-backed entry points: "profile next command" and "time region or sexp." Designed via =/brainstorm= 2026-04-26.
-Design: [[file:docs/design/debug-profiling.org][docs/design/debug-profiling.org]]
+Design: [[id:c713b431-ae14-498d-aba9-b84d52f981b6][docs/specs/debug-profiling-spec.org]]
Implement via =/start-work= against the design — branch =feat/debug-profiling=, commits decomposed along the test-first split-for-testability boundary. Once shipped, use it as the v1 exercise on the queued [#B] org-capture target-building investigation.
@@ -4341,7 +4341,7 @@ First pass can skip or mark as unsupported:
:LAST_REVIEWED: 2026-06-02
:END:
-Spec: [[file:docs/design/company-to-corfu-migration.org][docs/design/company-to-corfu-migration.org]]
+Spec: [[id:68733ba2-37a7-4a7b-bfaa-b845d82ff1e7][docs/specs/company-to-corfu-migration-spec.org]]
*** TODO [#C] Install corfu-side packages
Add corfu, cape, kind-icon, corfu-prescient to the package list. corfu-popupinfo ships inside corfu. Spec step 1.
@@ -4654,11 +4654,11 @@ What we're verifying: C-c c t and C-c c b file into the current projectile proje
Expected: in-project captures land in that project's Open Work; out-of-project captures fall back to the global inbox with a warning.
** TODO [#D] theme-studio per-tier reseed controls :feature:
-Deferred from the seeding-engine spec (vNext). V1 reseeds all three guide-owned tiers at once; later consider separate "reseed syntax", "reseed UI", and "reseed package/org" controls if all-at-once proves too blunt. Spec: [[file:docs/design/theme-studio-seeding-engine-spec.org][spec]] (vNext; review folded in 2026-06-08).
+Deferred from the seeding-engine spec (vNext). V1 reseeds all three guide-owned tiers at once; later consider separate "reseed syntax", "reseed UI", and "reseed package/org" controls if all-at-once proves too blunt. Spec: [[id:b70b37f2-37df-4c8e-ac2f-1f20d12e33dd][spec]] (vNext; review folded in 2026-06-08).
** TODO [#D] theme-studio low-contrast preset/mask mode :feature:
-Deferred from the perceptual color metrics spec (vNext). After raw OKLCH/APCA/DeltaE readouts exist, decide whether to add a named low-contrast workflow: APCA Lc bands, a contrast ceiling/floor mask, or a "soft" sibling to the existing any/AA+/AAA picker mask. Spec: [[file:docs/design/theme-studio-perceptual-color-metrics-spec.org][spec]] (vNext candidates; review folded in 2026-06-08).
+Deferred from the perceptual color metrics spec (vNext). After raw OKLCH/APCA/DeltaE readouts exist, decide whether to add a named low-contrast workflow: APCA Lc bands, a contrast ceiling/floor mask, or a "soft" sibling to the existing any/AA+/AAA picker mask. Spec: [[id:15db8ae3-fc14-49f3-9ed5-d5ff59790904][spec]] (vNext candidates; review folded in 2026-06-08).
** TODO [#D] theme-studio CIEDE2000 DeltaE option :feature:
-Deferred from the perceptual color metrics spec (vNext). v1 uses DeltaE-OK on its native scale with a 0.02 threshold (decided); revisit CIEDE2000 only if the native OKLab scale proves too unfamiliar or poorly calibrated for palette distinguishability. Spec: [[file:docs/design/theme-studio-perceptual-color-metrics-spec.org][spec]] (vNext candidates; review folded in 2026-06-08).
+Deferred from the perceptual color metrics spec (vNext). v1 uses DeltaE-OK on its native scale with a 0.02 threshold (decided); revisit CIEDE2000 only if the native OKLab scale proves too unfamiliar or poorly calibrated for palette distinguishability. Spec: [[id:15db8ae3-fc14-49f3-9ed5-d5ff59790904][spec]] (vNext candidates; review folded in 2026-06-08).
** TODO [#D] Treesitter grammar offline cache :feature:
Treesitter grammars are downloaded by =treesit-auto= on first use and live outside the localrepo. For true offline reproducibility, cache the grammars next to the localrepo (a =.localrepo/treesitter/= tier, or a separate mirror script). Cross-linked from =docs/design/localrepo.org=.
@@ -5190,12 +5190,12 @@ Auto-compress after recording.
Move to cloud sync directory.
Generate transcript (once transcription workflow exists).
-** DONE [#B] Implement coverage reporting (per docs/design/coverage.org)
+** DONE [#B] Implement coverage reporting (per docs/specs/coverage-spec-implemented.org)
CLOSED: [2026-04-23]
Diff-aware coverage report with pluggable backends. Shipped v1 on 2026-04-23.
-Design: [[file:docs/design/coverage.org][docs/design/coverage.org]]
+Design: [[id:7d7f4486-fad7-4f0a-bd9a-775bd4cd8f7e][docs/specs/coverage-spec-implemented.org]]
What shipped:
- modules/coverage-core.el (engine, backend registry, cj/coverage-report, cj/coverage-report-mode)
@@ -5204,7 +5204,7 @@ What shipped:
- tests/run-coverage-file.el (undercover driver for the Makefile)
- ERT tests for all pure helpers (parse-simplecov, parse-diff, intersect, format-report, backend registry, scope lookup) plus one smoke test for the command
- F7 global binding
-- docs/design/coverage.org (design doc with historical LCOV→simplecov pivot note)
+- docs/specs/coverage-spec-implemented.org (design doc with historical LCOV→simplecov pivot note)
Notable pivots during implementation:
- Switched collection format from LCOV to simplecov (undercover's :merge-report t only supports simplecov).
@@ -6270,7 +6270,7 @@ Assessed already-covered (pure logic tested; remaining % is interactive only —
Net: the coverage backlog is cleared — every module's testable logic is covered; the residual low percentages are interactive/config/process code that the testing rules say not to chase.
** DONE [#B] Review all config and pull library functions into system-lib file :refactor:
-Superseded by =PROJECT [#B] Consolidate shared utility helpers= (the structured version of this, with =docs/design/utility-consolidation.org= as the spec and =docs/design/utility-inventory.org= as the config-wide audit -- 30 candidate helpers across all modules, decided 11 Migrate / 3 Leave / 13 Defer). The system-lib extractions shipped 2026-05-10: =c75e36f= (=cj/executable-find-or-warn= from mail-config), =f1e8f08= (=cj/shell-quote-argument-readable= from dev-fkeys), =57e558c= (=cj/process-output-or-error= + =cj/git-output-or-error= from coverage-core), =aa72245= (=cj/file-from-context= from system-utils), plus the earlier =8e8152e= (=cj/log-silently=) -- each with its own test file. The rest of the 11 Migrate items landed as new =-lib.el= modules in the same marathon (=cj-cache-lib.el=, =cj-org-text-lib.el=, =external-open-lib.el=, =cj-window-geometry-lib.el=, =cj-window-toggle-lib.el=). The 13 deferred candidates remain tracked under the Consolidate-shared-utility-helpers PROJECT, not here.
+Superseded by =PROJECT [#B] Consolidate shared utility helpers= (the structured version of this, with =docs/specs/utility-consolidation-spec-doing.org= as the spec and =docs/design/utility-inventory.org= as the config-wide audit -- 30 candidate helpers across all modules, decided 11 Migrate / 3 Leave / 13 Defer). The system-lib extractions shipped 2026-05-10: =c75e36f= (=cj/executable-find-or-warn= from mail-config), =f1e8f08= (=cj/shell-quote-argument-readable= from dev-fkeys), =57e558c= (=cj/process-output-or-error= + =cj/git-output-or-error= from coverage-core), =aa72245= (=cj/file-from-context= from system-utils), plus the earlier =8e8152e= (=cj/log-silently=) -- each with its own test file. The rest of the 11 Migrate items landed as new =-lib.el= modules in the same marathon (=cj-cache-lib.el=, =cj-org-text-lib.el=, =external-open-lib.el=, =cj-window-geometry-lib.el=, =cj-window-toggle-lib.el=). The 13 deferred candidates remain tracked under the Consolidate-shared-utility-helpers PROJECT, not here.
** DONE [#C] Clean up calibredb-epub-config.el :refactor:bug:
CLOSED: [2026-05-11 Mon 14:55]
@@ -6936,7 +6936,7 @@ CLOSED: [2026-05-15 Fri]
What if we were writing this as it's own package and couldn't use EMMS. What would that look like?
The spec should be in docs/
Another task should be created to implement the spec
-Spec written in [[file:docs/design/music-config-without-emms.org][Design: music-config Without EMMS]].
+Spec written in [[id:423bc355-18d3-4e39-9e7a-f768b865d95b][Design: music-config Without EMMS]].
** DONE [#B] Update gptel models :chore:
CLOSED: [2026-05-14 Thu]
Anthropic side: bumped Opus 4.6 → 4.7 (current frontier); Sonnet 4.6
@@ -7295,7 +7295,7 @@ transient-setup: Cannot open load file: No such file or directory, gptel-magit
** DONE [#C] Implement flycheck modeline customization :feature:
CLOSED: [2026-05-16 Sat]
-Spec: [[file:docs/design/flycheck-modeline-customization.org][docs/design/flycheck-modeline-customization.org]] (Option 4 / hybrid).
+Spec: [[id:76979608-956e-474f-90a8-8d0c958101a0][docs/specs/flycheck-modeline-customization-spec-implemented.org]] (Option 4 / hybrid).
=modules/flycheck-config.el= got two new =:custom= lines:
=flycheck-mode-line-prefix= → "🐛", =flycheck-mode-success-indicator= →
@@ -7893,7 +7893,7 @@ last-test memory persists per source file; no-match error fires correctly.
Depends on: per-language test discovery.
*** TODO [#B] F7 hand-off to dev-fkeys story :feature:
-Once the coverage track ships ([[file:docs/design/coverage.org][docs/design/coverage.org]]),
+Once the coverage track ships ([[id:7d7f4486-fad7-4f0a-bd9a-775bd4cd8f7e][docs/specs/coverage-spec-implemented.org]]),
confirm F7 binds =cj/coverage-report= and lives alongside F4/F6 in the same
dev-fkeys module so the three keys read as one unit. No new coverage logic
here -- only the binding placement and a short comment block in the module
@@ -7945,7 +7945,7 @@ Per-language test discovery:
- Parsing unopened test files: use with-temp-buffer + insert-file-contents + python-ts-mode (etc.) + treesit-query-capture
- Elisp: built-in sexp navigation; scan for (ert-deftest <name> ...) forms. No tree-sitter needed.
-*F7 — coverage* (already designed in docs/design/coverage.org)
+*F7 — coverage* (already designed in docs/specs/coverage-spec-implemented.org)
**Required moves:**
- Move blacken-buffer (python), shfmt-buffer (sh), clang-format-buffer (c) off F6 to C-; f prefix (already the format-buffer prefix).
@@ -8151,7 +8151,7 @@ Built as scripts/theme-studio/build-theme.el (sibling to build-inventory.el), em
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-studio/README.md= (theme.json section) and =docs/design/theme-studio-package-faces-spec.org= (State and export policy, Relative height, Inheritance).
+- theme.json contract: =scripts/theme-studio/README.md= (theme.json section) and =docs/specs/theme-studio-package-faces-spec-doing.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=.
@@ -8165,7 +8165,7 @@ Scope:
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/=.
** DONE [#B] theme-studio tier-3 package faces :feature:theme:theme-studio:
CLOSED: [2026-06-08 Mon]
-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.
+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: [[id:8f37a1fd-cfd3-4b25-92e5-772468092bdc][docs/specs/theme-studio-package-faces-spec-doing.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.
@@ -8192,7 +8192,7 @@ Rewrote =README.md= for the full tool: three face tiers + palette, the in-page p
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.
** DONE [#B] theme-studio perceptual color metrics :feature:theme:theme-studio:
CLOSED: [2026-06-08 Mon]
-Spec (Ready, opens confirmed 2026-06-08): [[file:docs/design/theme-studio-perceptual-color-metrics-spec.org][docs/design/theme-studio-perceptual-color-metrics-spec.org]]. OKLCH model + perceptual-L/APCA readouts + pairwise ΔE, for building low-contrast themes by metric rather than by eye. All five phases shipped 2026-06-08 (commits 49342bf5, 78260018, 77c7f126, 163d3730, 22605426, 582d8a6a): colormath.js core inlined + WCAG/HSV helpers migrated; picker OKLCH/APCA readouts; palette ΔE warnings; OKLCH edit-model dials; C×L gamut plane. 17 Node tests (colormath 100/93.75/100), six browser hash gates green, inline-integrity guard. vNext deferrals (low-contrast preset, CIEDE2000) remain the two [#D] tasks below. Manual eyeballs tracked under Manual testing.
+Spec (Ready, opens confirmed 2026-06-08): [[id:15db8ae3-fc14-49f3-9ed5-d5ff59790904][docs/specs/theme-studio-perceptual-color-metrics-spec-implemented.org]]. OKLCH model + perceptual-L/APCA readouts + pairwise ΔE, for building low-contrast themes by metric rather than by eye. All five phases shipped 2026-06-08 (commits 49342bf5, 78260018, 77c7f126, 163d3730, 22605426, 582d8a6a): colormath.js core inlined + WCAG/HSV helpers migrated; picker OKLCH/APCA readouts; palette ΔE warnings; OKLCH edit-model dials; C×L gamut plane. 17 Node tests (colormath 100/93.75/100), six browser hash gates green, inline-integrity guard. vNext deferrals (low-contrast preset, CIEDE2000) remain the two [#D] tasks below. Manual eyeballs tracked under Manual testing.
*** 2026-06-08 Mon @ 19:43:50 -0500 Color-math foundation + Node tests landed
Pure color core in =scripts/theme-studio/colormath.js= (OKLab/OKLCH, APCA-W3 0.1.9 exact constants, ΔE-OK, binary-search gamut clamp returning ={hex,clamped}=) shipped in 49342bf5; this phase finished the integration in 78260018. =generate.py= now inlines the colormath.js body into the page script (export-stripped, =COLORMATH_J= placeholder), and the page's lin/rl/contrast/rating/hsv2rgb/rgb2hsv/hex2rgb/rgb2hex copies moved into the module — =rl= reuses the canonical =lin= (0.04045 cutoff), byte-identical to the old 0.03928 form on every #rrggbb (no 8-bit channel falls between the cutoffs; verified over 200k pairs, zero contrast change). =test-colormath.mjs= gained Normal/Boundary/Error cases for the migrated helpers, a seeded hsv-rgb round-trip property test, and an inline-integrity check that the generated page carries the module body verbatim. Gate met: =node --test scripts/theme-studio/*.mjs= 15 pass, colormath.js 100% line / 93.75% branch / 100% func; =node --check= on the spliced script clean; =#selftest= + =#cursortest= PASS in headless Chrome. NOTE: =node --test <dir>= directory-globbing is broken on Node v26 (tries to load the dir as a module) — use the =*.mjs= glob form.
*** 2026-06-08 Mon @ 19:55:53 -0500 Picker OKLCH/APCA readouts landed
@@ -8319,18 +8319,18 @@ Fixed in =modules/org-drill-config.el=: =cj/drill-refile= now =let=-binds =org-r
Follow-up 2026-06-12 (Codex review): the first fix reinvented file-listing with a raw =directory-files= call, bypassing the shared validated entry point =cj/--drill-files-or-error= — no missing/unreadable-dir =user-error=, silent fall-through on an empty dir, and it included leading-dot =.org= files the rest of the module excludes. Re-routed through =cj/--drill-files-or-error= + =expand-file-name=; the test was rewritten into three (validated-helper targets, no global clobber, =user-error= on a missing dir).
** CANCELLED [#B] M-S- launcher keys dead: eww, elfeed, calibredb unreachable :bug:quick:solo:
CLOSED: [2026-06-13 Sat]
-Not a bug. The audit used =key-binding=, which ignores =key-translation-map=, so it read the M-S- launcher chords as dead. They work in GUI: =keyboard-compat.el= installs a =key-translation-map= entry (=M-E -> M-S-e=, etc.) in GUI frames, so Meta+Shift+letter reaches eww/elfeed/calibredb. The "fix" =4a1ecf64= bound =M-E= directly and broke them instead; reverted here. The real console-reachability problem (the chords are dead outside GUI) is the subject of [[file:docs/design/keybinding-console-safety-spec.org][the keybinding-console-safety spec]].
+Not a bug. The audit used =key-binding=, which ignores =key-translation-map=, so it read the M-S- launcher chords as dead. They work in GUI: =keyboard-compat.el= installs a =key-translation-map= entry (=M-E -> M-S-e=, etc.) in GUI frames, so Meta+Shift+letter reaches eww/elfeed/calibredb. The "fix" =4a1ecf64= bound =M-E= directly and broke them instead; reverted here. The real console-reachability problem (the chords are dead outside GUI) is the subject of [[id:540bf06b-16b8-46c6-b459-c40d1b9c795d][the keybinding-console-safety spec]].
** DONE [#B] Signel Client Open Work
CLOSED: [2026-06-12 Fri]
:PROPERTIES:
:LAST_REVIEWED: 2026-06-12
:END:
-Parent task for the Emacs Signal client bring-up. Engine: signal-cli (linked secondary device). Front end: a fork of signel at =~/code/signel=, wired through =modules/signal-config.el=. Design: [[file:docs/design/signal-client.org][docs/design/signal-client.org]].
+Parent task for the Emacs Signal client bring-up. Engine: signal-cli (linked secondary device). Front end: a fork of signel at =~/code/signel=, wired through =modules/signal-config.el=. Design: [[id:0cabd6ee-c458-47b5-a8af-3ee054b25821][docs/specs/signal-client-spec-doing.org]].
Closed 2026-06-12: the bring-up shipped (dated history below). The signel project now has its own =.ai/= scope, so all open signel/signal-cli issues moved to [[file:~/code/signel/todo.org][the signel todo]] and are tracked there flat (the three open children here — handle-error leak, link-with-QR, groups in picker — moved in that pass). Work on =modules/signal-config.el= stays in this file.
*** 2026-06-12 Fri @ 07:34:05 -0500 Signel notify-only-for-unviewed-conversation shipped
-Wire =cj/signal--should-notify-p= (done) into signel's =signel--handle-receive= notify block (signel.el:277), route through Craig's notify script instead of bare =notifications-notify=, and gate sound behind a defcustom that defaults off. Spec addendum (the four notify details + wiring architecture) accepted 2026-06-11 — see [[file:docs/design/signal-client.org][signal-client.org]] "Notification slice".
+Wire =cj/signal--should-notify-p= (done) into signel's =signel--handle-receive= notify block (signel.el:277), route through Craig's notify script instead of bare =notifications-notify=, and gate sound behind a defcustom that defaults off. Spec addendum (the four notify details + wiring architecture) accepted 2026-06-11 — see [[id:0cabd6ee-c458-47b5-a8af-3ee054b25821][signal-client-spec-doing.org]] "Notification slice".
Built 2026-06-11 (TDD; fork commit e263367, dotemacs 9afc6128): =signel-notify-function= customization point in the fork; =cj/signel--notify= + =cj/signal--format-notify-body= + =cj/signel-notify-sound= in signal-config.el, wired in =:config= with a load-time =cj/executable-find-or-warn=. 17 new ERT tests green; full launch smoke clean; live-reloaded into the daemon and a synthetic toast fired through the script path. The two manual checks moved to the Manual testing and validation parent.