DSH HUB
HomePlugin StorePlugin PacksCommunityRankingsResourcesPublish Guide
Plugin source
Back to catalog

haruri03 /

haruri03/dsh-todo-ledger

Verified

todo-ledger for DeepSeek Harness: persistent task state, 11 native tools, and cross-session context in a repo-local _todo/ directory (legacy todo/ supported).

★ 0 Stars0 Forks0 IssuesN/A Community rating0 Confirmed installs
View on GitHub
READMESource: main@4c74d081

dsh-todo-ledger

release license

English | 中文

Repository: https://github.com/haruri03/dsh-todo-ledger

A host-level DSH plugin that turns the todo ledger workflow into a resident prompt section, a set of native tools, and context stored inside the repository's _todo/ directory.

It addresses the failure mode where rules live in a skill or AGENTS.md, the model forgets to read them, and the task list has to be rewritten every turn:

Before This plugin
Rules live in AGENTS.md / a skill and stop working when the model does not read them A host-level systemPrompt.section is present every step of every session, with no load step to forget
The system todo_write list is overwritten each turn and progress is lost Authoritative state lives in the repository's _todo/ files and survives sessions and compaction
Context exists only in conversation history and disappears after compaction todo_checkpoint / todo_note write conclusions and next steps into _todo/context/, and a snapshot is injected on every prompt assembly
The model has to assemble shell commands itself 11 native tools with schema validation and readable errors

The file format is fully compatible with an external todo CLI: the plugin and the original CLI can both write the same repository and both can run doctor on it.

Install (manual)

Choose one:

Human: copy this directory to $HOME/.dsh/profiles/<profile>/node_modules/dsh-todo-ledger, then append this row to the profile's cordis.patch.yml:

- insert:
    - id: todo-ledger
      name: './lib/index.js'

Agent: run plugin_manager install_bundle --target "<path-to-plugin>".

Install from Git

When the repository root is the package (it contains package.json and dsh.bundle), install it directly from its Git URL:

plugin_manager install_bundle --target "git+https://github.com/haruri03/dsh-todo-ledger.git"

The same operation is available to humans through the Web plugin page ("Add plugin") or the CLI:

dsh plugin --profile <profile> add "git+https://github.com/haruri03/dsh-todo-ledger.git"

npm package names and tarball URLs are also accepted. To update, remove and reinstall, or wait for an upstream release.

After installation, every new session carries a [todo-ledger · cross-session tasks and context] prompt section, and the tool list gains:

todo_list / todo_add / todo_show / todo_status / todo_complete / todo_archive / todo_note / todo_checkpoint / todo_snapshot / todo_doctor / todo_init

No restart is required.

Layout

Inside the repository root (the directory that contains _todo/; a repository that already keeps todo/ keeps working, the plugin accepts either name):

_todo/
├── todo.md              queue: `- [status] slug`
├── tasks.md             index: `- [status] **slug** — title → [details](tasks/slug.md)`
├── tasks/<slug>.md      details: goal / subtasks / acceptance / progress / blockers / files
├── archived/<slug>.md   completed + ## Delivery record (includes the sign-off quote)
├── AGENTS.md            directory notes generated by todo_init
└── context/             added by this plugin
    ├── now.md           current goal / next step / key files (overwritten by todo_checkpoint)
    └── log.md           append-only log (automatic tool trace + todo_note)

States are todo / doing / blocked / review; there is no done. review means work is finished and waiting for the owner's sign-off. Closing a task requires both evidence and signoff (the owner's own words); neither may be omitted. This is a hard rule of the todo ledger workflow.

Tools

Tool Purpose
todo_list List tasks and states (optionally filtered); call it before starting work
todo_show Show one task's details
todo_add Create a task (unique kebab-case slug)
todo_status Change state and sync the task frontmatter, index, and queue
todo_complete Close and archive a task; requires evidence + signoff
todo_archive Abandon a task; additionally requires reason
todo_note Append to context/log.md; with slug, insert at the end of that task's ## Progress section (the placeholder is removed on first write); with state, advance the state machine in the same call
todo_checkpoint Overwrite context/now.md: current goal / next step / key files
todo_snapshot Read-only: return the snapshot that would be injected into the prompt (check whether the ledger is stale)
todo_doctor Two-way consistency check; returns errors and warnings
todo_init Create the _todo/ skeleton (only when the user asks)

Every tool accepts an optional root, so it can operate on repositories outside the workspace:

todo_doctor { root: "<repo-root>" }.

Sidebar panel

The ledger panel in the sidebar: in progress, to do, awaiting review with an Accept button, and blocked

