diff --git a/docs/superpowers/specs/2026-03-30-workbench-v2-design.md b/docs/superpowers/specs/2026-03-30-workbench-v2-design.md new file mode 100644 index 0000000..7d992d2 --- /dev/null +++ b/docs/superpowers/specs/2026-03-30-workbench-v2-design.md @@ -0,0 +1,365 @@ +# Workbench Server v2 Design Spec + +**Date:** 2026-03-30 +**Status:** Draft +**Repo:** https://git.sethpc.xyz/Seth/workbench-server + +## Summary + +Workbench is an MCP server that lets any AI CLI create and control interactive web pages served over LAN. The AI pushes arbitrary HTML/CSS/JS to a browser page via WebSocket. Use cases: hardware diagnostics, guided procedures, dashboards, data collection — anything that benefits from a visual display surface the AI can control. + +v2 adds: server persistence (survives AI CLI restarts), pip-installable packaging, AI-guided setup (INSTALL.md/START.md), and a simplified desktop-focused layout (no embedded terminal panel). + +## What Changes From v1 + +| Aspect | v1 | v2 | +|--------|----|----| +| Server persistence | In-memory only — lost on restart | `.server.json` on disk, reconnect on startup | +| Layout | Split: diagnostic panel + sethmux iframe | Full-width display surface, no terminal | +| Mobile support | Responsive stacking | Desktop only | +| Dependencies | mcp, aiohttp | mcp, aiohttp (unchanged) | +| Packaging | Raw script | pip-installable package | +| Setup | Manual | AI-guided (INSTALL.md → START.md) | +| tmux/sethmux | Embedded iframe | Removed entirely | + +## What Stays The Same + +- MCP server on stdio transport +- 6 MCP tools: `workbench_scaffold`, `workbench_state`, `workbench_log`, `workbench_read_log`, `workbench_list`, `workbench_stop` +- HTTP + WebSocket per project (aiohttp) +- AI pushes arbitrary HTML/CSS/JS — no widget system, full creative freedom +- Dual-format session logging (session.md + session.jsonl) +- Project directories at `~/workbench//` +- LAN-native, no cloud, no auth +- Cost tracking (cost-log.jsonl) + +## Architecture + +``` +┌─────────────────────┐ ┌──────────────────────────────┐ +│ AI CLI terminal │ │ Browser (desktop) │ +│ │ │ │ +│ AI calls MCP tools │ stdio │ ┌────────────────────────┐ │ +│ workbench_state ──┼────┐ │ │ AI-generated content │ │ +│ workbench_log │ │ │ │ HTML / CSS / JS │ │ +│ etc. │ │ │ │ updated live via WS │ │ +│ │ ▼ │ │ │ │ +│ │ MCP │ │ Schematics, tables, │ │ +│ │ server │ │ checklists, dashboards│ │ +│ │ │ │ │ — anything the AI │ │ +│ │ │ │ │ decides to build │ │ +│ │ ▼ │ ├────────────────────────┤ │ +│ │ HTTP + │ │ Log feed │ │ +│ │ WS on │ └────────────────────────┘ │ +│ │ LAN │ ● Connected │ project-name │ +└─────────────────────┘ └──────────────────────────────┘ +``` + +## Persistence Mechanism + +### Problem + +The MCP server runs as a subprocess of the AI CLI. When the AI restarts, the MCP server restarts, and all in-memory state (running HTTP servers, WebSocket clients) is lost. The AI then calls `workbench_scaffold` again and starts a duplicate server. + +### Solution + +Persist server state to disk. On startup and on each `workbench_scaffold` call, check for an existing running server before starting a new one. + +**Per-project server file:** `~/workbench//.server.json` + +```json +{ + "pid": 12345, + "port": 8070, + "started": "2026-03-30T10:00:00-04:00" +} +``` + +### workbench_scaffold flow + +``` +workbench_scaffold(name, title) + │ + ├─ Project dir exists? + │ ├─ No → create dir, write scaffold HTML, init logs + │ └─ Yes → keep existing files + │ + ├─ .server.json exists? + │ ├─ No → start new HTTP server, write .server.json + │ └─ Yes → read port from file + │ ├─ HTTP GET localhost: returns 200? + │ │ ├─ Yes → server is alive, reattach (add to active_projects) + │ │ └─ No → server is dead, clean up .server.json, start new server + │ └─ PID still running? (fallback check) + │ + └─ Return {"path": "...", "url": "http://:"} +``` + +### MCP server startup (reconnect) + +When the MCP server process starts (before any tool calls), scan for running servers: + +```python +for project_dir in ~/workbench/*/: + server_file = project_dir / ".server.json" + if server_file.exists(): + info = json.loads(server_file.read_text()) + if is_server_alive(info["port"]): + active_projects[name] = {"port": info["port"], ...} +``` + +This means: AI CLI restarts → MCP server restarts → immediately knows about all running project servers → `workbench_list` and `workbench_state` work without calling `workbench_scaffold` again. + +### workbench_stop flow + +``` +workbench_stop(project) + │ + ├─ Log session end to cost-log.jsonl + ├─ Stop HTTP server (runner.cleanup()) + ├─ Delete .server.json + └─ Remove from active_projects +``` + +## Scaffold HTML (v2) + +Full-width desktop layout. No split pane, no iframe, no terminal embed. + +```html + + + + {{TITLE}} + + + +
+

