Skip to content

feat(gastown): Gastown (#204)#544

Merged
jrf0110 merged 1 commit intomainfrom
204-gt-prop-d
Feb 28, 2026
Merged

feat(gastown): Gastown (#204)#544
jrf0110 merged 1 commit intomainfrom
204-gt-prop-d

Conversation

@jrf0110
Copy link
Copy Markdown
Contributor

@jrf0110 jrf0110 commented Feb 24, 2026

What is Gastown?

Gastown is an agent orchestration system for managing multiple AI coding agents working concurrently across git repositories. It was originally built as a local CLI tool — two Go binaries (gt for orchestration and bd for the Beads work-tracking database) coordinated with tmux on the user's machine.

The core primitive is beads — a universal data model where every object (issues, mail, merge requests, escalations, convoys, agents) is a bead. Agents are organized into roles: a Mayor that coordinates, Polecats that do the work, a Refinery that reviews and merges, and a Witness that monitors health.

What is this PR?

Gastown Cloud — a cloud-native implementation of Gastown as a Kilo platform feature, built on Cloudflare Workers, Durable Objects, and Containers. Instead of tmux on a laptop, agents run in Cloudflare Containers. Instead of databases on disk, state lives in DO SQLite. Users interact through a web dashboard with live agent terminals via xterm.js.

There's still a lot of work to do being tracked in #204


Overview Page Rig Page
Overview Rig
Agent Detail Drawer Bead Detail Drawer
Agent Detail Bead Detail
Merge Queue Beads List
Merge Queue Beads List
Town Settings
Town Settings

Architecture

A diagram for ants
image

  • Cloudflare Worker (Hono) — API gateway with CF Access auth
  • TownDO — central control-plane DO with all rig, agent, bead, and config state in SQLite
  • AgentDO — per-agent event storage with 10GB isolation
  • TownContainerDO — Docker container lifecycle, PTY proxy, git merge infrastructure
  • GastownUserDO — user-to-town ownership registry

Data model

  • Beads-centric schema — all domain objects (issues, messages, molecules, agents, merge requests, convoys, escalations) are beads with type-specific satellite metadata tables
  • Bead dependencies graph for convoy tracking and molecule step ordering
  • Bead events log for audit trail

Agent system

  • Mayor — orchestrating AI that triages, plans, and delegates work via tool calls
  • Polecats — parallel workers dispatched to individual beads, working in isolated git worktrees
  • Refinery — LLM agent that reviews diffs and runs quality gates before merge (falls back to deterministic merge when no gates are configured)
  • Witness patrol — mechanical health checks in the TownDO alarm (stale agent detection, GUPP violation checks, mail delivery)
  • Mail — inter-agent messaging implemented as message-type beads, delivered by the alarm loop to running agents
  • Escalation — severity-routed with configurable thresholds and automatic re-escalation of unacknowledged escalations
  • Convoys — batch work tracking with auto-landing detection (backend complete, not yet wired to Mayor tools)
  • Molecules — multi-step task decomposition as parent-child bead trees with dependency ordering (backend complete, not yet used by agents)

Terminal and UI

  • xterm.js PTY terminals connected to container SDK sessions via WebSocket passthrough (browser → worker → container DO → container)
  • Next.js dashboard with drawer stack navigation for drill-down into beads, agents, and events
  • Persistent mayor terminal bar across all town pages
  • Town-specific sidebar with live rig list
  • All Gastown UI routes gated to admin-only users

Infrastructure

  • Git credential resolution from platform integrations with on-demand token refresh
  • Detached worktree merge strategy to avoid branch lock conflicts during concurrent merges
  • Multi-rig support — multiple rigs per town sharing a single container with isolated git clones

@kilo-code-bot
Copy link
Copy Markdown
Contributor

kilo-code-bot bot commented Feb 24, 2026

Code Review Summary

Status: 2 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 2
SUGGESTION 0
Issue Details (click to expand)

WARNING

File Line Issue
cloudflare-gastown/src/handlers/rig-escalations.handler.ts 32 body, metadata, and source_agent_id from the request are validated by Zod but silently dropped when calling routeEscalation — escalations lose context and attribution
cloudflare-gastown/src/handlers/rig-beads.handler.ts 160 handleSlingBead logs full metadata JSON which could contain sensitive data
Other Observations (not in diff)

No additional issues found outside the diff.

Files Reviewed (100 files)

Worker & Middleware (core security)

  • cloudflare-gastown/src/gastown.worker.ts - 0 new issues (existing comments address auth concerns)
  • cloudflare-gastown/src/middleware/auth.middleware.ts - 0 new issues
  • cloudflare-gastown/src/middleware/cf-access.middleware.ts - 0 new issues
  • cloudflare-gastown/src/middleware/mayor-auth.middleware.ts - 0 new issues

Handlers

  • cloudflare-gastown/src/handlers/rig-beads.handler.ts - 1 issue
  • cloudflare-gastown/src/handlers/rig-agents.handler.ts - 0 new issues
  • cloudflare-gastown/src/handlers/rig-escalations.handler.ts - 1 issue
  • cloudflare-gastown/src/handlers/rig-mail.handler.ts - 0 new issues
  • cloudflare-gastown/src/handlers/rig-review-queue.handler.ts - 0 new issues
  • cloudflare-gastown/src/handlers/rig-agent-events.handler.ts - 0 new issues
  • cloudflare-gastown/src/handlers/rig-bead-events.handler.ts - 0 new issues
  • cloudflare-gastown/src/handlers/rig-molecules.handler.ts - 0 new issues
  • cloudflare-gastown/src/handlers/mayor-tools.handler.ts - 0 new issues
  • cloudflare-gastown/src/handlers/mayor.handler.ts - 0 new issues
  • cloudflare-gastown/src/handlers/towns.handler.ts - 0 new issues
  • cloudflare-gastown/src/handlers/town-config.handler.ts - 0 new issues
  • cloudflare-gastown/src/handlers/town-container.handler.ts - 0 new issues
  • cloudflare-gastown/src/handlers/town-convoys.handler.ts - 0 new issues
  • cloudflare-gastown/src/handlers/town-escalations.handler.ts - 0 new issues
  • cloudflare-gastown/src/handlers/town-events.handler.ts - 0 new issues

Durable Objects

  • cloudflare-gastown/src/dos/Town.do.ts - 0 new issues
  • cloudflare-gastown/src/dos/TownContainer.do.ts - 0 new issues
  • cloudflare-gastown/src/dos/GastownUser.do.ts - 0 new issues
  • cloudflare-gastown/src/dos/Agent.do.ts - 0 new issues
  • cloudflare-gastown/src/dos/AgentIdentity.do.ts - 0 new issues
  • cloudflare-gastown/src/dos/town/container-dispatch.ts - 0 new issues
  • cloudflare-gastown/src/dos/town/config.ts - 0 new issues
  • cloudflare-gastown/src/dos/town/agents.ts - 0 new issues
  • cloudflare-gastown/src/dos/town/beads.ts - 0 new issues
  • cloudflare-gastown/src/dos/town/mail.ts - 0 new issues
  • cloudflare-gastown/src/dos/town/review-queue.ts - 0 new issues
  • cloudflare-gastown/src/dos/town/rigs.ts - 0 new issues

Utilities

  • cloudflare-gastown/src/util/jwt.util.ts - 0 new issues
  • cloudflare-gastown/src/util/secret.util.ts - 0 new issues
  • cloudflare-gastown/src/util/query.util.ts - 0 new issues
  • cloudflare-gastown/src/util/res.util.ts - 0 new issues
  • cloudflare-gastown/src/util/parse-json-body.util.ts - 0 new issues

Container

  • cloudflare-gastown/container/Dockerfile - 0 new issues
  • cloudflare-gastown/container/Dockerfile.dev - 0 new issues
  • cloudflare-gastown/container/src/control-server.ts - 0 new issues
  • cloudflare-gastown/container/src/agent-runner.ts - 0 new issues
  • cloudflare-gastown/container/src/process-manager.ts - 0 new issues
  • cloudflare-gastown/container/src/git-manager.ts - 0 new issues
  • cloudflare-gastown/container/src/main.ts - 0 new issues
  • cloudflare-gastown/container/plugin/client.ts - 0 new issues
  • cloudflare-gastown/container/plugin/tools.ts - 0 new issues

Other files (types, prompts, tables, tests, UI, config) - 0 new issues


Fix these issues in Kilo Cloud

Copy link
Copy Markdown
Contributor

@marius-kilocode marius-kilocode left a comment

Choose a reason for hiding this comment

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

LGTM

@jrf0110 jrf0110 force-pushed the 204-gt-prop-d branch 2 times, most recently from 1f8c996 to 43d6046 Compare February 27, 2026 18:47
@jrf0110 jrf0110 force-pushed the 204-gt-prop-d branch 3 times, most recently from 153a305 to 908395d Compare February 27, 2026 21:11
@jrf0110 jrf0110 force-pushed the 204-gt-prop-d branch 2 times, most recently from aea8ec9 to c275145 Compare February 28, 2026 00:59
@jrf0110 jrf0110 force-pushed the 204-gt-prop-d branch 2 times, most recently from cb10af4 to 43dbbe5 Compare February 28, 2026 01:16
Gastown is an autonomous software engineering platform built on
Cloudflare Workers, Durable Objects, and Containers. This branch
implements the full stack from scratch.
townId,
source_rig_id: params.rigId,
severity: parsed.data.priority ?? 'medium',
message: parsed.data.title,
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: body and metadata from the request are validated by the Zod schema (lines 12-14) but silently dropped here — only title is passed as message. The body field likely contains important context for the escalation that should be preserved.

Additionally, source_agent_id is hardcoded to undefined even though the authenticated agent's ID is available via getEnforcedAgentId(c). This means escalations lose attribution to the agent that created them.

Suggested change
message: parsed.data.title,
message: [parsed.data.title, parsed.data.body].filter(Boolean).join('\n\n'),

);
}
console.log(
`${HANDLER_LOG} handleSlingBead: rigId=${params.rigId} title="${parsed.data.title?.slice(0, 80)}" metadata=${JSON.stringify(parsed.data.metadata)}`
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: JSON.stringify(parsed.data.metadata) logs the full metadata object, which could contain sensitive data (tokens, credentials, PII) depending on what callers include. Consider logging only the metadata keys or a truncated summary.

Suggested change
`${HANDLER_LOG} handleSlingBead: rigId=${params.rigId} title="${parsed.data.title?.slice(0, 80)}" metadata=${JSON.stringify(parsed.data.metadata)}`
`${HANDLER_LOG} handleSlingBead: rigId=${params.rigId} title="${parsed.data.title?.slice(0, 80)}" metadataKeys=${JSON.stringify(Object.keys(parsed.data.metadata ?? {}))}`

@jrf0110 jrf0110 merged commit d470adc into main Feb 28, 2026
12 checks passed
@jrf0110 jrf0110 deleted the 204-gt-prop-d branch February 28, 2026 05:18
jrf0110 added a commit that referenced this pull request Feb 28, 2026
- Add .catch() error logging on fire-and-forget dispatchAgent in slingBead
- Validate SDK session.create response with Zod schema instead of duck-typing
- Add tests verifying registerAgent stores rig_id correctly
- Store town config per-request via Hono context with Zod validation
- Emit notification_failed bead events when escalation mayor notification fails
- Wrap git credential write in try/catch during rig creation for resilience
- Verify /api/gastown/git-credentials route exists (confirmed)
- Return 403 (not 400) for cross-town access attempts via resolveTownId
jrf0110 added a commit that referenced this pull request Mar 1, 2026
## Summary

Addresses all 8 hardening items identified in the PR #544 code review.

Closes #686

## Changes

### 1. Fire-and-forget `dispatchAgent` error logging
- Added `.catch()` with `console.error` on the `void
this.dispatchAgent()` call in `slingBead` so failures are visible in
logs.

### 2. Zod validation for SDK session creation response
- Replaced fragile `sessionResult.data ?? sessionResult` + `'id' in
session` duck-typing with a Zod schema (`z.object({ id:
z.string().min(1) }).passthrough()`).
- Now throws a clear error if the SDK response shape changes
unexpectedly.

### 3. `registerAgent` stores `rig_id` — verified + tested
- Verified the code path: handler passes `{ ...parsed.data, rig_id:
params.rigId }` → `agents.registerAgent` stores `input.rig_id ?? null`
in the beads table `rig_id` column.
- Added two integration tests: one verifying `rig_id` is stored when
provided, one verifying it's `null` when omitted.

### 4. Thread-safe `currentTownConfig` via Hono context
- Added Zod validation (`z.record(z.string(), z.unknown())`) for the
`X-Town-Config` header JSON.
- Typed the Hono app with `ContainerEnv` variables and store config
per-request via `c.set('townConfig', ...)`.
- Renamed module-level variable to `lastKnownTownConfig` to clarify it's
a cache, not the authoritative source.

### 5. Emit bead event on failed escalation notification
- Added `notification_failed` to the `BeadEventType` enum (both
`bead-events.table.ts` and `rig-bead-events.table.ts`).
- Both `routeEscalation` and the re-escalation alarm now emit a
`notification_failed` bead event with metadata (target, reason,
severity) when mayor notification fails.
- Fixed the re-escalation path that was silently swallowing errors with
`.catch(() => {})`.

### 6. Resilient rig creation + git credential write
- Wrapped the `updateTownConfig` git credential write in a try/catch so
a failed credential write doesn't propagate as a rig creation failure.
- Clear error logging with rig ID and integration ID for debugging.
- Container-side `resolveGitCredentialsIfMissing` and
`refreshTownGitCredentials` serve as recovery mechanisms.

### 7. `/api/gastown/git-credentials` route — verified
- Confirmed the route exists at
`src/app/api/gastown/git-credentials/route.ts` with proper auth,
ownership verification, and Zod validation. No changes needed.

### 8. Return 403 for cross-town access attempts
- Introduced `resolveTownId()` in auth middleware returning a
discriminated union: `{ townId }` | `{ error: 'missing', status: 400 }`
| `{ error: 'forbidden', status: 403 }`.
- Updated all 31 handler call sites across 8 handler files to use
`resolveTownId()` and return the correct HTTP status code.
- Kept `getTownId()` as a backward-compatible convenience wrapper.

## Files changed (16)

| File | Change |
|------|--------|
| `cloudflare-gastown/src/dos/Town.do.ts` | Items 1, 5 |
| `cloudflare-gastown/container/src/process-manager.ts` | Item 2 |
| `cloudflare-gastown/container/src/control-server.ts` | Item 4 |
| `cloudflare-gastown/src/db/tables/bead-events.table.ts` | Item 5 |
| `cloudflare-gastown/src/db/tables/rig-bead-events.table.ts` | Item 5 |
| `cloudflare-gastown/src/middleware/auth.middleware.ts` | Item 8 |
| `cloudflare-gastown/src/handlers/rig-*.handler.ts` (8 files) | Item 8
|
| `cloudflare-gastown/test/integration/rig-do.test.ts` | Item 3 |
| `src/routers/gastown-router.ts` | Item 6 |
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants