Status
Domain modelling complete. This issue is the parent synthesis. Engineering work is split across child issues; only the v1 plumbing pair is in scope for Phase 1.
Full proposal: docs/proposals/blockers-and-contexts.md.
Children
v1 plumbing (Phase 1):
Out of v1, awaiting clarity:
Deferred (post-v1, future phases):
Modelling synthesis
The original framing collapsed two distinct concepts into "polymorphic blockers." Modelling pulled them apart.
Blockers vs Contexts
Blockers attach to Task (the outcome). Describe outside-the-user world-state relevant to the outcome. Coexist with the Task's current NextAction — the user can act alongside the wait.
- PersonBlocker (v1): collapsed to
TodoTag(type='person'). No separate entity. Existence of the tag link is the wait; deletion clears it. No cleared_at, no notes field — both dissolved on inspection (Phase 4 / lives-in-description respectively).
- TaskBlocker (out of v1): designed (live-predicate clearing, cycle prevention, cascade-on-trash) but not built. Held for more lived-experience signal — the Blocker-vs-Project framing isn't settled, and v1 has no UX consumer for it.
Contexts attach to NextAction (the act). Describe predicates over current world state — "is now a moment when this action is doable?" Gate visibility of NextActions rather than coexisting with them.
- TimeContext and LocationContext — deferred to future phases.
Reclassifications from the original epic
- TimeBlocker(specific) ("after Nov 30") → TimeContext. Predicate-shaped, not event-shaped.
- Time pre-conditions vs deadlines: silently conflated in the original epic. Now split. "By Nov 30" = deadline = property of the outcome (lives on Task as
due_date). "After Nov 30" = pre-condition = property of an action (TimeContext).
- Person identity: PersonBlocker reuses
Tag(type='person') rather than introducing a Person entity.
Adjacent decisions surfaced during modelling
These shaped the model and live in the children's scope:
- Outcome-over-action is a core design tenet. Task = persistent outcome; NextAction is the moving part.
- NextAction is a lightweight cursor, not a typed entity with its own state machine.
- Future actions live in freeform Task notes, not as structured entities.
- Task long-term states:
active, someday, done, trashed. No long-term abandoned.
- Daily plan immutability: intra-day demotion is a UI affordance, not a state. Evening shutdown force-resolves to Rollover / Back-to-Next / Someday.
- Clarify vs organise: only clarifying stamps
last_clarified_at. Adding/removing person-tags (Blocker change) clarifies; adding/removing organising-type tags does not.
- Inline clarify is offered, never required: completion and clarification are decoupled.
v1 deferrals
Out of scope (this epic)
References
Status
Domain modelling complete. This issue is the parent synthesis. Engineering work is split across child issues; only the v1 plumbing pair is in scope for Phase 1.
Full proposal:
docs/proposals/blockers-and-contexts.md.Children
v1 plumbing (Phase 1):
TodoTag(type='person')— schema + status row + Waiting List)last_clarified_at+ derived predicates)Out of v1, awaiting clarity:
Deferred (post-v1, future phases):
Modelling synthesis
The original framing collapsed two distinct concepts into "polymorphic blockers." Modelling pulled them apart.
Blockers vs Contexts
Blockers attach to Task (the outcome). Describe outside-the-user world-state relevant to the outcome. Coexist with the Task's current NextAction — the user can act alongside the wait.
TodoTag(type='person'). No separate entity. Existence of the tag link is the wait; deletion clears it. Nocleared_at, no notes field — both dissolved on inspection (Phase 4 / lives-in-description respectively).Contexts attach to NextAction (the act). Describe predicates over current world state — "is now a moment when this action is doable?" Gate visibility of NextActions rather than coexisting with them.
Reclassifications from the original epic
due_date). "After Nov 30" = pre-condition = property of an action (TimeContext).Tag(type='person')rather than introducing a Person entity.Adjacent decisions surfaced during modelling
These shaped the model and live in the children's scope:
active,someday,done,trashed. No long-termabandoned.last_clarified_at. Adding/removing person-tags (Blocker change) clarifies; adding/removing organising-type tags does not.v1 deferrals
Tag(type='context')rows stay as-is until Contexts land.Out of scope (this epic)
intentenum, FSM retirement, FocusSession refactor — covered separately.References
docs/proposals/blockers-and-contexts.md.blocked_by_todo_id).