Files
platform/todo
pastilhasandClaude Opus 5 a3fced25c4 one buffer per file, shared by every panel showing it
The code editor held file contents per panel while Monaco keyed the model by
file URI globally, so two panels on one file had two buffers and one model.
@monaco-editor/react resolves a model as getModel(uri) || createModel(value),
so the second panel adopted the first one's model and its own value was
ignored; the value-sync effect then overwrote the shared model with
executeEdits, and the flag suppressing onChange around that write is
per-instance — so the OTHER panel's onChange fired, and the editor answers that
with setContent. One panel's buffer silently became the other's and the tab
went dirty with no keystroke.

useEditorState now keys buffers by path in one shared store and keeps only the
tab set and active path per panel. openFile discards the content it is handed
when the file is already open elsewhere, mirroring what Monaco does with the
model — that is what removes the divergence, because there is then no value for
the sync effect to reconcile. Buffers are refcounted by holders and dropped
when the last panel closes, so closing a tab cannot discard another panel's
unsaved work; closing the last one still discards, as before.

keepCurrentModel is the other half and was needed under any fix: the default
disposes the shared model on unmount, and key={activeFile.path} makes that
every tab switch rather than only a panel close.

Writes go through queryClient.setQueryData rather than useGlobal's setter,
which applies a functional update to the data captured in render — invisible
with one writer, wrong with one per panel.

Nine tests, and the editor had none before. The known-bugs card stays OPEN: this
removes a mechanism that produces the reported shape, not the mystery of where
the log text came from. The trap stays armed, and it can now fire legitimately
when two panels share a file, so the stack matters more than the count.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Officer-Session: f7a62308-0977-4cf4-aa29-c020853fd420
2026-08-25 07:45:32 +00:00
..

todo/ — the format

One item per file. A file is a card. That is the whole idea, and everything below follows from it.

It replaced a single 1,050-line TODO.md on 2026-08-21, which had reached 72 open items across 28 sections and was read mostly on a phone. The split was mechanical — no prose was rewritten.

Layout

todo/
├── README.md          # this file
├── <theme>/
│   ├── _index.md      # the theme itself: display name, and any prose that belongs to the whole group
│   └── <item>.md      # one item

The theme is the directory. _index.md carries the theme's display heading, so a theme is self-describing and nothing has to hold a slug→name map. TODO.md at the repository root is the generated index over all of it — bun run todo:index.

An item

---
id: fleet/an-orchestrator-that-acts-on-every-server-at
title: 'An orchestrator that acts on every server at once'
theme: fleet
status: open
created: 2026-08-21
date_source: stated
order: 1
---

**An orchestrator that acts on every server at once** — pull and update every platform, restart a
process everywhere, report which host is behind…
  • id — <theme>/<slug>, and it is the filename. Stable: rename the title freely, leave the id alone. Anything pointing at an item points at this.
  • status — open, doing, blocked, backburner or done. The board (/todos) renders one column per value; adding one is a new entry in TODO_STATUSES (api/todos/todo-tree.ts), not a new file or directory. backburner is parked-not-dead — still counted as open by the index.
  • created — the date the item was raised. date_source says how much to trust it: stated (the prose named a date — true), section (inherited from its old section heading — close), assumed (unknown, floored at 2026-08-20, the day before the split — a bounded "before today" rather than an invented day).
  • order — position within the theme, preserved from the original list. What a board reorders.
  • priority (optional) — urgent when the owner says so, absent otherwise. There is no scale of five: an item is either something he named as urgent or it is not, and a scale would only invite everything to drift upward. Urgent items are listed first in the generated index.
  • due (optional) — a date the owner named. Only ever written because he said one; never inferred from tone or from how the item is worded.
  • The body is prose, and it is the point. These entries carry the reasoning, what was verified versus assumed, and what was already tried. An item stripped to a title loses the thing that made this list worth keeping.

Two-way sync — the contract for the Kanban board

A board that reads this tree and writes back to it is a wanted feature (todo/prompt-library/… see todo/tooling/). What it may rely on:

  • A card is a file. Creating a card creates a file; moving a card between columns rewrites one frontmatter field; deleting a card deletes a file. Every board action is a small, reviewable git diff.
  • id is the identity, not the title and not the line number. Renaming or rewording never orphans a card.
  • Frontmatter is the machine's half, the body is the human's half. A board may rewrite frontmatter freely. It must not reformat a body it did not change — the prose is hand-written and a normalising pass would produce a diff nobody can read.
  • TODO.md is generated output. A board must never write to it; it regenerates from the tree.
  • Git is the sync log. No lock file and no sidecar state: the file on disk is the truth, and two writers are resolved the way every other conflict in this repository is.