musubi-sdd 5.1.0 → 5.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.ja.md +106 -48
- package/README.md +110 -32
- package/bin/musubi-analyze.js +74 -67
- package/bin/musubi-browser.js +27 -26
- package/bin/musubi-change.js +48 -47
- package/bin/musubi-checkpoint.js +10 -7
- package/bin/musubi-convert.js +25 -25
- package/bin/musubi-costs.js +27 -10
- package/bin/musubi-gui.js +52 -46
- package/bin/musubi-init.js +1952 -10
- package/bin/musubi-orchestrate.js +327 -239
- package/bin/musubi-remember.js +69 -56
- package/bin/musubi-resolve.js +53 -45
- package/bin/musubi-trace.js +51 -22
- package/bin/musubi-validate.js +39 -30
- package/bin/musubi-workflow.js +33 -34
- package/bin/musubi.js +39 -2
- package/package.json +1 -1
- package/src/agents/agent-loop.js +94 -95
- package/src/agents/agentic/code-generator.js +119 -109
- package/src/agents/agentic/code-reviewer.js +105 -108
- package/src/agents/agentic/index.js +4 -4
- package/src/agents/browser/action-executor.js +13 -13
- package/src/agents/browser/ai-comparator.js +11 -10
- package/src/agents/browser/context-manager.js +6 -6
- package/src/agents/browser/index.js +5 -5
- package/src/agents/browser/nl-parser.js +31 -46
- package/src/agents/browser/screenshot.js +2 -2
- package/src/agents/browser/test-generator.js +6 -4
- package/src/agents/function-tool.js +71 -65
- package/src/agents/index.js +7 -7
- package/src/agents/schema-generator.js +98 -94
- package/src/analyzers/ast-extractor.js +158 -146
- package/src/analyzers/codegraph-auto-update.js +858 -0
- package/src/analyzers/complexity-analyzer.js +536 -0
- package/src/analyzers/context-optimizer.js +241 -126
- package/src/analyzers/impact-analyzer.js +1 -1
- package/src/analyzers/large-project-analyzer.js +766 -0
- package/src/analyzers/repository-map.js +77 -81
- package/src/analyzers/security-analyzer.js +19 -11
- package/src/analyzers/stuck-detector.js +19 -17
- package/src/converters/index.js +78 -57
- package/src/converters/ir/types.js +12 -12
- package/src/converters/parsers/musubi-parser.js +134 -126
- package/src/converters/parsers/openapi-parser.js +70 -53
- package/src/converters/parsers/speckit-parser.js +239 -175
- package/src/converters/writers/musubi-writer.js +123 -118
- package/src/converters/writers/speckit-writer.js +124 -113
- package/src/generators/rust-migration-generator.js +512 -0
- package/src/gui/public/index.html +1365 -1211
- package/src/gui/server.js +41 -40
- package/src/gui/services/file-watcher.js +23 -8
- package/src/gui/services/project-scanner.js +26 -20
- package/src/gui/services/replanning-service.js +27 -23
- package/src/gui/services/traceability-service.js +8 -8
- package/src/gui/services/workflow-service.js +14 -7
- package/src/index.js +151 -0
- package/src/integrations/cicd.js +90 -104
- package/src/integrations/codegraph-mcp.js +643 -0
- package/src/integrations/documentation.js +142 -103
- package/src/integrations/examples.js +95 -80
- package/src/integrations/github-client.js +17 -17
- package/src/integrations/index.js +5 -5
- package/src/integrations/mcp/index.js +21 -21
- package/src/integrations/mcp/mcp-context-provider.js +76 -78
- package/src/integrations/mcp/mcp-discovery.js +74 -72
- package/src/integrations/mcp/mcp-tool-registry.js +99 -94
- package/src/integrations/mcp-connector.js +70 -66
- package/src/integrations/platforms.js +50 -49
- package/src/integrations/tool-discovery.js +37 -31
- package/src/llm-providers/anthropic-provider.js +11 -11
- package/src/llm-providers/base-provider.js +16 -18
- package/src/llm-providers/copilot-provider.js +22 -19
- package/src/llm-providers/index.js +26 -25
- package/src/llm-providers/ollama-provider.js +11 -11
- package/src/llm-providers/openai-provider.js +12 -12
- package/src/managers/agent-memory.js +36 -24
- package/src/managers/checkpoint-manager.js +4 -8
- package/src/managers/delta-spec.js +19 -19
- package/src/managers/index.js +13 -4
- package/src/managers/memory-condenser.js +35 -45
- package/src/managers/repo-skill-manager.js +57 -31
- package/src/managers/skill-loader.js +25 -22
- package/src/managers/skill-tools.js +36 -72
- package/src/managers/workflow.js +30 -22
- package/src/monitoring/cost-tracker.js +48 -46
- package/src/monitoring/incident-manager.js +116 -106
- package/src/monitoring/index.js +144 -134
- package/src/monitoring/observability.js +75 -62
- package/src/monitoring/quality-dashboard.js +45 -41
- package/src/monitoring/release-manager.js +63 -53
- package/src/orchestration/agent-skill-binding.js +39 -47
- package/src/orchestration/error-handler.js +65 -107
- package/src/orchestration/guardrails/base-guardrail.js +26 -24
- package/src/orchestration/guardrails/guardrail-rules.js +50 -64
- package/src/orchestration/guardrails/index.js +5 -5
- package/src/orchestration/guardrails/input-guardrail.js +58 -45
- package/src/orchestration/guardrails/output-guardrail.js +104 -81
- package/src/orchestration/guardrails/safety-check.js +79 -79
- package/src/orchestration/index.js +38 -55
- package/src/orchestration/mcp-tool-adapters.js +96 -99
- package/src/orchestration/orchestration-engine.js +21 -21
- package/src/orchestration/pattern-registry.js +60 -45
- package/src/orchestration/patterns/auto.js +34 -47
- package/src/orchestration/patterns/group-chat.js +59 -65
- package/src/orchestration/patterns/handoff.js +67 -65
- package/src/orchestration/patterns/human-in-loop.js +51 -72
- package/src/orchestration/patterns/nested.js +25 -40
- package/src/orchestration/patterns/sequential.js +35 -34
- package/src/orchestration/patterns/swarm.js +63 -56
- package/src/orchestration/patterns/triage.js +150 -109
- package/src/orchestration/reasoning/index.js +9 -9
- package/src/orchestration/reasoning/planning-engine.js +143 -140
- package/src/orchestration/reasoning/reasoning-engine.js +206 -144
- package/src/orchestration/reasoning/self-correction.js +121 -128
- package/src/orchestration/replanning/adaptive-goal-modifier.js +107 -112
- package/src/orchestration/replanning/alternative-generator.js +37 -42
- package/src/orchestration/replanning/config.js +63 -59
- package/src/orchestration/replanning/goal-progress-tracker.js +98 -100
- package/src/orchestration/replanning/index.js +24 -20
- package/src/orchestration/replanning/plan-evaluator.js +49 -50
- package/src/orchestration/replanning/plan-monitor.js +32 -28
- package/src/orchestration/replanning/proactive-path-optimizer.js +175 -178
- package/src/orchestration/replanning/replan-history.js +33 -26
- package/src/orchestration/replanning/replanning-engine.js +106 -108
- package/src/orchestration/skill-executor.js +107 -109
- package/src/orchestration/skill-registry.js +85 -89
- package/src/orchestration/workflow-examples.js +228 -231
- package/src/orchestration/workflow-executor.js +65 -68
- package/src/orchestration/workflow-orchestrator.js +72 -73
- package/src/phase4-integration.js +47 -40
- package/src/phase5-integration.js +89 -30
- package/src/reporters/coverage-report.js +82 -30
- package/src/reporters/hierarchical-reporter.js +498 -0
- package/src/reporters/traceability-matrix-report.js +29 -20
- package/src/resolvers/issue-resolver.js +43 -31
- package/src/steering/advanced-validation.js +133 -124
- package/src/steering/auto-updater.js +60 -73
- package/src/steering/index.js +6 -6
- package/src/steering/quality-metrics.js +41 -35
- package/src/steering/steering-auto-update.js +83 -86
- package/src/steering/steering-validator.js +98 -106
- package/src/steering/template-constraints.js +53 -54
- package/src/templates/agents/claude-code/CLAUDE.md +32 -32
- package/src/templates/agents/claude-code/skills/agent-assistant/SKILL.md +13 -5
- package/src/templates/agents/claude-code/skills/ai-ml-engineer/mlops-guide.md +23 -23
- package/src/templates/agents/claude-code/skills/ai-ml-engineer/model-card-template.md +60 -41
- package/src/templates/agents/claude-code/skills/api-designer/api-patterns.md +27 -19
- package/src/templates/agents/claude-code/skills/api-designer/openapi-template.md +11 -7
- package/src/templates/agents/claude-code/skills/bug-hunter/SKILL.md +4 -3
- package/src/templates/agents/claude-code/skills/bug-hunter/root-cause-analysis.md +37 -15
- package/src/templates/agents/claude-code/skills/change-impact-analyzer/dependency-graph-patterns.md +36 -42
- package/src/templates/agents/claude-code/skills/change-impact-analyzer/impact-analysis-template.md +69 -60
- package/src/templates/agents/claude-code/skills/cloud-architect/aws-patterns.md +31 -38
- package/src/templates/agents/claude-code/skills/cloud-architect/azure-patterns.md +28 -23
- package/src/templates/agents/claude-code/skills/code-reviewer/SKILL.md +61 -0
- package/src/templates/agents/claude-code/skills/code-reviewer/best-practices.md +27 -0
- package/src/templates/agents/claude-code/skills/code-reviewer/review-checklist.md +29 -10
- package/src/templates/agents/claude-code/skills/code-reviewer/review-standards.md +29 -24
- package/src/templates/agents/claude-code/skills/constitution-enforcer/SKILL.md +8 -6
- package/src/templates/agents/claude-code/skills/constitution-enforcer/constitutional-articles.md +62 -26
- package/src/templates/agents/claude-code/skills/constitution-enforcer/phase-minus-one-gates.md +35 -16
- package/src/templates/agents/claude-code/skills/database-administrator/backup-recovery.md +27 -17
- package/src/templates/agents/claude-code/skills/database-administrator/tuning-guide.md +25 -20
- package/src/templates/agents/claude-code/skills/database-schema-designer/schema-patterns.md +39 -22
- package/src/templates/agents/claude-code/skills/devops-engineer/ci-cd-templates.md +25 -22
- package/src/templates/agents/claude-code/skills/issue-resolver/SKILL.md +24 -21
- package/src/templates/agents/claude-code/skills/orchestrator/SKILL.md +148 -63
- package/src/templates/agents/claude-code/skills/orchestrator/patterns.md +35 -16
- package/src/templates/agents/claude-code/skills/orchestrator/selection-matrix.md +69 -64
- package/src/templates/agents/claude-code/skills/performance-engineer/optimization-playbook.md +47 -47
- package/src/templates/agents/claude-code/skills/performance-optimizer/SKILL.md +69 -0
- package/src/templates/agents/claude-code/skills/performance-optimizer/benchmark-template.md +63 -45
- package/src/templates/agents/claude-code/skills/performance-optimizer/optimization-patterns.md +33 -35
- package/src/templates/agents/claude-code/skills/project-manager/SKILL.md +7 -6
- package/src/templates/agents/claude-code/skills/project-manager/agile-ceremonies.md +47 -28
- package/src/templates/agents/claude-code/skills/project-manager/project-templates.md +94 -78
- package/src/templates/agents/claude-code/skills/quality-assurance/SKILL.md +20 -17
- package/src/templates/agents/claude-code/skills/quality-assurance/qa-plan-template.md +63 -49
- package/src/templates/agents/claude-code/skills/release-coordinator/SKILL.md +5 -5
- package/src/templates/agents/claude-code/skills/release-coordinator/feature-flag-guide.md +30 -26
- package/src/templates/agents/claude-code/skills/release-coordinator/release-plan-template.md +67 -35
- package/src/templates/agents/claude-code/skills/requirements-analyst/ears-format.md +54 -42
- package/src/templates/agents/claude-code/skills/requirements-analyst/validation-rules.md +36 -33
- package/src/templates/agents/claude-code/skills/security-auditor/SKILL.md +77 -19
- package/src/templates/agents/claude-code/skills/security-auditor/audit-checklists.md +24 -24
- package/src/templates/agents/claude-code/skills/security-auditor/owasp-top-10.md +61 -20
- package/src/templates/agents/claude-code/skills/security-auditor/vulnerability-patterns.md +43 -11
- package/src/templates/agents/claude-code/skills/site-reliability-engineer/SKILL.md +1 -0
- package/src/templates/agents/claude-code/skills/site-reliability-engineer/incident-response-template.md +55 -25
- package/src/templates/agents/claude-code/skills/site-reliability-engineer/observability-patterns.md +78 -68
- package/src/templates/agents/claude-code/skills/site-reliability-engineer/slo-sli-guide.md +73 -53
- package/src/templates/agents/claude-code/skills/software-developer/solid-principles.md +83 -37
- package/src/templates/agents/claude-code/skills/software-developer/test-first-workflow.md +38 -31
- package/src/templates/agents/claude-code/skills/steering/SKILL.md +1 -0
- package/src/templates/agents/claude-code/skills/steering/auto-update-rules.md +31 -0
- package/src/templates/agents/claude-code/skills/system-architect/adr-template.md +25 -7
- package/src/templates/agents/claude-code/skills/system-architect/c4-model-guide.md +74 -61
- package/src/templates/agents/claude-code/skills/technical-writer/doc-templates/documentation-templates.md +70 -52
- package/src/templates/agents/claude-code/skills/test-engineer/SKILL.md +2 -0
- package/src/templates/agents/claude-code/skills/test-engineer/ears-test-mapping.md +75 -71
- package/src/templates/agents/claude-code/skills/test-engineer/test-types.md +85 -63
- package/src/templates/agents/claude-code/skills/traceability-auditor/coverage-matrix-template.md +39 -36
- package/src/templates/agents/claude-code/skills/traceability-auditor/gap-detection-rules.md +22 -17
- package/src/templates/agents/claude-code/skills/ui-ux-designer/SKILL.md +1 -0
- package/src/templates/agents/claude-code/skills/ui-ux-designer/accessibility-guidelines.md +49 -75
- package/src/templates/agents/claude-code/skills/ui-ux-designer/design-system-components.md +71 -59
- package/src/templates/agents/codex/AGENTS.md +74 -42
- package/src/templates/agents/cursor/AGENTS.md +74 -42
- package/src/templates/agents/gemini-cli/GEMINI.md +74 -42
- package/src/templates/agents/github-copilot/AGENTS.md +83 -51
- package/src/templates/agents/qwen-code/QWEN.md +74 -42
- package/src/templates/agents/windsurf/AGENTS.md +74 -42
- package/src/templates/architectures/README.md +41 -0
- package/src/templates/architectures/clean-architecture/README.md +113 -0
- package/src/templates/architectures/event-driven/README.md +162 -0
- package/src/templates/architectures/hexagonal/README.md +130 -0
- package/src/templates/index.js +6 -1
- package/src/templates/locale-manager.js +16 -16
- package/src/templates/shared/delta-spec-template.md +20 -13
- package/src/templates/shared/github-actions/musubi-issue-resolver.yml +5 -5
- package/src/templates/shared/github-actions/musubi-security-check.yml +3 -3
- package/src/templates/shared/github-actions/musubi-validate.yml +4 -4
- package/src/templates/shared/steering/structure.md +95 -0
- package/src/templates/skills/browser-agent.md +21 -16
- package/src/templates/skills/web-gui.md +8 -0
- package/src/templates/template-constraints.js +50 -53
- package/src/validators/advanced-validation.js +30 -36
- package/src/validators/constitutional-validator.js +77 -73
- package/src/validators/critic-system.js +49 -59
- package/src/validators/delta-format.js +59 -55
- package/src/validators/traceability-validator.js +7 -11
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* MUSUBI Writer
|
|
3
|
-
*
|
|
3
|
+
*
|
|
4
4
|
* Writes Intermediate Representation (IR) to MUSUBI project structure
|
|
5
5
|
*/
|
|
6
6
|
|
|
@@ -21,7 +21,7 @@ async function writeMusubiProject(ir, outputPath, options = {}) {
|
|
|
21
21
|
const { dryRun = false, force = false, preserveRaw = false, verbose = false } = options;
|
|
22
22
|
const warnings = [];
|
|
23
23
|
let filesWritten = 0;
|
|
24
|
-
|
|
24
|
+
|
|
25
25
|
// Create base directories
|
|
26
26
|
const dirs = [
|
|
27
27
|
path.join(outputPath, 'steering'),
|
|
@@ -30,13 +30,13 @@ async function writeMusubiProject(ir, outputPath, options = {}) {
|
|
|
30
30
|
path.join(outputPath, 'steering', 'memories'),
|
|
31
31
|
path.join(outputPath, 'storage', 'specs'),
|
|
32
32
|
];
|
|
33
|
-
|
|
33
|
+
|
|
34
34
|
if (!dryRun) {
|
|
35
35
|
for (const dir of dirs) {
|
|
36
36
|
await fs.ensureDir(dir);
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
|
-
|
|
39
|
+
|
|
40
40
|
// Write project.yml
|
|
41
41
|
const projectYmlPath = path.join(outputPath, 'steering', 'project.yml');
|
|
42
42
|
const projectYml = generateProjectYml(ir);
|
|
@@ -45,7 +45,7 @@ async function writeMusubiProject(ir, outputPath, options = {}) {
|
|
|
45
45
|
filesWritten++;
|
|
46
46
|
}
|
|
47
47
|
if (verbose) console.log(` Writing: ${projectYmlPath}`);
|
|
48
|
-
|
|
48
|
+
|
|
49
49
|
// Write constitution
|
|
50
50
|
const constitutionPath = path.join(outputPath, 'steering', 'rules', 'constitution.md');
|
|
51
51
|
const constitution = generateConstitution(ir.constitution, preserveRaw);
|
|
@@ -54,7 +54,7 @@ async function writeMusubiProject(ir, outputPath, options = {}) {
|
|
|
54
54
|
filesWritten++;
|
|
55
55
|
}
|
|
56
56
|
if (verbose) console.log(` Writing: ${constitutionPath}`);
|
|
57
|
-
|
|
57
|
+
|
|
58
58
|
// Write product.md
|
|
59
59
|
const productPath = path.join(outputPath, 'steering', 'product.md');
|
|
60
60
|
const product = generateProduct(ir);
|
|
@@ -63,7 +63,7 @@ async function writeMusubiProject(ir, outputPath, options = {}) {
|
|
|
63
63
|
filesWritten++;
|
|
64
64
|
}
|
|
65
65
|
if (verbose) console.log(` Writing: ${productPath}`);
|
|
66
|
-
|
|
66
|
+
|
|
67
67
|
// Write structure.md
|
|
68
68
|
const structurePath = path.join(outputPath, 'steering', 'structure.md');
|
|
69
69
|
const structure = generateStructure(ir);
|
|
@@ -72,7 +72,7 @@ async function writeMusubiProject(ir, outputPath, options = {}) {
|
|
|
72
72
|
filesWritten++;
|
|
73
73
|
}
|
|
74
74
|
if (verbose) console.log(` Writing: ${structurePath}`);
|
|
75
|
-
|
|
75
|
+
|
|
76
76
|
// Write tech.md
|
|
77
77
|
const techPath = path.join(outputPath, 'steering', 'tech.md');
|
|
78
78
|
const tech = generateTech(ir);
|
|
@@ -81,15 +81,20 @@ async function writeMusubiProject(ir, outputPath, options = {}) {
|
|
|
81
81
|
filesWritten++;
|
|
82
82
|
}
|
|
83
83
|
if (verbose) console.log(` Writing: ${techPath}`);
|
|
84
|
-
|
|
84
|
+
|
|
85
85
|
// Write features
|
|
86
86
|
for (const feature of ir.features) {
|
|
87
87
|
const featurePath = path.join(outputPath, 'storage', 'specs', feature.id);
|
|
88
|
-
const result = await writeFeature(feature, featurePath, {
|
|
88
|
+
const result = await writeFeature(feature, featurePath, {
|
|
89
|
+
dryRun,
|
|
90
|
+
force,
|
|
91
|
+
preserveRaw,
|
|
92
|
+
verbose,
|
|
93
|
+
});
|
|
89
94
|
filesWritten += result.filesWritten;
|
|
90
95
|
warnings.push(...result.warnings);
|
|
91
96
|
}
|
|
92
|
-
|
|
97
|
+
|
|
93
98
|
// Write templates
|
|
94
99
|
for (const template of ir.templates) {
|
|
95
100
|
const templatePath = path.join(outputPath, 'steering', 'templates', `${template.name}.md`);
|
|
@@ -99,7 +104,7 @@ async function writeMusubiProject(ir, outputPath, options = {}) {
|
|
|
99
104
|
}
|
|
100
105
|
if (verbose) console.log(` Writing: ${templatePath}`);
|
|
101
106
|
}
|
|
102
|
-
|
|
107
|
+
|
|
103
108
|
// Write memories
|
|
104
109
|
for (const memory of ir.memories) {
|
|
105
110
|
const memoryPath = path.join(outputPath, 'steering', 'memories', `${memory.category}.md`);
|
|
@@ -110,18 +115,18 @@ async function writeMusubiProject(ir, outputPath, options = {}) {
|
|
|
110
115
|
}
|
|
111
116
|
if (verbose) console.log(` Writing: ${memoryPath}`);
|
|
112
117
|
}
|
|
113
|
-
|
|
118
|
+
|
|
114
119
|
return { filesWritten, warnings };
|
|
115
120
|
}
|
|
116
121
|
|
|
117
122
|
/**
|
|
118
123
|
* Write file with optional force overwrite
|
|
119
|
-
* @param {string} filePath
|
|
120
|
-
* @param {string} content
|
|
121
|
-
* @param {boolean} force
|
|
124
|
+
* @param {string} filePath
|
|
125
|
+
* @param {string} content
|
|
126
|
+
* @param {boolean} force
|
|
122
127
|
*/
|
|
123
128
|
async function writeFile(filePath, content, force = false) {
|
|
124
|
-
if (await fs.pathExists(filePath) && !force) {
|
|
129
|
+
if ((await fs.pathExists(filePath)) && !force) {
|
|
125
130
|
throw new Error(`File exists: ${filePath} (use --force to overwrite)`);
|
|
126
131
|
}
|
|
127
132
|
await fs.writeFile(filePath, content, 'utf-8');
|
|
@@ -129,7 +134,7 @@ async function writeFile(filePath, content, force = false) {
|
|
|
129
134
|
|
|
130
135
|
/**
|
|
131
136
|
* Generate project.yml content
|
|
132
|
-
* @param {import('../ir/types').ProjectIR} ir
|
|
137
|
+
* @param {import('../ir/types').ProjectIR} ir
|
|
133
138
|
* @returns {string}
|
|
134
139
|
*/
|
|
135
140
|
function generateProjectYml(ir) {
|
|
@@ -150,34 +155,34 @@ function generateProjectYml(ir) {
|
|
|
150
155
|
status: f.status,
|
|
151
156
|
})),
|
|
152
157
|
};
|
|
153
|
-
|
|
158
|
+
|
|
154
159
|
return yaml.dump(projectData, { lineWidth: 100 });
|
|
155
160
|
}
|
|
156
161
|
|
|
157
162
|
/**
|
|
158
163
|
* Generate constitution.md content
|
|
159
|
-
* @param {import('../ir/types').ConstitutionIR} constitution
|
|
160
|
-
* @param {boolean} preserveRaw
|
|
164
|
+
* @param {import('../ir/types').ConstitutionIR} constitution
|
|
165
|
+
* @param {boolean} preserveRaw
|
|
161
166
|
* @returns {string}
|
|
162
167
|
*/
|
|
163
168
|
function generateConstitution(constitution, preserveRaw = false) {
|
|
164
169
|
const lines = [];
|
|
165
|
-
|
|
170
|
+
|
|
166
171
|
lines.push('# MUSUBI Constitution');
|
|
167
172
|
lines.push('');
|
|
168
173
|
lines.push('The fundamental principles governing this project.');
|
|
169
174
|
lines.push('');
|
|
170
|
-
|
|
175
|
+
|
|
171
176
|
// Write articles
|
|
172
177
|
for (const article of constitution.articles) {
|
|
173
178
|
lines.push(`## Article ${article.number}: ${article.name}`);
|
|
174
179
|
lines.push('');
|
|
175
|
-
|
|
180
|
+
|
|
176
181
|
if (article.description) {
|
|
177
182
|
lines.push(article.description);
|
|
178
183
|
lines.push('');
|
|
179
184
|
}
|
|
180
|
-
|
|
185
|
+
|
|
181
186
|
if (article.rules && article.rules.length > 0) {
|
|
182
187
|
lines.push('### Rules');
|
|
183
188
|
lines.push('');
|
|
@@ -186,20 +191,20 @@ function generateConstitution(constitution, preserveRaw = false) {
|
|
|
186
191
|
}
|
|
187
192
|
lines.push('');
|
|
188
193
|
}
|
|
189
|
-
|
|
194
|
+
|
|
190
195
|
if (article.mappedFrom) {
|
|
191
196
|
lines.push(`> Mapped from: ${article.mappedFrom}`);
|
|
192
197
|
lines.push('');
|
|
193
198
|
}
|
|
194
199
|
}
|
|
195
|
-
|
|
200
|
+
|
|
196
201
|
// Write governance
|
|
197
202
|
if (constitution.governance) {
|
|
198
203
|
lines.push('## Governance');
|
|
199
204
|
lines.push('');
|
|
200
205
|
lines.push(`Version: ${constitution.governance.version}`);
|
|
201
206
|
lines.push('');
|
|
202
|
-
|
|
207
|
+
|
|
203
208
|
if (constitution.governance.rules && constitution.governance.rules.length > 0) {
|
|
204
209
|
for (const rule of constitution.governance.rules) {
|
|
205
210
|
lines.push(`- ${rule}`);
|
|
@@ -207,7 +212,7 @@ function generateConstitution(constitution, preserveRaw = false) {
|
|
|
207
212
|
lines.push('');
|
|
208
213
|
}
|
|
209
214
|
}
|
|
210
|
-
|
|
215
|
+
|
|
211
216
|
// Preserve raw content if requested
|
|
212
217
|
if (preserveRaw && constitution.rawContent) {
|
|
213
218
|
lines.push('---');
|
|
@@ -218,18 +223,18 @@ function generateConstitution(constitution, preserveRaw = false) {
|
|
|
218
223
|
lines.push(constitution.rawContent);
|
|
219
224
|
lines.push('```');
|
|
220
225
|
}
|
|
221
|
-
|
|
226
|
+
|
|
222
227
|
return lines.join('\n');
|
|
223
228
|
}
|
|
224
229
|
|
|
225
230
|
/**
|
|
226
231
|
* Generate product.md content
|
|
227
|
-
* @param {import('../ir/types').ProjectIR} ir
|
|
232
|
+
* @param {import('../ir/types').ProjectIR} ir
|
|
228
233
|
* @returns {string}
|
|
229
234
|
*/
|
|
230
235
|
function generateProduct(ir) {
|
|
231
236
|
const lines = [];
|
|
232
|
-
|
|
237
|
+
|
|
233
238
|
lines.push(`# ${ir.metadata.name}`);
|
|
234
239
|
lines.push('');
|
|
235
240
|
lines.push('## Overview');
|
|
@@ -238,27 +243,27 @@ function generateProduct(ir) {
|
|
|
238
243
|
lines.push('');
|
|
239
244
|
lines.push('## Features');
|
|
240
245
|
lines.push('');
|
|
241
|
-
|
|
246
|
+
|
|
242
247
|
for (const feature of ir.features) {
|
|
243
248
|
lines.push(`- **${feature.name}** (${feature.id}) - ${feature.status}`);
|
|
244
249
|
}
|
|
245
250
|
lines.push('');
|
|
246
|
-
|
|
251
|
+
|
|
247
252
|
lines.push('## Version History');
|
|
248
253
|
lines.push('');
|
|
249
254
|
lines.push(`- ${ir.metadata.version} - Initial conversion from ${ir.metadata.sourceFormat}`);
|
|
250
|
-
|
|
255
|
+
|
|
251
256
|
return lines.join('\n');
|
|
252
257
|
}
|
|
253
258
|
|
|
254
259
|
/**
|
|
255
260
|
* Generate structure.md content
|
|
256
|
-
* @param {import('../ir/types').ProjectIR} ir
|
|
261
|
+
* @param {import('../ir/types').ProjectIR} ir
|
|
257
262
|
* @returns {string}
|
|
258
263
|
*/
|
|
259
264
|
function generateStructure(ir) {
|
|
260
265
|
const lines = [];
|
|
261
|
-
|
|
266
|
+
|
|
262
267
|
lines.push('# Project Structure');
|
|
263
268
|
lines.push('');
|
|
264
269
|
lines.push('## Directory Layout');
|
|
@@ -276,39 +281,39 @@ function generateStructure(ir) {
|
|
|
276
281
|
lines.push('');
|
|
277
282
|
lines.push('storage/');
|
|
278
283
|
lines.push('└── specs/');
|
|
279
|
-
|
|
284
|
+
|
|
280
285
|
for (const feature of ir.features) {
|
|
281
286
|
lines.push(` └── ${feature.id}/`);
|
|
282
287
|
lines.push(' ├── spec.md');
|
|
283
288
|
lines.push(' ├── plan.md');
|
|
284
289
|
lines.push(' └── tasks.md');
|
|
285
290
|
}
|
|
286
|
-
|
|
291
|
+
|
|
287
292
|
lines.push('```');
|
|
288
|
-
|
|
293
|
+
|
|
289
294
|
return lines.join('\n');
|
|
290
295
|
}
|
|
291
296
|
|
|
292
297
|
/**
|
|
293
298
|
* Generate tech.md content
|
|
294
|
-
* @param {import('../ir/types').ProjectIR} ir
|
|
299
|
+
* @param {import('../ir/types').ProjectIR} ir
|
|
295
300
|
* @returns {string}
|
|
296
301
|
*/
|
|
297
302
|
function generateTech(ir) {
|
|
298
303
|
const lines = [];
|
|
299
|
-
|
|
304
|
+
|
|
300
305
|
lines.push('# Technology Stack');
|
|
301
306
|
lines.push('');
|
|
302
|
-
|
|
307
|
+
|
|
303
308
|
// Extract technical context from first feature with a plan
|
|
304
309
|
const featureWithPlan = ir.features.find(f => f.plan);
|
|
305
|
-
|
|
310
|
+
|
|
306
311
|
if (featureWithPlan && featureWithPlan.plan) {
|
|
307
312
|
const tech = featureWithPlan.plan.technicalContext;
|
|
308
|
-
|
|
313
|
+
|
|
309
314
|
lines.push('## Core Technologies');
|
|
310
315
|
lines.push('');
|
|
311
|
-
|
|
316
|
+
|
|
312
317
|
if (tech.language) {
|
|
313
318
|
lines.push(`- **Language**: ${tech.language}${tech.version ? ` ${tech.version}` : ''}`);
|
|
314
319
|
}
|
|
@@ -321,7 +326,7 @@ function generateTech(ir) {
|
|
|
321
326
|
if (tech.targetPlatform) {
|
|
322
327
|
lines.push(`- **Platform**: ${tech.targetPlatform}`);
|
|
323
328
|
}
|
|
324
|
-
|
|
329
|
+
|
|
325
330
|
if (tech.dependencies && tech.dependencies.length > 0) {
|
|
326
331
|
lines.push('');
|
|
327
332
|
lines.push('## Dependencies');
|
|
@@ -335,26 +340,26 @@ function generateTech(ir) {
|
|
|
335
340
|
lines.push('');
|
|
336
341
|
lines.push('> Technology stack to be defined based on project requirements.');
|
|
337
342
|
}
|
|
338
|
-
|
|
343
|
+
|
|
339
344
|
return lines.join('\n');
|
|
340
345
|
}
|
|
341
346
|
|
|
342
347
|
/**
|
|
343
348
|
* Write a feature to MUSUBI format
|
|
344
|
-
* @param {import('../ir/types').FeatureIR} feature
|
|
345
|
-
* @param {string} featurePath
|
|
346
|
-
* @param {Object} options
|
|
349
|
+
* @param {import('../ir/types').FeatureIR} feature
|
|
350
|
+
* @param {string} featurePath
|
|
351
|
+
* @param {Object} options
|
|
347
352
|
* @returns {Promise<{filesWritten: number, warnings: string[]}>}
|
|
348
353
|
*/
|
|
349
354
|
async function writeFeature(feature, featurePath, options = {}) {
|
|
350
355
|
const { dryRun = false, force = false, preserveRaw = false, verbose = false } = options;
|
|
351
356
|
const warnings = [];
|
|
352
357
|
let filesWritten = 0;
|
|
353
|
-
|
|
358
|
+
|
|
354
359
|
if (!dryRun) {
|
|
355
360
|
await fs.ensureDir(featurePath);
|
|
356
361
|
}
|
|
357
|
-
|
|
362
|
+
|
|
358
363
|
// Write spec.md
|
|
359
364
|
const specPath = path.join(featurePath, 'spec.md');
|
|
360
365
|
const specContent = generateSpec(feature, preserveRaw);
|
|
@@ -363,7 +368,7 @@ async function writeFeature(feature, featurePath, options = {}) {
|
|
|
363
368
|
filesWritten++;
|
|
364
369
|
}
|
|
365
370
|
if (verbose) console.log(` Writing: ${specPath}`);
|
|
366
|
-
|
|
371
|
+
|
|
367
372
|
// Write plan.md
|
|
368
373
|
if (feature.plan) {
|
|
369
374
|
const planPath = path.join(featurePath, 'plan.md');
|
|
@@ -374,7 +379,7 @@ async function writeFeature(feature, featurePath, options = {}) {
|
|
|
374
379
|
}
|
|
375
380
|
if (verbose) console.log(` Writing: ${planPath}`);
|
|
376
381
|
}
|
|
377
|
-
|
|
382
|
+
|
|
378
383
|
// Write tasks.md
|
|
379
384
|
if (feature.tasks && feature.tasks.length > 0) {
|
|
380
385
|
const tasksPath = path.join(featurePath, 'tasks.md');
|
|
@@ -385,7 +390,7 @@ async function writeFeature(feature, featurePath, options = {}) {
|
|
|
385
390
|
}
|
|
386
391
|
if (verbose) console.log(` Writing: ${tasksPath}`);
|
|
387
392
|
}
|
|
388
|
-
|
|
393
|
+
|
|
389
394
|
// Write research.md
|
|
390
395
|
if (feature.research) {
|
|
391
396
|
const researchPath = path.join(featurePath, 'research.md');
|
|
@@ -396,7 +401,7 @@ async function writeFeature(feature, featurePath, options = {}) {
|
|
|
396
401
|
}
|
|
397
402
|
if (verbose) console.log(` Writing: ${researchPath}`);
|
|
398
403
|
}
|
|
399
|
-
|
|
404
|
+
|
|
400
405
|
// Write data-model.md
|
|
401
406
|
if (feature.dataModel) {
|
|
402
407
|
const dataModelPath = path.join(featurePath, 'data-model.md');
|
|
@@ -407,14 +412,14 @@ async function writeFeature(feature, featurePath, options = {}) {
|
|
|
407
412
|
}
|
|
408
413
|
if (verbose) console.log(` Writing: ${dataModelPath}`);
|
|
409
414
|
}
|
|
410
|
-
|
|
415
|
+
|
|
411
416
|
// Write contracts
|
|
412
417
|
if (feature.contracts && feature.contracts.length > 0) {
|
|
413
418
|
const contractsPath = path.join(featurePath, 'contracts');
|
|
414
419
|
if (!dryRun) {
|
|
415
420
|
await fs.ensureDir(contractsPath);
|
|
416
421
|
}
|
|
417
|
-
|
|
422
|
+
|
|
418
423
|
for (const contract of feature.contracts) {
|
|
419
424
|
const contractFile = path.join(contractsPath, `${contract.name}.md`);
|
|
420
425
|
const contractContent = contract.rawContent || generateContract(contract);
|
|
@@ -425,33 +430,33 @@ async function writeFeature(feature, featurePath, options = {}) {
|
|
|
425
430
|
if (verbose) console.log(` Writing: ${contractFile}`);
|
|
426
431
|
}
|
|
427
432
|
}
|
|
428
|
-
|
|
433
|
+
|
|
429
434
|
return { filesWritten, warnings };
|
|
430
435
|
}
|
|
431
436
|
|
|
432
437
|
/**
|
|
433
438
|
* Generate spec.md content (MUSUBI format with EARS)
|
|
434
|
-
* @param {import('../ir/types').FeatureIR} feature
|
|
435
|
-
* @param {boolean} preserveRaw
|
|
439
|
+
* @param {import('../ir/types').FeatureIR} feature
|
|
440
|
+
* @param {boolean} preserveRaw
|
|
436
441
|
* @returns {string}
|
|
437
442
|
*/
|
|
438
443
|
function generateSpec(feature, preserveRaw = false) {
|
|
439
444
|
const lines = [];
|
|
440
445
|
const spec = feature.specification;
|
|
441
|
-
|
|
446
|
+
|
|
442
447
|
lines.push(`# ${spec.title || feature.name}`);
|
|
443
448
|
lines.push('');
|
|
444
|
-
|
|
449
|
+
|
|
445
450
|
if (spec.description) {
|
|
446
451
|
lines.push(spec.description);
|
|
447
452
|
lines.push('');
|
|
448
453
|
}
|
|
449
|
-
|
|
454
|
+
|
|
450
455
|
// Write requirements (EARS format)
|
|
451
456
|
if (spec.requirements && spec.requirements.length > 0) {
|
|
452
457
|
lines.push('## Requirements');
|
|
453
458
|
lines.push('');
|
|
454
|
-
|
|
459
|
+
|
|
455
460
|
for (const req of spec.requirements) {
|
|
456
461
|
lines.push(`### ${req.id}: ${req.title || 'Requirement'}`);
|
|
457
462
|
lines.push('');
|
|
@@ -460,7 +465,7 @@ function generateSpec(feature, preserveRaw = false) {
|
|
|
460
465
|
lines.push('');
|
|
461
466
|
lines.push(`**Statement**: ${req.statement}`);
|
|
462
467
|
lines.push('');
|
|
463
|
-
|
|
468
|
+
|
|
464
469
|
if (req.acceptanceCriteria && req.acceptanceCriteria.length > 0) {
|
|
465
470
|
lines.push('**Acceptance Criteria**:');
|
|
466
471
|
for (const ac of req.acceptanceCriteria) {
|
|
@@ -468,14 +473,14 @@ function generateSpec(feature, preserveRaw = false) {
|
|
|
468
473
|
}
|
|
469
474
|
lines.push('');
|
|
470
475
|
}
|
|
471
|
-
|
|
476
|
+
|
|
472
477
|
if (req.mappedFromUserStory) {
|
|
473
478
|
lines.push(`> Converted from User Story: ${req.mappedFromUserStory}`);
|
|
474
479
|
lines.push('');
|
|
475
480
|
}
|
|
476
481
|
}
|
|
477
482
|
}
|
|
478
|
-
|
|
483
|
+
|
|
479
484
|
// Write success criteria
|
|
480
485
|
if (spec.successCriteria && spec.successCriteria.length > 0) {
|
|
481
486
|
lines.push('## Success Criteria');
|
|
@@ -485,7 +490,7 @@ function generateSpec(feature, preserveRaw = false) {
|
|
|
485
490
|
}
|
|
486
491
|
lines.push('');
|
|
487
492
|
}
|
|
488
|
-
|
|
493
|
+
|
|
489
494
|
// Preserve raw content if requested
|
|
490
495
|
if (preserveRaw && spec.rawContent) {
|
|
491
496
|
lines.push('---');
|
|
@@ -496,33 +501,33 @@ function generateSpec(feature, preserveRaw = false) {
|
|
|
496
501
|
lines.push(spec.rawContent);
|
|
497
502
|
lines.push('```');
|
|
498
503
|
}
|
|
499
|
-
|
|
504
|
+
|
|
500
505
|
return lines.join('\n');
|
|
501
506
|
}
|
|
502
507
|
|
|
503
508
|
/**
|
|
504
509
|
* Generate plan.md content
|
|
505
|
-
* @param {import('../ir/types').PlanIR} plan
|
|
506
|
-
* @param {boolean} preserveRaw
|
|
510
|
+
* @param {import('../ir/types').PlanIR} plan
|
|
511
|
+
* @param {boolean} preserveRaw
|
|
507
512
|
* @returns {string}
|
|
508
513
|
*/
|
|
509
514
|
function generatePlan(plan, preserveRaw = false) {
|
|
510
515
|
const lines = [];
|
|
511
|
-
|
|
516
|
+
|
|
512
517
|
lines.push('# Implementation Plan');
|
|
513
518
|
lines.push('');
|
|
514
|
-
|
|
519
|
+
|
|
515
520
|
if (plan.summary) {
|
|
516
521
|
lines.push(plan.summary);
|
|
517
522
|
lines.push('');
|
|
518
523
|
}
|
|
519
|
-
|
|
524
|
+
|
|
520
525
|
// Technical Context
|
|
521
526
|
const tech = plan.technicalContext;
|
|
522
527
|
if (tech && (tech.language || tech.framework)) {
|
|
523
528
|
lines.push('## Technical Context');
|
|
524
529
|
lines.push('');
|
|
525
|
-
|
|
530
|
+
|
|
526
531
|
if (tech.language) {
|
|
527
532
|
lines.push(`- **Language**: ${tech.language}${tech.version ? ` ${tech.version}` : ''}`);
|
|
528
533
|
}
|
|
@@ -537,21 +542,21 @@ function generatePlan(plan, preserveRaw = false) {
|
|
|
537
542
|
}
|
|
538
543
|
lines.push('');
|
|
539
544
|
}
|
|
540
|
-
|
|
545
|
+
|
|
541
546
|
// Phases
|
|
542
547
|
if (plan.phases && plan.phases.length > 0) {
|
|
543
548
|
lines.push('## Phases');
|
|
544
549
|
lines.push('');
|
|
545
|
-
|
|
550
|
+
|
|
546
551
|
for (const phase of plan.phases) {
|
|
547
552
|
lines.push(`### Phase ${phase.number}: ${phase.name}`);
|
|
548
553
|
lines.push('');
|
|
549
|
-
|
|
554
|
+
|
|
550
555
|
if (phase.purpose) {
|
|
551
556
|
lines.push(phase.purpose);
|
|
552
557
|
lines.push('');
|
|
553
558
|
}
|
|
554
|
-
|
|
559
|
+
|
|
555
560
|
if (phase.outputs && phase.outputs.length > 0) {
|
|
556
561
|
lines.push('**Outputs**:');
|
|
557
562
|
for (const output of phase.outputs) {
|
|
@@ -561,7 +566,7 @@ function generatePlan(plan, preserveRaw = false) {
|
|
|
561
566
|
}
|
|
562
567
|
}
|
|
563
568
|
}
|
|
564
|
-
|
|
569
|
+
|
|
565
570
|
// Preserve raw content if requested
|
|
566
571
|
if (preserveRaw && plan.rawContent) {
|
|
567
572
|
lines.push('---');
|
|
@@ -572,21 +577,21 @@ function generatePlan(plan, preserveRaw = false) {
|
|
|
572
577
|
lines.push(plan.rawContent);
|
|
573
578
|
lines.push('```');
|
|
574
579
|
}
|
|
575
|
-
|
|
580
|
+
|
|
576
581
|
return lines.join('\n');
|
|
577
582
|
}
|
|
578
583
|
|
|
579
584
|
/**
|
|
580
585
|
* Generate tasks.md content (MUSUBI format)
|
|
581
|
-
* @param {import('../ir/types').TaskIR[]} tasks
|
|
586
|
+
* @param {import('../ir/types').TaskIR[]} tasks
|
|
582
587
|
* @returns {string}
|
|
583
588
|
*/
|
|
584
589
|
function generateTasks(tasks) {
|
|
585
590
|
const lines = [];
|
|
586
|
-
|
|
591
|
+
|
|
587
592
|
lines.push('# Tasks');
|
|
588
593
|
lines.push('');
|
|
589
|
-
|
|
594
|
+
|
|
590
595
|
// Group by phase
|
|
591
596
|
const phases = {};
|
|
592
597
|
for (const task of tasks) {
|
|
@@ -596,17 +601,17 @@ function generateTasks(tasks) {
|
|
|
596
601
|
}
|
|
597
602
|
phases[phase].push(task);
|
|
598
603
|
}
|
|
599
|
-
|
|
604
|
+
|
|
600
605
|
for (const [phaseNum, phaseTasks] of Object.entries(phases)) {
|
|
601
606
|
lines.push(`## Phase ${phaseNum}`);
|
|
602
607
|
lines.push('');
|
|
603
|
-
|
|
608
|
+
|
|
604
609
|
for (const task of phaseTasks) {
|
|
605
610
|
const checkbox = task.completed ? '[x]' : '[ ]';
|
|
606
611
|
let taskLine = `- ${checkbox} ${task.id}: ${task.description}`;
|
|
607
|
-
|
|
612
|
+
|
|
608
613
|
lines.push(taskLine);
|
|
609
|
-
|
|
614
|
+
|
|
610
615
|
// Add metadata as sub-items
|
|
611
616
|
if (task.filePath) {
|
|
612
617
|
lines.push(` - Path: ${task.filePath}`);
|
|
@@ -620,27 +625,27 @@ function generateTasks(tasks) {
|
|
|
620
625
|
}
|
|
621
626
|
lines.push('');
|
|
622
627
|
}
|
|
623
|
-
|
|
628
|
+
|
|
624
629
|
return lines.join('\n');
|
|
625
630
|
}
|
|
626
631
|
|
|
627
632
|
/**
|
|
628
633
|
* Generate research.md content
|
|
629
|
-
* @param {import('../ir/types').ResearchIR} research
|
|
630
|
-
* @param {boolean} preserveRaw
|
|
634
|
+
* @param {import('../ir/types').ResearchIR} research
|
|
635
|
+
* @param {boolean} preserveRaw
|
|
631
636
|
* @returns {string}
|
|
632
637
|
*/
|
|
633
638
|
function generateResearch(research, preserveRaw = false) {
|
|
634
639
|
const lines = [];
|
|
635
|
-
|
|
640
|
+
|
|
636
641
|
lines.push('# Research');
|
|
637
642
|
lines.push('');
|
|
638
|
-
|
|
643
|
+
|
|
639
644
|
// Decisions
|
|
640
645
|
if (research.decisions && research.decisions.length > 0) {
|
|
641
646
|
lines.push('## Decisions');
|
|
642
647
|
lines.push('');
|
|
643
|
-
|
|
648
|
+
|
|
644
649
|
for (const decision of research.decisions) {
|
|
645
650
|
lines.push(`### ${decision.topic}`);
|
|
646
651
|
lines.push('');
|
|
@@ -651,16 +656,16 @@ function generateResearch(research, preserveRaw = false) {
|
|
|
651
656
|
lines.push('');
|
|
652
657
|
}
|
|
653
658
|
}
|
|
654
|
-
|
|
659
|
+
|
|
655
660
|
// Alternatives
|
|
656
661
|
if (research.alternatives && research.alternatives.length > 0) {
|
|
657
662
|
lines.push('## Alternatives Considered');
|
|
658
663
|
lines.push('');
|
|
659
|
-
|
|
664
|
+
|
|
660
665
|
for (const alt of research.alternatives) {
|
|
661
666
|
lines.push(`### ${alt.name}`);
|
|
662
667
|
lines.push('');
|
|
663
|
-
|
|
668
|
+
|
|
664
669
|
if (alt.pros && alt.pros.length > 0) {
|
|
665
670
|
lines.push('**Pros**:');
|
|
666
671
|
for (const pro of alt.pros) {
|
|
@@ -668,7 +673,7 @@ function generateResearch(research, preserveRaw = false) {
|
|
|
668
673
|
}
|
|
669
674
|
lines.push('');
|
|
670
675
|
}
|
|
671
|
-
|
|
676
|
+
|
|
672
677
|
if (alt.cons && alt.cons.length > 0) {
|
|
673
678
|
lines.push('**Cons**:');
|
|
674
679
|
for (const con of alt.cons) {
|
|
@@ -676,7 +681,7 @@ function generateResearch(research, preserveRaw = false) {
|
|
|
676
681
|
}
|
|
677
682
|
lines.push('');
|
|
678
683
|
}
|
|
679
|
-
|
|
684
|
+
|
|
680
685
|
if (alt.rejected) {
|
|
681
686
|
lines.push(`**Status**: Rejected`);
|
|
682
687
|
if (alt.reason) {
|
|
@@ -686,7 +691,7 @@ function generateResearch(research, preserveRaw = false) {
|
|
|
686
691
|
}
|
|
687
692
|
}
|
|
688
693
|
}
|
|
689
|
-
|
|
694
|
+
|
|
690
695
|
// Preserve raw content if requested
|
|
691
696
|
if (preserveRaw && research.rawContent) {
|
|
692
697
|
lines.push('---');
|
|
@@ -697,36 +702,36 @@ function generateResearch(research, preserveRaw = false) {
|
|
|
697
702
|
lines.push(research.rawContent);
|
|
698
703
|
lines.push('```');
|
|
699
704
|
}
|
|
700
|
-
|
|
705
|
+
|
|
701
706
|
return lines.join('\n');
|
|
702
707
|
}
|
|
703
708
|
|
|
704
709
|
/**
|
|
705
710
|
* Generate data-model.md content
|
|
706
|
-
* @param {import('../ir/types').DataModelIR} dataModel
|
|
707
|
-
* @param {boolean} preserveRaw
|
|
711
|
+
* @param {import('../ir/types').DataModelIR} dataModel
|
|
712
|
+
* @param {boolean} preserveRaw
|
|
708
713
|
* @returns {string}
|
|
709
714
|
*/
|
|
710
715
|
function generateDataModel(dataModel, preserveRaw = false) {
|
|
711
716
|
const lines = [];
|
|
712
|
-
|
|
717
|
+
|
|
713
718
|
lines.push('# Data Model');
|
|
714
719
|
lines.push('');
|
|
715
|
-
|
|
720
|
+
|
|
716
721
|
// Entities
|
|
717
722
|
if (dataModel.entities && dataModel.entities.length > 0) {
|
|
718
723
|
lines.push('## Entities');
|
|
719
724
|
lines.push('');
|
|
720
|
-
|
|
725
|
+
|
|
721
726
|
for (const entity of dataModel.entities) {
|
|
722
727
|
lines.push(`### ${entity.name}`);
|
|
723
728
|
lines.push('');
|
|
724
|
-
|
|
729
|
+
|
|
725
730
|
if (entity.description) {
|
|
726
731
|
lines.push(entity.description);
|
|
727
732
|
lines.push('');
|
|
728
733
|
}
|
|
729
|
-
|
|
734
|
+
|
|
730
735
|
if (entity.fields && entity.fields.length > 0) {
|
|
731
736
|
lines.push('**Fields**:');
|
|
732
737
|
for (const field of entity.fields) {
|
|
@@ -743,18 +748,18 @@ function generateDataModel(dataModel, preserveRaw = false) {
|
|
|
743
748
|
}
|
|
744
749
|
}
|
|
745
750
|
}
|
|
746
|
-
|
|
751
|
+
|
|
747
752
|
// Relationships
|
|
748
753
|
if (dataModel.relationships && dataModel.relationships.length > 0) {
|
|
749
754
|
lines.push('## Relationships');
|
|
750
755
|
lines.push('');
|
|
751
|
-
|
|
756
|
+
|
|
752
757
|
for (const rel of dataModel.relationships) {
|
|
753
758
|
lines.push(`- ${rel.from} → ${rel.to} (${rel.type})`);
|
|
754
759
|
}
|
|
755
760
|
lines.push('');
|
|
756
761
|
}
|
|
757
|
-
|
|
762
|
+
|
|
758
763
|
// Preserve raw content if requested
|
|
759
764
|
if (preserveRaw && dataModel.rawContent) {
|
|
760
765
|
lines.push('---');
|
|
@@ -765,29 +770,29 @@ function generateDataModel(dataModel, preserveRaw = false) {
|
|
|
765
770
|
lines.push(dataModel.rawContent);
|
|
766
771
|
lines.push('```');
|
|
767
772
|
}
|
|
768
|
-
|
|
773
|
+
|
|
769
774
|
return lines.join('\n');
|
|
770
775
|
}
|
|
771
776
|
|
|
772
777
|
/**
|
|
773
778
|
* Generate contract content
|
|
774
|
-
* @param {import('../ir/types').ContractIR} contract
|
|
779
|
+
* @param {import('../ir/types').ContractIR} contract
|
|
775
780
|
* @returns {string}
|
|
776
781
|
*/
|
|
777
782
|
function generateContract(contract) {
|
|
778
783
|
const lines = [];
|
|
779
|
-
|
|
784
|
+
|
|
780
785
|
lines.push(`# ${contract.name}`);
|
|
781
786
|
lines.push('');
|
|
782
787
|
lines.push(`**Type**: ${contract.type}`);
|
|
783
788
|
lines.push('');
|
|
784
|
-
|
|
789
|
+
|
|
785
790
|
if (contract.rawContent) {
|
|
786
791
|
lines.push(contract.rawContent);
|
|
787
792
|
} else {
|
|
788
793
|
lines.push('> Contract details to be defined.');
|
|
789
794
|
}
|
|
790
|
-
|
|
795
|
+
|
|
791
796
|
return lines.join('\n');
|
|
792
797
|
}
|
|
793
798
|
|