Strip the inline `git checkout -B` block from the Docker and Sprites
default prepare scripts. The kandev-managed postlude
(KandevBranchCheckoutPostlude) is appended unconditionally after every
user prepare script, so keeping the same logic inline made the default
and the postlude two sources of truth that could drift.
Profiles created in the UI snapshot the *then-current* DefaultPrepareScript
into their stored prepare_script field. Updates to the default — like
shipping the worktree-branch checkout block — never reach those older
profiles, so users keep landing the agent on the chosen base branch
(main) even though the env row carries a feature branch name.
Append a kandev-managed postlude to whatever prepare_script ran (custom
or default), wrapped in a subshell + `|| true` so it's idempotent and
never blocks agentctl from starting. The postlude prefers the remote tip
when origin already has the branch (resume after a destroyed sandbox),
falls back to checking out the existing local branch, and finally
creates one off the current HEAD.
Sprites needed the WorktreeProvider in resolvePrepareScript so the
postlude's `{{worktree.branch}}` actually expands; Docker already had
it.
The Docker e2e gains a regression case that explicitly stores an older
default-style script (clone, no checkout) and asserts the agent still
ends up on the feature branch — locking the contract in regardless of
which default the user happens to have stored.
When a sandbox is destroyed and we provision a fresh one for the same
task, the agent may have previously committed and pushed onto the
feature branch. The previous prepare scripts only ran `git checkout -b
{{worktree.branch}}` which would overwrite that progress with a fresh
branch off the chosen base.
Try `git fetch origin <feature>` first; on success, `git checkout -B`
against the remote tip so the agent picks up where it left off. Falls
back to a fresh local branch when origin has nothing.
Also add the same checkout block to the Sprites prepare script — it was
missing entirely, so every Sprites session was committing onto main.
* feat: add GitHub token injection for remote executors and Docker session resume
- Add global GitHub access token configuration (backend + frontend)
- Inject GitHub token into Docker and Sprites executors via env vars and Git credential helper
- Transition Docker executor from host mounting to repository cloning
- Implement Docker session resume (reconnect to existing containers after backend restart)
- Add shell validation using exec.LookPath in agentctl
- Add scriptengine providers for agent install and agentctl placeholders
* fix: format github-status.tsx with prettier
* fix: resolve lint issues (goconst, errcheck, file-length)
* fix: address code review findings
- Fix resolveGHCLIToken to check both GITHUB_TOKEN and GH_TOKEN guards
- Fix credential helper to use \\ fallback
- Change /bin/bash to /bin/sh in credential helper for Alpine compat
- Strip embedded token from .git/config after clone in prepare scripts
- Extract buildLaunchAgentRequest helpers to stay under 80-line limit
- Add tests for GitHubAuthProvider, injectTokenIntoURL, reconnect validation
- Add GH_TOKEN-only test case for resolveGHCLIToken
* refactor(executor): extract GitHub credential resolution to separate file
Move injectGitHubToken, injectGitHubTokenFromCLI, resolveRemoteCredentials,
resolveAuthSecrets, methodIDToEnvVar, resolveGHCLIToken, and detectGHToken
out of executor_execute.go (was 803 logical lines, over the 800-line limit
after merging main) into a new executor_credentials.go file. Also adds the
nil-guard on secretStore in resolveAuthSecrets that was flagged by review.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
---------
Co-authored-by: Kandev Agent <agent@kandev.dev>
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>