Skip to content

feat(cockpit/web): scaffold S3 web cockpit renderer — Hono server, SSE, transcript reducer, chat UI#6

Open
TSchonleber wants to merge 1 commit into
codex/strand-cockpit-tuifrom
devin/1777058119-s3-web-cockpit-renderer
Open

feat(cockpit/web): scaffold S3 web cockpit renderer — Hono server, SSE, transcript reducer, chat UI#6
TSchonleber wants to merge 1 commit into
codex/strand-cockpit-tuifrom
devin/1777058119-s3-web-cockpit-renderer

Conversation

@TSchonleber
Copy link
Copy Markdown
Owner

Summary

Scaffolds the S3 web cockpit renderer as specified in §4/§7 of the cockpit design spec. Adds a real Hono-based server, SSE streaming, a renderer-agnostic transcript reducer, and a chat-first HTML UI — all consuming the pinned CockpitEvent schema from src/cockpit/core.

What's new

Module Purpose
src/cockpit/web/auth.ts Loopback-only random token generation (generateCockpitToken) + timing-safe verification via X-Cockpit-Token header
src/cockpit/web/server.ts Hono app factory: GET /events (SSE with X-Cockpit-Protocol: 1), POST /input, POST /commands/:slash — all behind token auth middleware
src/cockpit/web/transcript-reducer.ts Pure, renderer-agnostic state machine — reduceTranscriptEvent(state, event) handles all 14 CockpitEvent types. Ready for Ink parity tests
src/cockpit/web/sse-client.ts Fetch-based SSE consumer (custom header support since EventSource can't send headers)
src/cockpit/web/ui/index.html Chat-first dark-theme UI: transcript stream, subagent tabs placeholder, collapsible Systems drawer (off by default), /skills review feed placeholder, input box with /command routing
src/cockpit/web/ui/app.ts Typed entry point for future Vite bundling

Server contract

  • GET /events — SSE stream, X-Cockpit-Protocol: 1 header, JSON-serialized CockpitEvent per data: frame
  • POST /input{ sessionId, text, metadata? }ChatController.submit()
  • POST /commands/:slash{ sessionId, args? }ChatController.slash()
  • All routes require X-Cockpit-Token header (random 32-byte hex, timing-safe comparison)

Dependencies

  • hono ^4.12.15 (was already a transitive dep via @modelcontextprotocol/sdk)

Test coverage (35 tests passing)

  • auth (9 tests): token generation, uniqueness, verification, loopback detection
  • server contract (8 tests): auth rejection, field validation, controller dispatch, SSE streaming
  • transcript reducer (14 tests): message append/delta, tool lifecycle, subagent lifecycle, skill proposals, provider switch, budget warnings, errors, policy events, full session replay, immutability

S1 dependencies still stubbed

  • ChatController — server accepts it as an interface; no implementation yet (S1 delivers this)
  • EventBus — works end-to-end for SSE streaming; no persistent transcript store yet
  • Vite build pipeline not wired — HTML UI works as static served by Hono; Vite + Tailwind + shadcn/ui is a follow-up
  • No strand dev integration yet — server factory is ready to mount

Review & Testing Checklist for Human

  • Verify pnpm typecheck && pnpm lint && pnpm test -- tests/cockpit/ all pass
  • Review transcript-reducer.ts — this is the parity-critical piece shared between renderers. Confirm the state shape covers your expected Ink parity test contract
  • Review server.ts token auth middleware — confirm loopback-only + random token design matches your security intent from §4

Notes

  • Core schema (src/cockpit/core/events.ts) was NOT modified — all types consumed as-is
  • The transcript reducer is deliberately placed in src/cockpit/web/ per write scope, but it's renderer-agnostic and can be promoted to src/cockpit/core/ for Ink parity (S5's call)
  • ui/index.html inline <script> is intentionally a quick bootstrap; the typed app.ts + sse-client.ts are the real client-side modules for Vite bundling

Link to Devin session: https://app.devin.ai/sessions/6b21ab54f260444d96838afc6007c634
Requested by: @TSchonleber

…E, transcript reducer, chat UI

- auth.ts: loopback-only random token generation + timing-safe verification
- server.ts: Hono app factory with GET /events (SSE), POST /input, POST /commands/:slash
- transcript-reducer.ts: renderer-agnostic pure state machine consuming CockpitEvent
- sse-client.ts: fetch-based SSE consumer with custom header support
- ui/index.html: chat-first layout with transcript, subagent tabs, systems drawer, skills feed
- ui/app.ts: typed entry point for future Vite bundling
- index.ts: re-exports all new modules
- 35 tests passing (auth, server contract, transcript reducer parity)

Co-Authored-By: Terrence Schonleber <TVschonleber@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant