tlc-claude-code 1.2.28 → 1.3.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.
Files changed (87) hide show
  1. package/README.md +9 -4
  2. package/dashboard/dist/components/UsagePane.d.ts +13 -0
  3. package/dashboard/dist/components/UsagePane.js +51 -0
  4. package/dashboard/dist/components/UsagePane.test.d.ts +1 -0
  5. package/dashboard/dist/components/UsagePane.test.js +142 -0
  6. package/dashboard/dist/components/WorkspaceDocsPane.d.ts +19 -0
  7. package/dashboard/dist/components/WorkspaceDocsPane.js +146 -0
  8. package/dashboard/dist/components/WorkspaceDocsPane.test.d.ts +1 -0
  9. package/dashboard/dist/components/WorkspaceDocsPane.test.js +242 -0
  10. package/dashboard/dist/components/WorkspacePane.d.ts +18 -0
  11. package/dashboard/dist/components/WorkspacePane.js +17 -0
  12. package/dashboard/dist/components/WorkspacePane.test.d.ts +1 -0
  13. package/dashboard/dist/components/WorkspacePane.test.js +84 -0
  14. package/package.json +15 -4
  15. package/scripts/capture-screenshots.js +170 -0
  16. package/scripts/docs-update.js +253 -0
  17. package/scripts/generate-screenshots.js +321 -0
  18. package/scripts/project-docs.js +377 -0
  19. package/scripts/vps-setup.sh +477 -0
  20. package/server/lib/architecture-command.js +450 -0
  21. package/server/lib/architecture-command.test.js +754 -0
  22. package/server/lib/ast-analyzer.js +324 -0
  23. package/server/lib/ast-analyzer.test.js +437 -0
  24. package/server/lib/auth-system.test.js +4 -1
  25. package/server/lib/boundary-detector.js +427 -0
  26. package/server/lib/boundary-detector.test.js +320 -0
  27. package/server/lib/budget-alerts.js +138 -0
  28. package/server/lib/budget-alerts.test.js +235 -0
  29. package/server/lib/candidates-tracker.js +210 -0
  30. package/server/lib/candidates-tracker.test.js +300 -0
  31. package/server/lib/checkpoint-manager.js +251 -0
  32. package/server/lib/checkpoint-manager.test.js +474 -0
  33. package/server/lib/circular-detector.js +337 -0
  34. package/server/lib/circular-detector.test.js +353 -0
  35. package/server/lib/cohesion-analyzer.js +310 -0
  36. package/server/lib/cohesion-analyzer.test.js +447 -0
  37. package/server/lib/contract-testing.js +625 -0
  38. package/server/lib/contract-testing.test.js +342 -0
  39. package/server/lib/conversion-planner.js +469 -0
  40. package/server/lib/conversion-planner.test.js +361 -0
  41. package/server/lib/convert-command.js +351 -0
  42. package/server/lib/convert-command.test.js +608 -0
  43. package/server/lib/coupling-calculator.js +189 -0
  44. package/server/lib/coupling-calculator.test.js +509 -0
  45. package/server/lib/dependency-graph.js +367 -0
  46. package/server/lib/dependency-graph.test.js +516 -0
  47. package/server/lib/duplication-detector.js +349 -0
  48. package/server/lib/duplication-detector.test.js +401 -0
  49. package/server/lib/example-service.js +616 -0
  50. package/server/lib/example-service.test.js +397 -0
  51. package/server/lib/impact-scorer.js +184 -0
  52. package/server/lib/impact-scorer.test.js +211 -0
  53. package/server/lib/mermaid-generator.js +358 -0
  54. package/server/lib/mermaid-generator.test.js +301 -0
  55. package/server/lib/messaging-patterns.js +750 -0
  56. package/server/lib/messaging-patterns.test.js +213 -0
  57. package/server/lib/microservice-template.js +386 -0
  58. package/server/lib/microservice-template.test.js +325 -0
  59. package/server/lib/new-project-microservice.js +450 -0
  60. package/server/lib/new-project-microservice.test.js +600 -0
  61. package/server/lib/refactor-command.js +326 -0
  62. package/server/lib/refactor-command.test.js +528 -0
  63. package/server/lib/refactor-executor.js +254 -0
  64. package/server/lib/refactor-executor.test.js +305 -0
  65. package/server/lib/refactor-observer.js +292 -0
  66. package/server/lib/refactor-observer.test.js +422 -0
  67. package/server/lib/refactor-progress.js +193 -0
  68. package/server/lib/refactor-progress.test.js +251 -0
  69. package/server/lib/refactor-reporter.js +237 -0
  70. package/server/lib/refactor-reporter.test.js +247 -0
  71. package/server/lib/semantic-analyzer.js +198 -0
  72. package/server/lib/semantic-analyzer.test.js +474 -0
  73. package/server/lib/service-scaffold.js +486 -0
  74. package/server/lib/service-scaffold.test.js +373 -0
  75. package/server/lib/shared-kernel.js +578 -0
  76. package/server/lib/shared-kernel.test.js +255 -0
  77. package/server/lib/traefik-config.js +282 -0
  78. package/server/lib/traefik-config.test.js +312 -0
  79. package/server/lib/usage-command.js +218 -0
  80. package/server/lib/usage-command.test.js +391 -0
  81. package/server/lib/usage-formatter.js +192 -0
  82. package/server/lib/usage-formatter.test.js +267 -0
  83. package/server/lib/usage-history.js +122 -0
  84. package/server/lib/usage-history.test.js +206 -0
  85. package/server/package-lock.json +14 -0
  86. package/server/package.json +1 -0
  87. package/templates/docs-sync.yml +91 -0
