@hyperdrive.bot/gut 0.1.3 → 0.1.6

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 (87) hide show
  1. package/README.md +1 -779
  2. package/bin/run.js +5 -0
  3. package/package.json +10 -10
  4. package/bin/run +0 -5
  5. package/dist/base-command.d.ts +0 -21
  6. package/dist/base-command.js +0 -110
  7. package/dist/commands/add.d.ts +0 -13
  8. package/dist/commands/add.js +0 -73
  9. package/dist/commands/affected.d.ts +0 -23
  10. package/dist/commands/affected.js +0 -326
  11. package/dist/commands/audit.d.ts +0 -33
  12. package/dist/commands/audit.js +0 -593
  13. package/dist/commands/back.d.ts +0 -6
  14. package/dist/commands/back.js +0 -29
  15. package/dist/commands/commit.d.ts +0 -11
  16. package/dist/commands/commit.js +0 -113
  17. package/dist/commands/context.d.ts +0 -6
  18. package/dist/commands/context.js +0 -36
  19. package/dist/commands/contexts.d.ts +0 -7
  20. package/dist/commands/contexts.js +0 -92
  21. package/dist/commands/deps.d.ts +0 -10
  22. package/dist/commands/deps.js +0 -104
  23. package/dist/commands/entity/add.d.ts +0 -16
  24. package/dist/commands/entity/add.js +0 -105
  25. package/dist/commands/entity/clone-all.d.ts +0 -17
  26. package/dist/commands/entity/clone-all.js +0 -135
  27. package/dist/commands/entity/clone.d.ts +0 -15
  28. package/dist/commands/entity/clone.js +0 -109
  29. package/dist/commands/entity/list.d.ts +0 -11
  30. package/dist/commands/entity/list.js +0 -82
  31. package/dist/commands/entity/remove.d.ts +0 -12
  32. package/dist/commands/entity/remove.js +0 -58
  33. package/dist/commands/focus.d.ts +0 -19
  34. package/dist/commands/focus.js +0 -139
  35. package/dist/commands/graph.d.ts +0 -18
  36. package/dist/commands/graph.js +0 -238
  37. package/dist/commands/init.d.ts +0 -11
  38. package/dist/commands/init.js +0 -84
  39. package/dist/commands/insights.d.ts +0 -21
  40. package/dist/commands/insights.js +0 -434
  41. package/dist/commands/patterns.d.ts +0 -40
  42. package/dist/commands/patterns.js +0 -412
  43. package/dist/commands/pull.d.ts +0 -11
  44. package/dist/commands/pull.js +0 -121
  45. package/dist/commands/push.d.ts +0 -11
  46. package/dist/commands/push.js +0 -101
  47. package/dist/commands/quick-setup.d.ts +0 -20
  48. package/dist/commands/quick-setup.js +0 -422
  49. package/dist/commands/recent.d.ts +0 -9
  50. package/dist/commands/recent.js +0 -55
  51. package/dist/commands/related.d.ts +0 -23
  52. package/dist/commands/related.js +0 -257
  53. package/dist/commands/repos.d.ts +0 -14
  54. package/dist/commands/repos.js +0 -185
  55. package/dist/commands/stack.d.ts +0 -10
  56. package/dist/commands/stack.js +0 -83
  57. package/dist/commands/status.d.ts +0 -14
  58. package/dist/commands/status.js +0 -246
  59. package/dist/commands/sync.d.ts +0 -11
  60. package/dist/commands/sync.js +0 -142
  61. package/dist/commands/unfocus.d.ts +0 -6
  62. package/dist/commands/unfocus.js +0 -23
  63. package/dist/commands/used-by.d.ts +0 -10
  64. package/dist/commands/used-by.js +0 -111
  65. package/dist/commands/workspace.d.ts +0 -20
  66. package/dist/commands/workspace.js +0 -365
  67. package/dist/index.d.ts +0 -1
  68. package/dist/index.js +0 -5
  69. package/dist/models/entity.model.d.ts +0 -81
  70. package/dist/models/entity.model.js +0 -2
  71. package/dist/services/config.service.d.ts +0 -34
  72. package/dist/services/config.service.js +0 -230
  73. package/dist/services/entity.service.d.ts +0 -19
  74. package/dist/services/entity.service.js +0 -130
  75. package/dist/services/focus.service.d.ts +0 -70
  76. package/dist/services/focus.service.js +0 -587
  77. package/dist/services/git.service.d.ts +0 -37
  78. package/dist/services/git.service.js +0 -180
  79. package/dist/utils/display.d.ts +0 -25
  80. package/dist/utils/display.js +0 -150
  81. package/dist/utils/filesystem.d.ts +0 -32
  82. package/dist/utils/filesystem.js +0 -220
  83. package/dist/utils/index.d.ts +0 -13
  84. package/dist/utils/index.js +0 -18
  85. package/dist/utils/validation.d.ts +0 -22
  86. package/dist/utils/validation.js +0 -196
  87. package/oclif.manifest.json +0 -1463
