Bug: sequential strategy does not enforce step chain order — sibling of parallel+reduce bug (nullboiler-62s)
Filed: 2026-07-28
Sibling: nullboiler-62s (parallel strategy reduce block fails with "unknown step type")
Upstream: will file at https://github.com/nullclaw/nullboiler/issues
Summary
When submitting a workflow with "strategy": "sequential" via POST /runs, the strategy expansion is supposed to add depends_on between consecutive steps (chain mode per strategies/sequential.json build field). In practice, all steps dispatch concurrently. A later step can complete BEFORE earlier steps, receiving empty {{state.X}} template values because the upstream step hasn't written its output_key yet.
Reproduction
Submit:
curl -X POST http://localhost:7720/runs \
-H "Content-Type: application/json" \
-d '{
"strategy": "sequential",
"steps": [
{"id":"slow_rca","type":"task","output_key":"rca","worker_tags":["researcher"],"prompt_template":"long analysis taking 60+s","timeout_ms":300000},
{"id":"review","type":"task","output_key":"review","worker_tags":["researcher"],"prompt_template":"review: {{state.rca}}"}
]
}'
Expected: review waits for slow_rca to complete, then dispatches with {{state.rca}} filled.
Actual: review dispatches immediately, completes in ~9s with "I can'\''t review nothing — RCA context came through empty". slow_rca times out at 120s later. Run marked failed.
Verified on ~/dev/nullboiler/local-deploy branch (commits c0e3648 + f5d23f7).
Same bug class as nullboiler-62s
nullboiler-62s covers the parallel strategy wrapping reduce as type:"reduce" (rejected by validator). This ticket covers sequential strategy NOT enforcing chain order. Both are strategy-expansion bugs — the user-supplied steps aren't transformed correctly before dispatch.
Workaround
Drop "strategy" field entirely and use manual depends_on for chain:
{
"steps": [
{"id":"a","type":"task","output_key":"a_out",...,"timeout_ms":300000},
{"id":"b","type":"task","output_key":"b_out","depends_on":["a"],"prompt_template":"... {{state.a_out}} ..."}
]
}
Verified working — outputs chain correctly, step B waits for step A's output_key to land in state.
Suspected root cause
src/strategy.zig expandStrategy() for chain mode adds depends_on to the steps, but the engine (src/engine.zig) doesn't enforce depends_on ordering at dispatch time — it dispatches any ready step regardless of whether its dependencies are completed.
Per odb9 finding #7, step table rows are "decorative" — truth is in checkpoints + state. This may extend to depends_on: declared but not enforced.
Acceptance
Bug:
sequentialstrategy does not enforce step chain order — sibling ofparallel+reducebug (nullboiler-62s)Filed: 2026-07-28
Sibling:
nullboiler-62s(parallel strategy reduce block fails with "unknown step type")Upstream: will file at https://github.com/nullclaw/nullboiler/issues
Summary
When submitting a workflow with
"strategy": "sequential"viaPOST /runs, the strategy expansion is supposed to adddepends_onbetween consecutive steps (chain mode perstrategies/sequential.jsonbuild field). In practice, all steps dispatch concurrently. A later step can complete BEFORE earlier steps, receiving empty{{state.X}}template values because the upstream step hasn't written itsoutput_keyyet.Reproduction
Submit:
Expected: review waits for slow_rca to complete, then dispatches with
{{state.rca}}filled.Actual: review dispatches immediately, completes in ~9s with
"I can'\''t review nothing — RCA context came through empty". slow_rca times out at 120s later. Run marked failed.Verified on
~/dev/nullboiler/local-deploybranch (commits c0e3648 + f5d23f7).Same bug class as nullboiler-62s
nullboiler-62scovers the parallel strategy wrapping reduce astype:"reduce"(rejected by validator). This ticket covers sequential strategy NOT enforcing chain order. Both are strategy-expansion bugs — the user-supplied steps aren't transformed correctly before dispatch.Workaround
Drop
"strategy"field entirely and use manualdepends_onfor chain:{ "steps": [ {"id":"a","type":"task","output_key":"a_out",...,"timeout_ms":300000}, {"id":"b","type":"task","output_key":"b_out","depends_on":["a"],"prompt_template":"... {{state.a_out}} ..."} ] }Verified working — outputs chain correctly, step B waits for step A's output_key to land in state.
Suspected root cause
src/strategy.zig expandStrategy()for chain mode addsdepends_onto the steps, but the engine (src/engine.zig) doesn't enforce depends_on ordering at dispatch time — it dispatches anyreadystep regardless of whether its dependencies are completed.Per odb9 finding #7, step table rows are "decorative" — truth is in checkpoints + state. This may extend to depends_on: declared but not enforced.
Acceptance
{{state.X}}populated