{{TITLE}}

+

{{DESCRIPTION}}

+

Waiting for content...

+
+
+

Session Log

+
+
+
Connecting...
+ + + + +``` + +Key changes from v1: +- No split layout, no divider, no term-panel, no iframe +- Full-width `#content` area +- Flexbox column layout (content grows, log and status at bottom) +- No mobile media queries +- Same WebSocket reconnect logic +- Same localStorage state persistence + +## MCP Tools (unchanged API) + +The 6 tools keep the same interface. Only internal behavior changes for persistence. + +### workbench_scaffold + +Same parameters: `name`, `title`, `description`. +New behavior: checks `.server.json` before starting a new server (see Persistence Mechanism above). +Returns: `{"path": "...", "url": "http://:"}` (unchanged). + +### workbench_state + +Unchanged. Pushes JSON to browser via WebSocket. `template`, `styles`, `script` fields. + +### workbench_log + +Unchanged. Appends to session.md and session.jsonl, pushes to browser log feed. + +### workbench_read_log + +Unchanged. Returns recent log entries from session.jsonl. + +### workbench_list + +Same return format, but now also checks `.server.json` files to detect servers that survived an MCP restart. + +### workbench_stop + +Same behavior, plus deletes `.server.json` on stop. + +## Source Structure + +``` +workbench-server/ + pyproject.toml + README.md + INSTALL.md + LICENSE + src/ + workbench/ + __init__.py + __main__.py # python -m workbench + cli.py # CLI: mcp, serve, list, help + server.py # MCP server + HTTP/WS management + persistence + project.py # Project dir management, logging + scaffold.html # HTML template + tests/ + conftest.py + test_project.py + test_persistence.py + test_server.py +``` + +## Packaging + +```toml +[build-system] +requires = ["setuptools>=68.0"] +build-backend = "setuptools.build_meta" + +[project] +name = "workbench-server" +version = "0.1.0" +description = "MCP server that lets AI CLIs build interactive web pages served over LAN" +requires-python = ">=3.10" +dependencies = [ + "mcp>=1.26.0", + "aiohttp>=3.9.0", +] + +[project.scripts] +workbench = "workbench.cli:main" +``` + +## INSTALL.md + +Same AI-guided pattern as kitty-workbench, but simpler (no terminal detection needed): + +1. Clone + pip install +2. Detect platform and browser availability +3. Configure MCP for user's AI CLI +4. SSH ControlMaster setup (if applicable) +5. Smoke test +6. Write `~/workbench/START.md` + +## README.md + +Public-facing. Setup is "paste the URL" or "read INSTALL.md". Desktop browser as the display surface. No mention of kitty or terminal splitting. Examples: hardware diagnostics, guided procedures, data collection. + +## CLI Interface + +``` +workbench mcp # start MCP server (stdio transport) +workbench serve # serve a project without MCP (standalone) +workbench list # list projects +workbench help # usage +```