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,240 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workflows Command
|
|
3
|
+
*
|
|
4
|
+
* Lists and displays manual workflow documentation
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const chalk = require('chalk');
|
|
8
|
+
const fs = require('fs-extra');
|
|
9
|
+
const path = require('path');
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Available workflows
|
|
13
|
+
*/
|
|
14
|
+
const WORKFLOWS = {
|
|
15
|
+
'task-sync': {
|
|
16
|
+
name: 'Task Sync Workflow',
|
|
17
|
+
description: 'Keep workspace synchronized with task progress',
|
|
18
|
+
timeEstimate: '30-60 seconds',
|
|
19
|
+
file: 'manual-workflows-guide.md',
|
|
20
|
+
section: 'task-sync-workflow'
|
|
21
|
+
},
|
|
22
|
+
'context-export': {
|
|
23
|
+
name: 'Context Export Workflow',
|
|
24
|
+
description: 'Export spec context for sharing',
|
|
25
|
+
timeEstimate: '15-45 seconds',
|
|
26
|
+
file: 'manual-workflows-guide.md',
|
|
27
|
+
section: 'context-export-workflow'
|
|
28
|
+
},
|
|
29
|
+
'prompt-generation': {
|
|
30
|
+
name: 'Prompt Generation Workflow',
|
|
31
|
+
description: 'Generate AI prompts for specific tasks',
|
|
32
|
+
timeEstimate: '20-30 seconds',
|
|
33
|
+
file: 'manual-workflows-guide.md',
|
|
34
|
+
section: 'prompt-generation-workflow'
|
|
35
|
+
},
|
|
36
|
+
'daily': {
|
|
37
|
+
name: 'Daily Workflow Checklist',
|
|
38
|
+
description: 'Complete daily workflow checklist',
|
|
39
|
+
timeEstimate: '2-3 minutes',
|
|
40
|
+
file: 'manual-workflows-guide.md',
|
|
41
|
+
section: 'daily-workflow-checklist'
|
|
42
|
+
},
|
|
43
|
+
'task-completion': {
|
|
44
|
+
name: 'Task Completion Checklist',
|
|
45
|
+
description: 'Checklist for completing a task',
|
|
46
|
+
timeEstimate: 'Varies',
|
|
47
|
+
file: 'manual-workflows-guide.md',
|
|
48
|
+
section: 'task-completion-checklist'
|
|
49
|
+
},
|
|
50
|
+
'spec-creation': {
|
|
51
|
+
name: 'Spec Creation Checklist',
|
|
52
|
+
description: 'Checklist for creating a new spec',
|
|
53
|
+
timeEstimate: '10-15 minutes',
|
|
54
|
+
file: 'manual-workflows-guide.md',
|
|
55
|
+
section: 'spec-creation-checklist'
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* List all available workflows
|
|
61
|
+
*/
|
|
62
|
+
async function listWorkflows() {
|
|
63
|
+
console.log(chalk.blue('📋 Available Workflows'));
|
|
64
|
+
console.log();
|
|
65
|
+
|
|
66
|
+
Object.entries(WORKFLOWS).forEach(([id, workflow]) => {
|
|
67
|
+
console.log(chalk.cyan(` ${id}`));
|
|
68
|
+
console.log(` ${workflow.name}`);
|
|
69
|
+
console.log(chalk.gray(` ${workflow.description}`));
|
|
70
|
+
console.log(chalk.gray(` Time: ${workflow.timeEstimate}`));
|
|
71
|
+
console.log();
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
console.log(chalk.gray('Run'), chalk.cyan('kse workflows show <workflow-id>'), chalk.gray('to view details'));
|
|
75
|
+
console.log(chalk.gray('Run'), chalk.cyan('kse workflows guide'), chalk.gray('to open full guide'));
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Show specific workflow details
|
|
80
|
+
*
|
|
81
|
+
* @param {string} workflowId - Workflow ID
|
|
82
|
+
*/
|
|
83
|
+
async function showWorkflow(workflowId) {
|
|
84
|
+
const workflow = WORKFLOWS[workflowId];
|
|
85
|
+
|
|
86
|
+
if (!workflow) {
|
|
87
|
+
console.log(chalk.red('❌ Unknown workflow:'), workflowId);
|
|
88
|
+
console.log();
|
|
89
|
+
console.log(chalk.gray('Available workflows:'));
|
|
90
|
+
Object.keys(WORKFLOWS).forEach(id => {
|
|
91
|
+
console.log(chalk.gray(` - ${id}`));
|
|
92
|
+
});
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
console.log(chalk.blue('📋'), chalk.bold(workflow.name));
|
|
97
|
+
console.log();
|
|
98
|
+
console.log(chalk.gray('Description:'), workflow.description);
|
|
99
|
+
console.log(chalk.gray('Time Estimate:'), workflow.timeEstimate);
|
|
100
|
+
console.log();
|
|
101
|
+
|
|
102
|
+
// Try to read and display the workflow section
|
|
103
|
+
try {
|
|
104
|
+
const docsPath = path.join(__dirname, '../../docs', workflow.file);
|
|
105
|
+
|
|
106
|
+
if (await fs.pathExists(docsPath)) {
|
|
107
|
+
console.log(chalk.blue('📖 Full documentation:'));
|
|
108
|
+
console.log(chalk.cyan(` docs/${workflow.file}#${workflow.section}`));
|
|
109
|
+
console.log();
|
|
110
|
+
console.log(chalk.gray('Tip: Open the file in your editor for complete instructions'));
|
|
111
|
+
} else {
|
|
112
|
+
console.log(chalk.yellow('⚠️ Documentation file not found'));
|
|
113
|
+
console.log(chalk.gray(` Expected: docs/${workflow.file}`));
|
|
114
|
+
}
|
|
115
|
+
} catch (error) {
|
|
116
|
+
console.log(chalk.yellow('⚠️ Could not read documentation'));
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Open full workflows guide
|
|
122
|
+
*/
|
|
123
|
+
async function openGuide() {
|
|
124
|
+
const guidePath = path.join(__dirname, '../../docs/manual-workflows-guide.md');
|
|
125
|
+
|
|
126
|
+
try {
|
|
127
|
+
if (await fs.pathExists(guidePath)) {
|
|
128
|
+
console.log(chalk.blue('📖 Manual Workflows Guide'));
|
|
129
|
+
console.log();
|
|
130
|
+
console.log(chalk.cyan(' docs/manual-workflows-guide.md'));
|
|
131
|
+
console.log();
|
|
132
|
+
console.log(chalk.gray('Open this file in your editor for complete workflow documentation'));
|
|
133
|
+
console.log();
|
|
134
|
+
console.log(chalk.blue('Contents:'));
|
|
135
|
+
console.log(chalk.gray(' - Task Sync Workflow'));
|
|
136
|
+
console.log(chalk.gray(' - Context Export Workflow'));
|
|
137
|
+
console.log(chalk.gray(' - Prompt Generation Workflow'));
|
|
138
|
+
console.log(chalk.gray(' - Workflow Checklists'));
|
|
139
|
+
console.log(chalk.gray(' - Time Estimates'));
|
|
140
|
+
console.log(chalk.gray(' - Troubleshooting'));
|
|
141
|
+
} else {
|
|
142
|
+
console.log(chalk.red('❌ Guide not found:'), 'docs/manual-workflows-guide.md');
|
|
143
|
+
}
|
|
144
|
+
} catch (error) {
|
|
145
|
+
console.log(chalk.red('❌ Error:'), error.message);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Track workflow completion
|
|
151
|
+
*
|
|
152
|
+
* @param {string} workflowId - Workflow ID
|
|
153
|
+
*/
|
|
154
|
+
async function trackCompletion(workflowId) {
|
|
155
|
+
const workflow = WORKFLOWS[workflowId];
|
|
156
|
+
|
|
157
|
+
if (!workflow) {
|
|
158
|
+
console.log(chalk.red('❌ Unknown workflow:'), workflowId);
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
console.log(chalk.green('✅'), chalk.bold(`${workflow.name} completed!`));
|
|
163
|
+
console.log();
|
|
164
|
+
console.log(chalk.gray('Time estimate:'), workflow.timeEstimate);
|
|
165
|
+
console.log();
|
|
166
|
+
console.log(chalk.blue('💡 Next steps:'));
|
|
167
|
+
|
|
168
|
+
// Suggest next workflow based on current one
|
|
169
|
+
const suggestions = {
|
|
170
|
+
'task-sync': ['context-export', 'prompt-generation'],
|
|
171
|
+
'context-export': ['prompt-generation', 'task-completion'],
|
|
172
|
+
'prompt-generation': ['task-completion'],
|
|
173
|
+
'daily': ['task-sync', 'context-export'],
|
|
174
|
+
'task-completion': ['task-sync'],
|
|
175
|
+
'spec-creation': ['task-sync', 'prompt-generation']
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
const nextWorkflows = suggestions[workflowId] || [];
|
|
179
|
+
|
|
180
|
+
if (nextWorkflows.length > 0) {
|
|
181
|
+
nextWorkflows.forEach(nextId => {
|
|
182
|
+
const next = WORKFLOWS[nextId];
|
|
183
|
+
console.log(chalk.cyan(` kse workflows show ${nextId}`), chalk.gray(`- ${next.name}`));
|
|
184
|
+
});
|
|
185
|
+
} else {
|
|
186
|
+
console.log(chalk.gray(' Continue with your work!'));
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Main workflows command
|
|
192
|
+
*
|
|
193
|
+
* @param {string} action - Action to perform (list, show, guide, complete)
|
|
194
|
+
* @param {string} workflowId - Workflow ID (for show/complete actions)
|
|
195
|
+
*/
|
|
196
|
+
async function workflowsCommand(action = 'list', workflowId = null) {
|
|
197
|
+
try {
|
|
198
|
+
switch (action) {
|
|
199
|
+
case 'list':
|
|
200
|
+
await listWorkflows();
|
|
201
|
+
break;
|
|
202
|
+
|
|
203
|
+
case 'show':
|
|
204
|
+
if (!workflowId) {
|
|
205
|
+
console.log(chalk.red('❌ Workflow ID required'));
|
|
206
|
+
console.log(chalk.gray('Usage:'), chalk.cyan('kse workflows show <workflow-id>'));
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
await showWorkflow(workflowId);
|
|
210
|
+
break;
|
|
211
|
+
|
|
212
|
+
case 'guide':
|
|
213
|
+
await openGuide();
|
|
214
|
+
break;
|
|
215
|
+
|
|
216
|
+
case 'complete':
|
|
217
|
+
if (!workflowId) {
|
|
218
|
+
console.log(chalk.red('❌ Workflow ID required'));
|
|
219
|
+
console.log(chalk.gray('Usage:'), chalk.cyan('kse workflows complete <workflow-id>'));
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
await trackCompletion(workflowId);
|
|
223
|
+
break;
|
|
224
|
+
|
|
225
|
+
default:
|
|
226
|
+
console.log(chalk.red('❌ Unknown action:'), action);
|
|
227
|
+
console.log();
|
|
228
|
+
console.log(chalk.gray('Available actions:'));
|
|
229
|
+
console.log(chalk.gray(' - list: List all workflows'));
|
|
230
|
+
console.log(chalk.gray(' - show <id>: Show workflow details'));
|
|
231
|
+
console.log(chalk.gray(' - guide: Open full guide'));
|
|
232
|
+
console.log(chalk.gray(' - complete <id>: Mark workflow as complete'));
|
|
233
|
+
}
|
|
234
|
+
} catch (error) {
|
|
235
|
+
console.log(chalk.red('❌ Error:'), error.message);
|
|
236
|
+
process.exit(1);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
module.exports = workflowsCommand;
|
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Multi-Workspace Management Commands
|
|
3
|
+
*
|
|
4
|
+
* Implements CLI commands for managing multiple kse project workspaces.
|
|
5
|
+
* This is part of Spec 16-00: Multi-Workspace Management.
|
|
6
|
+
*
|
|
7
|
+
* Uses WorkspaceStateManager for atomic operations and single source of truth.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const chalk = require('chalk');
|
|
11
|
+
const path = require('path');
|
|
12
|
+
const WorkspaceStateManager = require('../workspace/multi/workspace-state-manager');
|
|
13
|
+
const fs = require('fs-extra');
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Create a new workspace
|
|
17
|
+
*
|
|
18
|
+
* Command: kse workspace create <name> [path]
|
|
19
|
+
*
|
|
20
|
+
* @param {string} name - Workspace name
|
|
21
|
+
* @param {Object} options - Command options
|
|
22
|
+
* @param {string} options.path - Optional workspace path (defaults to current directory)
|
|
23
|
+
* @returns {Promise<void>}
|
|
24
|
+
*/
|
|
25
|
+
async function createWorkspace(name, options = {}) {
|
|
26
|
+
const stateManager = new WorkspaceStateManager();
|
|
27
|
+
|
|
28
|
+
try {
|
|
29
|
+
// Use provided path or current directory
|
|
30
|
+
const workspacePath = options.path || process.cwd();
|
|
31
|
+
|
|
32
|
+
console.log(chalk.red('🔥') + ' Creating Workspace');
|
|
33
|
+
console.log();
|
|
34
|
+
console.log(`Name: ${chalk.cyan(name)}`);
|
|
35
|
+
console.log(`Path: ${chalk.gray(workspacePath)}`);
|
|
36
|
+
console.log();
|
|
37
|
+
|
|
38
|
+
// Create workspace (atomic operation)
|
|
39
|
+
const workspace = await stateManager.createWorkspace(name, workspacePath);
|
|
40
|
+
|
|
41
|
+
console.log(chalk.green('✅ Workspace created successfully'));
|
|
42
|
+
console.log();
|
|
43
|
+
console.log('Workspace Details:');
|
|
44
|
+
console.log(` Name: ${chalk.cyan(workspace.name)}`);
|
|
45
|
+
console.log(` Path: ${chalk.gray(workspace.path)}`);
|
|
46
|
+
console.log(` Created: ${chalk.gray(workspace.createdAt.toLocaleString())}`);
|
|
47
|
+
console.log();
|
|
48
|
+
console.log('Next steps:');
|
|
49
|
+
console.log(` ${chalk.cyan('kse workspace switch ' + name)} - Set as active workspace`);
|
|
50
|
+
console.log(` ${chalk.cyan('kse workspace list')} - View all workspaces`);
|
|
51
|
+
|
|
52
|
+
} catch (error) {
|
|
53
|
+
console.log(chalk.red('❌ Error:'), error.message);
|
|
54
|
+
process.exit(1);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* List all registered workspaces
|
|
60
|
+
*
|
|
61
|
+
* Command: kse workspace list
|
|
62
|
+
*
|
|
63
|
+
* @param {Object} options - Command options
|
|
64
|
+
* @returns {Promise<void>}
|
|
65
|
+
*/
|
|
66
|
+
async function listWorkspaces(options = {}) {
|
|
67
|
+
const stateManager = new WorkspaceStateManager();
|
|
68
|
+
|
|
69
|
+
try {
|
|
70
|
+
console.log(chalk.red('🔥') + ' Registered Workspaces');
|
|
71
|
+
console.log();
|
|
72
|
+
|
|
73
|
+
const workspaces = await stateManager.listWorkspaces();
|
|
74
|
+
const activeWorkspace = await stateManager.getActiveWorkspace();
|
|
75
|
+
const activeWorkspaceName = activeWorkspace ? activeWorkspace.name : null;
|
|
76
|
+
|
|
77
|
+
if (workspaces.length === 0) {
|
|
78
|
+
console.log(chalk.gray('No workspaces registered'));
|
|
79
|
+
console.log();
|
|
80
|
+
console.log('Create your first workspace:');
|
|
81
|
+
console.log(` ${chalk.cyan('kse workspace create <name>')}`);
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Sort by last accessed (most recent first)
|
|
86
|
+
workspaces.sort((a, b) => b.lastAccessed - a.lastAccessed);
|
|
87
|
+
|
|
88
|
+
console.log(`Found ${chalk.cyan(workspaces.length)} workspace(s):\n`);
|
|
89
|
+
|
|
90
|
+
for (const workspace of workspaces) {
|
|
91
|
+
const isActive = workspace.name === activeWorkspaceName;
|
|
92
|
+
const indicator = isActive ? chalk.green('● ') : chalk.gray('○ ');
|
|
93
|
+
const nameDisplay = isActive ? chalk.green.bold(workspace.name) : chalk.cyan(workspace.name);
|
|
94
|
+
|
|
95
|
+
console.log(`${indicator}${nameDisplay}`);
|
|
96
|
+
console.log(` Path: ${chalk.gray(workspace.path)}`);
|
|
97
|
+
console.log(` Last accessed: ${chalk.gray(workspace.lastAccessed.toLocaleString())}`);
|
|
98
|
+
|
|
99
|
+
if (isActive) {
|
|
100
|
+
console.log(` ${chalk.green('(Active)')}`);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
console.log();
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
console.log('Commands:');
|
|
107
|
+
console.log(` ${chalk.cyan('kse workspace switch <name>')} - Switch to a workspace`);
|
|
108
|
+
console.log(` ${chalk.cyan('kse workspace info <name>')} - View workspace details`);
|
|
109
|
+
|
|
110
|
+
} catch (error) {
|
|
111
|
+
console.log(chalk.red('❌ Error:'), error.message);
|
|
112
|
+
process.exit(1);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Switch to a different workspace
|
|
118
|
+
*
|
|
119
|
+
* Command: kse workspace switch <name>
|
|
120
|
+
*
|
|
121
|
+
* @param {string} name - Workspace name
|
|
122
|
+
* @param {Object} options - Command options
|
|
123
|
+
* @returns {Promise<void>}
|
|
124
|
+
*/
|
|
125
|
+
async function switchWorkspace(name, options = {}) {
|
|
126
|
+
const stateManager = new WorkspaceStateManager();
|
|
127
|
+
|
|
128
|
+
try {
|
|
129
|
+
console.log(chalk.red('🔥') + ' Switching Workspace');
|
|
130
|
+
console.log();
|
|
131
|
+
|
|
132
|
+
// Switch workspace (atomic operation - updates active + timestamp)
|
|
133
|
+
await stateManager.switchWorkspace(name);
|
|
134
|
+
|
|
135
|
+
const workspace = await stateManager.getWorkspace(name);
|
|
136
|
+
|
|
137
|
+
console.log(chalk.green('✅ Switched to workspace:'), chalk.cyan(name));
|
|
138
|
+
console.log();
|
|
139
|
+
console.log('Workspace Details:');
|
|
140
|
+
console.log(` Path: ${chalk.gray(workspace.path)}`);
|
|
141
|
+
console.log(` Last accessed: ${chalk.gray(workspace.lastAccessed.toLocaleString())}`);
|
|
142
|
+
console.log();
|
|
143
|
+
console.log('All kse commands will now use this workspace by default.');
|
|
144
|
+
|
|
145
|
+
} catch (error) {
|
|
146
|
+
console.log(chalk.red('❌ Error:'), error.message);
|
|
147
|
+
process.exit(1);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Remove a workspace from the registry
|
|
153
|
+
*
|
|
154
|
+
* Command: kse workspace remove <name>
|
|
155
|
+
*
|
|
156
|
+
* @param {string} name - Workspace name
|
|
157
|
+
* @param {Object} options - Command options
|
|
158
|
+
* @param {boolean} options.force - Skip confirmation prompt
|
|
159
|
+
* @returns {Promise<void>}
|
|
160
|
+
*/
|
|
161
|
+
async function removeWorkspace(name, options = {}) {
|
|
162
|
+
const stateManager = new WorkspaceStateManager();
|
|
163
|
+
|
|
164
|
+
try {
|
|
165
|
+
console.log(chalk.red('🔥') + ' Removing Workspace');
|
|
166
|
+
console.log();
|
|
167
|
+
|
|
168
|
+
// Check if workspace exists
|
|
169
|
+
const workspace = await stateManager.getWorkspace(name);
|
|
170
|
+
if (!workspace) {
|
|
171
|
+
const available = await stateManager.listWorkspaces();
|
|
172
|
+
const availableNames = available.map(ws => ws.name);
|
|
173
|
+
|
|
174
|
+
console.log(chalk.red('❌ Workspace not found:'), name);
|
|
175
|
+
console.log();
|
|
176
|
+
if (availableNames.length > 0) {
|
|
177
|
+
console.log('Available workspaces:', availableNames.join(', '));
|
|
178
|
+
} else {
|
|
179
|
+
console.log('No workspaces registered.');
|
|
180
|
+
}
|
|
181
|
+
process.exit(1);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
console.log(`Workspace: ${chalk.cyan(name)}`);
|
|
185
|
+
console.log(`Path: ${chalk.gray(workspace.path)}`);
|
|
186
|
+
console.log();
|
|
187
|
+
|
|
188
|
+
// Require confirmation unless --force
|
|
189
|
+
if (!options.force) {
|
|
190
|
+
console.log(chalk.yellow('⚠️ Warning: This will remove the workspace from the registry.'));
|
|
191
|
+
console.log(chalk.yellow(' Files in the workspace directory will NOT be deleted.'));
|
|
192
|
+
console.log();
|
|
193
|
+
console.log('To confirm, run:');
|
|
194
|
+
console.log(` ${chalk.cyan('kse workspace remove ' + name + ' --force')}`);
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// Check if it's the active workspace
|
|
199
|
+
const activeWorkspace = await stateManager.getActiveWorkspace();
|
|
200
|
+
const isActive = activeWorkspace && name === activeWorkspace.name;
|
|
201
|
+
|
|
202
|
+
// Remove workspace (atomic operation - removes + clears active if needed)
|
|
203
|
+
await stateManager.removeWorkspace(name);
|
|
204
|
+
|
|
205
|
+
console.log(chalk.green('✅ Workspace removed:'), chalk.cyan(name));
|
|
206
|
+
console.log();
|
|
207
|
+
console.log('The workspace directory and its files have been preserved.');
|
|
208
|
+
|
|
209
|
+
if (isActive) {
|
|
210
|
+
console.log();
|
|
211
|
+
console.log(chalk.yellow('Note: This was your active workspace.'));
|
|
212
|
+
console.log('Set a new active workspace:');
|
|
213
|
+
console.log(` ${chalk.cyan('kse workspace switch <name>')}`);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
} catch (error) {
|
|
217
|
+
console.log(chalk.red('❌ Error:'), error.message);
|
|
218
|
+
process.exit(1);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Display detailed information about a workspace
|
|
224
|
+
*
|
|
225
|
+
* Command: kse workspace info [name]
|
|
226
|
+
*
|
|
227
|
+
* @param {string|null} name - Workspace name (optional, defaults to active workspace)
|
|
228
|
+
* @param {Object} options - Command options
|
|
229
|
+
* @returns {Promise<void>}
|
|
230
|
+
*/
|
|
231
|
+
async function infoWorkspace(name = null, options = {}) {
|
|
232
|
+
const stateManager = new WorkspaceStateManager();
|
|
233
|
+
|
|
234
|
+
try {
|
|
235
|
+
console.log(chalk.red('🔥') + ' Workspace Information');
|
|
236
|
+
console.log();
|
|
237
|
+
|
|
238
|
+
let workspace;
|
|
239
|
+
|
|
240
|
+
// If no name provided, use active workspace
|
|
241
|
+
if (!name) {
|
|
242
|
+
workspace = await stateManager.getActiveWorkspace();
|
|
243
|
+
|
|
244
|
+
if (!workspace) {
|
|
245
|
+
console.log(chalk.yellow('⚠️ No active workspace set'));
|
|
246
|
+
console.log();
|
|
247
|
+
console.log('Set an active workspace:');
|
|
248
|
+
console.log(` ${chalk.cyan('kse workspace switch <name>')}`);
|
|
249
|
+
console.log();
|
|
250
|
+
console.log('Or specify a workspace name:');
|
|
251
|
+
console.log(` ${chalk.cyan('kse workspace info <name>')}`);
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
} else {
|
|
255
|
+
workspace = await stateManager.getWorkspace(name);
|
|
256
|
+
|
|
257
|
+
if (!workspace) {
|
|
258
|
+
const available = await stateManager.listWorkspaces();
|
|
259
|
+
const availableNames = available.map(ws => ws.name);
|
|
260
|
+
|
|
261
|
+
console.log(chalk.red('❌ Workspace not found:'), name);
|
|
262
|
+
console.log();
|
|
263
|
+
if (availableNames.length > 0) {
|
|
264
|
+
console.log('Available workspaces:', availableNames.join(', '));
|
|
265
|
+
}
|
|
266
|
+
process.exit(1);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// Check if it's the active workspace
|
|
271
|
+
const activeWorkspace = await stateManager.getActiveWorkspace();
|
|
272
|
+
const isActive = activeWorkspace && workspace.name === activeWorkspace.name;
|
|
273
|
+
|
|
274
|
+
// Count Specs in workspace
|
|
275
|
+
let specCount = 0;
|
|
276
|
+
try {
|
|
277
|
+
const specsPath = path.join(workspace.getPlatformPath(), '.kiro', 'specs');
|
|
278
|
+
const exists = await fs.pathExists(specsPath);
|
|
279
|
+
|
|
280
|
+
if (exists) {
|
|
281
|
+
const entries = await fs.readdir(specsPath);
|
|
282
|
+
// Count directories (each Spec is a directory)
|
|
283
|
+
for (const entry of entries) {
|
|
284
|
+
const entryPath = path.join(specsPath, entry);
|
|
285
|
+
const stats = await fs.stat(entryPath);
|
|
286
|
+
if (stats.isDirectory()) {
|
|
287
|
+
specCount++;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
} catch (error) {
|
|
292
|
+
// Ignore errors counting Specs
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// Display information
|
|
296
|
+
console.log(`Name: ${chalk.cyan.bold(workspace.name)}`);
|
|
297
|
+
if (isActive) {
|
|
298
|
+
console.log(`Status: ${chalk.green('Active')}`);
|
|
299
|
+
}
|
|
300
|
+
console.log();
|
|
301
|
+
console.log('Details:');
|
|
302
|
+
console.log(` Path: ${chalk.gray(workspace.path)}`);
|
|
303
|
+
console.log(` Created: ${chalk.gray(workspace.createdAt.toLocaleString())}`);
|
|
304
|
+
console.log(` Last accessed: ${chalk.gray(workspace.lastAccessed.toLocaleString())}`);
|
|
305
|
+
console.log(` Specs: ${chalk.cyan(specCount)}`);
|
|
306
|
+
console.log();
|
|
307
|
+
|
|
308
|
+
if (!isActive) {
|
|
309
|
+
console.log('Switch to this workspace:');
|
|
310
|
+
console.log(` ${chalk.cyan('kse workspace switch ' + workspace.name)}`);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
} catch (error) {
|
|
314
|
+
console.log(chalk.red('❌ Error:'), error.message);
|
|
315
|
+
process.exit(1);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
module.exports = {
|
|
320
|
+
createWorkspace,
|
|
321
|
+
listWorkspaces,
|
|
322
|
+
switchWorkspace,
|
|
323
|
+
removeWorkspace,
|
|
324
|
+
infoWorkspace
|
|
325
|
+
};
|