tlc-claude-code 1.8.2 → 1.8.4

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.
@@ -34,17 +34,24 @@ const { auditProject, generateReport } = require('./lib/standards/audit-checker'
34
34
 
35
35
  Run `auditProject(projectPath)` which executes:
36
36
 
37
- | Check | What It Finds |
38
- |-------|---------------|
39
- | Standards Files | Missing CLAUDE.md or CODING-STANDARDS.md |
40
- | Flat Folders | Files in src/services/, src/interfaces/, src/controllers/ |
41
- | Inline Interfaces | `interface X {` inside *.service.ts files |
42
- | Hardcoded URLs | http:// or https:// URLs in code |
43
- | Hardcoded Ports | `const port = 3000` patterns |
44
- | Magic Strings | `=== 'active'` comparisons without constants |
45
- | Flat Seeds | Seed files in src/seeds/ instead of src/{entity}/seeds/ |
46
- | Missing JSDoc | Exported functions without `/**` comments |
47
- | Deep Imports | `../../../` style imports (3+ levels) |
37
+ | Check | What It Finds | Severity |
38
+ |-------|---------------|----------|
39
+ | Standards Files | Missing CLAUDE.md or CODING-STANDARDS.md | error |
40
+ | Flat Folders | Files in src/services/, src/interfaces/, src/controllers/ | error |
41
+ | Inline Interfaces | `interface X {` inside *.service.ts or *.controller.ts files | error |
42
+ | Inline Constants | `const X =` hardcoded values inside service/controller files | warning |
43
+ | Hardcoded URLs | http:// or https:// URLs in code | error |
44
+ | Hardcoded Ports | `const port = 3000` patterns | error |
45
+ | Magic Strings | `=== 'active'` comparisons without constants | warning |
46
+ | Flat Seeds | Seed files in src/seeds/ instead of src/{entity}/seeds/ | warning |
47
+ | Missing JSDoc | Exported functions without `/**` comments | warning |
48
+ | Deep Imports | `../../../` style imports (3+ levels) | warning |
49
+ | **Oversized Files** | Files exceeding 1000 lines (warn at 500) | error/warning |
50
+ | **Overcrowded Folders** | Folders with >15 files directly inside (warn at 8) | error/warning |
51
+ | **`any` Type Usage** | `any` type annotations in TypeScript files | error |
52
+ | **Missing Return Types** | Exported functions without explicit return type | warning |
53
+ | **Missing Parameter Types** | Function parameters without type annotations | error |
54
+ | **Weak tsconfig** | `strict: true` not enabled in tsconfig.json | warning |
48
55
 
49
56
  ### Step 3: Generate Report
50
57
 
@@ -80,15 +87,27 @@ Status: {PASSED | FAILED}
80
87
  TLC Audit Results
81
88
  ═══════════════════════════════════════════════════════════════
82
89
 
83
- Status: FAILED (12 issues found)
84
-
85
- Standards Files: ✓ PASSED
86
- Flat Folders: ✗ 3 issues
87
- Inline Interfaces: 2 issues
88
- Hardcoded URLs: 4 issues
89
- Magic Strings: 2 issues
90
- JSDoc Coverage: ✗ 1 issue
91
- Import Style: ✓ PASSED
90
+ Status: FAILED (18 issues found)
91
+
92
+ STRUCTURE
93
+ Standards Files: PASSED
94
+ Flat Folders: 3 issues
95
+ Overcrowded Folders: 2 issues (controllers/ has 22 files)
96
+ Oversized Files: 1 issue (csp.controller.ts: 2,041 lines)
97
+
98
+ TYPES & INTERFACES
99
+ Inline Interfaces: 2 issues
100
+ Inline Constants: 3 issues
101
+ any Type Usage: 5 issues
102
+ Missing Return Types: 4 issues
103
+ Missing Param Types: 2 issues
104
+ Weak tsconfig: PASSED
105
+
106
+ CODE QUALITY
107
+ Hardcoded URLs: 4 issues
108
+ Magic Strings: 2 issues
109
+ JSDoc Coverage: 8 issues (42% of exports undocumented)
110
+ Import Style: PASSED
92
111
 
93
112
  Report saved to: .planning/AUDIT-REPORT.md
94
113
 
@@ -692,6 +692,11 @@ git diff --name-status main...HEAD
692
692
  1. **Test Coverage** - Every implementation file has a test file
693
693
  2. **TDD Compliance** - Commits show test-first pattern (score ≥ 50%)
694
694
  3. **Security Scan** - No hardcoded secrets, eval(), innerHTML, etc.
695
+ 4. **File Size** - No file exceeds 1000 lines (warning at 500+)
696
+ 5. **Folder Size** - No folder exceeds 15 files (warning at 8+)
697
+ 6. **Strict Typing** - No `any` types in new/changed files
698
+ 7. **Return Types** - All exported functions have explicit return types
699
+ 8. **Module Structure** - Files grouped by domain entity, not by type
695
700
 
696
701
  **Review output:**
697
702
 
@@ -702,6 +707,10 @@ git diff --name-status main...HEAD
702
707
  Test Coverage: ✅ 5/5 files covered
703
708
  TDD Score: 75% ✅
704
709
  Security: ✅ No issues
710
+ File Sizes: ✅ All under 1000 lines
711
+ Folder Sizes: ✅ All under 15 files
712
+ Strict Typing: ✅ No `any` found
713
+ Return Types: ✅ All exports typed
705
714
 
706
715
  Verdict: ✅ APPROVED
707
716
  ───────────────────────────────
@@ -721,6 +730,18 @@ TDD Score: 25% ❌ (target: 50%)
721
730
  Security: ❌ 1 high severity issue
722
731
  └── Hardcoded password in src/config.js
723
732
 
733
+ File Sizes: ⚠️ 1 file over limit
734
+ └── src/api/users.controller.ts (1,247 lines) → split by feature
735
+
736
+ Strict Typing: ❌ 3 `any` types found
737
+ ├── src/api/users.controller.ts:45 → define interface
738
+ ├── src/api/users.controller.ts:89 → use `unknown`
739
+ └── src/services/email.ts:12 → define `EmailOptions` interface
740
+
741
+ Return Types: ⚠️ 2 exported functions missing return types
742
+ ├── src/utils/helpers.ts:getConfig() → add `: AppConfig`
743
+ └── src/utils/helpers.ts:parseInput() → add `: ParsedInput`
744
+
724
745
  Verdict: ❌ CHANGES REQUESTED
725
746
 
726
747
  ⚠️ Phase cannot complete until issues are fixed.
@@ -730,7 +751,10 @@ Verdict: ❌ CHANGES REQUESTED
730
751
  **Actions on failure:**
731
752
  1. Add missing test files
732
753
  2. Fix security issues
733
- 3. Re-run `/tlc:build {phase}` to retry
754
+ 3. Split oversized files (>1000 lines) into focused sub-modules
755
+ 4. Replace `any` types with proper interfaces or `unknown`
756
+ 5. Add explicit return types to all exported functions
757
+ 6. Re-run `/tlc:build {phase}` to retry
734
758
 
735
759
  **CRITICAL: Phase is NOT complete until review passes.**
736
760
 
@@ -12,6 +12,10 @@ Automatically fix all coding standards violations. No prompts - just fixes every
12
12
  - Extracts inline interfaces to types/ files
13
13
  - Replaces magic strings with constants
14
14
  - Adds missing JSDoc comments
15
+ - **Splits oversized files** (>1000 lines) into focused sub-modules
16
+ - **Organizes overcrowded folders** (>15 files) into domain subfolders
17
+ - **Replaces `any` types** with proper interfaces or `unknown`
18
+ - **Adds missing return types** to exported functions
15
19
  4. Commits after each module/entity
16
20
  5. Reports results when done
17
21
 
@@ -101,6 +105,72 @@ export function getUser(id: string): User { }
101
105
  export function getUser(id: string): User { }
102
106
  ```
103
107
 
108
+ #### Oversized Files (>1000 lines)
109
+ ```
110
+ // Before: csp.controller.ts (2,041 lines)
111
+ // Analyze the file's responsibilities and split by feature:
112
+
113
+ // After:
114
+ modules/csp/
115
+ controllers/
116
+ policy.controller.ts # Policy CRUD routes
117
+ report.controller.ts # Violation report routes
118
+ directive.controller.ts # Directive management routes
119
+ csp.routes.ts # Thin route registration
120
+ csp.service.ts # Shared business logic
121
+ ```
122
+
123
+ **Split strategy:**
124
+ 1. Count exported functions/methods and group by feature
125
+ 2. Create a controller/service per feature group
126
+ 3. Keep a thin "facade" file that re-exports or registers all routes
127
+ 4. Move shared helpers to a utils file within the module
128
+
129
+ #### Overcrowded Folders (>15 files)
130
+ ```
131
+ // Before: controllers/ with 22 files
132
+ // Group by domain:
133
+
134
+ // After:
135
+ modules/
136
+ auth/ # auth.controller.ts, auth.service.ts
137
+ user/ # user.controller.ts, user.service.ts
138
+ billing/ # payment.controller.ts, invoice.controller.ts
139
+ catalog/ # product.controller.ts, category.controller.ts
140
+ ```
141
+
142
+ #### `any` Type Replacement
143
+ ```typescript
144
+ // Before
145
+ function processData(data: any): any {
146
+ return data.items;
147
+ }
148
+
149
+ // After
150
+ interface ProcessInput {
151
+ items: unknown[];
152
+ }
153
+
154
+ function processData(data: ProcessInput): unknown[] {
155
+ return data.items;
156
+ }
157
+ ```
158
+
159
+ **Strategy:** Read how the variable is used, infer the shape, create an interface.
160
+
161
+ #### Missing Return Types
162
+ ```typescript
163
+ // Before
164
+ export function calculateTotal(items: CartItem[]) {
165
+ return items.reduce((sum, item) => sum + item.price, 0);
166
+ }
167
+
168
+ // After
169
+ export function calculateTotal(items: CartItem[]): number {
170
+ return items.reduce((sum, item) => sum + item.price, 0);
171
+ }
172
+ ```
173
+
104
174
  ### Step 4: Commit After Each Module
105
175
 
106
176
  After fixing all issues in an entity/module:
@@ -17,6 +17,12 @@ Research and create implementation plans with clear tasks.
17
17
  - **Error boundaries**: Where can failures occur? How are they handled?
18
18
  - **Data flow**: How does data enter, transform, and exit the system?
19
19
 
20
+ ### Code Quality Gates
21
+ - **File size limit**: No file should exceed 1000 lines. Plan splits for large modules.
22
+ - **Folder limit**: No folder should exceed 15 files. Plan domain subfolders.
23
+ - **Strict typing**: Plan interfaces upfront — no `any` types, explicit return types.
24
+ - **Module structure**: Group by domain entity (NestJS-style), not by file type.
25
+
20
26
  ### Task Breakdown
21
27
  - **Vertical slices**: Each task delivers testable, visible progress
22
28
  - **Risk-first**: Tackle unknowns and integrations early
@@ -61,6 +67,13 @@ Each task should be:
61
67
  - **Small** - completable in one focused session
62
68
  - **Testable** - has clear pass/fail criteria
63
69
  - **Independent** - minimal dependencies on other tasks
70
+ - **Standards-compliant** - won't produce files >1000 lines or folders >15 files
71
+
72
+ **Before finalizing tasks, check:**
73
+ 1. Will any planned file exceed 1000 lines? → Split into sub-modules
74
+ 2. Will any folder exceed 15 files? → Plan domain subfolders
75
+ 3. Are all interfaces defined? → Add `interfaces/` directory per module
76
+ 4. Are types explicit? → Plan typed interfaces, not `any`
64
77
 
65
78
  #### Task Status Markers (Multi-User)
66
79
 
@@ -82,12 +95,15 @@ Use `/tlc:claim` to claim a task, `/tlc:release` to release one.
82
95
  **Goal:** Define database schema for users table
83
96
 
84
97
  **Files:**
85
- - src/db/schema/users.ts
98
+ - src/modules/user/interfaces/user.interface.ts
99
+ - src/modules/user/user.repository.ts
86
100
 
87
101
  **Acceptance Criteria:**
88
102
  - [ ] Schema has id, email, passwordHash, createdAt
89
103
  - [ ] Email is unique
90
104
  - [ ] Timestamps auto-populate
105
+ - [ ] All types explicit (no `any`)
106
+ - [ ] Exported functions have return types
91
107
 
92
108
  **Test Cases:**
93
109
  - Schema validates correct user data
@@ -42,6 +42,7 @@ Same checks as `/tlc:review`:
42
42
  - Test coverage for changed files
43
43
  - TDD compliance (commit order)
44
44
  - Security scan
45
+ - **Coding standards** (file size, folder size, strict typing, return types, module structure)
45
46
 
46
47
  ### Step 4: Generate PR Comment
47
48
 
@@ -53,12 +54,17 @@ Same checks as `/tlc:review`:
53
54
  | Test Coverage | ✅ All files covered |
54
55
  | TDD Score | ✅ 75% |
55
56
  | Security | ✅ No issues |
57
+ | File Sizes | ✅ All under 1000 lines |
58
+ | Folder Sizes | ✅ All under 15 files |
59
+ | Strict Typing | ✅ No `any` types |
60
+ | Return Types | ✅ All exports typed |
56
61
 
57
62
  ### Summary
58
63
 
59
64
  - 8 files changed (5 impl, 3 tests)
60
65
  - 4 commits analyzed
61
66
  - No security vulnerabilities detected
67
+ - All coding standards met
62
68
 
63
69
  ### Verdict: ✅ APPROVED
64
70
 
@@ -134,6 +140,12 @@ TDD Score: 0% ❌
134
140
  Security: ⚠️ 1 medium severity issue
135
141
  └── console.log with sensitive data
136
142
 
143
+ Coding Standards: ❌ 4 issues
144
+ ├── src/auth/login.js (1,247 lines) → split by feature
145
+ ├── src/auth/login.js:45 → `any` type found
146
+ ├── src/auth/login.js:89 → `any` type found
147
+ └── src/config.js:getConfig() → missing return type
148
+
137
149
  Posting review...
138
150
 
139
151
  ─────────────────────────────────
@@ -145,6 +157,9 @@ See: https://github.com/org/repo/pull/43#review-123457
145
157
  Required actions:
146
158
  1. Add/update tests for modified files
147
159
  2. Remove console.log with sensitive data
160
+ 3. Split oversized file (>1000 lines)
161
+ 4. Replace `any` types with proper interfaces
162
+ 5. Add return types to exported functions
148
163
  ─────────────────────────────────
149
164
  ```
150
165
 
@@ -112,6 +112,65 @@ Scan diff for common security issues:
112
112
 
113
113
  **Fail if:** Any HIGH severity issues found.
114
114
 
115
+ ### Step 5b: Coding Standards Check
116
+
117
+ Scan all changed/added files for coding standards violations:
118
+
119
+ #### File Size Check
120
+ ```bash
121
+ # For each changed implementation file
122
+ wc -l <file>
123
+ # >1000 lines = ERROR, 500-1000 = WARNING
124
+ ```
125
+
126
+ #### Folder Size Check
127
+ ```bash
128
+ # For each folder containing changed files
129
+ ls <folder> | wc -l
130
+ # >15 files = ERROR, 8-15 = WARNING
131
+ ```
132
+
133
+ #### Strict Typing Check
134
+ ```bash
135
+ # Scan changed .ts/.tsx files for `any` type
136
+ grep -n ': any' <file>
137
+ grep -n 'as any' <file>
138
+ grep -n '<any>' <file>
139
+ # Any match = ERROR
140
+ ```
141
+
142
+ #### Return Type Check
143
+ ```bash
144
+ # Scan changed .ts/.tsx files for exported functions missing return types
145
+ # Pattern: export function name(params) { (no : ReturnType before {)
146
+ grep -n 'export function.*)[[:space:]]*{' <file>
147
+ grep -n 'export const.*=.*=>.*{' <file>
148
+ # Missing return type on exported function = WARNING
149
+ ```
150
+
151
+ #### Module Structure Check
152
+ ```
153
+ # Flag flat folder anti-patterns in changed files:
154
+ # - src/services/ with >5 unrelated services → should be modules/{entity}/
155
+ # - src/controllers/ with >5 controllers → should be modules/{entity}/
156
+ # - src/interfaces/ at project root → should be per-module interfaces/
157
+ ```
158
+
159
+ **Standards results in report:**
160
+ ```
161
+ Coding Standards:
162
+ File Sizes: ✅ All under 1000 lines
163
+ Folder Sizes: ✅ All under 15 files
164
+ Strict Typing: ❌ 3 `any` types found
165
+ ├── src/api/users.controller.ts:45
166
+ ├── src/api/users.controller.ts:89
167
+ └── src/services/email.ts:12
168
+ Return Types: ⚠️ 2 missing on exports
169
+ Module Structure: ✅ Domain-grouped
170
+ ```
171
+
172
+ **Fail if:** Any `any` types in new code, or files >1000 lines.
173
+
115
174
  ### Step 6: Invoke External Providers (Codex, Gemini)
116
175
 
117
176
  **CRITICAL: This step runs automatically when providers are configured.**
@@ -220,6 +279,9 @@ Invoking Codex (GPT-5.2) for review...
220
279
  - ✅ All changed files have tests
221
280
  - ✅ TDD score: 75%
222
281
  - ✅ No security issues detected
282
+ - ✅ All files under 1000 lines
283
+ - ✅ No `any` types
284
+ - ✅ All exports have return types
223
285
 
224
286
  ## Statistics
225
287
 
@@ -16,10 +16,185 @@ See `/tlc:build` for the complete engineering standards checklist.
16
16
 
17
17
  ## What This Does
18
18
 
19
- Launches the TLC dashboard - a visual interface showing project state, phases, tests, and next actions.
19
+ Detects project state, checks for TLC version upgrades, and launches the dashboard. If a newer TLC version is installed than the project has configured, it automatically upgrades config and commands before proceeding.
20
20
 
21
21
  ## Process
22
22
 
23
+ ### Step 0: Check TLC Version (Upgrade Detection)
24
+
25
+ **Run this BEFORE anything else.** Compare installed TLC version against the project's `.tlc.json` version.
26
+
27
+ ```bash
28
+ # Get installed TLC version
29
+ installedVersion=$(node -e "
30
+ try {
31
+ const p = require('tlc-claude-code/package.json');
32
+ console.log(p.version);
33
+ } catch(e) {
34
+ // Try global
35
+ const { execSync } = require('child_process');
36
+ try {
37
+ const v = execSync('npm list -g tlc-claude-code --json 2>/dev/null', { encoding: 'utf-8' });
38
+ console.log(JSON.parse(v).dependencies['tlc-claude-code'].version);
39
+ } catch(e2) { console.log('unknown'); }
40
+ }
41
+ " 2>/dev/null)
42
+
43
+ # Get project TLC version from .tlc.json
44
+ projectVersion=$(node -e "
45
+ try {
46
+ const c = require('./.tlc.json');
47
+ console.log(c.tlcVersion || '0.0.0');
48
+ } catch(e) { console.log('0.0.0'); }
49
+ " 2>/dev/null)
50
+ ```
51
+
52
+ **If `installedVersion` > `projectVersion`:**
53
+
54
+ Show upgrade notice and apply automatically:
55
+
56
+ ```
57
+ ─────────────────────────────────────────────────────
58
+ TLC UPGRADE DETECTED
59
+ ─────────────────────────────────────────────────────
60
+
61
+ Installed: v{installedVersion}
62
+ Project: v{projectVersion}
63
+
64
+ New in this version:
65
+ {list new features — see Version Features Map below}
66
+
67
+ Applying upgrade...
68
+ ```
69
+
70
+ Then execute the upgrade steps:
71
+
72
+ #### Step 0.1: Merge New Config Sections into .tlc.json
73
+
74
+ Read the project's `.tlc.json`. For each new config section introduced since `projectVersion`, **add it ONLY if it doesn't already exist**. Never overwrite existing user settings.
75
+
76
+ ```javascript
77
+ // Pseudo-code for config merge
78
+ const config = JSON.parse(fs.readFileSync('.tlc.json'));
79
+
80
+ // Add new sections only if missing
81
+ if (!config.router) {
82
+ config.router = {
83
+ providers: {},
84
+ capabilities: {}
85
+ };
86
+ console.log(' + Added: router (LLM provider routing)');
87
+ }
88
+
89
+ if (!config.dashboard) {
90
+ config.dashboard = {
91
+ port: 3147,
92
+ auth: false
93
+ };
94
+ console.log(' + Added: dashboard config');
95
+ }
96
+
97
+ if (!config.docs) {
98
+ config.docs = {
99
+ autoSync: false,
100
+ screenshots: []
101
+ };
102
+ console.log(' + Added: docs automation config');
103
+ }
104
+
105
+ // Update version stamp
106
+ config.tlcVersion = installedVersion;
107
+
108
+ fs.writeFileSync('.tlc.json', JSON.stringify(config, null, 2));
109
+ ```
110
+
111
+ #### Step 0.2: Update CLAUDE.md Command Dispatch
112
+
113
+ Read the project's `CLAUDE.md`. Check if the command dispatch table exists. If new commands were added since `projectVersion`, append them to the table.
114
+
115
+ **How to detect:** Read `.claude/commands/tlc/*.md` directory listing from the installed TLC package. Compare against the dispatch table entries in the project's `CLAUDE.md`. Add any missing rows.
116
+
117
+ **Never remove or reorder existing entries.** Only append new ones.
118
+
119
+ #### Step 0.3: Sync Command Files
120
+
121
+ The `.claude/commands/tlc/` directory should already be up-to-date if the user ran `tlc` (the CLI installer). But verify:
122
+
123
+ ```bash
124
+ # Check if commands are current
125
+ installedCommandCount=$(ls node_modules/tlc-claude-code/.claude/commands/tlc/*.md 2>/dev/null | wc -l)
126
+ projectCommandCount=$(ls .claude/commands/tlc/*.md 2>/dev/null | wc -l)
127
+
128
+ if [ "$installedCommandCount" -gt "$projectCommandCount" ]; then
129
+ echo " + Syncing new commands to .claude/commands/tlc/"
130
+ cp node_modules/tlc-claude-code/.claude/commands/tlc/*.md .claude/commands/tlc/
131
+ fi
132
+ ```
133
+
134
+ #### Step 0.4: Detect New LLM Providers
135
+
136
+ If the `router` section was just added (or is empty), scan for available CLI tools:
137
+
138
+ ```bash
139
+ which claude >/dev/null 2>&1 && echo "claude detected"
140
+ which codex >/dev/null 2>&1 && echo "codex detected"
141
+ which gemini >/dev/null 2>&1 && echo "gemini detected"
142
+ ```
143
+
144
+ If providers are detected but `router.providers` is empty, offer to configure:
145
+
146
+ ```
147
+ LLM providers detected: claude, codex
148
+
149
+ Configure multi-model routing? (Y/n)
150
+ ```
151
+
152
+ If yes, populate `router.providers` with detected CLIs and default capability mappings.
153
+
154
+ If no, skip — user can run `/tlc:llm config` later.
155
+
156
+ #### Step 0.5: Report and Continue
157
+
158
+ ```
159
+ ─────────────────────────────────────────────────────
160
+ UPGRADE COMPLETE
161
+ ─────────────────────────────────────────────────────
162
+
163
+ Updated .tlc.json:
164
+ + router (LLM provider routing)
165
+ + dashboard config
166
+ + docs automation config
167
+ ~ tlcVersion: 0.0.0 → 1.8.2
168
+
169
+ Synced:
170
+ + 3 new commands added
171
+ + CLAUDE.md dispatch table updated
172
+
173
+ Configure LLM routing now? → /tlc:llm config
174
+ Configure dashboard? → /tlc:dashboard
175
+
176
+ Continuing to dashboard...
177
+ ─────────────────────────────────────────────────────
178
+ ```
179
+
180
+ Then continue to Step 1 (launch dashboard) as normal.
181
+
182
+ **If versions match:** Skip this step silently. No output.
183
+
184
+ #### Version Features Map
185
+
186
+ This map tells the upgrade which config sections to add based on version ranges. Update this when new features ship.
187
+
188
+ | Since Version | Config Section | Default Value | Description |
189
+ |---|---|---|---|
190
+ | 1.5.0 | `router` | `{ providers: {}, capabilities: {} }` | LLM multi-model routing |
191
+ | 1.5.0 | `enterprise` | `{ enabled: false }` | Enterprise features toggle |
192
+ | 1.7.0 | `docs` | `{ autoSync: false, screenshots: [] }` | Documentation automation |
193
+ | 1.8.0 | `dashboard` | `{ port: 3147, auth: false }` | Dashboard configuration |
194
+ | 1.8.2 | `dashboard.compose` | `"docker-compose.tlc.yml"` | Standalone dashboard compose file |
195
+
196
+ ---
197
+
23
198
  ### Step 1: Launch Dashboard
24
199
 
25
200
  Run the TLC dashboard:
@@ -588,6 +588,141 @@ Refs: #456
588
588
 
589
589
  ---
590
590
 
591
+ ## 18. File Size Limits
592
+
593
+ Large files are a code smell. They indicate a class or module is doing too much.
594
+
595
+ | Threshold | Action |
596
+ |---|---|
597
+ | **< 300 lines** | Ideal. No action needed. |
598
+ | **300-500 lines** | Acceptable. Review if it can be split. |
599
+ | **500-1000 lines** | Warning. Should be split into focused sub-modules. |
600
+ | **> 1000 lines** | Violation. MUST be split before merging. |
601
+
602
+ ### How to Split
603
+
604
+ **Controllers with many routes:**
605
+ ```
606
+ # Bad: csp.controller.ts (2,000+ lines)
607
+ # Good: Split by resource/feature:
608
+ modules/csp/
609
+ controllers/
610
+ policy.controller.ts # CRUD for policies
611
+ report.controller.ts # CSP violation reports
612
+ directive.controller.ts # Directive management
613
+ csp.routes.ts # Route registration (thin)
614
+ ```
615
+
616
+ **Services with many methods:**
617
+ ```
618
+ # Bad: user.service.ts (1,500 lines)
619
+ # Good: Split by responsibility:
620
+ modules/user/
621
+ services/
622
+ user-auth.service.ts # Login, register, password reset
623
+ user-profile.service.ts # Profile CRUD, avatar, preferences
624
+ user-admin.service.ts # Admin operations, ban, role changes
625
+ user.service.ts # Thin facade re-exporting sub-services
626
+ ```
627
+
628
+ ---
629
+
630
+ ## 19. Folder Overcrowding
631
+
632
+ Too many files in one folder makes navigation difficult. Organize into subfolders by domain.
633
+
634
+ | Threshold | Action |
635
+ |---|---|
636
+ | **< 8 files** | Fine as-is. |
637
+ | **8-15 files** | Consider grouping into subfolders. |
638
+ | **> 15 files** | MUST be organized into subfolders. |
639
+
640
+ ```
641
+ # Bad: 25 files dumped in controllers/
642
+ controllers/
643
+ auth.controller.ts
644
+ user.controller.ts
645
+ payment.controller.ts
646
+ invoice.controller.ts
647
+ product.controller.ts
648
+ ... (20 more)
649
+
650
+ # Good: Organized by domain
651
+ modules/
652
+ auth/auth.controller.ts
653
+ user/user.controller.ts
654
+ billing/
655
+ payment.controller.ts
656
+ invoice.controller.ts
657
+ catalog/
658
+ product.controller.ts
659
+ ```
660
+
661
+ ---
662
+
663
+ ## 20. Strict Typing
664
+
665
+ TypeScript without strict types is just JavaScript with extra steps.
666
+
667
+ ### Rules
668
+
669
+ 1. **No `any` type** - Use `unknown` and narrow, or define a proper interface.
670
+ 2. **No implicit `any`** - Enable `noImplicitAny` in tsconfig.
671
+ 3. **All functions must have explicit return types** - Not just exported functions.
672
+ 4. **All parameters must be typed** - No untyped function parameters.
673
+ 5. **Prefer `interface` over `type`** for object shapes - Easier to extend.
674
+ 6. **Use `strict: true`** in tsconfig.json.
675
+
676
+ ```typescript
677
+ // Bad: Missing types, implicit any
678
+ function processData(data) {
679
+ const result = data.items.map(item => item.value);
680
+ return result;
681
+ }
682
+
683
+ // Good: Explicit types everywhere
684
+ interface DataPayload {
685
+ items: Array<{ value: number }>;
686
+ }
687
+
688
+ function processData(data: DataPayload): number[] {
689
+ return data.items.map((item) => item.value);
690
+ }
691
+ ```
692
+
693
+ ```typescript
694
+ // Bad: any type
695
+ function handleResponse(response: any): any {
696
+ return response.data;
697
+ }
698
+
699
+ // Good: Proper types
700
+ interface ApiResponse<T> {
701
+ data: T;
702
+ status: number;
703
+ }
704
+
705
+ function handleResponse<T>(response: ApiResponse<T>): T {
706
+ return response.data;
707
+ }
708
+ ```
709
+
710
+ ### tsconfig.json Requirements
711
+
712
+ ```json
713
+ {
714
+ "compilerOptions": {
715
+ "strict": true,
716
+ "noImplicitAny": true,
717
+ "noImplicitReturns": true,
718
+ "noUnusedLocals": true,
719
+ "noUnusedParameters": true
720
+ }
721
+ }
722
+ ```
723
+
724
+ ---
725
+
591
726
  ## AI Instructions
592
727
 
593
728
  When generating code:
@@ -605,6 +740,10 @@ When generating code:
605
740
  11. **Always** add JSDoc to public members
606
741
  12. **Always** create index.ts with barrel exports
607
742
  13. **Always** verify build passes after changes
743
+ 14. **Never** let files exceed 1000 lines - split into sub-modules
744
+ 15. **Never** let folders exceed 15 files - organize into subfolders
745
+ 16. **Never** use `any` type - use `unknown` or proper interfaces
746
+ 17. **Always** add explicit return types to functions
608
747
 
609
748
  ### Cleanup Tasks
610
749
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tlc-claude-code",
3
- "version": "1.8.2",
3
+ "version": "1.8.4",
4
4
  "description": "TLC - Test Led Coding for Claude Code",
5
5
  "bin": {
6
6
  "tlc": "./bin/tlc.js",
package/server/index.js CHANGED
@@ -57,6 +57,7 @@ const EXTERNAL_APP_PORT = parseInt(process.env.TLC_APP_PORT || '5000');
57
57
  // State
58
58
  let appProcess = null;
59
59
  let appPort = 3000;
60
+ let appIsDocker = false; // true when app is Docker-managed (no local process)
60
61
  let wsClients = new Set();
61
62
  const logs = { app: [], test: [], git: [] };
62
63
  const commandHistory = [];
@@ -485,6 +486,19 @@ async function startApp() {
485
486
 
486
487
  appPort = project.port;
487
488
  addLog('app', `Detected: ${project.name}`, 'info');
489
+
490
+ // Docker-managed apps: don't spawn, just proxy
491
+ if (project.type === 'docker') {
492
+ appIsDocker = true;
493
+ addLog('app', `App is Docker-managed — proxying to port ${appPort}`, 'info');
494
+ if (project.url) {
495
+ addLog('app', `App URL: ${project.url}`, 'info');
496
+ }
497
+ addLog('app', 'TLC will not spawn the app. Use Docker to manage it.', 'info');
498
+ broadcast('app-start', { port: appPort });
499
+ return;
500
+ }
501
+
488
502
  addLog('app', `Command: ${project.cmd} ${project.args.join(' ')}`, 'info');
489
503
  addLog('app', `Port: ${appPort}`, 'info');
490
504
 
@@ -673,7 +687,7 @@ app.get('/api/status', (req, res) => {
673
687
  const plan = parsePlan(PROJECT_DIR);
674
688
 
675
689
  res.json({
676
- appRunning: appProcess !== null,
690
+ appRunning: appProcess !== null || appIsDocker,
677
691
  appPort,
678
692
  testsPass: plan.testsPass || 0,
679
693
  testsFail: plan.testsFail || 0,
@@ -1087,7 +1101,7 @@ app.get('/api/health', (req, res) => {
1087
1101
  heapUsed: memUsage.heapUsed,
1088
1102
  heapTotal: memUsage.heapTotal,
1089
1103
  },
1090
- appRunning: appProcess !== null,
1104
+ appRunning: appProcess !== null || appIsDocker,
1091
1105
  appPort,
1092
1106
  });
1093
1107
  });
@@ -1486,7 +1500,7 @@ function getHealthData() {
1486
1500
  memory: memUsed,
1487
1501
  cpu: Math.min(cpuPercent, 100),
1488
1502
  uptime: process.uptime(),
1489
- appRunning: appProcess !== null,
1503
+ appRunning: appProcess !== null || appIsDocker,
1490
1504
  appPort: appPort
1491
1505
  };
1492
1506
  }
@@ -10,6 +10,33 @@ function detectProject(projectDir) {
10
10
  if (fs.existsSync(tlcConfigPath)) {
11
11
  try {
12
12
  const config = JSON.parse(fs.readFileSync(tlcConfigPath, 'utf-8'));
13
+
14
+ // Check devServer config (Docker-managed apps)
15
+ if (config.devServer) {
16
+ if (config.devServer.type === 'docker') {
17
+ return {
18
+ name: 'Docker-managed (' + (config.devServer.containerName || 'docker') + ')',
19
+ type: 'docker',
20
+ cmd: null,
21
+ args: [],
22
+ port: config.devServer.port || config.devServer.internalPort || 5000,
23
+ healthCheck: config.devServer.healthCheck || null,
24
+ url: config.devServer.url || null
25
+ };
26
+ }
27
+ // Non-docker devServer with explicit start command
28
+ if (config.devServer.startCommand) {
29
+ const parts = config.devServer.startCommand.split(' ');
30
+ return {
31
+ name: 'Custom (.tlc.json devServer)',
32
+ cmd: parts[0],
33
+ args: parts.slice(1),
34
+ port: config.devServer.port || 3000
35
+ };
36
+ }
37
+ }
38
+
39
+ // Legacy: check server config
13
40
  if (config.server?.startCommand) {
14
41
  const parts = config.server.startCommand.split(' ');
15
42
  return {