cfait 1.1.8

Powerful, fast and elegant task / TODO manager. (GUI & TUI, CalDAV & local)
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
# Cfait Specifications & Developer Guidelines

> **⚠️ INSTRUCTIONS FOR DEVELOPERS AND CONTRIBUTORS:**
> This document is the ultimate source of truth for Cfait's behavior, data model, and architecture.
> 1. **Core-First & DRY:** Business logic, filtering, parsing, and data manipulation MUST live in the Rust core (`src/model`, `src/store.rs`, `src/controller.rs`). UIs (TUI, GUI, Mobile, CLI) must remain as thin as possible and act only as rendering/routing layers.
> 2. **Performance is Critical:** The UI must never lag, even with 100,000+ tasks. Avoid unnecessary cloning (use `&Task` references in filter pipelines). Rely on `TaskStore` indices for O(1) lookups.
> 3. **Keep this updated:** Update this document whenever introducing a new feature, syntax token, setting, or architectural shift. Keep it concise, behavioral, and accurate.

---

## 1. Core Architecture & Persistence

Cfait is an offline-first task manager that seamlessly synchronizes with CalDAV servers and local file storage.

### 1.1. Data Flow & Synchronization
*   **TaskStore (In-Memory):** The single source of truth for the active session. Contains tasks grouped by calendar HREF. Maintains O(1) HashMaps for UID lookups, blocking relationships, and parent-child hierarchies.
*   **Journal (Offline Queue):** All mutations (`Create`, `Update`, `Delete`, `Move`) append to `journal.json` immediately. UIs update optimistically.
*   **TaskController:** Orchestrates all updates. Receives `AppIntent`s from the UIs, applies them to the `TaskStore`, writes to the `Journal`, and signals the background worker.
*   **Background Sync:** 
    *   *Desktop (GUI/CLI daemon):* A background worker reads the Journal and pushes changes via `RustyClient`.
    *   *Android:* Handled via `WorkManager`. `PeriodicSyncWorker` runs based on `auto_refresh_interval_mins` (min 15 mins). Foreground manual syncs trigger immediate updates.
*   **Settings Sync:** User configuration (e.g., `default_calendar`, `disabled_calendars`, sorting presets, goals) and aliases sync across devices via a hidden `VTODO` task with UID `cfait-global-settings-v1` (status `CANCELLED`, category `cfait-internal`). 
    * *Exclusions:* Purely local view state (`hidden_calendars`, window dimensions, UI scale, expanded tree paths) intentionally do not sync so that each device retains its own independent viewing context.
    * *System Tags:* The `cfait-internal` category must be explicitly excluded from user-facing tag lists and autocomplete suggestions.
*   **Write Target (Active Collection):** When a new task is created, it is assigned to the UI's currently "active" collection. In the TUI/GUI, this is the collection currently selected/highlighted in the sidebar (regardless of how many other collections are visible in the main view). On Android, this is the collection tab currently being viewed. Upon app startup, this active collection is initialized to the globally synced `default_calendar`.
*   **Conflict & Error Handling:** 
    *   `412 Precondition Failed` (ETag mismatch): Performs a local 3-way merge. If unmergeable, a "Conflict Copy" is generated.
    *   **Fatal Server Errors (e.g., 400, 403, 415):** The problematic task is rescued into a local `local://recovery` calendar to prevent data loss or sync loop lockups, with the error appended to its description.
    *   **Duplicate UID Resolution:** If a duplicate UID is detected across collections (e.g., during a remote fetch), active collections always take precedence over system collections (`local://trash`, `local://recovery`). Otherwise, the task with the higher sequence number wins, tie-breaking alphabetically by collection HREF.

### 1.2. The Task & Journal Entity (`VTODO` & `VJOURNAL` Mapping)
Tasks map strictly to iCalendar `VTODO` components, while daily notes map to `VJOURNAL` components (RFC 5545). Non-standard metadata is stored via `X-CFAIT-` properties.
*   **VJOURNAL Support:** Each chronological journal entry is a date-anchored note (`DTSTART;VALUE=DATE`). Wiki pages are independent notes and intentionally omit the `DTSTART` property. Stored in the active collection. VJOURNAL components are omitted from the main task lists unless they contain child tasks, are children of another task, are explicitly tagged with `is:note` or `is:pinned` to force visibility, or are returned as part of an active search query. Both VTODO and VJOURNAL components are included in ICS import/export across all clients (GUI, CLI, Android), enabling migration between CalDAV providers.
*   **Status:** `NeedsAction` (Pending), `InProcess` (Timer running), `Completed`, `Cancelled`.
*   **Manual Block:** Stored via `X-CFAIT-BLOCKED` (boolean) to explicitly mark a task as blocked without dependencies.
*   **Dates (`DateType`):** Start (`DTSTART`) and Due (`DUE`). Supported variants:
    *   *Specific:* Exact DateTime (UTC).
    *   *All-Day:* NaiveDate.
    *   *Fuzzy:* Month/Year precision (stored as All-Day with `X-CFAIT-FUZZY-DUE`/`START` properties).
