Skip to content

Stream git hook progress events for stacked git actions#1214

Draft
juliusmarminge wants to merge 6 commits intomainfrom
t3code/show-git-hook-progress
Draft

Stream git hook progress events for stacked git actions#1214
juliusmarminge wants to merge 6 commits intomainfrom
t3code/show-git-hook-progress

Conversation

@juliusmarminge
Copy link
Member

@juliusmarminge juliusmarminge commented Mar 19, 2026

Closes #1194

Summary

  • add end-to-end git action progress reporting for runStackedAction, including action_started, phase transitions, hook lifecycle, hook output, success, and failure events
  • extend git execution layers to support progress callbacks and surface hook start/finish via Git Trace2 during commit execution
  • wire WebSocket handling to generate an actionId and publish gitActionProgress events only to the initiating client
  • update shared contracts/protocol types for git progress events and plumb support through web transport/native API/UI
  • add server, web, and contracts tests covering hook progress ordering, hook failure behavior, and websocket event scoping

Testing

  • apps/server/src/git/Layers/GitManager.test.ts: added tests for ordered commit-hook progress events and action_failed on hook rejection
  • apps/server/src/wsServer.test.ts: added test to verify git action progress is delivered only to the initiating websocket
  • apps/web/src/wsNativeApi.test.ts and apps/web/src/wsTransport.test.ts: added progress-channel handling coverage
  • packages/contracts/src/ws.test.ts: added contract-level ws progress event checks
  • Not run: bun fmt
  • Not run: bun lint
  • Not run: bun typecheck
  • Not run: bun run test

Note

Stream structured git hook progress events for stacked git actions to the UI

  • Adds a git.actionProgress WebSocket push channel that streams structured events (action_started, phase_started, hook_started, hook_output, hook_finished, action_failed, action_finished) back to the initiating client during stacked git actions.
  • Uses Git's trace2 mechanism in GitService to detect hook lifecycle events, and forwards incremental stdout/stderr lines to progress callbacks.
  • GitManager.runStackedAction emits per-phase and per-hook progress events; commit steps have a 10-minute timeout.
  • The GitActionsControl UI component subscribes to progress events and updates the progress toast in real time with phase labels, hook names, and output.
  • WsTransport gains support for timeoutMs: null on requests (used for long-running stacked actions) and now rejects pending requests on socket close.
📊 Macroscope summarized e84f5dc. 17 files reviewed, 2 issues evaluated, 0 issues filtered, 2 comments posted

🗂️ Filtered Issues

- Add hook/output progress callbacks to git execution and commit flow
- Emit ordered git action progress events (start, phases, hooks, finish/fail)
- Publish progress over WebSocket only to the initiating client
- Update shared contracts and tests for the new progress event channel
@juliusmarminge juliusmarminge marked this pull request as draft March 19, 2026 18:16
@github-actions github-actions bot added size:XXL 1,000+ changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. labels Mar 19, 2026
@coderabbitai
Copy link

coderabbitai bot commented Mar 19, 2026

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 7a5520bf-4fae-4fc4-8e64-ac9e55fe90d0

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch t3code/show-git-hook-progress
📝 Coding Plan
  • Generate coding plan for human review comments

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Low

ws.addEventListener("close", () => {
if (this.ws === ws) {
this.ws = null;
}
for (const [id, pending] of this.pending.entries()) {

When the WebSocket closes, pending requests are rejected and removed from this.pending, but this.outboundQueue is not cleared. On reconnect, flushQueue() sends queued messages with id values that no longer exist in this.pending. The server processes these requests and sends responses, but handleMessage() silently drops them because this.pending.get(message.id) returns undefined. For non-idempotent operations, this causes the caller to believe the request failed while the server actually executed it.

     ws.addEventListener("close", () => {
       if (this.ws === ws) {
         this.ws = null;
       }
+      this.outboundQueue.length = 0;
       for (const [id, pending] of this.pending.entries()) {
🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file apps/web/src/wsTransport.ts around lines 191-195:

When the WebSocket closes, pending requests are rejected and removed from `this.pending`, but `this.outboundQueue` is not cleared. On reconnect, `flushQueue()` sends queued messages with `id` values that no longer exist in `this.pending`. The server processes these requests and sends responses, but `handleMessage()` silently drops them because `this.pending.get(message.id)` returns `undefined`. For non-idempotent operations, this causes the caller to believe the request failed while the server actually executed it.

Evidence trail:
apps/web/src/wsTransport.ts lines 173-187 (close handler clears pending but not outboundQueue), line 153 (only dispose() clears outboundQueue), line 166 (open handler calls flushQueue), lines 215-219 (handleMessage silently drops responses for unknown IDs), lines 243-258 (flushQueue sends queued messages)

- Add `actionId` to `GitRunStackedActionInput` and related API calls
- Pass client-generated `actionId` from web UI through WS server to progress events
- Update server/web/contracts tests to assert deterministic progress correlation
- Switch Git trace2 monitoring from polling to filesystem watch
- Parse trace chunks with schema decoding and keep hook progress flowing
- Update test expectations for hook output ordering
- Emit the commit phase_started event only when the hook needs to generate a message
- Keep pre-resolved suggestions from triggering an unnecessary progress update
- Replace the ref indirection with `useEffectEvent`
- Keep push and PR actions wired to the latest toast state
- Remove the extra checkout helper in GitActionsControl
- Keep feature-branch flags with the action calls
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL 1,000+ changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Git commit time-out

1 participant