Overview
The self-repair module provides emergency recovery for common git sync failures, including stuck rebases, merge conflicts, and stale lock files.
Location: src/ops/self_repair.js
Function
repair()
Execute git self-repair operations.
Location: src/ops/self_repair.js:11
Git repository root (defaults to workspace root)
Array of repair actions performed
Repair Operations
1. Abort Pending Rebase
Location: src/ops/self_repair.js:16
try {
execSync('git rebase --abort', { cwd: root, stdio: 'ignore' });
repaired.push('rebase_aborted');
console.log('[SelfRepair] Aborted pending rebase.');
} catch (e) {}
Repair Action: rebase_aborted
2. Abort Pending Merge
Location: src/ops/self_repair.js:23
try {
execSync('git merge --abort', { cwd: root, stdio: 'ignore' });
repaired.push('merge_aborted');
console.log('[SelfRepair] Aborted pending merge.');
} catch (e) {}
Repair Action: merge_aborted
3. Remove Stale Lock Files
Location: src/ops/self_repair.js:30
const LOCK_MAX_AGE_MS = 10 * 60 * 1000; // 10 minutes
const lockFile = path.join(root, '.git', 'index.lock');
if (fs.existsSync(lockFile)) {
try {
const stat = fs.statSync(lockFile);
const age = Date.now() - stat.mtimeMs;
if (age > LOCK_MAX_AGE_MS) {
fs.unlinkSync(lockFile);
repaired.push('stale_lock_removed');
console.log('[SelfRepair] Removed stale index.lock (' + Math.round(age / 60000) + 'min old).');
}
} catch (e) {}
}
Lock File Age Threshold: 10 minutes
Repair Action: stale_lock_removed
4. Hard Reset to Remote (Optional)
Location: src/ops/self_repair.js:45
if (process.env.EVOLVE_GIT_RESET === 'true') {
try {
console.log('[SelfRepair] Resetting local branch to origin/main (HARD reset)...');
execSync('git fetch origin main', { cwd: root, stdio: 'ignore' });
execSync('git reset --hard origin/main', { cwd: root, stdio: 'ignore' });
repaired.push('hard_reset_to_origin');
} catch (e) {
console.warn('[SelfRepair] Hard reset failed: ' + e.message);
}
} else {
// Safe fetch
try {
execSync('git fetch origin', { cwd: root, stdio: 'ignore', timeout: 30000 });
repaired.push('fetch_ok');
} catch (e) {
console.warn('[SelfRepair] git fetch failed: ' + e.message);
}
}
Hard reset is destructive and only enabled when EVOLVE_GIT_RESET=true. Use with caution.
Repair Actions:
hard_reset_to_origin - When EVOLVE_GIT_RESET=true
fetch_ok - Safe fetch (default)
Environment Variables
Enable hard reset to origin/main (destructive operation)
CLI Usage
# Run self-repair
node src/ops/self_repair.js
# With hard reset enabled
EVOLVE_GIT_RESET=true node src/ops/self_repair.js
Example Usage
const { repair } = require('./src/ops/self_repair');
const result = repair();
if (result.length > 0) {
console.log('[SelfRepair] Performed repairs:', result.join(', '));
} else {
console.log('[SelfRepair] Nothing to repair');
}
// Example output:
// ['rebase_aborted', 'stale_lock_removed', 'fetch_ok']
Integration with Git Sync
const { execSync } = require('child_process');
const { repair } = require('./src/ops/self_repair');
function safeGitSync() {
try {
execSync('git pull --rebase origin main', { cwd: repoRoot, stdio: 'inherit' });
console.log('[GitSync] Pull successful');
} catch (e) {
console.error('[GitSync] Pull failed:', e.message);
// Attempt self-repair
console.log('[GitSync] Attempting self-repair...');
const repaired = repair(repoRoot);
if (repaired.length > 0) {
console.log('[GitSync] Repairs performed:', repaired.join(', '));
// Retry after repair
try {
execSync('git pull --rebase origin main', { cwd: repoRoot, stdio: 'inherit' });
console.log('[GitSync] Pull successful after repair');
} catch (e2) {
console.error('[GitSync] Pull failed after repair:', e2.message);
}
} else {
console.error('[GitSync] No repairs available');
}
}
}
safeGitSync();
Automatic Issue Reporting
When self-repair is triggered repeatedly, the issue reporter can automatically file a GitHub issue:
const { repair } = require('./src/ops/self_repair');
const { maybeReportIssue } = require('./gep/issueReporter');
let repairCount = 0;
const MAX_REPAIR_COUNT = 5;
function monitorAndRepair() {
setInterval(() => {
const result = repair();
if (result.length > 0) {
repairCount++;
console.log(`[SelfRepair] Repair #${repairCount}:`, result.join(', '));
if (repairCount >= MAX_REPAIR_COUNT) {
console.warn('[SelfRepair] Excessive repairs detected. Filing issue...');
maybeReportIssue({
signals: ['repeated_self_repair', 'git_sync_unstable'],
recentEvents: [],
sessionLog: `Self-repair triggered ${repairCount} times: ${result.join(', ')}`,
});
repairCount = 0; // Reset counter
}
}
}, 10 * 60 * 1000); // Check every 10 minutes
}
monitorAndRepair();