webui: improve reconnection delays

- make them a lot more aggressive,
  as the user is likely sitting and staring at the screen
- make the numbers rounder (easier to grok)
- add some jitter
diff --git a/webui/src/data.ts b/webui/src/data.ts
index af696dc..327ff89 100644
--- a/webui/src/data.ts
+++ b/webui/src/data.ts
@@ -31,10 +31,9 @@
   private eventSource: EventSource | null = null;
   private reconnectTimer: number | null = null;
   private reconnectAttempt: number = 0;
-  // Reconnection timeout delays in milliseconds (runs from 1s to 60s)
+  // Reconnection timeout delays in milliseconds (runs from 100ms to ~15s). Fibonacci-ish.
   private readonly reconnectDelaysMs: number[] = [
-    1000, 1500, 2250, 3375, 5062.5, 7593.75, 11390.625, 17085.9375,
-    25628.90625, 38443.359375, 57665.0390625, 60000, 60000
+    100, 100, 200, 300, 500, 800, 1300, 2100, 3400, 5500, 8900, 14400,
   ];
 
   // Initial load completion tracking
@@ -174,8 +173,13 @@
       this.reconnectTimer = null;
     }
 
-    const delayIndex = Math.min(this.reconnectAttempt, this.reconnectDelaysMs.length - 1);
-    const delay = this.reconnectDelaysMs[delayIndex];
+    const delayIndex = Math.min(
+      this.reconnectAttempt,
+      this.reconnectDelaysMs.length - 1,
+    );
+    let delay = this.reconnectDelaysMs[delayIndex];
+    // Add jitter: +/- 10% of the delay
+    delay *= 0.9 + Math.random() * 0.2;
 
     console.log(
       `Scheduling reconnect in ${delay}ms (attempt ${this.reconnectAttempt + 1})`,
diff --git a/webui/src/web-components/sketch-app-shell.test.ts b/webui/src/web-components/sketch-app-shell.test.ts
index 6c8d468..5180f7e 100644
--- a/webui/src/web-components/sketch-app-shell.test.ts
+++ b/webui/src/web-components/sketch-app-shell.test.ts
@@ -297,20 +297,20 @@
   // Wait for initial data to load
   await page.waitForTimeout(1000);
 
-  // Simulate connection established by setting the connection status property
+  // Simulate connection established by disabling DataManager connection changes
   await component.evaluate(async () => {
     const appShell = document.querySelector("sketch-app-shell") as any;
-    if (appShell) {
+    if (appShell && appShell.dataManager) {
+      // Prevent DataManager from changing connection status during tests
+      appShell.dataManager.scheduleReconnect = () => {};
+      appShell.dataManager.updateConnectionStatus = () => {};
+      // Set connected status
       appShell.connectionStatus = "connected";
       appShell.requestUpdate();
-      // Force an update cycle to complete
       await appShell.updateComplete;
     }
   });
 
-  // Wait a bit more for the status to update and for any async operations
-  await page.waitForTimeout(1000);
-
   // Check that the call status component shows IDLE
   // The last user/agent message (agent with end_of_turn: true) should make it idle
   // even though there are commit and tool messages after it
@@ -397,9 +397,15 @@
   expect(isIdleResult.expectedWorking).toBe(true);
 
   // Now test the full component interaction
-  await component.evaluate(() => {
+  await component.evaluate(async () => {
     const appShell = document.querySelector("sketch-app-shell") as any;
     if (appShell) {
+      // Disable DataManager connection status changes that interfere with tests
+      if (appShell.dataManager) {
+        appShell.dataManager.scheduleReconnect = () => {};
+        appShell.dataManager.updateConnectionStatus = () => {};
+      }
+      
       // Set connection status to connected
       appShell.connectionStatus = "connected";
 
@@ -413,6 +419,7 @@
       // The messages are already set from the previous test
       // Force a re-render
       appShell.requestUpdate();
+      await appShell.updateComplete;
     }
   });