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-05-18
last_updated: 2026-05-25
---
# Operations System
@@ -15,25 +15,30 @@ The operations system is the universal abstraction for all work in the alk.dev p
### Core Types (`operations/types.ts`)
- `OperationType` — QUERY (read-only), MUTATION (write), SUBSCRIPTION (async generator)
- `OperationSpec` — serializable, hashable subset (name, namespace, version, type, description, tags, inputSchema, outputSchema, errorSchemas, accessControl, \_meta)
- `OperationType``QUERY = "query"`, `MUTATION = "mutation"`, `SUBSCRIPTION = "subscription"` (enum names uppercase, string values lowercase)
- `OperationSpec` — serializable, hashable subset (name, namespace, version, type, description, title?, tags?, inputSchema, outputSchema, errorSchemas?, accessControl, _meta?)
- `IOperationDefinition` — extends `OperationSpec` with runtime `handler`
- `OperationContext` — metadata, requestId, parentRequestId, identity, env
- `AccessControl` — requiredScopes (all match), requiredScopesAny (any match), resourceType, resourceAction. See below.
- `ResponseEnvelope<T>` — universal result wrapper with source tracking (local/http/mcp). All `execute()` and `env` functions return `ResponseEnvelope<T>`.
- `CallError` / `InfrastructureErrorCode` — structured error codes: `OPERATION_NOT_FOUND`, `ACCESS_DENIED`, `VALIDATION_ERROR`, `TIMEOUT`, `ABORTED`, `EXECUTION_ERROR`, `UNKNOWN_ERROR`.
- `ErrorDefinition` — structured error schema declaration: `{ code: string, description: string, schema: unknown, httpStatus?: number }`
### Registry (`operations/registry.ts`)
- Register by `{namespace}.{name}` key
- `register()` now accepts `OperationSpec & { handler? }` (handler can be registered separately)
- `register()` accepts `OperationSpec & { handler? }` (handler can be registered separately)
- `registerSpec()` / `registerHandler()` — separate spec and handler registration
- `registerAll(definitions)` — bulk registration
- `execute()` returns `Promise<ResponseEnvelope<TOutput>>` (not `Promise<TOutput>`)
- Constructor accepts optional `SchemaAdapter` for Zod/Valibot conversion
- Access control is enforced in the registry (via `enforceAccess`)
- Validate input before handler execution
- Warn on output schema mismatch (don't throw)
- `getSpec()` / `getAllSpecs()` for serializable specs
- `get(name)` / `getByName(namespace, name)` — retrieve definitions
- `getHandler(name)` — retrieve handler function
- `list()` — list all registered operation names
### Scanner (`operations/scanner.ts`)
@@ -51,6 +56,7 @@ The operations system is the universal abstraction for all work in the alk.dev p
- Sets `trusted: true` on nested context (bypasses access control for internal calls)
- Env functions return `Promise<ResponseEnvelope>`, callers use `unwrap(envelope)` or `envelope.data`
- Filters SUBSCRIPTION operations out of env
- `subscribe(registry, operationId, input, context)` — standalone function for subscription operations
### FromSchema (`operations/from_schema.ts`)
@@ -119,7 +125,7 @@ Operations use `buildEnv()` which supports direct mode (see call-graph.md):
- **Direct mode**: `buildEnv({ registry, context })` → env functions call `registry.execute()`
The call protocol (PendingRequestMap, CallHandler) is part of `@alkdev/operations`. It provides call graph tracking, abort cascading, and structured error handling across all transports. See call-graph.md for the full spec.
The call protocol (PendingRequestMap, CallHandler) is part of `@alkdev/operations`. It provides call graph tracking, abort cascading, and structured error handling across all transports. The `buildCallHandler({ registry, callMap })` creates a `CallHandler` that subscribes to `call.requested` events on the `callMap` (a `PendingRequestMap`), enforces access control, and dispatches via `registry.execute()`. See call-graph.md for the full spec.
## How It Connects to Everything Else