feat(11-C4): play_run_async + play_wait + span_push + flow_library_search + play_start routing #20
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feat/11-phase-c4-rpcs-sse-routing"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Phase C4 of #11. Wires the executor (C3) into the LogicService trait so clients can drive Python flows over RPC, and routes the existing
play_startto the new path when aWorkflowVersionsetspython_source. SSE endpoint deliberately deferred — the broadcast plumbing is its own concern and Story 2 (#12) drives the UI that consumes it.What lands
play_run_async(workflow_sid, input_data, parent_span_id)→strparent_span_id(empty for top-level) becomes the parent of the child flow's root span viaHERO_FLOW_PARENT_SPAN. Rejects DAG-only versions.play_wait(play_sid, timeout_ms)→Playtimeout_ms == 0⇒ wait forever. 50ms polling.span_push(play_sid, event_json)→boolflow_library_search(query, limit)→[str]name+description, case-insensitive, name matches weighted 3×, newest-first within the same score bucket. v1 — no fuzzy / no vector similarity.play_start routing
When the resolved
WorkflowVersion.python_sourceis non-empty,play_startskips DAG validation entirely (nodes/edges aren't expected to populate for Python flows) and routes tospawn_python_flow. The DAG path stays as-is for old flows; Phase D removes it.span_socket refactor
Extracted
apply_event()body into a freeapply_event_to_playso bothSpanListenerand the new publicapply_event_json(whichspan_pushcalls) share one implementation. No behavior change.spawn_python_flow helper
Outcome →
ExecutionStatusmapping:Ok(outcome)+timed_outTimedOutOk(outcome)+exit_code == Some(0)SuccessFailedFailedAlways sets
completed_atandduration_msso the UI can render a finished play correctly.Tests (12 in
c4_testsmodule)flow_library_search: name-vs-description ranking, case insensitivity, limit, empty query, exclusion of non-matchesplay_wait: terminal-immediate-return (~ms), timeout-bound (~200ms)span_push: full lifecycle round-trip, malformed JSON rejectionplay_run_asyncPython path creates Running Play,play_run_asyncDAG workflow rejected with InvalidInput,play_startroutes bypython_sourcenon-emptyWhat's NOT here
GET /api/plays/:sid/spans(separate PR — needs broadcast channel throughSpanListenerand a UI route inhero_logic_ui)Phase plan (#11)
hero_tracing.pySDK (#16, merged)Test plan
cargo test -p hero_logic --lib c4_tests— 12/12 passcargo test --workspace --lib— 44 total, all greencargo build --workspaceclean🤖 Generated with Claude Code