Skip to content

feat(gastown): babysit existing PR feature#3601

Open
jrf0110 wants to merge 12 commits into
gastown-stagingfrom
convoy/babysit-existing-pr-feature-re-staged/254a4b7e/head
Open

feat(gastown): babysit existing PR feature#3601
jrf0110 wants to merge 12 commits into
gastown-stagingfrom
convoy/babysit-existing-pr-feature-re-staged/254a4b7e/head

Conversation

@jrf0110
Copy link
Copy Markdown
Contributor

@jrf0110 jrf0110 commented May 29, 2026

Summary

Adds the "babysit existing PR" feature to Gastown, allowing towns to adopt and manage external PRs (created manually, by other tools, or by third parties). The town polls the PR, addresses review feedback, fixes merge conflicts, and auto-merges — bypassing the refinery code review path since the user is opting into "merge this PR", not "review this PR".

Key changes across 4 chunks:

  • Chunk 0 (Town DO): slingExistingPr and previewPr methods on TownDO — validates PR URL against rig repo, checks PR status via SCM, creates a merge_request bead with gt:babysit label and babysit metadata (head_sha, force_push_allowed)
  • Chunk 1 (tRPC + HTTP): babysitPr and previewPr tRPC mutations + POST /api/mayor/:townId/tools/babysit-pr HTTP handler for mayor tool access
  • Chunk 2 (Mayor tool + force-push gate): gt_babysit_pr mayor tool, force_push_allowed metadata propagated through pr_fixup_context/pr_conflict_context in prime context, polecat prompt updated with force-push policy (default false for babysat PRs = merge-only, no history rewriting)
  • Chunk 3 (SlingDialog + UI): SlingDialog babysit-PR mode, BeadPanel babysit badge and metadata display, eventDescription extracted to module with babysit event types, buildRelatedBeads extracted for testability, ActivityFeed icons/colors for babysit events, Gastown platform filter in sessions UI

Also includes infrastructure improvements:

  • Container env var refactor: Removes setEnvVar/deleteEnvVar from TownContainerDO in favor of passing config through control server request protocol (/sync-config, /refresh-token, /agents/start). Eliminates stale persisted env var issues across DO evictions and container restarts.
  • Mayor cold start optimization: Backgrounds browse worktree setup, logs timing metrics for workspace creation and AGENTS.md writes
  • Boot hydration optimization: Prioritizes mayor resume over non-mayor agents, uses Zod validation for registry entries, defers non-mayor resumes
  • SDK bump: @kilocode/sdk 7.2.14 → 7.3.1, @kilocode/cli 7.2.14 → 7.3.1
  • Container max instances: 500 → 700

Verification

  • Tested babysit PR flow via mayor tool in staging environment
  • Verified babysat PR beads bypass refinery and fast-track to in_progress in reconciler
  • Verified force_push_allowed: false polecats use merge commits (no force-push)
  • Verified PR URL repo validation rejects cross-repo adoption
  • Verified previewPr returns correct metadata for GitHub and GitLab PRs

Visual Changes

  • Babysit badge ("Babysat external PR" with eye icon) on merge_request beads in BeadPanel
  • Babysit metadata section: Head SHA (linked to commit), Force-push status, Babysit started timestamp
  • New event icons/colors in ActivityFeed for babysit-related events
  • "Gastown" platform filter added to Cloud Agent sessions sidebar

Reviewer Notes

  • The slingExistingPr method in TownDO has duplicated PR URL parsing logic with previewPr — this is intentional to keep previewPr as a lightweight read-only path that can fail independently
  • The force_push_allowed gate defaults to true when absent (backwards compat for pre-babysit beads) — only explicit false disables force-push
  • The container env var refactor (removing setEnvVar/deleteEnvVar) is a significant infra change that removes the persisted env var store in favor of always-fresh request-scoped delivery. This eliminates stale-token bugs across DO evictions
  • 173 commits on this branch include many prior staging commits that have already been reviewed/merged separately

