Arcology Engine

Arcology2go: Tasks, Agenda, Habits

Contents

The agenda system brings org-agenda's task and habit management to the Android app. It extracts tasks and events from every heading in the org-roam directory — not just nodes with :ID: properties — and presents them in four views: a day-calendar agenda, a habit tracker with sparklines, a by-file project browser, and a by-tag task list.

This rebuild replaces a previous implementation that was removed because it was not satisfying enough to build on. The new design follows the same plugin-and-repository pattern as the quiz flashcard system: a TaskIndexerPlugin extracts task data during indexing, a TasksRepository provides typed queries against a dedicated Tasks.sq schema, and editor extensions in roam/editor.org write SCHEDULED/DEADLINE timestamps and handle repeaters.

Module Index

Agenda modules: ./

  • agenda/models.orgTaskHeading domain model, Tasks.sq schema (tasks, task_state_history), TasksRepository

  • agenda/indexer.orgTaskIndexerPlugin: walks the orgmode-kmp AST, extracts tasks/events from all headings (including non-node headings)

  • agenda/screen.orgAgendaScreen + AgendaViewModel: day-calendar view with TabRow for sub-views

  • agenda/habits.orgHabitScreen + HabitViewModel: sparkline habit tracker, consistency graph from task_state_history

  • agenda/projects.orgProjectScreen (by-file) + TaggedTasksScreen (by-tag) + shared TaskListViewModel for task-card actions and detail state

Modified modules:

  • roam/editor.org — new updateScheduled(), updateDeadline(), repeater handling in updateTodoState()

  • roam/indexer.org — wire TaskIndexerPlugin into FlowFileIndexer plugin list

  • app/bootstrap.orgScreen.Tasks route, bottom nav, NavHost entries, DI wiring

Architecture

The agenda system has four layers, built bottom-up:

  1. *Data layer* (agenda/models.org): A TaskHeading domain model represents any heading with a TODO state or active timestamp, regardless of whether it has an :ID:. Non-node headings are keyed by (file, position) — the node_id column is a nullable foreign key. TasksRepository provides queries for due tasks, overdue tasks, tasks by file, tasks by tag, and habits.

  2. *Indexer plugin* (agenda/indexer.org): TaskIndexerPlugin implements IndexerPlugin and walks the result.sections AST (top-level OrgSection list, with children nested in body). For each OrgSection, it checks the heading's planningInfo and todo state, collects floating active timestamps from the body, and extracts LOGBOOK state changes. Headings with a TODO keyword, a SCHEDULED/DEADLINE timestamp, a floating active timestamp, or a :STYLE: habit property are inserted into the task_headings table. This runs alongside QuizIndexerPlugin and ArroyoIndexerPlugin during FlowFileIndexer.storeParseResultBatched().

  3. *Editor extensions* (in roam/editor.org): The OrgDocumentEditor gains updateScheduled(nodeId, timestamp) and updateDeadline(nodeId, timestamp), following the existing text-surgery pattern — find the heading, regex-insert or replace the =SCHEDULED:=/=DEADLINE:= line between the heading line and the properties drawer. The existing updateTodoState() is extended to handle repeaters: when transitioning a heading with a repeater (e.g., =SCHEDULED: =) to DONE, the date advances by the repeater interval and the TODO state reverts to the original keyword.

  4. *UI layer* (agenda/screen.org, agenda/habits.org, agenda/projects.org): The bottom navigation gains a Tasks item in the first position. Tapping it opens AgendaScreen, which hosts a TabRow with four tabs: Agenda, Habits, Projects, Tagged. Each tab renders its own composable and is backed by its own ViewModel. The AgendaViewModel queries TasksRepository for tasks and events in the selected date range. HabitViewModel computes consistency graphs from task_state_history. TaskListViewModel is shared between the Projects and Tagged Tasks screens, with different sort/group modes.

Requirements

0) Data model & indexing changes

org-agenda works on headings, not just nodes; so there are going to be headings that are stored without IDs, they will need to be stored in the DB index by byte-offset, and outline-path for human-legibility.

Store tasks: headings that have TODO states. Store events: headings that have SCHEDULED or DEADLINE or floating active timestamps (timestamps set between <> rather than []).

Every file should be parsed for tasks & events as part of the FlowFileIndexer, alongside nodes & flashcards etc. They will have their own Repository but write to the same Database with their own .sq file like Quiz.sq and Arroyo.sq.

