todo: one file per item, grouped by theme, with a generated index

TODO.md had reached 1050 lines and 72 open items across 28 sections, read mostly
on a phone. It is now a directory: todo/<theme>/<item>.md, one card per file, with
frontmatter carrying id, status, created date and order, and the prose body copied
across verbatim. TODO.md becomes a generated index (bun run todo:index).

Dates: where an item's prose stated one it is used; otherwise its old section's;
otherwise 2026-08-20, floored at the day before the split rather than invented.
date_source records which.

Shaped for a two-way Kanban board, filed as todo/tooling — a card is a file, id is
the identity, frontmatter is the machine's half and the body is the owner's.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-21 05:42:39 +00:00
co-authored by Claude Fable 5
parent 8fa560df1b
commit 6071ded175
124 changed files with 2240 additions and 1043 deletions
+14
View File
@@ -0,0 +1,14 @@
---
theme: workspaces-panels
heading: "Workspaces & Panels"
kind: theme
---
Its own list — **`docs/workspace-panel-todo.md`** — because it is long and actively worked. Full
analysis behind it: `COMMS/workspace-panel-framework-analysis-2026-08-07.md`.
Headlines: the framework has **no panel lifecycle** (a panel can be destroyed but never told, which is
the real cause of the terminal orphan leak); three state-key families are **silently dropped on every
write**, orphaning a pty per reload; Running Shells has **404'd since 2026-07-31**; there are **zero
error boundaries** anywhere in the repo; and `dashboards.id` is a **global** primary key fed by
`slugify(name)`, so two members naming a dashboard the same thing collide.
@@ -0,0 +1,21 @@
---
id: workspaces-panels/a-deep-read-of-the-whole-framework-to
title: "A deep read of the whole framework, to understand it and then improve it"
theme: workspaces-panels
status: open
created: 2026-08-20
date_source: assumed
order: 1
---
**A deep read of the whole framework, to understand it and then improve it.** Low priority and
explicitly not pain-driven — it works, and it works well. But it was built fast and then added to,
repeatedly, and nobody has since sat down and read the whole thing at once.
Three questions to answer rather than assume: can the query strings come out of the flow; is there
a better shape for panel-to-panel communication than the current channel/URL split; and what does
the layout tree cost that a simpler one would not.
**Fold the existing panel items into this** — the silent `key`/`appType` mismatch, the destructive
layout migration on a renamed key, and `docs/workspace-panel-todo.md`. They are symptoms of the
same unexamined design, and fixing them one at a time is how it stays unexamined.
Also a teaching exercise: the owner wants to understand it end to end, which is a reason to do it
properly rather than quickly.
@@ -0,0 +1,23 @@
---
id: workspaces-panels/renaming-a-panel-key-is-a-silent-data
title: "Renaming a panel key is a silent data migration, and the repair is destructive"
theme: workspaces-panels
status: open
created: 2026-08-17
date_source: stated
order: 2
---
**Renaming a panel key is a silent data migration, and the repair is destructive.** A saved layout
holds `appType` strings. `normalizeLayout` replaces any appType not in the allow-list with the
caller's `fallback`, and `WorkspaceView.tsx:97` writes that back — so a renamed key turns every
saved layout into N copies of whichever panel is `allowed[0]`, permanently, on one page load.
Renaming `headscale-*` → `offscale-*` did exactly this: `/offscale` rendered three server pickers,
`ServersView` never mounted, and it survived every restart because the code was correct and the
data was not (2026-08-17, `ed3806f9`).
Plugin screens are now cleared at install, which covers plugins and nothing else. The general fix
is a rule about wholesale mismatch: **a layout in which NO panel has a recognised appType is
residue from older code — discard it and use the screen's default**, rather than collapsing it.
`fallback: allowed[0]` is arbitrary (it is whatever `panels.ts` happens to list first) and should
probably not be a per-panel substitution at all.