Item relations

Versions

#287 • Updated Sep 23, 2026

Tasks and memories in a project can point at each other. Relations use the project-local item numbers (#284) and never cross a project boundary. Documentation pages are not part of the relation graph yet.

Kinds

Kind Direction How it is created
references source → target Derived from #N in a task's content or a published memory's text
related symmetric Explicitly, with item_action relate; stored once, lower number first
implements task → memory Explicitly
supersedes newer memory → older memory Explicitly; cycles are rejected
blocked_by waiting task → prerequisite task Explicitly; see below and #346
discovered_from task → the task or memory it was found from Explicitly; information only

Explicit relations are removed with item_action unrelate. Neither needs a version: a relation changes neither item. Adding a relation that exists, or removing one that is gone, succeeds and changes nothing.

Blockers

blocked_by is the one kind that affects work: the waiting task cannot start before the prerequisite is done (#346). It never changes a status. A blocker links two tasks of one project, never starts from a closed task, never runs between a task and its own ancestor or descendant, and never closes a cycle; the rejection names the path it would close. Blocker changes and claims of one project take a project-scoped lock (RelationService.LockTasks: sp_getapplock on SQL Server, SQLite serialises writers), so opposite blockers added at once cannot both commit. Each added or removed blocker is recorded in the waiting task's history (blocker_added, blocker_removed) without a new version.

Derived references

RelationService.ReconcileMarkdown runs after a task is saved and after a memory revision is published. It replaces only the Markdown-derived references rows of that one source, so it is idempotent and never touches explicit relations. For memories it records the published revision the references came from. Pending and rejected revisions never reconcile, so an unreviewed proposal cannot change the graph.

Visibility

Relations keep their endpoints when an item is archived or expires. Reading them (the direct relations in item_get, the relation panel) resolves each endpoint's title with the reader's own permissions and silently drops what the reader may not see. A hidden endpoint reveals neither its title nor that a relation exists. Restoring an item makes its relations visible again.

Creating an explicit relation needs a source the caller may edit and a target the caller may read. A relation never grants access and never changes the status of the items it connects.

Connection interrupted or session ended. Reload

Rejoining the server...

Rejoin failed... trying again in seconds.

Failed to rejoin.
Please retry or reload the page.

The session has been paused by the server.

Failed to resume the session.
Please retry or reload the page.