Documentation
¶
Overview ¶
Package db provides SQLite database operations.
Index ¶
- Constants
- Variables
- func DefaultExecutor() string
- func DefaultPath() string
- func EffortLevels() []string
- func ExecutorSupportsModel(executor string) bool
- func ExpandHomePath(path string) string
- func FoldStatus(events []StatusEvent) string
- func FoldStatusAt(events []StatusEvent, throughID int64) string
- func GlobalDefaultPermissionMode() string
- func IsInProgress(status string) bool
- func IsKnownExecutor(name string) bool
- func IsRefused(err error) bool
- func IsValidEffortLevel(s string) bool
- func IsValidModel(s string) bool
- func KnownExecutors() []string
- func ModelBackendIsCustom(configDir string, env map[string]string) bool
- func ModelCapableExecutors() []string
- func ModelOptions() []string
- func ModelsForExecutor(executor string) []string
- func NextPermissionMode(mode string) string
- func NormalizePermissionMode(mode string) string
- func NormalizeViewName(name string) string
- func PermissionModeLabel(mode string) string
- func RefusalGate(err error) string
- func TaskSettingKey(base string, taskID int64) string
- func ValidateModel(executor, model string) error
- func ValidateViewName(name string) error
- type Actor
- type AgentTurn
- type Attachment
- type DB
- func (db *DB) AddAttachment(taskID int64, filename, mimeType string, data []byte) (*Attachment, error)
- func (db *DB) AddDependency(blockerID, blockedID int64, autoQueue bool) error
- func (db *DB) AgentTurnState(taskID int64) (AgentTurn, error)
- func (db *DB) AllocatePort(taskID int64) (int, error)
- func (db *DB) AppendTaskLog(taskID int64, lineType, content string) error
- func (db *DB) AttachmentDirectory() string
- func (db *DB) BeginAgentTurn(taskID int64) (AgentTurn, error)
- func (db *DB) BeginRemoteRun(taskID int64, host string) (string, error)
- func (db *DB) CheckStatusConsistency() ([]StatusMismatch, error)
- func (db *DB) ClearArchiveState(taskID int64) error
- func (db *DB) ClearTaskLogs(taskID int64) error
- func (db *DB) ClearTaskPaneIDs(taskID int64) error
- func (db *DB) ClearTaskPlacement(taskID int64) error
- func (db *DB) ClearTaskSessionPlacement(taskID int64) error
- func (db *DB) ClearTaskTmuxIDs(taskID int64) error
- func (db *DB) ClearTaskWorktreePath(taskID int64) error
- func (db *DB) ClearTaskWorktreeRefs(taskID int64) error
- func (db *DB) ClearWorktreeSweepFailure(taskID int64) error
- func (db *DB) CommitTaskPlacement(taskID int64, target, reason, workDir, branch string) error
- func (db *DB) CompleteAgentTurn(taskID int64) (AgentTurn, error)
- func (db *DB) CompleteOnboarding() error
- func (db *DB) CoordinatorID() (string, error)
- func (db *DB) CountAttachments(taskID int64) (int, error)
- func (db *DB) CountRecentExecutorStarts(taskID int64, window time.Duration) (int, error)
- func (db *DB) CountStatusEvents() (int, error)
- func (db *DB) CountTasksByProject(projectName string) (int, error)
- func (db *DB) CountTasksByStatus(status string) (int, error)
- func (db *DB) CreateProject(p *Project) error
- func (db *DB) CreateRoutineRun(routine string) (int64, error)
- func (db *DB) CreateTask(t *Task) error
- func (db *DB) CreateTaskType(t *TaskType) error
- func (db *DB) DeleteAttachment(id int64) error
- func (db *DB) DeleteProject(id int64) error
- func (db *DB) DeleteRoutineRuns(routine string) error
- func (db *DB) DeleteSavedView(name string) error
- func (db *DB) DeleteTask(id int64) error
- func (db *DB) DeleteTaskSettings(taskID int64) error
- func (db *DB) DeleteTaskType(id int64) error
- func (db *DB) FinishRoutineRun(id int64, status string, exitCode int, output string) error
- func (db *DB) GetActiveTaskPorts() (map[int]bool, error)
- func (db *DB) GetAllDependencies(taskID int64) (blockers []*Task, blockedBy []*Task, err error)
- func (db *DB) GetAllSettings() (map[string]string, error)
- func (db *DB) GetAppliedStatusEvents(taskID int64) ([]StatusEvent, error)
- func (db *DB) GetAttachment(id int64) (*Attachment, error)
- func (db *DB) GetBlockedBy(taskID int64) ([]*Task, error)
- func (db *DB) GetBlockers(taskID int64) ([]*Task, error)
- func (db *DB) GetConversationHistoryLogs(taskID int64) ([]*TaskLog, error)
- func (db *DB) GetDependency(blockerID, blockedID int64) (*Dependency, error)
- func (db *DB) GetExecutorUsageByProject(project string) (map[string]int, error)
- func (db *DB) GetLastEffortForProject(project string) (string, error)
- func (db *DB) GetLastExecutorForProject(project string) (string, error)
- func (db *DB) GetLastModelForProject(project string) (string, error)
- func (db *DB) GetLastPermissionForProject(project string) (string, error)
- func (db *DB) GetLastQuestion(taskID int64) (string, error)
- func (db *DB) GetLastTaskTypeForProject(project string) (string, error)
- func (db *DB) GetLastUsedProject() (string, error)
- func (db *DB) GetLatestLogPerTask(taskIDs []int64) (map[int64]*TaskLog, error)
- func (db *DB) GetMostRecentlyCreatedTask() (*Task, error)
- func (db *DB) GetNextQueuedTask() (*Task, error)
- func (db *DB) GetOpenBlockerCount(taskID int64) (int, error)
- func (db *DB) GetPipelineArtifact(branch, name string) (string, error)
- func (db *DB) GetProjectByName(name string) (*Project, error)
- func (db *DB) GetProjectByPath(cwd string) (*Project, error)
- func (db *DB) GetProjectContext(projectName string) (string, error)
- func (db *DB) GetQueuedTasks() ([]*Task, error)
- func (db *DB) GetRetryFeedback(taskID int64) (string, error)
- func (db *DB) GetRoutineRun(id int64) (*RoutineRun, error)
- func (db *DB) GetSavedView(name string) (*SavedView, error)
- func (db *DB) GetSetting(key string) (string, error)
- func (db *DB) GetStaleWorktreeTasks(maxAge time.Duration) ([]*Task, error)
- func (db *DB) GetStaleWorktreeTasksIncludingFailed(maxAge time.Duration) ([]*Task, error)
- func (db *DB) GetStatusEvents(taskID int64) ([]StatusEvent, error)
- func (db *DB) GetStepVerify(taskID int64) (string, error)
- func (db *DB) GetSweepableTrashedTasks(maxAge time.Duration) ([]*TrashedTask, error)
- func (db *DB) GetTagsList() ([]string, error)
- func (db *DB) GetTask(id int64) (*Task, error)
- func (db *DB) GetTaskBaseCommit(taskID int64) (string, error)
- func (db *DB) GetTaskBaseDirty(taskID int64) (string, error)
- func (db *DB) GetTaskByWorktreePath(path string) (*Task, error)
- func (db *DB) GetTaskLogCount(taskID int64) (int, error)
- func (db *DB) GetTaskLogs(taskID int64, limit int) ([]*TaskLog, error)
- func (db *DB) GetTaskLogsBefore(taskID, beforeID int64, limit int) ([]*TaskLog, error)
- func (db *DB) GetTaskLogsSince(taskID int64, sinceID int64) ([]*TaskLog, error)
- func (db *DB) GetTaskLogsSinceLimit(taskID, sinceID int64, limit int) ([]*TaskLog, error)
- func (db *DB) GetTaskPlacement(taskID int64) (target, reason string, err error)
- func (db *DB) GetTaskPlacementDecision(taskID int64) (TaskPlacement, error)
- func (db *DB) GetTaskRemoteWorktree(taskID int64) (path, branch string, err error)
- func (db *DB) GetTaskType(id int64) (*TaskType, error)
- func (db *DB) GetTaskTypeByName(name string) (*TaskType, error)
- func (db *DB) HasContinuationMarker(taskID int64) (bool, error)
- func (db *DB) HasLogLineContaining(taskID int64, substr string) (bool, error)
- func (db *DB) HasOpenTaskWithTitle(title string) (bool, error)
- func (db *DB) HasQuestionLog(taskID int64) (bool, error)
- func (db *DB) HasSessionEnded(taskID int64) (bool, error)
- func (db *DB) HasSessionStarted(taskID int64) (bool, error)
- func (db *DB) IsBlocked(taskID int64) (bool, error)
- func (db *DB) IsFirstRun() bool
- func (db *DB) LatestRoutineRuns() (map[string]*RoutineRun, error)
- func (db *DB) ListAttachments(taskID int64) ([]*Attachment, error)
- func (db *DB) ListAttachmentsWithData(taskID int64) ([]*Attachment, error)
- func (db *DB) ListPipelineArtifacts(branch string) ([]PipelineArtifact, error)
- func (db *DB) ListPlacementHosts() ([]string, error)
- func (db *DB) ListProjects() ([]*Project, error)
- func (db *DB) ListRoutineRuns(routine string, limit int) ([]*RoutineRun, error)
- func (db *DB) ListSavedViews() ([]*SavedView, error)
- func (db *DB) ListTaskTypes() ([]*TaskType, error)
- func (db *DB) ListTasks(opts ListTasksOptions) ([]*Task, error)
- func (db *DB) ListTrashedTasks() ([]*TrashedTask, error)
- func (db *DB) ListWorktreeRefs() ([]WorktreeRef, error)
- func (db *DB) MarkTaskStarted(id int64) error
- func (db *DB) MarkWorktreeSweepFailed(taskID int64) error
- func (db *DB) MigrateAttachmentFiles() error
- func (db *DB) Path() string
- func (db *DB) ProcessCompletedBlocker(blockerID int64) ([]*Task, error)
- func (db *DB) ReadSchemaVersion() (int, bool)
- func (db *DB) RecordHostHealth(host, problem string, observed bool) error
- func (db *DB) RecoverStaleTmuxRefs(activeSessions map[string]bool, validWindowIDs map[string]bool) (int, int, error)
- func (db *DB) RemoteHostHealth(host string) (HostHealth, error)
- func (db *DB) RemoteSignal(taskID int64, host string) (RemoteEvent, bool, error)
- func (db *DB) RemoveDependency(blockerID, blockedID int64) error
- func (db *DB) RequeueReadyTasks() ([]*Task, error)
- func (db *DB) RestartIdleClock(id int64) error
- func (db *DB) RestoreTask(id int64) error
- func (db *DB) RetryTask(id int64, feedback string) error
- func (db *DB) SaveArchiveState(taskID int64, archiveRef, archiveCommit, worktreePath, branchName string) error
- func (db *DB) SaveRemoteEvent(ev RemoteEvent) error
- func (db *DB) SaveView(name, query string) (*SavedView, error)
- func (db *DB) SearchTasks(query string, limit int) ([]*Task, error)
- func (db *DB) SetAutoQueue(blockerID, blockedID int64, autoQueue bool) error
- func (db *DB) SetEventEmitter(emitter EventEmitter)
- func (db *DB) SetLastEffortForProject(project, effort string) error
- func (db *DB) SetLastExecutorForProject(project, executor string) error
- func (db *DB) SetLastModelForProject(project, model string) error
- func (db *DB) SetLastPermissionForProject(project, mode string) error
- func (db *DB) SetLastTaskTypeForProject(project, taskType string) error
- func (db *DB) SetLastUsedProject(project string) error
- func (db *DB) SetPipelineArtifact(branch, name, content string) error
- func (db *DB) SetProjectContext(projectName string, context string) error
- func (db *DB) SetRoutineRunLogPath(id int64, logPath string) error
- func (db *DB) SetSetting(key, value string) error
- func (db *DB) SetStepVerify(taskID int64, command string) error
- func (db *DB) SetTaskBaseCommit(taskID int64, sha string) error
- func (db *DB) SetTaskBaseDirty(taskID int64, paths string) error
- func (db *DB) SetTaskPlacement(taskID int64, target, reason string) error
- func (db *DB) SetTaskPlacementDecision(taskID int64, target, reason, workDir string) error
- func (db *DB) SetTaskRemoteWorktree(taskID int64, path, branch string) error
- func (db *DB) SetTaskStatus(id int64, to string, actor Actor, reason string, evidence Evidence) error
- func (db *DB) SoftDeleteTask(id int64) error
- func (db *DB) UpdateProject(p *Project) error
- func (db *DB) UpdateTask(t *Task) error
- func (db *DB) UpdateTaskClaudeConfigDir(taskID int64, configDir string) error
- func (db *DB) UpdateTaskClaudeSessionID(taskID int64, sessionID string) error
- func (db *DB) UpdateTaskDaemonSession(taskID int64, daemonSession string) error
- func (db *DB) UpdateTaskDangerousMode(taskID int64, dangerousMode bool) error
- func (db *DB) UpdateTaskLastAccessedAt(taskID int64) error
- func (db *DB) UpdateTaskPRInfo(taskID int64, prURL string, prNumber int, prInfoJSON string) error
- func (db *DB) UpdateTaskPaneIDs(taskID int64, claudePaneID, shellPaneID string) error
- func (db *DB) UpdateTaskPermissionMode(taskID int64, mode string) error
- func (db *DB) UpdateTaskPinned(taskID int64, pinned bool) error
- func (db *DB) UpdateTaskStartedAt(taskID int64, t time.Time) error
- func (db *DB) UpdateTaskSummary(taskID int64, summary string) error
- func (db *DB) UpdateTaskType(t *TaskType) error
- func (db *DB) UpdateTaskWindowID(taskID int64, windowID string) error
- func (db *DB) ValidateTaskModel(t *Task) error
- func (db *DB) WaitForAgentReply(ctx context.Context, taskID int64, since AgentTurn, timeout time.Duration) (AgentTurn, error)
- func (db *DB) WorktreeSweepFailedAt(taskID int64) (*time.Time, error)
- type Dependency
- type EventEmitter
- type Evidence
- type HostHealth
- type ListTasksOptions
- type LocalTime
- type OpenOptions
- type PipelineArtifact
- type Project
- type ProjectAction
- type RefusedError
- type RemoteEvent
- type RoutineRun
- type SavedView
- type StatusEvent
- type StatusMismatch
- type Task
- type TaskLog
- type TaskPlacement
- type TaskType
- type TrashedTask
- type WorktreeRef
Constants ¶
const ( ModelFable = "fable" ModelOpus = "opus" ModelSonnet = "sonnet" ModelHaiku = "haiku" // ModelOpusPlan is Claude Code's planning alias (Opus to plan, Sonnet to // execute). Accepted as an override but kept out of the UI picker. ModelOpusPlan = "opusplan" )
Per-task model overrides pick which model an executor's CLI runs (its `--model` flag). An empty value means "no override": the task uses the agent's own default, leaving the user's global setting untouched.
Overrides are validated before they are stored because a bad one is invisible: the task launches, the agent CLI rejects the flag inside tmux, and the card just sits there looking busy. An early default baked the executor slug "claude" into every row (see the clear-model repair in sqlite.go) — exactly that failure.
const ( RoutineRunStatusRunning = "running" RoutineRunStatusOK = "ok" RoutineRunStatusFailed = "failed" )
Routine run statuses.
const ( // OutcomeApplied means the transition happened. Only these are folded. OutcomeApplied = "applied" // OutcomeRefused means a gate rejected it. Recorded so an attempt to bury a // task leaves a trace instead of a silent no-op. OutcomeRefused = "refused" )
Transition outcomes recorded in the log.
const ( // GateEvidenceRequired: a terminal transition arrived with nothing observed. GateEvidenceRequired = "evidence-required" // GateNeverStarted: automation tried to complete a task that never ran. GateNeverStarted = "never-started" // GateOpenPR: a done-write for a task whose pull request is still open. GateOpenPR = "open-pr" // GateHumanOnly: automation tried to finish or archive a task. Only a // person does that; the one exception is a workflow step with dependents. GateHumanOnly = "human-only" // GateUnknownStatus: the target status is not a status. GateUnknownStatus = "unknown-status" // GateMissingActor / GateMissingReason: the write did not say who or why. GateMissingActor = "missing-actor" GateMissingReason = "missing-reason" )
Gate names. A refusal always carries one, so the reason a write bounced is a value you can grep for and not prose you have to parse.
const ( StatusBacklog = "backlog" // Created but not yet started StatusQueued = "queued" // Waiting to be processed StatusProcessing = "processing" // Currently being executed StatusBlocked = "blocked" // Needs input/clarification StatusDone = "done" // Completed StatusArchived = "archived" // Archived (hidden from view) )
Task statuses
const ( // PermissionModeDefault prompts for every permission (the historical default). // Maps to Claude's --permission-mode default. PermissionModeDefault = "default" // PermissionModeAcceptEdits auto-accepts file edits but still prompts for // risky actions (shell, network, etc.). Maps to Claude's // --permission-mode acceptEdits. PermissionModeAcceptEdits = "accept-edits" // PermissionModeAuto is Claude Code's auto mode (--permission-mode auto): an // AI classifier auto-approves a broad set of safe actions (edits and safe // commands) while still hard-denying dangerous ones. More autonomous than // accept-edits, but far safer than fully bypassing permissions. PermissionModeAuto = "auto" // PermissionModeDangerous bypasses all permission checks // (Claude's --dangerously-skip-permissions). PermissionModeDangerous = "dangerous" )
Permission modes control how the underlying agent handles permission prompts. They map one-to-one onto Claude Code's --permission-mode choices (plus the --dangerously-skip-permissions shortcut). There are four sets, from most to least gated: default → accept-edits → auto → dangerous.
HISTORY: TaskYou originally used the value "auto" for what is really Claude's acceptEdits mode — that predated Claude Code shipping its own "auto mode". The value "auto" now means Claude Code's actual auto mode (--permission-mode auto), and the old acceptEdits set has the explicit value "accept-edits". A one-time DB migration rewrites pre-existing "auto" rows (which meant acceptEdits) to "accept-edits"; see migrate() in sqlite.go.
const ( TypeCode = "code" TypeWriting = "writing" TypeThinking = "thinking" )
Task types (default values, actual types are stored in task_types table)
const ( ExecutorClaude = "claude" // Claude Code CLI (default) ExecutorCodex = "codex" // OpenAI Codex CLI ExecutorGemini = "gemini" // Google Gemini CLI ExecutorGrok = "grok" // Grok CLI (https://x.ai/cli) ExecutorCursor = "cursor" // Cursor CLI (https://cursor.com/docs/cli) ExecutorOpenClaw = "openclaw" // OpenClaw AI assistant (https://openclaw.ai) ExecutorOpenCode = "opencode" // OpenCode AI assistant (https://opencode.ai) ExecutorPi = "pi" // Pi coding agent (https://github.com/mariozechner/pi-coding-agent) )
Task executors
const ( EffortLow = "low" EffortMedium = "medium" EffortHigh = "high" EffortXHigh = "xhigh" EffortMax = "max" )
Effort levels are per-task overrides for Claude's reasoning effort (claude --effort). An empty value means "no override" — the task uses Claude's global default, leaving the user's global setting untouched.
const ( PortRangeStart = 3100 // First port in the allocation range PortRangeEnd = 4099 // Last port in the allocation range (1000 ports total) )
Port allocation constants
const DefaultBusyTimeout = 5 * time.Second
DefaultBusyTimeout is how long a normal connection waits for a locked database before giving up. Long enough to ride out the daemon's writes.
const MaxSavedViewName = 40
MaxSavedViewName bounds a view name so it stays renderable in the TUI picker and in `ty views list`.
const SchemaVersion = 3
SchemaVersion is the migration level this build brings a database up to.
It is a hand-maintained counter, bumped by one every time a migration is added to migrate() below — there is no automatic derivation, because the migrations are idempotent statements rather than numbered files and nothing in the list can be counted reliably (ALTER TABLEs are allowed to fail, and remoteMigrations is appended from another file).
Two things read it. `ty doctor` compares the stamp in a database against this constant to tell "current" from "last touched by an older ty". And handshake.Protocol must be bumped whenever a schema change means a daemon and a client of different builds would disagree about a row — see internal/handshake.
const SchemaVersionKey = "schema_version"
SchemaVersionKey is where SchemaVersion is stamped in the settings table.
const SessionEndedLogPrefix = "Agent session ended"
SessionEndedLogPrefix starts the log line an agent's own "I am exiting" hook writes (Claude's SessionEnd). It is the one exit signal that is not an inference: a missing tmux window can equally mean the pane was moved into a UI session, or that the window has not come up yet.
Variables ¶
var DefaultProjectColors = []string{
"#C678DD",
"#61AFEF",
"#56B6C2",
"#98C379",
"#E5C07B",
"#E06C75",
"#D19A66",
"#ABB2BF",
}
DefaultProjectColors is a palette of distinct colors for projects. These are assigned to projects that don't have a color set.
var ErrProjectNotFound = fmt.Errorf("project not found")
ErrProjectNotFound is returned when a task is created with a non-existent project.
var ErrReplyTimeout = errors.New("timed out waiting for the agent to reply")
ErrReplyTimeout is returned by WaitForAgentReply when no new turn completed inside the timeout. It says nothing about the agent's health: a long task is indistinguishable here from a dead one.
var NoEvidence = Evidence{}
NoEvidence is the explicit "nothing observed" value. It is fine for ordinary transitions (queueing, starting, parking) and is refused for terminal ones.
var PermissionModeCycle = []string{ PermissionModeDefault, PermissionModeAcceptEdits, PermissionModeAuto, PermissionModeDangerous, }
PermissionModeCycle is the order the UI cycles permission modes, from most to least gated. Cycling keeps the four modes reachable on a running task; each step relaunches the live session so it matches the stored mode.
Functions ¶
func DefaultExecutor ¶
func DefaultExecutor() string
DefaultExecutor returns the default executor if none is specified.
func EffortLevels ¶ added in v0.2.40
func EffortLevels() []string
EffortLevels returns the valid per-task effort override values, in ascending order.
func ExecutorSupportsModel ¶ added in v0.3.26
ExecutorSupportsModel reports whether the executor's CLI takes a --model flag. An empty executor means the default (claude).
func ExpandHomePath ¶ added in v0.3.22
ExpandHomePath turns a leading "~" into the user's home directory.
A project path reaches the DB from several places — the settings form, the project-detect flow, `ty project add`, a hand-edited row — and some of them store the shell's own shorthand, "~/Projects/foo". Nothing downstream runs through a shell: the executor and the pipeline hand these paths straight to exec.Command("git", "-C", dir, ...), where a literal "~" is just a directory name that does not exist. The failure is remote from its cause — a pipeline aborting with
fatal: cannot change to '~/Projects/rails/offerlab': No such file or directory
and a GetProjectByPath that silently never matches, so project detection and project-local workflow dirs quietly do nothing.
Callers used to be expected to remember config.GetProjectDir; the ones that read Project.Path directly (three of them, at the time of writing) did not. Normalizing on both write and read removes the chance to forget.
A "~user/..." form is left alone: resolving another user's home is not something we can do reliably, and it has never been a path we support.
func FoldStatus ¶ added in v0.3.31
func FoldStatus(events []StatusEvent) string
FoldStatus projects a task's status from its event log: the target of the last APPLIED transition. Refused attempts are in the log for the audit trail and are deliberately not folded — a refusal changed nothing.
Events must be in append order (ascending id), which is what GetStatusEvents returns.
func FoldStatusAt ¶ added in v0.3.31
func FoldStatusAt(events []StatusEvent, throughID int64) string
FoldStatusAt projects the status as of event throughID — the same fold, rewound. This is what makes the log a source of truth rather than a changelog: any past state can be reproduced from it.
func GlobalDefaultPermissionMode ¶ added in v0.2.40
func GlobalDefaultPermissionMode() string
GlobalDefaultPermissionMode returns the fallback permission mode used when a project has no explicit default. It can be overridden with the TASKYOU_DEFAULT_PERMISSION_MODE environment variable. Defaults to "auto" (Claude Code's auto mode) so tasks start maximally unblocked while the classifier still gates dangerous actions; set the env var to "accept-edits" or "default" to dial back autonomy.
func IsInProgress ¶
IsInProgress returns true if the task is actively being worked on.
func IsKnownExecutor ¶ added in v0.3.24
IsKnownExecutor reports whether name is a built-in executor slug.
func IsRefused ¶ added in v0.3.31
IsRefused reports whether err is a gate refusal (as opposed to an I/O error).
func IsValidEffortLevel ¶ added in v0.2.40
IsValidEffortLevel reports whether s is a valid effort level. The empty string is valid and means "use the global/Claude default" (no per-task override).
func IsValidModel ¶ added in v0.3.14
IsValidModel reports whether s is an acceptable per-task model override for *some* executor. The empty string is valid and means "use the agent default". Prefer ValidateModel when the executor is known; this looser form exists for callers holding a remembered value with no executor in hand (the new-task form's per-project default).
func KnownExecutors ¶ added in v0.3.24
func KnownExecutors() []string
KnownExecutors returns the built-in executor slugs in display order.
func ModelBackendIsCustom ¶ added in v0.3.26
ModelBackendIsCustom reports whether a Claude run is pointed at something other than Anthropic's API — a CLAUDE_CONFIG_DIR override or an ANTHROPIC_BASE_URL env override (the two ways ty routes a task through a proxy such as ollama). Model names are the proxy's there, so overrides must not be validated against Anthropic's.
func ModelCapableExecutors ¶ added in v0.3.26
func ModelCapableExecutors() []string
ModelCapableExecutors returns the executors that accept a model override, in KnownExecutors display order.
func ModelOptions ¶ added in v0.3.14
func ModelOptions() []string
ModelOptions returns the per-task model override aliases offered in the UI picker. It is a curated shortlist, not the set ValidateModel accepts: full model IDs and opusplan are valid overrides but not picker entries.
func ModelsForExecutor ¶ added in v0.3.26
ModelsForExecutor returns the model names ty knows about for an executor, in display order — used for `ty create --model` shell completion and error messages. It is not exhaustive: any ID carrying the executor's vendor prefix is also accepted. Nil when the executor has no --model flag.
func NextPermissionMode ¶ added in v0.3.2
NextPermissionMode returns the next mode after the given one in PermissionModeCycle, wrapping around. Unknown input starts the cycle at accept-edits (one past default), so "advance from wherever you are" is sane.
func NormalizePermissionMode ¶ added in v0.2.40
NormalizePermissionMode coerces a raw value into a known permission mode. "prompt" and "" are treated as default; Claude's own "acceptEdits" spelling (and "accept_edits") normalizes to PermissionModeAcceptEdits. Matching is case- and whitespace-insensitive. Unknown values return "".
func NormalizeViewName ¶ added in v0.3.31
NormalizeViewName trims a view name and folds internal whitespace, so " In Progress " and "In Progress" are the same view rather than two rows that look identical in the picker.
func PermissionModeLabel ¶ added in v0.3.2
PermissionModeLabel returns a short human-facing label for a permission mode.
func RefusalGate ¶ added in v0.3.31
RefusalGate returns the gate that refused err, or "".
func TaskSettingKey ¶ added in v0.3.31
TaskSettingKey namespaces a setting to a single task. Per-task preferences live in the settings table under "<base>:<taskID>", beside the global default stored under "<base>" alone.
func ValidateModel ¶ added in v0.3.26
ValidateModel reports whether model is a model the executor's CLI would actually accept. The empty string is always valid and means "no override".
A model is accepted when it is one of the executor's aliases (optionally with a "[1m]" variant suffix) or a well-formed ID carrying the executor's vendor prefix — "claude-opus-5" and "grok-4-fast" pass without ty having to track every release. Everything else is rejected, which catches the two mistakes that actually happen: a typo ("opuss") and a model belonging to some other vendor ("gpt-5", or the "claude" executor slug).
Callers must skip this check when the agent is routed at a non-stock backend — a CLAUDE_CONFIG_DIR override or ANTHROPIC_BASE_URL pointing at a proxy like ollama — because the model names are then the proxy's (e.g. "glm-5.2:cloud") and ty has no way to know them. See ModelBackendIsCustom.
func ValidateViewName ¶ added in v0.3.31
ValidateViewName reports why a view name is unusable, or nil when it is fine.
Types ¶
type Actor ¶ added in v0.3.31
type Actor string
Actor names what made a status change. It is not decoration: "the sweep did it" versus "a human did it" is the difference between a bug and a decision, and after the fact the log is the only place that distinction survives.
const ( // ActorTUI is the interactive kanban UI, driven by a human at a keyboard. ActorTUI Actor = "tui" // ActorCLI is a `ty` subcommand, run by a human in a shell. ActorCLI Actor = "cli" // ActorWeb is the HTTP API (web UI, desktop app, remote control). ActorWeb Actor = "web" // ActorMCP is an agent calling a taskyou_* MCP tool about its own task. ActorMCP Actor = "mcp" // ActorDaemon is the executor's own lifecycle bookkeeping — queueing, // starting, and parking the tasks it runs. ActorDaemon Actor = "daemon" // ActorSweep is a periodic reconciler acting on a task no one asked about. // The most dangerous actor in the system, and the one with the strictest // evidence requirement. ActorSweep Actor = "sweep" // ActorHook is an executor hook (Claude's Stop/Notification/PreToolUse) // reporting what the agent process just did. ActorHook Actor = "hook" // ActorPipeline is workflow construction wiring a DAG's steps into their // initial states. ActorPipeline Actor = "pipeline" // ActorSystem is ty itself doing structural bookkeeping — creating a task, // releasing a dependent whose blockers all finished. ActorSystem Actor = "system" // ActorMigration is the one-time backfill that gave pre-log tasks a genesis // event. It never appears on a transition made after this feature shipped. ActorMigration Actor = "migration" )
func KnownActors ¶ added in v0.3.31
func KnownActors() []Actor
KnownActors lists every actor, for validation and for `ty debug`.
type AgentTurn ¶ added in v0.3.31
AgentTurn is a task's turn counters: how many turns the agent has begun, and how many it has finished. Started is always >= Completed while the agent is working.
func (AgentTurn) RepliedAfter ¶ added in v0.3.31
RepliedAfter reports whether t is a completed reply to a prompt sent when the counters read prev — a turn that both started after the send and has since finished.
Completed >= Started is what keeps the PREVIOUS turn's Stop from being read as this turn's answer: a stale Stop can only raise Completed to a value Started has already passed.
type Attachment ¶
type Attachment struct {
ID int64
TaskID int64
Filename string
MimeType string
Size int64
Data []byte
CreatedAt LocalTime
}
Attachment represents a file attached to a task.
type DB ¶
DB wraps the SQLite database connection.
func OpenReadOnly ¶ added in v0.3.31
OpenReadOnly opens an existing database without migrating it.
`ty doctor` exists to report what is on this machine, not to change it, and db.Open's first act is to run every migration — which on an old file is a repair. Opening read-only means doctor can say "this database was last migrated by an older build" instead of quietly making that untrue.
The file must already exist: creating one would itself be a change.
func OpenWithOptions ¶ added in v0.3.31
func OpenWithOptions(path string, opts OpenOptions) (*DB, error)
OpenWithOptions opens a database with explicit options. See Open.
The agent-facing hooks pass a short busy timeout and skip migrations: a hook runs in the agent's critical path, so a database another process holds locked must make it give up quickly and silently rather than hold the agent at a stopped cursor. Everything else should use Open.
func (*DB) AddAttachment ¶
func (db *DB) AddAttachment(taskID int64, filename, mimeType string, data []byte) (*Attachment, error)
AddAttachment adds a file attachment to a task.
func (*DB) AddDependency ¶
AddDependency creates a dependency where blockerID blocks blockedID. Returns an error if the dependency already exists or would create a cycle.
func (*DB) AgentTurnState ¶ added in v0.3.31
AgentTurnState returns a task's turn counters. A task nothing has been sent to yet reads as zero, which is the right answer: nothing has started and nothing has finished.
func (*DB) AllocatePort ¶
AllocatePort assigns an available port to a task. Returns the allocated port, or an error if no ports are available.
func (*DB) AppendTaskLog ¶
AppendTaskLog appends a log entry to a task.
func (*DB) AttachmentDirectory ¶ added in v0.3.31
AttachmentDirectory is durable storage owned by this database. Back up both. Worktrees hold execution copies and may be deleted independently.
func (*DB) BeginAgentTurn ¶ added in v0.3.31
BeginAgentTurn records that the agent started a turn (its UserPromptSubmit hook fired) and returns the counters as they now stand.
func (*DB) BeginRemoteRun ¶ added in v0.3.28
BeginRemoteRun fences signals from every earlier attempt of the same task.
func (*DB) CheckStatusConsistency ¶ added in v0.3.31
func (db *DB) CheckStatusConsistency() ([]StatusMismatch, error)
CheckStatusConsistency asserts the invariant this whole design rests on: for every task, the cached tasks.status equals the fold over its status events.
If this ever reports a mismatch, something wrote the status column outside SetTaskStatus — which is the bug class this package exists to make impossible. `ty debug status-consistency` runs it against a real DB.
func (*DB) ClearArchiveState ¶
ClearArchiveState clears the archive state for a task after unarchiving.
func (*DB) ClearTaskLogs ¶
ClearTaskLogs clears all logs for a task.
func (*DB) ClearTaskPaneIDs ¶ added in v0.3.18
ClearTaskPaneIDs clears only the tmux pane IDs for a task, leaving the window ID intact. Called when a task reaches a terminal state: its executor pane is torn down, which frees the pane ID for tmux to recycle onto a *different* task's pane. Leaving the stale ID in the DB is what let a finished task's pane pointer resolve to another live task's pane. Window IDs are not recycled as aggressively and are already staleness-checked on lookup, so we keep them.
func (*DB) ClearTaskPlacement ¶ added in v0.3.28
ClearTaskPlacement forgets a task's placement decision so the next spawn asks the resolver again. This is what `ty retry --replace` does, and it is the ONLY way a placed task moves hosts: a host that has gone away fails the task visibly rather than silently re-placing it, because a silent move orphans the worktree, branch and executor session the first attempt left behind.
func (*DB) ClearTaskSessionPlacement ¶ added in v0.3.30
ClearTaskSessionPlacement tears down a task's tmux placement in one statement: the window ID, both pane IDs, and the daemon session that owned the window. It deliberately leaves claude_session_id alone — that is what `--resume` needs to bring the conversation back, and dropping it turns a suspend into a discard. Used by both the idle-suspend sweep and `ty sessions suspend`, which must agree on what "suspended" means.
func (*DB) ClearTaskTmuxIDs ¶
ClearTaskTmuxIDs clears all tmux-related IDs for a task. This should be called before retrying/restarting a task to prevent stale references. Clears: tmux_window_id, claude_pane_id, shell_pane_id
func (*DB) ClearTaskWorktreePath ¶
ClearTaskWorktreePath clears just the worktree_path for a task. Used during async archive cleanup to avoid overwriting other fields.
func (*DB) ClearTaskWorktreeRefs ¶ added in v0.3.30
ClearTaskWorktreeRefs drops every reference a task holds to a directory on disk: the live worktree_path and the archive_worktree_path recorded when it was archived. Used when the recorded path turns out not to be a worktree at all (most commonly the project's own main checkout), where there is nothing to remove and nothing to restore.
Deliberately does NOT touch updated_at: the row is being corrected by a background sweep, not modified by the user, and bumping the timestamp makes a months-old task resurface at the top of every recently-touched view — which is exactly what the hourly re-archive of task 1201 did for five months.
func (*DB) ClearWorktreeSweepFailure ¶ added in v0.3.30
ClearWorktreeSweepFailure removes the un-sweepable marker. Called whenever a task gets a worktree set up again: the new worktree has never failed to archive, so the old verdict no longer applies.
func (*DB) CommitTaskPlacement ¶ added in v0.3.28
CommitTaskPlacement atomically publishes a carried branch and its destination, clears stale remote references, and fences the outgoing run's late signals.
func (*DB) CompleteAgentTurn ¶ added in v0.3.31
CompleteAgentTurn records that the agent finished the turn it was on (its Stop hook fired).
Completed is set to Started rather than incremented: a Stop with no turn behind it — an agent whose prompt predates turn tracking, or a hook that fired twice — must not push Completed past Started and make the next wait return on a turn that never began.
func (*DB) CompleteOnboarding ¶
CompleteOnboarding marks the onboarding as complete.
func (*DB) CoordinatorID ¶ added in v0.3.28
CoordinatorID is stable across daemon restarts and scoped to this database.
func (*DB) CountAttachments ¶
CountAttachments returns the number of attachments for a task.
func (*DB) CountRecentExecutorStarts ¶ added in v0.3.31
CountRecentExecutorStarts counts the executor launches logged for a task within the last window. It reads the shared database, so every process that can start an executor (each TUI, the web API) sees the same count; a counter held in one process let two TUIs relaunch one task 19 times between them without either tripping.
func (*DB) CountStatusEvents ¶ added in v0.3.31
CountStatusEvents returns the total number of rows in the status log. Used by `ty debug status-consistency` to say how much it actually checked — "0 mismatches" over an empty table is not the same claim as over a full one.
func (*DB) CountTasksByProject ¶
CountTasksByProject returns the number of tasks associated with a project name.
func (*DB) CountTasksByStatus ¶
CountTasksByStatus returns the count of tasks with a given status.
func (*DB) CreateProject ¶
CreateProject creates a new project.
func (*DB) CreateRoutineRun ¶ added in v0.3.7
CreateRoutineRun inserts a new run in the running state and returns its ID.
func (*DB) CreateTaskType ¶
CreateTaskType creates a new task type.
func (*DB) DeleteAttachment ¶
DeleteAttachment removes an attachment.
func (*DB) DeleteProject ¶
DeleteProject deletes a project.
func (*DB) DeleteRoutineRuns ¶ added in v0.3.7
DeleteRoutineRuns removes all recorded runs for a routine. Used when the routine itself is deleted so run history doesn't orphan.
func (*DB) DeleteSavedView ¶ added in v0.3.31
DeleteSavedView removes a view by name. Deleting a view that does not exist is not an error — the end state the caller asked for is already true.
func (*DB) DeleteTaskSettings ¶ added in v0.3.31
DeleteTaskSettings removes every per-task setting belonging to a task.
func (*DB) DeleteTaskType ¶
DeleteTaskType deletes a task type (only non-builtin types can be deleted).
func (*DB) FinishRoutineRun ¶ added in v0.3.7
FinishRoutineRun records a run's terminal state.
func (*DB) GetActiveTaskPorts ¶
GetActiveTaskPorts returns all ports currently in use by active (non-done, non-archived) tasks.
func (*DB) GetAllDependencies ¶
GetAllDependencies returns all dependencies for a given task (both blockers and blocked).
func (*DB) GetAllSettings ¶
GetAllSettings returns all settings as a map.
func (*DB) GetAppliedStatusEvents ¶ added in v0.3.31
func (db *DB) GetAppliedStatusEvents(taskID int64) ([]StatusEvent, error)
GetAppliedStatusEvents returns only the transitions that actually happened — the sequence FoldStatus projects over.
func (*DB) GetAttachment ¶
func (db *DB) GetAttachment(id int64) (*Attachment, error)
GetAttachment retrieves an attachment by ID.
func (*DB) GetBlockedBy ¶
GetBlockedBy returns all tasks that are blocked by the given task.
func (*DB) GetBlockers ¶
GetBlockers returns all tasks that block the given task.
func (*DB) GetConversationHistoryLogs ¶
GetConversationHistoryLogs retrieves only logs relevant for building conversation history. This is much more efficient than GetTaskLogs for the executor's prompt building, as it skips large output/tool log content that isn't needed for conversation context. Only fetches: continuation markers, questions, and user feedback.
func (*DB) GetDependency ¶
func (db *DB) GetDependency(blockerID, blockedID int64) (*Dependency, error)
GetDependency returns the dependency between two tasks, or nil if none exists.
func (*DB) GetExecutorUsageByProject ¶
GetExecutorUsageByProject returns a map of executor names to their usage counts for a project. This counts how many tasks have been created with each executor for the given project.
func (*DB) GetLastEffortForProject ¶ added in v0.3.3
GetLastEffortForProject returns the last used Claude effort override for a project ("" means the global/Claude default was used).
func (*DB) GetLastExecutorForProject ¶
GetLastExecutorForProject returns the last used executor for a project.
func (*DB) GetLastModelForProject ¶ added in v0.3.14
GetLastModelForProject returns the last used Claude model override for a project ("" means the global/Claude default was used).
func (*DB) GetLastPermissionForProject ¶ added in v0.3.3
GetLastPermissionForProject returns the last used permission mode for a project ("" means none recorded yet).
func (*DB) GetLastQuestion ¶
GetLastQuestion retrieves the most recent question log for a task.
func (*DB) GetLastTaskTypeForProject ¶
GetLastTaskTypeForProject returns the last used task type for a project.
func (*DB) GetLastUsedProject ¶
GetLastUsedProject returns the last used project name.
func (*DB) GetLatestLogPerTask ¶ added in v0.2.27
GetLatestLogPerTask returns the most recent log entry for each of the given task IDs. Returns a map of taskID -> latest TaskLog. Seek to the last indexed row per task instead of scanning its entire history with GROUP BY / MAX(id).
func (*DB) GetMostRecentlyCreatedTask ¶
GetMostRecentlyCreatedTask returns the task with the most recent created_at timestamp. This is used to get the last task's project for defaulting in new task forms.
func (*DB) GetNextQueuedTask ¶
GetNextQueuedTask returns the next task to process.
func (*DB) GetOpenBlockerCount ¶
GetOpenBlockerCount returns the number of incomplete blockers for a task.
func (*DB) GetPipelineArtifact ¶ added in v0.3.18
GetPipelineArtifact returns the content of a single artifact by (branch, name). A missing artifact returns an empty string and no error (same convenience as GetProjectContext) so callers can treat "not written yet" as empty.
func (*DB) GetProjectByName ¶
GetProjectByName returns a project by name or alias.
func (*DB) GetProjectByPath ¶
GetProjectByPath returns a project whose path matches the given directory. It checks if cwd equals or is a subdirectory of any project's path.
func (*DB) GetProjectContext ¶
GetProjectContext returns the auto-generated context for a project. This context is cached exploration results that can be reused across tasks.
func (*DB) GetQueuedTasks ¶
GetQueuedTasks returns all queued tasks (waiting to be processed).
func (*DB) GetRetryFeedback ¶
GetRetryFeedback returns the feedback from the most recent retry, or empty string if not a retry. Looks for "Feedback: ..." log entry after "--- Continuation ---" marker.
func (*DB) GetRoutineRun ¶ added in v0.3.7
func (db *DB) GetRoutineRun(id int64) (*RoutineRun, error)
GetRoutineRun fetches a single run by ID.
func (*DB) GetSavedView ¶ added in v0.3.31
GetSavedView looks a view up by name, case-insensitively. It returns (nil, nil) when no such view exists, so callers can tell "missing" from "broken" without inspecting the error.
func (*DB) GetSetting ¶
GetSetting returns a setting value.
func (*DB) GetStaleWorktreeTasks ¶
GetStaleWorktreeTasks returns done/archived tasks that have worktree paths set and were completed more than maxAge ago. These are candidates for cleanup.
Rows already marked un-sweepable (worktree_sweep_failed_at set, see MarkWorktreeSweepFailed) are excluded: their archive has already failed once and nothing about a retry would go differently, so the automatic sweep must not keep attempting them.
func (*DB) GetStaleWorktreeTasksIncludingFailed ¶ added in v0.3.30
GetStaleWorktreeTasksIncludingFailed is GetStaleWorktreeTasks plus the rows a prior sweep marked un-sweepable. Used by the on-demand `task worktrees cleanup` command: a human asking for a cleanup is entitled to a retry (and to see the error again), which is exactly what the unattended hourly sweep must not do.
func (*DB) GetStatusEvents ¶ added in v0.3.31
func (db *DB) GetStatusEvents(taskID int64) ([]StatusEvent, error)
GetStatusEvents returns a task's full transition history in append order, refusals included.
func (*DB) GetStepVerify ¶ added in v0.3.18
GetStepVerify returns the evidence-gate command for a step task, or "" when the step has no gate (the common case) — so callers treat "no row" as "no gate".
func (*DB) GetSweepableTrashedTasks ¶ added in v0.3.16
func (db *DB) GetSweepableTrashedTasks(maxAge time.Duration) ([]*TrashedTask, error)
GetSweepableTrashedTasks returns trashed tasks whose retention has expired — i.e. deleted_at is older than maxAge — so the daemon can hard-delete them.
func (*DB) GetTagsList ¶
GetTagsList returns all unique tags used across all tasks.
func (*DB) GetTaskBaseCommit ¶ added in v0.3.16
GetTaskBaseCommit returns the commit a task's worktree was created at, or "" if it was never recorded (a task from before the column existed).
func (*DB) GetTaskBaseDirty ¶ added in v0.3.16
GetTaskBaseDirty returns the paths dirty in the worktree when the task started.
func (*DB) GetTaskByWorktreePath ¶ added in v0.3.22
GetTaskByWorktreePath returns the task that owns a worktree directory, or nil.
Used when a branch turns out to be checked out somewhere: git names the worktree holding it, and the only way to decide whether that branch can be reclaimed is to ask what the owning task is doing. Trashed tasks are excluded — a deleted task's worktree is nobody's live work.
func (*DB) GetTaskLogCount ¶
GetTaskLogCount returns the number of logs for a task. This is a fast operation useful for checking if logs have changed.
func (*DB) GetTaskLogs ¶
GetTaskLogs retrieves logs for a task.
func (*DB) GetTaskLogsBefore ¶ added in v0.3.28
GetTaskLogsBefore returns a bounded history page, newest first. A zero beforeID selects the latest page.
func (*DB) GetTaskLogsSince ¶
GetTaskLogsSince retrieves logs after a given ID.
func (*DB) GetTaskLogsSinceLimit ¶ added in v0.3.28
GetTaskLogsSinceLimit bounds streaming catch-up without discarding older rows. A zero limit preserves the unbounded internal API for existing callers.
func (*DB) GetTaskPlacement ¶ added in v0.3.28
GetTaskPlacement returns the host a task ran on and why, both empty when the task ran locally or predates the placement hook.
func (*DB) GetTaskPlacementDecision ¶ added in v0.3.28
func (db *DB) GetTaskPlacementDecision(taskID int64) (TaskPlacement, error)
GetTaskPlacementDecision returns the placement already decided for a task.
func (*DB) GetTaskRemoteWorktree ¶ added in v0.3.28
GetTaskRemoteWorktree returns the remote worktree path and branch, both empty for a task that has never run remotely.
func (*DB) GetTaskType ¶
GetTaskType retrieves a task type by ID.
func (*DB) GetTaskTypeByName ¶
GetTaskTypeByName retrieves a task type by name.
func (*DB) HasContinuationMarker ¶
HasContinuationMarker checks if a task has any continuation markers. This is a fast EXISTS-style query to avoid loading logs just to check.
func (*DB) HasLogLineContaining ¶ added in v0.3.16
HasLogLineContaining reports whether the task has any log line whose content contains substr. Used to make a periodic sweep idempotent — e.g. logging a "parked for merge review" note exactly once for a terminal workflow step.
func (*DB) HasOpenTaskWithTitle ¶ added in v0.3.7
HasOpenTaskWithTitle reports whether a non-done, non-archived task with the exact title exists. Used to dedupe automatically created alert tasks.
func (*DB) HasQuestionLog ¶ added in v0.3.16
HasQuestionLog reports whether the task ever recorded a needs-input question (line_type "question"). The workflow "finished but couldn't signal" sweep uses this to avoid auto-completing a step that is genuinely waiting on a human answer.
func (*DB) HasSessionEnded ¶ added in v0.3.31
HasSessionEnded reports whether the task's CURRENT executor session has told us it exited, i.e. a SessionEndedLogPrefix line was written after the most recent session-start line. Comparing the two is what keeps a retry honest: a task relaunched after an earlier exit has a newer start line, so the old exit no longer counts.
This never says anything about how the session ended, only that it did — the caller still has to look at the task's status and its evidence to decide what that means.
func (*DB) HasSessionStarted ¶ added in v0.3.16
HasSessionStarted reports whether the task's executor session actually began. A task flips to 'processing' and then spends tens of seconds on worktree setup (clone, bundle, migrations) before any session exists — so this, not the absence of a tmux window, is how to tell "hasn't started yet" from "ran and finished". Conflating the two let the sweep complete steps before their agent ever launched.
func (*DB) IsFirstRun ¶
IsFirstRun returns true if this is the first time the app is being used. This is determined by checking if onboarding has been completed.
func (*DB) LatestRoutineRuns ¶ added in v0.3.7
func (db *DB) LatestRoutineRuns() (map[string]*RoutineRun, error)
LatestRoutineRuns returns the most recent run per routine, keyed by name.
func (*DB) ListAttachments ¶
func (db *DB) ListAttachments(taskID int64) ([]*Attachment, error)
ListAttachments retrieves all attachments for a task (without data for efficiency).
func (*DB) ListAttachmentsWithData ¶
func (db *DB) ListAttachmentsWithData(taskID int64) ([]*Attachment, error)
ListAttachmentsWithData retrieves all attachments for a task including data.
func (*DB) ListPipelineArtifacts ¶ added in v0.3.18
func (db *DB) ListPipelineArtifacts(branch string) ([]PipelineArtifact, error)
ListPipelineArtifacts returns every artifact for a branch, oldest first, so a phase can enumerate all upstream documents when no specific name is requested.
func (*DB) ListPlacementHosts ¶ added in v0.3.31
ListPlacementHosts returns the hosts tasks have actually been placed on, most used first. It is the source for the filter's `@host` autocomplete: the fleet is not configured anywhere central — a placement hook names whatever hosts it likes — so the tasks themselves are the only record of which machines exist.
Local runs (an empty placement_target) are not hosts and never appear here.
func (*DB) ListProjects ¶
ListProjects returns all projects, with "personal" always first.
func (*DB) ListRoutineRuns ¶ added in v0.3.7
func (db *DB) ListRoutineRuns(routine string, limit int) ([]*RoutineRun, error)
ListRoutineRuns returns the most recent runs for a routine, newest first.
func (*DB) ListSavedViews ¶ added in v0.3.31
ListSavedViews returns every saved view in display order.
func (*DB) ListTaskTypes ¶
ListTaskTypes returns all task types ordered by sort_order.
func (*DB) ListTasks ¶
func (db *DB) ListTasks(opts ListTasksOptions) ([]*Task, error)
ListTasks retrieves tasks with optional filters.
func (*DB) ListTrashedTasks ¶ added in v0.3.16
func (db *DB) ListTrashedTasks() ([]*TrashedTask, error)
ListTrashedTasks returns soft-deleted tasks, most recently trashed first.
func (*DB) ListWorktreeRefs ¶ added in v0.3.30
func (db *DB) ListWorktreeRefs() ([]WorktreeRef, error)
ListWorktreeRefs returns every non-deleted task that names a directory on disk through worktree_path or archive_worktree_path.
func (*DB) MarkTaskStarted ¶
MarkTaskStarted sets the started_at timestamp if not already set.
func (*DB) MarkWorktreeSweepFailed ¶ added in v0.3.30
MarkWorktreeSweepFailed records that the stale-worktree sweeper could not archive this task's worktree, excluding the row from future automatic sweeps. Like ClearTaskWorktreeRefs it leaves updated_at alone.
func (*DB) MigrateAttachmentFiles ¶ added in v0.3.31
MigrateAttachmentFiles moves legacy blobs only after their files are durable. It is restartable. SQLite reuses the freed pages; shrinking the database is a separate maintenance operation. Legacy blobs remain readable until migrated.
func (*DB) ProcessCompletedBlocker ¶
ProcessCompletedBlocker checks tasks blocked by the completed task and updates their status if they become unblocked. Returns the list of tasks that were unblocked.
func (*DB) ReadSchemaVersion ¶ added in v0.3.31
ReadSchemaVersion returns the schema version recorded in the file, and whether one was recorded at all. A database last opened by a build from before the stamp existed reports (0, false) — old, but not corrupt.
func (*DB) RecordHostHealth ¶ added in v0.3.28
func (*DB) RecoverStaleTmuxRefs ¶
func (db *DB) RecoverStaleTmuxRefs(activeSessions map[string]bool, validWindowIDs map[string]bool) (int, int, error)
RecoverStaleTmuxRefs clears stale daemon_session and tmux_window_id references from tasks. Called automatically on daemon startup to recover from crashes. Returns (staleDaemonCount, staleWindowCount) of cleaned references.
Only LOCAL references are swept: see placedElsewhere.
func (*DB) RemoteHostHealth ¶ added in v0.3.28
func (db *DB) RemoteHostHealth(host string) (HostHealth, error)
func (*DB) RemoteSignal ¶ added in v0.3.28
RemoteSignal returns the latest persisted event for the current host and run. It is deliberately not deleted: a crash before finalization must replay it.
func (*DB) RemoveDependency ¶
RemoveDependency removes a dependency between two tasks.
func (*DB) RequeueReadyTasks ¶ added in v0.3.16
RequeueReadyTasks is the eventually-consistent safety net for ProcessCompletedBlocker. That runs once, best-effort, the instant a blocker completes; a single dropped write (SQLITE_BUSY, a crash) would orphan the dependent in 'blocked' forever, stalling a workflow. This sweep re-queues any task still waiting in the DAG — blocked, never started — whose blockers have all completed. Idempotent: it only touches tasks that are genuinely ready. Returns the tasks it moved.
func (*DB) RestartIdleClock ¶ added in v0.3.31
RestartIdleClock stamps a blocked task's completed_at with now. The idle sweep measures a parked task's idle time from completed_at, so a session the user resumes by hand, without typing into it, would otherwise be suspended again on the sweep's next pass, a minute later. Only a task that actually ran (completed_at already set) is touched; a staged pipeline step stays unstamped.
This refreshes an existing stamp and never writes status, so it is not a way around the status log: a task it touches is already blocked and has already completed a turn.
func (*DB) RestoreTask ¶ added in v0.3.16
RestoreTask clears the trashed flag, returning a soft-deleted task to the board with its original status, worktree and session intact.
func (*DB) RetryTask ¶
RetryTask clears logs, appends feedback to body, and re-queues a task. Also clears stale tmux window/pane IDs to prevent duplicate window issues.
func (*DB) SaveArchiveState ¶
func (db *DB) SaveArchiveState(taskID int64, archiveRef, archiveCommit, worktreePath, branchName string) error
SaveArchiveState saves the archive state for a task. This stores the git ref, commit hash, worktree path, and branch name that were active at the time of archiving.
func (*DB) SaveRemoteEvent ¶ added in v0.3.28
func (db *DB) SaveRemoteEvent(ev RemoteEvent) error
SaveRemoteEvent deduplicates delivery and discards signals from old runs or other hosts. Success is permission to acknowledge the remote spool file.
func (*DB) SaveView ¶ added in v0.3.31
SaveView creates or updates a view by name and returns the stored row. Saving over an existing name replaces its query, which is what "save current filter as <name>" should do when the name is already taken.
func (*DB) SearchTasks ¶
SearchTasks searches for tasks by query string across title, project, ID, and PR number. This is used by the command palette to search all tasks, not just the preloaded ones.
func (*DB) SetAutoQueue ¶
SetAutoQueue updates the auto_queue flag for a dependency.
func (*DB) SetEventEmitter ¶
func (db *DB) SetEventEmitter(emitter EventEmitter)
SetEventEmitter sets the event emitter for this database. This is called by the executor to enable event emission.
func (*DB) SetLastEffortForProject ¶ added in v0.3.3
SetLastEffortForProject saves the last used Claude effort override for a project so the next task in it defaults to the same choice.
func (*DB) SetLastExecutorForProject ¶
SetLastExecutorForProject saves the last used executor for a project.
func (*DB) SetLastModelForProject ¶ added in v0.3.14
SetLastModelForProject saves the last used Claude model override for a project so the next task in it defaults to the same choice.
func (*DB) SetLastPermissionForProject ¶ added in v0.3.3
SetLastPermissionForProject saves the last used permission mode for a project so the next task in it defaults to the same choice.
func (*DB) SetLastTaskTypeForProject ¶
SetLastTaskTypeForProject saves the last used task type for a project.
func (*DB) SetLastUsedProject ¶
SetLastUsedProject saves the last used project name.
func (*DB) SetPipelineArtifact ¶ added in v0.3.18
SetPipelineArtifact upserts an artifact document keyed by (branch, name). A second write to the same key overwrites the previous content (and bumps updated_at), mirroring SetProjectContext's overwrite semantics.
func (*DB) SetProjectContext ¶
SetProjectContext saves auto-generated context for a project. This overwrites any existing context.
func (*DB) SetRoutineRunLogPath ¶ added in v0.3.7
SetRoutineRunLogPath records where the run's full log lives.
func (*DB) SetSetting ¶
SetSetting sets a setting value.
func (*DB) SetStepVerify ¶ added in v0.3.18
SetStepVerify records the opt-in evidence-gate command for a workflow step, keyed by the step's task id. It is written once at workflow-build time (see pipeline.Create) for steps whose YAML sets `verify:`. A second write overwrites.
func (*DB) SetTaskBaseCommit ¶ added in v0.3.16
SetTaskBaseCommit records the commit a task's worktree was created at. Written once, right after the worktree exists and before any agent session starts.
func (*DB) SetTaskBaseDirty ¶ added in v0.3.16
SetTaskBaseDirty records the paths already dirty in the task's worktree when it started (newline-separated). Worktree init regularly rewrites tracked files, so this is the baseline that "did the step leave uncommitted work?" is measured against.
func (*DB) SetTaskPlacement ¶ added in v0.3.28
SetTaskPlacement records where a task ran: the host the task.placement hook named and the reason it gave. Written once, just before the executor spawns.
An empty target is a real answer, not a missing one — it means the resolver chose this machine — so it is stored alongside its reason rather than skipped. Tasks that were never consulted (no placement plugin installed) keep both fields empty and read exactly as they always have.
func (*DB) SetTaskPlacementDecision ¶ added in v0.3.28
SetTaskPlacementDecision records a placement decision, stamping the time it was made. Called once, at the first spawn; every later spawn reads it back with GetTaskPlacementDecision instead of asking the resolver again.
func (*DB) SetTaskRemoteWorktree ¶ added in v0.3.28
SetTaskRemoteWorktree records the isolated worktree a remotely placed task was given on its host, so the TUI can say where the task actually is and a retry can find the same directory.
func (*DB) SetTaskStatus ¶ added in v0.3.31
func (db *DB) SetTaskStatus(id int64, to string, actor Actor, reason string, evidence Evidence) error
SetTaskStatus is the ONE path that may change a task's status.
actor and reason are positional and required precisely so a future caller cannot take the old shortcut: there is no signature that compiles without answering "who" and "why". evidence answers "on what grounds" and is checked by the gates below — pass NoEvidence for an ordinary transition and mean it.
It appends the transition and updates the cached row in one transaction, so the two can never diverge. Gates run here rather than in callers, so the CLI, the web API, the MCP tool and the TUI all get them without each remembering to ask.
func (*DB) SoftDeleteTask ¶ added in v0.3.16
SoftDeleteTask marks a task as trashed (deleted_at = now) instead of removing it. The row, worktree and Claude transcript all stay intact and recoverable via RestoreTask until the daemon trash sweep hard-deletes it after the retention window (see Executor.sweepTrashedTasks). Trashed tasks are hidden from the board and every default query. No-op if the task is already trashed.
func (*DB) UpdateProject ¶
UpdateProject updates a project.
func (*DB) UpdateTask ¶
UpdateTask updates a task's editable fields.
It deliberately does NOT write status. Status is append-only: it changes only through SetTaskStatus, which records who and why. This method was the second back door into the status column — a caller could load a task, assign t.Status and save, producing a status change with no transition behind it and a cached row the log could not explain. Assigning t.Status and calling this is now a loud error rather than a silent bypass.
func (*DB) UpdateTaskClaudeConfigDir ¶ added in v0.3.28
UpdateTaskClaudeConfigDir sets the per-task CLAUDE_CONFIG_DIR override, which is how a task is pinned to one Claude profile (account). Writing it as its own column update — rather than through UpdateTask — matters at spawn time: the routing decision is made from a task struct the daemon has been holding, and a full-row write would stomp any field another surface (the TUI, a hook) changed in the meantime.
func (*DB) UpdateTaskClaudeSessionID ¶
UpdateTaskClaudeSessionID updates only the Claude session ID for a task.
func (*DB) UpdateTaskDaemonSession ¶
UpdateTaskDaemonSession updates the tmux daemon session name for a task. This is used to track which daemon session owns the task's tmux window, so we can properly kill the Claude process when the task completes.
func (*DB) UpdateTaskDangerousMode ¶
UpdateTaskDangerousMode updates the dangerous_mode flag for a task, keeping the authoritative permission_mode column in sync. Toggling dangerous off resets the task to the default (prompt) mode.
func (*DB) UpdateTaskLastAccessedAt ¶
UpdateTaskLastAccessedAt updates the last_accessed_at timestamp for a task. This is used to track when a task was last accessed/opened in the UI, enabling the command palette to show recently visited tasks first.
func (*DB) UpdateTaskPRInfo ¶
UpdateTaskPRInfo updates only the PR-related fields for a task. This is used to persist PR state from GitHub API responses without touching other fields.
When the cached PR JSON actually changes, it records a board-change event so the HTTP API's SSE stream re-pushes the board — this is how a live PR badge reaches the web/desktop without a restart. We compare against the stored value first so idle refreshes (state unchanged) don't spam the change feed every tick.
func (*DB) UpdateTaskPaneIDs ¶
UpdateTaskPaneIDs updates the tmux pane IDs for a task. This is used to track the unique pane IDs (e.g., "%1234") for reliable pane identification when joining/breaking panes between the daemon and the TUI.
func (*DB) UpdateTaskPermissionMode ¶ added in v0.2.40
UpdateTaskPermissionMode updates the permission_mode for a task and keeps the legacy dangerous_mode boolean consistent.
func (*DB) UpdateTaskPinned ¶
UpdateTaskPinned updates only the pinned flag for a task.
func (*DB) UpdateTaskStartedAt ¶
UpdateTaskStartedAt updates the started_at timestamp for a task. This is primarily used for testing.
func (*DB) UpdateTaskSummary ¶
UpdateTaskSummary updates the task summary and distillation timestamp.
func (*DB) UpdateTaskType ¶
UpdateTaskType updates a task type.
func (*DB) UpdateTaskWindowID ¶
UpdateTaskWindowID updates the tmux window ID for a task. This is used to track the unique window ID (e.g., "@1234") for reliable window targeting.
func (*DB) ValidateTaskModel ¶ added in v0.3.26
ValidateTaskModel checks a task's model override against the executor that will run it, skipping the check when the task is routed at a non-stock backend. This is the entry point every write path should use — it resolves the escape hatch (per-task config dir or env, the project's config dir, an ambient ANTHROPIC_BASE_URL) that a bare ValidateModel call cannot see.
func (*DB) WaitForAgentReply ¶ added in v0.3.31
func (db *DB) WaitForAgentReply(ctx context.Context, taskID int64, since AgentTurn, timeout time.Duration) (AgentTurn, error)
WaitForAgentReply blocks until a turn that began after since has finished, and returns the counters at that moment. The waiting lives here so no caller has to write its own polling loop, and so there is one definition of what counts as "the agent answered me".
since is the counters read BEFORE the prompt was sent. Returns ErrReplyTimeout if nothing qualifies within timeout, or ctx.Err() if the caller gives up first.
type Dependency ¶
type Dependency struct {
ID int64 `json:"id"`
BlockerID int64 `json:"blocker_id"`
BlockedID int64 `json:"blocked_id"`
AutoQueue bool `json:"auto_queue"` // If true, auto-queue blocked task when unblocked
CreatedAt time.Time `json:"created_at"`
}
Dependency represents a blocking relationship between two tasks. The blocker task must be completed before the blocked task can proceed.
type EventEmitter ¶
type EventEmitter interface {
EmitTaskCreated(task *Task)
EmitTaskUpdated(task *Task, changes map[string]interface{})
EmitTaskDeleted(taskID int64, title string)
EmitTaskPinned(task *Task)
EmitTaskUnpinned(task *Task)
EmitTaskBlocked(task *Task, reason string)
EmitTaskCompleted(task *Task)
}
EventEmitter is an interface for emitting task events. This allows the DB to emit events without depending on the events package.
type Evidence ¶ added in v0.3.31
type Evidence struct {
// Observed is what the caller saw, in its own words. "the agent called
// taskyou_complete", "HEAD is 3 commits past base and pushed".
Observed string `json:"observed,omitempty"`
// Human records that a person asked for this, and how. A human closing a
// backlog item is legitimate even with nothing to point at; automation
// closing one is the bug.
Human string `json:"human,omitempty"`
// BaseCommit / HeadCommit are the step's starting commit and where it ended
// up. Different values are the only proof a step produced work.
BaseCommit string `json:"base_commit,omitempty"`
HeadCommit string `json:"head_commit,omitempty"`
// PRNumber / PRState carry a pull request's identity and observed state.
// PRState of MERGED or CLOSED is what lets a done-write past the open-PR gate.
PRNumber int `json:"pr_number,omitempty"`
PRState string `json:"pr_state,omitempty"`
// PRDisowned is the other way past the open-PR gate: the caller says, in
// its own words, why the PR recorded against this task is not this task's
// work. A workflow's steps share one branch, so every step matches the
// terminal step's PR; without this the gate would stall every DAG at step
// one. It is a positive claim a caller has to make and defend in the log,
// not an absence the gate can be talked into.
PRDisowned string `json:"pr_disowned,omitempty"`
// Gate names the completion gate that was run and passed (e.g. a step's
// `verify:` command).
Gate string `json:"gate,omitempty"`
}
Evidence is the positive fact a transition rests on.
The rule the sweep broke was "never infer completion from absence": no tmux window and no diff against origin look exactly like a step that has not started yet. Evidence is how a caller says what it actually OBSERVED, and a transition into a terminal state is refused without it — which is precisely the thing a caller reasoning from absence cannot produce.
func ByHuman ¶ added in v0.3.31
ByHuman builds Evidence recording that a person asked for this transition.
func (Evidence) DisownSharedBranchPR ¶ added in v0.3.31
DisownSharedBranchPR marks evidence as belonging to a workflow step that carries a PR number it did not open.
Every step of a workflow shares one branch, so a PR lookup on any of them finds the terminal step's PR. A non-terminal step completing is therefore a legitimate done-write with an open PR on the row — the one case the open-PR gate must let through. It is let through because the caller SAYS it is not its PR and the log keeps that claim, not because the gate inferred anything. A no-op when the task has no PR number.
type HostHealth ¶ added in v0.3.28
type HostHealth struct {
State string `json:"state"`
LastSeen string `json:"last_seen,omitempty"`
Problem string `json:"problem,omitempty"`
}
HostHealth keeps transport health separate from task state and is shared by the daemon, HTTP server and TUI through the coordinator database.
type ListTasksOptions ¶
type ListTasksOptions struct {
Status string
Type string
Project string
Tag string // Filter to tasks carrying this exact tag (delimiter-safe; "gm:cortex" does not match "gm:cortex-2")
Limit int // Zero defaults to 100; negative means no limit.
Offset int
IncludeClosed bool // Include closed tasks even when Status is empty
IncludeTrashed bool // Include soft-deleted (trashed) tasks; by default they are hidden
OrderByRecency bool // Sort purely by recency, ignoring pinned-first ordering
OpenPROnly bool // Only tasks whose stored PR is still open or draft (not merged/closed)
}
ListTasksOptions defines options for listing tasks.
type LocalTime ¶
LocalTime wraps time.Time and converts from UTC to local timezone when scanning.
type OpenOptions ¶ added in v0.3.31
type OpenOptions struct {
// BusyTimeout is how long to wait on a locked database. Zero means
// DefaultBusyTimeout.
BusyTimeout time.Duration
// SkipMigrate opens the database without running migrations. For short-lived
// processes that only read and write rows in a schema ty already created —
// the agent-facing hooks — where a migration is both unnecessary and, against
// a database somebody else has locked, several seconds of the agent's time.
SkipMigrate bool
}
OpenOptions tunes Open for callers that cannot take its defaults.
type PipelineArtifact ¶ added in v0.3.18
type PipelineArtifact struct {
Branch string
Name string
Content string
CreatedAt time.Time
UpdatedAt time.Time
}
PipelineArtifact is one inter-phase document produced by a workflow step and read by a later step on the same shared branch. It is the TaskYou-native hand-off store: document phases (research-questions, research, design, ...) write their output here instead of committing docs to git.
type Project ¶
type Project struct {
ID int64
Name string
Path string
Aliases string // comma-separated
Instructions string // project-specific instructions for AI
Actions []ProjectAction // actions triggered on task events (stored as JSON)
Color string // hex color for display (e.g., "#61AFEF")
ClaudeConfigDir string // override CLAUDE_CONFIG_DIR for this project
UseWorktrees bool // whether to use git worktrees for task isolation (default true)
// DefaultPermissionMode is the permission mode new tasks in this project
// inherit ("default", "auto", "dangerous"). Empty means use the global default.
DefaultPermissionMode string
CreatedAt LocalTime
}
Project represents a configured project.
func (*Project) EffectiveDefaultPermissionMode ¶ added in v0.2.40
EffectiveDefaultPermissionMode returns the permission mode new tasks in this project should inherit, falling back to the global default when unset.
func (*Project) GetAction ¶
func (p *Project) GetAction(trigger string) *ProjectAction
GetAction returns the action for a given trigger, or nil if not found.
func (*Project) UsesWorktrees ¶
UsesWorktrees returns whether this project uses git worktrees for task isolation. Defaults to true for backward compatibility.
type ProjectAction ¶
type ProjectAction struct {
Trigger string `json:"trigger"` // "on_create", "on_status:queued", etc.
Instructions string `json:"instructions"` // prompt/instructions for this action
}
ProjectAction defines an action that runs on tasks for a project.
type RefusedError ¶ added in v0.3.31
RefusedError is returned when a gate rejects a transition. Callers that want to render the refusal (the TUI notice, the MCP tool result, an HTTP 409) check for it with IsRefused.
func (*RefusedError) Error ¶ added in v0.3.31
func (e *RefusedError) Error() string
type RemoteEvent ¶ added in v0.3.28
type RemoteEvent struct {
ID string
TaskID int64
RunID string
Host string
Kind string
Detail string
}
RemoteEvent is a durable inbox entry. The sender retains it until this DB accepts it; reads are repeatable until the task's next run replaces its fence.
type RoutineRun ¶ added in v0.3.7
type RoutineRun struct {
ID int64 `json:"id"`
Routine string `json:"routine"`
Status string `json:"status"` // running, ok, failed
ExitCode int `json:"exit_code"`
Output string `json:"output"` // tail of combined output; full log on disk
LogPath string `json:"log_path"`
StartedAt LocalTime `json:"started_at"`
FinishedAt *LocalTime `json:"finished_at,omitempty"`
}
RoutineRun is one recorded execution of a routine (see internal/routine). Routines themselves live on disk; only run history lives in the database.
type SavedView ¶ added in v0.3.31
type SavedView struct {
ID int64 `json:"id"`
Name string `json:"name"`
Query string `json:"query"`
SortOrder int `json:"sort_order"`
CreatedAt LocalTime `json:"created_at"`
UpdatedAt LocalTime `json:"updated_at"`
}
SavedView is a named filter query — "the tasks I care about right now".
A view is nothing but its query string, in the grammar internal/taskfilter parses ("status:in-progress status:blocked", "is:pinned", "[offerlab]"). That keeps every surface honest: the TUI, the CLI and the HTTP API all resolve a view name to the same string and run the same matcher over it, so a view cannot mean one thing on the board and another in a script.
type StatusEvent ¶ added in v0.3.31
type StatusEvent struct {
ID int64
TaskID int64
From string
To string
Actor Actor
Reason string
Evidence Evidence
Outcome string
Gate string
CreatedAt LocalTime
}
StatusEvent is one appended fact about a task's status.
type StatusMismatch ¶ added in v0.3.31
StatusMismatch is one task whose cached status disagrees with its log.
func (StatusMismatch) String ¶ added in v0.3.31
func (m StatusMismatch) String() string
type Task ¶
type Task struct {
ID int64
Title string
Body string
Status string
Type string
Project string
Executor string // Task executor: "claude" (default), "codex", "gemini", "grok", "cursor"
EffortLevel string // Per-task Claude effort override ("" = use global/Claude default; otherwise low/medium/high/xhigh/max)
Model string // Per-task Claude model override ("" = use global/Claude default; otherwise an alias like opus/sonnet/haiku or a full model name)
ClaudeConfigDir string // Per-task CLAUDE_CONFIG_DIR override ("" = use the project's/default config dir). Lets a single step route through a different Claude config (e.g. an ollama-backed one) without changing the project.
EnvJSON string // Per-task env overrides for the spawned Claude, stored as a JSON object (e.g. {"ANTHROPIC_BASE_URL":"http://127.0.0.1:11434","ANTHROPIC_AUTH_TOKEN":"ollama"}). Injected as a process-env prefix on the claude command so a step can route through a non-Anthropic proxy (ollama) WITHOUT swapping CLAUDE_CONFIG_DIR — the default config dir (plugins, MCP, trusted worktrees) stays intact and process env wins over stored creds. "" = no overrides.
WorktreePath string
BranchName string
Port int // Unique port for running the application in this task's worktree
ClaudeSessionID string // Claude session ID for resuming conversations
DaemonSession string // tmux daemon session name (e.g., "task-daemon-12345")
TmuxWindowID string // tmux window ID (e.g., "@1234") for unique window identification
ClaudePaneID string // tmux pane ID (e.g., "%1234") for the Claude/executor pane
ShellPaneID string // tmux pane ID (e.g., "%1235") for the shell pane
PRURL string // Pull request URL (if associated with a PR)
PRNumber int // Pull request number (if associated with a PR)
PRInfoJSON string // Cached PR state as JSON (state, checks, mergeable, etc.)
DangerousMode bool // Whether task is running in dangerous mode (--dangerously-skip-permissions). Kept for backward compat; PermissionMode is authoritative.
PermissionMode string // Permission mode for execution: "default" (prompt), "accept-edits" (Claude's acceptEdits — auto-accept file edits, still prompts for risky actions), "auto" (Claude Code's auto mode — classifier auto-approves safe actions, blocks risky ones), "dangerous" (skip permissions). Empty falls back to DangerousMode/global default.
RemoteControl bool // Whether to launch claude with --remote-control (interactive, remote-drivable)
Pinned bool // Whether the task is pinned to the top of its column
Tags string // Comma-separated tags for categorization (e.g., "customer-support,email,influence-kit")
SourceBranch string // Existing branch to checkout for worktree (e.g., "fix/ui-overflow") instead of creating new branch
Summary string // Distilled summary of what was accomplished (for search and context)
CreatedAt LocalTime
UpdatedAt LocalTime
StartedAt *LocalTime
CompletedAt *LocalTime
// Distillation tracking
LastDistilledAt *LocalTime // When task was last distilled for learnings
// UI tracking
LastAccessedAt *LocalTime // When task was last accessed/opened in the UI
// Archive state for preserving worktree state when archiving
ArchiveRef string // Git ref storing stashed changes (e.g., "refs/task-archive/123")
ArchiveCommit string // Commit hash at time of archiving
ArchiveWorktreePath string // Original worktree path before archiving
ArchiveBranchName string // Original branch name before archiving
// Where this task ran, as decided by the task.placement hook. An empty target
// means this machine, which is every task unless a placement plugin is
// installed. Recorded so a result can be traced back to the machine that
// produced it: once tasks run on four hosts, a suite that only fails on one of
// them is indistinguishable from a real bug without it.
PlacementTarget string // Host the task ran on ("" = local)
PlacementReason string // The resolver's explanation for that choice
}
Task represents a task in the database.
func (*Task) EffectivePermissionMode ¶ added in v0.2.40
EffectivePermissionMode resolves the permission mode a task should run with, falling back to the legacy DangerousMode boolean and finally the default.
func (*Task) EnvMap ¶ added in v0.3.16
EnvMap parses a task's EnvJSON override blob into a map. A malformed or empty blob yields an empty (never nil) map, so callers can range over it without a nil check. This is the read side of the per-step env feature: the pipeline stores a step's `env:` map as JSON in EnvJSON, and the executor renders it into a process-env prefix on the claude command.
func (*Task) HasArchiveState ¶
HasArchiveState returns true if the task has saved archive state.
func (*Task) IsAcceptEdits ¶ added in v0.3.1
IsAcceptEdits reports whether the task runs in accept-edits (acceptEdits) mode.
func (*Task) IsAutoPermission ¶ added in v0.2.40
IsAutoPermission reports whether the task runs in Claude Code's auto mode.
func (*Task) IsDangerous ¶ added in v0.2.40
IsDangerous reports whether the task runs with permissions fully bypassed.
type TaskLog ¶
type TaskLog struct {
ID int64
TaskID int64
LineType string // "output", "tool", "error", "system"
Content string
CreatedAt LocalTime
}
TaskLog represents a log entry for a task.
type TaskPlacement ¶ added in v0.3.28
type TaskPlacement struct {
Target string // Host the task runs on ("" = this machine)
Reason string // The resolver's explanation
WorkDir string // The checkout on that host ("" for local)
Decided bool // Whether placement has been decided at all
}
TaskPlacement is a task's recorded placement decision: where it runs, why, and the checkout it was given on that host.
Decided is the state placement_target alone cannot express. An empty target is a real answer meaning "run here", so without a separate marker "the resolver chose local" and "the resolver was never asked" read identically — and a task that had been deliberately placed locally would be re-asked on every retry.
type TaskType ¶
type TaskType struct {
ID int64
Name string // e.g., "code", "writing", "thinking"
Label string // Display label
Instructions string // Prompt template for this type
SortOrder int // For UI ordering
IsBuiltin bool // Protect default types from deletion
CreatedAt LocalTime
}
TaskType represents a configurable task type with its prompt instructions.
type TrashedTask ¶ added in v0.3.16
type TrashedTask struct {
ID int64
Title string
Project string
WorktreePath string
DeletedAt time.Time
}
TrashedTask is a lightweight view of a soft-deleted task for the trash listing and the sweep — it deliberately avoids the full Task scan so new columns there never need threading through here.
type WorktreeRef ¶ added in v0.3.30
type WorktreeRef struct {
TaskID int64
Title string
Project string
Status string
WorktreePath string
ArchivePath string
}
WorktreeRef is one task row's claim on a directory: the live worktree and the path an archive would be restored to. Used by the worktree audit, which needs every row that names a directory regardless of status.