--- id: reactive/workflow-root name: Implement WorkflowReactiveRoot — signal graph, EventLogProjection, lifecycle, abort, dispose status: pending depends_on: - graph/flowgraph-class - schema/enums - schema/node-attrs - setup/test-infrastructure scope: broad risk: high impact: phase level: implementation --- ## Description Implement the `WorkflowReactiveRoot` class that wraps reactive state for an entire workflow execution. It takes the structural DAG, creates signal-backed state for each operation node, and implements the `EventLogProjection` interface from ADR-005. The reactive root owns all signals and is responsible for their lifecycle. ## Acceptance Criteria - [ ] `src/reactive/workflow.ts` exports `WorkflowReactiveRoot` class implementing `EventLogProjection` - [ ] `EventLogProjection` interface: `append(event)`, `getStatus(nodeId)`, `getResult(nodeId)`, `getEvents(nodeId)` - [ ] Constructor takes `DirectedGraph` and optional `{ failurePolicy?: FailurePolicy }`, calls `initializeSignals()` - [ ] `FailurePolicy`: `"continue-running" | "abort-dependents"` (default: `"continue-running"`) - [ ] `initializeSignals()`: iterates all DAG nodes, creates `signal("idle")`, `computed` preconditions (all predecessors completed/skipped), `computed` blockedByFailure (any predecessor failed/aborted), `computed` result from event log - [ ] `nodeKeyToRequestId: Map` — maps template node keys to call protocol requestIds - [ ] `statusMap: Map>`, `preconditions`, `blockedByFailure` — owned by this class - [ ] `append(event: CallEventMapValue)`: processes event, updates status via projection (idempotent) - [ ] `getStatus(nodeId)`: hybrid model — checks event log first for call-level statuses, falls back to signal map for workflow-level statuses - [ ] `getResult(nodeId)`: derives from most recent `call.responded`/`call.error`/`call.aborted` event per node - [ ] `abortAll()`: sets all non-terminal nodes (not completed/failed) to `"aborted"` - [ ] `abortNode(nodeId)`: aborts a specific node - [ ] `dispose()`: calls all effect disposers, clears all maps (critical for preventing signal leaks) - [ ] `isComplete(): boolean` — all nodes in terminal state - [ ] `getAggregateStatus()`: count breakdown by status - [ ] Unit tests: signal initialization for known DAG, append event → status update, getResult derived from events, abort cascade, dispose clears all, failurePolicy behavior ## References - docs/architecture/reactive-execution.md — WorkflowReactiveRoot full specification, EventLogProjection, lifecycle, ownership, disposal - docs/architecture/host-configs.md — ReactiveContext structure, signal-graph → WorkflowNode wiring ## Notes > To be filled by implementation agent ## Summary > To be filled on completion