board

package
v0.16.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 7, 2026 License: MIT Imports: 22 Imported by: 0

Documentation

Overview

Package board is the planner's store and rules (ADR 0005): epics, stories and subtasks for each Project, kept in one SQLite database through modernc.org/sqlite.

Every rule in ADR 0005 §1–§9 is enforced here, inside the transaction of the write it guards: the actor table, derived container status, scope and caps, holds and their single release path, requests, split, cancel, cascade, restore, the expiry sweep and purge. The package knows nothing about HTTP, Copilot, the session store or git: evidence, HEAD and working tree state are supplied by the caller.

"Task" always means a uam conversation. The leaf card kind is subtask.

Index

Constants

View Source
const (
	PrioHigh    = 1
	PrioMedium  = 2
	PrioLow     = 3
	PrioDefault = PrioLow
)

The priority scale: 1 high, 2 medium, 3 low (the default).

View Source
const (
	CapCreated      = 50  // live cards a Task created; deleted and expired ones free their place
	CapCreatedTotal = 200 // cards a Task may create in its lifetime, deleted and expired ones included; only purge frees a place
	CapUnconfirmed  = 10  // live unconfirmed children a Task may add to one container, the root included
	CapComments     = 20  // non-automatic comments a Task may add to one card
)

Caps counted per Task (ADR 0005 §4, ADR 0006). Calls made by a Task's subagents count against the Task.

View Source
const (
	PausedOwner = "owner"
	PausedUAM   = "uam"
)

Who paused a card: the owner's Pause, or uam when an attempt ended without landing.

View Source
const (
	AuthorOwner = "owner"
	AuthorUAM   = "uam"
)

Comment authors.

View Source
const (
	FlagAcceptanceCouldNotRun = "acceptance_could_not_run"
	FlagNoChangeInTree        = "no_change_in_tree"
	FlagTestsOrBuildChanged   = "tests_or_build_changed"
	FlagOverlap               = "overlap"
	// FlagBaselineMissing marks evidence gathered without the hold's
	// baseline commit, which no longer exists.
	FlagBaselineMissing = "baseline_missing"
)

The flags a done request may carry. The caller gathers the evidence and decides the flags; the store only records them.

View Source
const (
	ModeSafe = "safe"
	ModeYolo = "yolo"
)

The run modes, as a Task's.

View Source
const AutoAcceptComment = "Accepted automatically: the acceptance command passed"

AutoAcceptComment is the automatic comment on a subtask whose done request was accepted because its acceptance command passed.

View Source
const DefaultEffort = "S"

DefaultEffort is the estimate a card takes when none is given.

View Source
const ExpiryWindow = 14 * 24 * time.Hour

ExpiryWindow is how long an agent-created card stays unconfirmed before the sweep cancels it.

View Source
const FileName = "board.db"

FileName is the planner database's file name, created beside the session store.

View Source
const MaxAcceptParallel = 4

MaxAcceptParallel is the most acceptance runs a Project may allow at a time.

View Source
const MaxLanes = 4

MaxLanes is the most lane attempts that take a slot at a time, over every Project (ADR 0006 §4.4).

View Source
const MaxParallel = 4

MaxParallel is the most subtasks of one epic that may run at a time.

View Source
const SimilarityFloor = 0.34

SimilarityFloor rejects candidates sharing too little title vocabulary.

Variables

View Source
var ErrNotFound = &Error{Code: CodeNotFound}

ErrNotFound matches, with errors.Is, every not-found refusal.

Functions

func Similarity

func Similarity(a, b string) float64

Similarity is the Sørensen–Dice coefficient over normalized title token sets.

func TaskAuthor

func TaskAuthor(taskID string) string

TaskAuthor is the comment author for a Task.

Types

type Act added in v0.16.0

type Act struct {
	Task     string
	CardID   string
	Seq      int64
	Provider string
	// Why is set on a nudge and a cancel.
	Why Why
}

Act is something to do to a lane Task about the subtask it holds or last held.

type Actor

type Actor struct {
	Role    Role
	TaskID  string
	AgentID string
	// Head is the Project's HEAD at the time of an owner write. Every owner
	// touch pins the touched card to it.
	Head string
	// Proposals limits an agent to proposals, as a Utility job is (ADR 0005
	// §18): its edit of a confirmed card is refused rather than filed as a
	// change request.
	Proposals bool
}

Actor is who makes a write. An agent is identified by its Task, plus the subagent's ID when a subagent made the call; caps count against the Task.

func Agent

func Agent(taskID, agentID string) Actor

Agent is the actor for a Task's agent, or one of its subagents.

func Owner

func Owner(head string) Actor

Owner is the owner actor. head is the Project's HEAD, "" when unknown.

type ApproveItem added in v0.16.0

type ApproveItem struct {
	ID       string
	Revision int64
}

ApproveItem is a card the Approve dialog showed, at the revision it showed it.

type Baseline

type Baseline struct {
	Head  string            `json:"head"`
	Dirty []string          `json:"dirty"`
	Blobs map[string]string `json:"blobs,omitempty"`
}

Baseline is the working tree state recorded when a hold starts. Blobs maps each dirty path to the blob name of its content then, "" when the path did not exist; a dirty path missing from it counts as changed since.

type Breaker added in v0.16.0

type Breaker struct {
	Until    time.Time
	Failures int
	Detail   string
}

Breaker is a provider's circuit breaker (ADR 0006 §4.5), kept by the caller: while Until is ahead nothing starts and nothing is nudged on the provider.

type Card

type Card struct {
	ID           string
	Seq          int64
	ProjectID    string // "" is the read-only Unassigned list
	Kind         Kind
	ParentID     string // "" at the root
	Rank         int
	Title        string
	Desc         string
	WinCondition string
	Status       Status
	Progress     *Progress
	Prio         int
	Due          string
	Effort       string
	Labels       []string
	Checklist    []Check
	Blocked      bool
	BlockedBy    []string
	Blocks       []string
	// ExpiresAt is nil once the card is confirmed.
	ExpiresAt *time.Time
	HeldBy    string
	// WorkedBy is the Task of the subtask's latest attempt, which stays
	// after the attempt ends; "" when none started.
	WorkedBy  string
	PinnedSHA string
	// AcceptCmd is nil to inherit the Project default, "" for none.
	AcceptCmd *string
	Paths     []string
	CascadeID string
	CreatedBy string
	// Paused is "", PausedOwner or PausedUAM: nothing new starts at or under
	// the card (ADR 0006 §4.6). Only a card under an epic, or an approved
	// epic, is paused.
	Paused string
	// Run is an approved epic's run; nil on every other card.
	Run *Run
	// Lane is the git state of the subtask's latest attempt when that
	// attempt ran in a lane; nil otherwise.
	Lane            *Lane
	PendingRequests int
	Revision        int64
	CreatedAt       time.Time
	UpdatedAt       time.Time
	MovedAt         time.Time
}

Card is one node on a board. Status and Progress are derived for containers; Progress is nil on subtasks.

func (Card) Confirmed

func (c Card) Confirmed() bool

