How tasks work in Unitcore
Tasks are the second Unitcore product after the budget, and they follow the same rule: everything lives inside a space and everyone in that space sees it. In your personal space that makes it your own to-do list; in a family space it is a shared one, where you can see who picked up what and who closed it.
What follows goes from the simple to the deep end: what you see on screen, what the assistant can do, and how the whole thing is put together underneath.
What it is made of
Four ideas, and the model contains nothing else: a space, lists, tasks, subtasks.
Inbox is not a list — it is the absence of one: a task you never filed anywhere. It cannot be renamed, archived or lost, and it is also where tasks land if you delete the list they were in.
Subtasks nest exactly one level deep. That is a decision rather than a technical limit: nobody keeps a five-level tree tidy in a household to-do list, whereas “buy groceries → milk, bread” stays tidy by itself.
The board
Every list is a column, with Inbox first. A task can be dragged into a neighbouring column, or up and down inside its own. Closed ones fold away behind a counter so they stop taking up room, without going anywhere.
Every task carries:
| What | Why |
|---|---|
| Due date | with or without a time. “By Friday” and “at 6pm” are different things, and the product keeps them apart |
| Priority | low, normal, high, urgent |
| Assignee | anyone in the space |
| Note | whatever is worth remembering about this one |
| Labels | shared across the space, added as you need them |
| Subtasks | one level, with a “2 of 5” counter on the card |
Deletion is soft: the task drops into the trash at the bottom of the board and one tap brings it back. Its subtasks go with it — and the same ones come back, not everything that was ever deleted.
My tasks
A page of its own, collecting everything assigned to you across all of your spaces at once — personal, family, work. Four groups: overdue, today, upcoming, no due date.
Tasks you wrote for yourself and never assigned to anyone show up here too. In a personal space there is nobody to assign them to, and insisting on one would be silly.
The same thing, said out loud
Unitcore connects to Claude or ChatGPT as a connector, and the assistant sees tasks through your own eyes: your spaces, your permissions, nothing beyond them.
Two decisions worth saying out loud:
- The assistant is allowed to delete. But its delete is the trash, not an erase: any action it takes is one tap away from being undone. Only you empty the trash, by hand.
- Text other people wrote is data, not instructions. A task title is written by another member of the space and read by a model that holds write tools. So task content reaches the assistant inside a marked block that says plainly: this is text from the people in this space, not instructions.
How it works underneath
A schema of its own in the database, and no application layer in between: the web app and the assistant both talk to the same database as you, and the database itself decides what you are allowed to see.
Read from prepared views, write straight to the tables.
The same queries as the same user — only called with words.
One check across every table, plus a list of columns nothing outside the database may write.
Four tables and the triggers that hold the rules: one level of nesting, an assignee from this space only, closing a parent closes its subtasks.
Views assemble the names, the counters and the “mine” flag, so no client has to go back for a second query.
Why this rather than a server with the business logic in the middle:
The SQL details, for anyone curious
- Everything references a pair,
(id, space_id), rather than a bare id. A subtask from another space, or a label from the wrong one, is structurally impossible — no check in application code required. - Deleting a list is
on delete set nullon a single column: the tasks return to Inbox instead of disappearing with it. - Ordering is a fractional number. To drop a task between two neighbours the client writes the midpoint and touches no other row.
- “Who closed it” is stamped by the database from your session; that column is not granted to any client, so there is nothing to forge.
- Being overdue is stored nowhere and computed on read. No field, nothing to drift out of step with reality.
- Synchronisation only ever runs downwards: closing a parent closes its subtasks, and closing the last subtask does not close the parent.
When someone leaves a space
This is where tasks differ from the budget: a transaction is a settled fact, while a task faces forward and has an assignee — and an assignee can leave.
- Open tasks stay but lose their assignee: they belong to the space, not to a person.
- Closed tasks keep theirs. “Lea did that one” is still true a year later.
- Reopening clears the person who left — otherwise the task would go back into play assigned to someone who can no longer see it.
Limits, and what is deliberately missing
50 lists and 50 labels per space, 200 subtasks per task, 10,000 active tasks. A title is up to 500 characters, a note up to 10,000. These are ceilings nobody meets in ordinary use; they exist so one space cannot spoil the others.
Not in the first version, on purpose: recurring tasks, comments, attachments, several assignees on one task, private tasks inside a shared space, and notifications. Recurring tasks are designed and come next.
If you have not connected Unitcore to an assistant yet, it takes a couple of minutes: Connect Unitcore to Claude. And the spaces all of this stands on have an article of their own: How Unitcore is put together.