transition_guard blocks a move until conditions are met, and agent_responsibility fires a message into the write envelope without blocking. Both share the same outer shape; everything that differs lives in definition.
The Policy Envelope
transition_guard — Blocks a Move
string
required
A group id, or
"*" to match any source group.string
required
A group id, or
"*" to match any destination group. Use "*" → done for a definition-of-done gate.Condition[]
An implicit
all_of. Each condition is evaluated against the task as it would look after the move — so you can require fields that are set in the same update that moves the task.string | null
What the agent is told when the move is blocked. Write it as an instruction, not a description — it is the agent’s next action.
transition_blocked unless every require condition passes.
Use "*" → done for a definition-of-done gate that catches every path into the final column.
agent_responsibility — Advises, Never Blocks
Condition[]
Conditions that trigger the message. Absent or empty matches always — the message fires on every write to this board.
string
required
Surfaced in the write’s
policies_fired envelope. Write it as a direct instruction to the agent reading the response.Conditions
A leaf condition is{ field, op, value?, values? }. Field references resolve literal-first, then custom_data — so a custom field is task.<name>, and built-ins like task.group_id, task.title, task.description, and task.parent_id work too.
Operator Reference
Compound Conditions
Nest compounds freely:Operators never throw. A type mismatch, bad operand, or unparseable regex evaluates to
false — a malformed policy can never crash a write. The trade-off is that a wrong field path reads as “condition not met” rather than as an error, which is why you validate. String operators coerce scalars but not arrays: a string_list field will not match contains. Use has_any / has_all instead. matches_regex compiles author-supplied patterns — patterns over 1000 chars, non-strings, and anything that throws are treated as non-match.Validation at Author Time
Definitions are validated strictly against their type atcreate_policy / update_policy time and on load. A misspelled key or unknown operator produces a schema_violation error — it is not silently ignored. This catches shape errors, but not a wrong from_group, a wrong to_group, or a field path that resolves to nothing. For those, see Validate Gates.
Priority and enabled
priority orders evaluation among policies on the same board — lower numbers run first. Use it when the order of policies_fired messages matters.
enabled: false keeps a policy in the file as documentation without enforcing it — useful for gates you’re still drafting or have temporarily suspended.