fix: architecture review - address 5 critical issues, 6 warnings, 3 suggestions
Critical fixes: - C1: Create standalone ADR-006 file (edge type consistency), extract from open-questions.md inline content - C2: Convert CallResult from plain interface to TypeBox schema, aligning with 'TypeBox as single source of truth' constraint - C3: Add fromJSON() cycle detection specification - enforce ADR-002 DAG invariant even on deserialized input - C4: Rewrite consumer-integration.md Phase 4 to use ADR-005 event-append pattern instead of direct signal mutation - C5: Fix operator precedence bug in consumer-integration.md (missing parentheses around OR condition) Warnings addressed: - W1: Fix immutability claim - operation graph is 'conventionally immutable', not prevented by API - W2: Add EventLogProjection to reactive exports map - W3: Add CallResult/CallResultSchema to schema exports map - W4: Fix reactive-execution.md Level 1 error handling to use event-append pattern instead of direct signal mutation - W5: Remove duplicate dataFlow inference description in schema.md - W6: Clarify ADR-006 project context (flowgraph vs taskgraph) Suggestions implemented: - S1: Add 'reviewed' document lifecycle status between draft/stable, update all docs to reviewed status - S2: Add carve-out note for analysis result types in schema.md constraints (they are ephemeral, not serialized) - S3: Add isComplete() and getAggregateStatus() convenience methods to WorkflowReactiveRoot specification
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
---
|
||||
status: draft
|
||||
status: reviewed
|
||||
last_updated: 2026-05-22
|
||||
---
|
||||
|
||||
@@ -87,6 +87,8 @@ static fromJSON(data: FlowGraphSerialized<NodeAttrs, EdgeAttrs>): FlowGraph<Node
|
||||
|
||||
Deserializes from graphology native JSON format. Validates against the appropriate schema (`OperationGraphSerialized` or `CallGraphSerialized`). Throws `InvalidInputError` on validation failure.
|
||||
|
||||
After schema validation, `fromJSON()` validates DAG invariants by running cycle detection on the deserialized graph. If cycles are found, it throws `CycleError` with the cycle paths. This enforces ADR-002's DAG-only invariant even for externally-provided data — a corrupted or adversarial JSON input cannot produce a cyclic graph that would violate downstream assumptions (e.g., that `topologicalOrder()` always succeeds).
|
||||
|
||||
Round-trip guarantee: `fromSpecs()` → `export()` → `fromJSON()` is lossless.
|
||||
|
||||
## Mutation Methods
|
||||
@@ -266,7 +268,7 @@ This is an escape hatch. Direct graph mutation bypasses flowgraph's validation (
|
||||
| `validate()`, `hasCycles()` | No — reads | Validation results |
|
||||
| `typeCompat()` | No — reads | `TypeCompatResult` |
|
||||
|
||||
**Key invariant**: The operation graph produced by `fromSpecs()` is immutable after construction — no mutation methods are exposed. If the registry changes, rebuild the graph. The call graph produced by `fromCallEvents()` supports incremental mutation via `addCall`, `updateStatus`, and `addDependency`. The initial events populate the graph, and subsequent events update it.
|
||||
**Key invariant**: The operation graph produced by `fromSpecs()` is conventionally immutable — consumers should not call mutation methods on it after construction. The mutation methods (`addNode`, `addEdge`, etc.) are available for incremental construction via `new FlowGraph()` + `addOperation()`/`addTypedEdge()`. If the registry changes, rebuild the graph. The call graph produced by `fromCallEvents()` supports incremental mutation via `addCall`, `updateStatus`, and `addDependency`. The initial events populate the graph, and subsequent events update it.
|
||||
|
||||
## Exports Map
|
||||
|
||||
@@ -275,10 +277,10 @@ This is an escape hatch. Direct graph mutation bypasses flowgraph's validation (
|
||||
| `@alkdev/flowgraph` | `FlowGraph`, all public types |
|
||||
| `@alkdev/flowgraph/graph` | `FlowGraph`, `FlowGraphOptions` |
|
||||
| `@alkdev/flowgraph/analysis` | `typeCompat`, `buildTypeEdges`, `validateGraph`, `validateTemplate`, `topologicalOrder`, `parallelGroups`, `criticalPath`, `reachableFrom` |
|
||||
| `@alkdev/flowgraph/schema` | `OperationNodeAttrs`, `CallNodeAttrs`, `OperationEdgeAttrs`, `CallEdgeAttrs`, `TemplateEdgeAttrs`, `CallStatus`, `NodeStatus`, `EdgeType` |
|
||||
| `@alkdev/flowgraph/schema` | `OperationNodeAttrs`, `CallNodeAttrs`, `OperationEdgeAttrs`, `CallEdgeAttrs`, `TemplateEdgeAttrs`, `CallResultSchema`, `CallResult`, `CallStatus`, `NodeStatus`, `EdgeType` |
|
||||
| `@alkdev/flowgraph/component` | `Operation`, `Sequential`, `Parallel`, `Conditional`, `Map` |
|
||||
| `@alkdev/flowgraph/host` | `GraphologyHostConfig`, `ReactiveHostConfig` |
|
||||
| `@alkdev/flowgraph/reactive` | `WorkflowReactiveRoot`, `WorkflowNode`, `ReactiveContext` |
|
||||
| `@alkdev/flowgraph/reactive` | `WorkflowReactiveRoot`, `WorkflowNode`, `ReactiveContext`, `EventLogProjection` |
|
||||
| `@alkdev/flowgraph/error` | `FlowgraphError`, `ConstructionError`, `CycleError`, `ValidationError`, `TypeIncompatError`, `InvalidTransitionError` |
|
||||
|
||||
## Constraints
|
||||
@@ -288,7 +290,7 @@ This is an escape hatch. Direct graph mutation bypasses flowgraph's validation (
|
||||
- **No parallel edges** — `addEdge` throws `DuplicateEdgeError` if an edge already exists between the same (source, target) pair.
|
||||
- **No self-loops** — enforced at the graphology level (`allowSelfLoops: false`).
|
||||
- **Edge keys are deterministic** — `${source}->${target}` format. No user-specified edge keys.
|
||||
- **Operation graph is immutable after construction** — no mutation methods are exposed after `fromSpecs()`. If the registry changes, rebuild the graph.
|
||||
- **Operation graph is conventionally immutable after construction** — `fromSpecs()` produces a graph that consumers should treat as immutable. Mutation methods (`addOperation`, `addTypedEdge`) are available for incremental construction but should not be used on factory-produced graphs. If the registry changes, rebuild the graph.
|
||||
- **Call graph supports incremental mutation** — `addCall`, `updateStatus`, `addDependency` are the primary mutation paths.
|
||||
|
||||
## Open Questions
|
||||
|
||||
Reference in New Issue
Block a user