tlc-claude-code 0.8.8 → 0.9.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 (2) hide show
  1. package/package.json +2 -7
  2. package/server/index.js +118 -0
package/package.json CHANGED
@@ -1,15 +1,10 @@
1
1
  {
2
2
  "name": "tlc-claude-code",
3
- "version": "0.8.8",
3
+ "version": "0.9.0",
4
4
  "description": "TLC - Test Led Coding for Claude Code",
5
5
  "bin": {
6
6
  "tlc": "./bin/tlc.js",
7
- "tlc-claude-code": "./bin/install.js",
8
- "tlc-dashboard": "./dashboard/dist/index.js",
9
- "tlc-server": "./bin/server.js",
10
- "tlc-setup": "./bin/setup.js",
11
- "tlc-init": "./bin/init.js",
12
- "tlc-rebuild": "./bin/rebuild.js"
7
+ "tlc-claude-code": "./bin/install.js"
13
8
  },
14
9
  "files": [
15
10
  "bin/",
package/server/index.js CHANGED
@@ -211,6 +211,7 @@ app.get('/api/status', (req, res) => {
211
211
  appPort,
212
212
  testsPass: plan.testsPass || 0,
213
213
  testsFail: plan.testsFail || 0,
214
+ tasks: plan.tasks?.length || 0,
214
215
  bugsOpen: bugs.filter(b => b.status === 'open').length,
215
216
  phase: plan.currentPhase,
216
217
  phaseName: plan.currentPhaseName
@@ -235,6 +236,123 @@ app.get('/api/tasks', (req, res) => {
235
236
  });
236
237
  });
237
238
 
239
+ // Plan content endpoint
240
+ app.get('/api/plan', (req, res) => {
241
+ const plan = parsePlan(PROJECT_DIR);
242
+ let content = '';
243
+
244
+ // Try to read current phase plan file
245
+ const phasesDir = path.join(PROJECT_DIR, '.planning', 'phases');
246
+ if (plan.currentPhase && fs.existsSync(phasesDir)) {
247
+ const planFile = path.join(phasesDir, `${plan.currentPhase}-PLAN.md`);
248
+ if (fs.existsSync(planFile)) {
249
+ content = fs.readFileSync(planFile, 'utf-8');
250
+ }
251
+ }
252
+
253
+ // Fallback to ROADMAP.md
254
+ if (!content) {
255
+ const roadmapFile = path.join(PROJECT_DIR, '.planning', 'ROADMAP.md');
256
+ if (fs.existsSync(roadmapFile)) {
257
+ content = fs.readFileSync(roadmapFile, 'utf-8');
258
+ }
259
+ }
260
+
261
+ res.json({
262
+ phase: plan.currentPhase,
263
+ phaseName: plan.currentPhaseName,
264
+ content
265
+ });
266
+ });
267
+
268
+ // Test checklist endpoint
269
+ app.get('/api/tests', (req, res) => {
270
+ const plan = parsePlan(PROJECT_DIR);
271
+ let items = [];
272
+
273
+ // Try to read TESTS.md for current phase
274
+ const phasesDir = path.join(PROJECT_DIR, '.planning', 'phases');
275
+ if (plan.currentPhase && fs.existsSync(phasesDir)) {
276
+ const testsFile = path.join(phasesDir, `${plan.currentPhase}-TESTS.md`);
277
+ if (fs.existsSync(testsFile)) {
278
+ const content = fs.readFileSync(testsFile, 'utf-8');
279
+ // Parse checkboxes
280
+ const lines = content.split('\n');
281
+ for (const line of lines) {
282
+ const match = line.match(/^[-*]\s*\[([ x])\]\s*(.+)$/i);
283
+ if (match) {
284
+ items.push({
285
+ checked: match[1].toLowerCase() === 'x',
286
+ text: match[2].trim()
287
+ });
288
+ }
289
+ }
290
+ }
291
+ }
292
+
293
+ res.json({ items });
294
+ });
295
+
296
+ // Bugs list endpoint
297
+ app.get('/api/bugs', (req, res) => {
298
+ const bugs = parseBugs(PROJECT_DIR);
299
+ res.json(bugs);
300
+ });
301
+
302
+ // Changelog endpoint
303
+ app.get('/api/changelog', (req, res) => {
304
+ try {
305
+ const { execSync } = require('child_process');
306
+ const output = execSync('git log --oneline -20 --pretty=format:"%h|%s|%an|%ar"', {
307
+ cwd: PROJECT_DIR,
308
+ encoding: 'utf-8'
309
+ });
310
+
311
+ const commits = output.trim().split('\n').filter(Boolean).map(line => {
312
+ const [hash, message, author, date] = line.split('|');
313
+ return { hash, message, author, date };
314
+ });
315
+
316
+ res.json({ commits });
317
+ } catch (e) {
318
+ res.json({ commits: [] });
319
+ }
320
+ });
321
+
322
+ // Playwright endpoint
323
+ app.post('/api/playwright', (req, res) => {
324
+ addLog('test', '--- Running Playwright tests ---', 'info');
325
+
326
+ const testProcess = spawn('npx', ['playwright', 'test'], {
327
+ cwd: PROJECT_DIR,
328
+ env: { ...process.env, CI: 'true' },
329
+ shell: true
330
+ });
331
+
332
+ testProcess.stdout.on('data', (data) => {
333
+ const text = data.toString().trim();
334
+ if (text) {
335
+ broadcast('test-output', { data: text, stream: 'stdout' });
336
+ addLog('test', text);
337
+ }
338
+ });
339
+
340
+ testProcess.stderr.on('data', (data) => {
341
+ const text = data.toString().trim();
342
+ if (text) {
343
+ broadcast('test-output', { data: text, stream: 'stderr' });
344
+ addLog('test', text, 'error');
345
+ }
346
+ });
347
+
348
+ testProcess.on('exit', (code) => {
349
+ broadcast('test-complete', { exitCode: code });
350
+ addLog('test', `Playwright ${code === 0 ? 'passed' : 'failed'}`, code === 0 ? 'success' : 'error');
351
+ });
352
+
353
+ res.json({ success: true });
354
+ });
355
+
238
356
  app.post('/api/bug', (req, res) => {
239
357
  const { description, url, screenshot, severity } = req.body;
240
358