Documentation
¶
Overview ¶
Package tasklist implements a small, self-contained store for labelled, ordered collections of tasks. It owns the task_lists and tasks tables in the shared SQLite database (opened by the statestore package) but knows nothing about plans, phases, or any other owner: a task list is just a label, a lifecycle status, and an ordered set of task rows.
planengine consumes this package to back a plan phase's tasks, but the decoupling is deliberate — a future standalone task-list path can use tasklist directly without going through planengine at all.
Index ¶
- Variables
- func FenceFor(content string) string
- func RenderHint(hint, indent string) string
- func RenderMarkdown(tl TaskListWithTasks) string
- type ListStatus
- type Status
- type Store
- func (s *Store) AddTask(listID int64, body, hint string) (Task, error)
- func (s *Store) Bootstrap(ctx context.Context) error
- func (s *Store) CreateList(label string) (TaskList, error)
- func (s *Store) GetList(id int64) (TaskListWithTasks, error)
- func (s *Store) GetTask(taskID int64) (Task, error)
- func (s *Store) ListLists(filter ListStatus) ([]TaskList, error)
- func (s *Store) ReorderTask(taskID int64, targetPos int) error
- func (s *Store) SetAfterMutate(fn func(taskID int64) error)
- func (s *Store) UpdateListStatus(listID int64, status ListStatus) error
- func (s *Store) UpdateTask(taskID int64, upd TaskUpdate) error
- func (s *Store) UpdateTaskStatus(taskID int64, status Status) error
- type Task
- type TaskList
- type TaskListWithTasks
- type TaskUpdate
Constants ¶
This section is empty.
Variables ¶
ErrNotFound is returned when a lookup by ID finds no row. Callers can match against this with errors.Is.
Functions ¶
func FenceFor ¶
FenceFor returns a backtick fence string long enough to safely wrap content as a Markdown code block: at least three backticks, and always longer than the longest run of backticks appearing inside content. This prevents a hint that itself contains a fenced code block from prematurely closing the wrapping fence.
func RenderHint ¶
RenderHint renders a task hint as a fenced code block, with every line (including the fences) prefixed by indent so it nests under its task bullet. The fence length is chosen by FenceFor so hint content containing backticks renders intact. The returned string ends with a newline.
func RenderMarkdown ¶
func RenderMarkdown(tl TaskListWithTasks) string
RenderMarkdown produces the human-readable view of a single task list: an H1 with the list label, a status line, then a checkbox list of the tasks in display order. The function is pure — it takes a TaskListWithTasks and returns a string; the caller is responsible for writing the bytes anywhere.
Types ¶
type ListStatus ¶
type ListStatus string
ListStatus names the lifecycle state of a whole task list. pending is the starting state; in_progress once work has begun; completed when every task is resolved; abandoned when the list is dropped without completion.
const ( ListStatusPending ListStatus = "pending" ListStatusInProgress ListStatus = "in_progress" ListStatusCompleted ListStatus = "completed" ListStatusAbandoned ListStatus = "abandoned" )
func (ListStatus) IsValid ¶
func (s ListStatus) IsValid() bool
IsValid reports whether s is one of the four recognised list statuses. Used to validate input on UpdateListStatus.
type Status ¶
type Status string
Status names the lifecycle state of a single task within a list. pending is the starting state when the task is created. in_progress is set just before work begins; done after it is verified; skipped when the task can no longer be completed cleanly and the owner has agreed to move on. The values mirror planengine's task statuses so a plan-backed list renders identically.
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store wraps the shared SQLite connection and offers narrowly-scoped helpers for creating task lists, adding tasks, and transitioning statuses. It borrows the connection from statestore and never closes it; the session owns the connection lifecycle.
func New ¶
func New(db *statestore.DB) (*Store, error)
New returns a Store backed by the shared statestore connection, bootstrapping its tables on first use. It does not open or own the database — statestore does — so the connection is shared with every other state-owning package.
func (*Store) AddTask ¶
AddTask appends a new task to the list identified by listID, auto- assigning the next ord and bumping the list's updated_at. hint is optional freeform execution context; pass "" for none. Returns the persisted Task. Errors with ErrNotFound if listID does not exist.
func (*Store) Bootstrap ¶
Bootstrap creates the task_lists/tasks tables and the task index on the shared connection via the embedded CREATE TABLE IF NOT EXISTS script. It is idempotent: a no-op on an already-bootstrapped database, full creation on a fresh one. modernc.org/sqlite executes the multi-statement script as a batch.
func (*Store) CreateList ¶
CreateList inserts a new task list with the default pending status and equal created_at/updated_at timestamps. Returns the persisted TaskList with its allocated ID. label is required.
func (*Store) GetList ¶
func (s *Store) GetList(id int64) (TaskListWithTasks, error)
GetList returns the list and its tasks in display order. Errors with ErrNotFound if the list does not exist.
func (*Store) GetTask ¶
GetTask loads a single task by ID, including its task_list_id so callers can resolve the owning list. Errors with ErrNotFound if absent.
func (*Store) ListLists ¶
func (s *Store) ListLists(filter ListStatus) ([]TaskList, error)
ListLists returns all task lists ordered most-recently-updated first. When filter is non-empty, only lists with that status are returned; passing "" returns every list.
func (*Store) ReorderTask ¶
ReorderTask moves the task identified by taskID to targetPos (1-based) among its list's tasks, using the shared collision-safe reorder algorithm, and bumps the owning list's updated_at. Fires afterMutate on success, same as UpdateTask. Errors with ErrNotFound if the task does not exist.
func (*Store) SetAfterMutate ¶
SetAfterMutate registers a hook invoked after every committed task insert or status change, receiving the affected task's ID. Pass nil to clear it. It exists so the session can wire planengine's plan-touch onto the single shared task store without coupling tasklist to plan concepts. Not safe for concurrent use with task writes; set it once during session setup.
func (*Store) UpdateListStatus ¶
func (s *Store) UpdateListStatus(listID int64, status ListStatus) error
UpdateListStatus sets a list's status and bumps its updated_at. Errors if the list does not exist or the status is not a recognised ListStatus.
func (*Store) UpdateTask ¶
func (s *Store) UpdateTask(taskID int64, upd TaskUpdate) error
UpdateTask applies the provided fields of upd to the task identified by taskID, bumps the owning list's updated_at, and fires afterMutate. Only the non-nil pointer fields are written, built into a dynamic SET clause, so a caller can change any subset of body, hint, and status in one round trip. A nil-everywhere update is a no-op error. A non-nil Status is validated; a Hint set to "" stores SQL NULL (clearing the hint). Errors with ErrNotFound if the task does not exist.
type Task ¶
Task is one row of the tasks table. TaskListID identifies the owning list (used for owner resolution by consumers). Ord is the 1-based display order within the list; the store assigns it on insert as MAX(ord)+1. Body is a single imperative-mood sentence; Status drives the checkbox glyph in the rendered markdown. Hint is optional freeform execution context (rationale or a code snippet) authored by the planning model and consumed by the executing model; empty when unset.
type TaskList ¶
type TaskList struct {
ID int64
Label string
Status ListStatus
CreatedAt time.Time
UpdatedAt time.Time
}
TaskList is one row of the task_lists table. Label is the human-readable heading shown in the rendered markdown; Status drives the list-level lifecycle. CreatedAt/UpdatedAt are maintained by the store.
func CreateListTx ¶
CreateListTx inserts a new task list within an existing transaction and returns the persisted TaskList. It exists so a caller composing a larger multi-table write — e.g. planengine.AddPhase creating a phase and its linked task list atomically — can do so on a single connection. Opening a second pool connection (via Store.CreateList) while a write transaction is already open would deadlock under SQLite's single-writer model. label is required.
type TaskListWithTasks ¶
TaskListWithTasks groups a list with its tasks in display order. It is the shape returned by GetList so a consumer can load a whole list in one call.
type TaskUpdate ¶
TaskUpdate carries an optional, partial edit to a task: each non-nil pointer field is applied, each nil field is left unchanged. It lets a single UpdateTask call change any subset of a task's body, hint, or status while distinguishing an omitted field from one explicitly set to the empty string (e.g. clearing a hint).
Source Files
¶
- render.go
- store.go
- tasklist.go