bobs-workshop 0.1.4

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.
Files changed (94) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +252 -0
  3. package/bin/bobs-mcp.js +130 -0
  4. package/dist/api/taskLogger.js +106 -0
  5. package/dist/api/taskLogger.js.map +1 -0
  6. package/dist/cli/checker.js +401 -0
  7. package/dist/cli/checker.js.map +1 -0
  8. package/dist/cli/cleanup.js +131 -0
  9. package/dist/cli/cleanup.js.map +1 -0
  10. package/dist/cli/debug.js +157 -0
  11. package/dist/cli/debug.js.map +1 -0
  12. package/dist/cli/health.js +97 -0
  13. package/dist/cli/health.js.map +1 -0
  14. package/dist/cli/setup.js +81 -0
  15. package/dist/cli/setup.js.map +1 -0
  16. package/dist/cli/workshop.js +42 -0
  17. package/dist/cli/workshop.js.map +1 -0
  18. package/dist/dashboard/server.js +1206 -0
  19. package/dist/dashboard/server.js.map +1 -0
  20. package/dist/index.js +757 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/prompts/architect.js +157 -0
  23. package/dist/prompts/architect.js.map +1 -0
  24. package/dist/prompts/debugger.js +201 -0
  25. package/dist/prompts/debugger.js.map +1 -0
  26. package/dist/prompts/engineer.js +171 -0
  27. package/dist/prompts/engineer.js.map +1 -0
  28. package/dist/prompts/orchestrator.js +225 -0
  29. package/dist/prompts/orchestrator.js.map +1 -0
  30. package/dist/prompts/reviewer.js +199 -0
  31. package/dist/prompts/reviewer.js.map +1 -0
  32. package/dist/services/activitySummarizer.js +353 -0
  33. package/dist/services/activitySummarizer.js.map +1 -0
  34. package/dist/services/changeValidator.js +396 -0
  35. package/dist/services/changeValidator.js.map +1 -0
  36. package/dist/services/claudeOrchestrator.js +343 -0
  37. package/dist/services/claudeOrchestrator.js.map +1 -0
  38. package/dist/services/fileMonitor.js +250 -0
  39. package/dist/services/fileMonitor.js.map +1 -0
  40. package/dist/services/implementationSummarizer.js +306 -0
  41. package/dist/services/implementationSummarizer.js.map +1 -0
  42. package/dist/services/liveMonitor.js +315 -0
  43. package/dist/services/liveMonitor.js.map +1 -0
  44. package/dist/services/mcpAuditLogger.js +104 -0
  45. package/dist/services/mcpAuditLogger.js.map +1 -0
  46. package/dist/services/mcpLogger.js +223 -0
  47. package/dist/services/mcpLogger.js.map +1 -0
  48. package/dist/services/tmuxManager.js +541 -0
  49. package/dist/services/tmuxManager.js.map +1 -0
  50. package/dist/tools/approvalTools.js +244 -0
  51. package/dist/tools/approvalTools.js.map +1 -0
  52. package/dist/tools/autoDebugger.js +147 -0
  53. package/dist/tools/autoDebugger.js.map +1 -0
  54. package/dist/tools/cleanupService.js +221 -0
  55. package/dist/tools/cleanupService.js.map +1 -0
  56. package/dist/tools/dashboardTools.js +359 -0
  57. package/dist/tools/dashboardTools.js.map +1 -0
  58. package/dist/tools/developmentNudges.js +336 -0
  59. package/dist/tools/developmentNudges.js.map +1 -0
  60. package/dist/tools/gitTools.js +741 -0
  61. package/dist/tools/gitTools.js.map +1 -0
  62. package/dist/tools/orchestratorTools.js +765 -0
  63. package/dist/tools/orchestratorTools.js.map +1 -0
  64. package/dist/tools/searchTools.js +788 -0
  65. package/dist/tools/searchTools.js.map +1 -0
  66. package/dist/tools/specTools.js +350 -0
  67. package/dist/tools/specTools.js.map +1 -0
  68. package/dist/tools/tmuxTools.js +100 -0
  69. package/dist/tools/tmuxTools.js.map +1 -0
  70. package/dist/tools/workRecorder.js +215 -0
  71. package/dist/tools/workRecorder.js.map +1 -0
  72. package/dist/tools/worktreeTools.js +705 -0
  73. package/dist/tools/worktreeTools.js.map +1 -0
  74. package/dist/utils/__tests__/integration.test.js +57 -0
  75. package/dist/utils/__tests__/integration.test.js.map +1 -0
  76. package/dist/utils/__tests__/serverDetection.test.js +151 -0
  77. package/dist/utils/__tests__/serverDetection.test.js.map +1 -0
  78. package/dist/utils/errorHandling.js +336 -0
  79. package/dist/utils/errorHandling.js.map +1 -0
  80. package/dist/utils/processManager.js +172 -0
  81. package/dist/utils/processManager.js.map +1 -0
  82. package/dist/utils/reliability.js +263 -0
  83. package/dist/utils/reliability.js.map +1 -0
  84. package/dist/utils/responseFormatter.js +250 -0
  85. package/dist/utils/responseFormatter.js.map +1 -0
  86. package/dist/utils/serverDetection.js +133 -0
  87. package/dist/utils/serverDetection.js.map +1 -0
  88. package/dist/utils/specMigration.js +105 -0
  89. package/dist/utils/specMigration.js.map +1 -0
  90. package/dist/validation/schemas.js +299 -0
  91. package/dist/validation/schemas.js.map +1 -0
  92. package/package.json +79 -0
  93. package/scripts/init-workspace.js +63 -0
  94. package/scripts/install-search-tools.js +116 -0
