feat(runtime-api): expose git status metadata for Agent View#2862
Conversation
There was a problem hiding this comment.
Hmbown has reached the 50-review limit for trial accounts. To continue receiving code reviews, upgrade your plan.
There was a problem hiding this comment.
Code Review
This pull request adds Git HEAD commit and dirty worktree state metadata to the workspace and thread summaries, updating the relevant API documentation, changelogs, and tests. The review feedback focuses on optimizing performance by reducing the number of spawned Git processes. Specifically, it suggests combining multiple Git queries into a single rev-parse command and avoiding redundant git status checks when collecting workspace status.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| } | ||
| } | ||
|
|
||
| let workspace_git = collect_workspace_git_metadata(&thread.workspace); |
There was a problem hiding this comment.
| let metadata = collect_workspace_git_metadata(workspace); | ||
| status.branch = metadata.branch; | ||
| status.head = metadata.head; | ||
| status.dirty = metadata.dirty; | ||
|
|
||
| if let Some(porcelain) = run_git(workspace, &["status", "--porcelain=v1"]) { |
There was a problem hiding this comment.
To avoid running the expensive git status --porcelain=v1 command twice (once inside collect_workspace_git_metadata and once directly here), pass false to collect_workspace_git_metadata to skip the dirty check, and compute status.dirty directly from the porcelain output.
| let metadata = collect_workspace_git_metadata(workspace); | |
| status.branch = metadata.branch; | |
| status.head = metadata.head; | |
| status.dirty = metadata.dirty; | |
| if let Some(porcelain) = run_git(workspace, &["status", "--porcelain=v1"]) { | |
| let metadata = collect_workspace_git_metadata(workspace, false); | |
| status.branch = metadata.branch; | |
| status.head = metadata.head; | |
| if let Some(porcelain) = run_git(workspace, &["status", "--porcelain=v1"]) { | |
| status.dirty = !porcelain.trim().is_empty(); |
| fn collect_workspace_git_metadata(workspace: &std::path::Path) -> WorkspaceGitMetadata { | ||
| let Some(repo_check) = run_git(workspace, &["rev-parse", "--is-inside-work-tree"]) else { | ||
| return WorkspaceGitMetadata::default(); | ||
| }; | ||
| if repo_check.trim() != "true" { | ||
| return WorkspaceGitMetadata::default(); | ||
| } | ||
|
|
||
| WorkspaceGitMetadata { | ||
| branch: current_git_branch(workspace), | ||
| head: current_git_head(workspace), | ||
| dirty: run_git(workspace, &["status", "--porcelain=v1"]) | ||
| .is_some_and(|porcelain| !porcelain.trim().is_empty()), | ||
| } | ||
| } |
There was a problem hiding this comment.
The current implementation spawns up to 5-6 separate git processes per workspace check (including redundant checks for --is-inside-work-tree and multiple rev-parse calls). This can be optimized to a single rev-parse call that queries the repository status, branch name, and short HEAD hash simultaneously, significantly improving performance.
fn collect_workspace_git_metadata(workspace: &std::path::Path, include_dirty: bool) -> WorkspaceGitMetadata {
let Some(rev_parse) = run_git(workspace, &["rev-parse", "--is-inside-work-tree", "--abbrev-ref", "HEAD", "--short", "HEAD"]) else {
return WorkspaceGitMetadata::default();
};
let mut lines = rev_parse.lines();
let is_repo = lines.next().map(|s| s.trim() == "true").unwrap_or(false);
if !is_repo {
return WorkspaceGitMetadata::default();
}
let branch_raw = lines.next().map(|s| s.trim()).unwrap_or("");
let head_raw = lines.next().map(|s| s.trim()).unwrap_or("");
let branch = if branch_raw.is_empty() {
None
} else if branch_raw == "HEAD" {
(!head_raw.is_empty()).then(|| format!("detached@{head_raw}"))
} else {
Some(branch_raw.to_string())
};
let head = (!head_raw.is_empty()).then(|| head_raw.to_string());
let dirty = include_dirty && run_git(workspace, &["status", "--porcelain=v1"])
.is_some_and(|porcelain| !porcelain.trim().is_empty());
WorkspaceGitMetadata {
branch,
head,
dirty,
}
}
Summary
headanddirtymetadata for editor/Agent View laneshead/dirtyfields to/v1/workspace/statusresponsesStewardship / credit
This is a narrow maintainer slice in the GUI/VS Code lane. It keeps #2808 open as useful design input but does not harvest its mutation endpoints (
retry,undo,patch-undo, or restore-over-HTTP). Thanks @gaord for the GUI runtime API direction in #2808. The existing changelog trail also preserves the broader VS Code/GUI contributors and reporters.Verification
cargo fmt --all -- --checkgit diff --checkcmp -s CHANGELOG.md crates/tui/CHANGELOG.md./scripts/release/check-versions.sh./scripts/release/check-ohos-deps.shcargo test -p codewhale-tui workspace_status_reports_head_and_dirty_counts --lockedcargo test -p codewhale-tui thread_summary_includes_workspace_branch_metadata --lockedcargo test -p codewhale-tui workspace_and_automation_endpoints_work --locked