learn / 08 — the plans

plans thatRUNthemselves out

A workflow is a plan written in the grammar — tasks, states, dependencies, and schedules in one parseable file. Boards render from it, agents execute from it, and nothing ever needs syncing, because the plan is the state.

the plans11 min read
A figure before monumental canal locks opening in sequence, water flowing terrace to terrace — 1970s sci-fi style

the plan is always STALE

Every project keeps a plan, and almost no project keeps it where the work happens. The board lives in one tool, the code in another, the schedule in a third — and the moment work moves, the plan is a screenshot of last week's intentions. Someone's job quietly becomes updating the board, which is to say: manually syncing reality into a database that only ever drifts away from it again.

The deep cause isn't laziness, it's architecture. A tracker is a second system of record. The work has one state (the code, the files, the deploys) and the plan has another (cards, columns, assignees), and nothing structural connects them. Every standup meeting where someone reads the board aloud and someone else corrects it from memory is the interest payment on that split.

Agents made this worse before they made it better. An agent's "plan" typically lives in its context window — invisible, unreviewable, gone when the session ends. You can't diff it, can't validate it, can't hand it to the next worker. The most plan-hungry collaborators we've ever had arrived, and we gave them the one format nothing else can read.

the DEFINITION

work·flow /ˈwɜrk·floʊ/ noun

1. a plan written in the grammar: tasks, states, dependencies, and schedules in one parseable file — which boards render from and agents execute from.

The whole trick is in the two verbs. Nothing renders to a workflow and nothing exports from it — the file is the single source, and everything else is a view or a worker. Change the file and every board updates; finish a task and the file says so. There is no second copy to keep honest.

Here's a real one, whole. Five headlines, two properties, one schedule — this is not pseudocode, it's the actual format the rest of this page executes:

* TODO ship the landing page
** DONE write copy
** TODO render hero art
** TODO build page
   :PROPERTIES:
   :DEPENDS: render-hero-art
   :END:
** TODO deploy
   SCHEDULED: <2026-06-13 09:00>
   :PROPERTIES:
   :DEPENDS: build-page
   :END:
   waiting on the brand pass — see thread with m.

Notice the last line: prose, inside the plan. The reason deploy waits lives exactly where the waiting happens — not in a comment thread three tools away. That's the org lesson's whole argument (prose and structure, refusing to pick) applied to project management.

what a plan can SAY

Because workflows are written in org, the things a plan needs are native grammar, not bolted-on convention:

release-plan.org — one parseable tree
statesTODO → DONE keywords on headlines — the board columns, in the file
dependencies:DEPENDS: properties — execution order falls out, never written down
schedulesSCHEDULED / DEADLINE timestamps — calendars and overdue checks become arithmetic
prosethe why, in full sentences, exactly where the decision lives
nestingworkflows hold sub-workflows — a quarter holds projects holds tasks, one tree
every line of it parseable — a test suite can read your plan

That last property is the quiet one that matters most. Duplicated tasks, dependencies pointing at nothing, a DONE that depends on a TODO — these are checkable facts, and the kernel checks them the way a compiler checks types. The org lesson draws the boundary honestly: structure is checkable, prose is not. A workflow puts as much of the plan as possible on the checkable side of that line.

the READY set

All of workflow execution rests on one tiny definition, so let's give it the space it deserves. A task is ready when two things are true: it's still TODO, and every task it depends on is DONE. That's it. No priorities engine, no scheduler config, no assignment algorithm — readiness is a fact you can compute by reading the file.

Here's the plan from above, as the dependency graph the kernel sees. Copy is done; hero art has no dependencies and is ready right now; build waits on hero art; deploy waits on build:

flowchart LR
  copy["write copy ✓ DONE"]
  hero["render hero art — READY"]
  build["build page"]
  deploy["deploy"]
  hero --> build --> deploy
  style copy fill:#d9dbd3,stroke:#121316
  style hero fill:#13d943,stroke:#121316,stroke-width:2.5px
  style build fill:#ffffff,stroke:#121316
  style deploy fill:#ffffff,stroke:#121316
  