Confirmed reports whether the owner has saved, launched, accepted or restored the card.

type Change

type Change struct {
	ProjectID string
	Revision  int64
	Cards     []string
	Removed   []string
	Requests  []string
}

Change describes one committed write to one Project's board: the Project's new revision, the cards whose stored or derived state changed (ancestors included), the cards removed and the requests written.

type Check

type Check struct {
	Text string `json:"text"`
	Done bool   `json:"done"`
}

Check is one checklist item.

type ChecklistEdit

type ChecklistEdit struct {
	Tick   []int
	Untick []int
	Add    []string
}

ChecklistEdit ticks, unticks and appends checklist items; indexes are zero-based into the current checklist.

type Closure added in v0.16.0

type Closure struct {
	Cards    []Card
	Landings []Landing
	Running  []Card
}

Closure is what a revert takes along: the landed subtasks to revert, in outline order, their landed commits, and the running attempts that started on top of one of them, which the owner Stops first.

type Code

type Code string

Code classifies a refusal so callers can map it to their own errors.

const (
	CodeGuardOpenItems Code = "guard_open_items"
	CodeGuardBlockers  Code = "guard_blockers"
	CodeGuardBlocked   Code = "guard_blocked"
	CodeNotHeld        Code = "not_held"
	CodeReadOnly       Code = "read_only"
	CodeInvalid        Code = "invalid"
	CodeNotFound       Code = "not_found"
	CodeForbidden      Code = "forbidden"
	CodeLimit          Code = "limit"
	CodeDuplicate      Code = "duplicate"
	// CodeUnconfirmed refuses starting work while the subtask or an
	// ancestor is unconfirmed; Refs lists them.
	CodeUnconfirmed Code = "unconfirmed"
	// CodeInProgress refuses changing the plan of a started subtask
	// (lock.go) until the owner releases it.
	CodeInProgress Code = "in_progress"
	// CodeRunOwned refuses a manual start or a per-card confirmation under
	// an approved epic (ADR 0006 §6.2): uam runs it, and the owner approves
	// from the epic.
	CodeRunOwned Code = "run_owned"
	// CodeStale refuses an approval whose listed cards changed since the
	// dialog showed them; Refs lists them.
	CodeStale Code = "stale"
	// CodeNotReady refuses a run start of a subtask that is not ready, or
	// that no lane slot is free for (ADR 0006 §4.1); Refs lists what holds
	// it back.
	CodeNotReady Code = "not_ready"
	// CodeLanding refuses a write that would change the status or end the
	// hold of a subtask whose landing is under way (ADR 0006 §4.4).
	CodeLanding Code = "landing"
	// CodeRevertRunning refuses a revert while an attempt that started on
	// top of what it reverts still runs (ADR 0006 §5.7); Refs lists them.
	CodeRevertRunning Code = "revert_running"
	// The acceptance refusals (ADR 0005 §6), raised by the caller that runs
	// acceptance: the Project's runner stayed busy past the timeout, or the
	// command exited non-zero.
	CodeAcceptanceBusy   Code = "acceptance_busy"
	CodeAcceptanceFailed Code = "acceptance_failed"
)

The refusal codes. The first six are ADR 0005 §14's.

const CodeImportBusy Code = "import_busy"

CodeImportBusy refuses an import whose source kept changing while it was copied.

const CodeImportSchema Code = "import_schema"

CodeImportSchema refuses a source board at a schema version Import does not read.

func CodeOf

func CodeOf(err error) Code

CodeOf returns err's refusal code, or "" when err is not a refusal.

type Comment

type Comment struct {
	ID        int64
	CardID    string
	Author    string
	AgentID   string
	Body      string
	Automatic bool
	// Close marks the comment a card was finished with; a container's
	// roll-up is made of its children's close comments.
	Close     bool
	CreatedAt time.Time
}

Comment is one comment on a card. Automatic comments are written by uam and are exempt from the caps.

type DecidedBy added in v0.12.2

type DecidedBy string

DecidedBy is who decided a request.

const (
	DecidedByOwner DecidedBy = AuthorOwner
	DecidedByUAM   DecidedBy = AuthorUAM
)

The deciders: the owner, or uam for a done request accepted automatically.

type DeleteResult added in v0.15.4

type DeleteResult struct {
	Card     Card
	Released []Card
}

DeleteResult is an agent's delete: the card, now cancelled, and the live cards outside it that a deleted card blocked, which no longer wait on it.

type Detail

type Detail struct {
	Card     Card
	Comments []Comment
	Requests []Request
	Holds    []Hold
}

Detail is one card with its comments, requests and hold history.

type EditResult

type EditResult struct {
	Card       Card
	Request    *Request
	AcrossRun  bool
	OutOfPause bool
	Replaced   bool
}

EditResult is an edit's outcome: the card, and the change request filed instead when an agent's edit needs the owner. AcrossRun says it was filed because the move changes the card's epic while one of them is approved, OutOfPause because the move takes the card out from under a pause. Replaced says it withdrew the Task's earlier pending change request.

type EpicFacts added in v0.16.0

type EpicFacts struct {
	// Epic carries the run it was approved with and its pause.
	Epic Card
	// InUse is the number of lane slots in use under the epic, the count
	// StartRun checks against its parallel limit.
	InUse int
	// Ready lists, in outline order, the subtasks under the epic that a run
	// may start: those StartRun would not refuse as not ready.
	Ready []Card
}

EpicFacts is an approved epic in one pass.

type Error

type Error struct {
	Code    Code
	Message string
	Refs    []string
}

Error is a refusal from a board rule. Refs lists the cards or items the refusal is about, such as open checklist items or open blockers.

func (*Error) Error

func (e *Error) Error() string

func (*Error) Is

func (e *Error) Is(target error) bool

Is matches another *Error with the same code, so errors.Is(err, ErrNotFound) works.

type FiledRequest added in v0.12.2

type FiledRequest struct {
	Request   Request
	Wait      WaitReason
	Closes    []Card
	Proposals []Card
}

FiledRequest is a filed request, with Wait saying why a done request was left pending. For WaitClosesWithProposals, Closes are the containers accepting it would close, nearest first, and Proposals their live unconfirmed subtasks, which closing would cancel.

type Filter

type Filter struct {
	// Query is free text matched against title, description and labels:
	// every word must appear, the last as a prefix.
	Query  string
	Status Status
	Kind   Kind
	// Parent is a card ref; only its direct children match.
	Parent string
}

Filter narrows List. Zero fields match every card.

type Finishable

type Finishable struct {
	Card      Card
	AcceptCmd string
}

Finishable is a subtask that passed the finishing guard, with the acceptance command it resolves to ("" for none).

type Hold

type Hold struct {
	ID        string
	CardID    string
	TaskID    string
	Attempt   int
	StartedAt time.Time
	Baseline  Baseline
	EndedAt   *time.Time
	EndReason ReleaseReason
	// Lane is the attempt's git state; zero for an attempt in the Project
	// directory.
	Lane Lane
	// WaitedOn lists the IDs of the done subtasks a lane attempt waited on
	// when it started (ADR 0006 §5.3).
	WaitedOn []string
}

