Skip to content

fix(runtime-python): resolve QA findings RT-06/07/12/14 - #16

Merged
jascal merged 3 commits into
mainfrom
fix/python-runtime-qa-findings
Jun 2, 2026
Merged

fix(runtime-python): resolve QA findings RT-06/07/12/14#16
jascal merged 3 commits into
mainfrom
fix/python-runtime-qa-findings

Conversation

@jascal

@jascal jascal commented Jun 2, 2026

Copy link
Copy Markdown
Owner

Summary

Fixes four confirmed runtime bugs in packages/runtime-python documented in reports/python-runtime-qa-report.md. Each was reproduced end-to-end through parse_orca_md + OrcaMachine before fixing, and each is covered by a regression test.

ID Sev Fix
RT-12 HIGH Thread the triggering Event through guard evaluation (_evaluate_guard → _eval_guard → _eval_compare/_eval_nullcheck → _resolve_variable). A path led by event/payload now resolves against the event payload; everything else resolves against context as before. Previously event.amount > 100 resolved to context["event"]None.
RT-14 MED Ordered comparisons (< > <= >=) now require numeric operands (numeric strings still coerce); None/non-numeric operands fail closed (False) instead of falling back to lexicographic str() compare. eq/ne unchanged.
RT-06 MED _execute_entry_actions runs on_entry first, then starts the invoked child (XState order), instead of an early return that dropped on_entry. Entry logic extracted to _run_on_entry.
RT-07 MED-HIGH New _resume_children() rehydrates active_invoke and re-instantiates/re-resumes each invoked child (completion handler factored into _make_child_done_handler). Wired into both resume() and restore(). A machine that crashed inside an invoke state is no longer permanently wedged.

RT-12 + RT-14 were fixed together — RT-14 masked RT-12 (str(None) > "100" was True).

Resume/persistence contract (RT-07)

Conservative version as proposed in the report: sibling defs (register_machines) and action handlers must be re-registered before resume()/restore(); a child snapshot whose machine isn't a registered sibling is skipped with a UserWarning, not silently dropped or raised. Consistent with the existing start-path limitation.

Testing

  • 9 new regression tests in tests/test_qa_fixes.py (incl. an explicit "resumed machine is not wedged" test that drives a rehydrated child to completion and confirms the parent reaches on_done).
  • Full runtime-python suite: 115 passed (was 106).
  • Downstream consumers green: demo-nanolab 47 passed, demo-python smoke completes.

Docs

  • docs/runtime-python-production-hardening.md — added "Runtime correctness fixes (RT-06/07/12/14)" section + summary-table rows.
  • reports/python-runtime-qa-report.md — status updated to Fixed with a resolution note.

Note

restore() also now rehydrates children (the report named both resume()/restore(), though its repro targeted resume()). All pre-existing restore tests still pass — additive.

🤖 Generated with Claude Code

jascal and others added 3 commits June 2, 2026 17:40
Four confirmed runtime bugs from reports/python-runtime-qa-report.md, all
reproduced end-to-end and covered by regression tests in
tests/test_qa_fixes.py (9 tests). Full suite: 115 passed (was 106).

- RT-12 (HIGH): thread the triggering Event through guard evaluation so
  `event.*` guards resolve against the payload instead of None.
- RT-14 (MED): ordered comparisons (< > <= >=) fail closed on None/non-numeric
  operands instead of falling back to lexicographic string compare. RT-14 was
  masking RT-12, so the two are fixed together.
- RT-06 (MED): run a state's on_entry before starting its invoked child
  (XState order) instead of dropping on_entry via an early return.
- RT-07 (MED-HIGH): resume()/restore() rehydrate invoked child machines and
  active_invoke via _resume_children(), so a machine that crashed inside an
  invoke state is no longer permanently wedged. Sibling defs must be
  re-registered before resume; a missing sibling is skipped with a warning.

Fixes documented in docs/runtime-python-production-hardening.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… mixed-operand guard test

Addresses PR #16 review nits:
- _resolve_variable docstring: state that ctx/context segments are skipped
  (ctx.amount and amount are equivalent).
- _resume_children missing-sibling warning now names the exact
  register_machines({...}) call to make it actionable.
- Add test_rt12_mixed_event_and_ctx_operands: a single comparison
  (event.amount > ctx.limit) that exercises both the event-payload and
  context resolution paths, guarding the resolution logic against regression.

Suite: 116 passed (10 in test_qa_fixes.py).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds the changeset that drives CI to bump the whole release train to v0.1.29
(the fixed npm group bumps together; CI then syncs pyproject.toml + server.json
and tags v0.1.29, triggering the publish workflow). Also bumps the
runtime-python __init__.__version__ to match and adds a root CHANGELOG entry
for the GitHub release notes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@jascal
jascal merged commit 5daafbb into main Jun 2, 2026
2 checks passed
@jascal
jascal deleted the fix/python-runtime-qa-findings branch June 2, 2026 22:03
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