scene-capability-engine 3.0.0
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/CHANGELOG.md +2513 -0
- package/LICENSE +21 -0
- package/README.md +765 -0
- package/README.zh.md +630 -0
- package/bin/kiro-spec-engine.js +796 -0
- package/bin/kse.js +3 -0
- package/bin/sce.js +3 -0
- package/bin/sco.js +3 -0
- package/docs/331-poc-adaptation-roadmap.md +156 -0
- package/docs/331-poc-dual-track-integration-guide.md +120 -0
- package/docs/331-poc-weekly-delivery-checklist.md +52 -0
- package/docs/OFFLINE_INSTALL.md +96 -0
- package/docs/README.md +279 -0
- package/docs/adopt-migration-guide.md +599 -0
- package/docs/adoption-guide.md +616 -0
- package/docs/agent-hooks-analysis.md +815 -0
- package/docs/architecture.md +733 -0
- package/docs/articles/ai-driven-development-philosophy-and-practice-review.md +208 -0
- package/docs/articles/ai-driven-development-philosophy-and-practice.en.md +459 -0
- package/docs/articles/ai-driven-development-philosophy-and-practice.md +492 -0
- package/docs/autonomous-control-guide.md +851 -0
- package/docs/command-reference.md +1368 -0
- package/docs/community.md +115 -0
- package/docs/cross-tool-guide.md +555 -0
- package/docs/developer-guide.md +619 -0
- package/docs/document-governance.md +865 -0
- package/docs/environment-management-guide.md +526 -0
- package/docs/examples/add-export-command/design.md +194 -0
- package/docs/examples/add-export-command/requirements.md +110 -0
- package/docs/examples/add-export-command/tasks.md +88 -0
- package/docs/examples/add-rest-api/design.md +855 -0
- package/docs/examples/add-rest-api/requirements.md +323 -0
- package/docs/examples/add-rest-api/tasks.md +355 -0
- package/docs/examples/add-user-dashboard/design.md +192 -0
- package/docs/examples/add-user-dashboard/requirements.md +143 -0
- package/docs/examples/add-user-dashboard/tasks.md +91 -0
- package/docs/faq.md +697 -0
- package/docs/handoffs/evidence/ontology/moqui-template-baseline-2026-02-17-232922.json +156 -0
- package/docs/handoffs/evidence/ontology/moqui-template-baseline-2026-02-17-232922.md +24 -0
- package/docs/images/wechat-qr.png +0 -0
- package/docs/integration-modes.md +529 -0
- package/docs/integration-philosophy.md +313 -0
- package/docs/knowledge-management-guide.md +263 -0
- package/docs/manual-workflows-guide.md +418 -0
- package/docs/moqui-capability-matrix.md +73 -0
- package/docs/moqui-template-core-library-playbook.md +109 -0
- package/docs/multi-agent-coordination-guide.md +553 -0
- package/docs/multi-repo-management-guide.md +1344 -0
- package/docs/quick-start-with-ai-tools.md +375 -0
- package/docs/quick-start.md +146 -0
- package/docs/release-checklist.md +121 -0
- package/docs/releases/README.md +13 -0
- package/docs/releases/v1.46.2-validation.md +45 -0
- package/docs/releases/v1.46.2.md +50 -0
- package/docs/scene-runtime-guide.md +347 -0
- package/docs/spec-collaboration-guide.md +369 -0
- package/docs/spec-locking-guide.md +225 -0
- package/docs/spec-numbering-guide.md +348 -0
- package/docs/spec-workflow.md +519 -0
- package/docs/steering-strategy-guide.md +196 -0
- package/docs/team-collaboration-guide.md +465 -0
- package/docs/testing-strategy.md +272 -0
- package/docs/tools/claude-guide.md +654 -0
- package/docs/tools/cursor-guide.md +706 -0
- package/docs/tools/generic-guide.md +446 -0
- package/docs/tools/kiro-guide.md +308 -0
- package/docs/tools/vscode-guide.md +445 -0
- package/docs/tools/windsurf-guide.md +391 -0
- package/docs/troubleshooting.md +1135 -0
- package/docs/upgrade-guide.md +639 -0
- package/docs/value-observability-guide.md +127 -0
- package/docs/zh/README.md +341 -0
- package/docs/zh/quick-start.md +764 -0
- package/docs/zh/release-checklist.md +121 -0
- package/docs/zh/releases/README.md +13 -0
- package/docs/zh/releases/v1.46.2-validation.md +45 -0
- package/docs/zh/releases/v1.46.2.md +50 -0
- package/docs/zh/spec-numbering-guide.md +348 -0
- package/docs/zh/tools/claude-guide.md +349 -0
- package/docs/zh/tools/cursor-guide.md +281 -0
- package/docs/zh/tools/generic-guide.md +499 -0
- package/docs/zh/tools/kiro-guide.md +342 -0
- package/docs/zh/tools/vscode-guide.md +449 -0
- package/docs/zh/tools/windsurf-guide.md +378 -0
- package/docs/zh/value-observability-guide.md +127 -0
- package/docs//344/272/244/344/273/230/346/270/205/345/215/225.md +75 -0
- package/lib/adoption/adoption-logger.js +487 -0
- package/lib/adoption/adoption-strategy.js +538 -0
- package/lib/adoption/backup-manager.js +420 -0
- package/lib/adoption/conflict-resolver.js +410 -0
- package/lib/adoption/detection-engine.js +275 -0
- package/lib/adoption/diff-viewer.js +226 -0
- package/lib/adoption/error-formatter.js +509 -0
- package/lib/adoption/file-classifier.js +385 -0
- package/lib/adoption/progress-reporter.js +534 -0
- package/lib/adoption/smart-orchestrator.js +470 -0
- package/lib/adoption/strategy-selector.js +218 -0
- package/lib/adoption/summary-generator.js +493 -0
- package/lib/adoption/template-sync.js +605 -0
- package/lib/auto/autonomous-engine.js +485 -0
- package/lib/auto/checkpoint-manager.js +300 -0
- package/lib/auto/close-loop-runner.js +2476 -0
- package/lib/auto/config-schema.js +176 -0
- package/lib/auto/decision-engine.js +344 -0
- package/lib/auto/error-recovery-manager.js +580 -0
- package/lib/auto/goal-decomposer.js +278 -0
- package/lib/auto/progress-tracker.js +502 -0
- package/lib/auto/safety-manager.js +186 -0
- package/lib/auto/semantic-decomposer.js +137 -0
- package/lib/auto/state-manager.js +126 -0
- package/lib/auto/task-queue-manager.js +340 -0
- package/lib/backup/backup-system.js +372 -0
- package/lib/backup/selective-backup.js +207 -0
- package/lib/collab/agent-registry.js +240 -0
- package/lib/collab/collab-manager.js +285 -0
- package/lib/collab/contract-manager.js +320 -0
- package/lib/collab/coordinator.js +370 -0
- package/lib/collab/dependency-manager.js +280 -0
- package/lib/collab/index.js +20 -0
- package/lib/collab/integration-manager.js +202 -0
- package/lib/collab/merge-coordinator.js +252 -0
- package/lib/collab/metadata-manager.js +233 -0
- package/lib/collab/multi-agent-config.js +120 -0
- package/lib/collab/spec-lifecycle-manager.js +304 -0
- package/lib/collab/sync-barrier.js +88 -0
- package/lib/collab/visualizer.js +208 -0
- package/lib/commands/adopt.js +749 -0
- package/lib/commands/auto.js +19559 -0
- package/lib/commands/collab.js +275 -0
- package/lib/commands/context.js +99 -0
- package/lib/commands/docs.js +808 -0
- package/lib/commands/doctor.js +273 -0
- package/lib/commands/env.js +420 -0
- package/lib/commands/knowledge.js +309 -0
- package/lib/commands/lock.js +235 -0
- package/lib/commands/ops.js +409 -0
- package/lib/commands/orchestrate.js +446 -0
- package/lib/commands/prompt.js +105 -0
- package/lib/commands/repo.js +118 -0
- package/lib/commands/rollback.js +219 -0
- package/lib/commands/scene.js +15549 -0
- package/lib/commands/spec-bootstrap.js +147 -0
- package/lib/commands/spec-gate.js +157 -0
- package/lib/commands/spec-pipeline.js +205 -0
- package/lib/commands/status.js +321 -0
- package/lib/commands/task.js +199 -0
- package/lib/commands/templates.js +654 -0
- package/lib/commands/upgrade.js +231 -0
- package/lib/commands/value.js +569 -0
- package/lib/commands/watch.js +684 -0
- package/lib/commands/workflows.js +240 -0
- package/lib/commands/workspace-multi.js +325 -0
- package/lib/commands/workspace.js +189 -0
- package/lib/context/context-exporter.js +378 -0
- package/lib/context/prompt-generator.js +482 -0
- package/lib/data/moqui-capability-lexicon.json +45 -0
- package/lib/environment/backup-system.js +189 -0
- package/lib/environment/environment-manager.js +379 -0
- package/lib/environment/environment-registry.js +168 -0
- package/lib/gitignore/gitignore-backup.js +229 -0
- package/lib/gitignore/gitignore-detector.js +239 -0
- package/lib/gitignore/gitignore-integration.js +267 -0
- package/lib/gitignore/gitignore-transformer.js +193 -0
- package/lib/gitignore/layered-rules-template.js +42 -0
- package/lib/governance/archive-tool.js +284 -0
- package/lib/governance/cleanup-tool.js +237 -0
- package/lib/governance/config-manager.js +186 -0
- package/lib/governance/diagnostic-engine.js +271 -0
- package/lib/governance/doc-reference-checker.js +200 -0
- package/lib/governance/execution-logger.js +243 -0
- package/lib/governance/file-scanner.js +285 -0
- package/lib/governance/hooks-manager.js +333 -0
- package/lib/governance/reporter.js +337 -0
- package/lib/governance/validation-engine.js +181 -0
- package/lib/i18n.js +79 -0
- package/lib/knowledge/entry-manager.js +208 -0
- package/lib/knowledge/index-manager.js +261 -0
- package/lib/knowledge/knowledge-manager.js +273 -0
- package/lib/knowledge/template-manager.js +191 -0
- package/lib/lock/index.js +21 -0
- package/lib/lock/lock-file.js +192 -0
- package/lib/lock/lock-manager.js +321 -0
- package/lib/lock/machine-identifier.js +135 -0
- package/lib/lock/steering-file-lock.js +207 -0
- package/lib/lock/task-lock-manager.js +345 -0
- package/lib/operations/audit-logger.js +293 -0
- package/lib/operations/feedback-manager.js +1147 -0
- package/lib/operations/index.js +23 -0
- package/lib/operations/models/index.js +170 -0
- package/lib/operations/operations-manager.js +151 -0
- package/lib/operations/operations-validator.js +280 -0
- package/lib/operations/permission-manager.js +354 -0
- package/lib/operations/template-loader.js +143 -0
- package/lib/orchestrator/agent-spawner.js +629 -0
- package/lib/orchestrator/bootstrap-prompt-builder.js +236 -0
- package/lib/orchestrator/index.js +19 -0
- package/lib/orchestrator/orchestration-engine.js +1270 -0
- package/lib/orchestrator/orchestrator-config.js +173 -0
- package/lib/orchestrator/status-monitor.js +591 -0
- package/lib/python-checker.js +209 -0
- package/lib/repo/config-manager.js +580 -0
- package/lib/repo/errors/config-error.js +13 -0
- package/lib/repo/errors/git-error.js +15 -0
- package/lib/repo/errors/repo-error.js +14 -0
- package/lib/repo/git-operations.js +181 -0
- package/lib/repo/handlers/.gitkeep +1 -0
- package/lib/repo/handlers/exec-handler.js +155 -0
- package/lib/repo/handlers/health-handler.js +169 -0
- package/lib/repo/handlers/init-handler.js +197 -0
- package/lib/repo/handlers/status-handler.js +176 -0
- package/lib/repo/output-formatter.js +184 -0
- package/lib/repo/path-resolver.js +178 -0
- package/lib/repo/repo-manager.js +514 -0
- package/lib/scene-runtime/audit-emitter.js +59 -0
- package/lib/scene-runtime/binding-plugin-loader.js +351 -0
- package/lib/scene-runtime/binding-registry.js +349 -0
- package/lib/scene-runtime/eval-bridge.js +44 -0
- package/lib/scene-runtime/index.js +19 -0
- package/lib/scene-runtime/moqui-adapter.js +620 -0
- package/lib/scene-runtime/moqui-client.js +606 -0
- package/lib/scene-runtime/moqui-extractor.js +2029 -0
- package/lib/scene-runtime/plan-compiler.js +208 -0
- package/lib/scene-runtime/policy-gate.js +58 -0
- package/lib/scene-runtime/runtime-executor.js +358 -0
- package/lib/scene-runtime/scene-loader.js +96 -0
- package/lib/scene-runtime/scene-ontology.js +959 -0
- package/lib/scene-runtime/scene-template-linter.js +852 -0
- package/lib/scene-runtime/templates/scene-template-erp-query-v0.1.yaml +28 -0
- package/lib/scene-runtime/templates/scene-template-hybrid-shadow-v0.1.yaml +34 -0
- package/lib/spec/bootstrap/context-collector.js +48 -0
- package/lib/spec/bootstrap/draft-generator.js +158 -0
- package/lib/spec/bootstrap/questionnaire-engine.js +70 -0
- package/lib/spec/bootstrap/trace-emitter.js +59 -0
- package/lib/spec/multi-spec-orchestrate.js +93 -0
- package/lib/spec/pipeline/constants.js +6 -0
- package/lib/spec/pipeline/stage-adapters.js +118 -0
- package/lib/spec/pipeline/stage-runner.js +146 -0
- package/lib/spec/pipeline/state-store.js +119 -0
- package/lib/spec-gate/engine/gate-engine.js +165 -0
- package/lib/spec-gate/policy/default-policy.js +22 -0
- package/lib/spec-gate/policy/policy-loader.js +103 -0
- package/lib/spec-gate/result-emitter.js +81 -0
- package/lib/spec-gate/rules/default-rules.js +156 -0
- package/lib/spec-gate/rules/rule-registry.js +51 -0
- package/lib/steering/adoption-config.js +164 -0
- package/lib/steering/compliance-auto-fixer.js +204 -0
- package/lib/steering/compliance-cache.js +99 -0
- package/lib/steering/compliance-error-reporter.js +70 -0
- package/lib/steering/context-sync-manager.js +273 -0
- package/lib/steering/index.js +92 -0
- package/lib/steering/spec-steering.js +230 -0
- package/lib/steering/steering-compliance-checker.js +73 -0
- package/lib/steering/steering-loader.js +144 -0
- package/lib/steering/steering-manager.js +289 -0
- package/lib/task/index.js +12 -0
- package/lib/task/task-claimer.js +489 -0
- package/lib/task/task-status-store.js +418 -0
- package/lib/templates/cache-manager.js +440 -0
- package/lib/templates/content-generalizer.js +247 -0
- package/lib/templates/frontmatter-generator.js +128 -0
- package/lib/templates/git-handler.js +471 -0
- package/lib/templates/metadata-collector.js +328 -0
- package/lib/templates/path-utils.js +144 -0
- package/lib/templates/registry-parser.js +505 -0
- package/lib/templates/spec-reader.js +216 -0
- package/lib/templates/template-applicator.js +249 -0
- package/lib/templates/template-creator.js +256 -0
- package/lib/templates/template-error.js +143 -0
- package/lib/templates/template-exporter.js +502 -0
- package/lib/templates/template-manager.js +782 -0
- package/lib/templates/template-validator.js +361 -0
- package/lib/upgrade/migration-engine.js +382 -0
- package/lib/upgrade/migrations/.gitkeep +52 -0
- package/lib/upgrade/migrations/1.0.0-to-1.1.0.js +78 -0
- package/lib/utils/file-diff.js +177 -0
- package/lib/utils/fs-utils.js +274 -0
- package/lib/utils/tool-detector.js +383 -0
- package/lib/utils/validation.js +324 -0
- package/lib/value/gate-summary-emitter.js +99 -0
- package/lib/value/metric-contract-loader.js +210 -0
- package/lib/value/risk-evaluator.js +117 -0
- package/lib/value/weekly-snapshot-builder.js +61 -0
- package/lib/version/version-checker.js +156 -0
- package/lib/version/version-manager.js +327 -0
- package/lib/watch/action-executor.js +458 -0
- package/lib/watch/event-debouncer.js +323 -0
- package/lib/watch/execution-logger.js +550 -0
- package/lib/watch/file-watcher.js +499 -0
- package/lib/watch/presets.js +266 -0
- package/lib/watch/watch-manager.js +533 -0
- package/lib/workspace/multi/global-config.js +150 -0
- package/lib/workspace/multi/index.js +22 -0
- package/lib/workspace/multi/path-utils.js +173 -0
- package/lib/workspace/multi/workspace-context-resolver.js +244 -0
- package/lib/workspace/multi/workspace-registry.js +196 -0
- package/lib/workspace/multi/workspace-state-manager.js +537 -0
- package/lib/workspace/multi/workspace.js +90 -0
- package/lib/workspace/workspace-manager.js +370 -0
- package/lib/workspace/workspace-sync.js +356 -0
- package/locales/en.json +114 -0
- package/locales/zh.json +114 -0
- package/package.json +102 -0
- package/template/.kiro/README.md +247 -0
- package/template/.kiro/hooks/check-spec-on-create.kiro.hook +17 -0
- package/template/.kiro/hooks/run-tests-on-save.kiro.hook +13 -0
- package/template/.kiro/hooks/sync-tasks-on-edit.kiro.hook +16 -0
- package/template/.kiro/specs/SPEC_WORKFLOW_GUIDE.md +134 -0
- package/template/.kiro/steering/CORE_PRINCIPLES.md +133 -0
- package/template/.kiro/steering/CURRENT_CONTEXT.md +30 -0
- package/template/.kiro/steering/ENVIRONMENT.md +35 -0
- package/template/.kiro/steering/RULES_GUIDE.md +46 -0
- package/template/.kiro/templates/operations/default/change-impact.md +112 -0
- package/template/.kiro/templates/operations/default/deployment.md +91 -0
- package/template/.kiro/templates/operations/default/feedback-response.md +269 -0
- package/template/.kiro/templates/operations/default/migration-plan.md +172 -0
- package/template/.kiro/templates/operations/default/monitoring.md +135 -0
- package/template/.kiro/templates/operations/default/operations.md +135 -0
- package/template/.kiro/templates/operations/default/rollback.md +143 -0
- package/template/.kiro/templates/operations/default/tools.yaml +364 -0
- package/template/.kiro/templates/operations/default/troubleshooting.md +123 -0
- package/template/.kiro/tools/backup_manager.py +295 -0
- package/template/.kiro/tools/configuration_manager.py +218 -0
- package/template/.kiro/tools/document_evaluator.py +550 -0
- package/template/.kiro/tools/enhancement_logger.py +168 -0
- package/template/.kiro/tools/error_handler.py +335 -0
- package/template/.kiro/tools/improvement_identifier.py +444 -0
- package/template/.kiro/tools/modification_applicator.py +737 -0
- package/template/.kiro/tools/quality_gate_enforcer.py +207 -0
- package/template/.kiro/tools/quality_scorer.py +305 -0
- package/template/.kiro/tools/report_generator.py +154 -0
- package/template/.kiro/tools/ultrawork_enhancer.py +676 -0
- package/template/.kiro/tools/ultrawork_enhancer_refactored.py +0 -0
- package/template/.kiro/tools/ultrawork_enhancer_v2.py +463 -0
- package/template/.kiro/tools/ultrawork_enhancer_v3.py +606 -0
- package/template/.kiro/tools/workflow_quality_gate.py +100 -0
- package/template/README.md +111 -0
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TemplateValidator - Validates template structure and content
|
|
3
|
+
*
|
|
4
|
+
* Validates YAML frontmatter, file structure, and template completeness.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const fs = require('fs-extra');
|
|
8
|
+
const path = require('path');
|
|
9
|
+
const { ValidationError } = require('./template-error');
|
|
10
|
+
|
|
11
|
+
class TemplateValidator {
|
|
12
|
+
constructor() {
|
|
13
|
+
this.requiredFiles = ['requirements.md', 'design.md', 'tasks.md'];
|
|
14
|
+
this.requiredFrontmatterFields = [
|
|
15
|
+
'name', 'category', 'description', 'difficulty',
|
|
16
|
+
'tags', 'applicable_scenarios', 'author',
|
|
17
|
+
'created_at', 'updated_at', 'version'
|
|
18
|
+
];
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Validates a template directory
|
|
23
|
+
*
|
|
24
|
+
* @param {string} templatePath - Path to template directory
|
|
25
|
+
* @returns {Promise<Object>} Validation result
|
|
26
|
+
*/
|
|
27
|
+
async validateTemplate(templatePath) {
|
|
28
|
+
const result = {
|
|
29
|
+
valid: true,
|
|
30
|
+
errors: [],
|
|
31
|
+
warnings: []
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
// Check if directory exists
|
|
35
|
+
if (!await fs.pathExists(templatePath)) {
|
|
36
|
+
result.valid = false;
|
|
37
|
+
result.errors.push('Template directory does not exist');
|
|
38
|
+
return result;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Validate file structure
|
|
42
|
+
const structureResult = await this.validateStructure(templatePath);
|
|
43
|
+
result.errors.push(...structureResult.errors);
|
|
44
|
+
result.warnings.push(...structureResult.warnings);
|
|
45
|
+
|
|
46
|
+
if (structureResult.errors.length > 0) {
|
|
47
|
+
result.valid = false;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Validate frontmatter in each file
|
|
51
|
+
for (const file of this.requiredFiles) {
|
|
52
|
+
const filePath = path.join(templatePath, file);
|
|
53
|
+
|
|
54
|
+
if (await fs.pathExists(filePath)) {
|
|
55
|
+
const content = await fs.readFile(filePath, 'utf8');
|
|
56
|
+
const frontmatterResult = this.validateFrontmatter(content, file);
|
|
57
|
+
|
|
58
|
+
result.errors.push(...frontmatterResult.errors);
|
|
59
|
+
result.warnings.push(...frontmatterResult.warnings);
|
|
60
|
+
|
|
61
|
+
if (frontmatterResult.errors.length > 0) {
|
|
62
|
+
result.valid = false;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return result;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Validates template file structure
|
|
72
|
+
*
|
|
73
|
+
* @param {string} templatePath - Path to template directory
|
|
74
|
+
* @returns {Promise<Object>} Validation result
|
|
75
|
+
*/
|
|
76
|
+
async validateStructure(templatePath) {
|
|
77
|
+
const result = {
|
|
78
|
+
errors: [],
|
|
79
|
+
warnings: []
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
// Check for required files
|
|
83
|
+
for (const file of this.requiredFiles) {
|
|
84
|
+
const filePath = path.join(templatePath, file);
|
|
85
|
+
|
|
86
|
+
if (!await fs.pathExists(filePath)) {
|
|
87
|
+
result.errors.push(`Missing required file: ${file}`);
|
|
88
|
+
} else {
|
|
89
|
+
// Validate file content structure
|
|
90
|
+
const content = await fs.readFile(filePath, 'utf8');
|
|
91
|
+
const contentResult = this.validateContent(content, file);
|
|
92
|
+
result.errors.push(...contentResult.errors);
|
|
93
|
+
result.warnings.push(...contentResult.warnings);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return result;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Validates Spec document content structure
|
|
102
|
+
*
|
|
103
|
+
* @param {string} content - File content
|
|
104
|
+
* @param {string} filename - File name
|
|
105
|
+
* @returns {Object} Validation result
|
|
106
|
+
*/
|
|
107
|
+
validateContent(content, filename) {
|
|
108
|
+
const result = {
|
|
109
|
+
errors: [],
|
|
110
|
+
warnings: []
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
// Normalize line endings and remove frontmatter for content validation
|
|
114
|
+
const normalizedContent = content.replace(/\r\n/g, '\n');
|
|
115
|
+
const contentWithoutFrontmatter = normalizedContent.replace(/^---\n[\s\S]*?\n---\n/, '');
|
|
116
|
+
|
|
117
|
+
// Validate based on file type
|
|
118
|
+
if (filename === 'requirements.md') {
|
|
119
|
+
this._validateRequirementsStructure(contentWithoutFrontmatter, result);
|
|
120
|
+
} else if (filename === 'design.md') {
|
|
121
|
+
this._validateDesignStructure(contentWithoutFrontmatter, result);
|
|
122
|
+
} else if (filename === 'tasks.md') {
|
|
123
|
+
this._validateTasksStructure(contentWithoutFrontmatter, result);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return result;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Validates requirements.md structure
|
|
131
|
+
*
|
|
132
|
+
* @param {string} content - Content without frontmatter
|
|
133
|
+
* @param {Object} result - Result object to populate
|
|
134
|
+
* @private
|
|
135
|
+
*/
|
|
136
|
+
_validateRequirementsStructure(content, result) {
|
|
137
|
+
const requiredSections = [
|
|
138
|
+
'# Requirements Document',
|
|
139
|
+
'## Introduction',
|
|
140
|
+
'## Glossary'
|
|
141
|
+
];
|
|
142
|
+
|
|
143
|
+
for (const section of requiredSections) {
|
|
144
|
+
if (!content.includes(section)) {
|
|
145
|
+
result.warnings.push(`requirements.md: Missing section "${section}"`);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Check for at least one requirement
|
|
150
|
+
if (!content.includes('### Requirement')) {
|
|
151
|
+
result.warnings.push('requirements.md: No requirements found');
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Validates design.md structure
|
|
157
|
+
*
|
|
158
|
+
* @param {string} content - Content without frontmatter
|
|
159
|
+
* @param {Object} result - Result object to populate
|
|
160
|
+
* @private
|
|
161
|
+
*/
|
|
162
|
+
_validateDesignStructure(content, result) {
|
|
163
|
+
const requiredSections = [
|
|
164
|
+
'# Design Document',
|
|
165
|
+
'## Overview',
|
|
166
|
+
'## Architecture'
|
|
167
|
+
];
|
|
168
|
+
|
|
169
|
+
for (const section of requiredSections) {
|
|
170
|
+
if (!content.includes(section)) {
|
|
171
|
+
result.warnings.push(`design.md: Missing section "${section}"`);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Validates tasks.md structure
|
|
178
|
+
*
|
|
179
|
+
* @param {string} content - Content without frontmatter
|
|
180
|
+
* @param {Object} result - Result object to populate
|
|
181
|
+
* @private
|
|
182
|
+
*/
|
|
183
|
+
_validateTasksStructure(content, result) {
|
|
184
|
+
const requiredSections = [
|
|
185
|
+
'# Implementation Plan',
|
|
186
|
+
'## Overview',
|
|
187
|
+
'## Tasks'
|
|
188
|
+
];
|
|
189
|
+
|
|
190
|
+
for (const section of requiredSections) {
|
|
191
|
+
if (!content.includes(section)) {
|
|
192
|
+
result.warnings.push(`tasks.md: Missing section "${section}"`);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// Check for at least one task
|
|
197
|
+
if (!content.match(/^- \[ \]/m)) {
|
|
198
|
+
result.warnings.push('tasks.md: No tasks found');
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Validates YAML frontmatter
|
|
204
|
+
*
|
|
205
|
+
* @param {string} content - File content
|
|
206
|
+
* @param {string} filename - File name (for error messages)
|
|
207
|
+
* @returns {Object} Validation result
|
|
208
|
+
*/
|
|
209
|
+
validateFrontmatter(content, filename = 'file') {
|
|
210
|
+
const result = {
|
|
211
|
+
errors: [],
|
|
212
|
+
warnings: []
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
// Extract frontmatter
|
|
216
|
+
const frontmatter = this.extractFrontmatter(content);
|
|
217
|
+
|
|
218
|
+
if (!frontmatter) {
|
|
219
|
+
result.errors.push(`${filename}: Missing YAML frontmatter`);
|
|
220
|
+
return result;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// Parse YAML
|
|
224
|
+
let metadata;
|
|
225
|
+
try {
|
|
226
|
+
metadata = this.parseYaml(frontmatter);
|
|
227
|
+
} catch (error) {
|
|
228
|
+
result.errors.push(`${filename}: Invalid YAML syntax - ${error.message}`);
|
|
229
|
+
return result;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// Validate required fields
|
|
233
|
+
for (const field of this.requiredFrontmatterFields) {
|
|
234
|
+
if (!metadata[field]) {
|
|
235
|
+
result.errors.push(`${filename}: Missing required field "${field}"`);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// Validate field types
|
|
240
|
+
if (metadata.tags && !Array.isArray(metadata.tags)) {
|
|
241
|
+
result.errors.push(`${filename}: Field "tags" must be an array`);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
if (metadata.applicable_scenarios && !Array.isArray(metadata.applicable_scenarios)) {
|
|
245
|
+
result.errors.push(`${filename}: Field "applicable_scenarios" must be an array`);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// Validate difficulty
|
|
249
|
+
const validDifficulties = ['beginner', 'intermediate', 'advanced'];
|
|
250
|
+
if (metadata.difficulty && !validDifficulties.includes(metadata.difficulty)) {
|
|
251
|
+
result.errors.push(`${filename}: Invalid difficulty "${metadata.difficulty}"`);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
return result;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Extracts YAML frontmatter from content
|
|
259
|
+
*
|
|
260
|
+
* @param {string} content - File content
|
|
261
|
+
* @returns {string|null} Frontmatter content or null
|
|
262
|
+
*/
|
|
263
|
+
extractFrontmatter(content) {
|
|
264
|
+
// Normalize line endings to \n for consistent matching
|
|
265
|
+
const normalizedContent = content.replace(/\r\n/g, '\n');
|
|
266
|
+
const match = normalizedContent.match(/^---\n([\s\S]*?)\n---/);
|
|
267
|
+
return match ? match[1] : null;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Parses YAML content (simple implementation)
|
|
272
|
+
*
|
|
273
|
+
* @param {string} yaml - YAML content
|
|
274
|
+
* @returns {Object} Parsed object
|
|
275
|
+
*/
|
|
276
|
+
parseYaml(yaml) {
|
|
277
|
+
const result = {};
|
|
278
|
+
const lines = yaml.split('\n');
|
|
279
|
+
let currentKey = null;
|
|
280
|
+
let currentArray = null;
|
|
281
|
+
|
|
282
|
+
for (const line of lines) {
|
|
283
|
+
const trimmed = line.trim();
|
|
284
|
+
|
|
285
|
+
if (!trimmed || trimmed.startsWith('#')) {
|
|
286
|
+
continue;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// Array item
|
|
290
|
+
if (trimmed.startsWith('- ')) {
|
|
291
|
+
if (currentArray) {
|
|
292
|
+
currentArray.push(trimmed.substring(2).trim());
|
|
293
|
+
}
|
|
294
|
+
continue;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// Key-value pair
|
|
298
|
+
const colonIndex = trimmed.indexOf(':');
|
|
299
|
+
if (colonIndex > 0) {
|
|
300
|
+
const key = trimmed.substring(0, colonIndex).trim();
|
|
301
|
+
let value = trimmed.substring(colonIndex + 1).trim();
|
|
302
|
+
|
|
303
|
+
if (value === '') {
|
|
304
|
+
// Start of array or empty value
|
|
305
|
+
currentKey = key;
|
|
306
|
+
currentArray = [];
|
|
307
|
+
result[key] = currentArray;
|
|
308
|
+
} else {
|
|
309
|
+
// Simple value - check if it's an inline array
|
|
310
|
+
if (value.startsWith('[') && value.endsWith(']')) {
|
|
311
|
+
// Inline array format: [item1, item2, item3]
|
|
312
|
+
const arrayContent = value.substring(1, value.length - 1);
|
|
313
|
+
result[key] = arrayContent.split(',').map(item => item.trim());
|
|
314
|
+
} else {
|
|
315
|
+
// Simple string value
|
|
316
|
+
result[key] = value;
|
|
317
|
+
}
|
|
318
|
+
currentKey = null;
|
|
319
|
+
currentArray = null;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
return result;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* Generates validation report
|
|
329
|
+
*
|
|
330
|
+
* @param {Object} validationResult - Validation result
|
|
331
|
+
* @returns {string} Formatted report
|
|
332
|
+
*/
|
|
333
|
+
generateValidationReport(validationResult) {
|
|
334
|
+
let report = '';
|
|
335
|
+
|
|
336
|
+
if (validationResult.valid) {
|
|
337
|
+
report += '✅ Template validation passed\n';
|
|
338
|
+
} else {
|
|
339
|
+
report += '❌ Template validation failed\n\n';
|
|
340
|
+
|
|
341
|
+
if (validationResult.errors.length > 0) {
|
|
342
|
+
report += 'Errors:\n';
|
|
343
|
+
validationResult.errors.forEach((error, index) => {
|
|
344
|
+
report += ` ${index + 1}. ${error}\n`;
|
|
345
|
+
});
|
|
346
|
+
report += '\n';
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
if (validationResult.warnings.length > 0) {
|
|
351
|
+
report += 'Warnings:\n';
|
|
352
|
+
validationResult.warnings.forEach((warning, index) => {
|
|
353
|
+
report += ` ${index + 1}. ${warning}\n`;
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
return report;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
module.exports = TemplateValidator;
|