Hold is one attempt at a subtask by a Task.

type ImportReport

type ImportReport struct {
	Imported   int          `json:"imported"`
	Updated    int          `json:"updated"`
	Unassigned int          `json:"unassigned"`
	Comments   int          `json:"comments"`
	Links      int          `json:"links"`
	Skipped    []ImportSkip `json:"skipped"`
}

ImportReport is what one Import did. Imported counts the cards it added, Unassigned how many of those went to the Unassigned list, and Updated the existing cards it changed. Comments and Links count the comments and blocker links it copied. Skipped lists the source tasks, by their ID, that it left alone, and why.

type ImportSkip

type ImportSkip struct {
	ID     string `json:"id"`
	Reason string `json:"reason"`
}

ImportSkip is one source task an import left alone.

type Kind

type Kind string

Kind is a card's place in the tree. Kinds rank epic < story < subtask, and a parent must outrank its child.

const (
	KindEpic    Kind = "epic"
	KindStory   Kind = "story"
	KindSubtask Kind = "subtask"
)

The card kinds. Subtask is the leaf; epics and stories are containers.

type Landing added in v0.16.0

type Landing struct {
	CardID string
	Seq    int64
	Title  string
	SHA    string
}

Landing is a landed subtask's commit on its integration branch.

type Lane added in v0.16.0

type Lane struct {
	Branch      string
	LandedSHA   string
	RevertedSHA string
}

Lane is a lane attempt's git state (ADR 0006 §5.1). Branch, the attempt branch, marks the attempt as a lane's. LandedSHA is the landing intent while the attempt is open and the commit it landed as once it ended; RevertedSHA is the commit that reverted it.

type LaneCommits added in v0.16.0

type LaneCommits struct {
	Landed   map[string]bool
	Reverted map[string]int
}

LaneCommits are the commits uam made on a Project's integration branch, as its lane attempts record them: each landing, and each revert's last commit with the number of landings it reverted, one revert commit each.

type LaneEnd added in v0.16.0

type LaneEnd struct {
	CardID string
	Seq    int64
	Reason ReleaseReason
}

LaneEnd is how a lane Task's attempt ended.

type LaneFacts added in v0.16.0

type LaneFacts struct {
	CardID string
	Seq    int64
	// TaskID is the attempt's Task, the holder.
	TaskID string
	// Pending is the kind of the holder's pending done, blocked or split
	// request on the subtask, a done before the others, and Request its
	// ID; "" when it has none.
	Pending RequestKind
	Request string
	// Landing marks a pending done that waits only to land.
	Landing bool
	// Intent is the landing intent, the commit the attempt lands as; ""
	// when none is stored.
	Intent string
}

LaneFacts is an open lane attempt in one pass.

type Memory added in v0.16.0

type Memory struct {
	Now time.Time
	// Nudged counts each Task's nudges since boot.
	Nudged map[string]int
	// Starting maps each subtask a start is in progress for to its epic.
	Starting map[string]string
	// Landing marks each subtask a land call is in flight for, from a tool
	// call, an owner job or the executor.
	Landing map[string]bool
	// LandRetry is when each done request waiting to land may be tried
	// again after a transient failure.
	LandRetry map[string]time.Time
	// EpicBackoff is when each epic may start again after a failed start.
	EpicBackoff map[string]time.Time
	// Providers holds each provider's breaker.
	Providers map[string]Breaker
	// SeenFailure is, for each Task, the failed turn already reported.
	SeenFailure map[string]time.Time
}

Memory is what the executor keeps between passes, read by Next.

type NewCard

type NewCard struct {
	ProjectID    string
	Kind         Kind
	ParentID     string // a card ref; "" creates at the root
	Title        string
	Desc         string
	WinCondition string
	Prio         int // 0 takes PrioDefault
	Due          string
	Effort       string // "" takes DefaultEffort
	Labels       []string
	Checklist    []Check
}

NewCard is a card to create. A card created by the owner is confirmed, except under a proposal, where it is a proposal too; one created by an agent expires ExpiryWindow after creation unless confirmed.

type Options

type Options struct {
	Now   func() time.Time
	NewID func() string
}

Options supplies the store's clock and ID source. Zero fields use time.Now and random UUIDs.

type Patch

type Patch struct {
	Title        *string   `json:"title,omitempty"`
	Desc         *string   `json:"desc,omitempty"`
	WinCondition *string   `json:"win_condition,omitempty"`
	Prio         *int      `json:"prio,omitempty"`
	Due          *string   `json:"due,omitempty"`
	Effort       *string   `json:"effort,omitempty"`
	Labels       *[]string `json:"labels,omitempty"`
	Checklist    *[]Check  `json:"checklist,omitempty"`
	// ParentID moves the card: a card ref, or "" for the root.
	ParentID *string `json:"parent_id,omitempty"`
	// Rank places the card at that index among its siblings.
	Rank *int `json:"rank,omitempty"`

	Blocked *bool `json:"-"`
	// Paused pauses (true) or resumes (false) a card under an epic, approved
	// or not, or an approved epic: the owner's Pause / Resume. Under an epic
	// not approved yet it takes effect once the epic is. Resume clears uam's
	// pause too. It is no part of the card's plan, so a started card takes
	// it.
	Paused *bool `json:"-"`
	// AcceptCmd sets the subtask's acceptance command: an invalid
	// NullString inherits the Project default, a valid "" means none. It is
	// stored trimmed, so a blank one is none.
	AcceptCmd *sql.NullString `json:"-"`
	Paths     *[]string       `json:"-"`
	// ProjectID moves a card out of Unassigned into a Project.
	ProjectID *string `json:"-"`
}

Patch is a partial card update; nil fields are left unchanged. The owner-only fields never appear in a change request.

type Pick added in v0.16.0

type Pick struct {
	Epic Card
	Card Card
}

Pick is a subtask to start under its approved epic, with the epic's run.

type Progress

type Progress struct {
	Done     int
	Total    int
	Proposed int
}

Progress is a container's done ÷ non-cancelled confirmed leaves, plus the unconfirmed leaves shown as "+N proposed".

type ProjectSettings

type ProjectSettings struct {
	ProjectID      string
	AcceptCmd      string
	BaseRef        string
	AcceptParallel int
}

ProjectSettings holds a Project's planner settings. AcceptCmd is the default acceptance command, "" for none. BaseRef is the branch its integration branch follows, "" until set, and AcceptParallel how many acceptance runs it allows at a time (ADR 0006 §3.1).

type ReleaseReason

type ReleaseReason string

ReleaseReason is why a hold ended. Every hold ends through ReleaseHold's single path with one of these.