*   **Hierarchy:** `RELATED-TO` establishes the `parent_uid`.
*   **Dependencies:** `RELATED-TO;RELTYPE=DEPENDS-ON` establishes blocking relationships. `RELTYPE=SIBLING` establishes related tasks.
*   **Time Tracking:** Logged via `X-TIME-SPENT` (total seconds), `X-LAST-START` (unix timestamp), and `X-CFAIT-SESSION` (WorkSessions holding Unix start/end timestamps). The duration badge shown in task lists displays the aggregated time across the task's entire subtree (union-merged to avoid double-counting cascade overlaps), not just the task's own tracked time. Detail views and notifications show per-task time.
*   **System Entities:** Local trash uses `local://trash`. Items here are soft-deleted and pruned based on `trash_retention_days`.

### 1.3. System Integrations
*   **Keyring:** Passwords are never stored in plaintext `config.toml`. They are vaulted via OS keyrings: Windows Credential Manager, macOS Keychain, Linux Secret Portal (oo7) or Keyutils, Android Keystore.
*   **Logging:** Outputs to `cache/cfait.log` (rotating `cfait.old.log`). Terminal stderr logging is enabled for CLI/GUI, but disabled for TUI to prevent screen tearing. Android uses dual logging (File + Logcat).
*   **Crash Reporting (Android):** An `UncaughtExceptionHandler` should write panics to `cache/android_crash.txt` (but it doesn't work in practice).

---

## 2. Smart Syntax & Parsing
Evaluated instantly during text input. Supported across all clients.

### 2.0. Localization & Canonical Storage
*   **Canonical Storage:** The internal data model and `Task::to_smart_string()` MUST always output canonical English/ISO tokens (e.g., `due:`, `@2025-01-01`, `~30m`). This ensures CalDAV sync works seamlessly across devices even if one device is in French and another in English.
*   **Dual-Input Parser:** The parser accepts *both* localized terms AND English canonical terms. This prevents breaking muscle memory for existing users and keeps headless CLI scripts language-agnostic.
*   **Lexicon Cache:** `src/model/parser.rs` uses an `RwLock<ParserLexicon>` to cache valid tokens (O(1) lookups) built from the `rust_i18n` JSON files on startup.

### 2.1. Tokens
| Token | Meaning | Example |
| :--- | :--- | :--- |
| `!1` .. `!9` | Priority (1 is highest/most urgent). | `!1` |
| `@` or `due:` | Due date. | `@now`, `@tomorrow`, `@2025-12-31`, `@fri 2pm`, `@next 8` |
| `^` or `start:` | Start date. | `^next week`, `^next 15` |
| `^@` | Sets *both* Start and Due dates. | `^@tomorrow 9am` |
| `~` or `est:` | Estimated duration (supports ranges). | `~30m`, `~1h-2h` |
| `#` | Tag/Category (Supports brace expansion). | `#work`, `#project{sub1,sub2}` |
| `@@` or `loc:`| Location (Supports multiple via <code>&#124;</code>). | `@@office`,  <code>@@aldi&#124;auchan</code> |
| `url:` | Attach a URL. (Any `scheme://` or `mailto:` is supported. Bare URLs default to `https://`). | `url:perdu.com`, `url:https://example.com` |
| `[[ ]]` | Wiki-link to jump to or create a task/page. Use `:` for absolute paths and `+` for relative sub-items. | `[[Master plan]]`, `[[+Child]]`, `[[Project:Phase 1]]` |
| `dep:` or `depends:`| Set dependency (blocks the task). Supports short UIDs or fuzzy matching by summary. | `dep:"Install foundation"`, `dep:abc1234` |
| `rel:` or `related:`| Set related task (sibling). Supports short UIDs or fuzzy matching by summary. | `rel:"Master plan"`, `rel:abc1234` |
| `geo:` | Geo-coordinates. | `geo:50.1,4.2`, `geo:here` (Mobile: Fetches GPS) |
| `- ` or `is:note` | Mark task as a note/header (hides checkbox). | `- Pantry`, `is:note` |
| `desc:` | Append text to the description. | `desc:"Buy milk"` or `desc:{...}` |
| `rem:` | Reminder / Alarm. | `rem:10m`, `rem:in 1h`, `rem:8pm`, `rem:next friday` |
| `done:` | Mark completed / Set percentage. | `done:now`, `done:yesterday`, `done:50%` |
| `spent:` | Log time spent manually. | `spent:1h` |
| `rec:` or `@` | Recurrence (`RRULE`). | `@daily`, `rec:every 2 weeks` |
| `@after` | Relative recurrence (shifts from completion). | `@after 1w`, `@after 2mo` |
| `until` | End date for recurrence. | `@daily until 2025-12-31` |
| `except` | Exclusion dates (`EXDATE`). | `@daily except sat,sun` |
| `col:` | Assign task to a specific collection/calendar. | `col:Personal`, `col:"Work Projects"` |
| `+cal` / `-cal` | Force/prevent companion Calendar Event. | `+cal` |
| `is:pinned` | Pin task to the top of the list. | `is:pinned` |
| `is:permanent` | Mark task as a permanent/continuous tracker. | `is:permanent` |
| `is:page` | Create a Wiki sub-page (VJOURNAL component). | `is:page`, `is:journal` |
| `goal:` | Goal tracking target. | `goal:5/w`, `goal:2h/daily`, `goal:weekly` |

*Rules:* 
* Double prefixes (`##tag`, `@@@loc`) apply metadata but *keep* the word in the display title.
* Use `\` to escape special characters (e.g., `\#not-a-tag`).

### 2.2. Aliases (Macros)
Users can define reusable shortcuts that physically expand into multiple tags, locations, or priorities.
*   *Syntax:* `#gardening := #home:outside, @@garden, !4`
*   Aliases act as one-way text macros. They are resolved retroactively across the database upon creation/edit, meaning the target tags are physically appended to matching tasks. Because provenance (whether a tag was added manually or via alias) is not tracked, removing a tag from an alias definition will *not* remove it from existing tasks to prevent data loss. Cycle detection is strictly enforced (max depth 10).

### 2.3. Markdown Subtask Extraction & Round-Trip Editing (Context-Aware)
If a task's description contains Markdown lists, Cfait extracts actionable items into distinct child tasks whenever the task is saved. 
Users can also use the "Edit Tree" action (or `Ctrl+E`) to edit an entire existing task tree—including the root task's summary, metadata, and subtasks—as a single unified Markdown document.
*   **Document Preservation & Transient Metadata:** For Wiki pages/journals (`is:page`), Markdown Headers (`# Header`) and plain bullets (`- plain text`) are **never** extracted into components. They remain safely inside the `DESCRIPTION` property to avoid shredding long-form notes. For standard tasks (`VTODO`), they *are* extracted into structural `is:note` components to allow rapidly building task hierarchies without managing indentation spaces. However, any smart syntax tags (`#tag`) or locations (`@@loc`) written inside a journal's description body *are* dynamically extracted into transient memory. This ensures the journal page appears under those categories in the Sidebar and Search results, while preventing ghost tags from polluting the permanent CalDAV `CATEGORIES` property.
*   **Actionable Items:** Bullets containing checkboxes (`- [ ] Action item`) are always extracted into distinct actionable `VTODO` components. Supported checkbox states are:
    *   `[ ]` maps to `NeedsAction` (Pending / Unstarted).
    *   `[/]` or `[<]` maps to `NeedsAction` with `percent_complete` at 50% (Paused).
    *   `[>]` or `[▶]` maps to `InProcess` (Timer running).
    *   `[x]`, `[X]`, or `[*]` maps to `Completed`.
    *   `[-]` or `[~]` maps to `Cancelled`.
*   **The Structural Parent Rule:** If you indent an actionable task (`- [ ] subtask`) underneath a plain bullet point (`- Folder`), Cfait recognizes the plain bullet as a structural block and extracts it as an `is:note` component. This preserves the proper parent/child hierarchy.
*   **Context-Aware Wiki Links:** Creating a missing link inherits the component type of where it was clicked (creating an actionable `VTODO` from a task, or a `VJOURNAL` from a page). Standard links (`[[My Page]]`) always search globally and default to root-level creation.
    *   *Override Context:* Use `- [ ] [[My Task]]` to explicitly force an actionable task, or `[[My Page is:page]]` to explicitly force a journal page.
    *   *Hierarchy Paths:* Use `[[Project:Phase 1]]` to define an absolute path (dynamically generating missing ancestors). Use `[[+Subpage]]` to explicitly search for or create a child within the current context.
*   **Sequential Dependencies:** Numbered lists (`1. [ ]`, `2. [ ]`) create `DEPENDS-ON` blocking relationships. If multiple tasks share the same number at the same indentation level (e.g., two `3. [ ]` tasks), they are extracted as parallel steps that both depend on the previous step (`2. [ ]`). Items do not need to be written in sequential order; out-of-order lists are resolved systematically.
*   **Round-Trip UIDs:** Serialized task trees append an inline HTML comment containing a unique identifier (e.g., `<!-- uid:abc-123 -->`) to the end of each task line. Formatting and text without UID comments are parsed into the `DESCRIPTION`.

### 2.4. Inline Markdown Formatting
Cfait natively supports rendering basic inline Markdown across task summaries, descriptions, and the raw text editors.
*   **Supported Syntax:** `**bold**`, `__bold__`, `*italic*`, `_italic_`, `~~strikethrough~~`, `` `code` ``, standard Markdown links `[label](url)`, and bare URLs (any `scheme://` or `mailto:`).
*   **Marker Visibility:** Formatting markers (e.g., `**`, `~~`, `` ` ``) are hidden in read-only views (such as the task list, sidebar, and read-only details) to keep the text clean. The markers are preserved and highlighted in the raw text editors and inputs to ensure a seamless text-based editing experience.

---

## 3. Searching, Filtering, and Sorting

### 3.1. Search Operators & Primitives
The search bar supports a boolean recursive-descent parser.
*   **Logic:** Implicit `AND` (space), `OR` (`|`), `NOT` (`-`), and Grouping `()`.
*   **Primitives:**
    *   *State:* `is:done`, `is:active`, `is:started` / `is:ongoing`, `is:blocked`, `is:note`, `is:page`, `is:canceled` / `is:cancelled`.
    *   *Actionable:* `is:ready` (Excludes completed tasks, explicitly/implicitly blocked tasks, tasks starting in the future, and Notes whose children are all unready. `InProcess` bypasses this).
    *   *Comparison:* `~<30m` (duration < 30m), `!<4` (priority < 4).
    *   *Dates:* `@<today` (Overdue), `^>1w` (Starts in > 1 week).
*   **Match Highlighting:** Search terms are highlighted inline in task titles and descriptions across all clients.
*   **Parent Inclusion:** Search matches include parents of matching tasks in the results, so searching for a subtask surfaces its full ancestry.

### 3.2. Multi-Stage Sorting Algorithm
Tasks sort deterministically by rank (0 to 9), then by Overdue -> Priority -> Due Date -> Start Date -> Summary.
*   **Rank 0:** Pinned (`is:pinned`).
*   **Ranks 1-3 (Urgent/Ongoing/Due Soon):** Order dictated by `sort_preset` (e.g., Urgent > Ongoing > Due Soon).
*   **Rank 4 (Actionable):** Due date `<=` `sort_cutoff_days`.
*   **Rank 5 (Deferred):** No due date, or `>` `sort_cutoff_days`.
*   **Rank 6 (Blocked):** Has unresolved dependencies or parent is blocked.
*   **Rank 7 (Future):** Start date is > `start_grace_period_days`.
*   **Rank 8 (Completed):** Done or Cancelled.
*   **Rank 9 (Trash):** In `local://trash`.

*Rule:* If `sort_standard_by_priority` is enabled, Ranks 4 and 5 merge and sort by numeric Priority first, then Date.
*Rule:* Notes (`is:note`) and Journals (`is:journal`) always sort below actionable tasks within the same rank, and automatically drop to Rank 8 if their dates are in the past.
*Rule:* Note and journal sorting is symmetric — overdue notes are ranked as completed to drop them to the bottom of the list, mirroring the behavior for actionable tasks.

---

## 4. Core Business Workflows

### 4.0. Undo / Redo & Smart Commands
All clients maintain an active session Undo/Redo stack. Every task mutation applied to the `TaskStore` pushes an `UndoRecord` (containing the exact inverse journal actions derived from pre-mutation snapshots).
*   **Android:** Mutations trigger a transient Snackbar allowing 1-tap Undo. Markdown editors feature explicit ↶/↷ toolbar buttons.
*   **Desktop (GUI/TUI):** Global `Ctrl+Z` (Undo) and `Ctrl+Y` / `Ctrl+Shift+Z` (Redo) shortcuts.
*   **Smart Commands:** If the Add Task input starts with `:` and contains no spaces (e.g., `:undo`, `:redo`, `:empty-trash`), it is intercepted and executed as a session command rather than creating a task. 
*   **Auto-Complete:** The `CursorContextBanner` acts as a unified auto-complete engine, suggesting commands (when typing `:`), tags (when typing `#`), locations (when typing `@@`), collections (when typing `col:`), and relationships (when typing `dep:`, `rel:`, or `[[`). Suggestions are typically ordered by exact prefix match, then by descending frequency/usage, and finally alphabetically.

### 4.1. The "Yank" Relationship System
Instead of drag-and-drop, Cfait uses a robust "Yank" (Clipboard) system for hierarchy management.
1.  **Yank (`y` / Action Menu):** Copies the selected task's UID to an internal "Yanked" state. UI displays a persistent banner.
2.  **Relate:** Select a *target* task and execute:
    *   `c` (Child): Target becomes a subtask (child) of Yanked.
    *   `b` (Block): Target becomes blocked by Yanked.
    *   `l` (Link): Target becomes related (sibling) to Yanked.
3.  **Clear (`Esc`):** Clears yank state. (`Y` locks the yanked state for multiple relations).

### 4.2. Recurrence Recycling & DST Safety
When completing a recurring task:
1.  Running timers commit to `time_spent_seconds`.
2.  A **History Snapshot** is generated (`X-CFAIT-HISTORY-OF: parent_uid`) with the completion date. This snapshot is non-recurring and retains no alarms.
3.  Master task dates advance to the next occurrence based on the `RRULE`.
4.  *DST Rule:* Absolute alarms advance using Local Naive time math. (A 9:00 AM alarm stays 9:00 AM across DST shifts).
5.  *Relative Recurrence:* If `@after 1w` (or Shift+Complete), the master task's base date temporarily shifts to `now` before advancing.
6.  *Completed* subtasks/descendants of the recurring task reset to `NeedsAction`.

### 4.3. Virtualization & Truncation (Completed Groups)
*   If completed subtasks exceed `max_done_subtasks` (or roots exceed `max_done_roots`), the Model injects a **Virtual Expand/Collapse Row** into the flattened task list.
*   Selecting this virtual row toggles visibility of the hidden completed items. State is transient (in-memory only).
*   **Tree Navigation & Expansion (Tags, Locations, Tasks)**
    *   Tags and Locations automatically expand transiently to reveal their active selection, returning to their configured collapsed state when unselected.
        *   **Search & Filter Context:** When searching or filtering by tags/locations, the task tree is filtered to show exact matches alongside their full ancestry and descendants.
            *   *Direct Matches:* Tasks that explicitly match the active filters.
            *   *Descendants:* All subtasks of a direct match are fully visible and treated as matches (inheriting the parent's context).
            *   *Ancestors (Context):* Parent tasks all the way to the root are included to provide structural context, but are visually dimmed (`is_search_context = true`).
            *   *Unrelated Siblings:* Branches without any matches are completely hidden.
        *   During active searches or filtering, all matching task trees are automatically expanded. Users can manually collapse them, but this state is overridden on new queries.
    *   **Android Home-Screen Widget:** The task list widget can optionally respect the user's fold/unfold state via a "Respect fold/unfold state" toggle in the widget configuration screen (default on). When enabled, `respect_tree_collapse = true` is passed in `MobileFilterOptions` so collapsed task trees stay collapsed despite the widget's `is:ready` search query. The fold/unfold indicator is tappable and dispatches `ToggleTreeCollapse`, mirroring the main app's tree state.

### 4.4. Companion Events (Calendar Integration)
If `create_events_for_tasks` is enabled or `+cal` is used:
*   Generates `.ics` `VEVENT` files and `PUT`s them alongside the `VTODO`.
*   Start/Due ranges > 1 day apart split into `-start` and `-due` events.
*   WorkSessions emit as distinct events (`-session-0`).
*   `EXDATE`s sync to the event so skipped instances disappear from the user's agenda.
*   *Android Note:* Handled reliably via `CalendarSyncWorker` (WorkManager).

### 4.5. Goals & Habit Tracking
Goals act as quotas or habits and can be applied globally or locally.
*   **Global Goals:** Mapped to tags/locations using aliases (e.g., `#reading := goal:2h/w`). They appear in the Goals sidebar tab.
*   **Task-Specific Goals:** Defined directly on a task (e.g., `Read book goal:2h/w`). They replace the task's duration badge with a progress tracker. If `show_task_goals_in_sidebar` is true, they also appear under the Goals tab.
*   **Progress & Heatmaps:** Progress is calculated dynamically by summing `WorkSession` overlaps and completion dates within the calendar interval. The last 7 intervals are evaluated and rendered as a Heatmap sparkline (e.g., `■■□■■■□`) across all UI clients.
*   **Subtree Aggregation:** A goal matches a task if the task or any ancestor carries the matching tag/location (or, for `task:`-specific goals, if the task is or descends from the target). A tagged parent's goal naturally covers all work in its subtree — untagged subtasks' time flows up to the nearest tagged ancestor.
*   **Cascade Dedup:** Starting a subtask auto-starts all ancestors, producing overlapping `WorkSession`s on both the subtask and its parents. For Duration goals, all sessions from claimed tasks are union-merged, so overlapping cascade sessions collapse into a single interval — each second of work counts exactly once. For Count goals, sessions are counted per-task: a parent's session fully covered by a descendant's overlapping session is skipped (cascade artifact), but non-overlapping sessions on both parent and child count independently.
*   **Effective Goals:** Recurring tasks (`RRULE`) inherently generate a `1/period` count goal automatically to feed the Heatmap renderer, even if no explicit `goal:` token is set.
*   **Implicit Credit:** If a task with an `estimated_duration` is completed *without* explicitly running a timer, the remaining estimated time is granted instantly as goal progress. Logging a session fulfills "Count" goals if `sessions_count_as_completions` is true.

### 4.6. Permanent / Continuous Tasks
Tasks tagged with `is:permanent` act as endless trackers. When checked off (Completed), they do not change status. Instead:
1. If a timer is running, it is committed as a work session.
2. If no timer is running, a session is logged using the task's `estimated_duration` (or the default goal duration).
3. The task remains in `NeedsAction` state.

### 4.7. Alarms & Reminders
*   **AlarmIndex:** Optimized cache `alarm_index.json` stores upcoming triggers.
*   **Implicit:** Auto-generated alarms for Due / Start dates (if `auto_reminders` is true).
*   **Snoozing:** Snoozing acknowledges the original alarm and creates a new absolute alarm linked via `RELATED-TO;RELTYPE=SNOOZE`.
*   **Just-In-Time (JIT) Sync:** To prevent phantom alarms across devices, clients must attempt a synchronous network fetch immediately prior to firing an alarm (or within a 15-second pre-fire window). If the task was completed, canceled, or the alarm's trigger time was advanced (via recurrence) on another device, the local alarm is pruned before notifying the user.
*   *Android Implementation:* Uses `AlarmManager.setExactAndAllowWhileIdle`. When an alarm fires, an `AlarmWorker` executes a foreground `api.sync()` before posting a Notification. Notification Actions (Snooze, Done, Pause) are handled via `NotificationActionReceiver` which delegates back to a unique `WorkManager` request to prevent background ANRs.

---

## 5. UI Layout & Platform Specifics

### 5.1. Desktop Graphical User Interface (GUI)
*Powered by `iced`. Optimized for mouse & keyboard.*
*   **Layout:** 3-pane layout (Sidebar, Main List, Markdown Details Pane).
*   **Cursor Context Banner:** Raw text editors feature a dynamic banner that instantly resolves UIDs (`dep:`, `rel:`, `[[...]]`) into task summaries when the text cursor is placed on them.
    *   *Open via Ctrl+Click:* Ctrl+click (Cmd+click on macOS) a `[[wiki link]]` or URL in a text editor to open it, mirroring the TUI's `Ctrl+O`. Wiki links resolve to the target task or create the missing page in context; URLs open externally.
*   **Window:** Client-Side Decorations (Custom frameless window, resize grips) unless `--force-ssd` is passed.
*   **Zooming:** Global scale via `Ctrl++`, `Ctrl+-`, and `Ctrl+ScrollWheel`. Middle-click resets.
*   **Mouse Interactions:**
    *   *Single Click:* Select row.
    *   *Double Click:* Triggers `EditTaskStart` (focus title input).
    *   *Right Click:* Opens **Full Context Menu** at cursor coordinates.
    *   *Ellipsis (`...`) Click:* Opens **Partial Context Menu** anchored to the button (shows unpinned actions).
*   **Modals:** Hovering overlays with dimmed backdrops (Move Task, ICS Import, Alarm Notification).
*   **Privacy Mode:** When `blur_when_unfocused` is enabled, the window content is blurred when the app loses focus, preventing shoulder-surfing.
*   **Tooltips:** Any GUI button that has an associated keyboard shortcut must include that shortcut in its tooltip (when applicable).

### 5.2. Terminal Interface (TUI)
*Powered by `ratatui`. Keyboard-only paradigm.*
*   **Layout:** 2-Pane (Sidebar 20%, Main List 80%). Details view shares vertical space with Main List. Press `Shift+Up/Down` to scroll the active details pane without losing focus on the list.
*   **Modals/Popups:** Instead of context menus, pressing `Enter` on a task opens a centered **Action Menu** popup with fuzzy filtering. 
*   **Details Viewer (`L`):** Unified popup containing the full markdown description, History/Heatmaps, WorkSessions, and relationships (Parents, Children, Blockers, Successors, Siblings) for quick jump navigation.
*   **Session Manager (`T`):** Popup to view/delete `WorkSession` records.
*   **External Editor:** Pressing `E` launches `$VISUAL`/`$EDITOR` (suspending the TUI), falling back to the built-in modal if empty.

### 5.3. Mobile Interface (Android)
*Powered by Jetpack Compose. Touch-optimized.*
*   **Layout:** 
    *   *Top Bar:* Random Jump, Quick Filter, Search toggle, Refresh/Sync, Settings.
*   **Cursor Context Banner:** Raw text editors feature a dynamic banner that instantly resolves UIDs (`dep:`, `rel:`, `[[...]]`) into task summaries when the text cursor is placed on them.
    *   *Open resolved links:* When the caret is on a `[[wiki link]]` that resolves to an existing task, the banner becomes tappable to navigate to it (partial links still show autocomplete to finish the link). Wiki links and URLs in task titles and inline descriptions are also tappable.
    *   *Tabs:* Desktop "Sidebar" is translated into horizontal `HorizontalPager` tabs. Pull-to-refresh triggers manual sync.
    *   *Navigation Drawer:* Swipe from the left edge to switch between Calendars, Tags, Locations, Goals view modes. (Swipe logic uses custom pointer interception to avoid conflicting with tab paging).
*   **Task List Rendering:** `LazyColumn`. Real-time relative duration formatting via coroutines (`liveDurationMins`). Real-time syntax highlighting in input via `VisualTransformation`.
*   **Task Details:** Tapping a task navigates to a dedicated `TaskDetailScreen`. Includes an "Edit Tree" action for full-screen Markdown tree editing.
*   **Context Menu:** Long-pressing a row opens the full Dropdown Menu.
*   **Location Integration (`geo:here`):** If a user types `geo:here`, the UI requests permissions and invokes `LocationManager.getCurrentLocation`. If it fails within 5s, falls back to the last known location.
*   **Notifications:** 
    *   *Ongoing Tasks:* Generate a persistent, swipable notification with a live Chronometer and "Pause"/"Done" actions.
    *   *Alarms:* High-priority. Includes inline "Snooze Custom" via `RemoteInput` text reply.
*   **Intents:** Intercepts `ACTION_VIEW` for `.ics` files to launch the Import Screen.
*   **Debug Export:** UI includes an advanced option to generate a zip of `cache/`, `data/`, `config/`, and `android_crash.txt`, sharing it via `ACTION_SEND`.
*   **AMOLED Black Theme:** A pure-black color variant for OLED screens, selectable from the theme picker.
*   **Top Bar Position:** Configurable to top or bottom via settings (issue #31).

### 5.4. Journal & Wiki Pages (all clients)
Daily notes and wiki pages are `VJOURNAL` components (see 1.2). They share a unified UI across all three clients:
*   **Journal Tab:** A sidebar tab (toggled by `show_journal_tab`) that anchors notes to dates. Selecting a date opens its daily note alongside an activity panel showing tasks due, started, completed, or worked on that day.
*   **Wiki Index:** Wiki pages (notes without `DTSTART`) appear in a tree view under the Journal tab. Pages can be nested hierarchically via `[[Parent:Child]]` links and collapsed/expanded with `z` (TUI/GUI).
*   **Page Creation:** Typing `[[My Page]]` in any text editor creates the page if it doesn't exist. The component type is inherited from the context (actionable `VTODO` from a task, `VJOURNAL` from a page). Use `is:page` or `is:journal` to force the type explicitly.
*   **TUI Journal Navigation:** When the Journal tab is active, `j`/`k` (or arrow keys) navigate the page list, `Enter` opens the selected page for editing, and `z` collapses/expands the wiki tree.
*   **Android Journal:** A month-grid calendar view with daily-note indicators; tapping a day opens its note. Pages can be moved between dates via the context menu.

---

## 6. Keyboard Shortcuts (GUI & TUI)

*   **Navigation:** `j`/`k` or `Up`/`Down` (Select), `Tab` (Cycle focus between Sidebar, List, Input). `1..5` (Switch Sidebar tabs: 1:Collections, 2:Tags, 3:Locations, 4:Goals, 5:Journal). From text fields, use `Ctrl+1..5` instead.
*   **Main Actions:** 
    *   `Space`: Toggle Done/NeedsAction.
    *   `Shift+Space`: Complete & Shift recurrence (Relative advance).
    *   `s`: Start/Pause timer.
    *   `S`: Stop/Reset timer.
    *   `x`: Cancel task.
    *   `+` / `-`: Increase/Decrease priority.
    *   `e`: Edit title. `E`: Edit description (Markdown). `Ctrl+E`: Edit tree (Markdown) / Switch editor mode. `Ctrl+N`: Create new task with description. `Ctrl+M`: Maximize/Restore description editor.
    *   `Delete`: Move to trash. `Ctrl+Delete`: Delete entire tree.
    *   `M`: Move task (or task tree) to another collection.
    *   `t`: Log time session manually.
    *   `Ctrl+Z` / `Ctrl+Y` / `Ctrl+Shift+Z`: Undo / Redo.
*   **Tree/Relationships:** 
    *   `z`: Fold/Unfold tree.
    *   `>` / `.` : Demote (Indent / Make child of previous).
    *   `<` / `,` : Promote (Outdent / Move one level up).
    *   `L` : Open relationship browser.
    *   `o`: Open URL attached to the selected task.
    *   `Ctrl+O` (TUI): Open the wiki link or URL under the text cursor.
*   **App Actions:** 
    *   `/`: Focus search.
    *   `a`: Focus add task.
    *   `w`: Toggle Quick Filter.
    *   `m`: Toggle Match AND/OR logic for sidebar tags.
    *   `H`: Toggle Hide Completed.
    *   `*`: Clear all filters.
    *   `Shift+R`: Jump to random actionable task (weighted by priority).
    *   `Ctrl+,`: Settings.

---

## 7. Command Line Interface (CLI)
Used for headless automation, scripting, and piping. Operates directly on the `TaskStore`.

*Note on `<uid>` arguments:* Any CLI command accepting a `<uid>` also accepts partial UIDs, exact titles, partial summaries, or wiki-links (e.g. `[[My Task]]`). If a match is ambiguous, the CLI will output the matching options and exit.

*Global flags:* Most mutation commands accept `-n` / `--no-wait` (queue to journal and exit without syncing) and `-w` / `--wait` (block until network sync completes).

*   `cfait add` (alias: `create`) `<task...>`: Smart input task creation. Flags: `-c <href>`, `--desc <text>`, `-p <uid>` (set parent), `-n`, `-w`.
*   `cfait append <uid> <task...>`: Appends smart syntax tokens (tags, dates, deps, etc.) or text to an existing task. Flags: `--desc <text>` (appends to existing description), `-n`, `-w`.
*   `cfait edit <uid> [--tree]`: Opens an external editor (`$VISUAL`/`$EDITOR`) to edit the task's properties. Pass `--tree` to edit the entire task tree as a single Markdown document.
*   `cfait replace <uid> <task...>`: Replaces the entire task summary and metadata. To safely add tags or dates without losing the title, use `append`. Flags: `--clear-due`, `--clear-start`, `--clear-tags`, `--clear-loc`, `--clear-deps`, `-p <uid>`, `--clear-parent`, `--desc <text>`, `--file <path>` (replaces from markdown file), `--tree` (when used with `--file`, replaces entire tree), `-n`, `-w`.
*   `cfait list [--all] [--json] [-c <id>] [-p <uid>]`: Outputs task tree (use `-p` to focus on a specific sub-tree).
*   `cfait search <query> [--all] [--json] [-c <id>] [-p <uid>]`: Searches and outputs tasks within a specific sub-tree.
*   `cfait view` (alias: `show`) `<uid> [--json]`: Outputs detailed task info.
*   `cfait tree <uid>`: Views the task tree starting at `<uid>` serialized into markdown format (same format used by the `Ctrl+E` editor).
*   `cfait start|pause|toggle|done|complete <uid>`: State mutation commands.
*   `cfait move` (alias: `mv`) `<uid> <collection> [--tree]`: Moves a task to a different collection.
*   `cfait delete` (alias: `rm`) `<uid>`: Moves task to trash.
*   `cfait export [--collection <id>]`: Dumps collection (local or remote) as standard ICS to stdout, including VTODO and VJOURNAL components. The collection `id` can be a local collection name, a full HREF, or a remote collection name.
*   `cfait import <file.ics> [--collection <id>]`: Parses and imports ICS to store. Supports both local and remote collections; for remote collections, tasks are journaled and synced. Handles both VTODO and VJOURNAL components.
*   `cfait sync`: Foreground network sync.
*   `cfait daemon`: Runs a continuous background sync loop based on `auto_refresh_interval_mins`. Acquires a cross-process lock to prevent overlapping syncs with UIs.
*   `cfait collection list [--json]`: Lists CalDAV collections.
*   `cfait collection create <name> [--color #hex]`: Creates a new collection.
*   `cfait collection edit <href> --name <name> [--color #hex]`: Edits a collection's display name or color.

---

## 8. Configuration (`config.toml`)
All persistent state and settings live here. Unrecognized TOML keys must not be dropped during serialization.

**Data location:**
*   `data_dir`: String (Optional). Absolute or `~/`-relative path overriding where cfait stores its data files (e.g. `local.json`, `journal.json`, `alarm_index.json`) instead of the XDG default (`~/.local/share/cfait`). Read before any other setting so the data directory can be relocated (e.g. into a syncthing-managed folder) without moving config or cache. Only the data directory is affected; config and cache stay at their XDG defaults.

**Connection & Sync:**
*   `url`, `username`: CalDAV credentials. *(Password vaulted in OS Keyring).*
*   `tls_client_cert_path`, `tls_client_key_path`: Strings (Optional). Paths to PEM-encoded certificate and private key for mTLS.
*   `allow_insecure_certs`: Boolean.
*   `sync_settings`: Boolean. Enables the `cfait-global-settings-v1` hidden VTODO sync.
*   `auto_refresh_interval_mins`: Integer. Daemon sync loop interval.
*   `trash_retention_days`: Integer. Days before `local://trash` items are permanently purged. (0 = disable trash).

**UI & Behavior:**
*   `default_calendar`: String HREF.
*   `enable_local_mode`: Boolean. Allow offline `local://` collections.
*   `hide_completed`, `hide_fully_completed_tags`, `hide_aliases_in_sidebar`: Booleans.
*   `blur_when_unfocused`: Boolean. Privacy mode — hides task content when the window loses focus.
*   `strikethrough_completed`: Boolean. Line-through styling for done tasks.
*   `show_inline_descriptions`: Boolean. Previews up to 3 lines of the description in the list.
*   `ui_scale`: Float (0.5-3.0). Global zoom.
*   `theme`: Enum (RustyDark, Light, Dracula, Nord, Catppuccin variants, etc.).
*   `language`: String (`en`, `fr`). None = system locale.
*   `first_day_of_week`: Enum (`Monday`, `Sunday`). Controls the first day in calendar/journal week views.
*   `description_editor`: String. CLI command for TUI description editing. `builtin` forces internal UI editor.
*   `show_ongoing_notifications`, `show_priority_numbers`, `sidebar_is_hidden`, `show_task_goals_in_sidebar`: Booleans.
*   `show_calendars_tab`, `show_tags_tab`, `show_locations_tab`, `show_goals_tab`, `show_journal_tab`: Booleans. Toggle individual sidebar tab visibility. On Android, these live under "More settings" (advanced settings), not "Manage collections".
*   `show_undo_snackbar`: Boolean. Show the transient undo notification after task mutations (Android).
*   `pinned_actions`: Array of `TaskAction` enums. Dictates buttons pinned directly to GUI task rows.
*   `log_level`: Enum (`Error`, `Warn`, `Info`, `Debug`, `Trace`). Logging verbosity for both log file and terminal.

**Sorting & Limits:**
*   `sort_preset`: Enum (`UrgentStartedDue`, `UrgentDueStarted`, `StartedUrgentDue`).
*   `paused_sort_behavior`: Enum (`tiebreak`, `top`, `none`). Defines how paused tasks sort against unstarted ones. Default is `tiebreak` (wins ties within the same rank/priority).
*   `sort_tiebreak_recent`: Boolean. If true, ties in sorting are broken by recently modified rather than alphabetical.
*   `sort_cutoff_days`: Integer/None. Rank 4 vs 5 divider.
*   `sort_standard_by_priority`: Boolean. Merge ranks 4/5.
*   `urgent_days_horizon`: Integer. Tasks due within X days are "Urgent" (Rank 1-3).
*   `urgent_priority_threshold`: Integer (1-9). Priorities <= X are "Urgent".
*   `default_priority`: Integer (1-9). Maps `!0` to this.
*   `start_grace_period_days`: Integer. Show future tasks X days before they start (Rank 7).
*   `max_done_roots`, `max_done_subtasks`: Integers. Triggers Virtual Expand/Collapse rows.

**Data & Events:**
*   `create_events_for_tasks`, `delete_events_on_completion`: Booleans for VEVENT generation.
*   `default_duration_goal_mins`: Integer. Implicit duration credit for checked-off tasks without an estimate.
*   `sessions_count_as_completions`: Boolean. Logging time counts towards `Count` goals.

**Reminders:**
*   `auto_reminders`: Boolean. Implicit alarms for Due/Start.
*   `default_reminder_time`: String (HH:MM). Default time for all-day date alarms.
*   `snooze_short_mins`, `snooze_long_mins`: Integers for quick snooze preset buttons.

**Quick Filters & State:**
*   `quick_filter_term`, `quick_filter_icon`, `show_quick_filter`: Quick filter button settings.
*   `hidden_calendars`, `disabled_calendars`: Arrays of HREFs.
*   `expanded_tags`, `expanded_locations`: Arrays mapping visual tree expansion states.
*   `tag_aliases`: HashMap of Alias Key -> Array of Tags/Locations.
*   `goals`: HashMap of Goal Key -> Goal Object.
*   `collection_order`: Array of HREFs defining the custom display order of collections.
*   `sort_collections_by_size`: Boolean. Automatically sort collections from most to least tasks. Trash and Recovery collections are always shown below standard collections regardless of their task count.