Two things are worth noticing. First, copy isn't in the graph's path at all — it never blocked anything, so it ran whenever someone had a free hour. Plans are full of work like that, and a dependency graph finds it for you. Second, the graph was never drawn — it's computed from the :DEPENDS: properties, every time, from the current state of the file. When the file changes, the graph changes. There is nothing to keep in sync because there is only one artifact.

watching a board CLEAR

Execution is a loop so simple it barely deserves the name: find the ready set, do it, write DONE back, repeat. Each pass is a round, and the plan above clears in three:

sequenceDiagram
  participant P as the plan file
  participant W as workers (you, or agents)
  Note over P: ready: render hero art
  W->>P: round 1 — hero art → DONE
  Note over P: build unblocks
  W->>P: round 2 — build page → DONE
  Note over P: deploy unblocks (waits for 09:00)
  W->>P: round 3 — deploy → DONE
  Note over P: board clear — every state
written IN the file

Notice what nobody wrote: an execution order. The order fell out of the dependencies — reorder the headlines and nothing changes; add a dependency and everything downstream waits. And notice who the workers are: the loop doesn't care. A human working down the ready list and an agent on a schedule are interchangeable at this seam, which is exactly what makes human–agent handoffs boring, in the good way. The agent finishes round one overnight; you pick up round two with your coffee; the file is the meeting.

When the ready set is empty but TODOs remain, the board is stuck — and stuckness is diagnosable, because the only thing that blocks a task is a named dependency. The answer to "why isn't this moving?" is a path through the graph, not an archaeology project.

boards are RENDERINGS

A kanban board, a timeline, a calendar of deadlines — in this ecosystem those are renderings of the plan file, generated the way a browser generates a page from HTML:

flowchart TD
  file[["release-plan.org — the single source"]]
  file --> board["kanban board"]
  file --> timeline["timeline / gantt"]
  file --> cal["deadline calendar"]
  file --> agentview["an agent's ready list"]
  board -. "drag a card" .-> file
  agentview -. "write DONE" .-> file
  style file fill:#f2ddb0,stroke:#121316,stroke-width:2.5px
  

The arrows back into the file are the part trackers can't offer. Drag a card to the done column and the file's headline flips to DONE — the same two-way binding the kernel notebook lets you feel under your fingers, where ticking a checkbox rewrites the org source. Edit the file and the board redraws. The two can't disagree, because there aren't two.

A board that's secretly a text file inherits everything text already has. The plan gets code review. The plan has a diff. The plan can be reverted, blamed, branched, and merged. Six months from now, "why did we descope search?" is answered by git log on the plan — the archaeology is already done.

time is NATIVE

The third column of plan-tooling — after the board and the tracker — is the cron job: that other place where "what should happen and when" lives, readable by exactly one daemon and reviewed by no one. Workflows absorb it. SCHEDULED and DEADLINE are org timestamps on the headline itself, so the temporal half of a plan sits in the same parseable tree as the structural half:

** TODO publish the changelog
   SCHEDULED: <2026-06-13 09:00 +1w>     ← every Friday morning
** TODO rotate the signing key
   DEADLINE: <2026-06-20>                ← overdue is arithmetic

On a docked workbook, the engine fires these — a repeating SCHEDULED is a standing appointment for whichever worker picks it up, and a passed DEADLINE on a TODO is a fact the validator reports, not a notification you missed. The task's history accumulates under the same headline, so "when did this last run, and what happened?" is a read, not an investigation.

plans hold PLANS

Headlines nest, so plans do. A quarter holds projects, a project holds tasks, and the same readiness rule runs at every level — a parent is done when its children are. One file (or a tree of them) carries the whole altitude range, from "Q3 bets" to "rename that variable":

flowchart TD
  subgraph Q["Q3 — the quarter            (a workflow)"]
    subgraph P1["ship the landing page    (a sub-workflow)"]
      a1["write copy ✓"] ~~~ a2["hero art"] ~~~ a3["build + deploy"]
    end
    subgraph P2["launch the CLI           (a sub-workflow)"]
      b1["0.13 release ✓"] ~~~ b2["docs pass"]
    end
  end
  style Q fill:#fbfaf6,stroke:#121316
  style P1 fill:#ffffff,stroke:#121316
  style P2 fill:#ffffff,stroke:#121316
  

