--- status: draft last_updated: 2026-04-19 --- # Table Schemas: Coordination Mapping and detection tables for coordinator operations. For cross-cutting reference (cascade behavior, index reference, status enums, relations), see [table-reference.md](./table-reference.md). For design decisions, see [../../../decisions/](../../../decisions/). For coordination architecture, see [../../coordination.md](../../coordination.md). ### `mappings` Worktree/session/spoke relationships. Links spawned sessions to their parent coordinator, the spoke they're running on, and the git branch. This is the coordination table that drives `coord.spawn`, `coord.status`, `coord.message`, and `coord.abort`. | Column | Type | Notes | |--------|------|-------| | commonCols | — | id, metadata, createdAt, updatedAt | | sessionId | text NOT NULL | FK → sessions.id | | spokeId | text | FK → spokes.id | | workspaceId | text | FK → workspaces.id | | parentSessionId | text | FK → sessions.id — Coordinator's session. onDelete: SET NULL — deleting the coordinator detaches the mapping but preserves it. | | taskId | text | FK → tasks.id — The task this mapping is assigned to. Nullable — some mappings aren't task-scoped. | | task | text | Denormalized task display name (slug or name) for quick reference without a JOIN. | | status | text NOT NULL | Enum: `active`, `completed`, `aborted`, `failed`. Default: `active` | **Indexes**: `idx_mappings_session_id` on `(sessionId)`, `idx_mappings_parent_session_id` on `(parentSessionId)`, `idx_mappings_spoke_id` on `(spokeId)`, `idx_mappings_task_id` on `(taskId)`, `idx_mappings_workspace_id` on `(workspaceId)` — workspace-scoped mapping queries. `projectId` is derived from the session's project context, not stored directly. A mapping's project scope comes from its session. `workspaceId` is the workspace within that project. **Status transitions**: `active` → `completed` (successful finish), `active` → `failed` (error), `active` → `aborted` (coordinator cancelled). No transition back to `active` from terminal states. See coordination.md for the operations that create and query these mappings. ### `detections` Anomaly detection records produced by the hub's monitoring heuristics. See coordination.md for the detection heuristics and `coord.detect` operation. | Column | Type | Notes | |--------|------|-------| | commonCols | — | id, metadata, createdAt, updatedAt | | sessionId | text NOT NULL | FK → sessions.id | | anomalyType | text NOT NULL | `MODEL_DEGRADATION`, `HIGH_ERROR_COUNT`, `SESSION_STALL`. Extensible — new types can be added without schema migration. | | severity | text NOT NULL | `high`, `medium`, `low` | | details | jsonb | Detection-specific details (thresholds, counters, timestamps) | | resolvedAt | timestamp with tz | When the detection was resolved/dismissed. Null if still active. | | resolvedBy | text | FK → accounts.id — Who resolved it. onDelete: SET NULL | | resolution | text | How it was resolved: `acknowledged`, `dismissed`, `escalated`, `fixed`. Null if still active. | | dedupKey | text | Deterministic key for deduplication (e.g., hash of type+context). If a new detection has the same dedupKey as an active (unresolved) one, increment `occurrenceCount` instead of creating a new row. | | occurrenceCount | integer NOT NULL DEFAULT 1 | Number of times this detection pattern has occurred. Incremented on dedup matches. | **Indexes**: `idx_detections_session_id` on `(sessionId)` — find detections for a session, `idx_detections_type` on `(anomalyType)` — filter by detection type, `idx_detections_resolved_at` on `(resolvedAt)` — find active (unresolved) detections, `idx_detections_dedup_key` on `(dedupKey)` — dedup lookups. **Deduplication**: When a new detection is created, compute a `dedupKey` from the detection type and relevant context. If an active (unresolved) detection with the same `dedupKey` exists, increment its `occurrenceCount` and update `details`/`updatedAt` instead of inserting a new row. This prevents persistent `MODEL_DEGRADATION` from creating a new row every check interval. **Resolution**: A detection is active when `resolvedAt` is null. Setting `resolvedAt` (with `resolvedBy` and `resolution`) marks it as resolved. On session close (`sessions.status → archived`), consider auto-resolving active detections for that session.