Align storage & architecture specs with published npm libraries

Systematically compared @alkdev/taskgraph, @alkdev/operations, and
@alkdev/flowgraph against storage/arch specs and fixed all mismatches.

Key changes:

Tasks (storage/tasks.md + ADR-011):
- Rename TaskFrontmatter → TaskInput to match library export
- Fix dependsOn (was depends_on) in field mappings — library uses
  camelCase; parseFrontmatter normalizes YAML snake_case on input
- Document DependencyEdge shape {from, to, qualityRetention?} and
  DB↔library field mapping
- Document graph node vs DB column distinction (TaskGraphNodeAttrs
  is a subset of TaskInput)
- Fix default risk fallback from low → medium (matches resolveDefaults)
- Fix cross-project guard column references (dependentTaskId, not taskId)
- Clarify @alkdev/taskgraph TS is source of truth; frontmatter is for
  LLM output parsing and legacy imports, not Rust CLI
- Add complete library exports reference

Operations (storage/spokes.md + operations.md):
- Add version, title, _meta columns to operations table (required by
  OperationSpec, were missing)
- Fix type casing: query/mutation/subscription (lowercase, matching
  OperationType runtime values)
- Make outputSchema and accessControl NOT NULL (matching library)
- Document ErrorDefinition shape {code, description, schema, httpStatus?}
- Document _meta vs commonCols.metadata distinction
- Add registerAll, get, getHandler, getByName, list, subscribe methods
- Fix buildCallHandler signature ({ registry, callMap })
- Fix OperationType values (lowercase)

Call graph (storage/call-graph.md + call-graph.md):
- Change operationId to NOT NULL with RESTRICT FK (was nullable/SET NULL)
  — matches flowgraph's required CallNodeAttrs.operationId
- Document sentinel __removed__ operation strategy for deletions
- Document ISO 8601 string ↔ timestamptz conversion requirement
- Rewrite CallEventMap to match actual library: flat dot-notation keys,
  timestamp on all events, nested error structure, optional output on
  completed event
- Remove call.running event (doesn't exist in library) — hub calls
  updateStatus(running) directly on dispatch
- Fix buildCallHandler({ registry, callMap }) signature
- Fix PendingRequestMap constructor (positional EventTarget)
- Add updateCall/removeCall/graph methods to API summary
- Document abort cascade as hub logic, not flowgraph logic
- Add open questions for operation deletion and reactive vs call graph
  semantics

Table reference (storage/table-reference.md):
- Update call_graph_nodes.operationId cascade to RESTRICT
- Update operations.type comment to lowercase
- Update status enum reference
This commit is contained in:
2026-05-25 11:46:42 +00:00
parent 2b63cda1c7
commit 93e2286343
7 changed files with 288 additions and 112 deletions

View File

@@ -1,6 +1,6 @@
---
status: draft
last_updated: 2026-04-23
last_updated: 2026-05-25
---
# Storage: Table Schemas
@@ -90,7 +90,7 @@ export const commonCols = {
| task_dependencies.dependentTaskId → tasks.id | CASCADE | Dependent task deletion removes its incoming dependency edges |
| call_graph_edges.sourceId → call_graph_nodes.id | CASCADE | Deleting a node removes its outgoing edges |
| call_graph_edges.targetId → call_graph_nodes.id | CASCADE | Deleting a target node removes its incoming edges |
| call_graph_nodes.operationId → operations.id | SET NULL | Operation definition deletion preserves call records but detaches them (nullable FK — call data retains audit value even if the operation is removed) |
| call_graph_nodes.operationId → operations.id | RESTRICT | Call records must reference a valid operation. If an operation is being removed, the hub must reassign call records first (e.g., to a sentinel `__removed__` operation) or deny the removal. |
| api_keys.rotatedToId → api_keys.id | SET NULL | Old key keeps its data; if new key is deleted, rotation link is broken but both keys remain |
## Index Reference
@@ -134,7 +134,7 @@ export const commonCols = {
| call_graph_edges | `unq_call_graph_edges_source_target_type` | UNIQUE (sourceId, targetId, edgeType) | Prevent duplicate edges from retries/reconnections |
| operations | `unq_operations_namespace_name` | UNIQUE (namespace, name) | Operation definition uniqueness by namespace+name |
| operations | `idx_operations_namespace` | B-tree | Filter by namespace |
| operations | `idx_operations_type` | B-tree | Filter by operation type |
| operations | `idx_operations_type` | B-tree | Filter by operation type (lowercase: query/mutation/subscription) |
| operation_registrations | `unq_operation_registrations_active` | UNIQUE partial (WHERE status = 'active') | One active registration per provider per operation |
| operation_registrations | `idx_operation_registrations_operation_id` | B-tree | Find registrations for an operation |
| operation_registrations | `idx_operation_registrations_provider_id` | B-tree | Find registrations for a provider |
@@ -194,7 +194,7 @@ Status enums across tables:
| `sessions` | `idle`, `busy`, `retry`, `archived` | Session lifecycle |
| `sessions.roleName` | text | Which behavioral role (e.g., "architect", "implementation-specialist"). Free-form string, not a FK constraint. See [agent-roles.md](../../agent-roles.md) and [ADR-012](../../../decisions/ADR-012-agent-vs-role-vs-account.md). |
| `spokes` | `connected`, `disconnected` | WebSocket connection state |
| `operations` | (no status column) | — Definitions are persistent |
| `operations` | (no status column) | — Definitions are persistent. `type` column uses lowercase: `query`, `mutation`, `subscription` |
| `operation_registrations` | `active`, `inactive` | Provider registration lifecycle |
| `mappings` | `active`, `completed`, `aborted`, `failed` | Coordination workflow state |
| `call_graph_nodes` | `pending`, `running`, `completed`, `failed`, `aborted` | Call protocol lifecycle |