@@ -0,0 +1,250 @@
1
+ import fs from "fs-extra";
2
+ import path from "path";
3
+ // Enhanced icons for different states and modes
4
+ const MODE_ICONS = {
5
+ orchestrator: 'šŸŽÆ',
6
+ architect: 'šŸ“',
7
+ engineer: 'āš™ļø',
8
+ debugger: 'šŸ›',
9
+ reviewer: 'šŸ”',
10
+ unknown: 'šŸ”§'
11
+ };
12
+ const STATUS_ICONS = {
13
+ // Main spec states
14
+ draft: 'šŸ“',
15
+ ready: 'āœ…',
16
+ engineered: 'šŸš€',
17
+ done: 'šŸŽ‰',
18
+ // Debug resolution states
19
+ fixed: 'āœ…',
20
+ escalated: 'ā¬†ļø',
21
+ pending: 'ā³',
22
+ // Workflow step states
23
+ questioning: 'ā“',
24
+ spec_review: 'šŸ‘€',
25
+ approved: 'āœ…',
26
+ implementation: 'āš™ļø',
27
+ user_review: 'šŸ‘Øā€šŸ’»',
28
+ completed: 'šŸŽ‰',
29
+ routed_to_architect: 'šŸ“',
30
+ routed_to_engineer: 'āš™ļø',
31
+ routed_to_debugger: 'šŸ›',
32
+ routed_to_reviewer: 'šŸ”',
33
+ // Action states
34
+ clarify: 'ā“',
35
+ route: 'āž”ļø',
36
+ continue: 'ā–¶ļø',
37
+ await_approval: 'āøļø',
38
+ proceed: 'ā–¶ļø',
39
+ complete: 'šŸŽ‰',
40
+ // Additional states
41
+ debug: 'šŸ”§',
42
+ error: 'āŒ',
43
+ failed: 'šŸ’„',
44
+ success: 'āœ…',
45
+ healthy: 'šŸ’š',
46
+ degraded: 'āš ļø',
47
+ unknown: 'ā“'
48
+ };
49
+ const TOOL_ICONS = {
50
+ 'manual.create': 'šŸ“‹',
51
+ 'manual.update': 'āœļø',
52
+ 'manual.get': 'šŸ“–',
53
+ 'search.hybrid': 'šŸ”',
54
+ 'workflow.start': 'šŸš€',
55
+ 'workflow.deploy': 'šŸŽÆ',
56
+ 'health': 'šŸ’š',
57
+ 'validate': 'āœ…',
58
+ 'cleanup': '🧹',
59
+ 'dashboard': 'šŸ’»'
60
+ };
61
+ /**
62
+ * Detects the current mode based on context clues
63
+ */
64
+ function detectMode(toolName, result) {
65
+ // Try to detect from tool context
66
+ if (toolName?.includes('workflow.start'))
67
+ return 'architect';
68
+ if (toolName?.includes('workflow.deploy'))
69
+ return 'engineer';
70
+ if (toolName?.includes('search') && result?.phase)
71
+ return result.phase;
72
+ if (toolName?.includes('manual.create'))
73
+ return 'architect';
74
+ if (toolName?.includes('debug') || toolName?.includes('validate'))
75
+ return 'debugger';
76
+ if (toolName?.includes('health') || toolName?.includes('cleanup'))
77
+ return 'engineer';
78
+ // Check for activity logs that might indicate mode
79
+ if (result?.activity) {
80
+ const recentActivity = result.activity[result.activity.length - 1];
81
+ if (recentActivity?.role === 'engineer')
82
+ return 'engineer';
83
+ if (recentActivity?.role === 'debugger')
84
+ return 'debugger';
85
+ if (recentActivity?.role === 'architect')
86
+ return 'architect';
87
+ if (recentActivity?.role === 'reviewer')
88
+ return 'reviewer';
89
+ }
90
+ // Check process environment or arguments for mode hints
91
+ try {
92
+ const args = process.argv.join(' ').toLowerCase();
93
+ if (args.includes('architect'))
94
+ return 'architect';
95
+ if (args.includes('engineer'))
96
+ return 'engineer';
97
+ if (args.includes('debugger'))
98
+ return 'debugger';
99
+ if (args.includes('reviewer'))
100
+ return 'reviewer';
101
+ if (args.includes('orchestrator'))
102
+ return 'orchestrator';
103
+ }
104
+ catch (error) {
105
+ // Ignore errors in process inspection
106
+ }
107
+ return 'unknown';
108
+ }
109
+ /**
110
+ * Gets manual status for a given spec_id
111
+ */
112
+ async function getManualStatus(specId) {
113
+ try {
114
+ const specsDir = path.resolve(process.cwd(), ".bob/specs");
115
+ const filePath = path.join(specsDir, `${specId}.json`);
116
+ if (await fs.pathExists(filePath)) {
117
+ const specData = await fs.readJson(filePath);
118
+ return specData.state || 'unknown';
119
+ }
120
+ }
121
+ catch (error) {
122
+ // Silently fail and return unknown
123
+ }
124
+ return 'unknown';
125
+ }
126
+ export async function formatConciseResponse(toolName, result, options = {}) {
127
+ const { includeTimestamp = true, maxContentLength = 100, showMetadata = true, mode = options.mode || detectMode(toolName, result), specId = result.spec_id } = options;
128
+ // Get tool icon
129
+ const toolKey = Object.keys(TOOL_ICONS).find(key => toolName.includes(key)) || 'unknown';
130
+ const toolIcon = TOOL_ICONS[toolKey] || 'šŸ”§';
131
+ // Get mode and status information
132
+ const modeIcon = MODE_ICONS[mode] || MODE_ICONS.unknown;
133
+ let statusInfo = '';
134
+ if (specId) {
135
+ try {
136
+ const status = await getManualStatus(specId);
137
+ const statusIcon = STATUS_ICONS[status] || STATUS_ICONS.unknown;
138
+ statusInfo = ` ${statusIcon} ${status}`;
139
+ }
140
+ catch (error) {
141
+ // Silently handle error
142
+ }
143
+ }
144
+ // Default to just the summary if available
145
+ if (result._meta?.summary) {
146
+ return `${toolIcon} ${result._meta.summary}${statusInfo}`;
147
+ }
148
+ // Handle different tool types with enhanced formatting
149
+ let baseMessage = '';
150
+ switch (true) {
151
+ case toolName.includes('manual.update'):
152
+ baseMessage = formatManualUpdateResponse(result, maxContentLength);
153
+ break;
154
+ case toolName.includes('manual.create'):
155
+ baseMessage = formatManualCreateResponse(result);
156
+ break;
157
+ case toolName.includes('search'):
158
+ baseMessage = formatSearchResponse(result);
159
+ break;
160
+ case toolName.includes('workflow'):
161
+ baseMessage = formatWorkflowResponse(result);
162
+ break;
163
+ case toolName.includes('health'):
164
+ baseMessage = formatHealthResponse(result);
165
+ break;
166
+ default:
167
+ baseMessage = formatGenericResponse(result, maxContentLength);
168
+ }
169
+ // Add mode indicator if metadata is requested
170
+ const modeIndicator = showMetadata ? `${modeIcon} ` : '';
171
+ return `${toolIcon} ${modeIndicator}${baseMessage}${statusInfo}`;
172
+ }
173
+ function formatManualUpdateResponse(result, maxLength) {
174
+ const specId = result.spec_id || 'unknown';
175
+ const shortId = specId.split('-').pop() || specId;
176
+ const state = result.state || 'draft';
177
+ const timestamp = result.updated_at ? new Date(result.updated_at).toLocaleTimeString() : '';
178
+ return `Manual ${shortId} updated → ${state}${timestamp ? ` (${timestamp})` : ''}`;
179
+ }
180
+ function formatManualCreateResponse(result) {
181
+ const specId = result.spec_id || 'unknown';
182
+ const shortId = specId.split('-').pop() || specId;
183
+ const state = result.state || 'draft';
184
+ return `Manual created: ${shortId} → ${state}`;
185
+ }
186
+ function formatSearchResponse(result) {
187
+ if (result.stats?.totalResults !== undefined) {
188
+ const count = result.stats.totalResults;
189
+ const mode = result.stats.searchMode || 'hybrid';
190
+ return `Search (${mode}): ${count} result${count !== 1 ? 's' : ''} found`;
191
+ }
192
+ if (result.lexicalHits && result.semanticHits) {
193
+ const lexical = result.lexicalHits.length;
194
+ const semantic = result.semanticHits.length;
195
+ const total = lexical + semantic;
196
+ return `Search: ${total} results (${lexical} lexical, ${semantic} semantic)`;
197
+ }
198
+ return 'Search completed';
199
+ }
200
+ function formatWorkflowResponse(result) {
201
+ const workflowStatus = result.workflow_status;
202
+ if (workflowStatus === 'started' && result.manual?.spec_id) {
203
+ const shortId = result.manual.spec_id.split('-').pop() || 'manual';
204
+ return `Workflow started for ${shortId}`;
205
+ }
206
+ if (workflowStatus === 'deployed') {
207
+ return 'Workflow deployed successfully';
208
+ }
209
+ return `Workflow ${workflowStatus || 'completed'}`;
210
+ }
211
+ function formatHealthResponse(result) {
212
+ const status = result.status || (result.overall_healthy ? 'healthy' : 'degraded');
213
+ const componentCount = result.component_health ? Object.keys(result.component_health).length : 0;
214
+ return `System ${status}${componentCount > 0 ? ` (${componentCount} components checked)` : ''}`;
215
+ }
216
+ function formatGenericResponse(result, maxLength) {
217
+ if (typeof result === 'string') {
218
+ return result.length > maxLength ? result.substring(0, maxLength) + '...' : result;
219
+ }
220
+ if (result.message) {
221
+ return result.message.length > maxLength ? result.message.substring(0, maxLength) + '...' : result.message;
222
+ }
223
+ return 'Operation completed';
224
+ }
225
+ /**
226
+ * Creates activity log entries with different verbosity levels:
227
+ * - Terminal: Concise for clean command line output
228
+ * - Dashboard: Enhanced with specific task details and context
229
+ */
230
+ export function formatConciseActivityLog(action, details, maxLength = 80) {
231
+ switch (action) {
232
+ case 'section_updated':
233
+ const section = details.section?.replace(/_/g, ' ') || 'section';
234
+ const wordCount = details.wordCount || 0;
235
+ return `Updated ${section} (${wordCount} words)`;
236
+ case 'execution_log':
237
+ const filesCount = details.filesCount || 0;
238
+ const taskId = details.taskId || 'task';
239
+ return `šŸ› ļø ${taskId}: ${filesCount} files modified`;
240
+ case 'debug_log':
241
+ const confidence = details.confidence || 'medium';
242
+ return `šŸ› Debug issue resolved (confidence: ${confidence})`;
243
+ case 'state_change':
244
+ return `State: ${details.oldState} → ${details.newState}`;
245
+ default:
246
+ const summary = typeof details === 'string' ? details : details.summary || 'Activity logged';
247
+ return summary.length > maxLength ? summary.substring(0, maxLength) + '...' : summary;
248
+ }
249
+ }
250
+ //# sourceMappingURL=responseFormatter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"responseFormatter.js","sourceRoot":"","sources":["../../src/utils/responseFormatter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,133 @@
1
+ // src/utils/serverDetection.ts
2
+ import fs from "fs";
3
+ import path from "path";
4
+ /**
5
+ * Detects the project type based on files in the directory
6
+ */
7
+ export function detectProjectType(projectPath) {
8
+ try {
9
+ // Check for Node.js project
10
+ if (fs.existsSync(path.join(projectPath, 'package.json'))) {
11
+ return 'node';
12
+ }
13
+ // Check for Go project
14
+ if (fs.existsSync(path.join(projectPath, 'go.mod'))) {
15
+ return 'go';
16
+ }
17
+ // Check for Python project
18
+ if (fs.existsSync(path.join(projectPath, 'requirements.txt'))) {
19
+ return 'python';
20
+ }
21
+ return null;
22
+ }
23
+ catch (error) {
24
+ console.warn(`Error detecting project type in ${projectPath}:`, error);
25
+ return null;
26
+ }
27
+ }
28
+ /**
29
+ * Gets server configuration based on project type and detected settings
30
+ */
31
+ export async function getServerConfig(projectPath, projectType) {
32
+ if (!projectType) {
33
+ return null;
34
+ }
35
+ try {
36
+ switch (projectType) {
37
+ case 'node':
38
+ return await getNodeServerConfig(projectPath);
39
+ case 'go':
40
+ return getGoServerConfig(projectPath);
41
+ case 'python':
42
+ return getPythonServerConfig(projectPath);
43
+ default:
44
+ return null;
45
+ }
46
+ }
47
+ catch (error) {
48
+ console.warn(`Error getting server config for ${projectType}:`, error);
49
+ return null;
50
+ }
51
+ }
52
+ /**
53
+ * Gets Node.js server configuration by reading package.json
54
+ */
55
+ async function getNodeServerConfig(projectPath) {
56
+ const packageJsonPath = path.join(projectPath, 'package.json');
57
+ try {
58
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
59
+ const scripts = packageJson.scripts || {};
60
+ // Determine dev command
61
+ let devCommand = 'npm start';
62
+ if (scripts.dev) {
63
+ devCommand = 'npm run dev';
64
+ }
65
+ else if (scripts.start) {
66
+ devCommand = 'npm start';
67
+ }
68
+ else if (scripts.serve) {
69
+ devCommand = 'npm run serve';
70
+ }
71
+ return {
72
+ startupScript: 'npm install',
73
+ devCommand,
74
+ port: 3000, // Common default for Node.js apps
75
+ healthCheckUrl: 'http://localhost:3000'
76
+ };
77
+ }
78
+ catch (error) {
79
+ // Fallback configuration
80
+ return {
81
+ startupScript: 'npm install',
82
+ devCommand: 'npm start',
83
+ port: 3000
84
+ };
85
+ }
86
+ }
87
+ /**
88
+ * Gets Go server configuration
89
+ */
90
+ function getGoServerConfig(projectPath) {
91
+ // Check if main.go exists
92
+ const hasMainGo = fs.existsSync(path.join(projectPath, 'main.go'));
93
+ return {
94
+ devCommand: hasMainGo ? 'go run main.go' : 'go run .',
95
+ port: 8080, // Common default for Go apps
96
+ healthCheckUrl: 'http://localhost:8080'
97
+ };
98
+ }
99
+ /**
100
+ * Gets Python server configuration
101
+ */
102
+ function getPythonServerConfig(projectPath) {
103
+ // Check for common Python entry points
104
+ const hasAppPy = fs.existsSync(path.join(projectPath, 'app.py'));
105
+ const hasMainPy = fs.existsSync(path.join(projectPath, 'main.py'));
106
+ const hasManagePy = fs.existsSync(path.join(projectPath, 'manage.py'));
107
+ let devCommand = 'python app.py';
108
+ if (hasManagePy) {
109
+ // Django project
110
+ devCommand = 'python manage.py runserver';
111
+ }
112
+ else if (hasMainPy) {
113
+ devCommand = 'python main.py';
114
+ }
115
+ else if (hasAppPy) {
116
+ devCommand = 'python app.py';
117
+ }
118
+ return {
119
+ startupScript: 'pip install -r requirements.txt',
120
+ devCommand,
121
+ port: 5000, // Common default for Python apps
122
+ healthCheckUrl: 'http://localhost:5000'
123
+ };
124
+ }
125
+ /**
126
+ * Validates if a server configuration is valid
127
+ */
128
+ export function validateServerConfig(config) {
129
+ if (!config)
130
+ return false;
131
+ return Boolean(config.devCommand && config.devCommand.trim().length > 0);
132
+ }
133
+ //# sourceMappingURL=serverDetection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serverDetection.js","sourceRoot":"","sources":["../../src/utils/serverDetection.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,105 @@
1
+ // src/utils/specMigration.ts
2
+ import fs from "fs-extra";
3
+ import path from "path";
4
+ const DEFAULT_WORKTREE_METADATA = {
5
+ path: null,
6
+ branch: null,
7
+ status: "pending",
8
+ createdAt: null,
9
+ lastActivity: null,
10
+ specPath: null,
11
+ validation: {
12
+ isClean: false,
13
+ hasChanges: false,
14
+ lastChecked: null
15
+ }
16
+ };
17
+ /**
18
+ * Migrate a single SPEC file to include worktree metadata
19
+ */
20
+ export async function migrateSpecFile(specFilePath) {
21
+ try {
22
+ if (!await fs.pathExists(specFilePath)) {
23
+ console.warn(`SPEC file not found: ${specFilePath}`);
24
+ return false;
25
+ }
26
+ const specData = await fs.readJson(specFilePath);
27
+ // Check if migration is needed
28
+ if (specData.worktree) {
29
+ console.log(`SPEC ${specData.spec_id} already has worktree metadata, skipping migration`);
30
+ return false;
31
+ }
32
+ // Add worktree metadata
33
+ specData.worktree = DEFAULT_WORKTREE_METADATA;
34
+ specData.updated_at = new Date().toISOString();
35
+ // Write back to file
36
+ await fs.writeFile(specFilePath, JSON.stringify(specData, null, 2), "utf8");
37
+ console.log(`āœ… Migrated SPEC ${specData.spec_id} to include worktree metadata`);
38
+ return true;
39
+ }
40
+ catch (error) {
41
+ console.error(`āŒ Failed to migrate SPEC file ${specFilePath}:`, error);
42
+ return false;
43
+ }
44
+ }
45
+ /**
46
+ * Migrate all SPEC files in the .bob/specs directory
47
+ */
48
+ export async function migrateAllSpecs() {
49
+ const specsDir = path.resolve(process.cwd(), ".bob/specs");
50
+ if (!await fs.pathExists(specsDir)) {
51
+ console.warn("Specs directory not found, no migration needed");
52
+ return { total: 0, migrated: 0, skipped: 0, failed: 0 };
53
+ }
54
+ const files = await fs.readdir(specsDir);
55
+ const specFiles = files.filter(file => file.startsWith("SPEC-") && file.endsWith(".json"));
56
+ let migrated = 0;
57
+ let skipped = 0;
58
+ let failed = 0;
59
+ console.log(`\nšŸ”„ Starting migration of ${specFiles.length} SPEC files...\n`);
60
+ for (const specFile of specFiles) {
61
+ const specFilePath = path.join(specsDir, specFile);
62
+ try {
63
+ const wasMigrated = await migrateSpecFile(specFilePath);
64
+ if (wasMigrated) {
65
+ migrated++;
66
+ }
67
+ else {
68
+ skipped++;
69
+ }
70
+ }
71
+ catch (error) {
72
+ console.error(`Failed to migrate ${specFile}:`, error);
73
+ failed++;
74
+ }
75
+ }
76
+ const results = {
77
+ total: specFiles.length,
78
+ migrated,
79
+ skipped,
80
+ failed
81
+ };
82
+ console.log(`\nšŸ“Š Migration Summary:`);
83
+ console.log(` Total SPEC files: ${results.total}`);
84
+ console.log(` āœ… Migrated: ${results.migrated}`);
85
+ console.log(` ā­ļø Skipped (already migrated): ${results.skipped}`);
86
+ console.log(` āŒ Failed: ${results.failed}\n`);
87
+ return results;
88
+ }
89
+ /**
90
+ * Check if a SPEC file needs migration
91
+ */
92
+ export async function needsMigration(specFilePath) {
93
+ try {
94
+ if (!await fs.pathExists(specFilePath)) {
95
+ return false;
96
+ }
97
+ const specData = await fs.readJson(specFilePath);
98
+ return !specData.worktree;
99
+ }
100
+ catch (error) {
101
+ console.error(`Error checking migration status for ${specFilePath}:`, error);
102
+ return false;
103
+ }
104
+ }
105
+ //# sourceMappingURL=specMigration.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"specMigration.js","sourceRoot":"","sources":["../../src/utils/specMigration.ts"],"names":[],"mappings":"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"}