Skip to content

Comments

feat(scxml): add <invoke> parsing and runtime support#575

Merged
fgmacedo merged 6 commits intodevelopfrom
feat/scxml-invoke
Feb 21, 2026
Merged

feat(scxml): add <invoke> parsing and runtime support#575
fgmacedo merged 6 commits intodevelopfrom
feat/scxml-invoke

Conversation

@fgmacedo
Copy link
Owner

Summary

  • Parse SCXML <invoke> elements and wire them through the existing Python-level invoke infrastructure (IInvoke protocol, InvokeManager)
  • New SCXMLInvoker handler (io/scxml/invoke.py) that resolves child state machines from <content> or src=, evaluates <param> and namelist, handles autoforward and finalize
  • Parser support for <invoke>, <content> (inline SCXML), <param>, <finalize>, namelist
  • Engine hooks: handle_external_event() on InvokeManager for finalize/autoforward routing
  • Fix async processing loop early exit to properly resolve caller_future (prevents hang when SM terminates)
  • Fix finalize blocks running even after invocation terminates (race condition with child thread completion)
  • 19 W3C invoke tests now passing (removed from xfail sets); 7 remaining invoke-related xfails need deeper work (delayed send cancellation, autoforward loops, namelist error handling)

Base automatically changed from refactor/scxml-xfail-sets to develop February 19, 2026 20:06
Parse SCXML <invoke> elements and wire them through the existing
Python-level invoke infrastructure (IInvoke protocol, InvokeManager).

Key changes:
- New SCXMLInvoker handler (io/scxml/invoke.py) implementing IInvoke
- Parser support for <invoke>, <content>, <param>, <finalize>, namelist
- Processor wiring: InvokeDefinition → SCXMLInvoker → State(invoke=)
- Engine hooks: handle_external_event for finalize/autoforward routing
- Fix async processing loop early exit resolving caller_future
- Fix finalize running even after invocation terminates (race condition)
- 19 W3C invoke tests now passing (removed from xfail sets)
… catching for transition content

Implement two fixes for SCXML W3C tests 192 and 253:

1. Add #_<invokeid> send target support — the SCXML convention for
   parent-to-child event routing. Events are forwarded through
   InvokeManager.send_to_child() to the child handler's on_event().
   Unreachable targets queue error.communication.

2. Wrap transition `on` content with on_error so errors are caught
   per-block (SCXML spec §5.12.1). Previously, errors in transition
   actions caused full microstep rollback; now the transition completes
   and error.execution is queued separately. During error.execution
   processing, on_error is disabled for transition content to prevent
   infinite loops in self-transition error handlers.

Also includes:
- Decouple SCXMLInvoker from processor (takes base_dir + register_child)
- Add invoke_init callback for invoked child machines
- Thread leak detection fixture and interruptible wait fixes
- Unit tests for _send_to_invoke and SCXMLInvoker
- Documentation updates for invoke, error handling, and release notes
@codecov
Copy link

codecov bot commented Feb 21, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (a6e57a6) to head (446ddb1).
⚠️ Report is 6 commits behind head on develop.

Additional details and impacted files
@@            Coverage Diff            @@
##           develop      #575   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           33        33           
  Lines         4051      4116   +65     
  Branches       639       661   +22     
=========================================
+ Hits          4051      4116   +65     
Flag Coverage Δ
unittests 100.00% <100.00%> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Invoke handlers run in background threads, outside the processing loop.
Using the internal queue would either contaminate an unrelated macrostep
or stall indefinitely. This matches done.invoke, which also uses the
external queue for the same reason.
Add 19 tests covering uncovered lines in modified files:
- EventDataWrapper edge cases (no args, __getattr__, name via trigger_data)
- _send_to_parent namelist errors and param expr=None skip
- _send_to_invoke param without expr skip
- invoke_init idempotent behavior
- SCXMLInvoker: on_event exception, non-string content, param location
- Parser: <assign> child XML/text, <invoke> text content
- InvokeManager: send_to_child not found / no on_event, null event
- _stop_child_machine exception handling
- BaseEngine.__del__ cancel_all exception
- Async engine error in before callbacks

Also fix _make_invoker to not hardcode /tmp, and document
coverage report commands in AGENTS.md.
The `child.find("{http://www.w3.org/2005/07/scxml}scxml")` call was
unreachable because `strip_namespaces()` always runs before
`parse_invoke()`. Replaced with direct `child.find("scxml")`.

Also added a test for unknown child elements inside `<invoke>`.
@sonarqubecloud
Copy link

@fgmacedo fgmacedo merged commit 8d012fe into develop Feb 21, 2026
14 checks passed
@fgmacedo fgmacedo deleted the feat/scxml-invoke branch February 21, 2026 03:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant