Documentation Index Fetch the complete documentation index at: https://docs.canthus.org/llms.txt
Use this file to discover all available pages before exploring further.
Temporal task types
Deadline task Flexible completion by a due date/time. Mana is spent on the day it is completed.
Scheduled task Fixed event on a specific date/time. Mana is effectively committed to that day.
Horizon window
The horizon window determines how early a temporal task starts surfacing.
baseCost = relativeCost x durationMinutes x personalCoefficient x 0.5
typicalPool = 30-day median of poolEwma
horizonDays = clamp(ceil(baseCost / (typicalPool x 0.30)), 2, 7)
Task cost as % of typical pool Horizon window < 30% 2 days 30-60% 2-3 days 60-90% 3 days 90-120% 4 days 120-180% 4-5 days 180%+ 6-7 days
When inside horizon window:
Task becomes visible regardless of remaining pool
Card uses horizon framing copy
Scheduled tasks contribute to pre-warning logic
Cost preview framing
Future-day previews always use axis factor = 1.0:
“On a typical day this costs about [X] mana.”
This prevents false precision for unknown future states.
Deadline copy in horizon window
Days remaining Copy 3+ days ”This needs to happen by [Day] - on a typical day it costs about [X] mana.” 2 days ”This needs to happen by [Day] - on a typical day it costs about [X] mana.” 1 day ”This needs to happen by tomorrow - on a typical day it costs about [X] mana.” 0 days, in pool ”This is due today - on a typical day it costs about [X] mana.” 0 days, over pool ”This is due today and costs more than today’s mana. It may need to be your priority.”
“DUE” is not used as all-caps urgency language in user copy. Preferred phrasing is “needs to happen by” and “due today”.
Surfacing logic
Surfacing rules are policy-driven. The defaults below are the recommended profile, but teams should treat visibility behavior as user-configurable and wire those choices into onboarding.
Configurable policy surface
These policy switches should be selectable in onboarding and editable later in Settings:
Standard tasks over pool: hide (default), showWithCaution, showAlways
Scheduled tasks on due day when over pool: show (default), hideWhenOverPool
Mid-day refresh behavior: dynamic (default, hide/reveal as remaining pool changes), morningSnapshot (fixed list for that day)
Deadline tasks
if timingType == 'deadline':
if today >= dueDatetime - horizonDays:
always surface (pool exemption)
else:
standard surfacing (cost <= remainingPool)
Scheduled tasks
if timingType == 'scheduled':
if today == dueDatetime:
surface as active/completable
elif today >= dueDatetime - horizonDays:
surface with horizon framing, not completable
else:
hidden
The snippet above reflects default policy values. If onboarding preferences differ, the surfacing layer applies the selected policy at runtime.
Current app surfacing surfaces (March 12, 2026)
There is no dedicated Home surface in the current app shell. Temporal surfacing is currently consumed via:
Tasks tab list (app/lib/ui/tasks/widgets/tasks_screen.dart)
Orchard tab list for orchard-tagged surfaced tasks (app/lib/ui/orchard/widgets/orchard_screen.dart)
Mana tab upcoming notices (app/lib/ui/mana/view_models/mana_viewmodel.dart)
Primary executable rule coverage for these surfaces currently lives in:
app/test/domain/mana/engine/surfacing/task_surfacing_service_test.dart
app/test/ui/tasks/widgets/tasks_screen_test.dart
app/test/ui/orchard/widgets/orchard_screen_test.dart
app/test/ui/mana/widgets/mana_screen_test.dart
Scheduled copy in horizon window
Days remaining Copy 2+ days ”You have [Task Name] on [Day] - on a typical day it’ll use about [X] mana.” 1 day ”You have [Task Name] tomorrow - on a typical day it’ll use about [X] mana.” 0 days Standard task card; horizon copy removed
Day-before pre-warning
For scheduled tasks, show a quiet contextual note if significant load is coming.
Single-task trigger:
baseCost > typicalPool x 0.20
Multi-task conflict escalation:
sum(baseCost on dueDatetime) > typicalPool x 0.85
Lookahead runs across 7 days so warnings can appear early enough for planning.
UI differentiation
Type Icon Date label Deadline outline diamond by Thursday Scheduled solid calendar dot Thursday Scheduled with time solid calendar dot Thursday, 2:00pm
Deadline iconography should feel softer/flexible; scheduled should feel fixed.
Recurring tasks
Storage model
Root Task stores recurrence rule (RRule) and timing type
TaskOccurrences stores canonical per-instance due/state rows
Future recurring due slots are generated in the active horizon read window and persisted idempotently, then matched against existing rows
Runtime query shape:
dueSlots = generateFromRRule(rule, horizonStart, horizonEnd)
persistedRows = upsertMissingByDeterministicKey(dueSlots)
occurrences = merge(dueSlots, persistedRows)
activeOccurrence = nearest unresolved future dueDatetime
Only nearest unresolved future occurrence is surfaced. Missed recurring cycles are skipped automatically.
Recurrence setup UI
Two-step interaction:
Frequency type: every few days, weekly, every few weeks, monthly
Refinement: interval/day toggles depending on choice
Complex edge patterns are intentionally excluded to reduce cognitive burden.
Recurrence setup nudge
If baseCost > typicalPool x 0.25, show once during recurrence setup:
“This task costs about [X] mana on a typical day - on recurrence days, it’ll take a meaningful part of your budget.”
Informational only; never blocks setup.
Post-deadline state
State Meaning Source completeddone user action misseddue date/time passed without completion automatic cancelledwill not happen / called off user action
cancelled is available for all task types.
Partial completion
A user may mark a task as partially completed when they can do only a fraction of the work.
Stored as partialCompletionFraction (0.0–1.0) on TaskOccurrence
Occurrence remains state = active (not completed) until fully done or explicitly completed
Mana cost shown = baseCost × (1 - fraction) - the remaining effort only
On save, the UI prompts: “Defer the rest to tomorrow?” - auto-creating a deferred occurrence
No punitive framing; partial completion is presented as normal pacing behaviour
Recurrence exceptions
Three edit scopes apply to recurring task occurrences:
Scope Mechanism Skip this occurrence Set state = cancelled on the specific TaskOccurrence Edit this occurrence only Set dueDatetimeOverride on the specific TaskOccurrence (shifts effective due time) Edit this and all future EXDATE the current slot in the root task’s RRULE; create a new sibling task from that date with the modified rule
dueDatetimeOverride takes precedence over dueDatetime for all scheduling and surfacing calculations. It does not change the occurrenceKey (which is still keyed to dueDatetime).
EXDATE lines are stored in the task’s recurrenceRule field alongside DTSTART and RRULE:
DTSTART:20260505T090000
RRULE:FREQ=WEEKLY;BYDAY=MO
EXDATE:20260512T090000
Missed-state copy contract
Missed temporal states must remain actionable without moralized framing.
Allowed framing: “missed”, “still needs attention”, “scheduled item was missed”
Avoided framing: “failed”, “you should have”, “behind”, all-caps urgency
Actions remain available so users can recover without punitive UI
Read next