From b007fee8fb5b39a5f9b369c59af71ac9e795ceaf Mon Sep 17 00:00:00 2001 From: Peter Stone Date: Fri, 17 Jul 2026 22:22:37 +0000 Subject: Implement linear task chains and recurring maintenance buckets Backend, web timeline, and Android widget wiring for the last two unimplemented items from doot-future-task-scheduling-ideas. Chains: task_chains table + chain_id/chain_position/chain_unlocked on native_tasks (migration 026), WIP-limit-1 advancement hooked into CompleteNativeTask, locked tasks excluded from all date-based queries, 5 new /api/widget/chains* endpoints, an N/M position badge on web and Android widget rows. Buckets: maintenance_buckets table + bucket_id/bucket_state/ bucket_last_active_at on native_tasks (migration 027), staleness-then-priority selection scoring, a new RunBucketCycleCheck scheduler loop, 5 new endpoints including the distinct Defer action, a Defer button on web and Android widget rows. Also corrected stale "not yet approved" status headers on the two already-shipped specs this work depended on (labels/projects, budgets/ availability) -- their headers were never updated after implementation. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01EZ7ikw2ukGJFTHE3bJS7zL --- internal/store/native_tasks_test.go | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) (limited to 'internal/store/native_tasks_test.go') diff --git a/internal/store/native_tasks_test.go b/internal/store/native_tasks_test.go index 00785c2..d82576e 100644 --- a/internal/store/native_tasks_test.go +++ b/internal/store/native_tasks_test.go @@ -42,7 +42,13 @@ func newNativeTasksTestStore(t *testing.T) *Store { recurrence_weekdays TEXT DEFAULT '', recurrence_series_id TEXT DEFAULT '', next_occurrence_override TEXT DEFAULT '', - estimated_minutes INTEGER DEFAULT 0 + estimated_minutes INTEGER DEFAULT 0, + chain_id TEXT DEFAULT '', + chain_position INTEGER DEFAULT 0, + chain_unlocked BOOLEAN DEFAULT 0, + bucket_id TEXT DEFAULT '', + bucket_state TEXT DEFAULT '', + bucket_last_active_at DATETIME ) `); err != nil { t.Fatal(err) @@ -68,6 +74,28 @@ func newNativeTasksTestStore(t *testing.T) *Store { `); err != nil { t.Fatal(err) } + if _, err := db.Exec(` + CREATE TABLE task_chains ( + id TEXT PRIMARY KEY, + project_id TEXT NOT NULL, + status TEXT NOT NULL DEFAULT 'active', + created_at DATETIME DEFAULT CURRENT_TIMESTAMP + ) + `); err != nil { + t.Fatal(err) + } + if _, err := db.Exec(` + CREATE TABLE maintenance_buckets ( + id TEXT PRIMARY KEY, + name TEXT NOT NULL, + cycle_days INTEGER NOT NULL, + pick_n INTEGER NOT NULL, + last_cycle_at DATETIME, + created_at DATETIME DEFAULT CURRENT_TIMESTAMP + ) + `); err != nil { + t.Fatal(err) + } if _, err := db.Exec(`INSERT INTO native_tasks (id, content) VALUES ('real-1', 'Real task')`); err != nil { t.Fatal(err) } -- cgit v1.2.3