Skip to content

fix: a State belongs to one run, not to the Pipeline - #13

Merged
JoshuaWink merged 2 commits into
betafrom
state-per-run
Oct 13, 2026
Merged

JoshuaWink merged 2 commits into
betafrom
state-per-run

Conversation

@JoshuaWink

@JoshuaWink JoshuaWink commented Oct 13, 2026 •

Copy link
Copy Markdown
Member

What

A State belongs to one run, not to the Pipeline. Closes #11.

Before this change, two runs of one Pipeline that were in progress at the same time wrote into one State, so their steps mixed.

The rule (conformance/API.md, "State")

  • Each run writes into a State of its own.
  • The caller can give the State: run(payload, state). A caller with more than one run at a time gives each run its own.
  • With no State from the caller, the run makes a new one.
  • state on the Pipeline is the State of the run that started last. It is for a caller with one run at a time.

Nothing breaks for a caller with one run at a time: run(payload) and pipeline.state work as before.

Changes

Python

  • run and run_async take an optional state. The State is a local of the run.
  • A second fault of the same kind is fixed. A Valve kept "was it skipped" on itself, and each run in progress shared that flag. A run that waited on an async Filter behind a Valve could read the answer of another run. The Pipeline now asks the Predicate itself and reads no flag from the Valve.

TypeScript

  • run takes an optional state. Each run already wrote into its own State; a caller had no way to get it when runs overlapped.

Conformance

  • Three new cases in cases/state.json: the caller gives the State, a run that starts inside another run has its own State, and state on the Pipeline is the State of the run that started last.
  • A new reference step, run_again, starts a second run of its own pipeline inside the first one. This makes two runs overlap in the same way in each runtime, with no threads and no timers.
  • The step does not hold a Pipeline. The runner gives it the way to run the pipeline again: a method of the Pipeline, or for a compiled form a second call of its function. So both compilers lower the step, and no case is unsupported on any target.
  • One check does not apply to a compiled form: state on the Pipeline object. A compiled form is a function and has no such object. That case passes there on what it can show.

Checks

  • Conformance: 30 of 30 on each of the 7 targets, and nothing is unsupported. The fast compiled forms show no State, so they pass those cases on the output.
  • Python tests: 510 pass. Four new tests use runs that really overlap (asyncio.gather). All four fail on the code before this change.
  • TypeScript tests pass, with two new tests for overlapping runs.
  • Both linters report nothing.
  • Speed check (Python 3.12): every number is within 25% of its baseline.

Not in this change

🤖 Generated with Claude Code

JoshuaWink and others added 2 commits October 12, 2026 22:45
Two runs of one Pipeline that were in progress at the same time wrote
into one State, so their steps mixed. Each run now writes into a State of
its own, and the caller can give it: run(payload, state).

Python: the State is a local of the run. The Pipeline asks the Predicate
of a Valve itself and no longer reads a flag from the Valve, which each
run in progress shared. TypeScript: run takes an optional State.

The contract has the rule, and three conformance cases: the caller gives
the State, and a run that starts inside another run.

Closes #11

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The reference step no longer holds a Pipeline. The runner gives it the
way to run the pipeline again: a method of the Pipeline, or for a
compiled form a second call of its function. Both compilers lower the
step, so no case is unsupported on any target.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@JoshuaWink
JoshuaWink merged commit 5e7bd01 into beta Oct 13, 2026
10 checks passed
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