@@ -0,0 +1,251 @@
1
+ /**
2
+ * Checkpoint Manager
3
+ * Create and manage git-based checkpoints for safe refactoring
4
+ */
5
+
6
+ const { execSync } = require('child_process');
7
+ const fs = require('fs');
8
+ const path = require('path');
9
+
10
+ class CheckpointManager {
11
+ constructor(options = {}) {
12
+ this.exec = options.exec || this.defaultExec.bind(this);
13
+ this.readFile = options.readFile || this.defaultReadFile.bind(this);
14
+ this.writeFile = options.writeFile || this.defaultWriteFile.bind(this);
15
+ this.stateFile = options.stateFile || '.tlc/checkpoint.json';
16
+ }
17
+
18
+ /**
19
+ * Default exec implementation
20
+ */
21
+ async defaultExec(command) {
22
+ return new Promise((resolve, reject) => {
23
+ try {
24
+ const stdout = execSync(command, { encoding: 'utf-8' });
25
+ resolve({ stdout });
26
+ } catch (error) {
27
+ reject(error);
28
+ }
29
+ });
30
+ }
31
+
32
+ /**
33
+ * Default read file implementation
34
+ */
35
+ async defaultReadFile(filePath) {
36
+ return fs.promises.readFile(filePath, 'utf-8');
37
+ }
38
+
39
+ /**
40
+ * Default write file implementation
41
+ */
42
+ async defaultWriteFile(filePath, content) {
43
+ const dir = path.dirname(filePath);
44
+ await fs.promises.mkdir(dir, { recursive: true });
45
+ await fs.promises.writeFile(filePath, content, 'utf-8');
46
+ }
47
+
48
+ /**
49
+ * Create a new checkpoint
50
+ * @param {Object} options - Creation options
51
+ * @returns {Object} Checkpoint info
52
+ */
53
+ async create(options = {}) {
54
+ // Check for existing checkpoint
55
+ if (!options.force) {
56
+ const existing = await this.load();
57
+ if (existing) {
58
+ throw new Error('Checkpoint already exists. Use rollback() first or force: true');
59
+ }
60
+ }
61
+
62
+ // Get current branch
63
+ let originalBranch;
64
+ let wasDetached = false;
65
+
66
+ try {
67
+ const { stdout } = await this.exec('git branch --show-current');
68
+ originalBranch = stdout.trim();
69
+
70
+ if (!originalBranch) {
71
+ // Detached HEAD
72
+ const { stdout: headCommit } = await this.exec('git rev-parse HEAD');
73
+ originalBranch = headCommit.trim();
74
+ wasDetached = true;
75
+ }
76
+ } catch (error) {
77
+ throw new Error('Failed to get current branch: ' + error.message);
78
+ }
79
+
80
+ // Check for uncommitted changes
81
+ const { stdout: status } = await this.exec('git status --porcelain');
82
+ const hasChanges = status.trim().length > 0;
83
+ let hasStash = false;
84
+ let stashRef = null;
85
+
86
+ // Stash changes if any
87
+ if (hasChanges) {
88
+ await this.exec('git stash push -m "TLC checkpoint stash"');
89
+ hasStash = true;
90
+ stashRef = 'stash@{0}';
91
+ }
92
+
93
+ // Create refactor branch
94
+ const timestamp = Date.now();
95
+ let branch = `refactor/${timestamp}`;
96
+ let attempts = 0;
97
+
98
+ while (attempts < 3) {
99
+ try {
100
+ await this.exec(`git checkout -b ${branch}`);
101
+ break;
102
+ } catch (error) {
103
+ if (error.message.includes('already exists')) {
104
+ attempts++;
105
+ branch = `refactor/${timestamp}-${attempts}`;
106
+ } else {
107
+ throw error;
108
+ }
109
+ }
110
+ }
111
+
112
+ // Get commit hash
113
+ const { stdout: commitHash } = await this.exec('git rev-parse HEAD');
114
+
115
+ const checkpoint = {
116
+ id: `checkpoint-${timestamp}`,
117
+ branch,
118
+ originalBranch,
119
+ wasDetached,
120
+ hasStash,
121
+ stashRef,
122
+ commitHash: commitHash.trim(),
123
+ createdAt: new Date(),
124
+ };
125
+
126
+ // Save checkpoint state
127
+ await this.save(checkpoint);
128
+
129
+ return checkpoint;
130
+ }
131
+
132
+ /**
133
+ * Rollback to checkpoint state
134
+ * @param {Object} checkpoint - Checkpoint to rollback to
135
+ */
136
+ async rollback(checkpoint) {
137
+ // Checkout original branch
138
+ await this.exec(`git checkout ${checkpoint.originalBranch}`);
139
+
140
+ // Delete refactor branch
141
+ try {
142
+ await this.exec(`git branch -D ${checkpoint.branch}`);
143
+ } catch (error) {
144
+ // Branch might not exist
145
+ }
146
+
147
+ // Pop stash if we stashed
148
+ if (checkpoint.hasStash) {
149
+ try {
150
+ await this.exec('git stash pop');
151
+ } catch (error) {
152
+ // Stash might be empty or conflict
153
+ }
154
+ }
155
+
156
+ // Clear checkpoint state
157
+ await this.clear();
158
+ }
159
+
160
+ /**
161
+ * Commit current changes
162
+ * @param {string} message - Commit message
163
+ */
164
+ async commit(message) {
165
+ await this.exec('git add -A');
166
+ await this.exec(`git commit -m "${message.replace(/"/g, '\\"')}"`);
167
+ }
168
+
169
+ /**
170
+ * Merge refactor branch back to original
171
+ * @param {Object} checkpoint - Checkpoint info
172
+ * @param {Object} options - Merge options
173
+ */
174
+ async merge(checkpoint, options = {}) {
175
+ // Checkout original branch
176
+ await this.exec(`git checkout ${checkpoint.originalBranch}`);
177
+
178
+ // Merge refactor branch
179
+ await this.exec(`git merge ${checkpoint.branch}`);
180
+
181
+ // Cleanup if requested
182
+ if (options.cleanup) {
183
+ await this.exec(`git branch -d ${checkpoint.branch}`);
184
+ }
185
+
186
+ // Clear checkpoint state
187
+ await this.clear();
188
+ }
189
+
190
+ /**
191
+ * Save checkpoint state to file
192
+ */
193
+ async save(checkpoint) {
194
+ await this.writeFile(this.stateFile, JSON.stringify(checkpoint, null, 2));
195
+ }
196
+
197
+ /**
198
+ * Load existing checkpoint state
199
+ * @returns {Object|null} Checkpoint or null if none exists
200
+ */
201
+ async load() {
202
+ try {
203
+ const content = await this.readFile(this.stateFile);
204
+ return JSON.parse(content);
205
+ } catch (error) {
206
+ return null;
207
+ }
208
+ }
209
+
210
+ /**
211
+ * Clear checkpoint state
212
+ */
213
+ async clear() {
214
+ try {
215
+ await fs.promises.unlink(this.stateFile);
216
+ } catch (error) {
217
+ // File might not exist
218
+ }
219
+ }
220
+
221
+ /**
222
+ * Get current checkpoint status
223
+ * @returns {Object} Status info
224
+ */
225
+ async status() {
226
+ const checkpoint = await this.load();
227
+
228
+ if (!checkpoint) {
229
+ return {
230
+ active: false,
231
+ };
232
+ }
233
+
234
+ // Get current branch
235
+ const { stdout: currentBranch } = await this.exec('git branch --show-current');
236
+
237
+ // Check for uncommitted changes
238
+ const { stdout: status } = await this.exec('git status --porcelain');
239
+
240
+ return {
241
+ active: true,
242
+ branch: checkpoint.branch,
243
+ originalBranch: checkpoint.originalBranch,
244
+ isOnRefactorBranch: currentBranch.trim() === checkpoint.branch,
245
+ hasUncommittedChanges: status.trim().length > 0,
246
+ createdAt: checkpoint.createdAt,
247
+ };
248
+ }
249
+ }
250
+
251
+ module.exports = { CheckpointManager };