refactor: command.execute degrades to pure admission; composer notice channel retired

The wire response now carries only the matched bit — CommandExecuteResult
is deleted from the api, schema, and client mirrors (pre-release, no shim);
outcomes ride the durably logged command/run/command/done pair broadcast on
the mux stream and render as flow nodes. ui-command's runDetached→noticeFor
outcome routing is retired: admitted commands surface nothing through the
composer, while admission misses (matched:false, syntax feedback) and
transport failures keep their immediate notice. The connection fixture
mirrors the host: an admitted command appends the lifecycle pair to the
session log instead of returning result text.
This commit is contained in:
imccyu
2026-07-27 17:38:24 +08:00
parent ba928c5517
commit 4ddec0ba2f
17 changed files with 110 additions and 90 deletions

View File

@@ -91,7 +91,7 @@ function fakeApi(overrides: Partial<{ muxFrames: MuxFrame[]; hostFrames: HostFra
return { rpcId: request.rpcId, result: { ok: false, error: { code: 'cancelled', message: 'aborted', details: {} } } }
}
if (request.payload.line.startsWith('/plan')) {
return { rpcId: request.rpcId, result: { ok: true, value: { matched: true, result: { kind: 'success' as const, text: 'plan set' } } } }
return { rpcId: request.rpcId, result: { ok: true, value: { matched: true } } }
}
return { rpcId: request.rpcId, result: { ok: true, value: { matched: false } } }
},
@@ -163,7 +163,7 @@ describe('unary round trip (handler ⇄ client, no network)', () => {
const list = await c.commands.list({ sessionId: 's' as never })
expect(list.result).toEqual({ ok: true, value: { commands: [{ name: 'plan', description: 'Toggle plan mode', input: { hint: 'on|off' } }] } })
const hit = await c.commands.execute({ sessionId: 's' as never, line: '/plan off' })
expect(hit.result).toEqual({ ok: true, value: { matched: true, result: { kind: 'success', text: 'plan set' } } })
expect(hit.result).toEqual({ ok: true, value: { matched: true } })
const miss = await c.commands.execute({ sessionId: 's' as never, line: '/nope' })
expect(miss.result).toEqual({ ok: true, value: { matched: false } })
const skills = await c.skills.list({ sessionId: 's' as never })