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,446 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI commands for Agent Orchestration
|
|
3
|
+
*
|
|
4
|
+
* Provides `kse orchestrate run|status|stop` subcommands for managing
|
|
5
|
+
* parallel Spec execution via Codex CLI sub-agents.
|
|
6
|
+
*
|
|
7
|
+
* Requirements: 6.1 (run), 6.2 (status), 6.3 (stop), 6.4 (spec validation), 6.5 (maxParallel validation)
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const chalk = require('chalk');
|
|
11
|
+
const path = require('path');
|
|
12
|
+
const fs = require('fs-extra');
|
|
13
|
+
|
|
14
|
+
const SPECS_DIR = '.kiro/specs';
|
|
15
|
+
const STATUS_FILE = '.kiro/config/orchestration-status.json';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Run orchestration programmatically.
|
|
19
|
+
*
|
|
20
|
+
* @param {object} options
|
|
21
|
+
* @param {string} [options.specs] - Comma separated spec names
|
|
22
|
+
* @param {string[]} [options.specNames] - Explicit spec names array
|
|
23
|
+
* @param {number} [options.maxParallel]
|
|
24
|
+
* @param {boolean} [options.json]
|
|
25
|
+
* @param {boolean} [options.silent]
|
|
26
|
+
* @param {object} dependencies
|
|
27
|
+
* @param {string} [dependencies.workspaceRoot]
|
|
28
|
+
* @returns {Promise<object>}
|
|
29
|
+
*/
|
|
30
|
+
async function runOrchestration(options = {}, dependencies = {}) {
|
|
31
|
+
const workspaceRoot = dependencies.workspaceRoot || process.cwd();
|
|
32
|
+
const specNames = Array.isArray(options.specNames)
|
|
33
|
+
? options.specNames.map(name => `${name}`.trim()).filter(Boolean)
|
|
34
|
+
: _parseSpecNamesOption(options.specs);
|
|
35
|
+
|
|
36
|
+
if (specNames.length === 0) {
|
|
37
|
+
throw new Error('No specs specified');
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const maxParallel = options.maxParallel;
|
|
41
|
+
if (maxParallel !== undefined && (isNaN(maxParallel) || maxParallel < 1)) {
|
|
42
|
+
throw new Error('--max-parallel must be >= 1');
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const missing = await _validateSpecs(workspaceRoot, specNames);
|
|
46
|
+
if (missing.length > 0) {
|
|
47
|
+
throw new Error(`Specs not found: ${missing.join(', ')}`);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const { OrchestratorConfig } = require('../orchestrator/orchestrator-config');
|
|
51
|
+
const { BootstrapPromptBuilder } = require('../orchestrator/bootstrap-prompt-builder');
|
|
52
|
+
const { AgentSpawner } = require('../orchestrator/agent-spawner');
|
|
53
|
+
const { StatusMonitor } = require('../orchestrator/status-monitor');
|
|
54
|
+
const { OrchestrationEngine } = require('../orchestrator/orchestration-engine');
|
|
55
|
+
|
|
56
|
+
const DependencyManager = require('../collab/dependency-manager');
|
|
57
|
+
const MetadataManager = require('../collab/metadata-manager');
|
|
58
|
+
const { AgentRegistry } = require('../collab/agent-registry');
|
|
59
|
+
const { SpecLifecycleManager } = require('../collab/spec-lifecycle-manager');
|
|
60
|
+
const { MachineIdentifier } = require('../lock/machine-identifier');
|
|
61
|
+
|
|
62
|
+
let contextSyncManager = null;
|
|
63
|
+
try {
|
|
64
|
+
const { ContextSyncManager } = require('../steering/context-sync-manager');
|
|
65
|
+
contextSyncManager = new ContextSyncManager(workspaceRoot);
|
|
66
|
+
} catch (_err) {
|
|
67
|
+
// Non-fatal — status sync will be skipped
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const orchestratorConfig = new OrchestratorConfig(workspaceRoot);
|
|
71
|
+
const config = await orchestratorConfig.getConfig();
|
|
72
|
+
const effectiveMaxParallel = maxParallel || config.maxParallel;
|
|
73
|
+
|
|
74
|
+
const bootstrapPromptBuilder = new BootstrapPromptBuilder(workspaceRoot, orchestratorConfig);
|
|
75
|
+
const machineIdentifier = new MachineIdentifier(
|
|
76
|
+
path.join(workspaceRoot, '.kiro', 'config')
|
|
77
|
+
);
|
|
78
|
+
const agentRegistry = new AgentRegistry(workspaceRoot, machineIdentifier);
|
|
79
|
+
const agentSpawner = new AgentSpawner(
|
|
80
|
+
workspaceRoot, orchestratorConfig, agentRegistry, bootstrapPromptBuilder
|
|
81
|
+
);
|
|
82
|
+
const metadataManager = new MetadataManager(workspaceRoot);
|
|
83
|
+
const dependencyManager = new DependencyManager(metadataManager);
|
|
84
|
+
const specLifecycleManager = new SpecLifecycleManager(
|
|
85
|
+
workspaceRoot, contextSyncManager, agentRegistry
|
|
86
|
+
);
|
|
87
|
+
const statusMonitor = new StatusMonitor(specLifecycleManager, contextSyncManager);
|
|
88
|
+
|
|
89
|
+
const engine = new OrchestrationEngine(workspaceRoot, {
|
|
90
|
+
agentSpawner,
|
|
91
|
+
dependencyManager,
|
|
92
|
+
specLifecycleManager,
|
|
93
|
+
statusMonitor,
|
|
94
|
+
orchestratorConfig,
|
|
95
|
+
agentRegistry,
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
if (!options.silent && !options.json) {
|
|
99
|
+
console.log(
|
|
100
|
+
chalk.blue('🚀'),
|
|
101
|
+
`Starting orchestration for ${specNames.length} spec(s) (max-parallel: ${effectiveMaxParallel})...`
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const statusIntervalMs = Number.isInteger(options.statusIntervalMs) && options.statusIntervalMs > 0
|
|
106
|
+
? options.statusIntervalMs
|
|
107
|
+
: 1000;
|
|
108
|
+
|
|
109
|
+
let statusWriteChain = Promise.resolve();
|
|
110
|
+
const persistStatus = () => {
|
|
111
|
+
const statusSnapshot = engine.getStatus();
|
|
112
|
+
statusWriteChain = statusWriteChain.then(async () => {
|
|
113
|
+
await _writeStatus(workspaceRoot, statusSnapshot);
|
|
114
|
+
if (typeof options.onStatus === 'function') {
|
|
115
|
+
await Promise.resolve(options.onStatus(statusSnapshot));
|
|
116
|
+
}
|
|
117
|
+
}).catch(() => {});
|
|
118
|
+
return statusWriteChain;
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
const statusEvents = [
|
|
122
|
+
'batch:start',
|
|
123
|
+
'batch:complete',
|
|
124
|
+
'spec:start',
|
|
125
|
+
'spec:complete',
|
|
126
|
+
'spec:failed',
|
|
127
|
+
'spec:rate-limited',
|
|
128
|
+
'launch:budget-hold',
|
|
129
|
+
'parallel:throttled',
|
|
130
|
+
'parallel:recovered',
|
|
131
|
+
'orchestration:complete'
|
|
132
|
+
];
|
|
133
|
+
|
|
134
|
+
for (const eventName of statusEvents) {
|
|
135
|
+
engine.on(eventName, () => {
|
|
136
|
+
void persistStatus();
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const statusTimer = setInterval(() => {
|
|
141
|
+
void persistStatus();
|
|
142
|
+
}, statusIntervalMs);
|
|
143
|
+
if (typeof statusTimer.unref === 'function') {
|
|
144
|
+
statusTimer.unref();
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
let result;
|
|
148
|
+
try {
|
|
149
|
+
result = await engine.start(specNames, { maxParallel: effectiveMaxParallel });
|
|
150
|
+
} finally {
|
|
151
|
+
clearInterval(statusTimer);
|
|
152
|
+
await persistStatus();
|
|
153
|
+
await statusWriteChain;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const finalStatus = engine.getStatus();
|
|
157
|
+
if (result && typeof result === 'object' && finalStatus && typeof finalStatus === 'object') {
|
|
158
|
+
if (finalStatus.rateLimit && typeof finalStatus.rateLimit === 'object') {
|
|
159
|
+
result.rateLimit = { ...finalStatus.rateLimit };
|
|
160
|
+
}
|
|
161
|
+
if (finalStatus.parallel && typeof finalStatus.parallel === 'object') {
|
|
162
|
+
result.parallel = { ...finalStatus.parallel };
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
if (!options.silent) {
|
|
167
|
+
if (options.json) {
|
|
168
|
+
console.log(JSON.stringify(result, null, 2));
|
|
169
|
+
} else {
|
|
170
|
+
_printResult(result);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
return result;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Register orchestrate commands on the given Commander program.
|
|
179
|
+
* @param {import('commander').Command} program
|
|
180
|
+
*/
|
|
181
|
+
function registerOrchestrateCommands(program) {
|
|
182
|
+
const orchestrate = program
|
|
183
|
+
.command('orchestrate')
|
|
184
|
+
.description('Manage agent orchestration for parallel Spec execution');
|
|
185
|
+
|
|
186
|
+
// ── kse orchestrate run ──────────────────────────────────────────
|
|
187
|
+
orchestrate
|
|
188
|
+
.command('run')
|
|
189
|
+
.description('Start orchestration for specified Specs')
|
|
190
|
+
.requiredOption('--specs <specs>', 'Comma-separated list of Spec names')
|
|
191
|
+
.option('--max-parallel <n>', 'Maximum parallel agents', parseInt)
|
|
192
|
+
.option('--json', 'Output in JSON format')
|
|
193
|
+
.action(async (options) => {
|
|
194
|
+
try {
|
|
195
|
+
const result = await runOrchestration(options);
|
|
196
|
+
|
|
197
|
+
if (result.status === 'failed') {
|
|
198
|
+
process.exit(1);
|
|
199
|
+
}
|
|
200
|
+
} catch (err) {
|
|
201
|
+
_errorAndExit(err.message, options.json);
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
// ── kse orchestrate status ───────────────────────────────────────
|
|
206
|
+
orchestrate
|
|
207
|
+
.command('status')
|
|
208
|
+
.description('Show current orchestration status')
|
|
209
|
+
.option('--json', 'Output in JSON format')
|
|
210
|
+
.action(async (options) => {
|
|
211
|
+
try {
|
|
212
|
+
const workspaceRoot = process.cwd();
|
|
213
|
+
const status = await _readStatus(workspaceRoot);
|
|
214
|
+
|
|
215
|
+
if (!status) {
|
|
216
|
+
if (options.json) {
|
|
217
|
+
console.log(JSON.stringify({ status: 'idle', message: 'No orchestration data found' }));
|
|
218
|
+
} else {
|
|
219
|
+
console.log(chalk.gray('No orchestration data found. Run `kse orchestrate run` first.'));
|
|
220
|
+
}
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
if (options.json) {
|
|
225
|
+
console.log(JSON.stringify(status, null, 2));
|
|
226
|
+
} else {
|
|
227
|
+
_printStatus(status);
|
|
228
|
+
}
|
|
229
|
+
} catch (err) {
|
|
230
|
+
_errorAndExit(err.message, options.json);
|
|
231
|
+
}
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
// ── kse orchestrate stop ─────────────────────────────────────────
|
|
235
|
+
orchestrate
|
|
236
|
+
.command('stop')
|
|
237
|
+
.description('Stop all running agents')
|
|
238
|
+
.action(async () => {
|
|
239
|
+
try {
|
|
240
|
+
const workspaceRoot = process.cwd();
|
|
241
|
+
const status = await _readStatus(workspaceRoot);
|
|
242
|
+
|
|
243
|
+
if (!status || status.status !== 'running') {
|
|
244
|
+
console.log(chalk.gray('No running orchestration to stop.'));
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// Write a stop signal into the status file
|
|
249
|
+
status.status = 'stopped';
|
|
250
|
+
status.completedAt = new Date().toISOString();
|
|
251
|
+
await _writeStatus(workspaceRoot, status);
|
|
252
|
+
|
|
253
|
+
console.log(chalk.yellow('⏹'), 'Stop signal sent. Running agents will be terminated.');
|
|
254
|
+
} catch (err) {
|
|
255
|
+
console.error(chalk.red('Error:'), err.message);
|
|
256
|
+
process.exit(1);
|
|
257
|
+
}
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// ── Helpers ──────────────────────────────────────────────────────────
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Validate that all spec directories exist.
|
|
265
|
+
* @param {string} workspaceRoot
|
|
266
|
+
* @param {string[]} specNames
|
|
267
|
+
* @returns {Promise<string[]>} Missing spec names
|
|
268
|
+
*/
|
|
269
|
+
async function _validateSpecs(workspaceRoot, specNames) {
|
|
270
|
+
const missing = [];
|
|
271
|
+
for (const name of specNames) {
|
|
272
|
+
const specDir = path.join(workspaceRoot, SPECS_DIR, name);
|
|
273
|
+
const exists = await fs.pathExists(specDir);
|
|
274
|
+
if (!exists) {
|
|
275
|
+
missing.push(name);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
return missing;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* Read persisted orchestration status.
|
|
283
|
+
* @param {string} workspaceRoot
|
|
284
|
+
* @returns {Promise<object|null>}
|
|
285
|
+
*/
|
|
286
|
+
async function _readStatus(workspaceRoot) {
|
|
287
|
+
const statusPath = path.join(workspaceRoot, STATUS_FILE);
|
|
288
|
+
try {
|
|
289
|
+
return await fs.readJson(statusPath);
|
|
290
|
+
} catch (_err) {
|
|
291
|
+
return null;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* Persist orchestration status to disk.
|
|
297
|
+
* @param {string} workspaceRoot
|
|
298
|
+
* @param {object} status
|
|
299
|
+
*/
|
|
300
|
+
async function _writeStatus(workspaceRoot, status) {
|
|
301
|
+
const statusPath = path.join(workspaceRoot, STATUS_FILE);
|
|
302
|
+
await fs.ensureDir(path.dirname(statusPath));
|
|
303
|
+
await fs.writeJson(statusPath, status, { spaces: 2 });
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* Print a human-readable orchestration result.
|
|
308
|
+
* @param {object} result
|
|
309
|
+
*/
|
|
310
|
+
function _printResult(result) {
|
|
311
|
+
const icon = result.status === 'completed' ? chalk.green('✓') : chalk.red('✗');
|
|
312
|
+
console.log(`${icon} Orchestration ${result.status}`);
|
|
313
|
+
if (result.totalSpecs !== undefined) {
|
|
314
|
+
console.log(chalk.gray(` Total: ${result.totalSpecs} Completed: ${result.completedSpecs} Failed: ${result.failedSpecs}`));
|
|
315
|
+
}
|
|
316
|
+
if (result.specs) {
|
|
317
|
+
for (const [name, info] of Object.entries(result.specs)) {
|
|
318
|
+
const sym = _statusSymbol(info.status);
|
|
319
|
+
const extra = info.error ? chalk.gray(` — ${info.error}`) : '';
|
|
320
|
+
console.log(` ${sym} ${name}${extra}`);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* Print a human-readable orchestration status.
|
|
327
|
+
* @param {object} status
|
|
328
|
+
*/
|
|
329
|
+
function _printStatus(status) {
|
|
330
|
+
console.log(chalk.bold('Orchestration Status'));
|
|
331
|
+
console.log(chalk.gray('===================='));
|
|
332
|
+
console.log(`Status: ${_statusSymbol(status.status)} ${status.status}`);
|
|
333
|
+
if (status.totalSpecs !== undefined) {
|
|
334
|
+
console.log(`Total: ${status.totalSpecs} Completed: ${status.completedSpecs || 0} Failed: ${status.failedSpecs || 0} Running: ${status.runningSpecs || 0}`);
|
|
335
|
+
}
|
|
336
|
+
if (status.currentBatch !== undefined && status.totalBatches !== undefined) {
|
|
337
|
+
console.log(`Batch: ${status.currentBatch} / ${status.totalBatches}`);
|
|
338
|
+
}
|
|
339
|
+
if (status.parallel) {
|
|
340
|
+
const effective = status.parallel.effectiveMaxParallel ?? '-';
|
|
341
|
+
const max = status.parallel.maxParallel ?? '-';
|
|
342
|
+
const adaptive = status.parallel.adaptive === false ? 'off' : 'on';
|
|
343
|
+
console.log(`Parallel: ${effective} / ${max} (adaptive: ${adaptive})`);
|
|
344
|
+
}
|
|
345
|
+
if (status.rateLimit) {
|
|
346
|
+
const signals = status.rateLimit.signalCount || 0;
|
|
347
|
+
const backoff = status.rateLimit.totalBackoffMs || 0;
|
|
348
|
+
console.log(`Rate-limit: ${signals} signal(s), total backoff ${backoff}ms`);
|
|
349
|
+
|
|
350
|
+
const holdWindowMs = Number(status.rateLimit.lastLaunchHoldMs) || 0;
|
|
351
|
+
const lastSignalAtMs = Date.parse(status.rateLimit.lastSignalAt || '');
|
|
352
|
+
const elapsedSinceSignalMs = Number.isFinite(lastSignalAtMs)
|
|
353
|
+
? Math.max(0, Date.now() - lastSignalAtMs)
|
|
354
|
+
: Infinity;
|
|
355
|
+
const holdRemainingMs = holdWindowMs > 0
|
|
356
|
+
? Math.max(0, holdWindowMs - elapsedSinceSignalMs)
|
|
357
|
+
: 0;
|
|
358
|
+
if (holdRemainingMs > 0) {
|
|
359
|
+
console.log(`Rate-limit launch hold: ${holdRemainingMs}ms remaining`);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
const launchBudgetPerMinute = Number(status.rateLimit.launchBudgetPerMinute);
|
|
363
|
+
if (Number.isFinite(launchBudgetPerMinute) && launchBudgetPerMinute > 0) {
|
|
364
|
+
const launchBudgetWindowMs = Number(status.rateLimit.launchBudgetWindowMs) || 60000;
|
|
365
|
+
const launchBudgetUsed = Number(status.rateLimit.launchBudgetUsed) || 0;
|
|
366
|
+
const launchBudgetHoldCount = Number(status.rateLimit.launchBudgetHoldCount) || 0;
|
|
367
|
+
console.log(
|
|
368
|
+
`Launch budget: ${launchBudgetUsed}/${launchBudgetPerMinute} in ${launchBudgetWindowMs}ms (holds: ${launchBudgetHoldCount})`
|
|
369
|
+
);
|
|
370
|
+
|
|
371
|
+
const launchBudgetHoldWindowMs = Number(status.rateLimit.lastLaunchBudgetHoldMs) || 0;
|
|
372
|
+
const lastLaunchBudgetHoldAtMs = Date.parse(status.rateLimit.lastLaunchBudgetHoldAt || '');
|
|
373
|
+
const elapsedSinceBudgetHoldMs = Number.isFinite(lastLaunchBudgetHoldAtMs)
|
|
374
|
+
? Math.max(0, Date.now() - lastLaunchBudgetHoldAtMs)
|
|
375
|
+
: Infinity;
|
|
376
|
+
const budgetHoldRemainingMs = launchBudgetHoldWindowMs > 0
|
|
377
|
+
? Math.max(0, launchBudgetHoldWindowMs - elapsedSinceBudgetHoldMs)
|
|
378
|
+
: 0;
|
|
379
|
+
if (budgetHoldRemainingMs > 0) {
|
|
380
|
+
console.log(`Launch budget hold: ${budgetHoldRemainingMs}ms remaining`);
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
if (status.specs) {
|
|
385
|
+
console.log('');
|
|
386
|
+
for (const [name, info] of Object.entries(status.specs)) {
|
|
387
|
+
const sym = _statusSymbol(info.status);
|
|
388
|
+
const extra = info.error ? chalk.gray(` — ${info.error}`) : '';
|
|
389
|
+
console.log(` ${sym} ${name}${extra}`);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
/**
|
|
395
|
+
* Map status string to a coloured symbol.
|
|
396
|
+
* @param {string} status
|
|
397
|
+
* @returns {string}
|
|
398
|
+
*/
|
|
399
|
+
function _statusSymbol(status) {
|
|
400
|
+
const map = {
|
|
401
|
+
completed: chalk.green('✓'),
|
|
402
|
+
running: chalk.yellow('⧗'),
|
|
403
|
+
pending: chalk.gray('○'),
|
|
404
|
+
failed: chalk.red('✗'),
|
|
405
|
+
timeout: chalk.red('⏱'),
|
|
406
|
+
skipped: chalk.gray('⊘'),
|
|
407
|
+
idle: chalk.gray('○'),
|
|
408
|
+
stopped: chalk.yellow('⏹'),
|
|
409
|
+
};
|
|
410
|
+
return map[status] || '?';
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
/**
|
|
414
|
+
* Print an error and exit. Respects --json mode.
|
|
415
|
+
* @param {string} message
|
|
416
|
+
* @param {boolean} [json]
|
|
417
|
+
*/
|
|
418
|
+
function _errorAndExit(message, json) {
|
|
419
|
+
if (json) {
|
|
420
|
+
console.log(JSON.stringify({ error: message }));
|
|
421
|
+
} else {
|
|
422
|
+
console.error(chalk.red('Error:'), message);
|
|
423
|
+
}
|
|
424
|
+
process.exit(1);
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
/**
|
|
428
|
+
* Parse a comma-separated specs option.
|
|
429
|
+
* @param {string} specsOption
|
|
430
|
+
* @returns {string[]}
|
|
431
|
+
*/
|
|
432
|
+
function _parseSpecNamesOption(specsOption) {
|
|
433
|
+
if (!specsOption || typeof specsOption !== 'string') {
|
|
434
|
+
return [];
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
return specsOption
|
|
438
|
+
.split(',')
|
|
439
|
+
.map(item => item.trim())
|
|
440
|
+
.filter(Boolean);
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
module.exports = {
|
|
444
|
+
registerOrchestrateCommands,
|
|
445
|
+
runOrchestration,
|
|
446
|
+
};
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Prompt Command
|
|
3
|
+
*
|
|
4
|
+
* Generates task-specific prompts for AI coding assistants
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const chalk = require('chalk');
|
|
8
|
+
const PromptGenerator = require('../context/prompt-generator');
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Generate task prompt
|
|
12
|
+
*
|
|
13
|
+
* @param {string} specName - Spec name
|
|
14
|
+
* @param {string} taskId - Task ID
|
|
15
|
+
* @param {Object} options - Command options
|
|
16
|
+
* @param {string} options.tool - Target tool (generic, claude-code, cursor, codex, kiro)
|
|
17
|
+
* @param {number} options.maxLength - Maximum context length
|
|
18
|
+
* @returns {Promise<void>}
|
|
19
|
+
*/
|
|
20
|
+
async function generatePrompt(specName, taskId, options = {}) {
|
|
21
|
+
const projectPath = process.cwd();
|
|
22
|
+
const generator = new PromptGenerator();
|
|
23
|
+
|
|
24
|
+
console.log(chalk.red('🔥') + ' Generating Task Prompt');
|
|
25
|
+
console.log();
|
|
26
|
+
|
|
27
|
+
try {
|
|
28
|
+
console.log(`Spec: ${chalk.cyan(specName)}`);
|
|
29
|
+
console.log(`Task: ${chalk.cyan(taskId)}`);
|
|
30
|
+
|
|
31
|
+
const targetTool = options.tool || 'generic';
|
|
32
|
+
console.log(`Target Tool: ${chalk.cyan(targetTool)}`);
|
|
33
|
+
console.log();
|
|
34
|
+
|
|
35
|
+
const generateOptions = {
|
|
36
|
+
targetTool,
|
|
37
|
+
maxContextLength: options.maxLength || 10000
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
console.log('Generating prompt...');
|
|
41
|
+
console.log();
|
|
42
|
+
|
|
43
|
+
const result = await generator.generatePrompt(
|
|
44
|
+
projectPath,
|
|
45
|
+
specName,
|
|
46
|
+
taskId,
|
|
47
|
+
generateOptions
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
if (result.success) {
|
|
51
|
+
console.log(chalk.green('✅ Prompt generated successfully'));
|
|
52
|
+
console.log();
|
|
53
|
+
console.log(`Prompt file: ${chalk.cyan(result.promptPath)}`);
|
|
54
|
+
console.log(`Size: ${chalk.gray(formatBytes(result.size))}`);
|
|
55
|
+
console.log();
|
|
56
|
+
console.log('Usage:');
|
|
57
|
+
console.log(' 1. Copy the prompt file content');
|
|
58
|
+
console.log(' 2. Paste it into your AI coding assistant');
|
|
59
|
+
console.log(' 3. Follow the implementation guidelines');
|
|
60
|
+
console.log(' 4. Update task status after completion');
|
|
61
|
+
console.log();
|
|
62
|
+
|
|
63
|
+
// Tool-specific tips
|
|
64
|
+
if (targetTool === 'claude-code') {
|
|
65
|
+
console.log(chalk.blue('💡 Claude Code Tips:'));
|
|
66
|
+
console.log(' • Copy the entire prompt into the chat');
|
|
67
|
+
console.log(' • Reference specific sections as needed');
|
|
68
|
+
} else if (targetTool === 'cursor') {
|
|
69
|
+
console.log(chalk.blue('💡 Cursor Tips:'));
|
|
70
|
+
console.log(' • Paste the prompt into the composer');
|
|
71
|
+
console.log(' • Use Cmd+K to apply changes');
|
|
72
|
+
} else if (targetTool === 'codex') {
|
|
73
|
+
console.log(chalk.blue('💡 GitHub Copilot Tips:'));
|
|
74
|
+
console.log(' • Include the prompt in code comments');
|
|
75
|
+
console.log(' • Let Copilot suggest implementations');
|
|
76
|
+
} else if (targetTool === 'kiro') {
|
|
77
|
+
console.log(chalk.blue('💡 Kiro IDE Tips:'));
|
|
78
|
+
console.log(' • Steering rules are loaded automatically');
|
|
79
|
+
console.log(' • Use #File to reference specific files');
|
|
80
|
+
}
|
|
81
|
+
} else {
|
|
82
|
+
console.log(chalk.red('❌ Prompt generation failed'));
|
|
83
|
+
console.log();
|
|
84
|
+
console.log(`Error: ${result.error}`);
|
|
85
|
+
}
|
|
86
|
+
} catch (error) {
|
|
87
|
+
console.log(chalk.red('❌ Error:'), error.message);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Format bytes to human-readable string
|
|
93
|
+
*
|
|
94
|
+
* @param {number} bytes - Bytes
|
|
95
|
+
* @returns {string} Formatted string
|
|
96
|
+
*/
|
|
97
|
+
function formatBytes(bytes) {
|
|
98
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
99
|
+
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
100
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
module.exports = {
|
|
104
|
+
generatePrompt
|
|
105
|
+
};
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Repository Management Command Group
|
|
3
|
+
*
|
|
4
|
+
* Manages multiple Git subrepositories within a single project
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const chalk = require('chalk');
|
|
8
|
+
const InitHandler = require('../repo/handlers/init-handler');
|
|
9
|
+
const StatusHandler = require('../repo/handlers/status-handler');
|
|
10
|
+
const ExecHandler = require('../repo/handlers/exec-handler');
|
|
11
|
+
const HealthHandler = require('../repo/handlers/health-handler');
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Initialize repository configuration
|
|
15
|
+
*
|
|
16
|
+
* @param {Object} options - Command options
|
|
17
|
+
* @param {boolean} options.yes - Skip confirmation prompts
|
|
18
|
+
* @param {number} options.maxDepth - Maximum scan depth
|
|
19
|
+
* @param {string} options.exclude - Comma-separated paths to exclude
|
|
20
|
+
* @param {boolean} options.nested - Enable nested repository scanning (default: true)
|
|
21
|
+
* @returns {Promise<void>}
|
|
22
|
+
*/
|
|
23
|
+
async function initRepo(options = {}) {
|
|
24
|
+
const projectPath = process.cwd();
|
|
25
|
+
const handler = new InitHandler(projectPath);
|
|
26
|
+
|
|
27
|
+
console.log(chalk.red('🔥') + ' Initializing Repository Configuration');
|
|
28
|
+
console.log();
|
|
29
|
+
|
|
30
|
+
try {
|
|
31
|
+
await handler.execute({
|
|
32
|
+
skipConfirmation: options.yes,
|
|
33
|
+
maxDepth: options.maxDepth,
|
|
34
|
+
exclude: options.exclude ? options.exclude.split(',').map(p => p.trim()) : [],
|
|
35
|
+
nested: options.nested !== false // Default to true, false only if --no-nested is used
|
|
36
|
+
});
|
|
37
|
+
} catch (error) {
|
|
38
|
+
console.log(chalk.red('❌ Error:'), error.message);
|
|
39
|
+
process.exit(1);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Display repository status
|
|
45
|
+
*
|
|
46
|
+
* @param {Object} options - Command options
|
|
47
|
+
* @param {boolean} options.verbose - Show detailed status
|
|
48
|
+
* @returns {Promise<void>}
|
|
49
|
+
*/
|
|
50
|
+
async function statusRepo(options = {}) {
|
|
51
|
+
const projectPath = process.cwd();
|
|
52
|
+
const handler = new StatusHandler(projectPath);
|
|
53
|
+
|
|
54
|
+
console.log(chalk.red('🔥') + ' Repository Status');
|
|
55
|
+
console.log();
|
|
56
|
+
|
|
57
|
+
try {
|
|
58
|
+
await handler.execute({
|
|
59
|
+
verbose: options.verbose
|
|
60
|
+
});
|
|
61
|
+
} catch (error) {
|
|
62
|
+
console.log(chalk.red('❌ Error:'), error.message);
|
|
63
|
+
process.exit(1);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Execute command across repositories
|
|
69
|
+
*
|
|
70
|
+
* @param {string} command - Git command to execute
|
|
71
|
+
* @param {Object} options - Command options
|
|
72
|
+
* @param {boolean} options.dryRun - Show commands without executing
|
|
73
|
+
* @returns {Promise<void>}
|
|
74
|
+
*/
|
|
75
|
+
async function execRepo(command, options = {}) {
|
|
76
|
+
const projectPath = process.cwd();
|
|
77
|
+
const handler = new ExecHandler(projectPath);
|
|
78
|
+
|
|
79
|
+
console.log(chalk.red('🔥') + ' Executing Command Across Repositories');
|
|
80
|
+
console.log();
|
|
81
|
+
|
|
82
|
+
try {
|
|
83
|
+
await handler.execute(command, {
|
|
84
|
+
dryRun: options.dryRun
|
|
85
|
+
});
|
|
86
|
+
} catch (error) {
|
|
87
|
+
console.log(chalk.red('❌ Error:'), error.message);
|
|
88
|
+
process.exit(1);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Check repository health
|
|
94
|
+
*
|
|
95
|
+
* @param {Object} options - Command options
|
|
96
|
+
* @returns {Promise<void>}
|
|
97
|
+
*/
|
|
98
|
+
async function healthRepo(options = {}) {
|
|
99
|
+
const projectPath = process.cwd();
|
|
100
|
+
const handler = new HealthHandler(projectPath);
|
|
101
|
+
|
|
102
|
+
console.log(chalk.red('🔥') + ' Repository Health Check');
|
|
103
|
+
console.log();
|
|
104
|
+
|
|
105
|
+
try {
|
|
106
|
+
await handler.execute(options);
|
|
107
|
+
} catch (error) {
|
|
108
|
+
console.log(chalk.red('❌ Error:'), error.message);
|
|
109
|
+
process.exit(1);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
module.exports = {
|
|
114
|
+
initRepo,
|
|
115
|
+
statusRepo,
|
|
116
|
+
execRepo,
|
|
117
|
+
healthRepo
|
|
118
|
+
};
|