const (
	ReleaseAccepted  ReleaseReason = "accepted"  // request accepted → done
	ReleaseDone      ReleaseReason = "done"      // owner marked the subtask done
	ReleaseRejected  ReleaseReason = "rejected"  // request rejected, holder not live → todo
	ReleaseSettled   ReleaseReason = "settled"   // Settle dialog released it → todo
	ReleaseEnded     ReleaseReason = "ended"     // Task archived or deleted → todo
	ReleaseOwner     ReleaseReason = "released"  // owner Release → todo
	ReleaseCancelled ReleaseReason = "cancelled" // owner cancel or cascade → cancelled
	ReleaseSplit     ReleaseReason = "split"     // the subtask became a story; the hold moved (holds before split needed a release)
	ReleaseAborted   ReleaseReason = "aborted"   // a lane start failed after its hold was written → todo
	ReleaseBlocked   ReleaseReason = "blocked"   // a blocked request accepted on a lane hold → todo
)

The release reasons (ADR 0005 §5).

type Request

type Request struct {
	ID              string
	CardID          string
	TaskID          string
	AgentID         string
	Kind            RequestKind
	Comment         string
	Payload         json.RawMessage
	Evidence        json.RawMessage
	Flags           []string
	BaseRevision    int64
	Status          RequestStatus
	CreatedAt       time.Time
	DecidedAt       *time.Time
	DecisionComment string
	// DecidedBy is "" while pending and when withdrawn.
	DecidedBy DecidedBy
}

Request is one inbox row. BaseRevision is the card's revision when it was filed.

type RequestInput

type RequestInput struct {
	Kind    RequestKind
	Comment string
	// Evidence and Flags belong to done requests.
	Evidence json.RawMessage
	Flags    []string
	// Blocker is a blocked request's optional blocking card ref; accepting
	// the request links it instead of setting the blocked flag.
	Blocker string
	// ProposedAcceptCmd is text only; it never runs until the owner copies
	// it into the subtask.
	ProposedAcceptCmd string
	// PassedCmd is the acceptance command the caller ran for a done request
	// and saw exit 0, "" when none ran or it did not pass. While the subtask
	// still resolves to it and nothing else holds it back, the request is
	// accepted as soon as it is filed (ADR 0005 decision 5).
	PassedCmd string
}

RequestInput is an agent's done, cancel or blocked request. Split requests are filed by Split and change requests by Edit.

type RequestKind

type RequestKind string

RequestKind is what an agent asks the owner to decide.

const (
	RequestDone    RequestKind = "done"
	RequestCancel  RequestKind = "cancel"
	RequestBlocked RequestKind = "blocked"
	RequestSplit   RequestKind = "split"
	RequestChange  RequestKind = "change"
)

The request kinds.

type RequestStatus

type RequestStatus string

RequestStatus is where a request stands.

const (
	RequestPending   RequestStatus = "pending"
	RequestAccepted  RequestStatus = "accepted"
	RequestRejected  RequestStatus = "rejected"
	RequestWithdrawn RequestStatus = "withdrawn"
)

The request statuses.

type Role

type Role string

Role separates the owner from agents.

const (
	RoleOwner Role = "owner"
	RoleAgent Role = "agent"
)

The roles. The zero Role is neither and is refused.

type Run added in v0.16.0

type Run struct {
	RunSettings
	ApprovedAt time.Time
}

Run is an approved epic's run.

type RunFacts added in v0.16.0

type RunFacts struct {
	// Epics lists every approved epic, Project by Project in outline order.
	Epics []EpicFacts
	// Lanes lists every open lane attempt in #seq order, those whose slot a
	// pending request frees included.
	Lanes []LaneFacts
	// Ended maps each Task whose lane attempt ended to that attempt.
	Ended map[string]LaneEnd
	// InUse is the number of lane slots in use over every Project, the
	// count StartRun checks against MaxLanes.
	InUse int
}

RunFacts is the board as one executor pass sees it (ADR 0006 §4.1).

type RunSettings added in v0.16.0

type RunSettings struct {
	Provider    string
	Model       string
	Effort      string
	ContextSize string
	Mode        string
	Parallel    int
}

RunSettings is what an approval authorizes the epic's subtasks to run with. The model is explicit: no default stands in for it.

type SimilarHit

type SimilarHit struct {
	ID     string
	Seq    int64
	Title  string
	Status Status
	Score  float64
}

SimilarHit is a card whose title resembles a query. The similarity check is information only; the duplicate-title rule is the only refusal.

type Snapshot

type Snapshot struct {
	Cards    []Card
	Requests []Request
	Revision int64
}

Snapshot is one Project's board at one revision: every card, including cancelled ones, and the pending requests.

type SplitChild

type SplitChild struct {
	Title        string `json:"title"`
	WinCondition string `json:"win_condition,omitempty"`
}

SplitChild is one subtask a split creates.

type SplitResult

type SplitResult struct {
	Card      Card
	Request   *Request
	NotLinked []Card
}

SplitResult is a split's outcome: the card as the split left it (a story, or cancelled after a split into siblings), and the split request filed instead when it did not apply. NotLinked are the started dependents of a subtask split into siblings, which the siblings were not linked to.

type Stage

type Stage string

Stage is a Task's lifecycle stage as Reconcile sees it. A Task absent from the map given to Reconcile has been deleted.

const (
	StageActive   Stage = "active"
	StageSettled  Stage = "settled"
	StageArchived Stage = "archived"
)

The Task stages.

type Status

type Status string

Status is a leaf's stored status, or a container's derived one.

const (
	StatusPlanned   Status = "planned"
	StatusTodo      Status = "todo"
	StatusDoing     Status = "doing"
	StatusDone      Status = "done"
	StatusCancelled Status = "cancelled"
)

The statuses. Planned means never launched; todo means released after an attempt, or marked ready by the owner.

type Step added in v0.16.0

type Step struct {
	Start                        []Pick
	Nudge, Cancel, Retire, Abort []Act
	Land                         []string
	ProviderFailed               []Act
}

Step is what one executor pass does. Land lists done request IDs; ProviderFailed the Tasks whose failed turn counts against their provider's breaker, each failure once.

func Next added in v0.16.0

func Next(f RunFacts, tasks map[string]TaskFact, mem Memory) Step

Next is the executor's pure step (ADR 0006 §4.2): from the board's facts, the lane Tasks' facts (a Task missing from tasks is gone) and the executor's memory, it decides what one pass does. It reads its inputs only.

Each open lane attempt, in #seq order, takes the first row that applies:

a landing intent, no land call in flight, its retry
  time passed                                             land
a done waiting to land, no land call in flight, its
  retry time passed, holder not working or waiting        land
any other pending done, blocked or split from the holder  nothing: the owner decides
holder gone                                               nothing: reconcile releases it
holder settled or archived                                retire
working, waiting, or cancelled by the owner               nothing
interrupted, ended or cancelled by uam: not nudged since
  boot / nudged                                           nudge / retire
failed, nothing in the lane                               abort
failed after work: nudged 3 times / otherwise             retire / nudge once reported

A failed turn not reported yet is reported as a provider failure. A lane Task holding nothing is retired once its turn is not busy, or when settled; while busy, one whose attempt did not land is cancelled.

Each approved epic that is not paused, not backing off and whose provider's breaker is closed starts its ready subtasks, highest priority first, then in outline order, up to its parallel limit and MaxLanes over every epic, less the slots in use and the starts in progress.

