86 lines
5.3 KiB
Markdown
86 lines
5.3 KiB
Markdown
# @alkdev/flowgraph — Agent Guide
|
||
|
||
Project-specific context for AI agents working on this codebase.
|
||
|
||
## What This Is
|
||
|
||
DAG-based workflow orchestration library. Wraps graphology `DirectedGraph`, enforces DAG invariants, provides ujsx template composition and reactive signal-driven execution. Sits between `@alkdev/operations` (what can be called) and `@alkdev/alkhub` (what was called) — defines *how calls are orchestrated*.
|
||
|
||
## Build & Test Commands
|
||
|
||
```bash
|
||
npm run build # tsup (ESM + CJS + dts + sourcemaps)
|
||
npm run build:tsc # tsc type-check only
|
||
npm run lint # tsc --noEmit
|
||
npm run test # vitest run
|
||
npm run test:watch # vitest watch
|
||
npm run test:coverage # vitest run --coverage
|
||
```
|
||
|
||
Always run `npm run lint && npm run test` after making changes.
|
||
|
||
## Source Structure
|
||
|
||
```
|
||
src/
|
||
index.ts # Barrel — re-exports all sub-modules
|
||
component/ # ujsx workflow components (Operation, Sequential, Parallel, Conditional, Map)
|
||
host/ # HostConfig implementations (GraphologyHostConfig, ReactiveHostConfig)
|
||
schema/ # TypeBox schemas, enums, node/edge attribute types
|
||
graph/ # FlowGraph class (construction, mutation, query, serialization)
|
||
reactive/ # WorkflowReactiveRoot, signal-driven status, event log projection
|
||
analysis/ # Pure functions: typeCompat, validate, topologicalOrder, parallelGroups, criticalPath
|
||
error/ # FlowgraphError hierarchy
|
||
```
|
||
|
||
## Subpath Exports
|
||
|
||
The package has 8 export subpaths. Root `@alkdev/flowgraph` re-exports everything. Subpath imports make dependencies explicit:
|
||
|
||
| Subpath | Key Exports |
|
||
|---------|-------------|
|
||
| `/graph` | `FlowGraph`, `FlowGraphOptions`, `OperationSpec`, `CallEventMapValue` |
|
||
| `/schema` | `CallStatus`, `NodeStatus`, `EdgeType`, `OperationType`, all node/edge attribute types |
|
||
| `/component` | `Operation`, `Sequential`, `Parallel`, `Conditional`, `Map` |
|
||
| `/host` | `GraphologyHostConfig`, `ReactiveHostConfig` |
|
||
| `/analysis` | `typeCompat`, `buildTypeEdges`, `validateGraph`, `validateSchema`, `validate`, `validateTemplate`, `topologicalOrder`, `parallelGroups`, `criticalPath` |
|
||
| `/reactive` | `WorkflowReactiveRoot`, `EventLogProjection`, `WorkflowNode`, `FailurePolicy` |
|
||
| `/error` | `FlowgraphError`, `ConstructionError`, `CycleError`, `InvalidInputError`, `InvalidTransitionError` |
|
||
|
||
## Key Patterns
|
||
|
||
- **TypeBox schema + Static type pairs**: Every schema is exported as both a const (runtime) and an inferred type. `const FooSchema = Type.Object({...}); type Foo = Static<typeof FooSchema>;`
|
||
- **Delegation model**: `FlowGraph` wraps a graphology `DirectedGraph` (does not extend it). `flowGraph.graph` is an escape hatch that bypasses validation.
|
||
- **DAG enforcement**: `addEdge()` throws `CycleError` if the edge would create a cycle. `fromJSON()` validates DAG invariants on deserialization.
|
||
- **Event log as source of truth**: Call protocol events (`call.requested`, `call.responded`, `call.error`, `call.aborted`, `call.completed`) are appended to `WorkflowReactiveRoot`. Status/results are derived projections.
|
||
- **Signal-driven execution**: `@preact/signals-core` powers `WorkflowReactiveRoot`. `preconditions`, `canStart`, `blockedByFailure` are `ReadonlySignal<boolean>` computed from predecessor status.
|
||
- **`dispose()` is mandatory**: `WorkflowReactiveRoot.dispose()` must be called to release signal subscriptions.
|
||
|
||
## Architecture Docs
|
||
|
||
`docs/architecture/` contains detailed specs (all `status: reviewed`):
|
||
|
||
- `README.md` — overview, relationship to sibling packages, design decisions
|
||
- `flowgraph-api.md` — FlowGraph class full API
|
||
- `consumer-integration.md` — end-to-end integration walkthrough (5 phases)
|
||
- `schema.md` — TypeBox Module, all node/edge attribute schemas
|
||
- `operation-graph.md` — static graph from OperationSpecs
|
||
- `call-graph.md` — dynamic graph from call events
|
||
- `workflow-templates.md` — ujsx components, composition rules, template→DAG hydration
|
||
- `host-configs.md` — GraphologyHostConfig, ReactiveHostConfig
|
||
- `reactive-execution.md` — signal-driven status propagation, lifecycle, error boundaries
|
||
- `analysis.md` — type-compatibility checking, precondition validation, execution ordering
|
||
- `error-handling.md` — FlowgraphError hierarchy
|
||
- `build-distribution.md` — package structure, exports map
|
||
- `decisions/` — ADRs 001–006
|
||
|
||
Consult these for anything non-trivial. The README is surface-level; architecture docs are the specification.
|
||
|
||
## Constraints for Agent Modifications
|
||
|
||
- **Never add cycles** — this is a DAG-only library. Any edge that would create a cycle must throw `CycleError`.
|
||
- **Never mutate operation graphs after construction** — `fromSpecs()` graphs are conventionally immutable.
|
||
- **Keep schema as pure data** — `src/schema/` contains TypeBox schemas and types only, no runtime logic.
|
||
- **Keep analysis as pure functions** — `src/analysis/` functions take a `FlowGraph` or `DirectedGraph` as input and return results without side effects.
|
||
- **Maintain the delegation model** — `FlowGraph` delegates to graphology. Don't expose raw graphology methods that could violate DAG invariants without explicit validation.
|
||
- **tsup builds all subpath entries** — `tsup.config.ts` lists every subpath. If you add a new top-level module, add the entry there and update `package.json` exports. |