ai-agent-session-center 2.0.2 → 2.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/README.md +484 -429
  2. package/docs/3D/ADAPTATION_GUIDE.md +592 -0
  3. package/docs/3D/index.html +754 -0
  4. package/docs/AGENT_TEAM_TASKS.md +716 -0
  5. package/docs/CYBERDROME_V2_SPEC.md +531 -0
  6. package/docs/ERROR_185_ANALYSIS.md +263 -0
  7. package/docs/PLATFORM_FEATURES_PROMPT.md +296 -0
  8. package/docs/SESSION_DETAIL_FEATURES.md +98 -0
  9. package/docs/_3d_multimedia_features.md +1080 -0
  10. package/docs/_frontend_features.md +1057 -0
  11. package/docs/_server_features.md +1077 -0
  12. package/docs/session-duplication-fixes.md +271 -0
  13. package/docs/session-terminal-linkage.md +412 -0
  14. package/package.json +63 -5
  15. package/public/apple-touch-icon.svg +21 -0
  16. package/public/css/dashboard.css +0 -161
  17. package/public/css/detail-panel.css +25 -0
  18. package/public/css/layout.css +18 -1
  19. package/public/css/modals.css +0 -26
  20. package/public/css/settings.css +0 -150
  21. package/public/css/terminal.css +34 -0
  22. package/public/favicon.svg +18 -0
  23. package/public/index.html +6 -26
  24. package/public/js/alarmManager.js +0 -21
  25. package/public/js/app.js +21 -7
  26. package/public/js/detailPanel.js +63 -64
  27. package/public/js/historyPanel.js +61 -55
  28. package/public/js/quickActions.js +132 -48
  29. package/public/js/sessionCard.js +5 -20
  30. package/public/js/sessionControls.js +8 -0
  31. package/public/js/settingsManager.js +0 -142
  32. package/server/apiRouter.js +60 -15
  33. package/server/apiRouter.ts +774 -0
  34. package/server/approvalDetector.ts +94 -0
  35. package/server/authManager.ts +144 -0
  36. package/server/autoIdleManager.ts +110 -0
  37. package/server/config.ts +121 -0
  38. package/server/constants.ts +150 -0
  39. package/server/db.ts +475 -0
  40. package/server/hookInstaller.d.ts +3 -0
  41. package/server/hookProcessor.ts +108 -0
  42. package/server/hookRouter.ts +18 -0
  43. package/server/hookStats.ts +116 -0
  44. package/server/index.js +15 -1
  45. package/server/index.ts +230 -0
  46. package/server/logger.ts +75 -0
  47. package/server/mqReader.ts +349 -0
  48. package/server/portManager.ts +55 -0
  49. package/server/processMonitor.ts +239 -0
  50. package/server/serverConfig.ts +29 -0
  51. package/server/sessionMatcher.js +17 -6
  52. package/server/sessionMatcher.ts +403 -0
  53. package/server/sessionStore.js +109 -3
  54. package/server/sessionStore.ts +1145 -0
  55. package/server/sshManager.js +167 -24
  56. package/server/sshManager.ts +671 -0
  57. package/server/teamManager.ts +289 -0
  58. package/server/wsManager.ts +200 -0