jrf0110 and others added 12 commits May 19, 2026 20:32
…rm (#3372)

Bug 1: @kilocode/cli@7.2.14 doesn't read KILO_AUTH_CONTENT, causing all
kilo serve session-ingest to silently no-op. Bumped to 7.3.1 which has the
feature. Verified KILO_AUTH_CONTENT present in binary strings.

Bug 2: buildPrewarmEnv didn't set KILO_AUTH_CONTENT, KILO_PLATFORM, or
KILO_ORG_ID, so mayor sessions (which go through prewarm) were invisible.
Extracted buildKiloAuthEnv helper from buildAgentEnv and used it in both
buildAgentEnv and buildPrewarmEnv.

Refs #3307

Co-authored-by: John Fawcett <john@kilcoode.ai>
* perf(gastown): shorten mayor cold start path

* fix(gastown): address mayor latency review feedback

* fix(gastown): remove stale mayor setup parameter

* fix(gastown): remove stale mayor setup comment
* feat(cloud-agent): add Gastown filter option to ChatSidebar and mobile modal

* fix(cloud-agent-next): remove stale comment in default branch handling

---------

Co-authored-by: John Fawcett <john@kilcoode.ai>
Make worktree creation tolerate an existing local branch with a missing worktree directory, and allow internal @kilocode package updates to bypass release-age delays.
…unk 0) (#3576)

* feat(gastown): Town DO slingExistingPr method (babysit PR feature, chunk 0)

* fix(gastown): address PR review feedback on slingExistingPr

- Remove async from submitExternalPrToReviewQueue (no awaits inside)
- Add GitLab host validation in slingExistingPr URL parsing to prevent
  non-GitLab URLs (e.g. Bitbucket) from matching the GitLab regex
- Replace vacuous state validation tests with meaningful checkPRStatus
  integration tests that exercise the actual status resolution path

---------

Co-authored-by: John Fawcett <john@kilcoode.ai>
Add gastown.babysitPr tRPC mutation, gastown.previewPr tRPC query,
mayor-tools babysit-pr HTTP route, refinery bypass for babysat beads,
and reconciler fast-track extension for babysat MR beads.
feat(web): BeadPanel babysit badge + metadata surfacing (chunk 4)

- Add 'Babysat external PR' badge (cyan) when gt:babysit label present
- Hide source bead link for babysit beads (no source_bead_id)
- Add babysit metadata panel: head_sha (7-char, linked), force_push_allowed (Lock/Unlock icons), babysit_started_at (relative time)
- Add event formatters for babysit_started, pr_feedback_detected, pr_conflict_detected, pr_auto_merge, pr_status_changed
- Mirror babysit badge + metadata in BeadInspectorDashboard
- Extract buildRelatedBeads and eventDescription into separate files for testability
- Add unit tests for eventDescription and buildRelatedBeads babysit logic

Co-authored-by: John Fawcett <john@kilcoode.ai>
…3582)

* feat(gastown): gt_babysit_pr mayor tool + force-push gate (chunk 2)

Add gt_babysit_pr mayor tool registration and client method, update
mayor and polecat system prompts with babysit PR guidance and force-push
policy, surface force_push_allowed in polecat prime context, and add
corresponding unit tests.

* fix(gastown): address PR review warnings on babysit PR feature

- Rewrite PR Conflict Resolution Workflow in polecat-system.prompt.ts
  to choose strategy upfront (rebase vs merge) based on force_push_allowed,
  instead of rebase-then-abort which discarded conflict resolution work.
- Extract resolveForcePushAllowed() from agents.ts prime() so tests
  exercise the actual function instead of inlining the logic.

---------

