feat(chat-workflow): auto-commit + push after natural finish
Summary
Closes the auto-commit gap tracked in #605 (Tier 4 #12). When a chat workflow turn finishes naturally (not `tool-calls`) and the session has both `repo_owner` and `repo_name`, the workflow stages sandbox changes, generates a commit message via the gateway, commits, pushes to the session's branch, and emits a `data-commit` UIMessage chunk so the chat UI can show "Committing..." → "Committed at " live.
End-to-end flow
- `hasAutoCommitChanges` — fast `git status --porcelain` pre-flight (fail-open on errors)
- Emit `data-commit { status: "pending" }` to the SSE stream
- `runAutoCommit` → `performAutoCommit`:
- Set auth URL on origin (`x-access-token:$GITHUB_TOKEN@github.com/...`)
- `git add -A`
- LLM commit message from `git diff --cached` (fallback: `chore: update repository changes`)
- `git commit -m ''`
- `git rev-parse HEAD` + `git symbolic-ref --short HEAD`
- `GIT_TERMINAL_PROMPT=0 git push -u origin `
- Emit `data-commit { status: "success" | "error", url? }`
New files (TDD, 33 tests)
| File | Tests | Purpose |
|---|---|---|
| `lib/chat/auto-commit/performAutoCommit.ts` | 14 | Sandbox.exec orchestration with granular failure modes |
| `lib/chat/auto-commit/hasAutoCommitChanges.ts` | 5 | Fast pre-flight, fail-open on errors |
| `lib/chat/auto-commit/runAutoCommit.ts` | 4 | `"use step"` wrapping performAutoCommit |
| `lib/chat/auto-commit/buildCommitData.ts` | 7 | Pure helper: AutoCommitResult → UI chunk payload |
| `lib/chat/auto-commit/sendCommitChunk.ts` | 3 | `"use step"` writing data-commit chunks to the writable |
Plus 5 new tests on `runAgentWorkflow.test.ts` covering the happy path, no-changes skip, missing repo identifiers, intermediate (`tool-calls`) finish, and the error path.
Suite: 3195 → 3233 passing.
Known limitation (separate follow-up)
The data-commit chunks are emitted live to the SSE stream but are NOT re-persisted onto the assistant message's `parts` column. On page refresh the chunk disappears — but the commit itself is permanent on GitHub (the URL in the chunk resolves). Re-persistence needs either:
- A follow-up `persistAssistantMessage` call with the updated message containing the data-commit part, or
- A new `updateChatMessageParts(id, parts)` helper since the current `upsertChatMessage` ignores duplicates.
This will be filed as a separate issue.
Test plan
- 38 new unit tests pass
- Full suite (3233/3233)
- Lint / format / tsc clean
- Preview E2E: trigger a chat that modifies files in the sandbox (e.g., "create a test.md file with hello world"), confirm:
- `data-commit { status: "pending" }` chunk in the SSE stream
- `data-commit { status: "success", url }` chunk follows
- New commit appears on GitHub at the URL in the chunk
🤖 Generated with Claude Code
Summary by cubic
Adds auto-commit and push after a natural chat finish, with live data-commit updates that persist on the assistant message so the Git card survives refresh. Repo owner/name are parsed from session.clone_url to prevent silent skips (Linear #605).
-
New Features
- Runs only on natural finishes when
repoOwner,repoName, and a sandbox exist; skips if no changes. - Emits
data-commitchunks:{ status: "pending" }then{ status: "success" | "error", commitSha?, url? }; persists the resolved part to the message. - Commit pipeline:
git add -A→ LLM message fromgit diff --cached(fallback “chore: update repository changes”) →git commit→ SHA + branch →GIT_TERMINAL_PROMPT=0 git push -u origin <branch>; setsorigintox-access-token:$GITHUB_TOKENwhen available. runAgentWorkflowforwardssessionTitle,repoOwner,repoName, and a wrappedSandboxState; orchestration lives inautoCommitChatTurn.
- Runs only on natural finishes when
-
Refactors
- Extracted
generateCommitMessage,autoCommitChatTurn, and helpers;runAgentWorkflownow delegates via{ ...input, ...result }. generateCommitMessagenow usesopenai/gpt-5.4-nanoand trims to 72 chars.- Moved the step boundary out of Supabase:
updateChatMessageis pure;persistAssistantDataPartmerges the part and writes the whole message so resolveddata-commitpersists across refresh. - Added
parseGitHubRepoIdentifiersand expanded tests across auto-commit, persistence helpers, and Supabase update.
- Extracted