Nothing starts and nothing is nudged on a provider whose breaker is open, and a provider gets at most one nudge per pass.

type Store

type Store struct {
	// contains filtered or unexported fields
}

Store is the planner database. It is safe for concurrent use: the pool holds one connection, so writers serialize in-process, and a busy database held by another process is retried.

func Open

func Open(path string, opts Options) (*Store, error)

Open opens, creating when needed, the planner database at path with mode 0600, and applies pending migrations. The directory must exist.

func (*Store) AbortRun added in v0.16.0

func (s *Store) AbortRun(ctx context.Context, ref, taskID, detail string) (Card, error)

AbortRun ends taskID's lane attempt at the subtask ref, which never started its work: the start failed after the hold was written (ADR 0006 §4.5). The subtask returns to todo with no pause, and detail, when given, is said in an automatic comment, cut to one line's length.

func (*Store) Accept

func (s *Store) Accept(ctx context.Context, a Actor, id, comment string) (Request, error)

Accept accepts the pending request id. Accepting a done request needs the subtask doing and held by the requesting Task (unless a split filed it for a ticked item) and the finishing guard to pass; the claim text becomes the close comment and the acceptance is an owner touch. A lane's done request is accepted only by landing it (AcceptLanded), and an accepted blocked request ends a lane's attempt. Under an approved epic a split request, whose parts are proposals, is refused when it would bring a container to done or cancelled, as an agent's split is. comment is the owner's decision note.

func (*Store) AcceptLanded added in v0.16.0

func (s *Store) AcceptLanded(ctx context.Context, id, sha, integ string, by DecidedBy, comment string) (Request, error)

AcceptLanded accepts the pending lane done request id, whose commit sha, stored by MarkLanding, is now on the integration branch integ: the subtask is done and its attempt keeps sha. by decides it, with the owner's note comment when the owner's Accept landed it. The commit has landed, so the finishing guard is not run again.

func (*Store) AddComment

func (s *Store) AddComment(ctx context.Context, a Actor, ref, body string) (Comment, error)

AddComment adds a's comment to the card ref. Agents may comment on cards in their scope, up to CapComments per card per Task.

func (*Store) Approve added in v0.16.0

func (s *Store) Approve(ctx context.Context, a Actor, ref string, settings RunSettings, items []ApproveItem, base string) (Card, error)

Approve is the owner's approval of the epic ref (ADR 0006 §6.2). items are the cards the dialog showed, at the revisions it showed them: each listed proposal is confirmed and pinned to the owner's HEAD, as an owner touch confirms. The epic's run is written, or updated when it was approved before, and its own pause is cleared. base, trimmed, becomes the Project's base branch when it has none; "" leaves it as it is. It refuses, writing nothing, unless the epic is live and not done, or done and approved with live proposals under it; every item is a live card under it; every card the dialog shows (shown) is listed at its current revision (stale otherwise); no subtask under it is held but by a lane; every live story and the epic keep a live subtask that is confirmed or listed; and every such subtask not started resolves to an acceptance command.

func (*Store) Attach added in v0.14.0

func (s *Store) Attach(ctx context.Context, a Actor, ref, taskID, title string, base Baseline, confirm bool) (Card, error)

Attach makes the existing Task taskID work on a subtask, as Launch does for a new Task: its hold starts and its scope becomes the subtask's parent. ref is the subtask, which must not have started, or a story or an epic, under which a new subtask titled title is created for the Task. It is work, so it refuses with CodeUnconfirmed while the subtask or a parent is unconfirmed, unless confirm is set, in which case they are confirmed in the same write. A Task works on one subtask at a time. Under an approved epic nothing is attached (CodeRunOwned).

func (*Store) Board

func (s *Store) Board(ctx context.Context, projectID string) (Snapshot, error)

Board returns one Project's snapshot; "" is the Unassigned list.

func (*Store) CanStart added in v0.16.0

func (s *Store) CanStart(ctx context.Context, ref string) error

CanStart refuses, without writing, a run start of the subtask ref that StartRun would refuse, so a lane start checks before it makes a worktree and a Task. StartRun checks again in its own write.

func (*Store) Card

func (s *Store) Card(ctx context.Context, ref string) (Card, error)

Card returns the card ref.

func (*Store) Cards

func (s *Store) Cards(ctx context.Context, ids []string) ([]Card, error)

Cards returns the cards with the given IDs that still exist, in the order given.

func (*Store) CheckFinishable

func (s *Store) CheckFinishable(ctx context.Context, a Actor, ref string) (Finishable, error)

CheckFinishable runs the finishing guard on the subtask ref for a, so the caller can refuse a claim before running acceptance. For an agent the subtask must also be doing and held by the agent's Task. FileRequest runs the same checks again inside the filing transaction.

func (*Store) CheckLaunch added in v0.14.0

func (s *Store) CheckLaunch(ctx context.Context, a Actor, ref string, confirm bool) error

CheckLaunch refuses, without writing, a launch of ref that Launch would refuse for the cards' own state, so a caller can check before it creates the launch's Task. Launch checks again in its own write.

func (*Store) CheckRevert added in v0.16.0

func (s *Store) CheckRevert(ctx context.Context, a Actor, ref string, include, expect []string) (Closure, error)

CheckRevert refuses, without writing, a revert Revert would refuse, and returns its closure: the closure must be the cards expect lists (stale), and no running attempt may have started on top of it (revert_running).

func (*Store) Checklist

func (s *Store) Checklist(ctx context.Context, a Actor, ref string, e ChecklistEdit) (Card, error)

Checklist ticks, unticks and adds checklist items. Agents may do this on confirmed cards in their scope too. On a started subtask nothing is added, and only its Task and the owner tick.

func (*Store) Claim

func (s *Store) Claim(ctx context.Context, a Actor, ref string, base Baseline) (Card, error)

Claim starts the agent's Task's hold on the subtask ref, which must be in the Task's scope and confirmed, with its ancestors (startHold). A Task may have only one hold without a pending done, blocked or split request at a time, and a planning Task may hold nothing. Nothing under an approved epic is claimed (CodeRunOwned).

func (*Store) ClearLanding added in v0.16.0

func (s *Store) ClearLanding(ctx context.Context, id string) error

ClearLanding withdraws the landing intent of the pending lane done request id, whose integration branch did not move; the request stays pending.

func (*Store) Close

func (s *Store) Close() error

Close closes the database.

func (*Store) Confirm

func (s *Store) Confirm(ctx context.Context, a Actor, ref string) (Card, error)

Confirm confirms a card: it stops expiring and is pinned to the owner's HEAD, and so is every unconfirmed ancestor. Under an approved epic it is refused with CodeRunOwned: the owner approves there from the epic.

func (*Store) Create

func (s *Store) Create(ctx context.Context, a Actor, in NewCard) (Card, error)

