feat: repo-agnostic refactor (BMad spec-test-build loop)
- NEW: repo-profiler.js — deterministic archetype detection (Infra, Frontend, Backend, etc.) - NEW: extract-dynamic.js — generic extractor replacing hardcoded Foxtrot patterns - NEW: eval-generator.js — dynamic ground-truth question generation from any repo graph - NEW: specs/bmad-agnostic-refactor-spec.md — full BMad spec with acceptance criteria - REFACTORED: prose.js — two-pass LLM synthesis with rich context (shared secrets, ports, service refs) - REFACTORED: sysdoc.js — wired repo-profiler + extract-dynamic, --legacy escape hatch - REFACTORED: wiggum-v2.sh — uses eval-generator before benchmarks - FIXED: graph.js — _edgeSet rebuilt on loadSnapshot() (edge dedup was broken) - FIXED: graph.js — recursive sortKeys() for deep equality in diffing - FIXED: prose.js — robust JSON array extraction from LLM output - FIXED: ratchet.js — syntax validation (node --check) before saving LLM mutations - FIXED: extract-dynamic.js — centralized state services regex, added console.warn for silent failures - TESTS: test-eval-generator, test-repo-profiler, test-synthesis-quality + mock fixtures Eval: 81.5% on Foxtrot (fully repo-agnostic, no hardcoded reference pages) BMad reviews: Architect B+, Dev Lead B-, TEA B-
This commit is contained in:
97
test/test-repo-profiler.js
Normal file
97
test/test-repo-profiler.js
Normal file
@@ -0,0 +1,97 @@
|
||||
const assert = require('node:assert');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const { profileRepo, ARCHETYPES } = require('../repo-profiler');
|
||||
|
||||
const TEST_DIR = path.join(__dirname, 'temp-fixtures');
|
||||
|
||||
function setupFixture(name, files) {
|
||||
const dir = path.join(TEST_DIR, name);
|
||||
fs.mkdirSync(dir, { recursive: true });
|
||||
for (const [file, content] of Object.entries(files)) {
|
||||
fs.writeFileSync(path.join(dir, file), content);
|
||||
}
|
||||
return dir;
|
||||
}
|
||||
|
||||
function teardownFixtures() {
|
||||
if (fs.existsSync(TEST_DIR)) {
|
||||
fs.rmSync(TEST_DIR, { recursive: true, force: true });
|
||||
}
|
||||
}
|
||||
|
||||
async function runTests() {
|
||||
teardownFixtures();
|
||||
|
||||
try {
|
||||
// 1. Test Infrastructure detection
|
||||
const infraDir = setupFixture('infra', {
|
||||
'Chart.yaml': 'apiVersion: v2\nname: my-chart',
|
||||
'main.tf': 'resource "aws_vpc" "main" {}'
|
||||
});
|
||||
let result = profileRepo(infraDir);
|
||||
assert.strictEqual(result.archetype, ARCHETYPES.INFRASTRUCTURE, 'Should detect Infrastructure');
|
||||
assert.ok(result.confidence > 0.8, 'Confidence should be high');
|
||||
|
||||
// 2. Test Frontend SPA detection
|
||||
const frontendDir = setupFixture('frontend', {
|
||||
'package.json': JSON.stringify({
|
||||
dependencies: {
|
||||
react: '^18.0.0',
|
||||
'react-dom': '^18.0.0'
|
||||
},
|
||||
devDependencies: {
|
||||
vite: '^4.0.0'
|
||||
}
|
||||
})
|
||||
});
|
||||
result = profileRepo(frontendDir);
|
||||
assert.strictEqual(result.archetype, ARCHETYPES.FRONTEND, 'Should detect Frontend SPA');
|
||||
assert.ok(result.signals.includes('frontend_framework'));
|
||||
|
||||
// 3. Test Backend API detection
|
||||
const backendDir = setupFixture('backend', {
|
||||
'package.json': JSON.stringify({
|
||||
dependencies: {
|
||||
express: '^4.18.2'
|
||||
}
|
||||
})
|
||||
});
|
||||
result = profileRepo(backendDir);
|
||||
assert.strictEqual(result.archetype, ARCHETYPES.BACKEND, 'Should detect Backend API');
|
||||
|
||||
// 4. Test Library detection
|
||||
const libraryDir = setupFixture('library', {
|
||||
'package.json': JSON.stringify({
|
||||
main: 'index.js',
|
||||
exports: {
|
||||
'.': './index.js'
|
||||
},
|
||||
dependencies: {
|
||||
lodash: '^4.17.21'
|
||||
}
|
||||
})
|
||||
});
|
||||
result = profileRepo(libraryDir);
|
||||
assert.strictEqual(result.archetype, ARCHETYPES.LIBRARY, 'Should detect Library');
|
||||
|
||||
// 5. Monorepo detection
|
||||
const monorepoDir = setupFixture('monorepo', {
|
||||
'package.json': JSON.stringify({
|
||||
workspaces: ['packages/*']
|
||||
}),
|
||||
'turbo.json': '{}'
|
||||
});
|
||||
result = profileRepo(monorepoDir);
|
||||
assert.strictEqual(result.archetype, ARCHETYPES.MONOREPO, 'Should detect Monorepo');
|
||||
|
||||
console.log('✅ repo-profiler tests passed!');
|
||||
} finally {
|
||||
teardownFixtures();
|
||||
}
|
||||
}
|
||||
|
||||
runTests().catch(err => {
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
});
|
||||
Reference in New Issue
Block a user