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,328 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MetadataCollector - Collects template metadata through interactive prompts
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
const inquirer = require('inquirer');
|
|
6
|
+
const { execSync } = require('child_process');
|
|
7
|
+
|
|
8
|
+
class MetadataCollector {
|
|
9
|
+
constructor(options = {}) {
|
|
10
|
+
this.interactive = options.interactive !== false;
|
|
11
|
+
this.categories = [
|
|
12
|
+
'web-features',
|
|
13
|
+
'backend-features',
|
|
14
|
+
'infrastructure',
|
|
15
|
+
'testing',
|
|
16
|
+
'documentation',
|
|
17
|
+
'other'
|
|
18
|
+
];
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Collects all template metadata
|
|
23
|
+
* @param {Object} specMetadata - Extracted Spec metadata
|
|
24
|
+
* @param {boolean} interactive - Use interactive prompts
|
|
25
|
+
* @returns {Promise<Object>} Template metadata
|
|
26
|
+
*/
|
|
27
|
+
async collectMetadata(specMetadata, interactive = this.interactive) {
|
|
28
|
+
if (!interactive) {
|
|
29
|
+
return this.getDefaultMetadata(specMetadata);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const metadata = {};
|
|
33
|
+
|
|
34
|
+
// Template name
|
|
35
|
+
metadata.name = await this.promptTemplateName(specMetadata.specName);
|
|
36
|
+
|
|
37
|
+
// Description
|
|
38
|
+
metadata.description = await this.promptDescription();
|
|
39
|
+
|
|
40
|
+
// Category
|
|
41
|
+
metadata.category = await this.promptCategory();
|
|
42
|
+
|
|
43
|
+
// Tags
|
|
44
|
+
const suggestedTags = this.suggestTags({ 'requirements.md': '' });
|
|
45
|
+
metadata.tags = await this.promptTags(suggestedTags);
|
|
46
|
+
|
|
47
|
+
// Author
|
|
48
|
+
metadata.author = await this.promptAuthor(specMetadata.author);
|
|
49
|
+
|
|
50
|
+
// Version
|
|
51
|
+
metadata.version = await this.promptVersion();
|
|
52
|
+
|
|
53
|
+
// KSE version
|
|
54
|
+
metadata.kse_version = await this.promptKseVersion();
|
|
55
|
+
|
|
56
|
+
// Timestamps
|
|
57
|
+
const now = new Date().toISOString().split('T')[0];
|
|
58
|
+
metadata.created_at = now;
|
|
59
|
+
metadata.updated_at = now;
|
|
60
|
+
|
|
61
|
+
// Validate and confirm
|
|
62
|
+
const validation = this.validateMetadata(metadata);
|
|
63
|
+
if (!validation.valid) {
|
|
64
|
+
throw new Error(`Metadata validation failed: ${validation.errors.join(', ')}`);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
console.log('\n📋 Metadata Summary:');
|
|
68
|
+
console.log(JSON.stringify(metadata, null, 2));
|
|
69
|
+
|
|
70
|
+
const { confirmed } = await inquirer.prompt([
|
|
71
|
+
{
|
|
72
|
+
type: 'confirm',
|
|
73
|
+
name: 'confirmed',
|
|
74
|
+
message: 'Confirm metadata?',
|
|
75
|
+
default: true
|
|
76
|
+
}
|
|
77
|
+
]);
|
|
78
|
+
|
|
79
|
+
if (!confirmed) {
|
|
80
|
+
throw new Error('Metadata collection cancelled by user');
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return metadata;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Prompts for template name
|
|
88
|
+
* @param {string} defaultName - Default name
|
|
89
|
+
* @returns {Promise<string>} Template name
|
|
90
|
+
*/
|
|
91
|
+
async promptTemplateName(defaultName) {
|
|
92
|
+
const { name } = await inquirer.prompt([
|
|
93
|
+
{
|
|
94
|
+
type: 'input',
|
|
95
|
+
name: 'name',
|
|
96
|
+
message: 'Template name (kebab-case):',
|
|
97
|
+
default: defaultName,
|
|
98
|
+
validate: (input) => {
|
|
99
|
+
if (!/^[a-z0-9]+(-[a-z0-9]+)*$/.test(input)) {
|
|
100
|
+
return 'Name must be in kebab-case format (lowercase, hyphens only)';
|
|
101
|
+
}
|
|
102
|
+
return true;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
]);
|
|
106
|
+
return name;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Prompts for description
|
|
111
|
+
* @returns {Promise<string>} Description
|
|
112
|
+
*/
|
|
113
|
+
async promptDescription() {
|
|
114
|
+
const { description } = await inquirer.prompt([
|
|
115
|
+
{
|
|
116
|
+
type: 'input',
|
|
117
|
+
name: 'description',
|
|
118
|
+
message: 'Brief description (1-2 sentences):',
|
|
119
|
+
validate: (input) => {
|
|
120
|
+
if (input.length < 10) {
|
|
121
|
+
return 'Description must be at least 10 characters';
|
|
122
|
+
}
|
|
123
|
+
if (input.length > 200) {
|
|
124
|
+
return 'Description must be less than 200 characters';
|
|
125
|
+
}
|
|
126
|
+
return true;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
]);
|
|
130
|
+
return description;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Prompts for category
|
|
135
|
+
* @returns {Promise<string>} Selected category
|
|
136
|
+
*/
|
|
137
|
+
async promptCategory() {
|
|
138
|
+
const { category } = await inquirer.prompt([
|
|
139
|
+
{
|
|
140
|
+
type: 'list',
|
|
141
|
+
name: 'category',
|
|
142
|
+
message: 'Select category:',
|
|
143
|
+
choices: this.categories
|
|
144
|
+
}
|
|
145
|
+
]);
|
|
146
|
+
return category;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Prompts for tags
|
|
151
|
+
* @param {Array} suggestedTags - Suggested tags
|
|
152
|
+
* @returns {Promise<Array>} Tags
|
|
153
|
+
*/
|
|
154
|
+
async promptTags(suggestedTags = []) {
|
|
155
|
+
const suggestionText = suggestedTags.length > 0
|
|
156
|
+
? ` (suggested: ${suggestedTags.join(', ')})`
|
|
157
|
+
: '';
|
|
158
|
+
|
|
159
|
+
const { tagsInput } = await inquirer.prompt([
|
|
160
|
+
{
|
|
161
|
+
type: 'input',
|
|
162
|
+
name: 'tagsInput',
|
|
163
|
+
message: `Tags (comma-separated)${suggestionText}:`,
|
|
164
|
+
default: suggestedTags.join(', ')
|
|
165
|
+
}
|
|
166
|
+
]);
|
|
167
|
+
|
|
168
|
+
return tagsInput
|
|
169
|
+
.split(',')
|
|
170
|
+
.map(tag => tag.trim().toLowerCase())
|
|
171
|
+
.filter(tag => tag.length > 0);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Prompts for author
|
|
176
|
+
* @param {string} defaultAuthor - Default author
|
|
177
|
+
* @returns {Promise<string>} Author name
|
|
178
|
+
*/
|
|
179
|
+
async promptAuthor(defaultAuthor) {
|
|
180
|
+
const { author } = await inquirer.prompt([
|
|
181
|
+
{
|
|
182
|
+
type: 'input',
|
|
183
|
+
name: 'author',
|
|
184
|
+
message: 'Author name:',
|
|
185
|
+
default: defaultAuthor || this.getGitUser()
|
|
186
|
+
}
|
|
187
|
+
]);
|
|
188
|
+
return author;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Prompts for version
|
|
193
|
+
* @returns {Promise<string>} Version
|
|
194
|
+
*/
|
|
195
|
+
async promptVersion() {
|
|
196
|
+
const { version } = await inquirer.prompt([
|
|
197
|
+
{
|
|
198
|
+
type: 'input',
|
|
199
|
+
name: 'version',
|
|
200
|
+
message: 'Template version:',
|
|
201
|
+
default: '1.0.0',
|
|
202
|
+
validate: (input) => {
|
|
203
|
+
if (!/^\d+\.\d+\.\d+$/.test(input)) {
|
|
204
|
+
return 'Version must follow semver format (e.g., 1.0.0)';
|
|
205
|
+
}
|
|
206
|
+
return true;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
]);
|
|
210
|
+
return version;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Prompts for KSE version
|
|
215
|
+
* @returns {Promise<string>} KSE version
|
|
216
|
+
*/
|
|
217
|
+
async promptKseVersion() {
|
|
218
|
+
const currentVersion = this.getCurrentKseVersion();
|
|
219
|
+
const { kseVersion } = await inquirer.prompt([
|
|
220
|
+
{
|
|
221
|
+
type: 'input',
|
|
222
|
+
name: 'kseVersion',
|
|
223
|
+
message: 'Minimum KSE version required:',
|
|
224
|
+
default: currentVersion
|
|
225
|
+
}
|
|
226
|
+
]);
|
|
227
|
+
return kseVersion;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Validates metadata completeness
|
|
232
|
+
* @param {Object} metadata - Collected metadata
|
|
233
|
+
* @returns {Object} Validation result
|
|
234
|
+
*/
|
|
235
|
+
validateMetadata(metadata) {
|
|
236
|
+
const errors = [];
|
|
237
|
+
const requiredFields = ['name', 'description', 'category', 'tags', 'author', 'version', 'kse_version'];
|
|
238
|
+
|
|
239
|
+
for (const field of requiredFields) {
|
|
240
|
+
if (!metadata[field]) {
|
|
241
|
+
errors.push(`Missing required field: ${field}`);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// Validate kebab-case name
|
|
246
|
+
if (metadata.name && !/^[a-z0-9]+(-[a-z0-9]+)*$/.test(metadata.name)) {
|
|
247
|
+
errors.push('Name must be in kebab-case format');
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// Validate semver version
|
|
251
|
+
if (metadata.version && !/^\d+\.\d+\.\d+$/.test(metadata.version)) {
|
|
252
|
+
errors.push('Version must follow semver format');
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// Validate category
|
|
256
|
+
if (metadata.category && !this.categories.includes(metadata.category)) {
|
|
257
|
+
errors.push(`Category must be one of: ${this.categories.join(', ')}`);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
return {
|
|
261
|
+
valid: errors.length === 0,
|
|
262
|
+
errors
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Suggests tags based on content analysis
|
|
268
|
+
* @param {Object} fileContents - Spec file contents
|
|
269
|
+
* @returns {Array} Suggested tags
|
|
270
|
+
*/
|
|
271
|
+
suggestTags(fileContents) {
|
|
272
|
+
const allContent = Object.values(fileContents).join(' ').toLowerCase();
|
|
273
|
+
const keywords = [
|
|
274
|
+
'api', 'rest', 'graphql', 'database', 'authentication', 'authorization',
|
|
275
|
+
'testing', 'deployment', 'ci/cd', 'monitoring', 'logging', 'caching',
|
|
276
|
+
'frontend', 'backend', 'cli', 'template', 'automation', 'integration'
|
|
277
|
+
];
|
|
278
|
+
|
|
279
|
+
return keywords.filter(keyword => allContent.includes(keyword)).slice(0, 5);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Gets default metadata (non-interactive mode)
|
|
284
|
+
* @param {Object} specMetadata - Spec metadata
|
|
285
|
+
* @returns {Object} Default metadata
|
|
286
|
+
*/
|
|
287
|
+
getDefaultMetadata(specMetadata) {
|
|
288
|
+
const now = new Date().toISOString().split('T')[0];
|
|
289
|
+
return {
|
|
290
|
+
name: specMetadata.specName,
|
|
291
|
+
description: `Template for ${specMetadata.specNameTitle}`,
|
|
292
|
+
category: 'other',
|
|
293
|
+
tags: [],
|
|
294
|
+
author: specMetadata.author || this.getGitUser(),
|
|
295
|
+
version: '1.0.0',
|
|
296
|
+
kse_version: this.getCurrentKseVersion(),
|
|
297
|
+
created_at: now,
|
|
298
|
+
updated_at: now
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* Gets git user name
|
|
304
|
+
* @returns {string} Git user name
|
|
305
|
+
*/
|
|
306
|
+
getGitUser() {
|
|
307
|
+
try {
|
|
308
|
+
return execSync('git config user.name', { encoding: 'utf-8' }).trim();
|
|
309
|
+
} catch {
|
|
310
|
+
return 'Unknown';
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Gets current KSE version
|
|
316
|
+
* @returns {string} KSE version
|
|
317
|
+
*/
|
|
318
|
+
getCurrentKseVersion() {
|
|
319
|
+
try {
|
|
320
|
+
const packageJson = require('../../package.json');
|
|
321
|
+
return packageJson.version;
|
|
322
|
+
} catch {
|
|
323
|
+
return '1.0.0';
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
module.exports = MetadataCollector;
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Path Utilities
|
|
3
|
+
*
|
|
4
|
+
* Platform-independent path handling utilities for template operations.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const path = require('path');
|
|
8
|
+
const os = require('os');
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Normalize path to use forward slashes and resolve home directory
|
|
12
|
+
* @param {string} filePath - Path to normalize
|
|
13
|
+
* @returns {string} Normalized path
|
|
14
|
+
*/
|
|
15
|
+
function normalize(filePath) {
|
|
16
|
+
if (!filePath) {
|
|
17
|
+
throw new Error('Path cannot be empty');
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Expand home directory
|
|
21
|
+
let normalized = expandHome(filePath);
|
|
22
|
+
|
|
23
|
+
// Convert to absolute path if relative
|
|
24
|
+
if (!path.isAbsolute(normalized)) {
|
|
25
|
+
normalized = path.resolve(normalized);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Convert backslashes to forward slashes
|
|
29
|
+
normalized = normalized.replace(/\\/g, '/');
|
|
30
|
+
|
|
31
|
+
return normalized;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Expand ~ to home directory
|
|
36
|
+
* @param {string} filePath - Path that may contain ~
|
|
37
|
+
* @returns {string} Path with ~ expanded
|
|
38
|
+
*/
|
|
39
|
+
function expandHome(filePath) {
|
|
40
|
+
if (!filePath) return filePath;
|
|
41
|
+
|
|
42
|
+
if (filePath === '~' || filePath.startsWith('~/') || filePath.startsWith('~\\')) {
|
|
43
|
+
return path.join(os.homedir(), filePath.slice(1));
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return filePath;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Get the default template cache directory
|
|
51
|
+
* @returns {string} Path to cache directory
|
|
52
|
+
*/
|
|
53
|
+
function getDefaultCacheDir() {
|
|
54
|
+
return normalize(path.join(os.homedir(), '.kse', 'templates'));
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Get the cache directory for a specific source
|
|
59
|
+
* @param {string} sourceName - Name of the template source
|
|
60
|
+
* @returns {string} Path to source cache directory
|
|
61
|
+
*/
|
|
62
|
+
function getSourceCacheDir(sourceName) {
|
|
63
|
+
return normalize(path.join(getDefaultCacheDir(), sourceName));
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Get the path to cache metadata file
|
|
68
|
+
* @returns {string} Path to metadata file
|
|
69
|
+
*/
|
|
70
|
+
function getCacheMetadataPath() {
|
|
71
|
+
return normalize(path.join(getDefaultCacheDir(), '.cache-metadata.json'));
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Get the path to sources configuration file
|
|
76
|
+
* @returns {string} Path to sources file
|
|
77
|
+
*/
|
|
78
|
+
function getSourcesConfigPath() {
|
|
79
|
+
return normalize(path.join(getDefaultCacheDir(), '.sources.json'));
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Join path segments using forward slashes
|
|
84
|
+
* @param {...string} segments - Path segments to join
|
|
85
|
+
* @returns {string} Joined path
|
|
86
|
+
*/
|
|
87
|
+
function join(...segments) {
|
|
88
|
+
return path.join(...segments).replace(/\\/g, '/');
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Get the directory name of a path
|
|
93
|
+
* @param {string} filePath - File path
|
|
94
|
+
* @returns {string} Directory name
|
|
95
|
+
*/
|
|
96
|
+
function dirname(filePath) {
|
|
97
|
+
return path.dirname(filePath).replace(/\\/g, '/');
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Get the base name of a path
|
|
102
|
+
* @param {string} filePath - File path
|
|
103
|
+
* @param {string} ext - Optional extension to remove
|
|
104
|
+
* @returns {string} Base name
|
|
105
|
+
*/
|
|
106
|
+
function basename(filePath, ext) {
|
|
107
|
+
return path.basename(filePath, ext);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Get the extension of a path
|
|
112
|
+
* @param {string} filePath - File path
|
|
113
|
+
* @returns {string} Extension (including dot)
|
|
114
|
+
*/
|
|
115
|
+
function extname(filePath) {
|
|
116
|
+
return path.extname(filePath);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Check if a path is within another path
|
|
121
|
+
* @param {string} child - Child path
|
|
122
|
+
* @param {string} parent - Parent path
|
|
123
|
+
* @returns {boolean} True if child is within parent
|
|
124
|
+
*/
|
|
125
|
+
function isWithin(child, parent) {
|
|
126
|
+
const childNorm = normalize(child);
|
|
127
|
+
const parentNorm = normalize(parent);
|
|
128
|
+
|
|
129
|
+
return childNorm.startsWith(parentNorm + '/') || childNorm === parentNorm;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
module.exports = {
|
|
133
|
+
normalize,
|
|
134
|
+
expandHome,
|
|
135
|
+
getDefaultCacheDir,
|
|
136
|
+
getSourceCacheDir,
|
|
137
|
+
getCacheMetadataPath,
|
|
138
|
+
getSourcesConfigPath,
|
|
139
|
+
join,
|
|
140
|
+
dirname,
|
|
141
|
+
basename,
|
|
142
|
+
extname,
|
|
143
|
+
isWithin
|
|
144
|
+
};
|