One thesis: Worklists never invents demand; it converts it. dispatch is the verb that turns something that already exists — a purchase order, a fired exception, a plan, a schedule — into the tasks it implies. It is the one way tasks come into being, and it is the only reason a work door belongs in the same family as an event spine rather than next to any to-do app.
The fourth group
A work door has four groups of verbs, and a to-do app has three of them:
- Assign — work reaches a performer
- Perform — the lifecycle: start, block, escalate, complete, timeout
- Read — query the work, trace its lineage
- Dispatch — demand becomes work
Without the fourth, a task system is a place where people type what they intend to do. Its backlog is a second, disconnected record of the business, maintained by hand, drifting from the documents and events that actually drive the floor. With it, a document is the backlog.
The compile-down
Four kinds of demand, each with a concrete example from one bag of lettuce:
A document. A purchase order for forty cases arrives at transactions.dev. dispatch reads it and emits the receiving tasks it implies: one receiving count at dock 12, inside the delivery window, closable by a scan of the pallet's SSCC. When the ASN arrives, the task gains the expected SSCC as its subject. Nobody typed a task.
An exception. A watch on the spine fires because a lot was received but never put away in the window. That exception becomes an investigation task through dispatch — and this is the only verb that joins what happened to what needs doing, ruled one-way. Exceptions become work; work does not become exceptions.
A plan. A one-off, non-repeatable ordering that ends — a relabeling of a recalled lot, a physical inventory — is a Plan upstream, and dispatch emits its tasks. A Project is not a primitive here; it is a Plan, and both a Plan and a standing Process emit tasks the same way.
A schedule. A daily temperature check on the cold room is a dispatch whose demand is a calendar. schedule is a parameter, not a verb, because it is the same act with a different source.
Every task can name its parent
The surface spec renders this as a field: dispatchedBy, present on every task, sourced from trace. A task with no dispatching demand does not exist on this door. That is what lets an auditor walk from a closed receiving task back through the event hash that closed it and further back to the PO that asked for it, without an application in the loop asserting any link.
It also bounds the system. There is no create on the Task noun. Client surface is the domain verbs plus the universal verbs over nouns, and the matrix is sparse on purpose: Task has no create, no update, no delete. Every task arrives through dispatch and every change is a verb that leaves a record.
Cancel is dispatch's inverse, and it survives the act
The PO is amended and the fourth pallet is no longer coming. cancel marks the receiving task as canceled, with the reason and whatever partial record exists — a claim, a block, a half-done count — preserved. It is not a delete. A canceled task keeps its lineage, and trace still shows what dispatched it and what happened to it before it was withdrawn.
The fold reads a cancel act like any other. The record is append-only, so the cancellation is one more act, not a row removed.
What is built, and what is declared
Being plain about the line: dispatch and cancel are declared in the verb portfolio and are not implemented in the package worklists.dev. The package's fold reads their acts, because a task's history has to be readable whole, and no verb in the package writes one. The five that answer today are query, trace, claim, complete, timeout.
The design is fixed, though, and it is the design this post describes. Worklists never invents demand; it converts it. If you are wiring this door into a WMS or an order system, the integration point is the demand — the document you already receive, the exception you already raise, the schedule you already keep — not a form where somebody types a task.
Get started by reading the fold over an ActionRecord that begins with a dispatch act citing a PO. The first act on every task is the answer to why does this exist.