db

package
v0.3.28 Latest Latest
Warning

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

Go to latest
Published: Sep 7, 2026 License: MIT Imports: 15 Imported by: 0

Documentation

Overview

Package db provides SQLite database operations.

Index

Constants

View Source
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.

View Source
const (
	RoutineRunStatusRunning = "running"
	RoutineRunStatusOK      = "ok"
	RoutineRunStatusFailed  = "failed"
)

Routine run statuses.

View Source
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

View Source
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.

View Source
const (
	TypeCode     = "code"
	TypeWriting  = "writing"
	TypeThinking = "thinking"
)

Task types (default values, actual types are stored in task_types table)

View Source
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

View Source
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.

View Source
const (
	PortRangeStart = 3100 // First port in the allocation range
	PortRangeEnd   = 4099 // Last port in the allocation range (1000 ports total)
)

Port allocation constants

Variables

View Source
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.

View Source
var ErrProjectNotFound = fmt.Errorf("project not found")

ErrProjectNotFound is returned when a task is created with a non-existent project.

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 DefaultPath

func DefaultPath() string

DefaultPath returns the default database path.

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

func ExecutorSupportsModel(executor string) bool

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

func ExpandHomePath(path string) string

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 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

func IsInProgress(status string) bool

IsInProgress returns true if the task is actively being worked on.

func IsKnownExecutor added in v0.3.24

func IsKnownExecutor(name string) bool

IsKnownExecutor reports whether name is a built-in executor slug.

func IsValidEffortLevel added in v0.2.40

func IsValidEffortLevel(s string) bool

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

func IsValidModel(s string) bool

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

func ModelBackendIsCustom(configDir string, env map[string]string) bool

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

func ModelsForExecutor(executor string) []string

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

func NextPermissionMode(mode string) string

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

func NormalizePermissionMode(mode string) string

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 PermissionModeLabel added in v0.3.2

func PermissionModeLabel(mode string) string

PermissionModeLabel returns a short human-facing label for a permission mode.

func ValidateModel added in v0.3.26

func ValidateModel(executor, model string) error

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.

Types

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

type DB struct {
	*sql.DB
	// contains filtered or unexported fields
}

DB wraps the SQLite database connection.

func Open

func Open(path string) (*DB, error)

Open opens or creates a SQLite database at the given path.

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

func (db *DB) AddDependency(blockerID, blockedID int64, autoQueue bool) error

AddDependency creates a dependency where blockerID blocks blockedID. Returns an error if the dependency already exists or would create a cycle.

func (*DB) AllocatePort

func (db *DB) AllocatePort(taskID int64) (int, error)

AllocatePort assigns an available port to a task. Returns the allocated port, or an error if no ports are available.

func (*DB) AppendTaskLog

func (db *DB) AppendTaskLog(taskID int64, lineType, content string) error

AppendTaskLog appends a log entry to a task.

func (*DB) BeginRemoteRun added in v0.3.28

func (db *DB) BeginRemoteRun(taskID int64, host string) (string, error)

BeginRemoteRun fences signals from every earlier attempt of the same task.

func (*DB) ClearArchiveState

func (db *DB) ClearArchiveState(taskID int64) error

ClearArchiveState clears the archive state for a task after unarchiving.

func (*DB) ClearTaskLogs

func (db *DB) ClearTaskLogs(taskID int64) error

ClearTaskLogs clears all logs for a task.

func (*DB) ClearTaskPaneIDs added in v0.3.18

func (db *DB) ClearTaskPaneIDs(taskID int64) error

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

func (db *DB) ClearTaskPlacement(taskID int64) error

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) ClearTaskTmuxIDs

func (db *DB) ClearTaskTmuxIDs(taskID int64) error

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

func (db *DB) ClearTaskWorktreePath(taskID int64) error

ClearTaskWorktreePath clears just the worktree_path for a task. Used during async archive cleanup to avoid overwriting other fields.

func (*DB) CommitTaskPlacement added in v0.3.28

func (db *DB) CommitTaskPlacement(taskID int64, target, reason, workDir, branch string) error

CommitTaskPlacement atomically publishes a carried branch and its destination, clears stale remote references, and fences the outgoing run's late signals.

func (*DB) CompleteOnboarding

func (db *DB) CompleteOnboarding() error

CompleteOnboarding marks the onboarding as complete.

func (*DB) CoordinatorID added in v0.3.28