The TaskIndexerPlugin walks the OrgDocument AST (available on ParseResult.Success.document) rather than re-parsing the file. It iterates all OrgSection entries, not just those that became =OrgNode=s. This avoids duplicating parse work and keeps the plugin consistent with QuizIndexerPlugin and ArroyoIndexerPlugin.

=OrgDocumentEditor will need to be extended to support this. These methods live in roam/editor.org — the agenda module documents its needs here but the source blocks tangle into the existing OrgDocumentEditor.kt.

  • Parse SCHEDULED and DEADLINE, active and inactive timestamps

  • updateScheduled(nodeId, timestamp) — insert or replace the SCHEDULED planning line

  • updateDeadline(nodeId, timestamp) — insert or replace the DEADLINE planning line

  • Handle repeater in updateTodoState: when a heading with a repeater transitions to DONE, advance the timestamp by the repeater interval (+1d, ++1w, .+1m) and revert the TODO state to the original keyword, mirroring org-mode's org-auto-repeat-maybe.

1) AgendaScreen — partial re-implementation of org-agenda

ref: /nix/store/*-emacs-packages-deps/share/emacs/site-lisp/elpa/org-9.8.7/org-agenda.el

Show a static agenda that has:

  • Headings with active timestamps in the relevant time period shown in a day-calendar view; headings may NOT have an ID here, they may not be Nodes so they will need to be stored by byte-offset.

  • Tasks that may only have a date, not a specific time, may also appear here.

  • Overdue tasks must also appear here.

This view should be able to show arbitrary dates, and as a stretch would have a 3-day and 7-day view.

The screen hosts a TabRow with four tabs (Agenda, Habits, Projects, Tagged) — the bottom nav Tasks item navigates here, and the user switches sub-views from the top bar.

2) HabitScreen — habit tracking

ref: /nix/store/*-emacs-packages-deps/share/emacs/site-lisp/elpa/org-9.8.7/org-habit.el

Tasks that have a heading property :STYLE: habit and repeating scheduling should appear here with a "sparkline" showing how often a non-overdue hit is recorded for it.

So a habit that is "journal daily affirmations" would repeat daily and have a sparkline would be one spot per day; but something that has to be done monthly should show the whole last year of habit. If a habit is recorded late, that one would have a special color to differentiate "on time" vs. "overdue" habit hits.

The consistency graph is computed from task_state_history, which records every TODO state transition logged by OrgDocumentEditor.updateTodoState().

3) ProjectScreen and TaggedTasksScreen — task view

The task list between these two views will be shared (TaskListViewModel), but they will be orchestrated differently on each screen:

By-File

An index of all files that include tasks, opening the file will show a list of the tasks, sorted by priority and active timestamp. Shows the todo state, tags, and clicking the header should open the file in the editor.

The projects should be sorted by # of due tasks so that more important projects float to the top.

By-Tag

  • There should be a "meta" project at the top, showing untagged tasks, then individual tag-grouped sections below it.

  • there should be a way to filter down the tags

Implementation Order

Built bottom-up, each layer testable before the next is built:

  1. agenda/models.orgTaskHeading model, Tasks.sq schema, TasksRepository

  2. agenda/indexer.orgTaskIndexerPlugin, wire into FlowFileIndexer

  3. roam/editor.orgupdateScheduled(), updateDeadline(), repeater in updateTodoState()

  4. agenda/screen.orgAgendaScreen + AgendaViewModel

  5. agenda/habits.orgHabitScreen + HabitViewModel

  6. agenda/projects.orgProjectScreen + TaggedTasksScreen + TaskListViewModel

  7. app/bootstrap.orgScreen.Tasks route, bottom nav, DI wiring

Historical Note: Previous Implementation (Removed)

The previous Agenda, Habits, and Projects implementation was ripped out of the app in full. The prior implementation lived across seven org files (agenda-screen.org, habits-screen.org, projects-screen.org, tasks.org, data.org, filetags.org, cli.org) and tangled to ~21 source files spanning the Android app UI, ViewModels, shared domain models, SQLDelight schema, indexer plugin, filetag service, and a CLI subcommand.

All of that was removed because it was not satisfying enough to build on. The bottom navigation now has four tabs (Find, Quiz, Capture, Settings); the post-onboarding destination is the Find tab. The IndexingConfig.autoFiletagAssignment flag, the FiletagService, the TaskIndexerPlugin, the TasksRepository, the TaskCompletionService, and the MockTestTasksRepository test double are all gone. See app/index.org Sprint 11 for the historical note.