This sounds like a small convenience until you've lived the alternative: the roadmap in a slide deck, the projects in a tracker, the tasks in fifteen heads. Here the altitudes are the same document at different depths — zoom out for the quarter view, zoom in for the work, and the rollup percentages are queries, not status meetings.

the COMPILE story

Depth rung — skippable, but it's where workflows stop being a productivity feature and become infrastructure. The engine reads the same shape one level deeper: a workflow whose tasks are tagged as components, each carrying a source block with declared inputs and outputs, compiles into a world — a deployable unit whose data-flow edges are computed by matching one component's :out to another's :in:

flowchart LR
  subgraph plan["site-build.org  :workflow:"]
    r["render  :component:
out: page"] p["publish :component:
in: page · out: site"] end plan -- "kernel: tangle_plan()" --> world subgraph world["the compiled world"] r2["render"] -- "page" --> p2["publish"] x["exports: site"] end style plan fill:#fbfaf6,stroke:#121316 style world fill:#fbfaf6,stroke:#121316 style x fill:#13d943,stroke:#121316

Same grammar, same file, same validator — the kernel notebook runs this exact compile in your tab. The conceptual rhyme is the point: a to-do list and a build system are the same data structure — tasks with dependencies — and the ecosystem refuses to make you learn them twice. From sticky-note scale to build-system scale, it's one idea wearing different clothes.

what it REPLACES

Not everything, honestly. Here's the field:

plan lives where?agents read it?diffable / revertible?executes?
tracker (Jira, Linear)their cloud, their shapevia API, lossynono — humans sync it
CI pipeline (YAML)beside the code ✓yesyesonly on push — no states, no prose
cron + scriptsscatterednorarelyon time — invisible otherwise
workflowin the workbook, beside the worknatively — it's the grammaryes — it's textdeps + schedules, by any worker

The honest read of that table: a workflow is what you get when the tracker's states, the pipeline's execution, and cron's time agree to live in one reviewable file. Each of those tools still exists for a reason — at the boundary of your system you'll meet all three. Inside it, you stop needing them to agree with each other, because they're reading the same plan.

where it BITES

Honesty section. Plans drift — agents writing freely will eventually duplicate a task or contradict a state, and a workflow file doesn't prevent that any more than any format does. What it does is make drift detectable: the checks run on every write, and the contradiction gets a name and a line number instead of a shrug.

Dependency graphs have failure modes of their own. Cycles deadlock a board — the validator catches them before anything runs, but you still have to decide which edge was wrong. And over-specified dependencies are the quiet killer: declare everything-depends-on- everything and you've serialized your team. The graph executes whatever truth you write; writing less of it is sometimes the optimization.

And execution is not autonomy. The pitch is never software that runs itself — direction stays human, workers stop at the edges you set, and the edges are real: sandboxes, explicit grants, a written layer you can read, diff, and revert. A workflow makes follow-through cheap. It doesn't make judgment optional.

questions people actually ASK

How is this different from Jira or Linear?

Those are databases with views; the plan lives in their cloud, in their shape, readable through their API. A workflow lives next to the work, in plain text, in version control — and agents read it natively because the grammar is in their training data. Use both if you like; only one of them can be diffed in a pull request.

What stops circular dependencies?

Validation. A cycle, a dependency on a task that doesn't exist, a DONE resting on a TODO — the checker reports each one, named, before anything runs. It's the same class of check as the kernel's workflow validation, and it's cheap enough to run on every save.

Who actually executes the tasks?

Anyone who can read the file. You, working down the ready list; an agent on a schedule; a fleet of them on an engine. The format doesn't care — which is exactly what makes handoffs between humans and agents boring, in the good way.

Can a workflow trigger on time, not just on dependencies?

Yes — schedules are native timestamps, and a docked workbook's engine fires them. "Every weekday at nine" is a property on the headline, with the task's history accumulating right below it.

Does my whole team need to read org for this to work?

No — that's what renderings are for. The board is the interface most people touch; the file is what it's made of. Same as the web: everyone uses pages, few read HTML, and the ones who do hold the leverage.

Is the Autopoet one of these?

Exactly one of these — a standing agent working a maintenance workflow against the system itself. It's the worked example of this whole lesson, and it has its own sub-lesson.

the deep DIVES

Go deeper into this area — the technical docs underneath it.

keep GOING

Workflows sit on three other ideas — each has its own lesson.