Skip to content

fix(gastown): fix town deletion DO/container leaks and terminal stability#1196

Merged
jrf0110 merged 2 commits intomainfrom
1195-1182-gt-bugs
Mar 18, 2026
Merged

fix(gastown): fix town deletion DO/container leaks and terminal stability#1196
jrf0110 merged 2 commits intomainfrom
1195-1182-gt-bugs

Conversation

@jrf0110
Copy link
Copy Markdown
Contributor

@jrf0110 jrf0110 commented Mar 18, 2026

Summary

Fixes two Gastown bugs from Phase 3:

  • Bug: Deleting a town doesn't clean up TownDO, TownContainerDO, or AgentDOs — resources leak indefinitely #1182 — Town deletion leaks DOs and containers: The tRPC deleteTown mutation only removed rows from GastownUserDO, leaving TownDO, TownContainerDO, and AgentDO instances running indefinitely (burning Cloudflare resources). Fixed by: (1) calling TownDO.destroy() from the tRPC path, (2) destroying TownContainerDO in TownDO.destroy(), (3) adding alarm exit conditions to prevent resurrection after destroy, (4) bumping compat date to 2026-02-24 so deleteAll() clears alarms.

  • Fix terminal stability — WebSocket reconnection, resize debounce, control frame filtering #1195 — Terminal stability: Three compounding issues degraded the xterm.js terminal: (1) PTY WebSockets had no reconnection logic—container sleep/restart permanently froze the terminal, (2) undebounced ResizeObserver caused resize storms during CSS transitions (blacked-out cells), (3) SDK cursor metadata (0x00 prefix + JSON) was written as visible text to the terminal. All three are fixed, and the duplicated terminal setup code (~150 lines each in MayorTerminalPane and AgentTerminalPane) is consolidated into the shared useXtermPty hook.

Closes #1182
Closes #1195

Verification

  • pnpm typecheck — passes across all packages (gastown + root)
  • pnpm test:integration (gastown) — new town-deletion tests written; pre-existing failures in http-api.test.ts and convoy-dag.test.ts unchanged (22 failures existed before this PR on main)
  • pnpm test (gastown unit) — passes
  • Manual code review of all 6 root causes from Bug: Deleting a town doesn't clean up TownDO, TownContainerDO, or AgentDOs — resources leak indefinitely #1182 against the fix
  • Verified HTTP DELETE handler (towns.handler.ts) also benefits from TownDO.destroy() now destroying the container

Visual Changes

N/A

Reviewer Notes

  • The cloud-agent-next package has 51 pre-existing lint errors that block git push — used --no-verify as approved by the user.
  • The integration test suite has a pre-existing "Isolated storage failed" error in rig-do.test.ts that prevents test files alphabetically after it from running. The new town-deletion.test.ts tests are structurally sound and follow the exact patterns from rig-alarm.test.ts.
  • The compatibility date bump (2026-01-272026-02-24) enables deleteAll() to also clear alarms. The installed Miniflare runtime only supports up to 2026-01-28, so tests fall back gracefully.
  • The useXtermPty deduplication removes ~300 lines of duplicated code from TerminalBar.tsx while adding reconnection, resize debounce, and control frame filtering in one place.

Comment thread cloudflare-gastown/src/trpc/router.ts Outdated
@kilo-code-bot
Copy link
Copy Markdown
Contributor

kilo-code-bot Bot commented Mar 18, 2026

Code Review Summary

Status: 2 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 2
SUGGESTION 0

Fix these issues in Kilo Cloud

Issue Details (click to expand)

WARNING

File Line Issue
cloudflare-gastown/src/dos/Town.do.ts 3818 Treating a missing town:id as a deletion tombstone can still shut off the alarm loop for live towns whose id was never persisted.
src/components/gastown/useXtermPty.ts 149 Dropping every parseable JSON text frame will hide legitimate PTY output from programs that print JSON lines.
Other Observations (not in diff)

Issues found in unchanged code that cannot receive inline comments:

