4.6 KiB
Non-Linear: Data Model
Overview
The data model consists of two overlaid graphs on the same set of nodes:
- Decomposition Tree — strict parent→child hierarchy (DAG)
- Association Graph — lateral many-to-many connections with typed edges
These are deliberately separated. The decomposition tree is the spine of the product. The association graph is an overlay that adds context without defining structure.
Issue Node (Atomic Unit)
Every node in the graph is an issue. Issues are intentionally untyped — their depth in the decomposition tree implies their abstraction level.
| Field | Type | Description |
|---|---|---|
id |
UUID | Unique identifier |
title |
string | Short descriptive title |
description |
text | Detailed description (markdown) |
status |
enum | Current state (see Status below) |
labels |
string[] | Freeform tags for orthogonal concerns |
assignee |
actor_id? | User or agent assigned |
parent_id |
issue_id? | Parent in decomposition tree (null = root) |
created_at |
timestamp | Creation time |
updated_at |
timestamp | Last modification |
created_by |
actor_id | Creator (user or agent) |
Status
Default statuses (customizable per project):
backlog— not yet plannedtodo— planned, not startedin_progress— actively being worked onin_review— awaiting reviewdone— completedcancelled— abandoned
Labels
Labels handle all classification orthogonal to hierarchy:
- Kind:
bug,feature,chore,spike - Area:
frontend,backend,infra,docs - Priority:
p0,p1,p2,p3 - Custom: anything the team defines
Why Untyped
Traditional trackers have explicit types: Epic, Story, Task, Subtask, Bug. This creates rigidity — teams argue about what level something belongs at, and refactoring the hierarchy means changing types.
In Non-Linear, depth is type:
Root (depth 0) → "project level"
├── Child (depth 1) → "component/epic level"
│ ├── Child (depth 2) → "feature/story level"
│ │ └── Child (depth 3) → "task level"
A node's abstraction level is determined by its position, not a type field. Moving a node to a different depth changes its conceptual level automatically.
Decomposition Tree
The decomposition tree is a strict hierarchy with these properties:
- Single parent: Every node has exactly one parent (except roots)
- Directed: Edges flow from abstract (parent) to concrete (child)
- Acyclic: No node can be its own ancestor
- Single root per project: Each project has one root node (v0.1)
Reparenting
Moving a node to a different parent is a structural change. It affects:
- The node's implied abstraction level
- Agent permissions (if scoped to a subtree)
- The layered view layout
- Who can access the node (if resource-scoped policies apply)
The system should warn when reparenting changes permission boundaries.
Association Graph (Lateral Links)
Lateral links are typed, many-to-many relationships that don't affect hierarchy.
Link Types
| Type | Semantics | Directionality |
|---|---|---|
blocks |
A blocks B (B can't proceed until A is done) | Directed |
blocked_by |
Inverse of blocks | Directed (auto-created) |
relates_to |
General association | Undirected |
duplicates |
A is a duplicate of B | Directed |
Cross-Project Links (v0.2+)
In future versions, lateral links can cross project boundaries. This enables:
- Freelancer's client project depending on a shared library
- Shared infrastructure components blocking multiple projects
- Cross-team dependency tracking
Cross-project links add complexity to permissions (an agent scoped to Project A sees a link to Project B but may not access the target) and are deferred to v0.2.
Link vs. Parent Relationship
| Property | Parent→Child | Lateral Link |
|---|---|---|
| Cardinality | One parent per node | Many-to-many |
| Affects hierarchy | Yes | No |
| Affects layered view | Yes | Shown as overlay edges |
| Affects permissions | Yes (subtree scoping) | No |
| Removal impact | Structural (node needs new parent) | Annotation only |
Project (v0.1)
| Field | Type | Description |
|---|---|---|
id |
UUID | Unique identifier |
name |
string | Project name |
root_id |
issue_id | Root node of decomposition tree |
created_at |
timestamp | Creation time |
members |
actor_id[] | Users and agents with access |
In v0.1, each project has exactly one root node and one decomposition tree. Multi-root or cross-project features are deferred.