func (db *DB) CoordinatorID() (string, error)

CoordinatorID is stable across daemon restarts and scoped to this database.

func (*DB) CountAttachments

func (db *DB) CountAttachments(taskID int64) (int, error)

CountAttachments returns the number of attachments for a task.

func (*DB) CountTasksByProject

func (db *DB) CountTasksByProject(projectName string) (int, error)

CountTasksByProject returns the number of tasks associated with a project name.

func (*DB) CountTasksByStatus

func (db *DB) CountTasksByStatus(status string) (int, error)

CountTasksByStatus returns the count of tasks with a given status.

func (*DB) CreateProject

func (db *DB) CreateProject(p *Project) error

CreateProject creates a new project.

func (*DB) CreateRoutineRun added in v0.3.7

func (db *DB) CreateRoutineRun(routine string) (int64, error)

CreateRoutineRun inserts a new run in the running state and returns its ID.

func (*DB) CreateTask

func (db *DB) CreateTask(t *Task) error

CreateTask creates a new task.

func (*DB) CreateTaskType

func (db *DB) CreateTaskType(t *TaskType) error

CreateTaskType creates a new task type.

func (*DB) DeleteAttachment

func (db *DB) DeleteAttachment(id int64) error

DeleteAttachment removes an attachment.

func (*DB) DeleteProject

func (db *DB) DeleteProject(id int64) error

DeleteProject deletes a project.

func (*DB) DeleteRoutineRuns added in v0.3.7

func (db *DB) DeleteRoutineRuns(routine string) error

DeleteRoutineRuns removes all recorded runs for a routine. Used when the routine itself is deleted so run history doesn't orphan.

func (*DB) DeleteTask

func (db *DB) DeleteTask(id int64) error

DeleteTask deletes a task.

func (*DB) DeleteTaskType

func (db *DB) DeleteTaskType(id int64) error

DeleteTaskType deletes a task type (only non-builtin types can be deleted).

func (*DB) FinishRoutineRun added in v0.3.7

func (db *DB) FinishRoutineRun(id int64, status string, exitCode int, output string) error

FinishRoutineRun records a run's terminal state.

func (*DB) GetActiveTaskPorts

func (db *DB) GetActiveTaskPorts() (map[int]bool, error)

GetActiveTaskPorts returns all ports currently in use by active (non-done, non-archived) tasks.

func (*DB) GetAllDependencies

func (db *DB) GetAllDependencies(taskID int64) (blockers []*Task, blockedBy []*Task, err error)

GetAllDependencies returns all dependencies for a given task (both blockers and blocked).

func (*DB) GetAllSettings

func (db *DB) GetAllSettings() (map[string]string, error)

GetAllSettings returns all settings as a map.

func (*DB) GetAttachment

func (db *DB) GetAttachment(id int64) (*Attachment, error)

GetAttachment retrieves an attachment by ID.

func (*DB) GetBlockedBy

func (db *DB) GetBlockedBy(taskID int64) ([]*Task, error)

GetBlockedBy returns all tasks that are blocked by the given task.

func (*DB) GetBlockers

func (db *DB) GetBlockers(taskID int64) ([]*Task, error)

GetBlockers returns all tasks that block the given task.

func (*DB) GetConversationHistoryLogs

func (db *DB) GetConversationHistoryLogs(taskID int64) ([]*TaskLog, error)

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

func (db *DB) GetExecutorUsageByProject(project string) (map[string]int, error)

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

func (db *DB) GetLastEffortForProject(project string) (string, error)

GetLastEffortForProject returns the last used Claude effort override for a project ("" means the global/Claude default was used).

func (*DB) GetLastExecutorForProject

func (db *DB) GetLastExecutorForProject(project string) (string, error)

GetLastExecutorForProject returns the last used executor for a project.

func (*DB) GetLastModelForProject added in v0.3.14

func (db *DB) GetLastModelForProject(project string) (string, error)

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

func (db *DB) GetLastPermissionForProject(project string) (string, error)

GetLastPermissionForProject returns the last used permission mode for a project ("" means none recorded yet).

func (*DB) GetLastQuestion

func (db *DB) GetLastQuestion(taskID int64) (string, error)

GetLastQuestion retrieves the most recent question log for a task.

func (*DB) GetLastTaskTypeForProject

func (db *DB) GetLastTaskTypeForProject(project string) (string, error)