File Line Issue
cloudflare-gastown/src/handlers/towns.handler.ts 135 handleDeleteTown() still swallows TownDO.destroy() failures and deletes the user record anyway, so the HTTP DELETE path can still orphan running resources on cleanup errors.
Files Reviewed (57 files)
  • .specs/kiloclaw-billing.md - 0 issues
  • cloudflare-gastown/src/dos/Town.do.ts - 1 issue
  • cloudflare-gmail-push/src/routes/push.ts - 0 issues
  • kiloclaw/controller/src/backup-file.test.ts - 0 issues
  • kiloclaw/controller/src/backup-file.ts - 0 issues
  • kiloclaw/controller/src/index.ts - 0 issues
  • kiloclaw/controller/src/routes/files.test.ts - 0 issues
  • kiloclaw/controller/src/routes/files.ts - 0 issues
  • kiloclaw/controller/src/safe-path.test.ts - 0 issues
  • kiloclaw/controller/src/safe-path.ts - 0 issues
  • kiloclaw/google-setup/setup.mjs - 0 issues
  • kiloclaw/src/durable-objects/kiloclaw-instance.test.ts - 0 issues
  • kiloclaw/src/durable-objects/kiloclaw-instance/gateway.ts - 0 issues
  • kiloclaw/src/durable-objects/kiloclaw-instance/index.ts - 0 issues
  • kiloclaw/src/routes/platform.ts - 0 issues
  • kiloclaw/start-openclaw.sh - 0 issues
  • src/app/(app)/claw/components/ClawDashboard.tsx - 0 issues
  • src/app/(app)/claw/components/FileEditorPane.tsx - 0 issues
  • src/app/(app)/claw/components/FileEditorShell.tsx - 0 issues
  • src/app/(app)/claw/components/FileTree.tsx - 0 issues
  • src/app/(app)/claw/components/OpenClawButton.tsx - 0 issues
  • src/app/(app)/claw/components/OpenclawConfigEditor.tsx - 0 issues
  • src/app/(app)/claw/components/SettingsTab.tsx - 0 issues
  • src/app/(app)/claw/components/WorkspaceFileEditor.tsx - 0 issues
  • src/app/(app)/claw/components/changelog-data.ts - 0 issues
  • src/app/(app)/claw/components/validateOpenclawJson.ts - 0 issues
  • src/app/(app)/claw/components/withStatusQueryBoundary.test.ts - 0 issues
  • src/app/admin/components/KiloclawInstances/AdminFileEditor.tsx - 0 issues
  • src/app/admin/components/KiloclawInstances/KiloclawInstanceDetail.tsx - 0 issues
  • src/app/api/openrouter/[...path]/route.ts - 0 issues
  • src/app/api/private/users/route.ts - 0 issues
  • src/app/get-started/page.tsx - 0 issues
  • src/app/get-started/personal/_components/ProductOptionsContent.tsx - 0 issues
  • src/components/gastown/useXtermPty.ts - 1 issue
  • src/hooks/useKiloClaw.ts - 0 issues
  • src/hooks/useResizableSidebar.ts - 0 issues
  • src/lib/code-reviews/prompts/generate-prompt.ts - 0 issues
  • src/lib/code-reviews/triggers/prepare-review-payload.ts - 0 issues
  • src/lib/creditTransactions.ts - 0 issues
  • src/lib/firstTopupBonus.ts - 0 issues
  • src/lib/kilo-auto-model.ts - 0 issues
  • src/lib/kiloclaw/config-redaction.test.ts - 0 issues
  • src/lib/kiloclaw/config-redaction.ts - 0 issues
  • src/lib/kiloclaw/kiloclaw-internal-client.ts - 0 issues
  • src/lib/kiloclaw/types.ts - 0 issues
  • src/lib/models.ts - 0 issues
  • src/lib/processUsage.test.ts - 0 issues
  • src/lib/processUsage.ts - 0 issues
  • src/lib/providers/index.ts - 0 issues
  • src/lib/providers/openrouter/index.ts - 0 issues
  • src/lib/providers/openrouter/inference-provider-id.ts - 0 issues
  • src/lib/providers/openrouter/types.ts - 0 issues
  • src/lib/providers/vercel/index.ts - 0 issues
  • src/routers/admin-kiloclaw-instances-router.ts - 0 issues
  • src/routers/kiloclaw-billing-router.test.ts - 0 issues
  • src/routers/kiloclaw-router.ts - 0 issues
  • src/tests/openrouter-models-sorting.approved.json - 0 issues

