-
Notifications
You must be signed in to change notification settings - Fork 47
🤖 feat: show applied commits in Apply Patch tool #2106
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Ensure Apply Patch tool stories expand the card reliably in test-storybook by targeting the specific tool header and waiting for the expanded state. --- _Generated with `mux` • Model: `openai:gpt-5.2` • Thinking: `xhigh` • Cost: $19.93_ <!-- mux-attribution: model=openai:gpt-5.2 thinking=xhigh costs=19.93 -->
63f7844 to
ede451f
Compare
CI flakes showed the commit subject strings sometimes weren't found with a strict findByText() match. Switch these plays to assert against messageWindow.textContent (substring match) after expansion, which is resilient to text being split across nodes or embedded in a larger text block. Keep the per-assertion timeout under the test-runner per-story timeout. --- _Generated with `mux` • Model: `openai:gpt-5.2` • Thinking: `xhigh` • Cost: $20.58_ <!-- mux-attribution: model=openai:gpt-5.2 thinking=xhigh costs=20.58 -->
github-merge-queue bot
pushed a commit
that referenced
this pull request
Feb 3, 2026
## Summary
Show the exact commits applied (or that would be applied) when using the
`task_apply_git_patch` tool, instead of only showing a commit count +
HEAD SHA.
## Background
The Apply Patch tool UI currently only surfaced a summary count. For
auditing / review it’s helpful to render the per-commit subjects (and
SHAs for real applies) so users can see precisely what changed.
## Implementation
- Tool result schema now returns `appliedCommits: { subject, sha? }[]`
(and drops the redundant `appliedCommitCount`).
- Backend captures `HEAD` before `git am`, then enumerates newly-created
commits via `git log <before>..HEAD`.
- Dry-run: returns subjects only (no SHA).
- Real apply: returns `{sha, subject}` and `headCommitSha`.
- UI renders a new **Commits** section and derives the count from
`appliedCommits.length`.
- Includes a legacy fallback for old history that only has
`appliedCommitCount`.
## Validation
- `make static-check`
## Risks
Low. This is additive UI + tool output plumbing; the git apply behavior
is unchanged. Commit listing is best-effort and falls back safely.
---
<details>
<summary>📋 Implementation Plan</summary>
# Show applied commits in Apply Patch tool UI
## Context / Why
The **Apply Patch** tool UI currently shows:
- the source task ID,
- options (`dry_run`, `three_way`, `force`),
- a summary commit count, and
- the resulting `HEAD` SHA.
For review/auditing it’s useful to show **exactly which commits were (or
would be) applied**. If we always return a commit list, the UI can
derive the count from `appliedCommits.length` (so we can drop the
redundant `appliedCommitCount` field).
## Evidence (repo pointers)
- UI: `src/browser/components/tools/TaskApplyGitPatchToolCall.tsx`
currently renders commit count + `HEAD`, but no commit list.
- Schema: `TaskApplyGitPatchToolResultSchema` in
`src/common/utils/tools/toolDefinitions.ts` currently requires
`appliedCommitCount`.
- Backend: `src/node/services/tools/task_apply_git_patch.ts` runs `git
am` and (for real applies) already reads `HEAD` after success; it can
capture `HEAD` before the apply and run `git log` to enumerate commits.
- Dry-run uses a temp worktree (`git worktree add --detach ... HEAD`);
we can compute the would-apply commit subjects there too.
## Plan (recommended approach)
### 1) Update tool result schema: required `appliedCommits`, remove
`appliedCommitCount`
**File:** `src/common/utils/tools/toolDefinitions.ts`
Define a commit entry where `subject` is always present and `sha` is
optional (so dry-runs can omit unstable SHAs):
```ts
const AppliedCommitSchema = z
.object({
subject: z.string().min(1),
sha: z.string().min(1).optional(),
})
.strict();
export const TaskApplyGitPatchToolResultSchema = z.union([
z
.object({
success: z.literal(true),
taskId: z.string(),
appliedCommits: z.array(AppliedCommitSchema),
headCommitSha: z.string().optional(),
dryRun: z.boolean().optional(),
note: z.string().optional(),
})
.strict(),
z
.object({
success: z.literal(false),
taskId: z.string(),
error: z.string(),
note: z.string().optional(),
})
.strict(),
]);
```
**Net LoC:** ~15–30
### 2) Backend: always populate `appliedCommits`
**File:** `src/node/services/tools/task_apply_git_patch.ts`
Goals:
- Success results always include `appliedCommits`.
- Real applies include `{ sha, subject }`.
- Dry-runs include `{ subject }` only (no sha), since the commit IDs can
differ when applying “for real” later.
- Never fail the tool call solely because commit-listing failed (fall
back to best-effort subjects).
Implementation sketch:
```ts
async function getAppliedCommits(params: {
cwd: string;
beforeHeadSha: string | undefined;
commitCountHint: number | undefined;
includeSha: boolean;
}): Promise<Array<{ sha?: string; subject: string }>> {
// Prefer range-based log when beforeHeadSha is available.
// Fallback to -n <commitCountHint> on HEAD.
// If all else fails, return [].
}
// real apply:
const beforeHeadSha = await tryRevParse("HEAD");
await gitAm(...);
const afterHeadSha = await tryRevParse("HEAD");
const appliedCommits = await getAppliedCommits({
cwd,
beforeHeadSha,
commitCountHint: artifact.commitCount,
includeSha: true,
});
// dry-run apply (inside temp worktree):
const beforeHeadSha = await tryRevParse("HEAD", { cwd: dryRunWorktreePath });
await gitAm(..., { cwd: dryRunWorktreePath });
const appliedCommits = await getAppliedCommits({
cwd: dryRunWorktreePath,
beforeHeadSha,
commitCountHint: artifact.commitCount,
includeSha: false,
});
```
Recommended git command for listing:
- With range:
- `git log --reverse --format=%H%x00%s <before>..HEAD`
- With count fallback:
- `git log -n <count> --reverse --format=%H%x00%s HEAD`
Parsing:
- Split by `\n`, then split each line by `\0`.
- Use `assert` only after checking `exitCode === 0` (delimiter should
always exist in that case).
**Net LoC:** ~60–120
### 3) UI: derive count from `appliedCommits.length` and render the list
**File:** `src/browser/components/tools/TaskApplyGitPatchToolCall.tsx`
Changes:
- Replace all `successResult.appliedCommitCount` usage with
`successResult.appliedCommits.length`.
- Add a “Commits” section that renders subjects, and renders a copyable
SHA only when `sha` exists.
- Be defensive for legacy stored tool outputs:
- If `appliedCommits` is missing (old history), fall back to showing
`appliedCommitCount` if present and omit the list.
**Net LoC:** ~30–60
### 4) Update stories + tests
- Update Storybook mocks:
- `src/browser/stories/mockFactory.ts`
- `src/browser/stories/App.task.stories.tsx`
to populate `appliedCommits` instead of `appliedCommitCount`.
- Add/update a UI test to assert the commits section renders and shows
subjects (and SHA when present).
**Net LoC:** ~40–100
---
<details>
<summary>Alternative: keep <code>appliedCommitCount</code> as
optional</summary>
If you want extra resilience (e.g., if `git log` fails and we only have
subjects), we could keep `appliedCommitCount?: number` as an optional
field.
Pros:
- Lets the UI show an accurate count even if commit listing fails.
Cons:
- Redundant with `appliedCommits.length` when listing succeeds.
</details>
</details>
---
_Generated with `mux` • Model: `openai:gpt-5.2` • Thinking: `xhigh` •
Cost: `$3.43`_
<!-- mux-attribution: model=openai:gpt-5.2 thinking=xhigh costs=3.43 -->
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Summary
Show the exact commits applied (or that would be applied) when using the
task_apply_git_patchtool, instead of only showing a commit count + HEAD SHA.Background
The Apply Patch tool UI currently only surfaced a summary count. For auditing / review it’s helpful to render the per-commit subjects (and SHAs for real applies) so users can see precisely what changed.
Implementation
appliedCommits: { subject, sha? }[](and drops the redundantappliedCommitCount).HEADbeforegit am, then enumerates newly-created commits viagit log <before>..HEAD.{sha, subject}andheadCommitSha.appliedCommits.length.appliedCommitCount.Validation
make static-checkRisks
Low. This is additive UI + tool output plumbing; the git apply behavior is unchanged. Commit listing is best-effort and falls back safely.
📋 Implementation Plan
Show applied commits in Apply Patch tool UI
Context / Why
The Apply Patch tool UI currently shows:
dry_run,three_way,force),HEADSHA.For review/auditing it’s useful to show exactly which commits were (or would be) applied. If we always return a commit list, the UI can derive the count from
appliedCommits.length(so we can drop the redundantappliedCommitCountfield).Evidence (repo pointers)
src/browser/components/tools/TaskApplyGitPatchToolCall.tsxcurrently renders commit count +HEAD, but no commit list.TaskApplyGitPatchToolResultSchemainsrc/common/utils/tools/toolDefinitions.tscurrently requiresappliedCommitCount.src/node/services/tools/task_apply_git_patch.tsrunsgit amand (for real applies) already readsHEADafter success; it can captureHEADbefore the apply and rungit logto enumerate commits.git worktree add --detach ... HEAD); we can compute the would-apply commit subjects there too.Plan (recommended approach)
1) Update tool result schema: required
appliedCommits, removeappliedCommitCountFile:
src/common/utils/tools/toolDefinitions.tsDefine a commit entry where
subjectis always present andshais optional (so dry-runs can omit unstable SHAs):Net LoC: ~15–30
2) Backend: always populate
appliedCommitsFile:
src/node/services/tools/task_apply_git_patch.tsGoals:
appliedCommits.{ sha, subject }.{ subject }only (no sha), since the commit IDs can differ when applying “for real” later.Implementation sketch:
Recommended git command for listing:
git log --reverse --format=%H%x00%s <before>..HEADgit log -n <count> --reverse --format=%H%x00%s HEADParsing:
\n, then split each line by\0.assertonly after checkingexitCode === 0(delimiter should always exist in that case).Net LoC: ~60–120
3) UI: derive count from
appliedCommits.lengthand render the listFile:
src/browser/components/tools/TaskApplyGitPatchToolCall.tsxChanges:
successResult.appliedCommitCountusage withsuccessResult.appliedCommits.length.shaexists.appliedCommitsis missing (old history), fall back to showingappliedCommitCountif present and omit the list.Net LoC: ~30–60
4) Update stories + tests
src/browser/stories/mockFactory.tssrc/browser/stories/App.task.stories.tsxto populate
appliedCommitsinstead ofappliedCommitCount.Net LoC: ~40–100
Alternative: keep
appliedCommitCountas optionalIf you want extra resilience (e.g., if
git logfails and we only have subjects), we could keepappliedCommitCount?: numberas an optional field.Pros:
Cons:
appliedCommits.lengthwhen listing succeeds.Generated with
mux• Model:openai:gpt-5.2• Thinking:xhigh• Cost:$3.43