refactor: one git-run chokepoint owns output disposition #806

Closed
opened 2026-10-19 17:54:41 +00:00 by hexajon · 2 comments
Owner

madtea builds every git child process in one place (internal/gitexec), but the choice of what to do with that process stdout and stderr is spread across five run helpers in internal/git, and each one decides for itself.

The split shows up as a user-visible inconsistency. clone streams git native progress to the terminal, so a large clone shows a progress bar. pull and fetch buffer both streams, so a large pull shows nothing until it finishes and reads as hung.

The five helpers and their choices:

Helper stdout stderr
RunGitAuthDirWithStderr (pull, fetch) buffer buffer
RunGitAuthDirCaptureStderr stream tee (terminal + buffer)
RunGitAuthDirCaptureStderrOnly stream buffer
RunGitAuthDirWithCredentials (clone) stream stream
RunGitDirWithStderr buffer buffer

This is the same shape as ADR 0049 (one hardened HTTP client layer): clients built independently, only one carrying the policy, consolidated into one layer with a guard that fails the build on a bypass. The git runner is the one cross-cutting concern not consolidated yet. Command construction is already central in internal/gitexec per ADR 0038; only output disposition is scattered.

I want one git-run chokepoint that owns output disposition, with an explicit mode per stream (capture, stream, or tee), so a caller states what it wants instead of each helper hard-coding a different answer. A parity guard then fails the build on any git run built outside the chokepoint, the same way the HTTP client guard does. The progress gap between clone and pull becomes one caller choosing stream, not a separate fix.

I am recording the design as an ADR first. This issue is the decision issue for that record.

Acceptance:

  • one chokepoint owns how a git process stdout and stderr are handled;
  • a caller selects the disposition explicitly, and the default preserves todays parsing;
  • clone, pull, and fetch all show git native progress on the CLI, and the MCP surface stays buffered and quiet;
  • a parity guard fails the build when a git run is built outside the chokepoint;
  • the ADR for this lands and is accepted.
madtea builds every git child process in one place (internal/gitexec), but the choice of what to do with that process stdout and stderr is spread across five run helpers in internal/git, and each one decides for itself. The split shows up as a user-visible inconsistency. clone streams git native progress to the terminal, so a large clone shows a progress bar. pull and fetch buffer both streams, so a large pull shows nothing until it finishes and reads as hung. The five helpers and their choices: | Helper | stdout | stderr | |---|---|---| | RunGitAuthDirWithStderr (pull, fetch) | buffer | buffer | | RunGitAuthDirCaptureStderr | stream | tee (terminal + buffer) | | RunGitAuthDirCaptureStderrOnly | stream | buffer | | RunGitAuthDirWithCredentials (clone) | stream | stream | | RunGitDirWithStderr | buffer | buffer | This is the same shape as ADR 0049 (one hardened HTTP client layer): clients built independently, only one carrying the policy, consolidated into one layer with a guard that fails the build on a bypass. The git runner is the one cross-cutting concern not consolidated yet. Command construction is already central in internal/gitexec per ADR 0038; only output disposition is scattered. I want one git-run chokepoint that owns output disposition, with an explicit mode per stream (capture, stream, or tee), so a caller states what it wants instead of each helper hard-coding a different answer. A parity guard then fails the build on any git run built outside the chokepoint, the same way the HTTP client guard does. The progress gap between clone and pull becomes one caller choosing stream, not a separate fix. I am recording the design as an ADR first. This issue is the decision issue for that record. Acceptance: - one chokepoint owns how a git process stdout and stderr are handled; - a caller selects the disposition explicitly, and the default preserves todays parsing; - clone, pull, and fetch all show git native progress on the CLI, and the MCP surface stays buffered and quiet; - a parity guard fails the build when a git run is built outside the chokepoint; - the ADR for this lands and is accepted.
Author
Owner

Reopening. The ADR 0056 PR merge closed this, but the refactor it tracks is not done, so it stays open until the work lands.

I accept the design in ADR 0056. The record is landed as proposed and flips to accepted when the refactor lands and this issue closes.

Reopening. The ADR 0056 PR merge closed this, but the refactor it tracks is not done, so it stays open until the work lands. I accept the design in ADR 0056. The record is landed as proposed and flips to accepted when the refactor lands and this issue closes.
Author
Owner

Closing as the decision issue. The design is accepted and recorded in ADR 0056 (0056-one-git-runner-owns-output-disposition). The refactor that implements it continues in #808, which stays open until the code lands.

Closing as the decision issue. The design is accepted and recorded in ADR 0056 (0056-one-git-runner-owns-output-disposition). The refactor that implements it continues in #808, which stays open until the code lands.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
sixfold-space/madtea#806
No description provided.