Flow
Menu

The method

Connect

Say what each piece of work truly waits on, and nothing else. Readiness follows from that.

Connect records what each piece of work waits on, and nothing else. It produces edges between tasks, references to things outside the graph, and waits. From those, Flow computes what can start now (P5), so an honest edge is worth more here than a tidy one.

How to do it

Pick the weakest connection that is still true. How Flow works describes each one, and the vocabulary lists every kind.

If the truth is Record
B literally cannot start until A is done A blocks B
A is the reason B holds, or the choice B records A justifies B, or A decides B
A replaces B as the current version of the same thing A supersedes B
A and B are related, or B builds on A but could start first mentions, or nothing
The thing lives outside the graph: an issue, a PR, a commit, a URL A reference on the task, with its role
A date holds the task A scheduled wait with the date
A person or event outside your control, with no task, holds it An external wait naming who or what, with until as the date to chase on

blocks is the only edge that holds work up, so it is the one to be strict about. Every false blocks removes a task from the ready set for no reason.

Where a piece of work belongs is a different question from what it waits on. It is answered by which Flow project it is in and by its tags, and neither holds anything up.

No sub-tasks

There is no parent task and no nesting. An outcome is reached when the work that blocks it is done, and one piece of work can block several outcomes. Waiting on something is not the same as belonging to it, and a tree forces you to choose one parent when the truth is often two.

Moving work “into another feature” is not a restructuring either. You change what it blocks.

Decisions are tasks

An open question that holds work up waits on whoever answers it. Where it waits depends on how much it holds.

A question that holds one task is that task’s wait. The task moves to waiting, with an external wait on whoever decides, whose reason states the question, the options and a recommendation. The person answers by moving the task, or by telling the agent, whose move cites their words as its basis. The question, the answer and the move stay on the one task they are about, and nothing else needs writing.

A question that holds several tasks, or will decide later ones too, is a task of kind decision. It blocks everything that cannot proceed until it is answered, and closing it is what unblocks them, so there is no second step to remember. The answer goes in the decision’s outcome, and records that follow from it cite it with decides or justifies.

Decide, then build. A PRD waiting for sign-off, with the tasks that build it, is a decision followed by the work it decides. The decision is kept as it was answered while the work moves through its statuses, so they are separate records:

Record kind status Carries
“Which queue backs the export?” decision waiting, with an external wait naming who decides the PRD as a spec reference
“Build the export job” commitment active the same PRD, also as spec
“Build the export screen” commitment active the same PRD, also as spec

The decision blocks each piece of work. upsert-tasks writes all three, and the edges between them, in one call: each item gives itself a ref, and each work item’s link names the decision as { "ref": "decide" } because none of them has an id yet.

The decision waits on a person, so it is never offered to an agent as ready work, and the work behind it stays active and blocked:dependency. When the person answers, the decision closes as completed with the answer in its outcome, and the work becomes ready. A different answer later is a new decision that supersedes the first. It is never an edit.

Closing the decision frees the work whatever the answer was. If the answer is “don’t build it”, the work does not cancel itself, and an agent does not cancel it either: it proposes the cancel, with the decision as the basis. Decide, then build runs the whole sequence.

Standing rules for agents are decisions too (roles).

The person

  • Settle the edges that are really decisions. “Should the export wait for the new schema?” is not a fact an agent can find. Answer it on the task that waits for it, or make it a decision task that blocks both.
  • Decide what a cycle means. When two tasks block each other, one of those dependencies is wrong. Only you know which.
  • Keep one task per piece of intent. When a change spans three repositories, ask for three references on one task, not three tasks.

The agent’s side is the protocol: GTF-N1 to GTF-N6.

Failure modes

  • blocks for “seems related”. The ready set shrinks, agents sit idle, and nothing in the graph says why.
  • One task per repository. The intent splits into pieces that each look done while the whole is not. Use one task and several references.
  • A dependency written as prose. “After #312 lands” in a task body, or in a wait’s reason, gates nothing and is computed by nobody. Make it an edge.
  • Nesting by habit. Filing work “under” a feature as if it were a folder. Say what it blocks instead, and tag it.

In Flow

To Call
Link two tasks update-tasks with links
Write several linked tasks at once, all or none upsert-tasks
Withdraw an edge, keeping its history retract-link
Point a task at an issue, PR, file or URL update-tasks with references
Withdraw a reference retract-reference
Set or clear a wait update-tasks
See the blocks graph as ordered waves, and any cycles get-order
Everything still open before one goal get-order or get-next with upstream_of
Draw a neighbourhood of the graph render-graph

Links and references can also be written inline when a task is created with upsert-tasks, so “I finished A and two issues came out of it” is one call. Tasks that link to each other before any of them exists are the same call, each naming the others by ref.

Examples:

  • Break a feature into waves: record what each piece truly waits on, and the order shows how many agents can start at once.
  • File a milestone: name the goal, point the work at it, and “what is left” becomes a query.