Files
flowgraph/tasks/reactive-workflow-root.md
glm-5.1 466b121f77 decompose architecture into 38 atomic tasks across 12 parallel generations
Decompose the reviewed architecture specs into taskgraph-managed tasks:
- 2 setup tasks (project init, test infrastructure)
- 4 schema tasks (enums, node attrs, edge attrs, graph schemas)
- 1 error hierarchy task
- 6 graph tasks (FlowGraph class, 3 construction paths, queries, validation)
- 5 analysis tasks (type-compat, build-type-edges, ordering, template-validation, defaults)
- 5 component tasks (Operation, Sequential, Parallel, Conditional, Map)
- 2 host config tasks (GraphologyHostConfig, ReactiveHostConfig)
- 4 reactive tasks (WorkflowRoot, node-status, max-concurrency, retry-semantics)
- 3 review tasks (foundation, reactive-and-hosts, complete-library)
- 5 meta cluster tasks (schema, graph, component, reactive, analysis layers)
- 1 API exports task

Validated with taskgraph: zero cycles, 38 tasks, 12 parallel generations.
Critical path: 12 tasks through reactive execution layer.
2026-05-21 20:24:44 +00:00

50 lines
2.8 KiB
Markdown

---
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<NodeStatus>("idle")`, `computed<boolean>` preconditions (all predecessors completed/skipped), `computed<boolean>` blockedByFailure (any predecessor failed/aborted), `computed<CallResult | undefined>` result from event log
- [ ] `nodeKeyToRequestId: Map<string, string>` — maps template node keys to call protocol requestIds
- [ ] `statusMap: Map<string, Signal<NodeStatus>>`, `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