Create adds a card. Agents may create stories and subtasks under a container in their scope, and a Task with no scope may propose epics at the root, within the caps; the owner may create any kind anywhere the kind rules allow. The owner's card is confirmed, except under a proposal or an approved epic, where it is a proposal too.

func (*Store) Delete added in v0.15.4

func (s *Store) Delete(ctx context.Context, a Actor, ref string) (DeleteResult, error)

Delete is an agent's delete (ADR 0006): it cancels the card ref in the agent's reach, confirmed or not, and everything under it, in one cascade the owner can restore, each card stamped "deleted" by the Task. It is refused while anything in the subtree has started, while a started subtask waits on a card in it, and when it would bring a container above the card to done or cancelled: that would cancel the container's proposals and release its dependents before any replacement exists. An approved epic itself is never deleted: the agent files a cancel request.

func (*Store) Detail

func (s *Store) Detail(ctx context.Context, ref string) (Detail, error)

Detail returns the card ref with its comments, requests and holds.

func (*Store) Dismiss

func (s *Store) Dismiss(ctx context.Context, a Actor, ref string) (Card, error)

Dismiss is the owner's drop of an unconfirmed card: it cancels the card and everything under it, with the automatic comment "dismissed". It never ends a hold under the card (lock.go). Agents delete instead.

func (*Store) Edit

func (s *Store) Edit(ctx context.Context, a Actor, ref string, p Patch) (EditResult, error)

Edit applies p to the card ref. The owner may edit any field, and the edit confirms the card and its ancestors. An agent edits a card in its scope directly while it has not started, confirmed or not. Once a subtask has started its plan is locked (lock.go): the owner's change to it is refused, and an agent's is filed as a change request, which replaces the Task's earlier pending one. An agent patch carrying an owner-only field is refused before any write.

func (*Store) FileRequest

func (s *Store) FileRequest(ctx context.Context, a Actor, ref string, in RequestInput) (Request, error)

FileRequest files an agent's done, cancel or blocked request on the card ref. A done request needs the subtask doing and held by the agent's Task and passes the finishing guard; the caller supplies its evidence and flags. A newer request of the same kind from the same Task replaces the older pending one. A done request whose PassedCmd is the command the subtask resolves to is accepted at once, as the owner's Accept would accept it, and is returned accepted, unless something holds it back (see WaitReason); a lane's waits to land instead. Nothing is filed on a card whose landing is under way.

func (*Store) FileRequestDetail added in v0.12.2

func (s *Store) FileRequestDetail(ctx context.Context, a Actor, ref string, in RequestInput) (FiledRequest, error)

FileRequestDetail is FileRequest, also saying why a done request was left pending.

func (*Store) Held

func (s *Store) Held(ctx context.Context) ([]Card, error)

Held returns every held subtask on every board, in #seq order.

func (*Store) Import

func (s *Store) Import(ctx context.Context, src string, projects map[string]string) (ImportReport, error)

Import copies the board of the external kb app kept in the directory src, its kb.db at schema v11, into the store in one transaction. projects maps a source project name to a Project ID.

The source is never opened in place: its database, with any -wal and -shm files, is copied into a fresh owner-only temporary directory, read there read-only, and deleted. Symbolic links are refused. A copy that raced a writer is taken again, and a source that keeps changing is refused with CodeImportBusy. Any schema version but v11 is refused with CodeImportSchema.

Each task of the source's default user becomes a confirmed subtask at the root, with no pin, in the Project its project:: tag maps to, or in Unassigned. Title, description, priority, due date, effort, checklist (without blank items) and blocked flag carry over, and every tag but project:: and link:: becomes a label. Repeated titles are kept: the duplicate-title rule does not apply to imports. todo and doing become todo, done done and cancelled cancelled; a task in progress gets the automatic comment "was in progress in kb", and a done or cancelled one the automatic close comment "imported from kb". Comments and cancel reasons are copied as uam's automatic comments, naming their author, and blocker links where both cards are in one Project.

Cards are keyed on the task's UUID, so importing again adds nothing twice. A second import applies only what changed at the source since the last one, so the owner's edits stand until the source changes the same field; it moves a card still in Unassigned into a Project that now maps, copies new comments, and makes each source link not made yet, while the owner's unlinks stand. A change to a held card, to a card cancelled here, or a status the owner could not set directly is skipped and retried by the next import. A purged card is never brought back.

func (*Store) Labels

func (s *Store) Labels(ctx context.Context, projectID string) ([]string, error)

Labels lists a Project's labels, most recently used first.

func (*Store) LandFailed added in v0.16.0

func (s *Store) LandFailed(ctx context.Context, id, reason string, holderActive bool) (Request, error)

LandFailed rejects the pending lane done request id, which cannot land, with reason as uam's decision, and says so on the card (ADR 0006 §4.5). While its Task is live the attempt stays held for it to try again; otherwise the hold is released as rejected, which pauses the subtask. It refuses with landing while a landing intent is stored: the caller clears it first (ClearLanding).

func (*Store) LaneCommits added in v0.16.0

func (s *Store) LaneCommits(ctx context.Context, projectID string) (LaneCommits, error)

LaneCommits returns the landings and the reverts of projectID's lane attempts.

func (*Store) LaneHold added in v0.16.0

func (s *Store) LaneHold(ctx context.Context, branch string) (Card, Hold, error)

LaneHold returns the lane attempt on the attempt branch and its subtask, so cleanup can tell whether the attempt landed; a branch no attempt has is not found.

func (*Store) Launch

func (s *Store) Launch(ctx context.Context, a Actor, ref, taskID string, base Baseline, confirm bool) (Card, error)

Launch starts taskID's hold on the subtask ref and scopes the Task to the subtask's parent. On a container it is "Do whole story": it holds the container's first pending confirmed subtask and scopes the Task to the container. Work starts only on confirmed cards: while the held subtask or an ancestor is unconfirmed, Launch refuses with CodeUnconfirmed, listing them, unless confirm is set. Launch is an owner touch: the held subtask and its unconfirmed ancestors are confirmed and pinned, in the write that starts the hold. base is the working tree state the hold's evidence is measured from. Under an approved epic nothing is launched by hand (CodeRunOwned).

func (s *Store) Link(ctx context.Context, a Actor, blockerRef, blockedRef string) error

Link records "blocker blocks blocked". Both cards must be in the same Project, of the same kind under the same parent (sameLevel); either may be a proposal, since dependencies are part of planning and only starting work needs the owner's confirmation. Self links, duplicates and links that would close a cycle are refused. Agents may link a blocked card in their scope (inScope), which includes the epics a Task proposed, unless it is a container with work started under it (startedWork).

func (*Store) List

func (s *Store) List(ctx context.Context, projectID string, f Filter) ([]Card, error)

List returns a Project's cards matching f, in outline order.

func (*Store) MarkLanding added in v0.16.0

func (s *Store) MarkLanding(ctx context.Context, id, sha string) error

MarkLanding stores sha, the commit the pending lane done request id lands as, as the landing intent on its open attempt, once the finishing guard passes. From then on nothing changes the subtask's status or ends its hold (CodeLanding) until AcceptLanded or ClearLanding. Marking the same sha again does nothing.

