tlc-claude-code 1.2.29 → 1.4.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/dashboard/dist/components/AuditPane.d.ts +30 -0
- package/dashboard/dist/components/AuditPane.js +127 -0
- package/dashboard/dist/components/AuditPane.test.d.ts +1 -0
- package/dashboard/dist/components/AuditPane.test.js +339 -0
- package/dashboard/dist/components/CompliancePane.d.ts +39 -0
- package/dashboard/dist/components/CompliancePane.js +96 -0
- package/dashboard/dist/components/CompliancePane.test.d.ts +1 -0
- package/dashboard/dist/components/CompliancePane.test.js +183 -0
- package/dashboard/dist/components/SSOPane.d.ts +36 -0
- package/dashboard/dist/components/SSOPane.js +71 -0
- package/dashboard/dist/components/SSOPane.test.d.ts +1 -0
- package/dashboard/dist/components/SSOPane.test.js +155 -0
- package/dashboard/dist/components/UsagePane.d.ts +13 -0
- package/dashboard/dist/components/UsagePane.js +51 -0
- package/dashboard/dist/components/UsagePane.test.d.ts +1 -0
- package/dashboard/dist/components/UsagePane.test.js +142 -0
- package/dashboard/dist/components/WorkspaceDocsPane.d.ts +19 -0
- package/dashboard/dist/components/WorkspaceDocsPane.js +130 -0
- package/dashboard/dist/components/WorkspaceDocsPane.test.d.ts +1 -0
- package/dashboard/dist/components/WorkspaceDocsPane.test.js +242 -0
- package/dashboard/dist/components/WorkspacePane.d.ts +18 -0
- package/dashboard/dist/components/WorkspacePane.js +17 -0
- package/dashboard/dist/components/WorkspacePane.test.d.ts +1 -0
- package/dashboard/dist/components/WorkspacePane.test.js +84 -0
- package/dashboard/dist/components/ZeroRetentionPane.d.ts +44 -0
- package/dashboard/dist/components/ZeroRetentionPane.js +83 -0
- package/dashboard/dist/components/ZeroRetentionPane.test.d.ts +1 -0
- package/dashboard/dist/components/ZeroRetentionPane.test.js +160 -0
- package/package.json +1 -1
- package/server/lib/access-control-doc.js +541 -0
- package/server/lib/access-control-doc.test.js +672 -0
- package/server/lib/adr-generator.js +423 -0
- package/server/lib/adr-generator.test.js +586 -0
- package/server/lib/agent-progress-monitor.js +223 -0
- package/server/lib/agent-progress-monitor.test.js +202 -0
- package/server/lib/architecture-command.js +450 -0
- package/server/lib/architecture-command.test.js +754 -0
- package/server/lib/ast-analyzer.js +324 -0
- package/server/lib/ast-analyzer.test.js +437 -0
- package/server/lib/audit-attribution.js +191 -0
- package/server/lib/audit-attribution.test.js +359 -0
- package/server/lib/audit-classifier.js +202 -0
- package/server/lib/audit-classifier.test.js +209 -0
- package/server/lib/audit-command.js +275 -0
- package/server/lib/audit-command.test.js +325 -0
- package/server/lib/audit-exporter.js +380 -0
- package/server/lib/audit-exporter.test.js +464 -0
- package/server/lib/audit-logger.js +236 -0
- package/server/lib/audit-logger.test.js +364 -0
- package/server/lib/audit-query.js +257 -0
- package/server/lib/audit-query.test.js +352 -0
- package/server/lib/audit-storage.js +269 -0
- package/server/lib/audit-storage.test.js +272 -0
- package/server/lib/auth-system.test.js +4 -1
- package/server/lib/boundary-detector.js +427 -0
- package/server/lib/boundary-detector.test.js +320 -0
- package/server/lib/budget-alerts.js +138 -0
- package/server/lib/budget-alerts.test.js +235 -0
- package/server/lib/bulk-repo-init.js +342 -0
- package/server/lib/bulk-repo-init.test.js +388 -0
- package/server/lib/candidates-tracker.js +210 -0
- package/server/lib/candidates-tracker.test.js +300 -0
- package/server/lib/checkpoint-manager.js +251 -0
- package/server/lib/checkpoint-manager.test.js +474 -0
- package/server/lib/circular-detector.js +337 -0
- package/server/lib/circular-detector.test.js +353 -0
- package/server/lib/cohesion-analyzer.js +310 -0
- package/server/lib/cohesion-analyzer.test.js +447 -0
- package/server/lib/compliance-checklist.js +866 -0
- package/server/lib/compliance-checklist.test.js +476 -0
- package/server/lib/compliance-command.js +616 -0
- package/server/lib/compliance-command.test.js +551 -0
- package/server/lib/compliance-reporter.js +692 -0
- package/server/lib/compliance-reporter.test.js +707 -0
- package/server/lib/contract-testing.js +625 -0
- package/server/lib/contract-testing.test.js +342 -0
- package/server/lib/conversion-planner.js +469 -0
- package/server/lib/conversion-planner.test.js +361 -0
- package/server/lib/convert-command.js +351 -0
- package/server/lib/convert-command.test.js +608 -0
- package/server/lib/coupling-calculator.js +189 -0
- package/server/lib/coupling-calculator.test.js +509 -0
- package/server/lib/data-flow-doc.js +665 -0
- package/server/lib/data-flow-doc.test.js +659 -0
- package/server/lib/dependency-graph.js +367 -0
- package/server/lib/dependency-graph.test.js +516 -0
- package/server/lib/duplication-detector.js +349 -0
- package/server/lib/duplication-detector.test.js +401 -0
- package/server/lib/ephemeral-storage.js +249 -0
- package/server/lib/ephemeral-storage.test.js +254 -0
- package/server/lib/evidence-collector.js +627 -0
- package/server/lib/evidence-collector.test.js +901 -0
- package/server/lib/example-service.js +616 -0
- package/server/lib/example-service.test.js +397 -0
- package/server/lib/flow-diagram-generator.js +474 -0
- package/server/lib/flow-diagram-generator.test.js +446 -0
- package/server/lib/idp-manager.js +626 -0
- package/server/lib/idp-manager.test.js +587 -0
- package/server/lib/impact-scorer.js +184 -0
- package/server/lib/impact-scorer.test.js +211 -0
- package/server/lib/memory-exclusion.js +326 -0
- package/server/lib/memory-exclusion.test.js +241 -0
- package/server/lib/mermaid-generator.js +358 -0
- package/server/lib/mermaid-generator.test.js +301 -0
- package/server/lib/messaging-patterns.js +750 -0
- package/server/lib/messaging-patterns.test.js +213 -0
- package/server/lib/mfa-handler.js +452 -0
- package/server/lib/mfa-handler.test.js +490 -0
- package/server/lib/microservice-template.js +386 -0
- package/server/lib/microservice-template.test.js +325 -0
- package/server/lib/new-project-microservice.js +450 -0
- package/server/lib/new-project-microservice.test.js +600 -0
- package/server/lib/oauth-flow.js +375 -0
- package/server/lib/oauth-flow.test.js +487 -0
- package/server/lib/oauth-registry.js +190 -0
- package/server/lib/oauth-registry.test.js +306 -0
- package/server/lib/readme-generator.js +490 -0
- package/server/lib/readme-generator.test.js +493 -0
- package/server/lib/refactor-command.js +326 -0
- package/server/lib/refactor-command.test.js +528 -0
- package/server/lib/refactor-executor.js +254 -0
- package/server/lib/refactor-executor.test.js +305 -0
- package/server/lib/refactor-observer.js +292 -0
- package/server/lib/refactor-observer.test.js +422 -0
- package/server/lib/refactor-progress.js +193 -0
- package/server/lib/refactor-progress.test.js +251 -0
- package/server/lib/refactor-reporter.js +237 -0
- package/server/lib/refactor-reporter.test.js +247 -0
- package/server/lib/repo-dependency-tracker.js +261 -0
- package/server/lib/repo-dependency-tracker.test.js +350 -0
- package/server/lib/retention-policy.js +281 -0
- package/server/lib/retention-policy.test.js +486 -0
- package/server/lib/role-mapper.js +236 -0
- package/server/lib/role-mapper.test.js +395 -0
- package/server/lib/saml-provider.js +765 -0
- package/server/lib/saml-provider.test.js +643 -0
- package/server/lib/security-policy-generator.js +682 -0
- package/server/lib/security-policy-generator.test.js +544 -0
- package/server/lib/semantic-analyzer.js +198 -0
- package/server/lib/semantic-analyzer.test.js +474 -0
- package/server/lib/sensitive-detector.js +112 -0
- package/server/lib/sensitive-detector.test.js +209 -0
- package/server/lib/service-interaction-diagram.js +700 -0
- package/server/lib/service-interaction-diagram.test.js +638 -0
- package/server/lib/service-scaffold.js +486 -0
- package/server/lib/service-scaffold.test.js +373 -0
- package/server/lib/service-summary.js +553 -0
- package/server/lib/service-summary.test.js +619 -0
- package/server/lib/session-purge.js +460 -0
- package/server/lib/session-purge.test.js +312 -0
- package/server/lib/shared-kernel.js +578 -0
- package/server/lib/shared-kernel.test.js +255 -0
- package/server/lib/sso-command.js +544 -0
- package/server/lib/sso-command.test.js +552 -0
- package/server/lib/sso-session.js +492 -0
- package/server/lib/sso-session.test.js +670 -0
- package/server/lib/traefik-config.js +282 -0
- package/server/lib/traefik-config.test.js +312 -0
- package/server/lib/usage-command.js +218 -0
- package/server/lib/usage-command.test.js +391 -0
- package/server/lib/usage-formatter.js +192 -0
- package/server/lib/usage-formatter.test.js +267 -0
- package/server/lib/usage-history.js +122 -0
- package/server/lib/usage-history.test.js +206 -0
- package/server/lib/workspace-command.js +249 -0
- package/server/lib/workspace-command.test.js +264 -0
- package/server/lib/workspace-config.js +270 -0
- package/server/lib/workspace-config.test.js +312 -0
- package/server/lib/workspace-docs-command.js +547 -0
- package/server/lib/workspace-docs-command.test.js +692 -0
- package/server/lib/workspace-memory.js +451 -0
- package/server/lib/workspace-memory.test.js +403 -0
- package/server/lib/workspace-scanner.js +452 -0
- package/server/lib/workspace-scanner.test.js +677 -0
- package/server/lib/workspace-test-runner.js +315 -0
- package/server/lib/workspace-test-runner.test.js +294 -0
- package/server/lib/zero-retention-command.js +439 -0
- package/server/lib/zero-retention-command.test.js +448 -0
- package/server/lib/zero-retention.js +322 -0
- package/server/lib/zero-retention.test.js +258 -0
- package/server/package-lock.json +14 -0
- package/server/package.json +1 -0
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Refactor Command
|
|
3
|
+
* Main orchestrator for /tlc:refactor skill
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const { AstAnalyzer } = require('./ast-analyzer.js');
|
|
7
|
+
const { DuplicationDetector } = require('./duplication-detector.js');
|
|
8
|
+
const { SemanticAnalyzer } = require('./semantic-analyzer.js');
|
|
9
|
+
const { ImpactScorer } = require('./impact-scorer.js');
|
|
10
|
+
const { CheckpointManager } = require('./checkpoint-manager.js');
|
|
11
|
+
const { RefactorExecutor } = require('./refactor-executor.js');
|
|
12
|
+
const { RefactorReporter } = require('./refactor-reporter.js');
|
|
13
|
+
const { CandidatesTracker } = require('./candidates-tracker.js');
|
|
14
|
+
const { RefactorProgress } = require('./refactor-progress.js');
|
|
15
|
+
|
|
16
|
+
class RefactorCommand {
|
|
17
|
+
constructor(options = {}) {
|
|
18
|
+
this.options = options;
|
|
19
|
+
this.astAnalyzer = options.astAnalyzer || new AstAnalyzer();
|
|
20
|
+
this.duplicationDetector = options.duplicationDetector || new DuplicationDetector();
|
|
21
|
+
this.semanticAnalyzer = options.semanticAnalyzer || new SemanticAnalyzer(options.semanticOptions);
|
|
22
|
+
this.impactScorer = options.impactScorer || new ImpactScorer(options.scorerOptions);
|
|
23
|
+
this.checkpointManager = options.checkpointManager || new CheckpointManager(options.checkpointOptions);
|
|
24
|
+
this.executor = options.executor || new RefactorExecutor(options.executorOptions);
|
|
25
|
+
this.reporter = options.reporter || new RefactorReporter();
|
|
26
|
+
this.candidatesTracker = options.candidatesTracker || new CandidatesTracker(options.trackerOptions);
|
|
27
|
+
this.progress = options.progress || new RefactorProgress(options.progressOptions);
|
|
28
|
+
|
|
29
|
+
// Callbacks for interactive mode
|
|
30
|
+
this.onProgress = options.onProgress || (() => {});
|
|
31
|
+
this.onConfirm = options.onConfirm || (async () => true);
|
|
32
|
+
this.onSelectModels = options.onSelectModels || (async () => ['default']);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Run the refactor command
|
|
37
|
+
* @param {Object} options - Command options
|
|
38
|
+
* @returns {Object} Result with report and applied changes
|
|
39
|
+
*/
|
|
40
|
+
async run(options = {}) {
|
|
41
|
+
const {
|
|
42
|
+
mode = 'interactive', // 'interactive', 'auto', 'analyze-only'
|
|
43
|
+
scope = 'changed', // 'changed', 'all', 'file', 'directory'
|
|
44
|
+
target = null, // specific file/directory for 'file' or 'directory' scope
|
|
45
|
+
format = 'markdown', // report format
|
|
46
|
+
useMultiModel = true,
|
|
47
|
+
dryRun = false,
|
|
48
|
+
} = options;
|
|
49
|
+
|
|
50
|
+
const result = {
|
|
51
|
+
analyzed: 0,
|
|
52
|
+
opportunities: [],
|
|
53
|
+
applied: [],
|
|
54
|
+
skipped: [],
|
|
55
|
+
report: null,
|
|
56
|
+
cancelled: false,
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
try {
|
|
60
|
+
// Step 1: Get files to analyze
|
|
61
|
+
const files = await this.getFilesToAnalyze(scope, target);
|
|
62
|
+
result.analyzed = files.length;
|
|
63
|
+
|
|
64
|
+
if (files.length === 0) {
|
|
65
|
+
result.report = this.reporter.generate([], format);
|
|
66
|
+
return result;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Step 2: Ask about multi-model if enabled
|
|
70
|
+
let models = ['default'];
|
|
71
|
+
if (useMultiModel) {
|
|
72
|
+
models = await this.onSelectModels();
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Step 3: Analyze files
|
|
76
|
+
this.onProgress({ phase: 'analyzing', total: files.length, completed: 0 });
|
|
77
|
+
|
|
78
|
+
const analysisResult = await this.analyzeFiles(files, models);
|
|
79
|
+
|
|
80
|
+
if (analysisResult.cancelled) {
|
|
81
|
+
result.cancelled = true;
|
|
82
|
+
return result;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
result.opportunities = analysisResult.opportunities;
|
|
86
|
+
|
|
87
|
+
// Step 4: Score and prioritize
|
|
88
|
+
const scored = this.scoreOpportunities(result.opportunities);
|
|
89
|
+
|
|
90
|
+
// Step 5: Add to candidates tracker
|
|
91
|
+
await this.candidatesTracker.add(scored.map(s => ({
|
|
92
|
+
file: s.opportunity.file,
|
|
93
|
+
startLine: s.opportunity.line || 1,
|
|
94
|
+
description: s.opportunity.description,
|
|
95
|
+
impact: s.score.total,
|
|
96
|
+
})));
|
|
97
|
+
|
|
98
|
+
// Step 6: Handle based on mode
|
|
99
|
+
if (mode === 'analyze-only') {
|
|
100
|
+
result.report = this.reporter.generate(scored, format);
|
|
101
|
+
return result;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Step 7: Execute refactorings
|
|
105
|
+
if (mode === 'interactive') {
|
|
106
|
+
const toApply = await this.confirmRefactorings(scored);
|
|
107
|
+
if (toApply.length === 0) {
|
|
108
|
+
result.skipped = scored;
|
|
109
|
+
result.report = this.reporter.generate([], format);
|
|
110
|
+
return result;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (!dryRun) {
|
|
114
|
+
const applied = await this.applyRefactorings(toApply);
|
|
115
|
+
result.applied = applied.successful;
|
|
116
|
+
result.skipped = [...scored.filter(s => !toApply.includes(s)), ...applied.failed];
|
|
117
|
+
} else {
|
|
118
|
+
result.applied = toApply;
|
|
119
|
+
}
|
|
120
|
+
} else if (mode === 'auto') {
|
|
121
|
+
// Auto mode: apply high-priority only
|
|
122
|
+
const highPriority = scored.filter(s => s.score.total >= 80);
|
|
123
|
+
if (!dryRun && highPriority.length > 0) {
|
|
124
|
+
const applied = await this.applyRefactorings(highPriority);
|
|
125
|
+
result.applied = applied.successful;
|
|
126
|
+
result.skipped = [...scored.filter(s => s.score.total < 80), ...applied.failed];
|
|
127
|
+
} else {
|
|
128
|
+
result.applied = highPriority;
|
|
129
|
+
result.skipped = scored.filter(s => s.score.total < 80);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Step 8: Generate report
|
|
134
|
+
result.report = this.reporter.generate(result.applied, format);
|
|
135
|
+
|
|
136
|
+
return result;
|
|
137
|
+
} catch (error) {
|
|
138
|
+
result.error = error.message;
|
|
139
|
+
return result;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Get files to analyze based on scope
|
|
145
|
+
*/
|
|
146
|
+
async getFilesToAnalyze(scope, target) {
|
|
147
|
+
const { getChangedFiles, getAllFiles, getFilesByPath } = this.options;
|
|
148
|
+
|
|
149
|
+
switch (scope) {
|
|
150
|
+
case 'changed':
|
|
151
|
+
if (getChangedFiles) {
|
|
152
|
+
return await getChangedFiles();
|
|
153
|
+
}
|
|
154
|
+
return [];
|
|
155
|
+
|
|
156
|
+
case 'all':
|
|
157
|
+
if (getAllFiles) {
|
|
158
|
+
return await getAllFiles();
|
|
159
|
+
}
|
|
160
|
+
return [];
|
|
161
|
+
|
|
162
|
+
case 'file':
|
|
163
|
+
case 'directory':
|
|
164
|
+
if (getFilesByPath && target) {
|
|
165
|
+
return await getFilesByPath(target);
|
|
166
|
+
}
|
|
167
|
+
return [];
|
|
168
|
+
|
|
169
|
+
default:
|
|
170
|
+
return [];
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Analyze files for refactoring opportunities
|
|
176
|
+
*/
|
|
177
|
+
async analyzeFiles(files, models) {
|
|
178
|
+
const opportunities = [];
|
|
179
|
+
let completed = 0;
|
|
180
|
+
|
|
181
|
+
this.progress.start(files.length);
|
|
182
|
+
|
|
183
|
+
for (const file of files) {
|
|
184
|
+
if (this.progress.isCancelled()) {
|
|
185
|
+
return { opportunities, cancelled: true };
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
try {
|
|
189
|
+
// AST analysis
|
|
190
|
+
const astResult = this.astAnalyzer.analyze(file.content, file.path);
|
|
191
|
+
|
|
192
|
+
// Check for complexity issues
|
|
193
|
+
for (const fn of astResult.functions || []) {
|
|
194
|
+
if (fn.complexity > 10) {
|
|
195
|
+
opportunities.push({
|
|
196
|
+
type: 'complexity',
|
|
197
|
+
file: file.path,
|
|
198
|
+
line: fn.line,
|
|
199
|
+
name: fn.name,
|
|
200
|
+
description: `High complexity (${fn.complexity}) in ${fn.name}`,
|
|
201
|
+
metrics: fn,
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
if (fn.lines > 50) {
|
|
206
|
+
opportunities.push({
|
|
207
|
+
type: 'length',
|
|
208
|
+
file: file.path,
|
|
209
|
+
line: fn.line,
|
|
210
|
+
name: fn.name,
|
|
211
|
+
description: `Long function (${fn.lines} lines) - ${fn.name}`,
|
|
212
|
+
metrics: fn,
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// Semantic analysis with models
|
|
218
|
+
if (models.length > 0 && models[0] !== 'skip') {
|
|
219
|
+
const semanticResult = await this.semanticAnalyzer.analyze(
|
|
220
|
+
file.content,
|
|
221
|
+
file.path,
|
|
222
|
+
{ models }
|
|
223
|
+
);
|
|
224
|
+
|
|
225
|
+
if (semanticResult.issues) {
|
|
226
|
+
for (const issue of semanticResult.issues) {
|
|
227
|
+
opportunities.push({
|
|
228
|
+
type: 'semantic',
|
|
229
|
+
file: file.path,
|
|
230
|
+
line: issue.line,
|
|
231
|
+
description: issue.description,
|
|
232
|
+
suggestion: issue.suggestion,
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
} catch (error) {
|
|
238
|
+
// Log but continue
|
|
239
|
+
console.error(`Error analyzing ${file.path}:`, error.message);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
completed++;
|
|
243
|
+
this.progress.update(file.path);
|
|
244
|
+
this.onProgress({ phase: 'analyzing', total: files.length, completed });
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// Duplication detection across all files
|
|
248
|
+
const duplicationResult = this.duplicationDetector.detect(files);
|
|
249
|
+
if (duplicationResult.duplicates) {
|
|
250
|
+
for (const dup of duplicationResult.duplicates) {
|
|
251
|
+
opportunities.push({
|
|
252
|
+
type: 'duplication',
|
|
253
|
+
file: dup.file1,
|
|
254
|
+
line: dup.line1,
|
|
255
|
+
description: `Duplicate code found in ${dup.file1} and ${dup.file2}`,
|
|
256
|
+
duplicate: dup,
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
return { opportunities, cancelled: false };
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Score opportunities by impact
|
|
266
|
+
*/
|
|
267
|
+
scoreOpportunities(opportunities) {
|
|
268
|
+
return opportunities
|
|
269
|
+
.map(opp => ({
|
|
270
|
+
opportunity: opp,
|
|
271
|
+
score: this.impactScorer.score(opp),
|
|
272
|
+
}))
|
|
273
|
+
.sort((a, b) => b.score.total - a.score.total);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* Confirm refactorings with user (interactive mode)
|
|
278
|
+
*/
|
|
279
|
+
async confirmRefactorings(scored) {
|
|
280
|
+
const confirmed = [];
|
|
281
|
+
|
|
282
|
+
for (const item of scored) {
|
|
283
|
+
const shouldApply = await this.onConfirm(item);
|
|
284
|
+
if (shouldApply) {
|
|
285
|
+
confirmed.push(item);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
return confirmed;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Apply confirmed refactorings
|
|
294
|
+
*/
|
|
295
|
+
async applyRefactorings(items) {
|
|
296
|
+
const refactorings = items.map(item => ({
|
|
297
|
+
...item.opportunity,
|
|
298
|
+
score: item.score,
|
|
299
|
+
}));
|
|
300
|
+
|
|
301
|
+
const result = await this.executor.execute(refactorings);
|
|
302
|
+
|
|
303
|
+
// Mark completed in tracker
|
|
304
|
+
for (const applied of result.successful || []) {
|
|
305
|
+
await this.candidatesTracker.markComplete(applied.file, applied.line);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
return result;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* Cancel ongoing analysis
|
|
313
|
+
*/
|
|
314
|
+
cancel() {
|
|
315
|
+
this.progress.cancel();
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* Get current progress
|
|
320
|
+
*/
|
|
321
|
+
getProgress() {
|
|
322
|
+
return this.progress.getProgress();
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
module.exports = { RefactorCommand };
|