Files
maka/docs/session-todo-lifecycle.md
AstroHan 3db83c26a3 chore: retire the Task Ledger domain and drop its storage (#4400)
#4351 removed the Task Ledger protocol operation and coordinator but left the
layers above and below it standing: a 970-line core module, a closed three-file
storage island, a legacy bootstrap path, and the SQLite table that path read
from. Nothing on `main` writes that table any more, and nothing outside the
island reads the modules.

BREAKING: upgrading a workspace last opened by v0.2.0-incubating-rc1 or earlier
discards its unfinished Tasks. Those releases shipped a live Task Ledger, and
`bootstrapLegacyTasks` — the path that would have carried those rows into
SessionTodo on first read — has never shipped in any release. Rather than keep
an unshipped bridge alive for a pre-1.0 surface, workflow schema 12 drops
`workflow_task_ledger_events` outright and the bridge goes with it. Tasks are
not imported; SessionTodo starts empty. Completed and cancelled Tasks were
never going to be imported anyway, and the affected surface is one RC and a
0.1.x line. `CHANGELOG.md` records the affected releases and tells users to
finish, export, or back up outstanding Tasks before first opening this build,
since the migration removes the only live copy.

The drop follows the `workflow_plan_reminders` idiom directly above it. Two
mechanisms that name Task Ledger are deliberately kept:
`RELEASED_WORKFLOW_PROJECTION_TABLES` still retires
`workflow_task_ledger_projections`, which released databases really carry, and
the released-cutover validation contract in `operational-state-store.ts` still
records what a released build wrote to `cutover_journal` — dropping that entry
would fail a workspace closed rather than clean it.

`readOrBootstrap` now persists an empty document, and `initializeCopy` no
longer writes a placeholder row into an uninitialized copy source; both are
observationally unchanged and now have tests that pin the stored rows rather
than only the returned snapshot. Tests that only needed some store to open the
workflow database move to the Plan store, and the schema-10 migration case
asserts the new drop. `docs/session-todo-lifecycle.md` no longer describes the
removed bootstrap.

`apps/desktop/src/renderer/styles/task-ledger.css` is residue from the same
retirement and is tracked separately in #4394.

Closes #4399

Generated-by: Claude Code
2026-09-01 13:01:13 +08:00

7.0 KiB

SessionTodo Lifecycle

Status: Current. The former Session Task Ledger is Removed: its module, storage, and workflow_task_ledger_events table are gone as of workflow schema 12. SessionTodo is the only Session task surface.

This document answers one question for Runtime, Runtime Host, CLI, and Desktop contributors: who owns a Session's current Todo list, and what must happen to that list as the Session is read, copied, archived, or removed?

Mental model

SessionTodo is one small current-state document attached to one Session. It is closer to replacing a whiteboard checklist than appending to an audit log. todo_read returns the whole ordered list; todo_write atomically replaces the whole ordered list.

For example, this write:

{
  "todos": [
    { "content": "inspect the owner", "status": "completed" },
    { "content": "run focused tests", "status": "in_progress" }
  ]
}

commits exactly those two items in that order. A later write containing only the second item removes the first. There is no item identity, patch operation, revision, history, hierarchy, owner, evidence, cursor, or watermark.

completed is model-reported progress. It is not proof that a command ran, a test passed, or a file changed; AgentRun, RuntimeEvent, tool results, filesystem, and git remain the authorities for those facts.

Authority and data flow

The Runtime Host is the sole interactive authority. Storage owns the durable document and migration transaction; Runtime exposes the model tools; CLI and Desktop only render Host-owned results.

model todo_read / todo_write          Desktop read-only panel
              \                         /
               Runtime Host SessionTodo coordinator
                    | admission + Session presence
                    | commit, then signal-only invalidation
                    v
            SQLite SessionTodo current document

todo_write is an internal Host tool port rather than a public Client mutation operation. Desktop reads through session.todo.query. A successful replacement commits before the Host publishes a todo domain invalidation. Reads and first-read initialization are silent because they do not change the effective current list.

The stored document is canonical product state. Before model or Desktop display, content passes through the shared Unicode sanitization, secret redaction, and <session-todo> tag-neutralization projection. Display safety does not rewrite the stored document.

Document contract

Each item contains only:

  • content: non-empty normalized text, at most 200 Unicode code points;
  • status: pending, in_progress, or completed.

The document contains at most 200 items and at most 256 KiB of encoded JSON. These bounds keep the complete snapshot below the Runtime Host frame budget, so the operation needs no paging contract.

An initialized empty list is different from no SessionTodo row. That distinction is what makes explicit clearing deterministic.

First read

The first Host read of an uninitialized Session, through either todo_read or session.todo.query, persists an empty document and returns it. The first explicit todo_write writes the requested complete list directly.

Copy and branch semantics

Conversation copy initializes the target Todo inside the Host-owned copy lifecycle, before the target Session is published:

  • an ordinary branch whose selected cut includes the latest committed turn copies the source's current Todo;
  • a historical cut, before-revision, or side conversation initializes an explicit empty Todo document.

Initialization is one SQLite write transaction. The source's current document is read — an uninitialized source reads as empty, without being written — and the absent target is inserted in the same transaction. Retrying an identical initialization is idempotent; a different or corrupt existing target fails closed instead of being overwritten.

The Runtime Host holds the source and target Session admission lanes during the copy. A failed copy purges the incomplete target's Todo state before discarding the preparing Session.

Archive, removal, backup, and rollback

  • Archive retains the current Todo document.
  • Remove and incomplete-copy discard purge the Todo document, so a deleted Session cannot show stale work if its identifier is observed again.
  • Backup and restore preserve both non-empty and initialized-empty documents.

Rollback across the cutover means restoring a database backup taken before the upgrade. That loses Todo edits made after the backup; running an old binary directly against the upgraded live database is not a supported rollback guarantee.

Upgrading to workflow schema 12 drops workflow_task_ledger_events without migrating it. A workspace last opened by v0.2.0-incubating-rc1 or earlier loses its unfinished Tasks; they are not imported into SessionTodo.

Surface behavior

CLI/TUI renders the settled semantic todo_read or todo_write tool result. It does not present todo_write arguments as committed state, including when a durable transcript is reconstructed after restart.

Desktop renders the same current ordered snapshot as a flat read-only list. Session and request-generation fences reject late responses after navigation; signal-only invalidations trigger a fresh full read rather than client-side merging.

No SessionTodo content is appended to a turn-tail prompt or dynamic system prompt. The model reads it on demand with todo_read.

Code map

  • packages/core/src/session-todo.ts: document validation, bounds, and shared display projection.
  • packages/storage/src/session-todo-store.ts: SQLite persistence, migration, copy initialization, and purge.
  • packages/runtime-host/src/server/session-todo-coordinator.ts: Session admission, presence checks, commit, and invalidation.
  • packages/runtime/src/session-todo-tools.ts: model-facing read and whole-document write tools.
  • packages/runtime-host/src/server/session-revision-coordinator.ts and session-retirement-coordinator.ts: copy and lifecycle integration.
  • apps/desktop/src/main/runtime-host-client.ts: Desktop query adapter and display-safe projection.

The legacy Task codecs, replay, and tables are deleted. Nothing may recreate a second product surface for Session tasks or change this current-document contract.