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:
- User creates a rig with a git URL (e.g.,
https://github.com/user/repo.git)
- Town config should have
git_auth.github_token set (from the user's GitHub integration or manually)
container-dispatch.ts reads townConfig.git_auth.github_token and maps it to envVars.GIT_TOKEN
- Container's
cloneRepo embeds the token in the clone URL: https://x-access-token:<token>@github.com/...
- Container's
configureGitCredentials writes a credential-store file for push operations
- 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
Bug
Polecat agents fail to
git pushbecause 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_tokento the town config.The intended flow:
https://github.com/user/repo.git)git_auth.github_tokenset (from the user's GitHub integration or manually)container-dispatch.tsreadstownConfig.git_auth.github_tokenand maps it toenvVars.GIT_TOKENcloneRepoembeds the token in the clone URL:https://x-access-token:<token>@github.com/...configureGitCredentialswrites a credential-store file for push operationsgit pushuses the credential-store helperWhat actually happens:
createRigmutation sendsgitUrlbut no git tokencreateTownmutation setskilocode_tokenandowner_user_idbut notgit_auth/api/towns/:townId/configPATCH) supportsgit_authbut no UI flow populates it during rig creationgit_auth.github_tokenis alwaysundefined,envVars.GIT_TOKENis never set, clone uses unauthenticated URL (works for public repos), push failsSecondary issues:
startMergeInContainerdoesn't mapGITLAB_INSTANCE_URLto envVars (breaks self-hosted GitLab merges)/tmp/with a unique suffix per agent, but the SDK subprocess (opencode serve) may not inherit the worktree's git config ifprocess.chdirchanges before the subprocess reads itFix Requirements
1. Populate git credentials on rig creation
When a rig is created via
createRigtRPC mutation:platform_integration_id), fetch an installation token from the GitHub API and store it ingit_auth.github_tokengit_auth.gitlab_token2. Token refresh
GitHub installation tokens expire (typically 1 hour). The token needs to be refreshed:
startAgentInContainercall, check if the token is expired and refresh3. Fix startMergeInContainer
Map
GITLAB_INSTANCE_URLin the merge dispatch path (same as the agent dispatch path).4. Verify credential-store propagation to SDK subprocess
The
configureGitCredentialsfunction writes to/tmp/.git-credentials-<suffix>and setscredential.helperin the worktree's git config. Verify that whenopencode servespawns and the agent runsgit push, the git config is found and the credential-store file is readable.Acceptance Criteria
git pushto a GitHub repo after being dispatchedgit pushto a GitLab repo (including self-hosted) after being dispatched/git/merge) can push to both GitHub and GitLab repos