func (*Store) Note added in v0.16.0

func (s *Store) Note(ctx context.Context, ref, body string) (bool, error)

Note adds uam's automatic comment body to the card ref, once: a card that has the same comment from uam already is left as it is. It reports whether it added the comment.

func (*Store) OnChange

func (s *Store) OnChange(fn func(Change))

OnChange registers fn to receive each committed write's changes, one per Project, after the commit and outside any transaction. Writers call fn from their own goroutines, so calls may overlap and arrive out of revision order; a Change's Revision orders them.

func (*Store) PauseRun added in v0.16.0

func (s *Store) PauseRun(ctx context.Context, ref, reason string) (Card, error)

PauseRun pauses the approved epic ref as uam after its lane starts kept failing on git or the store (ADR 0006 §4.5), and says why in an automatic comment, cut to one line's length: the owner resumes it. An epic paused already keeps its pause and gets no comment.

func (*Store) PendingLeaves

func (s *Store) PendingLeaves(ctx context.Context, ref string) ([]Card, error)

PendingLeaves returns the confirmed subtasks under the container ref that are waiting to be worked on, depth-first, with blocked ones last.

func (*Store) ProjectSettings

func (s *Store) ProjectSettings(ctx context.Context, projectID string) (ProjectSettings, error)

ProjectSettings returns projectID's settings.

func (*Store) Purge

func (s *Store) Purge(ctx context.Context, a Actor, projectID string) (int, error)

Purge deletes projectID's cancelled cards whose whole subtree is cancelled, with their comments, links, requests and holds. It is the only hard delete. It returns the number of cards deleted.

func (*Store) Reconcile

func (s *Store) Reconcile(ctx context.Context, tasks map[string]Stage, asOf time.Time, uncommitted map[string][]string) (int, error)

Reconcile releases every hold whose Task is Archived or deleted to todo, with the automatic comment "attempt #n ended, uncommitted: …". tasks maps each Task ID to its stage, as the caller read it at asOf on the store's clock; a Task missing from it has been deleted. A hold that started at or after asOf may belong to a Task the snapshot predates, so it is left alone. uncommitted maps a Project ID to its working tree's uncommitted paths, when known. It reads only stored state, so Settled Tasks keep their holds across restarts, and when nothing has ended it writes nothing. It returns the number of holds released.

func (*Store) Reject

func (s *Store) Reject(ctx context.Context, a Actor, id, reason string, holderActive bool) (Request, error)

Reject rejects the pending request id with a reason. When the requesting Task holds the card and is not Active, the hold is released to todo with the reason as a comment; while it is Active the hold stays and the caller sends the reason to the Task. Nothing is rejected on a card whose landing is under way.

func (*Store) ReleaseHold

func (s *Store) ReleaseHold(ctx context.Context, a Actor, ref string, reason ReleaseReason, comment string) (Card, error)

ReleaseHold ends the hold on the subtask ref and returns it to todo, for the owner's Release (ReleaseOwner) or the Settle dialog's release (ReleaseSettled). A non-empty comment is added as the owner's. Every other way a hold ends goes through the same internal path.

func (*Store) Reopen added in v0.16.0

func (s *Store) Reopen(ctx context.Context, a Actor, ref, integ, comment string) (Card, error)

Reopen is the owner's "Reopen without reverting code" of the landed subtask ref, for when Revert cannot apply (ADR 0006 §5.7): it is To do again, paused by the owner, and its landed commit stays on the integration branch integ, as uam's comment says. A non-empty comment is added as the owner's. Nothing moves in git, and the subtasks that landed on top of it stay landed.

func (*Store) Request

func (s *Store) Request(ctx context.Context, id string) (Request, error)

Request returns the request id.

func (*Store) Restore

func (s *Store) Restore(ctx context.Context, a Actor, ref, comment string) (Card, error)

Restore reopens exactly the cards cancelled with the card ref, in one cascade, and confirms each, with its unconfirmed ancestors. Under an approved epic each card but the epic itself comes back as a proposal with a fresh expiry instead, to approve again (ADR 0006 §6.3), unless live confirmed work outside the cascade sits under it; cancelled work under such a card becomes a proposal with it, as no confirmed card sits under a proposal; and a container the restore brings to done stays open with them. A subtask with an earlier attempt reopens as todo, one without as planned. It needs a comment, and is refused while a card of the cascade sits under a cancelled card outside it.

func (*Store) Revert added in v0.16.0

func (s *Store) Revert(ctx context.Context, a Actor, ref string, include, expect []string, commit, reason string) (Closure, error)

Revert records the owner's revert of the card ref, with include, in commit, the revert commit built on the integration tip, before the branch moves to it: each card of the closure is To do again, paused by the owner, and each of its landings is marked reverted in commit, with uam's comment and the reason, when given. It refuses as CheckRevert does, writing nothing.

func (*Store) RevertClosure added in v0.16.0

func (s *Store) RevertClosure(ctx context.Context, ref string, include []string) (Closure, error)

RevertClosure returns what reverting the card ref takes along. The seeds are the subtask, or every landed subtask under a story or an epic, and the cards include adds the same way. The closure is the seeds and the landed subtasks that started on top of one of them, transitively: from the done subtasks each attempt recorded it waited on as it started, so a link changed since changes nothing. A seed with no landed work is refused.

func (*Store) Reverted added in v0.16.0

func (s *Store) Reverted(ctx context.Context) ([]Card, error)

Reverted lists, in #seq order, the subtasks whose latest attempt's landing was reverted and that are still To do and unheld: the reverts whose commit recovery checks is on the integration branch (ADR 0006 §4.7).

func (*Store) Revisions

func (s *Store) Revisions(ctx context.Context) (map[string]int64, error)

Revisions returns every Project's board revision, "" for Unassigned. A Project that was never written has none.

func (*Store) RunFacts added in v0.16.0

func (s *Store) RunFacts(ctx context.Context) (RunFacts, error)

RunFacts reads, in one transaction, what an executor pass decides on: every approved epic with its ready subtasks and its slots in use, every open lane attempt, and each lane Task's ended attempt. Ready and the slot counts are the ones StartRun checks, so a start RunFacts offers is refused only when a write lands in between.

func (*Store) SetProjectAcceptCmd

func (s *Store) SetProjectAcceptCmd(ctx context.Context, a Actor, projectID, cmd string) error

SetProjectAcceptCmd sets projectID's default acceptance command, trimmed; "" means none. Only the owner writes acceptance commands.

func (*Store) SetProjectAcceptParallel added in v0.16.0

func (s *Store) SetProjectAcceptParallel(ctx context.Context, a Actor, projectID string, n int) error

SetProjectAcceptParallel sets how many acceptance runs projectID allows at a time, 1 to MaxAcceptParallel.

func (*Store) SetProjectBaseRef added in v0.16.0

func (s *Store) SetProjectBaseRef(ctx context.Context, a Actor, projectID, ref string) error

SetProjectBaseRef sets the branch projectID's integration branch follows, trimmed; "" unsets it. Whether the branch exists is the caller's to check.

