feat: command.execute returns the lifecycle pairing id ({matched, commandId?})

CommandService.execute now returns a CommandExecution — the normalized
result plus the commandId minted for its command/run/command/done records —
and the wire admission value carries commandId exactly when matched, so the
issuing client can correlate its RPC acknowledgment with the flow node the
lifecycle events produce. apiproxy api/schema/handler, the connection
fixture, and the TUI/plan/goal consumers follow the new shape.
This commit is contained in:
imccyu
2026-07-27 21:05:15 +08:00
parent 2ebaa30c6d
commit 6d2e5a7cd7
21 changed files with 85 additions and 55 deletions

View File

@@ -72,14 +72,14 @@ function domainEvents(session: Session): readonly Session['events'][number][] {
}
/** Execute `/goal` through the same registry boundary as a UI adapter. */
async function run(test: Harness, suffix = ''): Promise<NonNullable<Awaited<ReturnType<CommandService['execute']>>>> {
const result = await test.ctx.commands.execute(
async function run(test: Harness, suffix = ''): Promise<NonNullable<Awaited<ReturnType<CommandService['execute']>>>['result']> {
const execution = await test.ctx.commands.execute(
test.agent,
`/goal${suffix}`,
new AbortController().signal,
)
if (result === undefined) throw new Error('goal command was not registered')
return result
if (execution === undefined) throw new Error('goal command was not registered')
return execution.result
}
/** Current exact compare-and-set ref. */