0.4.3 (July 3, 2026)

This release hardens checkpoint and DLQ correctness, improves worker and health server lifecycle safety, and promotes several runtime helpers to public API status so integrations and tests can rely on supported accessors instead of white-box internals.

Runtime correctness

  • Middleware failures that cannot be durably routed to the DLQ no longer allow later records to advance checkpoint state past the unresolved failure.
  • Fail-closed batch delivery now stops at the first unrouted failed record in a failed batch instead of letting later records in that batch advance checkpoints or success hooks.
  • Sink write result normalization now returns fresh per-record WriteResult objects instead of reusing shared mutable success or error state.

Recovery and state

  • DLQ replay no longer increments replay attempts when replay pipeline construction fails before the retry can actually run.
  • SQLite DLQ storage now upgrades legacy schemas in place to add retry-tracking columns such as attempt and max_attempts.
  • Memory and SQLite state backends now ignore expired entries in count_prefix results.
  • In-memory dedup LRU tracking now respects TTL expiry, and HTTP cache stats no longer count expired rows as live cache entries.

Worker and health lifecycle

  • WorkerPool now rejects duplicate pipeline registration by object identity or pipeline_id.
  • Worker startup cleans up coordinator state, signal handlers, and background tasks correctly when partial initialization fails.
  • Worker live metrics and lease-gating hooks now compose with user-provided callbacks instead of overwriting them.
  • Schedule.wait_after_skip() keeps skipped interval and cron runs on their configured cadence while still preventing hot-spin for continuous schedules.
  • HealthServer now returns 405 Method Not Allowed for non-GET requests, authenticates only /health, /metrics, and /ready, and can be stopped and started again safely on the same instance.

Public API and typing

  • Pipeline.pipe() and MiddlewareChain now expose tighter middleware typing via public middleware protocols.
  • BoundPipeline.config is now a public accessor for the normalized runtime configuration.
  • PipelineContext now exposes trace_depth, start_trace_span(), and finish_trace_span().
  • MetricsCollector.pipeline_stats() and MetricsCollector.pipeline_stats_map() are now public snapshot accessors, with get() and all() retained as compatibility aliases.
  • AIMiddleware.provider, AIMiddleware.cache, and AIMiddleware.render_prompt() are now supported public helpers.
  • WorkerPool.health_port is now exposed as a public property.

Upgrade notes

  • No config migration is required for existing 0.4.x pipelines.
  • SQLite-backed DLQ and state stores are upgraded in place when opened.
  • Teams with custom middleware extensions may see stricter type-checking around Pipeline.pipe() and MiddlewareChain; adopting the public middleware protocols is the forward-compatible path.