Skip to main content

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
function repair(gitRoot)
gitRoot
string
Git repository root (defaults to workspace root)
repaired
string[]
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

EVOLVE_GIT_RESET
boolean
default:"false"
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();

Build docs developers (and LLMs) love