Skip to content

v0.32.3

Choose a tag to compare

@github-actions github-actions released this 19 Sep 22:28
· 3 commits to main since this release

v0.32.3 (2026-09-19)

Fix

  • fix(execution): align async engine with sync engine semantics (audit follow-up) (#133)

  • fix(execution): align async engine with sync engine semantics (sync is canonical)

Body: ports the async engine onto the sync engine's observable contract.

  • publish() routes on compiled publish_plan.strategy and completion_policy
  • output contracts validated at publish (TypeError), like sync
  • materializer crashes propagate; mid-stream item failures keep sync prefix semantics (valid prefix + had_error) with lazy out-of-core access preserved
  • producer failures delivered in-band to consumers under any on_error policy (no silent truncation under CONTINUE)
  • PipelineStopException queued to consumers carries its cause
  • execute() awaits cleanup in finally; cleanup() logs instead of silent pass
  • terminal lazy streams stored in executor.outputs like sync
  • builder compiles fn_kind + async_stream_deps; runtimes consult metadata, not runtime introspection
  • builder compiles publish_async_fanout for single-consumer async streams (EACH consumers unroll via queue branches)
  • dropped dead _is_stream_output helpers

Tests updated to canonical contract: annotated under-annotated async generators, fixed the async threshold helper that silently disconnected producer from consumer (broken copy of sync twin), mirrored in-band failure handoff test in sync.

  • refactor(core): remove dead builder code, collapse duplicated validators, fail loud on cycles
  • delete the unreachable 'requires a custom materializer' validation in
    _resolve_materializers (the factory identity it checked had already
    been resolved away) together with its now-unused _is_builtin_type
    helper; a regression test locks in that the default memory factory
    handles custom item types
  • collapse _validate_no_async_handlers/_validate_no_sync_handlers
    (~130 near-duplicate lines) into one parameterized
    _validate_handler_execution_modes; error messages preserved
  • replace the vacuous _validate_declared_step_names duplicate-name call
    (it passed an empty dag, so only the reserved check could fire) with
    an explicit validate_reserved_step_name; duplicate detection stays in
    the expanded pass where it works
  • get_execution_levels now raises a descriptive ValueError when the
    remaining nodes form a cycle instead of silently returning a partial
    topological order (regression test added)
  • delete dead _check_scalar_producer_to_iterable_consumer
  • drop the import("typing").Union hack; reuse core
    is_async_callable in composite materializers (superset: also detects
    partials and async callable objects)
  • add module docstring to composite.py
  • test(corpus): register orphaned nested_fanout packs, fix async linear drift, harden corpus hygiene
  • nested_fanout corpus packs existed in both engines but were never
    registered in _MODULES — dead specification. Both packs are now
    complete (frozen json_dag, execution levels, step results) and
    registered; the build-time corpus tests now cover the nested
    fan-out/fan-in topology. NOTE: executing this topology currently
    deadlocks the sync engine (workers block) — tracked separately; the
    runtime step-results assertions stay unregistered until that is
    fixed (see step_results explicit pack lists)
  • fix real sync/async drift in the linear corpus pack: the async twin
    silently dropped the step-level observer its sync twin declares
    (with the frozen observers json entry) — mirrored with an
    async-adapted handler
  • add a corpus symmetry meta-test: pack sets must match across engines
    (modulo the documented sync-only threadpool pack) so an orphaned or
    engine-missing pack can never happen silently again
  • test_runner_step_results (both engines): a failing iterator now
    propagates instead of being swallowed into a truncated 'passing' list
  • conftest run_pipeline fixture: document why it is sync-only
    (pipelines are engine-specific by contract; parity lives in the
    twins + corpus + meta-test) and drop the misleading dead async branch
  • PipelinePack.expected_dag was never populated and never read: removed
  • test_dag_builder_future docstring no longer claims xfail semantics
    for passing contract tests
  • style: module docstrings, English state.py docs, small type-hint gaps
  • add purposeful module docstrings to the modules flagged in the audit
    (core build/validation modules, both executors and step runners,
    handoff, stats, overrides, materializers)
  • translate ExecutionState docstrings to English (language consistency)
    and make seed() fail loud on unsupported params types instead of
    crashing on AttributeError (plain dict now accepted)
  • type the previously untyped _identity / async_adapter signatures
  • add direct unit tests for ExecutionState (seeding, consumer-scoped
    keys, inputs_available) — previously covered only transitively; live
    under tests/execution/ since the module is engine-agnostic

Co-authored-by: Marcelo Elias Del Valle <marcelo@mvalle.br> (0b4097a)