@@ -0,0 +1,531 @@
1
+ # Cyberdrome V2 — Comprehensive Enhancement Specification
2
+
3
+ ## Team Execution Plan
4
+
5
+ This spec is designed for parallel agent team execution. Each workstream is independent enough to run concurrently, with dependency arrows noted where sequencing matters.
6
+
7
+ ---
8
+
9
+ ## Workstream 1: Group → Room Rename (Foundation — blocks all others)
10
+
11
+ **Goal:** Eliminate the "group" abstraction entirely. The mental model is **Rooms** — physical spaces in the Cyberdrome where robots work.
12
+
13
+ ### Renames
14
+
15
+ | From | To |
16
+ |------|-----|
17
+ | `src/stores/groupStore.ts` | `src/stores/roomStore.ts` |
18
+ | `src/stores/groupStore.test.ts` | `src/stores/roomStore.test.ts` |
19
+ | `src/styles/modules/SessionGroup.module.css` | `src/styles/modules/Room.module.css` |
20
+ | Type `SessionGroup` | Type `Room` |
21
+ | Hook `useGroupStore` | Hook `useRoomStore` |
22
+ | `STORAGE_KEY = 'session-groups'` | `STORAGE_KEY = 'session-rooms'` |
23
+ | ID prefix `group-` | ID prefix `room-` |
24
+
25
+ ### Method Renames
26
+
27
+ | From | To |
28
+ |------|-----|
29
+ | `createGroup(name)` | `createRoom(name)` |
30
+ | `renameGroup(id, name)` | `renameRoom(id, name)` |
31
+ | `deleteGroup(id)` | `deleteRoom(id)` |
32
+ | `toggleCollapse(id)` | `toggleCollapse(id)` (keep) |
33
+ | `getGroupForSession(sid)` | `getRoomForSession(sid)` |
34
+
35
+ ### CSS Class Renames
36
+
37
+ | From | To |
38
+ |------|-----|
39
+ | `.group` | `.room` |
40
+ | `.groupGrid` | `.roomGrid` |
41
+ | `.groupDragging` | `.roomDragging` |
42
+ | `.groupDropLeft` | `.roomDropLeft` |
43
+ | `.groupDropRight` | `.roomDropRight` |
44
+
45
+ ### Files to Update (imports + local variable names)
46
+
47
+ - `src/components/3d/CyberdromeScene.tsx` — `groups` → `rooms`
48
+ - `src/components/3d/SceneOverlay.tsx` — all group refs → room refs
49
+ - `src/components/3d/SessionRobot.tsx` — `getGroupForSession` → `getRoomForSession`
50
+ - `src/components/3d/RoomLabels.tsx` — `groups` → `rooms`
51
+ - `src/components/session/SessionControlBar.tsx` — UI text "No group" → "No room", "+ New Group" → "+ New Room"
52
+ - `src/lib/cyberdromeScene.ts` — `SessionGroup` → `Room`, param name `groups` → `rooms`, field `groupId` → `roomId` in `RoomConfig`
53
+ - `src/components/session/DetailPanel.test.tsx` — check for group refs
54
+
55
+ ### DO NOT rename
56
+
57
+ - `groupBy` in `settingsStore.ts` / `BrowserSettings` — different concept (sort/filter)
58
+
59
+ ---
60
+
61
+ ## Workstream 2: Room Door Labels (3D Text at Doorway)
62
+
63
+ **Goal:** Room names displayed as 3D text on the floor in front of each room's south door (the entry door), parallel to the ground plane, readable from the default camera angle.
64
+
65
+ ### Current State
66
+
67
+ `RoomLabels.tsx` uses `<Html>` (drei) at position `[cx, 2.5, cz]` — floating above room center. This is a DOM overlay that can cover other UI elements.
68
+
69
+ ### Target
70
+
71
+ Replace `<Html>` labels with `<Text>` from `@react-three/drei` (SDF text rendered in WebGL, not DOM):
72
+
73
+ - **Position:** `[cx, 0.02, cz + ROOM_HALF + 1.5]` — just outside the south wall door, slightly above floor
74
+ - **Rotation:** `[-Math.PI / 2, 0, 0]` — flat on the ground, facing up
75
+ - **Font:** `'Orbitron'` or a suitable monospace/sci-fi web font
76
+ - **Color:** Room's strip color from the neon palette, with emissive glow
77
+ - **Size:** `fontSize={0.8}` — readable at zoom level but not overwhelming
78
+ - **Content:** Room name in uppercase + unit count badge
79
+
80
+ ### Why 3D Text Instead of Html
81
+
82
+ - Never covers DOM overlays (settings, detail panel)
83
+ - Properly occluded by 3D geometry
84
+ - Scales naturally with camera zoom
85
+ - No z-index conflicts
86
+
87
+ ### Sub-count Badge
88
+
89
+ Below room name, smaller text: `"N UNITS"` in dimmer color.
90
+
91
+ ---
92
+
93
+ ## Workstream 2.5: Desk-Sitting Behavior for Prompting & Working
94
+
95
+ **Goal:** When a robot is **prompting** or **working**, it must walk to an available desk in its assigned room, sit down, and show its status from the seated position. This is the core "office worker" metaphor — robots aren't wandering aimlessly, they go to their desk to think and work.
96
+
97
+ ### Current State
98
+
99
+ - `working` already has `seekDesk: true` in `robotStateMap.ts` — robot finds a workstation
100
+ - `prompting/thinking` has `seekDesk: false`, `wander: true` — robot wanders randomly
101
+
102
+ ### Target Behavior
103
+
104
+ | Status | seekDesk | Desk Animation | Visual |
105
+ |--------|----------|----------------|--------|
106
+ | `idle` | `false` | N/A — wander slowly | Standing, gentle float |
107
+ | `prompting` | **`true`** | Walk to desk → sit → "chin scratch" thinking pose | Seated, head tilted, one arm raised |
108
+ | `working` | `true` | Walk to desk → sit → rapid arm movement (typing) | Seated, arms moving, body sway |
109
+ | `waiting` | `false` | Stand up from desk → wander slowly | Standing, hop bounce |
110
+ | `approval` | `false` | Stay at desk if already seated, else freeze in place | Seated or standing, visor flash yellow |
111
+ | `input` | `false` | Stay at desk if already seated, else freeze in place | Seated or standing, visor flash purple |
112
+ | `ended` | `false` | Slump at desk if seated, else collapse in place | Limp, all emissives dim |
113
+ | `connecting` | `false` | N/A — boot animation at spawn point | Scale-up from 0 |
114
+
115
+ ### Key Changes to `robotStateMap.ts`
116
+
117
+ ```typescript
118
+ // prompting/thinking — NOW seeks desk
119
+ thinking: {
120
+ seekDesk: true, // was: false
121
+ wander: false, // was: true
122
+ urgentFlash: false,
123
+ visorColorOverride: null,
124
+ speedMultiplier: 0.7, // walks to desk at moderate pace
125
+ },
126
+ ```
127
+
128
+ ### Desk Occupancy Rules
129
+
130
+ - Each room has 6 workstations (3 north wall, 2 west wall, 1 east wall)
131
+ - When `prompting` or `working`: robot claims the nearest empty desk in its room
132
+ - A robot **keeps its desk** through `prompting → working` transitions (don't stand up and re-seat)
133
+ - Desk released only when transitioning to `idle`, `waiting`, `ended`, or room reassignment
134
+ - If all desks in a room are full: robot stands behind the nearest occupied desk (overflow position)
135
+
136
+ ### Seated Status Display
137
+
138
+ While seated, the robot's dialogue bubble (WS3) and glow disc (WS4) remain active:
139
+ - Dialogue bubble floats above seated robot's head
140
+ - Glow disc stays beneath the desk chair position
141
+ - The desk itself can have a small holographic "screen" effect (optional) — a translucent rectangle in front of the seated robot showing the current tool icon
142
+
143
+ ### Animation Transitions
144
+
145
+ - `idle → prompting`: Robot walks to desk → sits → thinking pose
146
+ - `prompting → working`: Smooth transition from thinking to typing (no stand-up)
147
+ - `working → waiting`: Robot stands up from desk → releases desk → wanders
148
+ - `working → approval`: Robot stays seated, visor turns yellow, arms freeze mid-type
149
+ - `approval → working`: Resume typing animation (still seated, same desk)
150
+
151
+ ### Implementation Files
152
+
153
+ - `src/lib/robotStateMap.ts` — Change `thinking.seekDesk` to `true`, adjust speeds
154
+ - `src/components/3d/SessionRobot.tsx` — Update NAV logic: don't release desk on `prompting ↔ working` transitions
155
+ - `src/components/3d/Robot3DModel.tsx` — Add seated-thinking pose variant (distinct from seated-working)
156
+ - `src/lib/cyberdromeScene.ts` — Desk occupancy tracking already exists via `Workstation.occupantId`
157
+
158
+ ---
159
+
160
+ ## Workstream 3: Robot Dialogue Popup System
161
+
162
+ **Goal:** Replace the current movement-action visual system with speech-bubble dialogue popups above each robot's head. These show contextual messages based on session status and events. Dialogues appear whether the robot is standing or **seated at a desk** (see WS2.5).
163
+
164
+ ### Design
165
+
166
+ - Floating panel above robot head at `Y + 2.5` (above the label)
167
+ - Use `<Html>` from drei with `distanceFactor` so it scales with distance
168
+ - Styled as a cyberpunk speech bubble: dark background, neon border matching robot color, small triangle pointer at bottom
169
+ - Auto-dismiss after 4-6 seconds with fade-out
170
+ - Only one dialogue visible per robot at a time (latest wins)
171
+ - Queue rapid messages, show each briefly
172
+
173
+ ### Dialogue Content by Event
174
+
175
+ | Session Event / Status | Dialogue Text | Style |
176
+ |----------------------|---------------|-------|
177
+ | `SessionStart` | `"ONLINE"` | Green border, fade in |
178
+ | `UserPromptSubmit` | First 60 chars of prompt + `"..."` | Cyan border |
179
+ | `PreToolUse` (Read) | `"Reading {filename}..."` | Dim cyan |
180
+ | `PreToolUse` (Bash) | `"$ {command}"` (first 40 chars) | Orange border |
181
+ | `PreToolUse` (Edit/Write) | `"Editing {filename}..."` | Blue border |
182
+ | `PreToolUse` (Task) | `"Spawning agent..."` | Purple border |
183
+ | `PreToolUse` (WebFetch) | `"Fetching {url}..."` | Cyan border |
184
+ | `PostToolUse` | (dismiss current bubble) | — |
185
+ | Status → `approval` | `"AWAITING APPROVAL"` | Yellow border, persistent, pulse |
186
+ | Status → `input` | `"NEEDS INPUT"` | Purple border, persistent, pulse |
187
+ | Status → `waiting` | `"Task complete!"` | Green border |
188
+ | `SessionEnd` | `"OFFLINE"` | Red border, fade out |
189
+
190
+ ### Implementation
191
+
192
+ - New component: `src/components/3d/RobotDialogue.tsx`
193
+ - Receives dialogue queue from a new `dialogueStore` (or local state per robot)
194
+ - The `useWebSocket` hook dispatches dialogue events alongside session updates
195
+ - Dialogue state stored per sessionId: `{ text, borderColor, persistent, timestamp }`
196
+
197
+ ---
198
+
199
+ ## Workstream 4: Status-Driven Robot Visual Effects
200
+
201
+ **Goal:** Each session status is reflected through multiple visual channels on the robot — color, lighting, ground glow, and body animations are already partially there. Enhance with:
202
+
203
+ ### A. Character Accent Color by CLI Source
204
+
205
+ | CLI Source | Base Accent | Robot Tint |
206
+ |------------|-------------|------------|
207
+ | Claude Code | `#00f0ff` (cyan) | Cool cyan/blue palette |
208
+ | Gemini CLI | `#4285f4` (Google blue) | Blue-white palette |
209
+ | Codex CLI | `#10a37f` (OpenAI green) | Green palette |
210
+ | OpenClaw | `#ff6b2b` (orange) | Warm orange palette |
211
+ | Unknown | `#aa66ff` (purple) | Purple palette |
212
+
213
+ The robot's neon material, visor, glow disc, and antenna tip should all use the CLI source accent color as the base, with status modifying the intensity/behavior.
214
+
215
+ ### B. Ground Glow Circle Enhancement
216
+
217
+ Current: `glowDisc` at Y=0.01-0.13, single color.
218
+
219
+ Enhanced:
220
+ - **idle**: Gentle pulse, 60% opacity, accent color
221
+ - **prompting/thinking**: Ripple outward animation (expanding ring), accent color — visible under desk while seated
222
+ - **working**: Bright steady glow, slight rotation, accent color — visible under desk while seated
223
+ - **waiting**: Slow breathing pulse, green tint
224
+ - **approval**: Rapid yellow pulse, expanding/contracting, `#ffdd00`
225
+ - **input**: Slow purple orbit ring, `#aa66ff`
226
+ - **ended**: Fade to dark, shrink to nothing
227
+ - **connecting**: Boot-up expanding circle from 0 to full radius
228
+
229
+ ### C. Alert Visual (Replaces Label Completion Alerts)
230
+
231
+ Instead of the current "Label Alerts" in settings (which use browser notifications), alerts should manifest as:
232
+
233
+ - **Pulsing glow ring** around the robot (ground level, ring geometry)
234
+ - Ring color = status color (yellow for approval, purple for input)
235
+ - Ring radius pulses between 1.0 and 1.8 units
236
+ - Emission intensity increases over time (urgency escalation)
237
+ - After 30s of approval state: ring starts flashing rapidly
238
+ - After 60s: ring becomes double-ring with particle trail
239
+
240
+ ### D. Status Sound Effects (Per-CLI Configurable)
241
+
242
+ Each status transition triggers a sound. The sound set is configurable per CLI source:
243
+
244
+ ```
245
+ Claude Code: {
246
+ sessionStart: 'chime',
247
+ approval: 'alarm',
248
+ input: 'warble',
249
+ working: 'click',
250
+ ended: 'cascade',
251
+ ...
252
+ }
253
+ Gemini CLI: {
254
+ sessionStart: 'ding',
255
+ approval: 'buzz',
256
+ ...
257
+ }
258
+ ```
259
+
260
+ ---
261
+
262
+ ## Workstream 5: Sound Settings Per-CLI Configuration
263
+
264
+ **Goal:** The SOUND tab in settings should be restructured to configure sounds per AI CLI independently.
265
+
266
+ ### Current State (Broken)
267
+
268
+ `SoundSettings.tsx` has a hardcoded `SOUND_LIBRARY` that doesn't match `soundEngine.ts` actual sounds. Action names also don't match. The preview button is not wired up.
269
+
270
+ ### Target Architecture
271
+
272
+ #### Settings Shape
273
+
274
+ ```typescript
275
+ interface SoundSettings {
276
+ enabled: boolean;
277
+ volume: number; // 0-1 master volume
278
+ perCli: {
279
+ [cliSource: string]: { // 'claude', 'gemini', 'codex', 'openclaw'
280
+ enabled: boolean;
281
+ volume: number; // 0-1 per-CLI volume multiplier
282
+ actions: {
283
+ [action in SoundAction]?: SoundName;
284
+ };
285
+ };
286
+ };
287
+ }
288
+ ```
289
+
290
+ #### Default CLI Configs
291
+
292
+ | CLI | Character | Sound Profile |
293
+ |-----|-----------|---------------|
294
+ | Claude Code | Precision, technical | Clean digital tones (chime, ping, click) |
295
+ | Gemini CLI | Warm, organic | Warmer sounds (ding, chirp, swoosh) |
296
+ | Codex CLI | Minimal, efficient | Short blips (blip, beep, click) |
297
+ | OpenClaw | Bold, energetic | Stronger sounds (buzz, fanfare, cascade) |
298
+
299
+ #### UI Layout (SoundSettings.tsx)
300
+
301
+ ```
302
+ ┌─────────────────────────────────────┐
303
+ │ [Master Volume Slider] [Enable All] │
304
+ ├─────────────────────────────────────┤
305
+ │ CLI Tabs: [Claude] [Gemini] [Codex] [OpenClaw] │
306
+ ├─────────────────────────────────────┤
307
+ │ Selected CLI: Claude Code │
308
+ │ [Enable] [Volume: ████░░ 70%] │
309
+ │ │
310
+ │ Session Events: │
311
+ │ Session Start [chime ▾] [▶] │
312
+ │ Prompt Submit [ping ▾] [▶] │
313
+ │ Task Complete [fanfare ▾] [▶] │
314
+ │ Session End [cascade ▾] [▶] │
315
+ │ │
316
+ │ Tool Sounds: │
317
+ │ Read/Grep/Glob [click ▾] [▶] │
318
+ │ Write/Edit [blip ▾] [▶] │
319
+ │ Bash [buzz ▾] [▶] │
320
+ │ Web Fetch [swoosh ▾] [▶] │
321
+ │ Task/Agent [ding ▾] [▶] │
322
+ │ │
323
+ │ Alerts: │
324
+ │ Approval Needed [alarm ▾] [▶] │
325
+ │ Input Needed [chime ▾] [▶] │
326
+ │ Kill [thud ▾] [▶] │
327
+ └─────────────────────────────────────┘
328
+ ```
329
+
330
+ Each `[▶]` is a preview button that plays the selected sound.
331
+
332
+ #### Fix Mismatches
333
+
334
+ - Import `SoundName`, `SoundAction`, `DEFAULT_ACTION_SOUNDS`, `ACTION_LABELS`, `ACTION_CATEGORIES` directly from `soundEngine.ts` instead of local hardcoded lists
335
+ - Wire up preview: `soundEngine.preview(soundName)` method (new — plays sound regardless of enabled state)
336
+
337
+ ---
338
+
339
+ ## Workstream 6: Z-Index & Layering Fixes
340
+
341
+ **Goal:** Robot labels, room names, and dialogue bubbles must never cover DOM overlays (settings modal, detail panel).
342
+
343
+ ### Strategy
344
+
345
+ 1. **Room labels** → Moved to 3D `<Text>` (Workstream 2) — inherently behind DOM
346
+ 2. **Robot labels** (`RobotLabel.tsx`) → Already uses `<Html>` with `zIndexRange={[0, 0]}` to prevent DOM overlay conflicts. If not set, add it.
347
+ 3. **Robot dialogues** (new) → Use `<Html>` with `zIndexRange={[0, 0]}` and `style={{ zIndex: 1 }}`
348
+ 4. **SceneOverlay** (HUD) → z-index 10 — keep as-is
349
+ 5. **Detail Panel** → z-index 100 — keep as-is
350
+ 6. **Settings Modal** → z-index 200+ — verify this is higher than all 3D Html elements
351
+
352
+ ### drei `<Html>` Props
353
+
354
+ - `zIndexRange={[0, 0]}` — prevents drei from auto-managing z-index
355
+ - `style={{ pointerEvents: 'none' }}` — labels don't intercept clicks
356
+ - `occlude` prop — can optionally hide labels when behind geometry
357
+
358
+ ---
359
+
360
+ ## Workstream 7: Additional Enhancements (Ideas You May Have Missed)
361
+
362
+ ### A. CLI Source Badge on Robot
363
+
364
+ Small icon/emblem on the robot's chest or antenna showing which AI CLI it belongs to:
365
+ - Claude: `C` in cyan circle
366
+ - Gemini: `G` in blue circle
367
+ - Codex: `X` in green circle
368
+ - OpenClaw: `O` in orange circle
369
+
370
+ Rendered as a small `<Text>` or `<Sprite>` attached to the robot mesh.
371
+
372
+ ### B. Approval Urgency Escalation
373
+
374
+ The longer a robot stays in `approval` or `input` state, the more urgent its visual effects become:
375
+
376
+ | Duration | Visual Effect |
377
+ |----------|---------------|
378
+ | 0-15s | Yellow/purple glow, normal pulse |
379
+ | 15-30s | Faster pulse, brighter glow, ring expands |
380
+ | 30-60s | Rapid flash, double ring, subtle shake |
381
+ | 60s+ | Ring particles, visor flashing, sound alarm repeats |
382
+
383
+ ### C. Tool-Specific Working Animations
384
+
385
+ When `working`, the robot's animation subtly changes based on which tool is active:
386
+ - `Read/Grep/Glob`: Head scanning left-right (reading)
387
+ - `Write/Edit`: Arms typing rapidly
388
+ - `Bash`: One arm extended (commanding)
389
+ - `WebFetch`: Antenna glowing brightly (receiving data)
390
+ - `Task`: Both arms raised (delegating)
391
+
392
+ This requires tracking `currentTool` on the session object and passing it to `Robot3DModel`.
393
+
394
+ ### D. Team/Subagent Visual Connections
395
+
396
+ When a robot spawns a subagent (via Task tool), draw a faint laser-line from parent to child robot:
397
+ - Line color: parent's accent color at 30% opacity
398
+ - Animated dash pattern flowing from parent → child
399
+ - Line disappears when subagent session ends
400
+
401
+ Implementation: `<Line>` from drei, updated per frame.
402
+
403
+ ### E. White Noise & Ambient Sound (Settings Feature)
404
+
405
+ A dedicated **Ambient** section in the SOUND settings tab for background audio while monitoring the Cyberdrome.
406
+
407
+ #### White Noise Presets
408
+
409
+ | Preset | Description |
410
+ |--------|-------------|
411
+ | Off | Silence (default) |
412
+ | Rain | Gentle rain ambience |
413
+ | Lo-fi Hum | Soft electronic low-frequency hum |
414
+ | Server Room | Data center fan/hum loop |
415
+ | Deep Space | Slow droning ambient pad |
416
+ | Coffee Shop | Muted chatter + clink sounds |
417
+
418
+ - Master toggle: on/off
419
+ - Volume slider (independent of sound effects volume)
420
+ - Loops seamlessly via Web Audio `AudioBufferSourceNode` with `loop: true`
421
+ - Generated procedurally via Web Audio oscillators + filters (no audio file downloads needed)
422
+
423
+ #### Room Activity Sound (toggle within Ambient section)
424
+
425
+ Layered on top of the white noise:
426
+ - **Toggle:** `[x] Room Activity Sounds`
427
+ - When enabled, each room emits a subtle electronic activity layer proportional to working robots:
428
+ - 0 robots: silence
429
+ - 1-2 working: soft keyclick undertone
430
+ - 3-5 working: busier hum + occasional blips
431
+ - 6+: full activity buzz
432
+ - Volume scales with camera distance to room (spatial audio via Web Audio panner)
433
+ - Can be enabled independently of white noise (e.g., room sounds on, white noise off)
434
+
435
+ #### UI Layout (inside SoundSettings.tsx, below per-CLI config)
436
+
437
+ ```
438
+ ┌─────────────────────────────────────┐
439
+ │ Ambient & White Noise │
440
+ ├─────────────────────────────────────┤
441
+ │ [x] Enable Ambient Audio │
442
+ │ Volume: ████░░░░ 40% │
443
+ │ │
444
+ │ Preset: [Server Room ▾] │
445
+ │ │
446
+ │ [x] Room Activity Sounds │
447
+ │ Room Volume: ██░░░░░░ 25% │
448
+ └─────────────────────────────────────┘
449
+ ```
450
+
451
+ #### Settings Shape Addition
452
+
453
+ ```typescript
454
+ interface AmbientSettings {
455
+ enabled: boolean;
456
+ volume: number; // 0-1
457
+ preset: 'off' | 'rain' | 'lofi' | 'serverRoom' | 'deepSpace' | 'coffeeShop';
458
+ roomSounds: boolean; // room activity layer toggle
459
+ roomVolume: number; // 0-1
460
+ }
461
+ ```
462
+
463
+ ### F. Status Transition Particle Effects
464
+
465
+ When a robot changes status, emit a brief particle burst:
466
+ - `idle → working`: Small spark shower (upward)
467
+ - `working → waiting`: Confetti-like green particles
468
+ - `any → approval`: Yellow warning particles (outward ring)
469
+ - `any → ended`: Smoke/fade particles (downward)
470
+
471
+ Implementation: `@react-three/drei` `<Sparkles>` or custom `Points` geometry.
472
+
473
+ ### G. Session Progress Timer
474
+
475
+ A small circular progress indicator on the robot's glow disc showing how long the current status has been active:
476
+ - Ring fills clockwise over time
477
+ - Resets on status change
478
+ - Useful for gauging how long approval has been pending
479
+
480
+ ---
481
+
482
+ ## Team Structure for Execution
483
+
484
+ ### Agent Assignments
485
+
486
+ | Agent | Workstreams | Dependencies |
487
+ |-------|-------------|--------------|
488
+ | **rename-agent** | WS1 (Group→Room rename) | None — runs first |
489
+ | **desk-behavior-agent** | WS2.5 (Desk-Sitting for Prompting & Working) | After WS1 |
490
+ | **3d-labels-agent** | WS2 (Door Labels) + WS6 (Z-Index) | After WS1 |
491
+ | **dialogue-agent** | WS3 (Dialogue Popups) | After WS1 + WS2.5 (needs seated position for bubble placement) |
492
+ | **visual-fx-agent** | WS4 (Status Visuals) + WS7.B,C,F,G | After WS1 + WS2.5 (glow disc at desk) |
493
+ | **sound-agent** | WS5 (Sound Settings per-CLI) + WS4.D (Status Sounds) + WS7.E (White Noise & Ambient) | After WS1 |
494
+ | **polish-agent** | WS7.A,D (CLI Badge, Subagent Lines) | After WS1 |
495
+
496
+ ### Execution Order
497
+
498
+ ```
499
+ Phase 1: rename-agent (WS1) — all other agents blocked
500
+ Phase 2a: desk-behavior-agent (WS2.5) + 3d-labels-agent (WS2+6) + sound-agent (WS5) — in parallel
501
+ Phase 2b: dialogue-agent (WS3) + visual-fx-agent (WS4) + polish-agent (WS7) — after WS2.5 lands
502
+ Phase 3: Integration test — build + test + visual verification
503
+ ```
504
+
505
+ ---
506
+
507
+ ## Verification Checklist
508
+
509
+ - [ ] `npx tsc --noEmit` — no type errors
510
+ - [ ] `npx vite build` — builds cleanly
511
+ - [ ] `npx vitest run` — all tests pass
512
+ - [ ] No "group" references remaining (except `groupBy` in settings)
513
+ - [ ] Room names visible at doorways (3D text on floor), not covering UI
514
+ - [ ] Robots walk to desk and sit when prompting or working
515
+ - [ ] Robots keep same desk through prompting → working transitions
516
+ - [ ] Robots stand up and wander when returning to idle/waiting
517
+ - [ ] Dialogue bubbles appear above seated/standing robots on status changes
518
+ - [ ] Dialogue bubbles show tool names, prompt snippets, status messages
519
+ - [ ] Robot glow/color reflects CLI source (cyan/blue/green/orange)
520
+ - [ ] Ground glow circle animates per-status (pulse, ripple, flash)
521
+ - [ ] Alert glow ring escalates urgency over 15s/30s/60s thresholds
522
+ - [ ] Sound settings show per-CLI tabs (Claude/Gemini/Codex/OpenClaw)
523
+ - [ ] Sound preview buttons play the selected sound
524
+ - [ ] Status transitions trigger per-CLI configurable sounds
525
+ - [ ] White noise presets play and loop seamlessly (rain, lo-fi, server room, etc.)
526
+ - [ ] White noise volume independent of sound effects volume
527
+ - [ ] Room activity sounds toggle on/off independently of white noise
528
+ - [ ] Room activity volume scales with camera distance
529
+ - [ ] Labels/dialogues don't cover settings or detail panel
530
+ - [ ] Approval urgency escalates visually over time
531
+ - [ ] Status transition particle effects fire on state changes