GetLastTaskTypeForProject returns the last used task type for a project.

func (*DB) GetLastUsedProject

func (db *DB) GetLastUsedProject() (string, error)

GetLastUsedProject returns the last used project name.

func (*DB) GetLatestLogPerTask added in v0.2.27

func (db *DB) GetLatestLogPerTask(taskIDs []int64) (map[int64]*TaskLog, error)

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

func (db *DB) GetMostRecentlyCreatedTask() (*Task, error)

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

func (db *DB) GetNextQueuedTask() (*Task, error)

GetNextQueuedTask returns the next task to process.

func (*DB) GetOpenBlockerCount

func (db *DB) GetOpenBlockerCount(taskID int64) (int, error)

GetOpenBlockerCount returns the number of incomplete blockers for a task.

func (*DB) GetPipelineArtifact added in v0.3.18

func (db *DB) GetPipelineArtifact(branch, name string) (string, error)

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

func (db *DB) GetProjectByName(name string) (*Project, error)

GetProjectByName returns a project by name or alias.

func (*DB) GetProjectByPath

func (db *DB) GetProjectByPath(cwd string) (*Project, error)

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

func (db *DB) GetProjectContext(projectName string) (string, error)

GetProjectContext returns the auto-generated context for a project. This context is cached exploration results that can be reused across tasks.

func (*DB) GetQueuedTasks

func (db *DB) GetQueuedTasks() ([]*Task, error)

GetQueuedTasks returns all queued tasks (waiting to be processed).

func (*DB) GetRetryFeedback

func (db *DB) GetRetryFeedback(taskID int64) (string, error)

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) GetSetting

func (db *DB) GetSetting(key string) (string, error)

GetSetting returns a setting value.

func (*DB) GetStaleWorktreeTasks

func (db *DB) GetStaleWorktreeTasks(maxAge time.Duration) ([]*Task, error)

GetStaleWorktreeTasks returns done/archived tasks that have worktree paths set and were completed more than maxAge ago. These are candidates for cleanup.

func (*DB) GetStepVerify added in v0.3.18

func (db *DB) GetStepVerify(taskID int64) (string, error)

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

func (db *DB) GetTagsList() ([]string, error)

GetTagsList returns all unique tags used across all tasks.

func (*DB) GetTask

func (db *DB) GetTask(id int64) (*Task, error)

GetTask retrieves a task by ID.

func (*DB) GetTaskBaseCommit added in v0.3.16

func (db *DB) GetTaskBaseCommit(taskID int64) (string, error)

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

func (db *DB) GetTaskBaseDirty(taskID int64) (string, error)

GetTaskBaseDirty returns the paths dirty in the worktree when the task started.

func (*DB) GetTaskByWorktreePath added in v0.3.22

func (db *DB) GetTaskByWorktreePath(path string) (*Task, error)

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

func (db *DB) GetTaskLogCount(taskID int64) (int, error)

GetTaskLogCount returns the number of logs for a task. This is a fast operation useful for checking if logs have changed.

func (*DB) GetTaskLogs

func (db *DB) GetTaskLogs(taskID int64, limit int) ([]*TaskLog, error)

GetTaskLogs retrieves logs for a task.

func (*DB) GetTaskLogsBefore added in v0.3.28

func (db *DB) GetTaskLogsBefore(taskID, beforeID int64, limit int) ([]*TaskLog, error)

GetTaskLogsBefore returns a bounded history page, newest first. A zero beforeID selects the latest page.

func (*DB) GetTaskLogsSince

func (db *DB) GetTaskLogsSince(taskID int64, sinceID int64) ([]*TaskLog, error)

GetTaskLogsSince retrieves logs after a given ID.

func (*DB) GetTaskLogsSinceLimit added in v0.3.28

func (db *DB) GetTaskLogsSinceLimit(taskID, sinceID int64, limit int) ([]*TaskLog, error)

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

func (db *DB) GetTaskPlacement(taskID int64) (target, reason string, err error)

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

func (db *DB) GetTaskRemoteWorktree(taskID int64) (path, branch string, err error)

GetTaskRemoteWorktree returns the remote worktree path and branch, both empty for a task that has never run remotely.

func (*DB) GetTaskType

func (db *DB) GetTaskType(id int64) (*TaskType, error)

GetTaskType retrieves a task type by ID.

func (*DB) GetTaskTypeByName

func (db *DB) GetTaskTypeByName(name string) (*TaskType, error)