The plugin also serves a sidebar panel for the ledger of the current session working directory: browsing is read-only, and the panel's only action is accepting a review task. It is opt-in: nothing is injected into the layout until a user opens the panel from the right sidebar's guide capsule (named after the plugin); it then renders as a sidebar tab.

  • Four sections — doing, todo, review, blocked — with a count each, plus a per-state colour so the shape of the ledger reads at a glance.
  • Ordering is fixed: doing first, then todo, review, blocked; an empty section still shows.
  • The panel reads; it does not write task content. Polling runs only while the panel is visible (every 5 s), so a closed or backgrounded tab costs nothing.
  • When a session has no ledger above its working directory, or the ledger files disagree, the panel says so instead of guessing. Run todo_doctor to repair the latter.

Each row under review carries an accept action. Accepting a review task from the panel archives it through the same path as todo_complete, recording the panel click as both the evidence and the sign-off (accepted from the ledger panel at <ISO timestamp>). Only review tasks can be accepted this way; any other state is refused with an inline error rather than an alarm.

The panel talks to two host routes, both read-only in intent and dispatched as GET:

Route Purpose
/todo-ledger/projection?sessionId=<id> Ledger projection for that session's working directory
/todo-ledger/complete?slug=<slug>&sessionId=<id> Accept one review task; the only side-effecting call

A host restart is required after installing or updating the host-side code; the panel itself is plain client JavaScript shipped by the package, so it needs no build step and appears after a page refresh.

Dependencies

Tasks can wait for other tasks. Pass depends_on (a list of slugs) to todo_add, and the task is created blocked with blocker_cause: dependency until every predecessor is formally completed. If the predecessors are already completed, the task is created as todo straight away.

graph LR
  spec["Design the API contract<br/>todo"] --> impl["Implement the endpoint<br/>blocked"]
  spec --> form["Wire the form to it<br/>blocked"]
  impl --> notes["Draft the release notes<br/>blocked"]
  form --> notes
  legacy["Migrate the legacy config loader<br/>blocked, manual"]

Completing spec promotes impl and form to todo in the same call. notes stays blocked until both of its predecessors are completed — one is not enough. legacy has no predecessor: its blocker_cause: manual means nothing unblocks it automatically.

  • Completion only. A predecessor in review does not count; neither does an archived task that was dropped instead of completed. Only todo_complete — or the panel's accept — unblocks.
  • Validated at creation. Unknown, already-dropped, self-referential and circular predecessors are rejected, as is a dependency blocker with no predecessor.
  • Repairable. todo_doctor reports dependency fields that disagree with the archives.

How context survives

  1. On each system-prompt assembly the plugin finds the nearest _todo/ above the session working directory and injects:
    • Ledger last written: N ago (the newest mtime among context/log.md, tasks.md, and now.md);
    • Session staleness: how many tool calls happened since the last todo_* write and how many of them were writes; 3 or more writes adds a ⚠ telling the agent to update the ledger first;
    • Task totals (four states), review items (with (Nd) days waiting) and blocked slugs;
    • Progress of doing tasks: the last real line of the task's ## Progress section (≤80 chars); the whole line is omitted when there is no progress; a state unchanged for 2+ days is marked state Nd unchanged; template placeholders are filtered out;
    • The body of context/now.md and the last 6 log entries.
  2. At every turn end (agent/turn-stopping) the plugin counts write-class operations per turn boundary. At 3 or more it appends a factual log entry (tool calls / writes / state changes) without inventing semantics. If the turn only wrote notes and never advanced a state, the entry says the state machine did not advance. It deliberately does not measure from the last todo_* write, because a final todo_note would reset the counter and hide a turn that edited many files but left a single note.
  3. todo_checkpoint records conclusions, not long excerpts; todo_note records small findings; writes append a trace automatically.
  4. After compaction, a new session, or a DSH restart, the next prompt still carries the snapshot, so work can continue.
  5. Without a _todo/ directory the plugin only injects the rules and mentions todo_init; it never creates the directory on its own.

The unsolved half: the semantic summary is still written by the model. The plugin turns "the ledger is stale" into a visible fact and a ⚠ instead of inventing conclusions for the model.

Configuration

This row in cordis.patch.yml can be adjusted:

- id: todo-ledger
  name: './lib/index.js'
  config:
    root: "<repo-root>"                # optional: pin the repository root
    sectionOrder: 180                  # prompt section order, default 180
    maxSnapshotChars: 4000             # snapshot size limit, default 4000

Without root, the plugin searches upward from the session working directory for _todo/tasks.md; if that fails it uses the TODO_ROOT environment variable.

Verification

node test/smoke.mjs

Coverage: prompt section registration and snapshot rendering, the schemas of all 11 tools, the full init → add → status → note → checkpoint → doctor → complete/archive flow, and rejection of a close without signoff. When TODO_CLI points at an external todo.js, the test also verifies list/doctor interoperability.

Uninstall

plugin_manager remove_bundle --target dsh-todo-ledger

The plugin removes only its own registrations; the _todo/ directory (including context/) is left untouched.

—/ 5

No ratings yet

Verified DSH bundle

Commit 4c74d0812f22

Community comments

No comments yet. Be the first to write one.

DSH HUB

A community index for DSH plugins. Not an official GitHub or DeepSeek AI product.

CommunityResourcesAPIAbout