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,470 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Smart Adoption Orchestrator
|
|
3
|
+
*
|
|
4
|
+
* Coordinates the entire adoption process without user interaction.
|
|
5
|
+
* Implements zero-question, smart decision-making with mandatory backups.
|
|
6
|
+
*
|
|
7
|
+
* Core Philosophy:
|
|
8
|
+
* - Zero user interaction by default
|
|
9
|
+
* - Smart automatic decisions
|
|
10
|
+
* - Safety first (mandatory backups)
|
|
11
|
+
* - Clear progress feedback
|
|
12
|
+
* - Easy rollback
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
const chalk = require('chalk');
|
|
16
|
+
const path = require('path');
|
|
17
|
+
const DetectionEngine = require('./detection-engine');
|
|
18
|
+
const { getAdoptionStrategy } = require('./adoption-strategy');
|
|
19
|
+
const BackupManager = require('./backup-manager');
|
|
20
|
+
const VersionManager = require('../version/version-manager');
|
|
21
|
+
const StrategySelector = require('./strategy-selector');
|
|
22
|
+
const ProgressReporter = require('./progress-reporter');
|
|
23
|
+
const SummaryGenerator = require('./summary-generator');
|
|
24
|
+
const ErrorFormatter = require('./error-formatter');
|
|
25
|
+
const GitignoreIntegration = require('../gitignore/gitignore-integration');
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Smart Adoption Orchestrator
|
|
29
|
+
* Main coordinator for zero-interaction adoption
|
|
30
|
+
*/
|
|
31
|
+
class SmartOrchestrator {
|
|
32
|
+
constructor(dependencies = {}) {
|
|
33
|
+
// Support dependency injection for testing
|
|
34
|
+
this.detectionEngine = dependencies.detectionEngine || new DetectionEngine();
|
|
35
|
+
this.versionManager = dependencies.versionManager || new VersionManager();
|
|
36
|
+
this.backupManager = dependencies.backupManager || new BackupManager();
|
|
37
|
+
this.strategySelector = dependencies.strategySelector || new StrategySelector({
|
|
38
|
+
versionManager: this.versionManager
|
|
39
|
+
});
|
|
40
|
+
this.progressReporter = null; // Will be initialized in orchestrate()
|
|
41
|
+
// Note: SummaryGenerator and ErrorFormatter are used as utilities, not stored as instance properties
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Main orchestration method - coordinates entire adoption process
|
|
46
|
+
*
|
|
47
|
+
* @param {string} projectPath - Absolute path to project root
|
|
48
|
+
* @param {Object} options - Orchestration options
|
|
49
|
+
* @param {boolean} options.dryRun - Preview without executing
|
|
50
|
+
* @param {boolean} options.verbose - Show detailed logs
|
|
51
|
+
* @param {boolean} options.skipBackup - Skip backup (dangerous, not recommended)
|
|
52
|
+
* @param {boolean} options.skipUpdate - Skip template updates
|
|
53
|
+
* @returns {Promise<OrchestrationResult>}
|
|
54
|
+
*/
|
|
55
|
+
async orchestrate(projectPath, options = {}) {
|
|
56
|
+
const {
|
|
57
|
+
dryRun = false,
|
|
58
|
+
verbose = false,
|
|
59
|
+
skipBackup = false,
|
|
60
|
+
skipUpdate = false
|
|
61
|
+
} = options;
|
|
62
|
+
|
|
63
|
+
// Initialize progress reporter with options
|
|
64
|
+
this.progressReporter = new ProgressReporter({ verbose, quiet: false });
|
|
65
|
+
this.progressReporter.start();
|
|
66
|
+
|
|
67
|
+
const result = {
|
|
68
|
+
success: false,
|
|
69
|
+
mode: null,
|
|
70
|
+
backup: null,
|
|
71
|
+
changes: {
|
|
72
|
+
updated: [],
|
|
73
|
+
created: [],
|
|
74
|
+
deleted: [],
|
|
75
|
+
preserved: []
|
|
76
|
+
},
|
|
77
|
+
errors: [],
|
|
78
|
+
warnings: [],
|
|
79
|
+
summary: null
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
try {
|
|
83
|
+
// Stage 1: Analyze project
|
|
84
|
+
this.progressReporter.reportStage('Analyzing project structure', 'in-progress');
|
|
85
|
+
const detection = await this.detectionEngine.analyze(projectPath);
|
|
86
|
+
this.progressReporter.reportStage('Analyzing project structure', 'complete');
|
|
87
|
+
|
|
88
|
+
// Stage 2: Select strategy using StrategySelector
|
|
89
|
+
this.progressReporter.reportStage('Creating adoption plan', 'in-progress');
|
|
90
|
+
const projectState = await this.strategySelector.detectProjectState(projectPath);
|
|
91
|
+
const mode = this.strategySelector.selectMode(projectState);
|
|
92
|
+
result.mode = mode;
|
|
93
|
+
|
|
94
|
+
// Check if adoption is needed
|
|
95
|
+
if (mode === 'skip') {
|
|
96
|
+
this.progressReporter.reportStage('Creating adoption plan', 'complete');
|
|
97
|
+
result.success = true;
|
|
98
|
+
result.warnings.push('Already at latest version - no action needed');
|
|
99
|
+
this.progressReporter.reportInfo('Already at latest version - no action needed');
|
|
100
|
+
this.progressReporter.end();
|
|
101
|
+
return result;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Classify files and determine actions
|
|
105
|
+
const plan = await this._createAdoptionPlan(projectPath, detection, mode);
|
|
106
|
+
this.progressReporter.reportStage('Creating adoption plan', 'complete');
|
|
107
|
+
|
|
108
|
+
// Display plan using progress reporter
|
|
109
|
+
this.progressReporter.displayPlan(plan);
|
|
110
|
+
|
|
111
|
+
// Dry run mode - stop here
|
|
112
|
+
if (dryRun) {
|
|
113
|
+
result.success = true;
|
|
114
|
+
result.changes = plan.changes;
|
|
115
|
+
result.warnings.push('Dry run - no changes made');
|
|
116
|
+
this.progressReporter.reportWarning('Dry run mode - no changes made');
|
|
117
|
+
this.progressReporter.end();
|
|
118
|
+
return result;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Stage 3: Create mandatory backup
|
|
122
|
+
if (!skipBackup && plan.requiresBackup) {
|
|
123
|
+
this.progressReporter.reportStage('Creating backup', 'in-progress');
|
|
124
|
+
|
|
125
|
+
try {
|
|
126
|
+
const backup = await this.backupManager.createMandatoryBackup(
|
|
127
|
+
projectPath,
|
|
128
|
+
plan.filesToModify,
|
|
129
|
+
{ type: 'adopt-smart' }
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
result.backup = backup;
|
|
133
|
+
this.progressReporter.reportStage('Creating backup', 'complete', backup.id);
|
|
134
|
+
|
|
135
|
+
// Report backup details
|
|
136
|
+
this.progressReporter.reportBackup(backup);
|
|
137
|
+
|
|
138
|
+
// Backup validation is now done inside createMandatoryBackup
|
|
139
|
+
this.progressReporter.reportValidation({
|
|
140
|
+
success: true,
|
|
141
|
+
filesVerified: backup.validationDetails.filesVerified
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
} catch (backupError) {
|
|
145
|
+
this.progressReporter.reportStage('Creating backup', 'error');
|
|
146
|
+
// Add simple error message for result
|
|
147
|
+
result.errors.push(`Backup failed: ${backupError.message}`);
|
|
148
|
+
result.errors.push('Aborting adoption for safety');
|
|
149
|
+
// Display formatted error to user
|
|
150
|
+
const formattedError = ErrorFormatter.formatBackupError(backupError);
|
|
151
|
+
console.log(formattedError);
|
|
152
|
+
this.progressReporter.displayErrorSummary(result);
|
|
153
|
+
this.progressReporter.end();
|
|
154
|
+
return result;
|
|
155
|
+
}
|
|
156
|
+
} else if (skipBackup && plan.requiresBackup) {
|
|
157
|
+
result.warnings.push('⚠️ Backup skipped - changes cannot be undone!');
|
|
158
|
+
this.progressReporter.reportWarning('Backup skipped - changes cannot be undone!');
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Stage 5: Execute adoption
|
|
162
|
+
this.progressReporter.reportStage('Updating files', 'in-progress');
|
|
163
|
+
|
|
164
|
+
const adoptionResult = await this._executeAdoption(
|
|
165
|
+
projectPath,
|
|
166
|
+
mode,
|
|
167
|
+
plan,
|
|
168
|
+
skipUpdate
|
|
169
|
+
);
|
|
170
|
+
|
|
171
|
+
if (!adoptionResult.success) {
|
|
172
|
+
this.progressReporter.reportStage('Updating files', 'error');
|
|
173
|
+
result.errors.push(...adoptionResult.errors);
|
|
174
|
+
this.progressReporter.displayErrorSummary(result);
|
|
175
|
+
this.progressReporter.end();
|
|
176
|
+
return result;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Report file operations
|
|
180
|
+
adoptionResult.filesUpdated.forEach(file => {
|
|
181
|
+
this.progressReporter.reportFileOperation('update', file);
|
|
182
|
+
});
|
|
183
|
+
adoptionResult.filesCreated.forEach(file => {
|
|
184
|
+
this.progressReporter.reportFileOperation('create', file);
|
|
185
|
+
});
|
|
186
|
+
plan.filesToPreserve.forEach(file => {
|
|
187
|
+
this.progressReporter.reportFileOperation('preserve', file);
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
result.changes = {
|
|
191
|
+
updated: adoptionResult.filesUpdated,
|
|
192
|
+
created: adoptionResult.filesCreated,
|
|
193
|
+
deleted: [],
|
|
194
|
+
preserved: plan.filesToPreserve
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
this.progressReporter.reportStage('Updating files', 'complete');
|
|
198
|
+
|
|
199
|
+
// Stage 6: Finalize
|
|
200
|
+
this.progressReporter.reportStage('Finalizing adoption', 'in-progress');
|
|
201
|
+
|
|
202
|
+
// Update version info
|
|
203
|
+
if (!skipUpdate) {
|
|
204
|
+
await this._updateVersionInfo(projectPath, mode, detection);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
this.progressReporter.reportStage('Finalizing adoption', 'complete');
|
|
208
|
+
|
|
209
|
+
// Stage 7: Fix .gitignore for team collaboration
|
|
210
|
+
this.progressReporter.reportStage('Checking .gitignore configuration', 'in-progress');
|
|
211
|
+
|
|
212
|
+
try {
|
|
213
|
+
const gitignoreIntegration = new GitignoreIntegration();
|
|
214
|
+
const gitignoreResult = await gitignoreIntegration.integrateWithAdopt(projectPath);
|
|
215
|
+
|
|
216
|
+
if (gitignoreResult.success) {
|
|
217
|
+
if (gitignoreResult.action !== 'skipped') {
|
|
218
|
+
this.progressReporter.reportFileOperation(gitignoreResult.action, '.gitignore');
|
|
219
|
+
result.warnings.push(gitignoreResult.message);
|
|
220
|
+
}
|
|
221
|
+
} else {
|
|
222
|
+
// Don't block adoption on .gitignore fix failure
|
|
223
|
+
result.warnings.push(`⚠️ .gitignore fix failed: ${gitignoreResult.message}`);
|
|
224
|
+
result.warnings.push('You can fix this manually with: kse doctor --fix-gitignore');
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
this.progressReporter.reportStage('Checking .gitignore configuration', 'complete');
|
|
228
|
+
} catch (gitignoreError) {
|
|
229
|
+
// Don't block adoption on .gitignore fix failure
|
|
230
|
+
this.progressReporter.reportStage('Checking .gitignore configuration', 'error');
|
|
231
|
+
result.warnings.push(`⚠️ .gitignore check failed: ${gitignoreError.message}`);
|
|
232
|
+
result.warnings.push('You can fix this manually with: kse doctor --fix-gitignore');
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// Success!
|
|
236
|
+
result.success = true;
|
|
237
|
+
result.warnings.push(...adoptionResult.warnings);
|
|
238
|
+
|
|
239
|
+
// Display summary using progress reporter
|
|
240
|
+
this.progressReporter.displaySummary(result);
|
|
241
|
+
this.progressReporter.end();
|
|
242
|
+
|
|
243
|
+
return result;
|
|
244
|
+
|
|
245
|
+
} catch (error) {
|
|
246
|
+
result.errors.push(`Orchestration failed: ${error.message}`);
|
|
247
|
+
// Display formatted error to user
|
|
248
|
+
const formattedError = ErrorFormatter.formatOrchestrationError(error);
|
|
249
|
+
console.log(formattedError.message);
|
|
250
|
+
this.progressReporter.displayErrorSummary(result);
|
|
251
|
+
this.progressReporter.end();
|
|
252
|
+
return result;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Creates a detailed adoption plan
|
|
258
|
+
*
|
|
259
|
+
* @param {string} projectPath - Project path
|
|
260
|
+
* @param {DetectionResult} detection - Detection result
|
|
261
|
+
* @param {string} mode - Adoption mode
|
|
262
|
+
* @returns {Promise<AdoptionPlan>}
|
|
263
|
+
* @private
|
|
264
|
+
*/
|
|
265
|
+
async _createAdoptionPlan(projectPath, detection, mode) {
|
|
266
|
+
const plan = {
|
|
267
|
+
mode,
|
|
268
|
+
requiresBackup: false,
|
|
269
|
+
filesToModify: [],
|
|
270
|
+
filesToPreserve: [],
|
|
271
|
+
changes: {
|
|
272
|
+
updated: [],
|
|
273
|
+
created: [],
|
|
274
|
+
deleted: [],
|
|
275
|
+
preserved: []
|
|
276
|
+
}
|
|
277
|
+
};
|
|
278
|
+
|
|
279
|
+
// Define template files
|
|
280
|
+
const templateFiles = [
|
|
281
|
+
'steering/CORE_PRINCIPLES.md',
|
|
282
|
+
'steering/ENVIRONMENT.md',
|
|
283
|
+
'steering/RULES_GUIDE.md',
|
|
284
|
+
'tools/ultrawork_enhancer.py',
|
|
285
|
+
'README.md'
|
|
286
|
+
];
|
|
287
|
+
|
|
288
|
+
// Define files to always preserve
|
|
289
|
+
const preservePatterns = [
|
|
290
|
+
'specs/',
|
|
291
|
+
'steering/CURRENT_CONTEXT.md',
|
|
292
|
+
'backups/'
|
|
293
|
+
];
|
|
294
|
+
|
|
295
|
+
if (mode === 'fresh') {
|
|
296
|
+
// Fresh adoption - create everything
|
|
297
|
+
plan.changes.created = [
|
|
298
|
+
'.kiro/',
|
|
299
|
+
'.kiro/specs/',
|
|
300
|
+
'.kiro/steering/',
|
|
301
|
+
'.kiro/tools/',
|
|
302
|
+
'.kiro/backups/',
|
|
303
|
+
...templateFiles.map(f => `.kiro/${f}`),
|
|
304
|
+
'.kiro/version.json'
|
|
305
|
+
];
|
|
306
|
+
plan.requiresBackup = false;
|
|
307
|
+
|
|
308
|
+
} else if (mode === 'smart-adopt' || mode === 'smart-update') {
|
|
309
|
+
// Check which template files exist and differ
|
|
310
|
+
const kiroPath = path.join(projectPath, '.kiro');
|
|
311
|
+
|
|
312
|
+
for (const templateFile of templateFiles) {
|
|
313
|
+
const filePath = path.join(kiroPath, templateFile);
|
|
314
|
+
const fs = require('fs-extra');
|
|
315
|
+
|
|
316
|
+
if (await fs.pathExists(filePath)) {
|
|
317
|
+
// File exists - will be updated
|
|
318
|
+
plan.filesToModify.push(templateFile);
|
|
319
|
+
plan.changes.updated.push(`.kiro/${templateFile}`);
|
|
320
|
+
} else {
|
|
321
|
+
// File doesn't exist - will be created
|
|
322
|
+
plan.changes.created.push(`.kiro/${templateFile}`);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// Identify preserved files
|
|
327
|
+
if (detection.hasSpecs) {
|
|
328
|
+
plan.filesToPreserve.push('specs/');
|
|
329
|
+
plan.changes.preserved.push('specs/');
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
// Always preserve CURRENT_CONTEXT.md if it exists
|
|
333
|
+
const currentContextPath = path.join(kiroPath, 'steering/CURRENT_CONTEXT.md');
|
|
334
|
+
const fs = require('fs-extra');
|
|
335
|
+
if (await fs.pathExists(currentContextPath)) {
|
|
336
|
+
plan.filesToPreserve.push('steering/CURRENT_CONTEXT.md');
|
|
337
|
+
plan.changes.preserved.push('steering/CURRENT_CONTEXT.md');
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
plan.requiresBackup = plan.filesToModify.length > 0;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
return plan;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* Executes the adoption strategy
|
|
348
|
+
*
|
|
349
|
+
* @param {string} projectPath - Project path
|
|
350
|
+
* @param {string} mode - Adoption mode
|
|
351
|
+
* @param {AdoptionPlan} plan - Adoption plan
|
|
352
|
+
* @param {boolean} skipUpdate - Skip template updates
|
|
353
|
+
* @returns {Promise<AdoptionResult>}
|
|
354
|
+
* @private
|
|
355
|
+
*/
|
|
356
|
+
async _executeAdoption(projectPath, mode, plan, skipUpdate) {
|
|
357
|
+
try {
|
|
358
|
+
// Map smart modes to strategy modes
|
|
359
|
+
let strategyMode = mode;
|
|
360
|
+
if (mode === 'smart-adopt') {
|
|
361
|
+
strategyMode = 'partial';
|
|
362
|
+
} else if (mode === 'smart-update') {
|
|
363
|
+
strategyMode = 'full';
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
const strategy = getAdoptionStrategy(strategyMode);
|
|
367
|
+
const packageJson = require('../../package.json');
|
|
368
|
+
|
|
369
|
+
// Build resolution map - update all template files
|
|
370
|
+
const resolutionMap = {};
|
|
371
|
+
if (!skipUpdate) {
|
|
372
|
+
plan.filesToModify.forEach(file => {
|
|
373
|
+
resolutionMap[file] = 'overwrite';
|
|
374
|
+
});
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
// Preserve user content
|
|
378
|
+
plan.filesToPreserve.forEach(file => {
|
|
379
|
+
resolutionMap[file] = 'keep';
|
|
380
|
+
});
|
|
381
|
+
|
|
382
|
+
const result = await strategy.execute(projectPath, strategyMode, {
|
|
383
|
+
kseVersion: packageJson.version,
|
|
384
|
+
dryRun: false,
|
|
385
|
+
force: !skipUpdate,
|
|
386
|
+
resolutionMap
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
return result;
|
|
390
|
+
} catch (error) {
|
|
391
|
+
return {
|
|
392
|
+
success: false,
|
|
393
|
+
errors: [error.message],
|
|
394
|
+
warnings: [],
|
|
395
|
+
filesCreated: [],
|
|
396
|
+
filesUpdated: [],
|
|
397
|
+
filesSkipped: []
|
|
398
|
+
};
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
/**
|
|
403
|
+
* Updates version information
|
|
404
|
+
*
|
|
405
|
+
* @param {string} projectPath - Project path
|
|
406
|
+
* @param {string} mode - Adoption mode
|
|
407
|
+
* @param {DetectionResult} detection - Detection result
|
|
408
|
+
* @returns {Promise<void>}
|
|
409
|
+
* @private
|
|
410
|
+
*/
|
|
411
|
+
async _updateVersionInfo(projectPath, mode, detection) {
|
|
412
|
+
const packageJson = require('../../package.json');
|
|
413
|
+
const targetVersion = packageJson.version;
|
|
414
|
+
|
|
415
|
+
if (mode === 'fresh' || mode === 'smart-adopt') {
|
|
416
|
+
// Create new version info
|
|
417
|
+
const versionInfo = this.versionManager.createVersionInfo(targetVersion);
|
|
418
|
+
await this.versionManager.writeVersion(projectPath, versionInfo);
|
|
419
|
+
} else if (mode === 'smart-update') {
|
|
420
|
+
// Update existing version info
|
|
421
|
+
const existingVersion = await this.versionManager.readVersion(projectPath);
|
|
422
|
+
if (existingVersion) {
|
|
423
|
+
const updatedVersion = this.versionManager.addUpgradeHistory(
|
|
424
|
+
existingVersion,
|
|
425
|
+
detection.existingVersion,
|
|
426
|
+
targetVersion,
|
|
427
|
+
true
|
|
428
|
+
);
|
|
429
|
+
await this.versionManager.writeVersion(projectPath, updatedVersion);
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
/**
|
|
435
|
+
* Generates comprehensive summary using SummaryGenerator
|
|
436
|
+
*
|
|
437
|
+
* @param {OrchestrationResult} result - Orchestration result
|
|
438
|
+
* @returns {string} Formatted summary text
|
|
439
|
+
*/
|
|
440
|
+
generateSummary(result) {
|
|
441
|
+
// Create a new summary generator and populate it with result data
|
|
442
|
+
const generator = new SummaryGenerator();
|
|
443
|
+
generator.setMode(result.mode);
|
|
444
|
+
|
|
445
|
+
if (result.backup) {
|
|
446
|
+
generator.setBackup(result.backup);
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
// Add file changes
|
|
450
|
+
if (result.changes) {
|
|
451
|
+
generator.addFileChanges('create', result.changes.created || []);
|
|
452
|
+
generator.addFileChanges('update', result.changes.updated || []);
|
|
453
|
+
generator.addFileChanges('delete', result.changes.deleted || []);
|
|
454
|
+
generator.addFileChanges('preserve', result.changes.preserved || []);
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
// Add warnings and errors
|
|
458
|
+
if (result.warnings) {
|
|
459
|
+
result.warnings.forEach(warning => generator.addWarning(warning));
|
|
460
|
+
}
|
|
461
|
+
if (result.errors) {
|
|
462
|
+
result.errors.forEach(error => generator.addError(error));
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
// Generate text summary with verbose mode to show all details
|
|
466
|
+
return generator.generateTextSummary({ verbose: true, color: true });
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
module.exports = SmartOrchestrator;
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Strategy Selector
|
|
3
|
+
*
|
|
4
|
+
* Automatically detects project state and selects the optimal adoption mode.
|
|
5
|
+
* Extracted from SmartOrchestrator to provide a focused, testable component.
|
|
6
|
+
*
|
|
7
|
+
* Responsibilities:
|
|
8
|
+
* - Detect current project state
|
|
9
|
+
* - Analyze version compatibility
|
|
10
|
+
* - Select optimal adoption mode
|
|
11
|
+
* - Return comprehensive project state information
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
const path = require('path');
|
|
15
|
+
const fs = require('fs-extra');
|
|
16
|
+
const VersionManager = require('../version/version-manager');
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Adoption modes
|
|
20
|
+
*/
|
|
21
|
+
const AdoptionMode = {
|
|
22
|
+
FRESH: 'fresh', // No .kiro/ directory - create new
|
|
23
|
+
SKIP: 'skip', // Already at latest version - no action
|
|
24
|
+
SMART_UPDATE: 'smart-update', // Older version - update templates only
|
|
25
|
+
WARNING: 'warning', // Newer version - warn user
|
|
26
|
+
SMART_ADOPT: 'smart-adopt' // No version info - full adoption with backup
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Project state information
|
|
31
|
+
*/
|
|
32
|
+
class ProjectState {
|
|
33
|
+
constructor(data = {}) {
|
|
34
|
+
this.hasKiroDir = data.hasKiroDir !== undefined ? data.hasKiroDir : false;
|
|
35
|
+
this.hasVersionFile = data.hasVersionFile !== undefined ? data.hasVersionFile : false;
|
|
36
|
+
this.currentVersion = data.currentVersion !== undefined ? data.currentVersion : null;
|
|
37
|
+
this.targetVersion = data.targetVersion !== undefined ? data.targetVersion : null;
|
|
38
|
+
this.hasSpecs = data.hasSpecs !== undefined ? data.hasSpecs : false;
|
|
39
|
+
this.hasSteering = data.hasSteering !== undefined ? data.hasSteering : false;
|
|
40
|
+
this.hasTools = data.hasTools !== undefined ? data.hasTools : false;
|
|
41
|
+
this.conflicts = data.conflicts || [];
|
|
42
|
+
this.versionComparison = data.versionComparison !== undefined ? data.versionComparison : null;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Strategy Selector
|
|
48
|
+
* Detects project state and selects optimal adoption mode
|
|
49
|
+
*/
|
|
50
|
+
class StrategySelector {
|
|
51
|
+
constructor(dependencies = {}) {
|
|
52
|
+
// Support dependency injection for testing
|
|
53
|
+
this.versionManager = dependencies.versionManager || new VersionManager();
|
|
54
|
+
this.fs = dependencies.fs || fs;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Detects the current project state
|
|
59
|
+
*
|
|
60
|
+
* @param {string} projectPath - Absolute path to project root
|
|
61
|
+
* @returns {Promise<ProjectState>} - Comprehensive project state
|
|
62
|
+
*/
|
|
63
|
+
async detectProjectState(projectPath) {
|
|
64
|
+
const kiroPath = path.join(projectPath, '.kiro');
|
|
65
|
+
const versionPath = path.join(kiroPath, 'version.json');
|
|
66
|
+
const specsPath = path.join(kiroPath, 'specs');
|
|
67
|
+
const steeringPath = path.join(kiroPath, 'steering');
|
|
68
|
+
const toolsPath = path.join(kiroPath, 'tools');
|
|
69
|
+
|
|
70
|
+
// Get target version from package.json
|
|
71
|
+
const packageJson = require('../../package.json');
|
|
72
|
+
const targetVersion = packageJson.version;
|
|
73
|
+
|
|
74
|
+
// Check directory existence
|
|
75
|
+
const hasKiroDir = await this.fs.pathExists(kiroPath);
|
|
76
|
+
const hasVersionFile = hasKiroDir && await this.fs.pathExists(versionPath);
|
|
77
|
+
const hasSpecs = hasKiroDir && await this.fs.pathExists(specsPath);
|
|
78
|
+
const hasSteering = hasKiroDir && await this.fs.pathExists(steeringPath);
|
|
79
|
+
const hasTools = hasKiroDir && await this.fs.pathExists(toolsPath);
|
|
80
|
+
|
|
81
|
+
// Read current version if available
|
|
82
|
+
let currentVersion = null;
|
|
83
|
+
let versionComparison = null;
|
|
84
|
+
|
|
85
|
+
if (hasVersionFile) {
|
|
86
|
+
try {
|
|
87
|
+
const versionInfo = await this.versionManager.readVersion(projectPath);
|
|
88
|
+
currentVersion = versionInfo['kse-version'] || null;
|
|
89
|
+
|
|
90
|
+
// Compare versions if we have both
|
|
91
|
+
if (currentVersion && targetVersion) {
|
|
92
|
+
versionComparison = this.versionManager.compareVersions(
|
|
93
|
+
currentVersion,
|
|
94
|
+
targetVersion
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
} catch (error) {
|
|
98
|
+
// Version file exists but is corrupted - treat as no version
|
|
99
|
+
currentVersion = null;
|
|
100
|
+
versionComparison = null;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Detect potential conflicts (files that exist and might be overwritten)
|
|
105
|
+
const conflicts = [];
|
|
106
|
+
if (hasKiroDir) {
|
|
107
|
+
const templateFiles = [
|
|
108
|
+
'steering/CORE_PRINCIPLES.md',
|
|
109
|
+
'steering/ENVIRONMENT.md',
|
|
110
|
+
'steering/RULES_GUIDE.md',
|
|
111
|
+
'tools/ultrawork_enhancer.py',
|
|
112
|
+
'README.md'
|
|
113
|
+
];
|
|
114
|
+
|
|
115
|
+
for (const templateFile of templateFiles) {
|
|
116
|
+
const filePath = path.join(kiroPath, templateFile);
|
|
117
|
+
if (await this.fs.pathExists(filePath)) {
|
|
118
|
+
conflicts.push(templateFile);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return new ProjectState({
|
|
124
|
+
hasKiroDir,
|
|
125
|
+
hasVersionFile,
|
|
126
|
+
currentVersion,
|
|
127
|
+
targetVersion,
|
|
128
|
+
hasSpecs,
|
|
129
|
+
hasSteering,
|
|
130
|
+
hasTools,
|
|
131
|
+
conflicts,
|
|
132
|
+
versionComparison
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Selects the optimal adoption mode based on project state
|
|
138
|
+
*
|
|
139
|
+
* @param {ProjectState} state - Project state from detectProjectState()
|
|
140
|
+
* @returns {string} - Adoption mode (one of AdoptionMode values)
|
|
141
|
+
*/
|
|
142
|
+
selectMode(state) {
|
|
143
|
+
// No .kiro/ directory - fresh adoption
|
|
144
|
+
if (!state.hasKiroDir) {
|
|
145
|
+
return AdoptionMode.FRESH;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Has .kiro/ but no version file or no current version - smart adopt
|
|
149
|
+
if (!state.hasVersionFile || !state.currentVersion) {
|
|
150
|
+
return AdoptionMode.SMART_ADOPT;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// Has version file and current version - check version comparison
|
|
154
|
+
// Version comparison can be null if comparison failed
|
|
155
|
+
if (state.versionComparison === null || state.versionComparison === undefined) {
|
|
156
|
+
// Version comparison failed - default to smart adopt
|
|
157
|
+
return AdoptionMode.SMART_ADOPT;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
if (state.versionComparison === 0) {
|
|
161
|
+
// Same version - skip
|
|
162
|
+
return AdoptionMode.SKIP;
|
|
163
|
+
} else if (state.versionComparison < 0) {
|
|
164
|
+
// Current version is older - smart update
|
|
165
|
+
return AdoptionMode.SMART_UPDATE;
|
|
166
|
+
} else {
|
|
167
|
+
// Current version is newer - warning
|
|
168
|
+
return AdoptionMode.WARNING;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Detects project state and selects mode in one call
|
|
174
|
+
* Convenience method that combines detectProjectState() and selectMode()
|
|
175
|
+
*
|
|
176
|
+
* @param {string} projectPath - Absolute path to project root
|
|
177
|
+
* @returns {Promise<{state: ProjectState, mode: string}>}
|
|
178
|
+
*/
|
|
179
|
+
async detectAndSelect(projectPath) {
|
|
180
|
+
const state = await this.detectProjectState(projectPath);
|
|
181
|
+
const mode = this.selectMode(state);
|
|
182
|
+
|
|
183
|
+
return { state, mode };
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Gets a human-readable description of the selected mode
|
|
188
|
+
*
|
|
189
|
+
* @param {string} mode - Adoption mode
|
|
190
|
+
* @returns {string} - Human-readable description
|
|
191
|
+
*/
|
|
192
|
+
getModeDescription(mode) {
|
|
193
|
+
const descriptions = {
|
|
194
|
+
[AdoptionMode.FRESH]: 'Fresh Adoption - Creating new .kiro/ structure',
|
|
195
|
+
[AdoptionMode.SKIP]: 'Already Up-to-Date - No changes needed',
|
|
196
|
+
[AdoptionMode.SMART_UPDATE]: 'Smart Update - Updating template files to latest version',
|
|
197
|
+
[AdoptionMode.WARNING]: 'Version Warning - Project version is newer than KSE version',
|
|
198
|
+
[AdoptionMode.SMART_ADOPT]: 'Smart Adoption - Adopting existing .kiro/ directory'
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
return descriptions[mode] || `Unknown mode: ${mode}`;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Validates that a mode is valid
|
|
206
|
+
*
|
|
207
|
+
* @param {string} mode - Mode to validate
|
|
208
|
+
* @returns {boolean} - True if valid
|
|
209
|
+
*/
|
|
210
|
+
isValidMode(mode) {
|
|
211
|
+
return Object.values(AdoptionMode).includes(mode);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// Export class and constants
|
|
216
|
+
module.exports = StrategySelector;
|
|
217
|
+
module.exports.AdoptionMode = AdoptionMode;
|
|
218
|
+
module.exports.ProjectState = ProjectState;
|