auto-claude: 154-fix-task-modal-conflict-check-status-refresh (#1462)

* auto-claude: subtask-1-1 - Add git update-index --refresh before git status

* fix: add git update-index --refresh to release-service.ts

Apply the same stale git index fix to release-service.ts that was
added to worktree-handlers.ts. This prevents false-positive
"uncommitted changes" errors that could incorrectly block releases.

Affected methods:
- runPreflightChecks: prevents blocking releases due to stale index
- isWorktreeMerged: ensures accurate worktree merge detection
- bumpVersion: prevents unnecessary stashing

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* refactor: extract refreshGitIndex utility to eliminate code duplication

Extract the repeated git update-index --refresh pattern into a reusable
utility function in git-isolation.ts. This replaces 4 identical 9-line
blocks across release-service.ts and worktree-handlers.ts with single
function calls.

Changes:
- Add refreshGitIndex() to git-isolation.ts with full documentation
- Update release-service.ts to use refreshGitIndex (3 locations)
- Update worktree-handlers.ts to use refreshGitIndex (1 location)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: use static imports and isolated git env in refreshGitIndex

- Replace dynamic require() with static imports at module level
- Add getIsolatedGitEnv() to prevent git environment contamination
- Remove misleading comment about non-existent circular dependency

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Andy
2026-01-25 11:30:07 +01:00
committed by GitHub
parent d659730751
commit 0299009dfc
3 changed files with 48 additions and 1 deletions
@@ -19,7 +19,7 @@ import {
findTaskWorktree,
} from '../../worktree-paths';
import { persistPlanStatus, updateTaskMetadataPrUrl } from './plan-file-utils';
import { getIsolatedGitEnv } from '../../utils/git-isolation';
import { getIsolatedGitEnv, refreshGitIndex } from '../../utils/git-isolation';
import { killProcessGracefully } from '../../platform';
// Regex pattern for validating git branch names
@@ -2402,6 +2402,8 @@ export function registerWorktreeHandlers(
let uncommittedFiles: string[] = [];
if (isGitWorkTree(project.path)) {
try {
refreshGitIndex(project.path);
const gitStatus = execFileSync(getToolPath('git'), ['status', '--porcelain'], {
cwd: project.path,
encoding: 'utf-8'
@@ -15,6 +15,7 @@ import type {
} from '../shared/types';
import { DEFAULT_CHANGELOG_PATH } from '../shared/constants';
import { getToolPath } from './cli-tool-manager';
import { refreshGitIndex } from './utils/git-isolation';
/**
* Service for creating GitHub releases with worktree-aware pre-flight checks.
@@ -198,6 +199,8 @@ export class ReleaseService extends EventEmitter {
// Check 1: Git working directory is clean
try {
refreshGitIndex(projectPath);
const gitStatus = execFileSync(getToolPath('git'), ['status', '--porcelain'], {
cwd: projectPath,
encoding: 'utf-8'
@@ -445,6 +448,8 @@ export class ReleaseService extends EventEmitter {
// If empty or error checking, assume merged for safety
if (unmergedCommits === 'error') {
refreshGitIndex(worktreePath);
// Try alternative: check if worktree has any uncommitted changes
const hasChanges = execFileSync(getToolPath('git'), ['status', '--porcelain'], {
cwd: worktreePath,
@@ -486,6 +491,8 @@ export class ReleaseService extends EventEmitter {
}
// Check for uncommitted changes
refreshGitIndex(projectPath);
const gitStatus = execFileSync(getToolPath('git'), ['status', '--porcelain'], {
cwd: projectPath,
encoding: 'utf-8'
@@ -13,6 +13,9 @@
* Backend equivalent: apps/backend/core/git_executable.py:get_isolated_git_env()
*/
import { execFileSync } from 'child_process';
import { getToolPath } from '../cli-tool-manager';
/**
* Git environment variables that can cause cross-contamination between worktrees.
*
@@ -105,3 +108,38 @@ export function getIsolatedGitSpawnOptions(
...additionalOptions,
};
}
/**
* Refreshes the git index to ensure accurate status after external commits.
*
* Git caches file stat information in its index. When files are modified
* externally (e.g., by another process or IDE), the cached stat info can
* become stale, causing `git status` to report false positives for
* uncommitted changes.
*
* This function runs `git update-index --refresh` which updates the cached
* stat information to match the actual file system state.
*
* @param cwd - Working directory where the git command should run
*
* @example
* ```typescript
* import { refreshGitIndex } from './git-isolation';
*
* // Call before git status to ensure accurate results
* refreshGitIndex(projectPath);
* const status = execFileSync('git', ['status', '--porcelain'], { cwd: projectPath });
* ```
*/
export function refreshGitIndex(cwd: string): void {
try {
execFileSync(getToolPath('git'), ['update-index', '--refresh'], {
cwd,
encoding: 'utf-8',
stdio: ['pipe', 'pipe', 'pipe'],
env: getIsolatedGitEnv(),
});
} catch {
// Ignore refresh errors - it's a best-effort optimization
}
}