Vigil: AI-Powered GitHub Repository Intelligence
Why Vigil?
Maintaining healthy repositories at scale is manual, repetitive, and error-prone. Vigil automates the entire audit → fix → verify loop using AI agents that understand your codebase.
Architecture
┌─────────────────────────────────────────────────────────────────┐
│ Vigil Pipeline │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Scan │───▶│ Analyze │───▶│ Fix │───▶│ Verify │ │
│ │ Repo │ │ Issues │ │ Generate│ │ & PR │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
│ │ │ │ │ │
│ ▼ ▼ ▼ ▼ │
│ • Files • Categorize • Generate • Run tests │
│ • Config • Prioritize • Validate • Security scan │
│ • History • Deduplicate • Test • Build check │
│ • Dependencies • Format • Merge when green │
│ │
└─────────────────────────────────────────────────────────────────┘
Audit Categories
1. Documentation Health
// src/audits/docs.ts
export async function auditDocs(repo: RepoContext): Promise<Issue[]> {
const issues: Issue[] = [];
// README completeness
if (!repo.hasFile('README.md')) {
issues.push({ type: 'missing-readme', severity: 'high' });
}
// API docs coverage
const apiCoverage = await calculateAPICoverage(repo);
if (apiCoverage < 0.8) {
issues.push({ type: 'low-api-docs', severity: 'medium', value: apiCoverage });
}
// Stale docs detection
const staleDocs = await findStaleDocs(repo);
issues.push(...staleDocs.map(d => ({ type: 'stale-docs', file: d, severity: 'low' })));
return issues;
}
2. CI/CD Health
// src/audits/ci.ts
export async function auditCI(repo: RepoContext): Promise<Issue[]> {
const issues: Issue[] = [];
const workflows = await repo.getWorkflows();
for (const wf of workflows) {
// Missing security scanning
if (!wf.hasJob('security')) {
issues.push({ type: 'missing-security-scan', workflow: wf.name, severity: 'high' });
}
// No dependency review
if (!wf.hasStep('dependency-review')) {
issues.push({ type: 'missing-dep-review', workflow: wf.name, severity: 'medium' });
}
// Flaky test detection
const flaky = await detectFlakyTests(wf);
if (flaky.length > 0) {
issues.push({ type: 'flaky-tests', tests: flaky, severity: 'medium' });
}
}
return issues;
}
3. Security Posture
// src/audits/security.ts
export async function auditSecurity(repo: RepoContext): Promise<Issue[]> {
const issues: Issue[] = [];
// Secret scanning
const secrets = await scanSecrets(repo);
issues.push(...secrets.map(s => ({ type: 'exposed-secret', ...s, severity: 'critical' })));
// Dependency vulnerabilities
const vulns = await scanDependencies(repo);
issues.push(...vulns.map(v => ({ type: 'vulnerable-dependency', ...v, severity: v.severity })));
// CodeQL / Semgrep findings
const staticFindings = await runStaticAnalysis(repo);
issues.push(...staticFindings.map(f => ({ type: 'static-analysis', ...f })));
return issues;
}
4. Test Coverage & Quality
// src/audits/tests.ts
export async function auditTests(repo: RepoContext): Promise<Issue[]> {
const issues: Issue[] = [];
const coverage = await getCoverage(repo);
if (coverage.lines < 0.8) {
issues.push({ type: 'low-coverage', metric: 'lines', value: coverage.lines, severity: 'medium' });
}
// Missing test types
const hasUnit = await repo.hasTests('unit');
const hasIntegration = await repo.hasTests('integration');
const hasE2E = await repo.hasTests('e2e');
if (!hasUnit) issues.push({ type: 'missing-unit-tests', severity: 'high' });
if (!hasIntegration) issues.push({ type: 'missing-integration-tests', severity: 'medium' });
if (!hasE2E) issues.push({ type: 'missing-e2e-tests', severity: 'low' });
return issues;
}
Automated Fix Generation
Each issue type has a corresponding fix generator:
// src/fixes/generator.ts
export class FixGenerator {
private generators = new Map<IssueType, FixGeneratorFn>([
['missing-readme', generateREADME],
['missing-security-scan', addSecurityWorkflow],
['exposed-secret', rotateSecretAndRemove],
['vulnerable-dependency', updateDependency],
['low-coverage', generateMissingTests],
['stale-docs', updateDocumentation],
// ... 50+ generators
]);
async generateFix(issue: Issue, context: RepoContext): Promise<Fix> {
const generator = this.generators.get(issue.type);
if (!generator) return { type: 'manual', reason: 'No generator available' };
return await generator(issue, context);
}
}
Fix Verification Pipeline
Every generated fix goes through verification before PR creation:
// src/verification/pipeline.ts
export async function verifyFix(fix: Fix, repo: RepoContext): Promise<VerificationResult> {
// 1. Create temporary branch
const branch = await repo.createBranch(`vigil/fix-${fix.id}`);
// 2. Apply fix
await applyFix(branch, fix);
// 3. Run verification checks
const results = await Promise.all([
runTests(branch),
runSecurityScan(branch),
runBuild(branch),
runLint(branch),
runTypeCheck(branch),
]);
// 4. All must pass
const allPass = results.every(r => r.pass);
if (allPass) {
// 5. Create PR with fix
await createPR(branch, fix);
return { verified: true, prUrl: pr.url };
} else {
// 6. Clean up, report failure
await branch.delete();
return { verified: false, failures: results.filter(r => !r.pass) };
}
}
Results
| Metric | Before Vigil | After Vigil | |--------|-------------|-------------| | Avg issues/repo | 47 | 3 | | Time to fix critical | 4 hours | 12 minutes | | Security findings in prod | 12/quarter | 0 | | Test coverage | 62% | 91% | | Stale docs | 34% | 2% |
Key Takeaways
- AI agents can reliably audit entire repo health across 6+ dimensions
- Fix generation + verification eliminates "PR roulette" where fixes break things
- Prioritization by severity + exploitability focuses effort where it matters
- Automated PRs with passing CI mean maintainers just review and merge
- The system learns: fixed patterns become prevention rules for new repos
Code References
Further Reading
Conclusion
Vigil transforms repository maintenance from reactive firefighting to proactive health management. Across 50+ repos, it's caught critical vulnerabilities before deployment, eliminated entire classes of CI failures, and raised our org-wide test coverage from 62% to 91%. The key insight: audit → fix → verify as a single atomic pipeline, not three separate manual steps.
Thanks for reading!
Read More Articles