GetTaskTypeByName retrieves a task type by name.

func (*DB) HasContinuationMarker

func (db *DB) HasContinuationMarker(taskID int64) (bool, error)

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

func (db *DB) HasLogLineContaining(taskID int64, substr string) (bool, error)

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

func (db *DB) HasOpenTaskWithTitle(title string) (bool, error)

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

func (db *DB) HasQuestionLog(taskID int64) (bool, error)

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) HasSessionStarted added in v0.3.16

func (db *DB) HasSessionStarted(taskID int64) (bool, error)

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) IsBlocked

func (db *DB) IsBlocked(taskID int64) (bool, error)

IsBlocked returns true if the task has any incomplete blockers.

func (*DB) IsFirstRun

func (db *DB) IsFirstRun() bool

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) ListProjects

func (db *DB) ListProjects() ([]*Project, error)

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) ListTaskTypes

func (db *DB) ListTaskTypes() ([]*TaskType, error)

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) MarkPRAutoCompleted added in v0.3.11

func (db *DB) MarkPRAutoCompleted(taskID int64, prNumber int) error

MarkPRAutoCompleted records that PR #prNumber has auto-completed this task, so a later reconcile pass won't re-complete the task for the same PR after a human reopens it to keep working.

func (*DB) MarkTaskStarted

func (db *DB) MarkTaskStarted(id int64) error

MarkTaskStarted sets the started_at timestamp if not already set.

func (*DB) Path

func (db *DB) Path() string

Path returns the path to the database file.

func (*DB) ProcessCompletedBlocker

func (db *DB) ProcessCompletedBlocker(blockerID int64) ([]*Task, error)

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) RecordHostHealth added in v0.3.28

func (db *DB) RecordHostHealth(host, problem string, observed bool) error

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

func (db *DB) RemoteSignal(taskID int64, host string) (RemoteEvent, bool, error)

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

func (db *DB) RemoveDependency(blockerID, blockedID int64) error

RemoveDependency removes a dependency between two tasks.

func (*DB) RequeueReadyTasks added in v0.3.16

func (db *DB) RequeueReadyTasks() ([]*Task, error)

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) RestoreTask added in v0.3.16

func (db *DB) RestoreTask(id int64) error

RestoreTask clears the trashed flag, returning a soft-deleted task to the board with its original status, worktree and session intact.

func (*DB) RetryTask

func (db *DB) RetryTask(id int64, feedback string) error

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) SearchTasks

func (db *DB) SearchTasks(query string, limit int) ([]*Task, error)

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

func (db *DB) SetAutoQueue(blockerID, blockedID int64, autoQueue bool) error

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

func (db *DB) SetLastEffortForProject(project, effort string) error

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

func (db *DB) SetLastExecutorForProject(project, executor string) error

SetLastExecutorForProject saves the last used executor for a project.

func (*DB) SetLastModelForProject added in v0.3.14

func (db *DB) SetLastModelForProject(project, model string) error

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

func (db *DB) SetLastPermissionForProject(project, mode string) error

SetLastPermissionForProject saves the last used permission mode for a project so the next task in it defaults to the same choice.

func (*DB) SetLastTaskTypeForProject

func (db *DB) SetLastTaskTypeForProject(project, taskType string) error

SetLastTaskTypeForProject saves the last used task type for a project.

func (*DB) SetLastUsedProject

func (db *DB) SetLastUsedProject(project string) error

SetLastUsedProject saves the last used project name.

func (*DB) SetPipelineArtifact added in v0.3.18

func (db *DB) SetPipelineArtifact(branch, name, content string) error

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

func (db *DB) SetProjectContext(projectName string, context string) error

SetProjectContext saves auto-generated context for a project. This overwrites any existing context.

func (*DB) SetRoutineRunLogPath added in v0.3.7

func (db *DB) SetRoutineRunLogPath(id int64, logPath string) error

SetRoutineRunLogPath records where the run's full log lives.

func (*DB) SetSetting

func (db *DB) SetSetting(key, value string) error

SetSetting sets a setting value.

func (*DB) SetStepVerify added in v0.3.18

func (db *DB) SetStepVerify(taskID int64, command string) error

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

func (db *DB) SetTaskBaseCommit(taskID int64, sha string) error

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

func (db *DB) SetTaskBaseDirty(taskID int64, paths string) error

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

