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:
@@ -1,56 +1,52 @@
|
||||
const fs = require('fs');
|
||||
let content = fs.readFileSync('/home/node/.openclaw/workspace/projects/dev-intel-v2/sysdoc.js', 'utf8');
|
||||
|
||||
const oldStr = `const sysArchContent = \`# System Architecture
|
||||
\${archProse}
|
||||
## Summary Statistics
|
||||
- **Subsystems:** \${subs.subsystems.length}
|
||||
- **Helm Charts:** \${helmCharts.length}
|
||||
- **Total Contracts:** \${contractsResult.contracts.length}
|
||||
- **Cross-Cutting Concerns:** \${subs.crossCutting.join(', ') || 'none'}
|
||||
let content = fs.readFileSync('sysdoc.js', 'utf8');
|
||||
|
||||
## Subsystems`;
|
||||
content = content.replace(
|
||||
"const { extractDeep } = require('./extract-deep.js');",
|
||||
"const { extractDeep } = require('./extract-deep.js');\nconst { profileRepo, ARCHETYPES } = require('./repo-profiler.js');\nconst { extractDynamic } = require('./extract-dynamic.js');"
|
||||
);
|
||||
|
||||
const newStr = `const sysArchContent = \`# System Architecture
|
||||
\${archProse}
|
||||
## Summary Statistics
|
||||
- **Subsystems:** \${subs.subsystems.length}
|
||||
- **Helm Charts:** \${helmCharts.length}
|
||||
- **Total Contracts:** \${contractsResult.contracts.length}
|
||||
- **Cross-Cutting Concerns:** \${subs.crossCutting.join(', ') || 'none'}
|
||||
content = content.replace(
|
||||
/const patterns = extractAllPatterns\(srcRoot\);\s*const deepData = extractDeep\(srcRoot\);/,
|
||||
`let patterns = {
|
||||
layers: [],
|
||||
appsets: [],
|
||||
regions: { aws: [], gcp: [], azure: [] },
|
||||
cidrs: [],
|
||||
naming: [],
|
||||
techStack: { containerImages: [] },
|
||||
syncWaves: []
|
||||
};
|
||||
let deepData = { addons: [], scriptParams: [], tfConfigs: [], helmValues: [], stateServices: [] };
|
||||
let archetypeStr = ARCHETYPES ? ARCHETYPES.UNKNOWN : 'Unknown';
|
||||
|
||||
## Platform Architecture Patterns
|
||||
if (opts.legacyMode) {
|
||||
patterns = extractAllPatterns(srcRoot);
|
||||
deepData = extractDeep(srcRoot);
|
||||
if (!archetypeStr || archetypeStr === 'Unknown') archetypeStr = 'Infrastructure';
|
||||
} else {
|
||||
const profile = profileRepo(srcRoot, graph);
|
||||
archetypeStr = profile.archetype;
|
||||
console.log(\`Detected Repo Archetype: \${archetypeStr} (confidence: \${profile.confidence})\`);
|
||||
|
||||
const dynamicData = extractDynamic(graph, archetypeStr, srcRoot);
|
||||
deepData = {
|
||||
addons: [],
|
||||
scriptParams: [],
|
||||
tfConfigs: [],
|
||||
helmValues: [],
|
||||
stateServices: dynamicData.stateServices || [],
|
||||
configs: dynamicData.configs || [],
|
||||
deploymentPatterns: dynamicData.deploymentPatterns || [],
|
||||
networkTopology: dynamicData.networkTopology || []
|
||||
};
|
||||
}`
|
||||
);
|
||||
|
||||
### Layered Architecture
|
||||
The system is organized into the following logical layers (top to bottom):
|
||||
\${patterns.layers.map(l => \`- **\${l.layer}** (\${l.repos.join(', ')})\`).join('\\n')}
|
||||
content = content.replace(
|
||||
/await proseMod\.synthesizeReferencePages\(agentKB, deepData, outDir, \{ confluenceCtx, model: process\.env\.LLM_MODEL \|\| 'claude-haiku-4\.5' \}\);/,
|
||||
"await proseMod.synthesizeReferencePages(agentKB, deepData, outDir, archetypeStr, { confluenceCtx, model: process.env.LLM_MODEL || 'claude-haiku-4.5' });"
|
||||
);
|
||||
|
||||
### Deployment Topology (Hub & Spoke)
|
||||
ArgoCD ApplicationSets define the following ownership model:
|
||||
**Hub (Infrastructure/Control Plane):**
|
||||
\${patterns.appsets.filter(a => a.location === 'hub').map(a => \`- \\\`\${a.name}\\\` manages \\\`\${a.repoName}\\\`\`).join('\\n')}
|
||||
**Spoke (Applications/Runtime):**
|
||||
\${patterns.appsets.filter(a => a.location === 'spoke').map(a => \`- \\\`\${a.name}\\\` manages \\\`\${a.repoName}\\\`\`).join('\\n')}
|
||||
|
||||
### Cloud Regions Supported
|
||||
- **AWS:** \${patterns.regions.aws.join(', ')}
|
||||
- **GCP:** \${patterns.regions.gcp.join(', ')}
|
||||
- **Azure:** \${patterns.regions.azure.join(', ')}
|
||||
|
||||
### Network CIDR Allocations
|
||||
| CIDR Block | Context | File |
|
||||
|---|---|---|
|
||||
\${patterns.cidrs.slice(0, 15).map(c => \`| \\\`\${c.cidr}\\\` | \${c.refs[0].context} | \\\`\${c.refs[0].file}\\\` |\`).join('\\n')}
|
||||
|
||||
### Naming Conventions
|
||||
The following resource naming patterns are enforced:
|
||||
\${patterns.naming.slice(0, 15).map(n => \`- \\\`\${n.pattern}\\\` (via \\\`\${n.file}\\\`)\`).join('\\n')}
|
||||
|
||||
### Tech Stack & Dependencies
|
||||
**Core Images:**
|
||||
\${patterns.techStack.containerImages.slice(0, 20).map(i => \`- \\\`\${i}\\\`\`).join('\\n')}
|
||||
|
||||
## Subsystems`;
|
||||
|
||||
content = content.replace(oldStr, newStr);
|
||||
fs.writeFileSync('/home/node/.openclaw/workspace/projects/dev-intel-v2/sysdoc.js', content);
|
||||
fs.writeFileSync('sysdoc.js', content);
|
||||
|
||||
Reference in New Issue
Block a user