diff options
| author | t <t@tjp.lol> | 2026-09-02 10:47:15 -0600 |
|---|---|---|
| committer | t <t@tjp.lol> | 2026-09-02 10:47:37 -0600 |
| commit | b206f895d9d3e82fcd2dc028d993b66ab0734011 (patch) | |
| tree | df77a6a1c3667a088c6082eda1ad89ae70d0aeac | |
| parent | fd2b3dfd85d8d87716481425216abc5e8cdd9c1b (diff) | |
Defer workflow completion wake until callback unwinds
| -rw-r--r-- | spec/test_luatool.lua | 9 | ||||
| -rw-r--r-- | subagents/workflow.lua | 12 |
2 files changed, 17 insertions, 4 deletions
diff --git a/spec/test_luatool.lua b/spec/test_luatool.lua index ee0a79e..013459f 100644 --- a/spec/test_luatool.lua +++ b/spec/test_luatool.lua @@ -27,7 +27,10 @@ local function pump(id) for _ = 1, 2000 do uv.run("nowait") local record = workflow.workflows[id] - if record and record.status ~= "running" then return record end + if record and record.status ~= "running" then + uv.run("nowait") -- deliver the deferred primary wake + return record + end uv.sleep(1) end error("workflow did not settle: " .. tostring(id), 0) @@ -113,8 +116,8 @@ return { assert(#handle.submissions == 1, "completion wakes the primary once") has(handle.submissions[1], id) assert(table.concat(handle.emitted, ",") == - "background_work_start,agent_submission,background_work_end", - "background work brackets the primary wake") + "background_work_start,background_work_end,agent_submission", + "the primary wake runs after the completion callback unwinds") end) end }, diff --git a/subagents/workflow.lua b/subagents/workflow.lua index ff534cb..28a76a6 100644 --- a/subagents/workflow.lua +++ b/subagents/workflow.lua @@ -760,7 +760,17 @@ local function notify(record) local submitted = pcall(primary.submit, primary, string.format( "[subagents] Workflow %s %s. Inspect subagents.workflows[%q] with subagents.lua.", record.id, record.status, record.id)) - if submitted then emit("agent_submission") end + if not submitted then return end + + -- Completion runs inside a host callback. Let it unwind before asking the + -- TUI to drain the queued submission; synchronous dispatch can observe a + -- transient busy state and leave that submission parked until another turn. + local timer = uv.new_timer() + timer:start(0, 0, function() + timer:stop() + timer:close() + emit("agent_submission") + end) end local function finish_workflow(record, status, result, err) |
