#+TITLE: Open Tasks Workflow #+AUTHOR: Craig Jennings & Claude #+DATE: 2026-04-25 * Overview Unified workflow for surfacing open tasks. Two modes share the same data-gathering and reconciliation logic, then branch on output: - *List mode* — exhaustive, priority-grouped display of every open task. Use when Craig wants to see his full plate. - *Next mode* — single-task recommendation via prioritization cascade. Use when Craig wants to pick what to do next without scanning the whole list. This workflow merges the two earlier standalone workflows =open-tasks.org= (list mode) and =whats-next.org= (next mode), which duplicated the data-gathering and reconciliation logic. It is not the daily list-hygiene habit — that lives in =task-review.org= and re-grades, kills, and stamps tasks rather than just displaying them. * When to Use This Workflow User says one of: - *List mode triggers:* "list open tasks", "show me all tasks", "what's on my plate" - *Next mode triggers:* "what's next", "what should I work on next", "what should I work on", "I need a recommendation" - *Ambiguous:* "what should I do today", "show me my tasks" — ask which mode Don't route "task review" / "review tasks" here — those trigger the hygiene habit in =task-review.org=, a different workflow. * Phase A: Data Gathering (both modes) ** Phase A pre-step — archive any freshly-DONE tasks Before reading =todo.org=, run the cleanup script's archive-done sweep so completed level-2 subtrees move from =* $Project Open Work= to =* $Project Resolved=: #+begin_src bash emacs --batch -q -l .ai/scripts/todo-cleanup.el --archive-done todo.org #+end_src Costs a few hundred milliseconds. Without it, a task that completed earlier in the session sits as =** DONE= under Open Work until the next =clean-todo= or wrap-up pass, and Next Mode would surface it as a "what's next" candidate. The sweep makes Phase A's read of =todo.org= reflect current state. Skip the sweep if the workflow is invoked in an explicit read-only or dry-run context. Default is to run it. ** Phase A reads — one parallel batch Issue all source reads as a single batch of parallel tool calls. They're independent: 1. Read =notes.org= — sections *Active Reminders*, *Pending Decisions*, and *Workflow State* (note the =:LAST_AUDIT:= date if present; "unset" or absent is treated as "never run"). 2. Read each of the 2-3 most recent files in =.ai/sessions/= — only the *Next Steps* subsection under =* Summary= (those capture recent "next time, do X" items that may still be open). 3. Read =todo.org= — entries under the open-work header (=* $Project Open Work=, e.g. =* Homelab Open Work=). Skip the resolved header (=* $Project Resolved=). 4. Run =date= for an accurate timestamp (used to evaluate deadlines + flag suspected completions). The phases below work entirely from this in-memory snapshot. The original split-workflow versions issued these reads sequentially in different files; consolidating saves round-trips and prevents the two implementations drifting apart. * Phase A.1: Evaluate audit-warranted (Next Mode only) Before Next Mode produces a recommendation, decide whether a =task-audit= run looks warranted. List Mode skips this phase — it displays the plate as-is and should not trigger a write-side-effect workflow first. Two triggers; either one trips the warranted flag. ** Temporal threshold If =:LAST_AUDIT:= is absent / unset, or its date is older than 14 days from today, the temporal trigger trips. (The 14-day default is per-project; tune by editing this workflow if a project churns faster or slower.) ** State-signal scan Walk the Phase A snapshot for any of these cheap signals — one is enough: 1. *Reminder/task mismatch* — an Active Reminder names a task or completion target that doesn't appear in =todo.org=, or =todo.org= names a reminder not present in *Active Reminders*. 2. *Passed scheduled date* — a task with =SCHEDULED:= or =DEADLINE:= earlier than today is still =TODO= or =DOING= with no completion log under it. 3. *"Waiting on X" matches a shipped X* — a task body contains "waiting on", "after X ships", "blocked by", and the recent session *Next Steps* (or *Files Modified*) summaries log the named X as shipped. 4. *Dead =file:= link* — a task body's =file:= link points to a path that no longer exists (one existence check per linked path). 5. *Sub-task DONE coverage >75%* — a parent task is still =TODO= or =DOING= while >75% of its sub-tasks are =DONE= or =CANCELLED= (a likely promotion-to-DONE candidate). ** Surface and decide If neither trigger trips, proceed silently to Phase B. If one or both trip, surface them inline and ask: #+begin_example Task-audit looks worth running before recommending what's next: - Temporal: 23 days since last audit (threshold 14). - Signal: "blocked by review of spec X" — sessions show spec X merged. 1. Run task-audit first, then come back to "what's next" (recommended) 2. Skip the audit — proceed straight to the recommendation 3. Defer — proceed now, file a TODO to run task-audit later #+end_example If the user picks option 1, hand off to =task-audit.org= and resume Next Mode at Phase B after it stamps =:LAST_AUDIT:=. If option 2, continue. If option 3, file a =** TODO [#B] Run task-audit= entry under =* $Project Open Work= with today's date and continue. * Phase B: Reconcile (both modes) Compare the open-task signal across sources. For each task in =notes.org= Active Reminders or in a recent session's Next Steps that does NOT have a corresponding =todo.org= entry: 1. Create a new =** TODO= entry under the =* $Project Open Work= header. 2. Assign a priority based on context: =[#A]= if time-sensitive or blocking, =[#B]= if important, =[#C]= if low urgency. 3. Include: - =:CREATED:= property with today's date. - Brief description of what needs to be done. - Why it matters (context from the reminder or session note). - Recommended approach or next steps. 4. If a deadline exists, add a =DEADLINE:= line. *Do NOT remove the item from =notes.org= Active Reminders.* Reminders serve a different purpose (surfaced at session start). The =todo.org= entry is for tracking and prioritization. *Judgment call:* Not every reminder needs a =todo.org= entry. Skip: - Pure informational notes (e.g. "rsyncshot running with 600s timeout"). - Waiting-for items with no action Craig can take (e.g. "package arriving Feb 25"). - Items already completed (handle in Phase C list mode). * Phase C: Mode-Specific Output ** List Mode *** Step 1: Review for Suspected Completions Quickly scan all open tasks and check if any appear already done, based on: - Recent session history mentioning completion. - Context clues (e.g. "arriving Feb 7" and today's date is Feb 12). - Work completed in previous sessions that wasn't marked done. Build a list of *suspected completions* — do NOT mark them done yet. These get confirmed with Craig in Step 3. *** Step 2: Display All Open Tasks Present grouped by priority. Format rules: - *Group by priority:* A (High), B (Medium), C (Low/Someday). - *Default priority:* Tasks without an explicit priority are treated as C. - *No table structure* — use a flat bulleted list within each group. - *Include deadlines:* If a task has a =DEADLINE:=, show it inline as =DEADLINE: =. - *Include scheduled dates:* If a task has a =SCHEDULED:=, show it inline. - *Keep descriptions concise* — task name + one-line summary, not full details. - *Note source* if task came from reminders only (not yet in =todo.org=) vs =todo.org=. Example: #+begin_example **Priority A (High)** - Complete Sara Essex email setup — add Google Workspace MX records, verify delivery - Set up Comet KVMs — remote console for TrueNAS and ratio - Complete UPS/TrueNAS integration — USB cable, configure shutdown threshold. DEADLINE: <2026-01-21> **Priority B (Medium)** - Design Zettelkasten architecture — resume at Question 4 (Staleness) - Compare Ubiquiti UTR vs open source mesh router **Priority C (Low / Someday)** - Explore Whisper-to-Claude-Code voice integration - Get Keychron Q6 Pro carrying case. SCHEDULED: <2026-02-07> #+end_example *** Step 3: Confirm Suspected Completions After displaying the list, present suspected completions: #+begin_example These tasks may already be completed — can you confirm? - "OBSBOT Tiny 3 webcam arriving" — it's past the expected delivery date - "Sweetwater order arriving" — expected Feb 7, now Feb 12 #+end_example For each task Craig confirms as done — applies to top-level (=**=) entries, which is what this workflow's list contains. Sub-tasks (=***+=) follow the dated-rewrite rule in [[file:../../claude-rules/todo-format.md][todo-format.md → Completion]] instead: 1. Add =CLOSED: [YYYY-MM-DD Day]= timestamp (use the =date= output from Phase A). 2. Change status from =TODO= to =DONE=. 3. Add a brief completion note (when/how it was resolved). 4. Move the entry from =* $Project Open Work= to =* $Project Resolved= in =todo.org=. 5. If the task also exists in Active Reminders in =notes.org=, remove it from there. For tasks Craig says are NOT done, leave them as-is. ** Next Mode Next Mode answers two questions in one output: "what matters most right now?" (the cascade, importance/urgency) and "what shape of task can I actually finish?" (the friction filter, effort + autonomy). The user picks the row that matches the state of their day. *** Step 1 — Cascade recommendation (importance/urgency) Apply the prioritization cascade in order. Stop at the first matching step. This is the importance/urgency answer. **** 1. In-Progress Tasks - Look for tasks marked =DOING= or partially complete. - *If found:* Recommend that task (always finish what's started). - *If user declines:* Continue to next step. **** 2. Active Reminders - Review notes.org Active Reminders (already in the Phase A snapshot). - *If found:* Recommend reminder task. - *If user declines:* Add to =todo.org= per Phase B (if not already there), then continue. **** 3. Deadline-Driven Tasks - Scan =todo.org= for tasks with explicit deadlines. - *If found:* Recommend the task with the closest deadline. - *If none:* Continue to next step. **** 4. V2MOM Method Order (if applicable) If =todo.org= is structured with V2MOM methods: - Method 1 priority A tasks first. - Then Method 2 priority A, Method 3 priority A, etc. - Then Method 1 priority B, Method 2 priority B, etc. - Continue pattern through priorities C and D. **** 5. Simple Priority Order If =todo.org= is a flat list: - Evaluate all priority A tasks, pick most important. - If no priority A, evaluate priority B tasks. - Continue through priorities C and D. **** 6. All Tasks Complete If no tasks remain: report "All done — no open tasks in =todo.org=." **** Handling Multiple Tasks at Same Level When multiple tasks share priority/method position, pick one based on: 1. *Blocks other work* — dependencies matter. 2. *Recently discussed* — mentioned in recent conversation. 3. *Most foundational* — enables other tasks. 4. *If truly uncertain* — show 2-3 options and let the user choose. *** Step 2 — Friction filter (effort + autonomy) Independently of the cascade, scan the open-task set for tasks tagged =:quick:= and =:solo:=. Build three ranked picks: - *Quick + solo* — the top task carrying BOTH tags. Smallest effort × highest autonomy = lowest friction. Ideal for a 20-minute window or a flagging-energy moment. - *Quick only* — the top task carrying =:quick:= but not =:solo:=. Small but needs the user's preference / hardware / sign-off. - *Solo only* — the top task carrying =:solo:= but not =:quick:=. Bounded scope that Claude can finish end-to-end, but not a short job. Within each row, pick a single task per the same-level tie-breakers above (blocks-other-work, recently-discussed, most-foundational). If a row has no tasks, omit it rather than padding. The friction filter is the override path. When the cascade winner is partially blocked, hardware-dependent, or simply too large for the user's current state, one of the friction rows is what they pick instead. *** Output Format Pair the cascade recommendation with the friction block beneath it. Recommendation-at-item-1 convention applies to the friction rows — quick+solo first, since it's the strongest low-friction pick. #+begin_example Cascade recommendation (importance/urgency): - Fix org-noter reliability — [#A], Method 1, 8/18 complete, blocks daily reading/annotation If you want lower friction instead: 1. Quick + solo: Bump linter config — [#C] :quick:solo:, ~15 min 2. Quick: Confirm new dirvish setup — [#B] :quick:, needs your eye 3. Solo: Refactor config-utilities — [#B] :solo:, bounded but multi-hour #+end_example Include for each row: - Task name / description. - Priority + tag cluster. - One-line reasoning. For the cascade row, name which cascade step matched. For friction rows, an effort hint when one is obvious. - Progress indicator (for V2MOM-structured todos) on the cascade row only. **** Edge cases - *Empty friction block.* If no =:quick:= or =:solo:= tagged tasks exist in the open set, omit the friction block entirely. Present only the cascade recommendation. - *Dedupe.* If the cascade recommendation IS the same task as one of the friction rows (e.g. it's =:quick:solo:= and also won the cascade), show it once at the top with both labels. Don't list it twice. - *Decline behavior.* If the user declines the cascade recommendation, drop straight to the friction block as the natural next prompt. Do not fall through to lower-cascade-tier tasks; the friction filter IS the override. * Resolving a Task — Format Reference When moving a task to Resolved (list mode Step 3), it should look like this: #+begin_example ** DONE [#A] Set up Comet KVMs CLOSED: [2026-02-12 Thu] :PROPERTIES: :CREATED: [2026-01-19 Mon] :END: Comet KVMs set up for TrueNAS and ratio. Remote BIOS/console access working. *Resolution:* Completed during Feb 12 session. Both KVMs connected and tested. #+end_example Key elements: - =DONE= replaces =TODO=. - =CLOSED:= line with completion date. - Original =:PROPERTIES:= block preserved. - Brief resolution note explaining when/how. * Common Mistakes 1. *Running Phase A sequentially* — issue all reads in one parallel batch. 2. *Marking tasks done without confirmation* — always ask Craig first (list mode Step 3). 3. *Removing reminders from =notes.org= when adding to =todo.org=* — they serve different purposes. 4. *Creating =todo.org= entries for pure informational reminders* — use judgment in Phase B. 5. *Using a table for the task list* — Craig prefers flat bulleted lists in list mode. 6. *Skipping the cascade order in next mode* — the cascade exists to override subjective choice with objective criteria; respect it. 7. *Recommending more than one task in the cascade row* — be decisive on the cascade. The friction block is a 3-row choice by design, but the cascade row is single-pick. 8. *Re-querying =todo.org= during Phase C* — the snapshot from Phase A is canonical; don't re-read. 9. *Skipping the friction block when the cascade winner isn't actionable.* The friction filter is the override path; don't fall through to lower-cascade-tier tasks if a =:quick:= or =:solo:= task is what's actually needed. 10. *Padding the friction block when a row is empty.* If no task carries both =:quick:= and =:solo:=, omit that row entirely. Don't promote a =:quick:=-only task into the =:quick:solo:= slot. 11. *Recommending over stale facts in Next Mode.* When =:LAST_AUDIT:= is old or a state signal trips in Phase A.1, offer =task-audit= first. Let the user override — but don't skip the offer. 12. *Running Phase A.1 in List Mode.* The audit-warranted check is a Next Mode pre-step. List Mode displays the plate as-is and shouldn't trigger a write workflow first. 13. *Recommending a freshly-DONE task.* Phase A's archive-done pre-step exists for exactly this. Skip it only in an explicit read-only or dry-run context; the default is always to sweep before reading. * Living Document Update this workflow as task management patterns evolve. If new task sources are added (external issue trackers, shared task lists), add them to Phase A. If the cascade ordering needs to change for a project, document the variant here. * History This file merged two earlier workflows: - the original =open-tasks.org= (list mode logic now lives in Phase C → List Mode) - =whats-next.org= (next mode logic now lives in Phase C → Next Mode) It was briefly named =task-review.org=; that name was reclaimed for the daily list-hygiene habit, and this workflow took back the =open-tasks.org= name.