tlc-claude-code 1.8.4 → 1.8.5

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tlc-claude-code",
3
- "version": "1.8.4",
3
+ "version": "1.8.5",
4
4
  "description": "TLC - Test Led Coding for Claude Code",
5
5
  "bin": {
6
6
  "tlc": "./bin/tlc.js",
package/server/index.js CHANGED
@@ -649,10 +649,22 @@ app.get('/api/project', (req, res) => {
649
649
  const roadmapPath = path.join(PROJECT_DIR, '.planning', 'ROADMAP.md');
650
650
  if (fs.existsSync(roadmapPath)) {
651
651
  const content = fs.readFileSync(roadmapPath, 'utf-8');
652
- const phases = content.match(/##\s+Phase\s+\d+/g) || [];
653
- totalPhases = phases.length;
654
- const completed = content.match(/##\s+Phase\s+\d+[^[]*\[x\]/gi) || [];
655
- completedPhases = completed.length;
652
+
653
+ // Format 1: ## Phase N heading format
654
+ const headingPhases = content.match(/##\s+Phase\s+\d+/g) || [];
655
+ const headingCompleted = content.match(/##\s+Phase\s+\d+[^[]*\[x\]/gi) || [];
656
+
657
+ // Format 2: Table format | N | [Name](link) | status |
658
+ const tablePhases = content.match(/\|\s*\d+\s*\|\s*\[[^\]]+\][^\|]*\|\s*\w+\s*\|/g) || [];
659
+ const tableCompleted = (content.match(/\|\s*\d+\s*\|\s*\[[^\]]+\][^\|]*\|\s*(?:complete|done|verified)\s*\|/gi) || []);
660
+
661
+ if (headingPhases.length > 0) {
662
+ totalPhases = headingPhases.length;
663
+ completedPhases = headingCompleted.length;
664
+ } else if (tablePhases.length > 0) {
665
+ totalPhases = tablePhases.length;
666
+ completedPhases = tableCompleted.length;
667
+ }
656
668
  }
657
669
 
658
670
  // Calculate progress
@@ -18,7 +18,7 @@ function parsePlan(projectDir) {
18
18
  if (fs.existsSync(roadmapPath)) {
19
19
  const content = fs.readFileSync(roadmapPath, 'utf-8');
20
20
 
21
- // Find first incomplete phase
21
+ // Format 1: ## Phase N: Name [x] (heading format)
22
22
  const phaseMatches = content.matchAll(/##\s+Phase\s+(\d+)(?:\.(\d+))?[:\s]+(.+?)(?:\s*\[([x ])\])?$/gm);
23
23
  for (const match of phaseMatches) {
24
24
  const phaseNum = match[2] ? `${match[1]}.${match[2]}` : match[1];
@@ -31,16 +31,42 @@ function parsePlan(projectDir) {
31
31
  break;
32
32
  }
33
33
  }
34
+
35
+ // Format 2: Table format | 01 | [Name](link) | status | description |
36
+ if (!result.currentPhase) {
37
+ const tableMatches = content.matchAll(/\|\s*(\d+)\s*\|\s*\[([^\]]+)\][^\|]*\|\s*(\w+)\s*\|/g);
38
+ for (const match of tableMatches) {
39
+ const phaseNum = match[1].replace(/^0+/, '') || '0'; // strip leading zeros
40
+ const phaseName = match[2].trim();
41
+ const status = match[3].trim().toLowerCase();
42
+ const completed = status === 'complete' || status === 'done' || status === 'verified';
43
+
44
+ if (!completed) {
45
+ result.currentPhase = phaseNum;
46
+ result.currentPhaseName = phaseName;
47
+ break;
48
+ }
49
+ }
50
+ }
34
51
  }
35
52
 
36
53
  // Load current phase PLAN.md
37
54
  if (result.currentPhase) {
38
- const planPath = path.join(
39
- projectDir,
40
- '.planning',
41
- 'phases',
42
- `${result.currentPhase}-PLAN.md`
43
- );
55
+ const phasesDir = path.join(projectDir, '.planning', 'phases');
56
+ let planPath = path.join(phasesDir, `${result.currentPhase}-PLAN.md`);
57
+
58
+ // Try exact match first, then glob for prefixed names like "06-name-PLAN.md"
59
+ if (!fs.existsSync(planPath) && fs.existsSync(phasesDir)) {
60
+ const padded = result.currentPhase.toString().padStart(2, '0');
61
+ const files = fs.readdirSync(phasesDir);
62
+ const match = files.find(f =>
63
+ (f.startsWith(`${padded}-`) || f.startsWith(`${result.currentPhase}-`)) &&
64
+ f.endsWith('-PLAN.md')
65
+ );
66
+ if (match) {
67
+ planPath = path.join(phasesDir, match);
68
+ }
69
+ }
44
70
 
45
71
  if (fs.existsSync(planPath)) {
46
72
  const content = fs.readFileSync(planPath, 'utf-8');