aios-core
Version:
Synkra AIOS: AI-Orchestrated System for Full Stack Development - Core Framework
148 lines (130 loc) • 4.06 kB
JavaScript
/**
* Git Status Check
*
* Verifies working directory status and uncommitted changes.
*
* @module aios-core/health-check/checks/repository/git-status
* @version 1.0.0
* @story HCS-2 - Health Check System Implementation
*/
const { execSync } = require('child_process');
const { BaseCheck, CheckSeverity, CheckDomain } = require('../../base-check');
/**
* Git status check
*
* @class GitStatusCheck
* @extends BaseCheck
*/
class GitStatusCheck extends BaseCheck {
constructor() {
super({
id: 'repository.git-status',
name: 'Git Status',
description: 'Checks for uncommitted changes and working directory status',
domain: CheckDomain.REPOSITORY,
severity: CheckSeverity.LOW,
timeout: 5000,
cacheable: false, // Status changes frequently
healingTier: 0,
tags: ['git', 'status'],
});
}
/**
* Execute the check
* @param {Object} context - Execution context
* @returns {Promise<Object>} Check result
*/
async execute(context) {
const projectRoot = context.projectRoot || process.cwd();
try {
// Get status
const status = execSync('git status --porcelain', {
cwd: projectRoot,
encoding: 'utf8',
windowsHide: true,
});
const lines = status
.trim()
.split('\n')
.filter((l) => l);
const staged = [];
const modified = [];
const untracked = [];
for (const line of lines) {
const indexStatus = line[0];
const workTreeStatus = line[1];
const file = line.substring(3);
if (indexStatus === '?') {
untracked.push(file);
} else if (indexStatus !== ' ') {
staged.push(file);
}
if (workTreeStatus === 'M' || workTreeStatus === 'D') {
modified.push(file);
}
}
const details = {
staged: staged.length,
modified: modified.length,
untracked: untracked.length,
total: lines.length,
};
// Check if ahead/behind remote
let aheadBehind = { ahead: 0, behind: 0 };
try {
const revList = execSync('git rev-list --left-right --count HEAD...@{u}', {
cwd: projectRoot,
encoding: 'utf8',
windowsHide: true,
}).trim();
const [ahead, behind] = revList.split('\t').map(Number);
aheadBehind = { ahead, behind };
details.ahead = ahead;
details.behind = behind;
} catch {
// No upstream configured
}
// Clean working directory
if (lines.length === 0) {
if (aheadBehind.ahead > 0) {
return this.warning(
`Working directory clean, ${aheadBehind.ahead} commit(s) ahead of remote`,
{
recommendation: 'Consider pushing your commits',
details,
},
);
}
if (aheadBehind.behind > 0) {
return this.warning(
`Working directory clean, ${aheadBehind.behind} commit(s) behind remote`,
{
recommendation: 'Consider pulling latest changes',
details,
},
);
}
return this.pass('Working directory clean and in sync', { details });
}
// Has changes
const parts = [];
if (staged.length > 0) parts.push(`${staged.length} staged`);
if (modified.length > 0) parts.push(`${modified.length} modified`);
if (untracked.length > 0) parts.push(`${untracked.length} untracked`);
return this.warning(`Working directory has changes: ${parts.join(', ')}`, {
recommendation: 'Commit or stash changes before major operations',
details: {
...details,
files: {
staged: staged.slice(0, 5),
modified: modified.slice(0, 5),
untracked: untracked.slice(0, 5),
},
},
});
} catch (error) {
return this.error(`Git status check failed: ${error.message}`, error);
}
}
}
module.exports = GitStatusCheck;