feat(coding-agent): auto-commit infrastructure and git_commit_checkpoint tool#806
feat(coding-agent): auto-commit infrastructure and git_commit_checkpoint tool#806DeprecatedLuke wants to merge 1 commit intocan1357:mainfrom
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e041caf595
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| import type { Settings } from "../config/settings"; | ||
| import { generateCommitMessage } from "../utils/commit-message-generator"; | ||
| import * as git from "../utils/git"; | ||
| import { discoverNestedRepos, getOutermostRepoRoot } from "./worktree"; |
There was a problem hiding this comment.
Export worktree helpers before importing them
dirtyRepos imports discoverNestedRepos and getOutermostRepoRoot from task/worktree, but packages/coding-agent/src/task/worktree.ts does not export either symbol (discoverNestedRepos is file-local and getOutermostRepoRoot is not defined there), so this file cannot type-check/compile when the commit is built.
Useful? React with 👍 / 👎.
| export async function dirtyRepos(cwd: string): Promise<DirtyRepoReport> { | ||
| const root = await getOutermostRepoRoot(cwd); | ||
| const nestedRepos = await discoverNestedRepos(root); | ||
| const allRepos = [root, ...nestedRepos.map(relativePath => path.join(root, relativePath))]; |
There was a problem hiding this comment.
Commit nested repos before the outer repo
Building allRepos with the root first causes commitDirtyRepos to commit the parent repository before embedded nested repositories; in that ordering, git add -A in the parent records the nested repo as an embedded git entry, and when the nested repo is committed afterward the parent becomes dirty again (M nested). That violates the checkpoint contract of leaving repos clean in projects that contain ordinary nested repos.
Useful? React with 👍 / 👎.
…int tool Adds the shared dirty-repo committing pipeline used both by the orchestrator's pre-task auto-commit and by the explicit git_commit_checkpoint tool, and wires the tool into the registry behind the new tools.gitCommitCheckpoint.enabled setting (off by default). - Adds packages/coding-agent/src/task/auto-commit.ts: walks every dirty repo under the session cwd, generates the commit message via the smol model used for isolated task branches, and falls back to wip: <reason> when no model registry is available. Returns per-repo committed/skipped/ failed entries. - Adds packages/coding-agent/src/tools/git-commit-checkpoint.ts: thin tool wrapper that exposes the auto-commit pipeline to the agent. Registered conditionally via createIf — requires top-level depth and the new tools.gitCommitCheckpoint.enabled setting. Throws when every dirty repo's commit fails so the caller sees the failure. - Tests cover model-generated and fallback message paths, partial per-repo failure, and the all-fail throw.
e041caf to
33c55a7
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 33c55a78e8
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| if (!message) { | ||
| throw new Error("Could not generate a commit message."); | ||
| } | ||
| await git.commit(repoPath, message); |
There was a problem hiding this comment.
Pass --no-gpg-sign when creating checkpoint commits
The checkpoint path calls git.commit with default Git behavior, so users with commit.gpgsign=true will attempt a signed commit even though this tool is documented as producing unsigned WIP checkpoints. In environments where signing is configured globally but the agent session lacks an available key/agent, each checkpoint commit fails and the tool cannot perform its primary function.
Useful? React with 👍 / 👎.
| } catch (error) { | ||
| const message = error instanceof Error ? error.message : String(error); | ||
| entries.push({ | ||
| repoPath, | ||
| status: "failed", |
There was a problem hiding this comment.
Roll back staged changes after per-repo commit failures
commitSingleRepo stages the entire repo up front, but the outer catch path only records the error and continues. If commit message generation or git commit fails (for example transient model failure or commit hook/signing failure), the repository is left with all files staged even though the checkpoint reports a failed entry, which mutates user state and can affect later commit/cherry-pick flows.
Useful? React with 👍 / 👎.
What
Introduces a git checkpoint tool which uses the smol model to synchronize repository(-ies) clearing any stashed/uncommited work before moving on, ensures clean audit trail and transcript transparency via scope parameter.
Creates a clean way to revert regressions and stops hours long work from being lost due to agent checking out entire files as a bonus.
Used in task tool (upcoming PR) to create a clean slate for tasks rather than stash/pop as task tool usually indicates a change of scope and pop being unreliable when poping onto dirty tree.
Disabled by default.
Testing
Asking the agent to git checkpoint results in no uncommited changes.
bun checkpasses