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.org—TaskHeadingdomain model,Tasks.sqschema (tasks, task_state_history),TasksRepositoryagenda/indexer.org—TaskIndexerPlugin: walks the orgmode-kmp AST, extracts tasks/events from all headings (including non-node headings)agenda/screen.org—AgendaScreen+AgendaViewModel: day-calendar view with TabRow for sub-viewsagenda/habits.org—HabitScreen+HabitViewModel: sparkline habit tracker, consistency graph from task_state_historyagenda/projects.org—ProjectScreen(by-file) +TaggedTasksScreen(by-tag) + sharedTaskListViewModelfor task-card actions and detail state
Modified modules:
roam/editor.org — new
updateScheduled(),updateDeadline(), repeater handling inupdateTodoState()roam/indexer.org — wire
TaskIndexerPluginintoFlowFileIndexerplugin listapp/bootstrap.org —
Screen.Tasksroute, bottom nav,NavHostentries, DI wiring
Architecture
The agenda system has four layers, built bottom-up:
*Data layer* (
agenda/models.org): ATaskHeadingdomain 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)— thenode_idcolumn is a nullable foreign key.TasksRepositoryprovides queries for due tasks, overdue tasks, tasks by file, tasks by tag, and habits.*Indexer plugin* (
agenda/indexer.org):TaskIndexerPluginimplements IndexerPlugin and walks theresult.sectionsAST (top-levelOrgSectionlist, with children nested inbody). For eachOrgSection, it checks the heading'splanningInfoandtodostate, 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: habitproperty are inserted into thetask_headingstable. This runs alongsideQuizIndexerPluginandArroyoIndexerPluginduringFlowFileIndexer.storeParseResultBatched().*Editor extensions* (in
roam/editor.org): TheOrgDocumentEditorgainsupdateScheduled(nodeId, timestamp)andupdateDeadline(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 existingupdateTodoState()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.*UI layer* (
agenda/screen.org,agenda/habits.org,agenda/projects.org): The bottom navigation gains a Tasks item in the first position. Tapping it opensAgendaScreen, which hosts aTabRowwith four tabs: Agenda, Habits, Projects, Tagged. Each tab renders its own composable and is backed by its own ViewModel. TheAgendaViewModelqueriesTasksRepositoryfor tasks and events in the selected date range.HabitViewModelcomputes consistency graphs fromtask_state_history.TaskListViewModelis 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.
0) Task-related editor actions
=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 lineupdateDeadline(nodeId, timestamp)— insert or replace the DEADLINE planning lineHandle 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'sorg-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:
agenda/models.org—TaskHeadingmodel,Tasks.sqschema,TasksRepositoryagenda/indexer.org—TaskIndexerPlugin, wire intoFlowFileIndexerroam/editor.org—updateScheduled(),updateDeadline(), repeater inupdateTodoState()agenda/screen.org—AgendaScreen+AgendaViewModelagenda/habits.org—HabitScreen+HabitViewModelagenda/projects.org—ProjectScreen+TaggedTasksScreen+TaskListViewModelapp/bootstrap.org—Screen.Tasksroute, 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.