func (*Store) SetStatus

func (s *Store) SetStatus(ctx context.Context, a Actor, ref string, to Status, comment string, force bool) (Card, error)

SetStatus is the owner's direct status change. On a subtask: done needs a comment and passes the finishing guard unless force is set; cancelled needs a comment; todo marks a planned or done subtask ready, or releases a doing one. Done and todo are refused while a lane holds the subtask: its done request lands it, and Stop releases it. Todo is refused on a landed subtask, which is reverted or reopened instead (Reopen). On a container only cancelled is allowed, as a cascade over its subtree; force exists on subtasks only.

func (*Store) Similar

func (s *Store) Similar(ctx context.Context, projectID, title, excludeID string, limit int) ([]SimilarHit, error)

Similar returns up to limit cards in projectID whose titles resemble title, best first, excluding excludeID.

func (*Store) Split

func (s *Store) Split(ctx context.Context, a Actor, ref string, children []SplitChild) (SplitResult, error)

Split splits the subtask ref. Under an epic or at the root it becomes a story whose children are the given ones, then its checklist items in order. Under a story, which can't hold a story, those cards become its siblings, placed right after it, and the subtask is cancelled under its own cascade with the automatic comment "split into #a, #b, …", so Restore brings it back and leaves the siblings. Unticked items become planned subtasks and ticked ones subtasks with a pending done request that cites the tick: a split never creates a done subtask. A subtask that has not started splits at once, for the owner and for an agent in scope; an agent's parts are proposals, so its split is refused, as a delete is, when it would bring a container above the subtask to done or cancelled, and when it would turn a confirmed subtask under an approved epic into a story of proposals, which would never finish. A started one keeps its plan (lock.go): the owner's split is refused, and an agent's is filed as one split request, which the owner can accept once the subtask is released.

func (*Store) StaleCandidates

func (s *Store) StaleCandidates(ctx context.Context, projectID string) ([]Card, error)

StaleCandidates returns the subtasks staleness is computed for: confirmed, not terminal and not held.

func (*Store) StartPlanning

func (s *Store) StartPlanning(ctx context.Context, a Actor, ref, taskID string) error

StartPlanning scopes taskID, a planning Task or a Utility scout, to the container ref. Such a Task creates and edits under the container and holds nothing.

func (*Store) StartRun added in v0.16.0

func (s *Store) StartRun(ctx context.Context, a Actor, ref, taskID string, base Baseline, lane Lane) (Card, error)

StartRun starts a lane attempt at the subtask ref under an approved epic for the new Task taskID (ADR 0006 §4.4, §5.3): it refuses with CodeNotReady unless the subtask is ready and a slot is free under both the epic's parallel limit and MaxLanes, scopes the Task to the subtask alone, records the done subtasks it waited on, and starts the hold on lane's branch from base, the integration branch's tip. The subtask is confirmed already, so nothing is confirmed or pinned. A ref outside approved epics, or a container, is refused as invalid.

func (*Store) Sweep

func (s *Store) Sweep(ctx context.Context) (int, error)

Sweep runs the expiry sweep over every Project, as at boot. It returns the number of cards cancelled.

func (*Store) Unassign

func (s *Store) Unassign(ctx context.Context, projectID string) (int, error)

Unassign moves every card of projectID, a Project being removed, to the read-only Unassigned list, keeping its tree, comments and history. The Project's Tasks are gone with it, so its pending requests are withdrawn and a hold still open ends as an ended attempt, a landing under way included: its repository is gone. Its epics' approvals and its pauses were given for its repository, so they go too. It returns the number of cards moved.

func (*Store) UndoRevert added in v0.16.0

func (s *Store) UndoRevert(ctx context.Context, commit, reason string) error

UndoRevert withdraws the revert recorded in commit, which the integration branch never took (ADR 0006 §4.4): its landings are unmarked, each of its subtasks still To do and unheld is done again and no longer paused, and uam's comment on each says why with reason. These are uam's writes. A pause the owner set on a landed subtask before the revert is not kept: it held nothing back, since a landed subtask goes back to To do only through a Revert or a Reopen, which both pause it.

func (s *Store) Unlink(ctx context.Context, a Actor, aRef, bRef string) error

Unlink removes the link between two cards, whichever way it points. An agent unlinks where it may link: the blocked card is in its scope, and no container with work started under it. Neither card may have started (lock.go).

type TaskFact added in v0.16.0

type TaskFact struct {
	Stage    Stage
	Turn     Turn
	Provider string
	// Worked reports whether the lane has commits or changes beyond its
	// base; the caller reads it for a failed holder only.
	Worked bool
	// FailedAt is when a failed turn ended.
	FailedAt time.Time
}

TaskFact is a lane Task as one executor pass sees it.

type Turn added in v0.16.0

type Turn int

Turn is where a lane Task's turn stands, as the caller reads it.

const (
	TurnWorking        Turn = iota // a turn is running
	TurnWaiting                    // the turn waits for a permission or an answer
	TurnEnded                      // the turn completed, or none ran
	TurnFailed                     // the turn failed, or the runtime exited
	TurnInterrupted                // a restart interrupted the turn
	TurnOwnerCancelled             // the owner cancelled the turn
	TurnUAMCancelled               // uam cancelled the turn, with a reason
)

The turns.

type WaitReason added in v0.12.2

type WaitReason string

WaitReason is why a done request was left pending for the owner instead of accepted as it was filed (ADR 0005 decision 5).

const (
	// WaitNone: the request was accepted, or is not a done request.
	WaitNone WaitReason = ""
	// WaitNoCommand: the subtask resolves to no acceptance command.
	WaitNoCommand WaitReason = "no_command"
	// WaitCouldNotRun: the command's shell did not start.
	WaitCouldNotRun WaitReason = "could_not_run"
	// WaitFlagged: the request carries another flag.
	WaitFlagged WaitReason = "flagged"
	// WaitCommandChanged: the command the subtask resolves to is not the one
	// that passed, as when the owner changed it during the run.
	WaitCommandChanged WaitReason = "command_changed"
	// WaitClosesWithProposals: accepting it would close containers that
	// still have proposals.
	WaitClosesWithProposals WaitReason = "closes_with_proposals"
	// WaitLanding: a lane's done request that nothing else holds back waits
	// to land on the integration branch, which accepts it (ADR 0006 §5.4).
	WaitLanding WaitReason = "landing"
)

The wait reasons, in the order they are checked.

type Why added in v0.16.0

type Why string

Why says why a lane Task is nudged or cancelled.

const (
	// WhyRestarted: a restart interrupted the holder's turn.
	WhyRestarted Why = "restarted"
	// WhyNoDone: the holder's turn ended without a done request.
	WhyNoDone Why = "no_done"
	// WhyProviderFailed: the provider failed during the holder's turn.
	WhyProviderFailed Why = "provider_failed"
	// WhyStopped: a cancel of a Task whose attempt was stopped.
	WhyStopped Why = "stopped"
)

The reasons (ADR 0006 §4.2).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL