Yaojia Wang
b5f21e5fdd
feat(v0.2): tab status dot, activity (unread) indicator, drag-reorder
...
- terminal-session.ts: track SessionStatus (connecting/connected/reconnecting/
exited) + onStatus callback; FIX: wire onTitleChange (onTitle was in opts but
never bound — auto-title was dead)
- tabs.ts: per-tab status dot (color = connection state), unread flag set on
background output + cleared on activate, HTML5 drag-to-reorder (preserves
active tab, persisted)
- style.css: .tab-dot colors, .unread ring, .dragging/.drag-over feedback
- Browser-verified: green dot connected, unread ring after bg output, reorder
AAA|BBB→BBB|AAA persists across reload. 191 tests green, typechecks + build ok.
2026-06-17 14:55:19 +02:00
Yaojia Wang
064330f8d9
docs: log v0.2 multi-tab + titles + keybar feature
2026-06-17 12:13:17 +02:00
Yaojia Wang
4f66016f02
feat(v0.2): multi-tab terminal + titles + Claude Code shortcut bar
...
Frontend feature (backend unchanged — manager was already multi-session):
- Multi-tab: each tab = independent WS + Terminal + session (terminal-session.ts,
tabs.ts); tab bar with +, ×, middle-click close; persisted to localStorage
(migrates v0.1 single-session key)
- Tab titles: auto from xterm onTitleChange (OSC 0/2), double-click to rename
inline (manual wins over auto); ellipsis + tooltip
- Shortcut key bar now shown on ALL devices (clickable buttons trigger shortcuts),
reordered for Claude Code (Esc prominent, ⇧Tab, ↑↓, ⏎, ^C, Tab, ←→, /);
responsive sizing via @media (pointer:coarse) for touch
- Verified in browser: rename, two independent sessions, keybar on desktop +
narrow viewport. 191 tests green; both typechecks + esbuild build pass.
2026-06-17 12:11:18 +02:00
Yaojia Wang
f3b6ad5a68
docs: W5 acceptance — browser smoke (F1/F2/F3/F8) + log v0.1 status
...
7/9 acceptance criteria auto-verified: F1/F2/F3/F8 via headless browser
(xterm renders, echo round-trips, exit prompt, resize survives), F5/F6/F9 via
integration tests. F4 (LAN) + F7 (phone keybar) need physical devices -> user.
gitignore .gstack/.
2026-06-17 11:18:13 +02:00
Yaojia Wang
81585ad35f
docs: T21 README (install/run/config/security) + security self-review
...
- No hardcoded secrets; Origin+path+maxPayload checks verified wired in server.ts
- No eval/exec; input is verbatim to PTY by design (byte-shuttle)
- npm run build -> dist/server.js verified
2026-06-17 11:02:16 +02:00
Yaojia Wang
86c7e3de02
docs: log W2-W4 (T12-T15 done, 187 tests, real-PTY E2E verified)
2026-06-17 10:37:01 +02:00
Yaojia Wang
cdec19a256
test: T15 integration/E2E (real WS, M2/M4/L3/L5, F5/F6)
...
6 cases against real startServer via ws client:
①bad-origin 401 ②wrong-path destroy ③oversized-frame 1009 ④spawn-fail exit(-1)
— all pass in sandbox; ⑤attach->output ⑥reconnect-replay gated by PTY_AVAILABLE
(auto-skip where posix_spawn is blocked). Orchestrator verified ⑤⑥ sandbox-off:
6/6 pass with real shell — F5/F6 confirmed (replay incl CJK/ANSI intact).
2026-06-17 10:16:14 +02:00
Yaojia Wang
0dac54b4f4
feat: T14 server.ts — wiring (noServer/handleUpgrade, M4/M5/L3/L5)
...
Express static (public/+build/); WebSocketServer noServer + maxPayload (L5);
upgrade gate: path!=wsPath->destroy, bad origin->401, else handleUpgrade (L3);
connection waits attach, handleAttach in try/catch -> exit(-1)+close on spawn
fail (M4); message routes input/resize; close->detach (never kill); SIGINT/TERM
->shutdown; reapIdle timer; safeSend guards readyState (M5). tsc clean.
2026-06-16 20:09:33 +02:00
Yaojia Wang
a2897b2e12
feat: T13 session/manager.ts — session table (M3/L1/L2)
...
handleAttach 4 paths (new/alive/exited-L1/not-found); reapIdle uses
now-max(detachedAt,lastOutputAt)>idleTtl (M3); shutdown kills all; injected
onExit removes from table when attached, keeps for L1 replay when detached (L2);
createSession errors propagate (M4). 21 tests; full suite 181 green.
2026-06-16 18:58:14 +02:00
Yaojia Wang
20212dd7f6
feat: T12 session/session.ts — PTY lifecycle (M4/M5/L1/L4)
...
createSession/attachWs/detachWs/writeInput/resize/kill; node-pty spawn (throws
on failure/M4), onData->buffer+forward, onExit->exitedAt+exit+injected onExit;
sendIfOpen guards readyState (M5); detach never kills PTY; write/resize no-op
after exit (L4); detach-then-exit keeps session (L1).
Tests vi.mock node-pty -> mock IPty (no real spawn): 19 tests. Full suite green.
2026-06-16 18:54:15 +02:00
Yaojia Wang
c27aaa1ac2
docs: log W1 frontend batch (T8-T11 done, 141 tests)
2026-06-16 18:49:01 +02:00
Yaojia Wang
326d3472dd
feat: W1 frontend — index.html, style.css, keybar, main.ts (esbuild entry)
...
- T8 public/index.html — #term/#keybar, loads ./build/main.js (type=module)
- T9 public/style.css — fullscreen term, keybar fixed bottom, hidden >768px
- T10 public/keybar.ts — key→byte map + mountKeybar (13 tests)
- T11 public/main.ts — xterm+fit, WS client (wss on https/M6), reconnect
backoff, resize debounce, mountKeybar wiring
Verified by orchestrator: backend+frontend tsc clean; full suite 141 tests;
npm run build:web bundles main.ts -> public/build/main.js (430kb).
Note: main.ts uses one @ts-ignore for the CSS import (minor; future: *.css d.ts).
2026-06-16 18:36:32 +02:00
Yaojia Wang
de8c366ab2
docs: log W1 backend batch (T3-T7 done, 128 tests)
2026-06-16 08:10:38 +02:00
Yaojia Wang
0fa0b69ce9
feat: W1 batch — config, protocol, ring-buffer, origin, mock-pty (TDD)
...
Parallel module-builder subagents, disjoint file ownership, shared tree:
- T4 src/config.ts — loadConfig+M1 origins (32 tests)
- T5 src/protocol.ts — parse/serialize+SESSION_ID_RE+M7 (60 tests)
- T6 src/session/ring-buffer.ts — byte-accurate, no UTF-8/ANSI split+M2 (15 tests)
- T7 src/http/origin.ts — host+port match, undefined rejected (12 tests)
- T3 test/helpers/mock-pty.ts — IPty double w/ emitData/emitExit (9 tests)
Verified by orchestrator: tsc --noEmit clean; full suite 128 tests pass.
2026-06-16 08:09:40 +02:00
Yaojia Wang
0e10dc21c3
feat: T2 freeze src/types.ts (shared contracts)
...
- All ARCHITECTURE §3 interfaces as pure types; dependency-free (no ws/node/DOM)
so both backend and frontend can import it
- Refinements vs §3 (documented): EnvLike (not NodeJS.ProcessEnv), WebSocketLike +
WS_OPEN (not ws.WebSocket), added Config.wsPath (invariant 8)
- ARCHITECTURE §3.1/§3.4 reconciled to match (anti-drift)
- tsc --noEmit passes
T2 of docs/PLAN.md
2026-06-16 07:58:52 +02:00
Yaojia Wang
409b208928
build: adopt esbuild for frontend bundling (build:web → public/build/)
...
- esbuild dev dep; build:web/dev:web bundle public/main.ts → public/build/main.js
- gitignore public/build/; tsconfig.web.json now typecheck-only
- frontend build convention documented in PLAN §1, DISPATCH, ARCHITECTURE §5
- resolves the T1 deferred decision
2026-06-16 07:36:01 +02:00
Yaojia Wang
987cab8eb7
docs: log T1 done; flag frontend-bundling decision for T11/T14
2026-06-16 07:22:33 +02:00
Yaojia Wang
b126cf0e42
feat: T1 scaffold — package.json, tsconfig (backend+web), vitest, dirs
...
- All deps declared once (express5, ws, node-pty, @xterm/xterm6, addon-fit;
dev: typescript6, tsx, vitest4, @types/node|ws|express)
- postinstall chmod +x node-pty spawn-helper (prebuild ships it non-exec → posix_spawnp fails)
- node-pty verified: require + real PTY spawn (exitCode 0)
- npm test passes with no tests (passWithNoTests)
- tsconfig.web.json type-checks frontend; browser bundling strategy still TBD (see log)
T1 of docs/PLAN.md
2026-06-16 07:21:42 +02:00
Yaojia Wang
91d0a7189f
docs: add subagent dispatch kit (per-task prompts + templates)
2026-06-16 07:08:54 +02:00
Yaojia Wang
dda09ef2c6
docs: web-terminal v0.1 spec, plan, and multi-agent dev config
...
- TECH_DOC + ARCHITECTURE (cross-validated, 12 fixes M1-M7/L1-L5)
- PLAN: waves W0-W5, tasks T1-T21 for multi-agent parallel dev
- PROGRESS_LOG: orchestrator-owned cross-session memory
- CLAUDE.md: required-reading + orchestrator-worker workflow
- .claude/agents: module-builder, module-reviewer
2026-06-16 06:54:57 +02:00