Relocate buildTypeEdges from construction.ts to type-compat.ts per architecture spec.
construction.ts re-exports it for backward compatibility. Add 10 unit tests for
buildTypeEdges covering compatible edges, incompatible edges with mismatches,
unknown schema passthrough, incremental construction, and edge deduplication.
Implements the core FlowGraph class with generic type parameters, DAG-enforced mutations,
cycle detection via graphology-dag, node/edge CRUD, traversal methods, and static factory stubs.
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
Resolve all 19 remaining open questions across the architecture. Every
question now has a documented resolution with rationale:
- OQ-004/OQ-029: edgeType is a universal required attribute on all edges,
single graph per FlowGraph instance (ADR-006)
- OQ-011: No OR preconditions for v1; preconditionMode as v2 extension
- OQ-012: maxConcurrency enforced via reactive counting semaphore
- OQ-014: Unknown operationId creates node with pending status
- OQ-017: Expose common graphology traversal methods on FlowGraph (80/20)
- OQ-020: condition as Type.Unknown() with string/function documentation
- OQ-022: Identity imported from @alkdev/operations peer dep
- All other questions resolved with documented rationale
Fix three critical issues found by architecture review:
1. edgeType serialization/validation gap: document two-step validation
2. CallEdgeAttrs runtime discrimination: edgeType as runtime discriminant,
depends_on edges clarified as observability-only (not execution)
3. ADR-005 signal mutation inconsistency: explicitly distinguish call-level
statuses (event-log-driven) from workflow-derived statuses (signal-mutation)
Additional clarifications:
- dataFlow inference uses conservative strategy (defaults false)
- Conditional.test string resolution: operationName → status === completed
- Add negated field to TemplateEdgeAttrs for else-branch conditions
- Document edge key priority convention for composite keys
- Add maxConcurrency semaphore design to reactive-execution.md
Resolve the three open consequences from ADR-005 (Event Log as Single
Source of Truth) and transition from Proposed to Accepted:
1. Event log IS the call protocol event stream — not a separate type,
but an EventLogProjection interface (append/getStatus/getResult/
getEvents) over CallEventMapValue[] with an append-only contract.
2. Event log persists across template re-renders — projections recompute
against the new DAG; orphaned events stay in log for audit but don't
affect active projections.
3. Edges get dataFlow: boolean attribute on TemplateEdgeAttrs — inferred
(not manual) by GraphologyHostConfig from template expressions.
typeCompat() only runs on dataFlow: true edges. Inference rules are
precisely specified for Conditional.test, Map.over, and Operation.input.
Also resolve OQ-05 (structural containers stay transparent; aggregate
status is a projection from children) and OQ-10 (running node failure
is a FailurePolicy configuration, default continues-running).
Cascading updates to:
- reactive-execution.md: add hybrid status model (event-log-driven vs
projection-driven vs signal-mutation), EventLogProjection interface,
result projection respecting retries, FailurePolicy type
- host-configs.md: ReactiveContext now includes resultProjection and
computed results; resolved Q1/Q3/Q4
- schema.md: dataFlow attribute on TemplateEdgeAttrs with inference
rules and type checking implications
- workflow-templates.md: edge creation rules with dataFlow, result
projection in Conditional/Map, resolved Q1/Q4
- open-questions.md: all ADR-005 questions marked resolved, updated
summary table and cross-cutting themes, removed duplicate OQ-07
7 files changed, 464 insertions, 139 deletions
Proposed architecture decision to use an append-only execution event log
(call protocol events) as ground truth, with status/result/call-graph as
projections. Resolves OQ-06, OQ-07, OQ-08, OQ-09; reframes OQ-01, OQ-02,
OQ-10. Inspired by event sourcing discipline (notification vs state transfer)
and compute_graph ExecutionContext pattern.
- Replace workspace:* deps with published npm semver ranges (^0.34.49, ^0.1.0)
- Expand package.json: add description, publishConfig, scripts, engines,
devDependencies, conditional exports with types/default for import+require
- Fix tsup entry names (path-prefixed like ujsx), add target: es2022,
remove splitting:true (not used by sibling projects)
- Align tsconfig with sibling projects: add lib, noUncheckedIndexedAccess,
noUnusedLocals, noUnusedParameters, erasableSyntaxOnly, etc.
- Expand vitest.config.ts with include, coverage, and path alias
- Clarify @preact/signals-core as direct dep (not just transitive via ujsx)
- Clarify @alkdev/pubsub is a consumer dependency, not flowgraph's dep
- Fix edge key convention: document composite key format for call graph's
multi-edge-type scenario (triggered + depends_on between same pair)
- Align OperationEdgeAttrs field naming: use detail+mismatches consistently
instead of compatibilityDetail
- Add InvalidInputError to error hierarchy (referenced in flowgraph-api but
was missing)
- Fix undefined attrs.category reference in reactive-execution.md
- Remove internal drafting note from host-configs.md
- Fix ReactiveHostConfig constructor signature inconsistency across docs
- Constrain TemplateEdgeAttrs.edgeType to sequential|conditional only