Skip to content

Fix: Polecat agents cannot push — git credentials never populated in town config #443

@jrf0110

Description

@jrf0110

Bug

Polecat agents fail to git push because git credentials are never set up. The agent clones successfully (using credentials embedded in the clone URL) but subsequent push operations fail with authentication errors.

Parent: #204 / #419

Root Cause

The git credential flow has a gap: no code path ever writes git_auth.github_token to the town config.

The intended flow:

  1. User creates a rig with a git URL (e.g., https://github.com/user/repo.git)
  2. Town config should have git_auth.github_token set (from the user's GitHub integration or manually)
  3. container-dispatch.ts reads townConfig.git_auth.github_token and maps it to envVars.GIT_TOKEN
  4. Container's cloneRepo embeds the token in the clone URL: https://x-access-token:<token>@github.com/...
  5. Container's configureGitCredentials writes a credential-store file for push operations
  6. Agent's git push uses the credential-store helper

What actually happens:

  • Step 2 never occurs. The tRPC createRig mutation sends gitUrl but no git token
  • The tRPC createTown mutation sets kilocode_token and owner_user_id but not git_auth
  • The town config settings page (/api/towns/:townId/config PATCH) supports git_auth but no UI flow populates it during rig creation
  • Result: git_auth.github_token is always undefined, envVars.GIT_TOKEN is never set, clone uses unauthenticated URL (works for public repos), push fails

Secondary issues:

  • startMergeInContainer doesn't map GITLAB_INSTANCE_URL to envVars (breaks self-hosted GitLab merges)
  • The credential-store file is written to /tmp/ with a unique suffix per agent, but the SDK subprocess (opencode serve) may not inherit the worktree's git config if process.chdir changes before the subprocess reads it

Fix Requirements

1. Populate git credentials on rig creation

When a rig is created via createRig tRPC mutation:

  • If the rig uses a GitHub integration (platform_integration_id), fetch an installation token from the GitHub API and store it in git_auth.github_token
  • If the rig uses a GitLab integration, fetch an access token and store it in git_auth.gitlab_token
  • If the rig has no integration (manual git URL), the user must provide credentials via the town config settings page

2. Token refresh

GitHub installation tokens expire (typically 1 hour). The token needs to be refreshed:

  • Before each startAgentInContainer call, check if the token is expired and refresh
  • Or: use a long-lived personal access token / fine-grained token instead of installation tokens
  • Or: configure the container's git credential helper to call back to the worker for fresh tokens on demand

3. Fix startMergeInContainer

Map GITLAB_INSTANCE_URL in the merge dispatch path (same as the agent dispatch path).

4. Verify credential-store propagation to SDK subprocess

The configureGitCredentials function writes to /tmp/.git-credentials-<suffix> and sets credential.helper in the worktree's git config. Verify that when opencode serve spawns and the agent runs git push, the git config is found and the credential-store file is readable.

Acceptance Criteria

  • Polecat agent can git push to a GitHub repo after being dispatched
  • Polecat agent can git push to a GitLab repo (including self-hosted) after being dispatched
  • Deterministic merge (/git/merge) can push to both GitHub and GitLab repos
  • Credentials are refreshed before they expire for long-running agents
  • E2E test: create town → create rig with GitHub repo → sling bead → agent clones, makes changes, pushes successfully

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingkilo-auto-fixAuto-generated label by Kilokilo-triagedAuto-generated label by Kilo

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions