From 7c64553ab036f79e24be6d739d82f58d78581459 Mon Sep 17 00:00:00 2001 From: oberon Date: Tue, 5 May 2026 00:46:45 +0300 Subject: [PATCH] Add data-model.md --- data-model.md | 127 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 data-model.md diff --git a/data-model.md b/data-model.md new file mode 100644 index 0000000..1502e21 --- /dev/null +++ b/data-model.md @@ -0,0 +1,127 @@ +# Non-Linear: Data Model + +## Overview + +The data model consists of two overlaid graphs on the same set of nodes: + +1. **Decomposition Tree** — strict parent→child hierarchy (DAG) +2. **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 planned +- `todo` — planned, not started +- `in_progress` — actively being worked on +- `in_review` — awaiting review +- `done` — completed +- `cancelled` — 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. \ No newline at end of file