Workflow
How items move through Joy's six statuses, the verb shortcuts, and how gates scale strictness from solo to team.
Every Joy item moves through one small, fixed set of statuses. There is exactly one workflow per project: it is not templated, selectable, or importable. You scale strictness by tightening individual transitions with gates, not by adding statuses.
The states
- new: the item exists or was proposed, but is not yet approved for work.
- open: approved and triaged into the backlog, ready to pick up.
- in-progress: being worked on.
- review: work done, awaiting acceptance.
- closed: accepted and finished.
- deferred: deliberately set aside; reachable from any active state, because there can always be a reason to put something on hold.
blocked is not a manual state; it is computed automatically from dependencies.
The verbs
Each transition has a one-word shortcut:
joy approve IT-0001 # new -> open
joy start IT-0001 # new or open -> in-progress
joy submit IT-0001 # in-progress -> review
joy close IT-0001 # review -> closed
joy rework IT-0001 # review -> in-progress
joy defer IT-0001 # any active state -> deferred
joy reopen IT-0001 # closed or deferred -> openGates
By default every transition is open and Joy only warns, never blocks. When you need more control, you tighten individual transitions with gates. The workflow itself stays the same.
start works directly from new, so the open status is optional in everyday use. It comes into play with a triage gate on new -> open: items are then approved into the backlog with joy approve before work starts. A gate with allow_ai: false on new -> open is a handy way to keep AI-created items in new until a human approves them.
Solo: no gates
Every transition is open; start goes straight from new.
Team: triage and acceptance gates
A triage gate on new -> open (with allow_ai: false for AI-created items) routes proposals through human approval; an acceptance gate on review -> closed lets only leads close work, optionally requiring green CI.
Same workflow, more strictness: nothing was added to the state model, two transitions were tightened. See Capabilities and gates for how gates are configured.
One workflow, tuned with gates
Joy keeps a single, deliberately small set of statuses and lets you adjust strictness through gates rather than by adding states or selectable processes.
Decisions: the validity axis
A decision item records an architectural or product decision. Decisions are the project's living specification: people and AI read them before any work to learn the rules that bind it. They are not a backlog to burn down.
A decision flows through the normal workflow while it is being made (new to closed). But "is the deciding finished?" and "does the decided rule still hold?" are two different questions, so a decision carries a second field, validity, orthogonal to status:
statustracks the work of deciding.closedmeans the deciding is finished.validitytracks the rule that came out of it.
A decision binds when its status is closed and its validity is accepted. Closing the decision is the precondition for the rule to take force, just as finishing construction is the precondition for a building to open.
| validity | meaning |
|---|---|
accepted | in force, a binding rule |
proposed | still being decided, not yet binding |
rejected | considered and declined, never in force |
replaced | superseded by another decision (see replaced_by) |
retired | dropped without a successor, no longer in force |
Closing a decision defaults its validity to accepted. A decision is never deleted; when it is superseded you record the successor with joy edit IT-0001 --replaced-by IT-0042, which links the two and marks the old one replaced.
Reading decisions
The -D / --decisions view is built for reading the living specification:
joy ls -D # decisions only, with a val (validity) column
joy ls -D -a # include closed and retired ones too
joy board -D # a board grouped by validity, not statusTwo axes, one item
status answers "is the deciding done?"; validity answers "does the rule still hold?". A binding decision is closed and accepted; a closed decision that was replaced is history, not current policy.