fix(workflow): honor subagent readiness boundary
This commit is contained in:
@@ -431,17 +431,17 @@ One `agent()` call settled (clean result, child failure, or run cancellation). P
|
||||
'workflow/agent-end'(info: WorkflowRunInfo, agent: WorkflowAgentEndInfo): void
|
||||
```
|
||||
|
||||
Source: [`packages/workflow/workflow/src/index.ts:96`](../../packages/workflow/workflow/src/index.ts)
|
||||
Source: [`packages/workflow/workflow/src/index.ts:98`](../../packages/workflow/workflow/src/index.ts)
|
||||
|
||||
### `workflow/agent-start` — emit
|
||||
|
||||
One `agent()` call started a child run. Paired with Events['workflow/agent-end'] by `agent.seq`.
|
||||
One `agent()` call established a ready child run. Paired with Events['workflow/agent-end'] by `agent.seq`. A call that never crosses the provider's publication/readiness boundary emits neither event in this pair.
|
||||
|
||||
```ts cordis-catalog
|
||||
'workflow/agent-start'(info: WorkflowRunInfo, agent: WorkflowAgentInfo): void
|
||||
```
|
||||
|
||||
Source: [`packages/workflow/workflow/src/index.ts:85`](../../packages/workflow/workflow/src/index.ts)
|
||||
Source: [`packages/workflow/workflow/src/index.ts:87`](../../packages/workflow/workflow/src/index.ts)
|
||||
|
||||
### `workflow/end` — emit
|
||||
|
||||
@@ -451,7 +451,7 @@ A workflow run settled (any stop reason). Fired when WorkflowRun.result resolves
|
||||
'workflow/end'(info: WorkflowRunInfo, result: WorkflowResultInfo): void
|
||||
```
|
||||
|
||||
Source: [`packages/workflow/workflow/src/index.ts:106`](../../packages/workflow/workflow/src/index.ts)
|
||||
Source: [`packages/workflow/workflow/src/index.ts:108`](../../packages/workflow/workflow/src/index.ts)
|
||||
|
||||
### `workflow/log` — emit
|
||||
|
||||
|
||||
@@ -331,7 +331,7 @@ Semantics every implementation must honor:
|
||||
abstract start(request: WorkflowStartRequest): WorkflowRun
|
||||
```
|
||||
|
||||
Source: [`packages/workflow/workflow/src/index.ts:210`](../../packages/workflow/workflow/src/index.ts)
|
||||
Source: [`packages/workflow/workflow/src/index.ts:214`](../../packages/workflow/workflow/src/index.ts)
|
||||
|
||||
## Inherited `ctx` members (cordis core + loader/hmr/timer)
|
||||
|
||||
|
||||
@@ -41,9 +41,9 @@ This matrix shows which packages dispatch each harness-owned event and which pac
|
||||
| `tools/post-execute` | `waterfall` | [`packages/core/tools/src/index.ts:151`](../packages/core/tools/src/index.ts) | [`tools`](../packages/core/tools) (`waterfall`) | [`hooks-claude`](../packages/hooks/hooks-claude), [`hooks-codex`](../packages/hooks/hooks-codex), [`repeat-tool-guard`](../packages/guard/repeat-tool-guard) |
|
||||
| `tools/pre-execute` | `waterfall` | [`packages/core/tools/src/index.ts:104`](../packages/core/tools/src/index.ts) | [`tools`](../packages/core/tools) (`waterfall`) | [`hooks-claude`](../packages/hooks/hooks-claude), [`hooks-codex`](../packages/hooks/hooks-codex) |
|
||||
| `tools/result` | `parallel` | [`packages/core/tools/src/index.ts:166`](../packages/core/tools/src/index.ts) | [`tools`](../packages/core/tools) (`events.dispatch`) | [`subagent-inprocess`](../packages/subagent/subagent-inprocess) |
|
||||
| `workflow/agent-end` | `emit` | [`packages/workflow/workflow/src/index.ts:96`](../packages/workflow/workflow/src/index.ts) | [`workflow`](../packages/workflow/workflow) (`events.dispatch`) | - |
|
||||
| `workflow/agent-start` | `emit` | [`packages/workflow/workflow/src/index.ts:85`](../packages/workflow/workflow/src/index.ts) | [`workflow`](../packages/workflow/workflow) (`events.dispatch`) | - |
|
||||
| `workflow/end` | `emit` | [`packages/workflow/workflow/src/index.ts:106`](../packages/workflow/workflow/src/index.ts) | [`workflow`](../packages/workflow/workflow) (`events.dispatch`) | - |
|
||||
| `workflow/agent-end` | `emit` | [`packages/workflow/workflow/src/index.ts:98`](../packages/workflow/workflow/src/index.ts) | [`workflow`](../packages/workflow/workflow) (`events.dispatch`) | - |
|
||||
| `workflow/agent-start` | `emit` | [`packages/workflow/workflow/src/index.ts:87`](../packages/workflow/workflow/src/index.ts) | [`workflow`](../packages/workflow/workflow) (`events.dispatch`) | - |
|
||||
| `workflow/end` | `emit` | [`packages/workflow/workflow/src/index.ts:108`](../packages/workflow/workflow/src/index.ts) | [`workflow`](../packages/workflow/workflow) (`events.dispatch`) | - |
|
||||
| `workflow/log` | `emit` | [`packages/workflow/workflow/src/index.ts:77`](../packages/workflow/workflow/src/index.ts) | [`workflow`](../packages/workflow/workflow) (`events.dispatch`) | - |
|
||||
| `workflow/phase` | `emit` | [`packages/workflow/workflow/src/index.ts:70`](../packages/workflow/workflow/src/index.ts) | [`workflow`](../packages/workflow/workflow) (`events.dispatch`) | - |
|
||||
| `workflow/start` | `emit` | [`packages/workflow/workflow/src/index.ts:62`](../packages/workflow/workflow/src/index.ts) | [`workflow`](../packages/workflow/workflow) (`events.dispatch`) | - |
|
||||
|
||||
@@ -553,8 +553,18 @@ SubagentService.start(...):
|
||||
attach result settlement handlers immediately
|
||||
await returnedRun.started
|
||||
emit subagent/start; later emit the buffered or eventual subagent/end
|
||||
|
||||
Workflow worker bridge after receiving returnedRun:
|
||||
register the run so cancellation can reach pre-publication work
|
||||
attach result settlement handlers immediately and snapshot the outcome
|
||||
if returnedRun.started fulfills:
|
||||
send ChildStarted; then send the buffered or eventual outcome
|
||||
else:
|
||||
send ChildStartError and dispose the attempt
|
||||
```
|
||||
|
||||
Every downstream protocol that announces a subagent must honor the same boundary. The workflow worker bridge therefore registers the returned run before waiting, observes and snapshots `result` immediately, sends `ChildStarted` only after `started` fulfills, and sends `ChildStartError` plus host-driven disposal when readiness rejects. This keeps cancellation able to reach pending creation, prevents an early result rejection from going unhandled, and ensures `workflow/agent-start` never names an unpublished child.
|
||||
|
||||
Parent teardown reaches `runOwner` by nesting; the provider and returned run handle reach the same node through their explicit disposers.
|
||||
|
||||
### Persona, filtering, and lifetime use ordinary registrations
|
||||
|
||||
Reference in New Issue
Block a user