Deep Dive -- Best read between s12 and s13. It prevents the most common confusion in Stage 3.
Right after s12 (Task System), before you start s13 (Background Tasks). This note separates two meanings of "task" that beginners frequently collapse into one.
This bridge note resolves one confusion that becomes expensive very quickly:
the task in the work graph is not the same thing as the task that is currently running
This note works best between these documents:
- read
s12-task-system.mdfirst to lock in the durable work graph - then read
s13-background-tasks.mdto see background execution - if the terms begin to blur, you might find it helpful to revisit
glossary.md - if you want the fields to line up exactly, you might find it helpful to revisit
data-structures.mdandentity-map.md
The mainline is still correct:
s12teaches the task systems13teaches background tasks
But without one more bridge layer, you can easily start collapsing two different meanings of "task" into one bucket.
For example:
- a work-graph task such as "implement auth module"
- a background execution such as "run pytest"
- a teammate execution such as "alice is editing files"
All three can be casually called tasks, but they do not live on the same layer.
This is the durable node introduced in s12.
It answers:
- what should be done
- which work depends on which other work
- who owns it
- what the progress status is
It is best understood as:
a durable unit of planned work
This layer answers:
- what execution unit is alive right now
- what kind of execution it is
- whether it is running, completed, failed, or killed
- where its output lives
It is best understood as:
a live execution slot inside the runtime
Treat these as two separate tables:
work-graph task
- durable
- goal and dependency oriented
- longer lifecycle
runtime task
- execution oriented
- output and status oriented
- shorter lifecycle
Their relationship is not "pick one."
It is:
one work-graph task
can spawn
one or more runtime tasks
For example:
work-graph task:
"Implement auth module"
runtime tasks:
1. run tests in the background
2. launch a coder teammate
3. monitor an external service
If you do not keep these layers separate, the later chapters start tangling together:
s13background execution blurs into thes12task boards15-s17teammate work has nowhere clean to attachs18worktrees become unclear because you no longer know what layer they belong to
The shortest correct summary is:
work-graph tasks manage goals; runtime tasks manage execution
This is the durable task from s12.
task = {
"id": 12,
"subject": "Implement auth module",
"status": "in_progress",
"blockedBy": [],
"blocks": [13],
"owner": "alice",
"worktree": "auth-refactor",
}A minimal teaching shape can look like this:
runtime_task = {
"id": "b8k2m1qz",
"type": "local_bash",
"status": "running",
"description": "Run pytest",
"start_time": 1710000000.0,
"end_time": None,
"output_file": ".task_outputs/b8k2m1qz.txt",
"notified": False,
}The key fields are:
type: what execution unit this isstatus: whether it is active or terminaloutput_file: where the result is storednotified: whether the system already surfaced the result
You do not need to implement every type in the teaching repo immediately.
But you should still know that runtime task is a family, not just one shell command type.
A minimal table:
local_bash
local_agent
remote_agent
in_process_teammate
monitor
workflow
Do not overload it.
class RuntimeTaskManager:
def __init__(self):
self.tasks = {}def spawn_bash_task(command: str):
task_id = new_runtime_id()
runtime_tasks[task_id] = {
"id": task_id,
"type": "local_bash",
"status": "running",
"description": command,
}runtime_tasks[task_id]["work_graph_task_id"] = 12You do not need that field on day one, but it becomes increasingly important once the system reaches teams and worktrees.
Work Graph
task #12: Implement auth module
|
+-- runtime task A: local_bash (pytest)
+-- runtime task B: local_agent (coder worker)
+-- runtime task C: monitor (watch service status)
Runtime Task Layer
A/B/C each have:
- their own runtime ID
- their own status
- their own output
- their own lifecycle
Once this layer is clear, the rest of the runtime and platform chapters become much easier:
s13background commands are runtime taskss15-s17teammates can also be understood as runtime task variantss18worktrees mostly bind to durable work, but still affect runtime executions19some monitoring or async external work can also land in the runtime layer
Whenever you see "something is alive in the background and advancing work," ask two questions:
- is this a durable goal from the work graph?
- or is this a live execution slot in the runtime?
That mixes durable task state and runtime execution state.
In real systems, one goal often spawns multiple execution units.
For example:
- durable tasks:
pending / in_progress / completed - runtime tasks:
running / completed / failed / killed
Those should stay distinct when possible.
The durable task board does not care much about them. The runtime layer cares a lot.
"Task" means two different things: a durable goal in the work graph (what should be done) and a live execution slot in the runtime (what is running right now). Keep them on separate layers.