@@ -1,434 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const tslib_1 = require("tslib");
4
- const core_1 = require("@oclif/core");
5
- const base_command_1 = tslib_1.__importDefault(require("../base-command"));
6
- const fs = tslib_1.__importStar(require("fs"));
7
- const path = tslib_1.__importStar(require("path"));
8
- const child_process_1 = require("child_process");
9
- const chalk_1 = tslib_1.__importDefault(require("chalk"));
10
- const ora_1 = tslib_1.__importDefault(require("ora"));
11
- const cli_table3_1 = tslib_1.__importDefault(require("cli-table3"));
12
- class Insights extends base_command_1.default {
13
- static description = 'Display analytics and insights about the workspace';
14
- static examples = [
15
- '<%= config.bin %> <%= command.id %>',
16
- '<%= config.bin %> <%= command.id %> --detailed',
17
- '<%= config.bin %> <%= command.id %> --format json',
18
- ];
19
- static flags = {
20
- detailed: core_1.Flags.boolean({
21
- char: 'd',
22
- description: 'Show detailed statistics for each entity',
23
- default: false,
24
- }),
25
- format: core_1.Flags.string({
26
- char: 'f',
27
- description: 'Output format',
28
- options: ['table', 'json', 'summary'],
29
- default: 'table',
30
- }),
31
- 'include-ignored': core_1.Flags.boolean({
32
- description: 'Include gitignored files in statistics',
33
- default: false,
34
- }),
35
- };
36
- async run() {
37
- const { flags } = await this.parse(Insights);
38
- const { detailed, format, 'include-ignored': includeIgnored } = flags;
39
- const spinner = (0, ora_1.default)('Analyzing workspace').start();
40
- try {
41
- const entities = await this.entityService.listEntities();
42
- if (entities.length === 0) {
43
- spinner.fail('No entities found in workspace');
44
- this.log(chalk_1.default.yellow('Initialize your workspace with: gut init'));
45
- return;
46
- }
47
- const entityStats = [];
48
- for (const entity of entities) {
49
- const stats = await this.analyzeEntity(entity, includeIgnored);
50
- entityStats.push({ entity, stats });
51
- }
52
- const workspaceStats = this.calculateWorkspaceStats(entityStats);
53
- spinner.succeed('Analysis complete');
54
- switch (format) {
55
- case 'json':
56
- this.printJSON(workspaceStats, entityStats);
57
- break;
58
- case 'summary':
59
- this.printSummary(workspaceStats);
60
- break;
61
- case 'table':
62
- default:
63
- this.printTable(workspaceStats, entityStats, detailed);
64
- break;
65
- }
66
- }
67
- catch (error) {
68
- spinner.fail();
69
- this.error(error.message);
70
- }
71
- }
72
- async analyzeEntity(entity, includeIgnored) {
73
- const stats = {
74
- files: 0,
75
- lines: 0,
76
- size: '0B',
77
- languages: new Map(),
78
- lastCommit: 'N/A',
79
- contributors: 0,
80
- branches: 0,
81
- uncommitted: 0,
82
- };
83
- const entityPath = path.resolve(entity.path);
84
- if (!fs.existsSync(entityPath)) {
85
- return stats;
86
- }
87
- // Count files and lines
88
- const fileStats = this.countFiles(entityPath, includeIgnored);
89
- stats.files = fileStats.files;
90
- stats.lines = fileStats.lines;
91
- stats.size = this.formatSize(fileStats.size);
92
- stats.languages = fileStats.languages;
93
- // Git statistics
94
- if (fs.existsSync(path.join(entityPath, '.git'))) {
95
- try {
96
- // Last commit
97
- const lastCommit = (0, child_process_1.execSync)('git log -1 --format=%ar', {
98
- cwd: entityPath,
99
- encoding: 'utf-8',
100
- stdio: 'pipe',
101
- }).trim();
102
- stats.lastCommit = lastCommit;
103
- // Contributors
104
- const contributors = (0, child_process_1.execSync)('git shortlog -sn', {
105
- cwd: entityPath,
106
- encoding: 'utf-8',
107
- stdio: 'pipe',
108
- }).split('\n').filter(l => l.trim()).length;
109
- stats.contributors = contributors;
110
- // Branches
111
- const branches = (0, child_process_1.execSync)('git branch -a', {
112
- cwd: entityPath,
113
- encoding: 'utf-8',
114
- stdio: 'pipe',
115
- }).split('\n').filter(l => l.trim()).length;
116
- stats.branches = branches;
117
- // Uncommitted changes
118
- const status = (0, child_process_1.execSync)('git status --porcelain', {
119
- cwd: entityPath,
120
- encoding: 'utf-8',
121
- stdio: 'pipe',
122
- }).split('\n').filter(l => l.trim()).length;
123
- stats.uncommitted = status;
124
- }
125
- catch (error) {
126
- // Ignore git errors
127
- }
128
- }
129
- return stats;
130
- }
131
- countFiles(dir, includeIgnored) {
132
- const result = {
133
- files: 0,
134
- lines: 0,
135
- size: 0,
136
- languages: new Map(),
137
- };
138
- const shouldIgnore = (file) => {
139
- if (includeIgnored)
140
- return false;
141
- const ignoredPatterns = ['node_modules', '.git', 'dist', 'build', '.next', 'coverage'];
142
- return ignoredPatterns.some(pattern => file.includes(pattern));
143
- };
144
- const walkDir = (currentDir) => {
145
- try {
146
- const entries = fs.readdirSync(currentDir, { withFileTypes: true });
147
- for (const entry of entries) {
148
- const fullPath = path.join(currentDir, entry.name);
149
- if (shouldIgnore(fullPath))
150
- continue;
151
- if (entry.isDirectory()) {
152
- walkDir(fullPath);
153
- }
154
- else if (entry.isFile()) {
155
- result.files++;
156
- const stats = fs.statSync(fullPath);
157
- result.size += stats.size;
158
- const ext = path.extname(fullPath).toLowerCase();
159
- const lang = this.getLanguageFromExt(ext);
160
- if (lang) {
161
- result.languages.set(lang, (result.languages.get(lang) || 0) + 1);
162
- }
163
- // Count lines for text files
164
- if (this.isTextFile(fullPath)) {
165
- try {
166
- const content = fs.readFileSync(fullPath, 'utf-8');
167
- result.lines += content.split('\n').length;
168
- }
169
- catch (error) {
170
- // Ignore read errors
171
- }
172
- }
173
- }
174
- }
175
- }
176
- catch (error) {
177
- // Ignore permission errors
178
- }
179
- };
180
- walkDir(dir);
181
- return result;
182
- }
183
- getLanguageFromExt(ext) {
184
- const langMap = {
185
- '.js': 'JavaScript',
186
- '.jsx': 'JavaScript',
187
- '.ts': 'TypeScript',
188
- '.tsx': 'TypeScript',
189
- '.py': 'Python',
190
- '.java': 'Java',
191
- '.go': 'Go',
192
- '.rs': 'Rust',
193
- '.rb': 'Ruby',
194
- '.php': 'PHP',
195
- '.c': 'C',
196
- '.cpp': 'C++',
197
- '.cs': 'C#',
198
- '.swift': 'Swift',
199
- '.kt': 'Kotlin',
200
- '.scala': 'Scala',
201
- '.r': 'R',
202
- '.m': 'Objective-C',
203
- '.dart': 'Dart',
204
- '.vue': 'Vue',
205
- '.svelte': 'Svelte',
206
- '.json': 'JSON',
207
- '.yml': 'YAML',
208
- '.yaml': 'YAML',
209
- '.xml': 'XML',
210
- '.html': 'HTML',
211
- '.css': 'CSS',
212
- '.scss': 'SCSS',
213
- '.sass': 'Sass',
214
- '.less': 'Less',
215
- '.sql': 'SQL',
216
- '.sh': 'Shell',
217
- '.bash': 'Shell',
218
- '.md': 'Markdown',
219
- };
220
- return langMap[ext] || null;
221
- }
222
- isTextFile(filePath) {
223
- const textExts = [
224
- '.js', '.jsx', '.ts', '.tsx', '.json', '.md', '.txt',
225
- '.yml', '.yaml', '.xml', '.html', '.css', '.scss', '.sass',
226
- '.py', '.rb', '.go', '.rs', '.java', '.c', '.cpp', '.h',
227
- '.php', '.sql', '.sh', '.bash', '.env', '.gitignore'
228
- ];
229
- const ext = path.extname(filePath).toLowerCase();
230
- return textExts.includes(ext);
231
- }
232
- formatSize(bytes) {
233
- const units = ['B', 'KB', 'MB', 'GB'];
234
- let size = bytes;
235
- let unitIndex = 0;
236
- while (size >= 1024 && unitIndex < units.length - 1) {
237
- size /= 1024;
238
- unitIndex++;
239
- }
240
- return `${size.toFixed(1)}${units[unitIndex]}`;
241
- }
242
- calculateWorkspaceStats(entityStats) {
243
- let totalFiles = 0;
244
- let totalLines = 0;
245
- let totalSize = 0;
246
- const allLanguages = new Map();
247
- let mostActive = '';
248
- let mostActiveCommit = new Date(0);
249
- let leastActive = '';
250
- let leastActiveCommit = new Date();
251
- let largestEntity = '';
252
- let largestSize = 0;
253
- let smallestEntity = '';
254
- let smallestSize = Infinity;
255
- for (const { entity, stats } of entityStats) {
256
- totalFiles += stats.files;
257
- totalLines += stats.lines;
258
- // Parse size back to bytes for total
259
- const sizeMatch = stats.size.match(/(\d+\.?\d*)([BKMG])/);
260
- if (sizeMatch) {
261
- const value = parseFloat(sizeMatch[1]);
262
- const unit = sizeMatch[2];
263
- const multipliers = { B: 1, K: 1024, M: 1024 * 1024, G: 1024 * 1024 * 1024 };
264
- totalSize += value * multipliers[unit];
265
- }
266
- // Merge languages
267
- stats.languages.forEach((count, lang) => {
268
- allLanguages.set(lang, (allLanguages.get(lang) || 0) + count);
269
- });
270
- // Track most/least active
271
- if (stats.lastCommit !== 'N/A') {
272
- const commitDate = this.parseRelativeDate(stats.lastCommit);
273
- if (commitDate > mostActiveCommit) {
274
- mostActiveCommit = commitDate;
275
- mostActive = entity.name;
276
- }
277
- if (commitDate < leastActiveCommit) {
278
- leastActiveCommit = commitDate;
279
- leastActive = entity.name;
280
- }
281
- }
282
- // Track largest/smallest
283
- const entitySize = stats.files;
284
- if (entitySize > largestSize) {
285
- largestSize = entitySize;
286
- largestEntity = entity.name;
287
- }
288
- if (entitySize < smallestSize && entitySize > 0) {
289
- smallestSize = entitySize;
290
- smallestEntity = entity.name;
291
- }
292
- }
293
- return {
294
- totalEntities: entityStats.length,
295
- totalFiles,
296
- totalLines,
297
- totalSize: this.formatSize(totalSize),
298
- languages: allLanguages,
299
- mostActive,
300
- leastActive,
301
- largestEntity,
302
- smallestEntity,
303
- };
304
- }
305
- parseRelativeDate(relativeDate) {
306
- const now = new Date();
307
- const match = relativeDate.match(/(\d+)\s+(\w+)\s+ago/);
308
- if (!match)
309
- return now;
310
- const value = parseInt(match[1]);
311
- const unit = match[2];
312
- const date = new Date(now);
313
- switch (unit) {
314
- case 'second':
315
- case 'seconds':
316
- date.setSeconds(date.getSeconds() - value);
317
- break;
318
- case 'minute':
319
- case 'minutes':
320
- date.setMinutes(date.getMinutes() - value);
321
- break;
322
- case 'hour':
323
- case 'hours':
324
- date.setHours(date.getHours() - value);
325
- break;
326
- case 'day':
327
- case 'days':
328
- date.setDate(date.getDate() - value);
329
- break;
330
- case 'week':
331
- case 'weeks':
332
- date.setDate(date.getDate() - value * 7);
333
- break;
334
- case 'month':
335
- case 'months':
336
- date.setMonth(date.getMonth() - value);
337
- break;
338
- case 'year':
339
- case 'years':
340
- date.setFullYear(date.getFullYear() - value);
341
- break;
342
- }
343
- return date;
344
- }
345
- printTable(workspaceStats, entityStats, detailed) {
346
- // Workspace summary
347
- this.log('');
348
- this.log(chalk_1.default.bold.blue('📊 Workspace Insights'));
349
- this.log('');
350
- const summaryTable = new cli_table3_1.default({
351
- head: [chalk_1.default.cyan('Metric'), chalk_1.default.cyan('Value')],
352
- style: { head: [], border: [] }
353
- });
354
- summaryTable.push(['Total Entities', workspaceStats.totalEntities.toString()], ['Total Files', workspaceStats.totalFiles.toLocaleString()], ['Total Lines', workspaceStats.totalLines.toLocaleString()], ['Total Size', workspaceStats.totalSize], ['Most Active', workspaceStats.mostActive || 'N/A'], ['Largest Entity', workspaceStats.largestEntity || 'N/A']);
355
- this.log(summaryTable.toString());
356
- // Language distribution
357
- if (workspaceStats.languages.size > 0) {
358
- this.log('');
359
- this.log(chalk_1.default.bold('Language Distribution:'));
360
- const sortedLangs = Array.from(workspaceStats.languages.entries())
361
- .sort((a, b) => b[1] - a[1])
362
- .slice(0, 5);
363
- sortedLangs.forEach(([lang, count]) => {
364
- const percentage = ((count / workspaceStats.totalFiles) * 100).toFixed(1);
365
- const bar = '█'.repeat(Math.floor(parseFloat(percentage) / 2));
366
- this.log(` ${lang.padEnd(12)} ${bar} ${percentage}%`);
367
- });
368
- }
369
- // Entity details
370
- if (detailed) {
371
- this.log('');
372
- this.log(chalk_1.default.bold('Entity Details:'));
373
- const entityTable = new cli_table3_1.default({
374
- head: [
375
- chalk_1.default.cyan('Entity'),
376
- chalk_1.default.cyan('Files'),
377
- chalk_1.default.cyan('Lines'),
378
- chalk_1.default.cyan('Size'),
379
- chalk_1.default.cyan('Last Commit'),
380
- chalk_1.default.cyan('Changes'),
381
- ],
382
- style: { head: [], border: [] }
383
- });
384
- entityStats.forEach(({ entity, stats }) => {
385
- entityTable.push([
386
- entity.name,
387
- stats.files.toString(),
388
- stats.lines.toLocaleString(),
389
- stats.size,
390
- stats.lastCommit,
391
- stats.uncommitted > 0 ? chalk_1.default.yellow(stats.uncommitted.toString()) : '0',
392
- ]);
393
- });
394
- this.log(entityTable.toString());
395
- }
396
- this.log('');
397
- this.log(chalk_1.default.dim('Tip: Use --detailed flag for per-entity statistics'));
398
- }
399
- printSummary(workspaceStats) {
400
- this.log('');
401
- this.log(chalk_1.default.bold.blue('Workspace Summary'));
402
- this.log(chalk_1.default.dim('─'.repeat(40)));
403
- this.log(`Entities: ${workspaceStats.totalEntities}`);
404
- this.log(`Files: ${workspaceStats.totalFiles.toLocaleString()}`);
405
- this.log(`Lines: ${workspaceStats.totalLines.toLocaleString()}`);
406
- this.log(`Size: ${workspaceStats.totalSize}`);
407
- if (workspaceStats.languages.size > 0) {
408
- const topLang = Array.from(workspaceStats.languages.entries())
409
- .sort((a, b) => b[1] - a[1])[0];
410
- this.log(`Primary Language: ${topLang[0]}`);
411
- }
412
- this.log(`Most Active: ${workspaceStats.mostActive || 'N/A'}`);
413
- this.log(`Largest: ${workspaceStats.largestEntity || 'N/A'}`);
414
- }
415
- printJSON(workspaceStats, entityStats) {
416
- const output = {
417
- workspace: {
418
- ...workspaceStats,
419
- languages: Object.fromEntries(workspaceStats.languages),
420
- },
421
- entities: entityStats.map(({ entity, stats }) => ({
422
- name: entity.name,
423
- type: entity.type,
424
- path: entity.path,
425
- stats: {
426
- ...stats,
427
- languages: Object.fromEntries(stats.languages),
428
- },
429
- })),
430
- };
431
- this.log(JSON.stringify(output, null, 2));
432
- }
433
- }
434
- exports.default = Insights;
@@ -1,40 +0,0 @@
1
- import { BaseCommand } from '../base-command';
2
- export default class Patterns extends BaseCommand {
3
- static description: string;
4
- static examples: string[];
5
- static flags: {
6
- entity: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
7
- type: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
8
- mode: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
9
- json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
10
- };
11
- run(): Promise<void>;
12
- private analyzePatterns;
13
- private analyzeEntityPatterns;
14
- private analyzeTypePatterns;
15
- private analyzeModePatterns;
16
- private analyzeCrossEntityPatterns;
17
- private generateTemporalPatterns;
18
- private generateProductivityPatterns;
19
- private displayPatterns;
20
- private displayEntityPatterns;
21
- private displayTypePatterns;
22
- private displayModePatterns;
23
- private displayProductivityPatterns;
24
- private displayTemporalPatterns;
25
- private analyzeFilePatterns;
26
- private analyzeCollaborationPatterns;
27
- private calculateTypicalDuration;
28
- private getCommonModes;
29
- private analyzeRelationshipPatterns;
30
- private getSuccessMetrics;
31
- private getTypicalActivities;
32
- private getOptimalDuration;
33
- private getCommonTools;
34
- private getSuccessIndicators;
35
- private getTransitionPatterns;
36
- private findDependencyChains;
37
- private findSimilarClusters;
38
- private findSharedSystems;
39
- private findWorkflowSimilarities;
40
- }