Documentation
¶
Overview ¶
Package gate holds the rules about when a ticket may move.
These are pure functions over already-loaded state, deliberately separated from the store. Two reasons: they can be unit-tested without touching a filesystem, and there is exactly one file to change when a rule changes — the CLI and the TUI both call in here rather than each carrying their own copy, which is the only way "enforced identically by both interfaces" is true rather than merely intended.
Index ¶
Constants ¶
const ( CodeMissingField = "missing_field" CodeBlocked = "blocked" CodeUnknownLane = "unknown_lane" CodeNoSuchLane = "no_such_lane" CodeMissingOutcome = "missing_outcome" CodeNeedsSignal = "needs_nonmodel_signal" CodeNeedsQuestion = "needs_question" CodeNeedsReason = "needs_blocked_reason" CodeNeedsCommits = "needs_commits" CodeSelfBlock = "self_block" CodeMissingProduces = "missing_lane_output" CodePlanIncomplete = "plan_incomplete" CodeNeedsHuman = "needs_human" CodeStepNotChosen = "step_not_chosen" CodeNotOwner = "not_owner" )
Violation codes. Agents branch on these, so they are stable strings rather than prose that might be reworded.
Variables ¶
var PromotionFields = []string{ ticket.FieldGoal, ticket.FieldDoD, ticket.FieldContext, ticket.FieldAssignee, }
PromotionFields are required before a ticket may leave the backlog.
The point of the gate is that capture should be frictionless while execution should not be: anything can be thrown into the backlog, but nothing starts without a goal, a definition of done, the context it came from, and a human who owns the outcome. Acquiring those is the price of admission to a run.
Functions ¶
func Actionable ¶
Actionable reports whether a ticket could be picked up right now.
Types ¶
type Env ¶
type Env struct {
Lanes *lane.Set
// All is every ticket, used to evaluate blockers. Only id and status are read.
All []*ticket.Ticket
}
Env is the surrounding state a decision needs.
type Request ¶
type Request struct {
To string
// Question accompanies a move into a lane that requires one.
Question string
// Reason accompanies a move into a lane that will not take a ticket without
// knowing what it is waiting on.
Reason string
// Actor is who is performing the move, used only in messages.
Actor string
// Interactive marks a move a person made by hand, in the board. It is the
// only distinction available that an agent cannot simply assert: an agent
// drives the CLI, and cannot press a key in someone's terminal. Lanes that
// require a human to release a ticket rely on it.
Interactive bool
// NewAssignee accompanies a move that also hands the ticket to someone
// else. A hand-over is always allowed, regardless of who currently owns
// the ticket — otherwise an absent owner could freeze it forever.
NewAssignee string
}
Request describes a proposed move.
type Violation ¶
type Violation struct {
Code string `json:"code"`
Field string `json:"field,omitempty"`
Message string `json:"message"`
}
Violation is one reason a move was refused. Field is set when the fix is to supply a value, so an agent can act on it without parsing the message.
type Violations ¶
type Violations []Violation
Violations is an ordered set of refusals.
func CheckAdvance ¶
func CheckAdvance(env Env, t *ticket.Ticket, req Request) Violations
CheckAdvance decides whether t may move to req.To.
func (Violations) Err ¶
func (vs Violations) Err() error
func (Violations) Fields ¶
func (vs Violations) Fields() []string
Fields lists the field names that need filling in.