func (db *DB) SetTaskPlacement(taskID int64, target, reason string) error

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

func (db *DB) SetTaskPlacementDecision(taskID int64, target, reason, workDir string) error

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

func (db *DB) SetTaskRemoteWorktree(taskID int64, path, branch string) error

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) SoftDeleteTask added in v0.3.16

func (db *DB) SoftDeleteTask(id int64) error

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

func (db *DB) UpdateProject(p *Project) error

UpdateProject updates a project.

func (*DB) UpdateTask

func (db *DB) UpdateTask(t *Task) error

UpdateTask updates a task's fields.

func (*DB) UpdateTaskClaudeConfigDir added in v0.3.28

func (db *DB) UpdateTaskClaudeConfigDir(taskID int64, configDir string) error

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

func (db *DB) UpdateTaskClaudeSessionID(taskID int64, sessionID string) error

UpdateTaskClaudeSessionID updates only the Claude session ID for a task.

func (*DB) UpdateTaskDaemonSession

func (db *DB) UpdateTaskDaemonSession(taskID int64, daemonSession string) error

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

func (db *DB) UpdateTaskDangerousMode(taskID int64, dangerousMode bool) error

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

func (db *DB) UpdateTaskLastAccessedAt(taskID int64) error

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

func (db *DB) UpdateTaskPRInfo(taskID int64, prURL string, prNumber int, prInfoJSON string) error

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

func (db *DB) UpdateTaskPaneIDs(taskID int64, claudePaneID, shellPaneID string) error

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

func (db *DB) UpdateTaskPermissionMode(taskID int64, mode string) error

UpdateTaskPermissionMode updates the permission_mode for a task and keeps the legacy dangerous_mode boolean consistent.

func (*DB) UpdateTaskPinned

func (db *DB) UpdateTaskPinned(taskID int64, pinned bool) error

UpdateTaskPinned updates only the pinned flag for a task.

func (*DB) UpdateTaskStartedAt

func (db *DB) UpdateTaskStartedAt(taskID int64, t time.Time) error

UpdateTaskStartedAt updates the started_at timestamp for a task. This is primarily used for testing.

func (*DB) UpdateTaskStatus

func (db *DB) UpdateTaskStatus(id int64, status string) error

UpdateTaskStatus updates a task's status.

func (*DB) UpdateTaskSummary

func (db *DB) UpdateTaskSummary(taskID int64, summary string) error

UpdateTaskSummary updates the task summary and distillation timestamp.

func (*DB) UpdateTaskType

func (db *DB) UpdateTaskType(t *TaskType) error

UpdateTaskType updates a task type.

func (*DB) UpdateTaskWindowID

func (db *DB) UpdateTaskWindowID(taskID int64, windowID string) error

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

func (db *DB) ValidateTaskModel(t *Task) error

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) WasPRAutoCompleted added in v0.3.11

func (db *DB) WasPRAutoCompleted(taskID int64, prNumber int) (bool, error)

WasPRAutoCompleted reports whether PR #prNumber has already auto-completed this task in a prior reconcile pass.

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 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
}

ListTasksOptions defines options for listing tasks.

type LocalTime

type LocalTime struct {
	time.Time
}

LocalTime wraps time.Time and converts from UTC to local timezone when scanning.

func (*LocalTime) Scan

func (lt *LocalTime) Scan(value interface{}) error

Scan implements sql.Scanner, converting scanned time to local timezone.

func (LocalTime) Value

func (lt LocalTime) Value() (driver.Value, error)

Value implements driver.Valuer for inserting LocalTime into database.

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

func (p *Project) EffectiveDefaultPermissionMode() string

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

func (p *Project) UsesWorktrees() bool

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 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 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

func (t *Task) EffectivePermissionMode() string

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

func (t *Task) EnvMap() map[string]string

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

func (t *Task) HasArchiveState() bool

HasArchiveState returns true if the task has saved archive state.

func (*Task) IsAcceptEdits added in v0.3.1

func (t *Task) IsAcceptEdits() bool

IsAcceptEdits reports whether the task runs in accept-edits (acceptEdits) mode.

func (*Task) IsAutoPermission added in v0.2.40

func (t *Task) IsAutoPermission() bool

IsAutoPermission reports whether the task runs in Claude Code's auto mode.

func (*Task) IsDangerous added in v0.2.40

func (t *Task) IsDangerous() bool

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.

Jump to

Keyboard shortcuts

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