Reviewed by gpt-5.4-20260305 · 603,343 tokens

@jrf0110 jrf0110 force-pushed the 1195-1182-gt-bugs branch from 2459643 to 58bc05b Compare March 18, 2026 04:05
Comment thread cloudflare-gastown/test/integration/town-deletion.test.ts
Comment thread cloudflare-gastown/test/integration/town-deletion.test.ts Outdated
Comment thread cloudflare-gastown/src/dos/Town.do.ts
@jrf0110 jrf0110 force-pushed the 1195-1182-gt-bugs branch from 58bc05b to f642a18 Compare March 18, 2026 04:16
Comment thread cloudflare-gastown/src/dos/Town.do.ts
Comment thread cloudflare-gastown/src/dos/Town.do.ts Outdated
Comment thread cloudflare-gastown/src/dos/Town.do.ts Outdated
Comment thread src/components/gastown/useXtermPty.ts Outdated
@jrf0110 jrf0110 force-pushed the 1195-1182-gt-bugs branch from f642a18 to d525289 Compare March 18, 2026 14:55
jrf0110 added 2 commits March 18, 2026 09:58
…1182)

Town deletion via tRPC only removed rows from GastownUserDO, leaving
TownDO, TownContainerDO, and AgentDOs running indefinitely. Six
compounding root causes:

1. tRPC deleteTown now calls TownDO.destroy() before removing user rows
2. TownDO.destroy() now destroys TownContainerDO (kills container)
3. Alarm has an exit condition: skips re-arming when town:id is missing
4. armAlarmIfNeeded() checks for town:id to prevent alarm resurrection
5. Compatibility date updated to 2026-02-24 so deleteAll() clears alarms
6. Integration tests for the full deletion flow

Closes #1182
… control frame filter (#1195)

Three compounding bugs caused terminal instability:

1. PTY WebSockets had no reconnection logic — container sleep/restart
   permanently froze the terminal. Now reconnects with exponential
   backoff (1s→2s→4s→8s, 8 attempts) and re-creates PTY sessions.

2. Undebounced ResizeObserver fired resize storms during CSS transitions,
   causing PTY/xterm dimension mismatches (blacked-out cells). Now
   debounced at 150ms.

3. SDK cursor metadata (0x00 prefix + JSON) written as raw text to
   xterm. Now filtered on both binary and string WebSocket frames.

Additionally:
- Deduplicated terminal setup: MayorTerminalPane and AgentTerminalPane
  now use the shared useXtermPty hook instead of duplicating ~150 lines
  of xterm/WebSocket/resize logic each.
- Added visual connection status indicator (green=connected,
  yellow=reconnecting, gray=disconnected) to all terminal panes.

Closes #1195
@jrf0110 jrf0110 force-pushed the 1195-1182-gt-bugs branch from d525289 to 8621796 Compare March 18, 2026 14:59
JSON.parse(data);
// Valid JSON on the PTY WebSocket = SDK control message.
// Actual PTY output that starts with '{' would be part
// of a larger escape sequence and wouldn't parse as JSON.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: Valid JSON can be legitimate terminal output

Programs often emit JSON lines verbatim (for example {"status":"ok"} from CLI tools). This branch now parses any text frame that starts with { and drops it, so those commands will silently lose output in the terminal. The filter needs a stronger sentinel than "parses as JSON" before returning here.

@jrf0110 jrf0110 merged commit 347ba01 into main Mar 18, 2026
18 checks passed
@jrf0110 jrf0110 deleted the 1195-1182-gt-bugs branch March 18, 2026 15:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants