Skip to content

Commit e75880d

Browse files
committed
Fix PRD runtime gaps and align docs
1 parent 50591f0 commit e75880d

14 files changed

Lines changed: 566 additions & 172 deletions

File tree

docs/prd-implementation-review.md

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
# PRD Review Against Current Implementation
2+
3+
Date: 2026-03-23
4+
5+
This review compares [prd.md](/home/bretuobay/prjts/multimodal-user-interfaces-framework/docs/prd.md) to the current repository state. It focuses on observable implementation, shipped package surface, and demo/docs behavior.
6+
7+
## Executive Summary
8+
9+
The current repository is materially ahead of the PRD roadmap in package breadth, but behind the PRD in a few core runtime guarantees.
10+
11+
- The PRD still presents the project as Phase 1 complete with Phase 2 and 3 mostly future work, but the repo already ships `audio`, `video`, `motion`, `vue`, `solid`, `wc`, and `devtools` packages and a docs site labeled "Phase 3" ([docs/prd.md:440](/home/bretuobay/prjts/multimodal-user-interfaces-framework/docs/prd.md#L440), [apps/docs/app/page.tsx:7](/home/bretuobay/prjts/multimodal-user-interfaces-framework/apps/docs/app/page.tsx#L7), [packages/audio/src/index.ts:1](/home/bretuobay/prjts/multimodal-user-interfaces-framework/packages/audio/src/index.ts#L1), [packages/devtools/src/index.ts:1](/home/bretuobay/prjts/multimodal-user-interfaces-framework/packages/devtools/src/index.ts#L1)).
12+
- Several headline PRD behaviors are not implemented as specified: `Channel.sink.writable` is not connected to the outbound stream, async-generator `ActionDefinition` final return values are not recovered correctly, the React agent path does not receive streaming progress, and devtools channel tracking does not match the emitted session event payload ([packages/core/src/channel.ts:97](/home/bretuobay/prjts/multimodal-user-interfaces-framework/packages/core/src/channel.ts#L97), [packages/core/src/session.ts:185](/home/bretuobay/prjts/multimodal-user-interfaces-framework/packages/core/src/session.ts#L185), [packages/core/src/action.ts:190](/home/bretuobay/prjts/multimodal-user-interfaces-framework/packages/core/src/action.ts#L190), [packages/agent/src/agent-channel.ts:108](/home/bretuobay/prjts/multimodal-user-interfaces-framework/packages/agent/src/agent-channel.ts#L108), [packages/react/src/use-agent.ts:57](/home/bretuobay/prjts/multimodal-user-interfaces-framework/packages/react/src/use-agent.ts#L57), [packages/devtools/src/session-inspector.ts:28](/home/bretuobay/prjts/multimodal-user-interfaces-framework/packages/devtools/src/session-inspector.ts#L28)).
13+
- The PRD’s demo/documentation references are stale. The PRD says the Phase 1 demo is complete in `apps/web/app/chat`, but that route now redirects to `/` and the chat demo actually renders from the home page ([docs/prd.md:442](/home/bretuobay/prjts/multimodal-user-interfaces-framework/docs/prd.md#L442), [apps/web/app/chat/page.tsx:1](/home/bretuobay/prjts/multimodal-user-interfaces-framework/apps/web/app/chat/page.tsx#L1), [apps/web/app/page.tsx:1](/home/bretuobay/prjts/multimodal-user-interfaces-framework/apps/web/app/page.tsx#L1)).
14+
15+
## Where Implementation Is Ahead Of The PRD
16+
17+
### Roadmap state is understated
18+
19+
The PRD positions these as future phases:
20+
21+
- Phase 2: `@muix/audio`, `@muix/video`, `@muix/motion`, `@muix/vue`, `@muix/wc` ([docs/prd.md:458](/home/bretuobay/prjts/multimodal-user-interfaces-framework/docs/prd.md#L458))
22+
- Phase 3: `@muix/solid`, `@muix/devtools`, WebXR extension, full docs ([docs/prd.md:472](/home/bretuobay/prjts/multimodal-user-interfaces-framework/docs/prd.md#L472))
23+
24+
Current repo state already exports those packages:
25+
26+
- Audio is present with `AudioChannel`, `MicrophoneSource`, `AudioWorkletSink`, and VAD helpers ([packages/audio/src/index.ts:9](/home/bretuobay/prjts/multimodal-user-interfaces-framework/packages/audio/src/index.ts#L9))
27+
- Video is present with `VideoChannel`, `CameraSource`, and `CanvasSink` ([packages/video/src/index.ts:8](/home/bretuobay/prjts/multimodal-user-interfaces-framework/packages/video/src/index.ts#L8))
28+
- Motion is present with `MotionChannel`, `PointerSource`, `DeviceOrientationSource`, and gesture recognition ([packages/motion/src/index.ts:15](/home/bretuobay/prjts/multimodal-user-interfaces-framework/packages/motion/src/index.ts#L15))
29+
- Vue, Solid, WC, and DevTools packages all export usable surfaces today ([packages/vue/src/index.ts:1](/home/bretuobay/prjts/multimodal-user-interfaces-framework/packages/vue/src/index.ts#L1), [packages/solid/src/index.ts:1](/home/bretuobay/prjts/multimodal-user-interfaces-framework/packages/solid/src/index.ts#L1), [packages/wc/src/index.ts:1](/home/bretuobay/prjts/multimodal-user-interfaces-framework/packages/wc/src/index.ts#L1), [packages/devtools/src/index.ts:1](/home/bretuobay/prjts/multimodal-user-interfaces-framework/packages/devtools/src/index.ts#L1))
30+
- The docs home page explicitly labels the current state as `v0.1.0 — Phase 3` ([apps/docs/app/page.tsx:7](/home/bretuobay/prjts/multimodal-user-interfaces-framework/apps/docs/app/page.tsx#L7))
31+
32+
### Capability scope is ahead of the PRD text
33+
34+
The PRD’s built-in probe list mentions microphone, camera, screen, speech synthesis, speech recognition, and WebRTC ([docs/prd.md:180](/home/bretuobay/prjts/multimodal-user-interfaces-framework/docs/prd.md#L180)). Current exports also include WebXR capability probes (`immersive-vr`, `immersive-ar`, `inline`) ([packages/capability/src/index.ts:15](/home/bretuobay/prjts/multimodal-user-interfaces-framework/packages/capability/src/index.ts#L15), [packages/capability/src/probes/webxr.ts:34](/home/bretuobay/prjts/multimodal-user-interfaces-framework/packages/capability/src/probes/webxr.ts#L34)).
35+
36+
## Where Implementation Matches The PRD Broadly
37+
38+
- Core package structure exists as described: observable, signal, channel, action, session, capability registry, policy engine, text channel, and agent channel are all present as first-class packages and exports.
39+
- The repo is a Turborepo monorepo with package-per-concern organization, matching the PRD’s architecture and build assumptions ([package.json:4](/home/bretuobay/prjts/multimodal-user-interfaces-framework/package.json#L4)).
40+
- The demo API route uses SSE-style streaming responses, which aligns with the PRD’s streaming-first design for agent interactions ([apps/web/app/api/chat/route.ts:1](/home/bretuobay/prjts/multimodal-user-interfaces-framework/apps/web/app/api/chat/route.ts#L1)).
41+
42+
## Gaps And Contradictions
43+
44+
### 1. `Channel` does not satisfy the PRD’s duplex contract
45+
46+
The PRD defines `Channel` as a duplex primitive with `source.readable` and `sink.writable`, where the writable side writes into the channel ([docs/prd.md:75](/home/bretuobay/prjts/multimodal-user-interfaces-framework/docs/prd.md#L75)). In the implementation, `sink.writable` is backed by `_inboundTransform`, but that stream is never connected to `_transform`, `source.readable`, or `observe()` ([packages/core/src/channel.ts:65](/home/bretuobay/prjts/multimodal-user-interfaces-framework/packages/core/src/channel.ts#L65), [packages/core/src/channel.ts:97](/home/bretuobay/prjts/multimodal-user-interfaces-framework/packages/core/src/channel.ts#L97), [packages/core/src/channel.ts:107](/home/bretuobay/prjts/multimodal-user-interfaces-framework/packages/core/src/channel.ts#L107)).
47+
48+
Impact:
49+
50+
- `sink.writable` is effectively dead from a consumer perspective.
51+
- The PRD’s source/sink abstraction and threading model are overstated in current code.
52+
- Packages built around sources and sinks are relying on `send()` and `observe()`, not on the advertised duplex wiring.
53+
54+
### 2. Async-generator actions do not preserve final return values correctly
55+
56+
The PRD explicitly supports `ActionDefinition.execute()` returning an async generator whose yielded values are progress and whose return value is the final result ([docs/prd.md:146](/home/bretuobay/prjts/multimodal-user-interfaces-framework/docs/prd.md#L146)). Both `Session.dispatch()` and `runAction()` consume the generator with `for await` and then call `gen.return(undefined)` to recover the result ([packages/core/src/session.ts:185](/home/bretuobay/prjts/multimodal-user-interfaces-framework/packages/core/src/session.ts#L185), [packages/core/src/action.ts:190](/home/bretuobay/prjts/multimodal-user-interfaces-framework/packages/core/src/action.ts#L190)).
57+
58+
That does not recover the generator’s original return value after normal completion. The likely outcome is an `undefined` final result for async-generator actions.
59+
60+
Impact:
61+
62+
- The documented `ActionDefinition` contract is not reliable for generator-based actions.
63+
- Scenario flows that depend on progress plus final result are underspecified in tests.
64+
65+
### 3. React agent streaming path is inconsistent with `AgentChannel`
66+
67+
The PRD’s Scenario 1 depends on `AgentChannel.sendMessage()` driving `useAgent().streamingText` during the stream ([docs/prd.md:379](/home/bretuobay/prjts/multimodal-user-interfaces-framework/docs/prd.md#L379)). In code:
68+
69+
- `useAgent()` listens to `action.observe()` and expects `progress.partial` to contain `AgentStreamFrame[]` snapshots ([packages/react/src/use-agent.ts:57](/home/bretuobay/prjts/multimodal-user-interfaces-framework/packages/react/src/use-agent.ts#L57))
70+
- `AgentChannel.sendMessage()` accumulates frames locally, but never calls `action._emitProgress(...)` ([packages/agent/src/agent-channel.ts:65](/home/bretuobay/prjts/multimodal-user-interfaces-framework/packages/agent/src/agent-channel.ts#L65))
71+
72+
Impact:
73+
74+
- `streamingText` and `streamFrames` in the React hook are not updated from the action path as implemented.
75+
- The current React demo path does not match the PRD’s stated streaming flow.
76+
- This gap is not covered by the current React tests, which only validate `useSignal` and session context behavior ([packages/react/src/test/hooks.test.tsx:1](/home/bretuobay/prjts/multimodal-user-interfaces-framework/packages/react/src/test/hooks.test.tsx#L1)).
77+
78+
### 4. DevTools channel tracking is wired to the wrong event payload
79+
80+
Phase 3 in the PRD calls for a working devtools inspector ([docs/prd.md:487](/home/bretuobay/prjts/multimodal-user-interfaces-framework/docs/prd.md#L487)). `SessionInspector` subscribes to `channel:added` but expects the event payload to contain a `channel` object ([packages/devtools/src/session-inspector.ts:27](/home/bretuobay/prjts/multimodal-user-interfaces-framework/packages/devtools/src/session-inspector.ts#L27)). `Session` actually emits `{ channelId }` only ([packages/core/src/session.ts:166](/home/bretuobay/prjts/multimodal-user-interfaces-framework/packages/core/src/session.ts#L166)).
81+
82+
Impact:
83+
84+
- Devtools cannot create `ChannelTracer` instances from session events as written.
85+
- The package exists, but one of its core runtime integrations is currently broken.
86+
87+
### 5. Demo and quick-start references are stale
88+
89+
The PRD says the Phase 1 exit criterion is a working chat demo in `apps/web/app/chat` ([docs/prd.md:442](/home/bretuobay/prjts/multimodal-user-interfaces-framework/docs/prd.md#L442)). The actual `apps/web/app/chat/page.tsx` just redirects to `/` ([apps/web/app/chat/page.tsx:1](/home/bretuobay/prjts/multimodal-user-interfaces-framework/apps/web/app/chat/page.tsx#L1)), and the app root renders the chat component ([apps/web/app/page.tsx:1](/home/bretuobay/prjts/multimodal-user-interfaces-framework/apps/web/app/page.tsx#L1)).
90+
91+
Impact:
92+
93+
- The roadmap completion criteria are out of date.
94+
- A reader following the PRD literally will look in the wrong place for the shipped demo.
95+
96+
### 6. PRD examples have adapter API drift
97+
98+
The PRD presents React, Vue, WC, and Solid as phased adapters with specific surfaces ([docs/prd.md:293](/home/bretuobay/prjts/multimodal-user-interfaces-framework/docs/prd.md#L293)). The repo has those adapters, but the exact APIs have drifted from the PRD examples.
99+
100+
Examples:
101+
102+
- PRD quick start shows `useAgent({ channel })` inside a `SessionProvider`, but the React hook itself does not take or use a `session`, despite earlier README-style examples implying that linkage.
103+
- Vue exports `provideSession` rather than a component-style provider surface ([packages/vue/src/index.ts:6](/home/bretuobay/prjts/multimodal-user-interfaces-framework/packages/vue/src/index.ts#L6)).
104+
- Solid exports `createSessionProvider`, which is beyond the PRD’s wording that described it as a Phase 3 bridge, but the exact lifecycle/documentation should be updated together.
105+
106+
This is not a blocker by itself, but it means the PRD is no longer a precise source of truth for public adapter APIs.
107+
108+
## Recommendations
109+
110+
1. Update the PRD roadmap and package status sections to reflect current repo state instead of Phase 1-only completion.
111+
2. Either wire `Channel.sink.writable` into the actual channel pipeline or narrow the PRD contract so it matches the current implementation.
112+
3. Fix generator action completion semantics in both `runAction()` and `Session.dispatch()`, then add explicit tests for async-generator return values.
113+
4. Make `AgentChannel.sendMessage()` emit progress frames or refactor `@muix/react` `useAgent()` to consume `channel.observe()` consistently, then add integration tests for streaming text updates.
114+
5. Fix devtools to derive channels from `channelId` plus `session.getChannel()` or change the session event payload to include the channel instance.
115+
6. Refresh PRD references to the current demo route and current adapter APIs.
116+
117+
## Confidence
118+
119+
High confidence on package-presence and API-drift findings.
120+
121+
Medium-high confidence on runtime behavior gaps where the contradiction is directly visible in code but not currently covered by an existing test:
122+
123+
- `Channel.sink.writable` not being connected
124+
- async-generator final result handling
125+
- React agent streaming progress
126+
- devtools channel event payload mismatch
127+
128+
## Validation Performed
129+
130+
- Reviewed the PRD and compared it against the exported package surfaces, representative implementations, demo routes, and docs app.
131+
- Ran `npm test -- --filter=@muix/*` at the repo root on 2026-03-23. All package test suites passed.
132+
- The passing test run does not invalidate the main gaps above; several are contract mismatches that are not covered by the current tests.

docs/prd.md

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -317,17 +317,17 @@ useAgent({ channel: AgentChannel }): {
317317
}
318318
```
319319
320-
### 5.2 Vue — `@muix/vue` *(Phase 2)*
320+
### 5.2 Vue — `@muix/vue`
321321
322-
Composables mirroring the React hook surface: `useSignal`, `useChannel`, `useSession`, `useAgent`.
322+
Composables mirroring the React adapter shape: `provideSession`, `useSession`, `useSignal`, `useChannel`, `useAction`, `useAgent`.
323323
324-
### 5.3 Web Components — `@muix/wc` *(Phase 2)*
324+
### 5.3 Web Components — `@muix/wc`
325325
326-
Custom elements: `<muix-session>`, `<muix-channel>`. Attribute/property bindings backed by Signals.
326+
Custom elements: `<muix-session>`, `<muix-channel>`.
327327
328-
### 5.4 Solid.js — `@muix/solid` *(Phase 3)*
328+
### 5.4 Solid.js — `@muix/solid`
329329
330-
Bridge between MUIX Signals and Solid's reactive primitives via `createSignal`/`createEffect`.
330+
Solid adapter surface: `createSessionProvider`, `useSession`, `useSignal`, `useChannel`, `useAction`, `useAgent`.
331331
332332
---
333333
@@ -439,7 +439,7 @@ User message → AgentChannel.sendMessage()
439439
440440
### Phase 1 — Core + Text + Agent + React ✅
441441
442-
**Exit criterion:** Working LLM streaming chat demo in `apps/web/app/chat`.
442+
**Exit criterion:** Working LLM streaming chat demo in `apps/web/app`.
443443
444444
| Package | Status |
445445
|---|---|
@@ -449,35 +449,35 @@ User message → AgentChannel.sendMessage()
449449
| `@muix/text` | ✅ Complete — 5 tests |
450450
| `@muix/agent` | ✅ Complete — 14 tests |
451451
| `@muix/react` | ✅ Complete — 6 tests |
452-
| Demo (`apps/web/app/chat`) | ✅ Complete |
452+
| Demo (`apps/web/app`) | ✅ Complete |
453453
454454
**Total: 95 tests, all passing.**
455455
456456
---
457457
458-
### Phase 2 — Audio + Video + Motion + Vue + Web Components
458+
### Phase 2 — Audio + Video + Motion + Vue + Web Components
459459
460-
**Exit criterion:** Voice-to-text demo + camera with gesture overlay in `apps/web`.
460+
**Status:** Package implementations are present in the monorepo. End-to-end demo hardening is still in progress.
461461
462462
| Package | Capability deps | Key classes |
463463
|---|---|---|
464-
| `@muix/audio` | `media:microphone`, `speech:synthesis` | `MicrophoneSource`, `AudioWorkletSink`, `VoiceActivityDetector` |
465-
| `@muix/video` | `media:camera`, `media:screen` | `CameraSource`, `CanvasSink`, `WebRTCSink` |
464+
| `@muix/audio` | `media:microphone`, `speech:synthesis` | `MicrophoneSource`, `AudioWorkletSink`, `createVad` |
465+
| `@muix/video` | `media:camera`, `media:screen` | `CameraSource`, `CanvasSink` |
466466
| `@muix/motion` | — (pointer events, device orientation) | `PointerSource`, `DeviceOrientationSource`, `GestureRecognizer` |
467-
| `@muix/vue` | — | Composables: `useSignal`, `useChannel`, `useSession`, `useAgent` |
467+
| `@muix/vue` | — | `provideSession`, `useSignal`, `useChannel`, `useAction`, `useAgent` |
468468
| `@muix/wc` | — | `<muix-session>`, `<muix-channel>` custom elements |
469469
470470
---
471471
472-
### Phase 3 — WebXR + Solid + DevTools + Production Hardening
472+
### Phase 3 — WebXR + Solid + DevTools + Production Hardening 🚧
473473
474-
**Exit criterion:** Stable 1.0 public API, production benchmarks pass.
474+
**Status:** WebXR probes, Solid adapter, DevTools package, and docs app are present. Public API freeze and production hardening remain open.
475475
476476
| Package | Key deliverables |
477477
|---|---|
478-
| `@muix/capability` (extension) | WebXR probe, XRController/XRHand sources |
479-
| `@muix/solid` | Solid.js bridge — MUIX Signal ↔ Solid createSignal |
480-
| `@muix/devtools` | Session inspector overlay, channel frame rate tracer, policy audit log |
478+
| `@muix/capability` (extension) | WebXR probes shipped; XRController/XRHand sources remain future work |
479+
| `@muix/solid` | Solid.js adapter shipped |
480+
| `@muix/devtools` | Session inspector overlay and channel frame tracer shipped |
481481
| All packages | Public API freeze, full API docs in `apps/docs`, 60fps VideoChannel benchmark |
482482
483483
---

packages/agent/src/agent-channel.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ export class AgentChannel extends Channel<AgentMessage, AgentStreamFrame> {
106106
if (abortController.signal.aborted) break;
107107

108108
frames.push(frame);
109+
action._emitProgress({ partial: [...frames] });
109110

110111
// Send to channel's outbound stream
111112
if (this.status.value === 'open' || this.status.value === 'idle') {
@@ -152,6 +153,7 @@ export class AgentChannel extends Channel<AgentMessage, AgentStreamFrame> {
152153
toolResult: { toolCallId, result: toolResult, isError },
153154
};
154155
frames.push(resultFrame);
156+
action._emitProgress({ partial: [...frames] });
155157
await this.send_frame(resultFrame);
156158
}
157159
}

0 commit comments

Comments
 (0)