You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
- Rename all af references to afx (Spec 647)
- Update version from v1.x to v3.x
- Add .codev/config.json layered config system
- Add forge-agnostic language (GitHub/GitLab/Gitea support)
- Add afx spawn --branch support to Spawn Builder command
- Add author attribution (@username) to TreeView items (Spec 637)
- Add EscapeBuffer for incomplete ANSI sequences across WS frames (Bugfix #630)
- Add resize deferral during replay (Bugfix #625)
- Document workspace-scoped vs global API routes in Connection Manager
- Add SSE heartbeat handling (Bugfix #580)
- Expand references with Specs 618, 627, 637, 647
@@ -16,7 +16,7 @@ A1: No. The extension coexists with the browser dashboard. Users choose their pr
16
16
A2: Yes. VS Code's `createTerminal({ pty })` with a custom `Pseudoterminal` can proxy I/O over WebSocket to Tower's PTY sessions. Unlike the old spec (0066), tmux is no longer in the stack — shellper handles persistence natively.
17
17
18
18
**Q3: How does architect-builder communication work?**
19
-
A3: `af send` posts to `POST /api/send` on Tower. Tower resolves the target builder's PTY session, checks idle state (3s threshold), formats the message with `### [ARCHITECT INSTRUCTION | timestamp] ###` framing, and writes it to the PTY via shellper. The VS Code extension doesn't change this — it's a different viewport onto the same Tower infrastructure.
19
+
A3: `afx send` posts to `POST /api/send` on Tower. Tower resolves the target builder's PTY session, checks idle state (3s threshold), formats the message with `### [ARCHITECT INSTRUCTION | timestamp] ###` framing, and writes it to the PTY via shellper. The VS Code extension doesn't change this — it's a different viewport onto the same Tower infrastructure.
20
20
21
21
**Q4: What about the old spec 0066?**
22
22
A4: Spec 0066 was written 2026-01-12 against the old tmux/ttyd architecture. The stack has since moved to shellper + node-pty + custom WebSocket protocol. This spec starts fresh with the current architecture.
@@ -32,23 +32,29 @@ Codev's Agent Farm operates through a browser-based dashboard served by the Towe
32
32
33
33
## Current State
34
34
35
-
**Tower Architecture (v1.x, March 2026):**
35
+
**Tower Architecture (v3.x, April 2026):**
36
36
- Node.js HTTP/WebSocket server on localhost:4100
37
37
- Shellper daemon for PTY persistence (survives Tower restarts)
38
38
- React 19 + xterm.js 5.5 dashboard served at `/`
39
39
- SQLite state (local state.db per workspace + global.db system-wide)
40
40
- Binary WebSocket protocol: `0x00` = control frames (JSON), `0x01` = data frames (raw PTY bytes)
41
-
- SSE at `/api/events` for real-time push notifications
-**SSE client**: Subscribes to `/api/events`, routes events to TreeView/Status Bar refresh
226
+
-**SSE client**: Subscribes to `/api/events`, routes events to TreeView/Status Bar refresh. Handles 30s heartbeat events without triggering state refreshes.
219
227
-**REST client**: Authenticated calls to all `/api/*` endpoints
220
228
-**WebSocket pool**: One WebSocket per open terminal, managed lifecycle
221
229
-**Auth**: Reads `~/.agent-farm/local-key`, sends as `codev-web-key` header (HTTP) or query param (WebSocket)
222
230
-**Health check**: Pings `/api/health` on activation and after SSE drops
The Connection Manager encodes the active workspace path as base64url and prefixes all workspace-scoped requests. The workspace path is determined by matching VS Code's workspace folder against Tower's known workspaces (via `GET /api/workspaces`).
224
240
225
241
All consumers (TreeView, Status Bar, Terminals, Commands) go through this singleton. When Tower goes offline, a single state change propagates to all UI surfaces.
226
242
@@ -246,6 +262,12 @@ Each Tower PTY session maps to a VS Code `Pseudoterminal`:
246
262
- On reconnect, send last-seen sequence number for ring buffer replay
247
263
- Terminal scrollback is preserved via shellper — no data loss
248
264
265
+
**Escape sequence buffering:**
266
+
WebSocket frames can split ANSI escape sequences mid-sequence (e.g., CSI, OSC, DCS). Writing a partial escape to `onDidWrite` corrupts terminal state (production Bugfix #630). The Pseudoterminal adapter must buffer incomplete trailing sequences and prepend them to the next frame — same logic as `dashboard/src/lib/escapeBuffer.ts`. This should be extracted into `@cluesmith/codev-api-client` as a shared utility.
267
+
268
+
**Resize deferral during replay:**
269
+
On reconnect, the ring buffer replays potentially large scrollback. Sending a resize control frame (`0x00` with `type: 'resize'`) while replay data is being written causes garbled rendering (production Bugfix #625). The adapter must queue resize events and flush them only after the replay write completes.
270
+
249
271
**Backpressure:**
250
272
- Chunk large `onDidWrite` calls (> 16KB) with `setTimeout(0)` between chunks
251
273
- Prevents extension host CPU spikes and "Extension causes high CPU" warnings
@@ -269,17 +291,21 @@ CODEV AGENT FARM
269
291
│ ├── #43 dashboard-polish [review] ● running
270
292
│ └── #44 api-refactor [plan-approval] ⏸ blocked
271
293
├── 📋 Pull Requests (2)
272
-
│ ├── #187 feat: password hashing (ready)
273
-
│ └── #188 fix: dashboard layout (draft)
294
+
│ ├── #187 feat: password hashing @alice (ready)
295
+
│ └── #188 fix: dashboard layout @bob (draft)
274
296
├── 📥 Backlog (5)
275
-
│ ├── #190 Add rate limiting
276
-
│ ├── #191 Improve error messages
297
+
│ ├── #190 Add rate limiting @alice
298
+
│ ├── #191 Improve error messages @bob
277
299
│ └── ... (2 more)
278
300
└── ✓ Recently Closed (3)
279
301
├── #185 feat: password reset (merged)
280
302
└── ... (2 more)
281
303
```
282
304
305
+
**Author attribution**: Backlog and PR items show `@username` when the forge provides author data (Spec 637). Gracefully omitted when the author field is absent (e.g., some non-GitHub forges).
306
+
307
+
**Forge-agnostic**: All issue/PR data comes through Tower's overview API, which dispatches to the configured forge provider (GitHub, GitLab, Gitea). The extension never calls `gh` or any forge CLI directly. "Open in Browser" actions use URLs from the API response, not hardcoded GitHub URLs.
308
+
283
309
**Data source**: `GET /api/overview` (same as browser dashboard Work View)
284
310
**Refresh**: On SSE events + manual refresh button
285
311
**Actions (context menu):**
@@ -305,7 +331,7 @@ Commands registered under `Codev:` prefix:
305
331
306
332
| Command | Action |
307
333
|---------|--------|
308
-
|`Codev: Spawn Builder`| Quick-pick for issue number + protocol → `af spawn`|
334
+
|`Codev: Spawn Builder`| Quick-pick for issue number + protocol + optional branch → `afx spawn`|
@@ -323,7 +349,7 @@ Commands registered under `Codev:` prefix:
323
349
324
350
### 6. File Link Handling
325
351
326
-
**Intercept `af open`**: Register a URI handler so `af open file.ts:42` triggers VS Code to open the file at line 42 using `vscode.workspace.openTextDocument` + `vscode.window.showTextDocument` with `vscode.Selection`.
352
+
**Intercept `afx open`**: Register a URI handler so `afx open file.ts:42` triggers VS Code to open the file at line 42 using `vscode.workspace.openTextDocument` + `vscode.window.showTextDocument` with `vscode.Selection`.
327
353
328
354
**Terminal file path detection**: The browser dashboard uses `FilePathDecorationManager` to make file paths clickable in xterm.js. In VS Code, this is handled natively by the terminal's link provider. Register a `TerminalLinkProvider` that detects file paths and opens them in the editor on click.
329
355
@@ -432,8 +458,10 @@ Without this package, the extension becomes a third independent copy of these ty
432
458
Environment-agnostic Tower API client shared between dashboard and extension:
433
459
434
460
- REST client with authenticated fetch (local-key header)
435
-
- SSE client with reconnection logic
461
+
- SSE client with reconnection logic and heartbeat handling
- Must accept a custom HTTP agent — VS Code extensions run behind corporate proxies and need to integrate with `vscode.workspace.getConfiguration('http').get('proxy')`
439
467
@@ -463,7 +491,7 @@ Environment-agnostic Tower API client shared between dashboard and extension:
463
491
| State | Behavior |
464
492
|-------|----------|
465
493
|**Activation**| On `codev.*` command or workspace contains `codev/` directory. Lazy — no heavy init until needed. |
466
-
|**Tower not running**| Status bar shows offline. Commands show "Tower is not running — start with `af tower start`". TreeView shows empty state. |
494
+
|**Tower not running**| Status bar shows offline. Commands show "Tower is not running — start with `afx tower start`". TreeView shows empty state. |
467
495
|**Tower starts**| Health check succeeds → SSE connects → TreeView populates → status bar updates |
|**VS Code reload**| Extension re-activates → reconnects to Tower → re-creates terminal Pseudoterminals → reattaches to existing shellper sessions |
@@ -475,7 +503,7 @@ Environment-agnostic Tower API client shared between dashboard and extension:
475
503
-[x] Should the extension be in this monorepo or a separate repo? **RESOLVED: Monorepo.** Extension lives in this repo (e.g., `packages/codev-vscode/`), sharing types and build infrastructure.
476
504
477
505
### Important (Affects Design)
478
-
-[ ] Should `af open` use a VS Code URI scheme (`vscode://codev/open?file=...`) or a filesystem watcher approach?
506
+
-[ ] Should `afx open` use a VS Code URI scheme (`vscode://codev/open?file=...`) or a filesystem watcher approach?
479
507
-[ ] Should the extension auto-start Tower if it's not running, or always require manual start?
0 commit comments