resolve all remaining open questions (OQ-03–OQ-29), add ADR-006
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
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
---
|
||||
status: draft
|
||||
last_updated: 2026-05-20
|
||||
last_updated: 2026-05-22
|
||||
---
|
||||
|
||||
# Operation Graph (Static)
|
||||
@@ -169,13 +169,13 @@ See [analysis.md](analysis.md) for the full type-compatibility algorithm.
|
||||
|
||||
## Open Questions
|
||||
|
||||
1. **Should `fromSpecs()` add ALL possible edges or only compatible ones?** The current design adds both compatible and incompatible edges. An alternative is to only add compatible edges, with a separate `potentialEdges()` query that computes incompatible connections on demand. Pro: smaller graph. Con: loses diagnostic information.
|
||||
1. ~~**Should `fromSpecs()` add ALL possible edges or only compatible ones?**~~ **Resolved (OQ-001/ADR-005)**: Type-compatibility edges are only added on edges where `dataFlow: true`. Temporal-only edges bypass type checking. Both compatible and incompatible edges are added where data flows for diagnostic value.
|
||||
|
||||
2. **How to handle version conflicts?** If two versions of the same operation exist in the registry, should they be separate nodes (`task.classify@1.0.0` vs `task.classify@2.0.0`) or should the latest version win? The current design uses `namespace.name` (no version) as the node key, meaning only one version per operation can exist in the graph.
|
||||
2. ~~**How to handle version conflicts?**~~ **Resolved (OQ-026)**: The current design uses `namespace.name` (no version) as the node key, meaning only one version per operation can exist in the graph. This is intentional simplicity. Version conflicts are a niche concern that can be addressed when a concrete use case arises. If versioning becomes needed, the node key format could be extended to `namespace.name@version`, but this is a significant change that requires careful consideration. For v1, the one-version-per-operation constraint is sufficient and keeps the key format simple and consistent.
|
||||
|
||||
3. **Should subscription operations be treated differently?** A subscription produces a stream, not a single output. Its `outputSchema` describes a single stream element, but the data flow semantics are different from query/mutation. Should the type compatibility check account for this?
|
||||
3. ~~**Should subscription operations be treated differently in type compatibility?**~~ **Resolved (OQ-003)**: For v1, subscriptions are treated identically to queries/mutations in `typeCompat()`. A subscription's `outputSchema` describes a single stream element, and `typeCompat()` checks whether that single element is compatible with the downstream input. This is correct for the `Map` component (which processes stream elements individually) and may be misleading for direct subscription→operation connections. The `OperationNodeAttrs.type` field is available for consumers that need subscription-aware behavior. A v2 extension could add a `streaming: boolean` flag on edges to capture stream semantics explicitly, but this adds complexity without a current use case.
|
||||
|
||||
4. **How granular should type compatibility be?** The current `detail` field is a string. A more structured approach would be `{ compatible: boolean, mismatchPaths: string[] }` listing the specific JSON paths that don't match. This adds complexity but improves diagnostics.
|
||||
4. ~~**How granular should type compatibility be?**~~ **Resolved (OQ-002/ADR-005)**: Type compatibility checking only applies to state-transfer edges (where `dataFlow: true`). The `typeCompat()` function returns `{ compatible, detail?, mismatches? }` for state-transfer edges only. Temporal-only edges bypass type checking entirely.
|
||||
|
||||
## References
|
||||
|
||||
|
||||
Reference in New Issue
Block a user