Co-authored-by: John Fawcett <john@kilcoode.ai>
const convoys = convoysQuery.data ?? [];
const relatedBeads = buildRelatedBeads(bead, allBeads, convoys);
const relatedBeads = buildRelatedBeads(bead, allBeads, convoys).filter(
r => !(r.relation === 'source' && isBabysit)
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.

CRITICAL: isBabysit is used before it is declared — this will throw a ReferenceError at runtime.

The .filter() callback references isBabysit at line 242, but const isBabysit = bead.labels.includes('gt:babysit') is declared ~14 lines later (line 256). In a JavaScript function body, const bindings are in the temporal dead zone until their declaration is evaluated, so this will crash every time BeadPanel renders.

Move the isBabysit declaration above the relatedBeads computation:

Suggested change
r => !(r.relation === 'source' && isBabysit)
r => !(r.relation === 'source' && isBabysit)

The fix is to hoist the declaration:

// Babysit bead detection (must come before relatedBeads filter below)
const isBabysit = bead.labels.includes('gt:babysit');
const relatedBeads = buildRelatedBeads(bead, allBeads, convoys).filter(
  r => !(r.relation === 'source' && isBabysit)
);

value={bead.metadata?.force_push_allowed === true ? 'Allowed' : 'Blocked'}
/>
{typeof bead.metadata?.babysit_started_at === 'string' && (
<MetaCell
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: bead.metadata?.babysit_started_at is displayed here, but babysit_started_at is never written to bead metadata in submitExternalPrToReviewQueue (see services/gastown/src/dos/town/review-queue.ts). The metadata fields written are: source_agent_id, babysit, head_sha, force_push_allowed. This section will never render. Either add babysit_started_at: new Date().toISOString() to the metadata in submitExternalPrToReviewQueue, or remove this dead UI branch.

<span className="text-red-400">Blocked</span>
</>
)}
</dd>
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: bead.metadata.babysit_started_at is rendered here but this field is never written in submitExternalPrToReviewQueue. The section will silently never display. Same issue as in BeadPanel.tsx — add babysit_started_at to the bead metadata at creation time, or remove this block.

@kilo-code-bot
Copy link
Copy Markdown
Contributor

kilo-code-bot Bot commented May 29, 2026

Code Review Summary

Status: 3 Issues Found | Recommendation: Address before merge

Executive Summary

isBabysit is referenced before its const declaration in BeadPanel.tsx, causing a ReferenceError on every render of that component.

Overview

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

CRITICAL

File Line Issue
apps/web/src/components/gastown/drawer-panels/BeadPanel.tsx 242 isBabysit used before const declaration (temporal dead zone → ReferenceError at runtime)

WARNING

File Line Issue
apps/web/src/components/gastown/drawer-panels/BeadPanel.tsx 561 babysit_started_at displayed in UI but never written to bead metadata in submitExternalPrToReviewQueue — section will never render
apps/web/src/app/admin/gastown/towns/[townId]/beads/[beadId]/BeadInspectorDashboard.tsx 297 Same babysit_started_at dead UI branch in the admin inspector
Other Observations (not blocking)
  • services/gastown/test/unit/babysit-pr.test.ts and services/gastown/test/unit/sling-existing-pr.test.ts are nearly identical — they cover the same checkPRStatus, parseGitUrl, and metadata-shape assertions. Consider consolidating to avoid maintaining duplicate test suites.
  • The container env var refactor is a significant infra change. The removal of setEnvVar/deleteEnvVar and the container:envVars persisted store means a container that boots before any /agents/start or /refresh-token arrives will start with no GASTOWN_TOWN_ID or GASTOWN_CONTAINER_TOKEN. The warmUp() now passes townId and an optional containerToken in startOptions.envVars, which covers the normal warm-up path. This looks intentional and the PR notes it, but is worth a careful eye in production to ensure no window exists where a cold-start container is booted without those values.
  • The void setupMayorBrowseWorktrees(request).catch(...) fire-and-forget in runAgent means mayor startup no longer blocks on worktree setup, which is the intended optimization. However, any error is only logged — if the browse worktree fails silently after the .catch(), the mayor will start but tooling that relies on browsing may silently degrade. The existing logging covers this.
Files Reviewed (40 files)
  • apps/mobile/src/components/agents/platform-filter-modal.tsx
  • apps/web/src/app/admin/gastown/towns/[townId]/beads/[beadId]/BeadInspectorDashboard.tsx — 1 issue
  • apps/web/src/components/cloud-agent-next/ChatSidebar.tsx
  • apps/web/src/components/cloud-agent-next/CloudSidebarLayout.tsx
  • apps/web/src/components/gastown/ActivityFeed.test.ts
  • apps/web/src/components/gastown/ActivityFeed.tsx
  • apps/web/src/components/gastown/drawer-panels/BeadPanel.test.ts
  • apps/web/src/components/gastown/drawer-panels/BeadPanel.tsx — 2 issues
  • apps/web/src/components/gastown/drawer-panels/buildRelatedBeads.ts
  • apps/web/src/components/gastown/eventDescription.ts
  • services/gastown/container/Dockerfile
  • services/gastown/container/Dockerfile.dev
  • services/gastown/container/package.json
  • services/gastown/container/plugin/client.test.ts
  • services/gastown/container/plugin/client.ts
  • services/gastown/container/plugin/mayor-tools.test.ts
  • services/gastown/container/plugin/mayor-tools.ts
  • services/gastown/container/plugin/types.ts
  • services/gastown/container/src/agent-runner.test.ts
  • services/gastown/container/src/agent-runner.ts
  • services/gastown/container/src/control-server.ts
  • services/gastown/container/src/git-manager.ts
  • services/gastown/container/src/main.ts
  • services/gastown/container/src/process-manager.test.ts
  • services/gastown/container/src/process-manager.ts
  • services/gastown/src/db/tables/bead-events.table.ts
  • services/gastown/src/dos/Town.do.ts
  • services/gastown/src/dos/TownContainer.do.ts
  • services/gastown/src/dos/town/actions.ts
  • services/gastown/src/dos/town/agents.ts
  • services/gastown/src/dos/town/config.ts
  • services/gastown/src/dos/town/container-dispatch.ts
  • services/gastown/src/dos/town/reconciler.ts
  • services/gastown/src/dos/town/review-queue.ts
  • services/gastown/src/dos/town/town-scm.ts
  • services/gastown/src/gastown.worker.ts
  • services/gastown/src/handlers/mayor-tools.handler.ts
  • services/gastown/src/prompts/mayor-system.prompt.ts
  • services/gastown/src/prompts/polecat-system.prompt.ts
  • services/gastown/src/trpc/router.ts
  • services/gastown/src/trpc/schemas.ts
  • services/gastown/src/types.ts
  • services/gastown/src/util/platform-pr.util.ts
  • services/gastown/test/unit/babysit-pr.test.ts
  • services/gastown/test/unit/sling-existing-pr.test.ts
  • services/gastown/wrangler.jsonc

Fix these issues in Kilo Cloud


Reviewed by claude-sonnet-4.6 · 4,250,533 tokens

Review guidance: REVIEW.md from base branch gastown-staging

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.

1 participant