Documentation
¶
Overview ¶
Package task implements nt's todo.txt task model with the lossless round-trip guarantee from SPEC §4: a file is parsed into an ordered list of nodes (each a parsed task or a preserved raw line), and an unmodified line is re-emitted byte-for-byte. Only when a task is mutated do we re-render it from structured fields, touching only the tokens nt owns and preserving any unknown key:value tokens another todo.txt client may have written.
Index ¶
- Constants
- Variables
- func AdvanceDue(t *Task, today string) string
- func BlockedIDs(tasks []*Task) map[string]bool
- func DanglingBlocks(tasks []*Task) []string
- func DepCycles(tasks []*Task) [][]string
- func DueBucket(t *Task, today, weekEnd string) string
- func EffectiveStatus(t *Task, isBlocked bool) string
- func IsPositional(handle string) bool
- func NextDue(t *Task, today string) string
- func SortByUrgency(ts []*Task)
- func Urgency(t *Task) float64
- func VisibleInList(t *Task, blockedByDep, includeDone, includeBlocked bool) bool
- type Doc
- func (d *Doc) Append(t *Task)
- func (d *Doc) FindByID(id string) *Task
- func (d *Doc) Remove(id string) (before string, ok bool)
- func (d *Doc) Render() []byte
- func (d *Doc) ReplaceByID(id string, t *Task) bool
- func (d *Doc) Resolve(handle string) (t *Task, ambiguous bool)
- func (d *Doc) Tasks() []*Task
- type Node
- type Review
- type Task
- func (t *Task) AddLink(target string)
- func (t *Task) AddTag(tag string)
- func (t *Task) Blocks() string
- func (t *Task) Discovered() string
- func (t *Task) Due() string
- func (t *Task) EnsureID()
- func (t *Task) ID() string
- func (t *Task) Key(name string) string
- func (t *Task) Line() string
- func (t *Task) Links() []string
- func (t *Task) Parent() string
- func (t *Task) Projects() []string
- func (t *Task) Recur() string
- func (t *Task) RemoveTag(tag string)
- func (t *Task) SetDone(done bool, today string)
- func (t *Task) SetKey(key, val string)
- func (t *Task) SetPriority(p byte)
- func (t *Task) SetProject(project string)
- func (t *Task) SetState(s string)
- func (t *Task) SetText(s string)
- func (t *Task) SetTitle(title string)
- func (t *Task) Source() string
- func (t *Task) Start() string
- func (t *Task) State() string
- func (t *Task) Status() string
- func (t *Task) Tags() []string
Constants ¶
const ( BucketOverdue = "Overdue" BucketToday = "Today" BucketThisWeek = "This week" BucketLater = "Later" BucketNoDate = "No date" BucketDone = "Done" )
Date buckets for the planner/agenda grouping, in display order.
Variables ¶
var DueBuckets = []string{BucketOverdue, BucketToday, BucketThisWeek, BucketLater, BucketNoDate, BucketDone}
DueBuckets is the bucket order for a date-grouped task view.
Functions ¶
func AdvanceDue ¶ added in v0.4.0
AdvanceDue returns the task's due advanced to its next occurrence — one period past the current due (or today if undated), rolled forward to on/after today. Used by `nt skip` to move a recurring task forward without completing it. Returns "" if the task isn't recurring.
func BlockedIDs ¶
BlockedIDs returns the set of task ULIDs that are blocked by an open task (SPEC §9). A task B with `blocks:X` blocks task X for as long as B is not done; X is then hidden from default listings. Tasks caught in a dependency cycle are deliberately NOT marked blocked — none could ever unblock, so hiding them all would be an invisible deadlock; they stay visible so the user can break the cycle (and `nt doctor` reports it).
func DanglingBlocks ¶ added in v0.4.0
DanglingBlocks returns the ULIDs of tasks whose blocks: target no longer exists (e.g. the blocked task was deleted) — a stale edge `nt doctor` reports.
func DepCycles ¶ added in v0.4.0
DepCycles returns each dependency cycle among open tasks as a list of task ULIDs (e.g. A blocks B, B blocks A → ["A","B"]). Because the blocking graph is functional, a cycle is found by following each chain until it revisits a node already on the current path.
func DueBucket ¶ added in v0.4.0
DueBucket assigns a task to a planner bucket relative to today and weekEnd (both YYYY-MM-DD). Comparisons use the date prefix, so a due with a time-of-day (due:…T17:00) still buckets by its calendar day — the rule the TUI and the web agenda share, kept here so they can't drift (and the TUI no longer mis-files a same-day timed due into "This week").
func EffectiveStatus ¶
EffectiveStatus is the display status accounting for dependency blocking: a not-done task that is the target of an open blocker shows as "blocked" even without an explicit s:blocked marker.
func IsPositional ¶
IsPositional reports whether a handle is a positional "task:N" / "N" reference rather than a stable ULID — so adapters can refuse it from non-interactive callers, where the list index may have shifted between read and act (§7.2).
func NextDue ¶ added in v0.4.0
NextDue computes the next occurrence's due date for a recurring task, given the completion/reference date `today`:
- Strict recurrences (rec:+3d, rec:+weekly) anchor to the task's scheduled due and roll FORWARD to the next slot on/after today — so a task completed late never spawns an already-overdue occurrence, and the cadence stays pinned to the calendar (e.g. "rent on the 1st").
- Plain recurrences (rec:3d, rec:weekly) schedule from `today` itself — the "N days after I last did it" semantics (e.g. "water the plant 3d after").
Returns "" when the task isn't recurring.
func SortByUrgency ¶
func SortByUrgency(ts []*Task)
SortByUrgency orders tasks most-urgent first (stable).
func Urgency ¶
Urgency scores a task by priority, due-date proximity, and doing-state. It's the single ranking behind `nt list --sort urgency`, the TUI's grouping, and `nt ready` / the MCP server, so the three never drift (SPEC §9).
func VisibleInList ¶ added in v0.4.0
VisibleInList reports whether a task should appear in a default task listing, given the show-done / show-blocked toggles. It is the one visibility rule every surface shares (SPEC §9), extracted here so the CLI, TUI, web, and MCP can't drift on it:
- a done task hides unless includeDone;
- an open task that is dependency-blocked hides unless includeBlocked.
blockedByDep is raw membership in the blocked set (see BlockedIDs) — the "& not-done" part is applied here so callers pass the set lookup directly.
Types ¶
type Doc ¶
type Doc struct {
Nodes []Node
// contains filtered or unexported fields
}
Doc is an ordered list of nodes — the in-memory model of a tasks file. It preserves line order and the file's trailing-newline state so an unmodified document renders byte-identically (SPEC §4).
func (*Doc) Append ¶
Append adds a task as a new node. If the document is non-empty and lacks a trailing newline, one is added first so the new task starts on its own line.
func (*Doc) Remove ¶
Remove deletes the node holding the task with id, returning the removed task's raw line (its before-image) for the undo journal.
func (*Doc) ReplaceByID ¶
ReplaceByID swaps in a new task for the node with the given id, returning false if no such task exists.
type Node ¶
Node is one line of the file: a parsed Task, or a preserved raw line (blank lines, comments, anything that isn't a task). Exactly one field is set.
type Review ¶ added in v0.10.0
type Review struct {
Overdue []*Task // actionable, past due
Stale []*Task // open ≥ StaleDays, not overdue, no progress
Undated []*Task // actionable, no due date
StuckProjects []string // projects whose every open task is blocked
StaleDays int // the threshold used, for display
}
Review is the weekly-triage breakdown surfaced by `nt review` (CLI) and the web /review: what needs a decision. Shared here so both surfaces bucket identically (SPEC §9, the shared query layer).
func BuildReview ¶ added in v0.10.0
BuildReview triages tasks into the review buckets. today is ISO (YYYY-MM-DD); blocked maps task id → dependency-blocked (from BlockedIDs). A task appears in at most one task bucket (overdue wins over stale wins over undated).
type Task ¶
type Task struct {
Done bool
Priority byte // 0, or 'A'..'Z'
Completed string // YYYY-MM-DD or ""
Created string // YYYY-MM-DD or ""
Text string // description, including inline +project / @tag / [[link]]
// contains filtered or unexported fields
}
Task is a single todo.txt line, parsed.
func CompletedSince ¶
CompletedSince returns the completed tasks, newest completion first, optionally bounded to those completed on or after `since` (a YYYY-MM-DD date; "" = no bound). This is the core rule behind both the TUI Logbook and `nt log`, so the ordering and the meaning of "completed" live in the domain, not an adapter.
A since bound excludes tasks with no completion date (an empty date sorts before any real one), which is the desired behaviour for "what did I finish in the last N days".
func New ¶
New builds a fresh task with a ULID. Callers add text/metadata then it is appended to a Doc.
func ParseLine ¶
ParseLine parses a single line into a Task (raw, unmodified). Used by the undo engine to restore a before-image so it renders byte-identically.
func SpawnNext ¶
SpawnNext builds the next occurrence of a recurring task (SPEC §9). The new task copies the description, priority, recurrence, source, workstream, and parent, gets a fresh ULID, and is scheduled by NextDue. Call it while the original is still open (before SetDone moves the priority to a pri: key). Returns nil if the recurrence spec is empty or unparseable (so no malformed duplicate spawns).
func (*Task) AddTag ¶ added in v0.16.0
AddTag adds an @tag to the description if not already present (no leading @).
func (*Task) Discovered ¶
Discovered is the ULID of the task this one was discovered while working on — provenance for work an agent surfaced mid-task (key: discovered:<ULID>).
func (*Task) EnsureID ¶
func (t *Task) EnsureID()
EnsureID assigns a ULID if the task lacks one (SPEC §4: hand-added lines get an id on the next mutation that touches them).
func (*Task) Key ¶ added in v0.4.0
Key returns the value of an arbitrary key:value token (empty if absent), so callers outside the package can read/normalize tokens nt doesn't model.
func (*Task) Line ¶
Line returns the on-disk representation: the original raw line when unmodified, or a freshly rendered canonical line when mutated.
func (*Task) RemoveTag ¶ added in v0.16.0
RemoveTag drops an @tag from the description (no-op if absent).
func (*Task) SetDone ¶
SetDone toggles completion. Marking done preserves any (A) priority as a pri:A key (SPEC §4); reopening restores it.
func (*Task) SetPriority ¶
SetPriority sets (0 clears) the priority. No-op on done tasks beyond storing the pri key.
func (*Task) SetProject ¶ added in v0.16.0
SetProject replaces the task's +project(s) with the given one ("" clears them).
func (*Task) SetState ¶
SetState sets s:doing / s:blocked, or clears it for "open". "done"/"" are handled via SetDone by the caller.
func (*Task) SetTitle ¶ added in v0.16.0
SetTitle replaces the prose description while preserving the inline metadata tokens (@tag, +project, [[link]]) — so a typo fix doesn't drop a task's tags.
func (*Task) Start ¶ added in v0.4.0
Start is the threshold/defer date (todo.txt "t:" key): the task is not actionable until this date. Agenda/ready views hide future-start tasks.