# Phase 1 spikes — status

ARCHITECTURE.md §8 requires OD-2, OD-3, and OD-6 be run "here, not later," in
Phase 1, with a documented decision each.

## OD-2 — Does ProseMirror meet the composer performance budget?

**Status: resolved — proceed with TipTap (ProseMirror).**

The composer in `apps/web/src/components/RichTextEditor.tsx` is TipTap 3 on
`@tiptap/pm`. TipTap is a ProseMirror editor; there is no separate
`libs/editor` package because the sanitiser (`libs/core/src/blocks.ts`) is the
server-side budget enforcer and the widget is app-local.

Measured: `sanitizeMessageBlocks` on a 400-paragraph (~budget-sized) tree
completes in well under 50 ms in CI (`libs/core/src/blocks.budget.test.ts`).
Trees above 2 000 nodes truncate rather than hang. Keystroke p95 < 16 ms is a
browser measurement and is not runnable in this environment; the decision is
to keep ProseMirror and use Lexical (ADR-008) only if a future profiler on a
low-end machine shows dropped frames in the real widget.

**Decision:** keep TipTap/ProseMirror. Lexical fallback unused.

## OD-3 — Does `getDisplayMedia` work in WKWebView on macOS?

**Status: not executed — no macOS hardware in this environment.**

A probe page lives at `scripts/spikes/od3-getdisplaymedia.html`. It must be
loaded inside the packaged Tauri webview on a real Mac (WebView2 / Chromium
on Windows and Chrome on Linux cannot answer this spike).

**Decision until a Mac run exists:** ship screen share on web/PWA/Windows;
macOS screen share stays on the ADR-009 fallbacks (Tauri capture APIs, or
share from a browser). Chat is unaffected. Re-run the probe before calling
Phase 6 screen share "done" on macOS desktop.

## OD-6 — Socket.IO density: 8 000 sockets/node across two nodes?

**Status: harness written, 8k measurement not run.**

`scripts/spikes/od6-socket-density.mjs` opens N JWT-authenticated Socket.IO
connections. Default `N=50` is a local smoke. The architectural target (8 000
across two gateway nodes, event-loop lag p99 < 50 ms) needs staging: two
gateway processes, Redis adapter, and a load generator. This environment has
no such cluster.

**Decision until staging numbers exist:** keep Socket.IO + Redis adapter
(ADR-013) as the default. Fallback remains raw `ws` with a hand-built room
layer if an 8k soak fails. Do not treat the socket-density budget as
measured.

```
GATEWAY_URL=http://127.0.0.1:3002 JWT_ACCESS_SECRET=... N=50 node scripts/spikes/od6-socket-density.mjs
```

Requires `socket.io-client` (from `apps/web`). Example:

```
pnpm --filter @slackwsh/web exec node ../../scripts/spikes/od6-socket-density.mjs
```

## Phase 1 exit

Isolation suite: `libs/messaging/src/isolation.integration.test.ts` plus HTTP
and socket catalogs in `apps/api` and `apps/gateway`. Spikes: OD-2 decided;
OD-3 and OD-6 documented with harnesses and explicit "not measured" status
rather than silent skips.
