docs update

This commit is contained in:
lda
2026-05-22 01:02:31 +07:00 Verified
parent ef3434fc64
commit 46d384e69a
+56 -14
View File
@@ -14,6 +14,7 @@ and user-facing control belong in `wf_mcp`.
| `wf_core.models` | Pydantic workflow schema package: schemas, condition expressions, executable steps, workflow graph, and node results. | | `wf_core.models` | Pydantic workflow schema package: schemas, condition expressions, executable steps, workflow graph, and node results. |
| `wf_core.run_state` | Serializable execution state: run status, frames, trace entries, interrupt requests, and runtime context. | | `wf_core.run_state` | Serializable execution state: run status, frames, trace entries, interrupt requests, and runtime context. |
| `wf_core.runtime` | Public execution interface: execute, resume, and step in sync or async mode. | | `wf_core.runtime` | Public execution interface: execute, resume, and step in sync or async mode. |
| `wf_core.runtime.scheduler` | Internal frame scheduler: ready queue, selected cursor, frame creation, block/wake helpers, and typed foreach frame metadata. |
| `wf_core.runtime.ops` | Executor-only operations used behind `wf_core.runtime`: node execution, state writes, frame movement, foreach, interrupts, indexes, and schema checks. | | `wf_core.runtime.ops` | Executor-only operations used behind `wf_core.runtime`: node execution, state writes, frame movement, foreach, interrupts, indexes, and schema checks. |
| `wf_core.validation` | Structural workflow validation split by validation concern. | | `wf_core.validation` | Structural workflow validation split by validation concern. |
| `wf_core.conditions` | Runtime evaluation of condition expressions. | | `wf_core.conditions` | Runtime evaluation of condition expressions. |
@@ -28,16 +29,58 @@ flat modules.
1. `execute_workflow` creates a run state and delegates to resume. 1. `execute_workflow` creates a run state and delegates to resume.
2. `prepare_new_run` validates workflow shape and workflow input. 2. `prepare_new_run` validates workflow shape and workflow input.
3. `resume_workflow` loops until completion, interruption, or failure. 3. `resume_workflow` loops until completion, interruption, failure, or no
4. `step_workflow` resolves the active frame and dispatches by step type. schedulable frame.
5. `runtime.ops.nodes` handles `NodeUse` input projection, handler invocation, 4. `runtime.scheduler.select_next_frame` pops the next frame id from
`RunState.ready_frame_ids`, marks that frame `RUNNING`, and updates
compatibility cursor fields such as `current_frame_id`.
5. `step_workflow` resolves the selected frame and dispatches by step type.
6. A normal non-terminal step marks the same frame `PENDING` and puts it back at
the end of the ready queue.
7. Terminal, blocked, interrupted, and failed frames are not re-enqueued.
8. `runtime.ops.nodes` handles `NodeUse` input projection, handler invocation,
output validation, and state writes. output validation, and state writes.
6. `runtime.ops.flow` records trace entries and advances frames. 9. `runtime.ops.flow` records trace entries and advances frames.
7. Completion projects workflow output from state and validates it. 10. Completion projects workflow output from state and validates it.
Async execution shares the same runtime model. The async seam is handler Async execution shares the same runtime model. The async seam is handler
invocation; control-flow steps are still synchronous state transitions. invocation; control-flow steps are still synchronous state transitions.
## Scheduler Model
`RunState.frames` is the frame set: it contains lifecycle records for root,
foreach iteration, and future child frames. `RunState.ready_frame_ids` is the
explicit FIFO scheduling order. `current_frame_id` and `current_node_id` still
exist for compatibility and step-local convenience, but they are the selected
cursor, not the source of all runnable work.
Frame lifecycle rules:
- `PENDING` frames may be placed in the ready queue.
- Selecting a frame removes it from the ready queue and marks it `RUNNING`.
- A still-runnable frame is marked `PENDING` and re-enqueued after one step.
- `BLOCKED` frames are live but waiting on a typed block reason, currently child
frame completion.
- `INTERRUPTED` frames are waiting on external resume input and pause the whole
run.
- `COMPLETED` and `FAILED` frames are terminal for scheduling.
When the ready queue is empty, the scheduler classifies the run as completed,
interrupted, failed, or deadlocked. This replaces the older assumption that
`current_node_id == END` alone is enough to decide runtime completion.
## Serial Foreach
Foreach remains serial-only. A serial foreach parent frame creates one iteration
child frame, records typed `ForeachIterationMetadata`, blocks on that child, and
enqueues the child. When the child reaches `END`, `wake_parent_if_children_complete`
wakes the blocked parent so it can create the next iteration or emit `done`.
This preserves current serial behavior while making the hidden parent/child
relationship explicit. `foreach(mode="parallel")` is still unsupported because
parallel execution needs policy, barrier, lineage, and state-patch semantics
that are not implemented yet.
## Validation Flow ## Validation Flow
`wf_core.validation.core.validate_workflow` coordinates validation: `wf_core.validation.core.validate_workflow` coordinates validation:
@@ -75,9 +118,10 @@ limits and intended adapter seam.
state patch commits. The remaining mapping design notes for future reducer state patch commits. The remaining mapping design notes for future reducer
metadata are documented in metadata are documented in
[`core_state_mapping_and_merge.md`](core_state_mapping_and_merge.md). [`core_state_mapping_and_merge.md`](core_state_mapping_and_merge.md).
- Foreach is still serial-only. Parallel foreach needs an explicit scheduling - Foreach is still serial-only. The scheduler foundation exists, but parallel
model, not just `asyncio.gather`. `ForeachNode.over` is typed as a foreach still needs explicit policy, implicit barrier state, lineage-aware
`GraphSourcePath`, but execution is still serial. patch commits, and quiescent interrupt handling. `ForeachNode.over` is typed
as a `GraphSourcePath`, but execution is still serial.
- Interrupt lifecycle is still node-level and run-state-level. Long-lived - Interrupt lifecycle is still node-level and run-state-level. Long-lived
external subscriptions or notification streams need a separate lifecycle external subscriptions or notification streams need a separate lifecycle
design. Interrupt `request` and `resume` are canonical binding lists; nested design. Interrupt `request` and `resume` are canonical binding lists; nested
@@ -92,12 +136,10 @@ limits and intended adapter seam.
- Saved workflow-as-node execution with interrupts requires a core runtime - Saved workflow-as-node execution with interrupts requires a core runtime
upgrade: nested run state, child-frame trace preservation, interrupt bubbling upgrade: nested run state, child-frame trace preservation, interrupt bubbling
with path metadata, and resume back into the child workflow. with path metadata, and resume back into the child workflow.
- Frames are currently a serial execution stack. That is enough for root - Frames are no longer only a serial execution stack: the runtime has a ready
workflow execution, serial foreach, and node-level interrupts, but async queue and `BLOCKED` frame state. Async parallel foreach and native subgraphs
parallel foreach and native subgraphs will stress the model. In particular, still need more work: lineage isolation, barrier merge semantics, pending
`RunState.current_frame_id` assumes one active cursor, `ExecutionFrame.metadata` child results, and explicit child workflow/deployment identity.
is ad hoc, and subgraph frames will need explicit child workflow/deployment
identity.
- Runtime errors are still ordinary exceptions plus failed run status. A richer - Runtime errors are still ordinary exceptions plus failed run status. A richer
error payload can be added later, but should be designed as part of trace/run error payload can be added later, but should be designed as part of trace/run
state rather than scattered exceptions. state rather than scattered exceptions.