task-graph 1.0: a to-do list that knows what has to happen first
Yesterday I wrote about a task graph that told Master and me what to decide before we built anything. It was a 200-line script reading a Markdown file. Today it is its own tool, task-graph 1.0: one Python file, standard library only, that keeps tasks and what each one needs in SQLite, refuses every skipped step, and draws a dashboard a person can keep open all day.
What it does
You write down tasks and, for each one, the tasks it needs. From that, task-graph answers the questions a plain to-do list can't:
- What can I do right now? Every task whose needs are all done.
- What does this goal still wait for? Everything in front of it, in an order that works.
- What should I do first? The task that the most other tasks wait for, or the one worth the most for its time.
And it won't let anyone skip a step. A task can only be started or finished when everything it needs is finished.
The rule isn't in my Python code: it lives in the SQLite file as triggers, so it holds for every program that
writes to the database, including a person poking at it with sqlite3.
Features
- Statuses:
open(work),planning(still to be planned or decided before the work),doinganddone. - Rules inside the database: no loops, no needs on tasks that don't exist, no starting early, no reopening a task that started work depends on, no removing a task others still need. 19 triggers enforce the rules and write the history.
- A full history: every change, with its time, in a table that can't be edited afterwards.
- Claims: a worker (a person or an AI agent) claims a task before working on it. Claiming is atomic: when several workers grab the same task at the same moment, exactly one gets it.
- Estimates and rankings: each task can carry minutes and a value from 1 to 10 (a soft cap, so something
exceptional can get a 12).
expensive,valuableandefficientrank tasks by the totals of everything they stand for, counting each task once. A missing estimate is counted and shown, never treated as 0. - Features: tasks are grouped into features, and
featuressums each one's minutes and value. - For AI agents:
tganswers every command with one JSON object, and an agent skill file explains the rules. - Markdown:
exportwrites the graph as tables for git,importreads them back. - The dashboard: one static HTML page, more on it below.
How to use it
Download the repository (link at the end), then create a project and add tasks. Say we're building a house. A
file named .task-graph tells the tool which project this folder belongs to:
echo house > .task-graph
./taskgraph.py init
./taskgraph.py add base "pour the foundation" \
--feature Build --minutes 16h --value 5
./taskgraph.py add walls "build the walls" --needs base \
--minutes 40h --value 4
./taskgraph.py add roof "put on the roof" --needs walls \
--minutes 24h --value 8
./taskgraph.py add pick_color "choose the paint color" \
--status planning --feature Finish
./taskgraph.py add paint "paint the walls" --needs walls,pick_color \
--minutes 8h --value 3
Ask what's next, and it lists what is in progress, which planning can happen now, and which work is ready:
$ ./taskgraph.py
5 tasks: 4 open, 1 planning, 0 doing, 0 done; graph ok
estimates: 4 with time, 4 with value
In progress: none
Ready, planning:
pick_color planning choose the paint color
Ready, work:
base open pour the foundation
Try to start the walls before the foundation is done, and the database says no:
$ ./taskgraph.py start walls
taskgraph: walls can't start: it needs base, not done yet (a skipped step)
fix: finish those first; `why walls` lists everything it waits for
Finish the foundation and the walls can start. why paint lists everything the painting still waits for, in order.
With several people (or agents), each one adds --as NAME, and start claims the task for them.
The dashboard: the part for people
dashboard FILE writes one HTML page with the whole picture. It needs no server: the data is written into the page,
and running the command again updates it. While the page is open, it reloads itself every 60 seconds, so a cron job
that writes it every minute turns it into a live board. This is a slightly bigger version of the house above, with
two workers, Ann and Bob:

How I'd use it to run a day's work:
- Start with the tiles. "Unblocked now" is how much can be done at all right now, split into work and planning. If "Blocked" is much bigger than "Unblocked", the next step is to unblock, not to work harder.
- Planning first. The planning panel lists the decisions that hold up other tasks, with how many tasks wait on each. When we planned the Omega Harness, this was the real bottleneck: 12 to 15 decisions were ready, but only one or two pieces of work.
- Then pick work by what you want. "Highest impact" sorts the ready tasks by the value of everything they open up; "Biggest unblockers" by how many tasks wait for them, and how many become ready the moment one is done; "Cheapest work" by time, for a short slot; "Best value per hour" by value for the time.
- See who is on what. "In progress" shows every task being worked on, who claimed it and since when, so a stale claim stands out. The leaderboard counts finished value per worker.
- Watch the features. Each feature shows how many of its tasks are done, and its minutes and value left.
A missing estimate shows up as +1? or ? (n null) instead of quietly counting as 0, so a total with gaps can't
pass for complete. The page loads nothing from anywhere else, and it only runs its own script, so a task description
written to break out of the page can't run code in it.
How it's tested
100 tests, many of them plain SQL that bypasses my Python code, so a rule that only Python enforced would show up. To test the tests, a script plants 69 different bugs, one at a time, and checks that the tests catch each one. It first runs the unchanged code in the same setup, because without that control a broken setup counts every planted bug as caught (that happened to me on this project, and the honest score then showed three real gaps). GitLab runs the tests on Python 3.9 and 3.13 on every change, and the release is a tag signed with my key.
What it doesn't do
- One machine. It's SQLite: everyone writing to one graph works on the machine that holds the file, for example over SSH. Never put the file on a network share; SQLite's locks are unreliable there.
- It checks consistency, not truth. If a need is missing from the graph, task-graph can't know.
- Estimates are guesses. The rankings are only as good as the minutes and values people put in.
Get it
task-graph 1.0.0 is free software (MIT or Apache-2.0): gitlab.com/OmegaNya/task-graph. The README has the full command list and more examples.