tlc-claude-code 2.2.1 → 2.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.
Files changed (49) hide show
  1. package/.claude/agents/builder.md +17 -0
  2. package/.claude/commands/tlc/audit.md +12 -0
  3. package/.claude/commands/tlc/autofix.md +31 -0
  4. package/.claude/commands/tlc/build.md +98 -24
  5. package/.claude/commands/tlc/coverage.md +31 -0
  6. package/.claude/commands/tlc/discuss.md +31 -0
  7. package/.claude/commands/tlc/docs.md +31 -0
  8. package/.claude/commands/tlc/edge-cases.md +31 -0
  9. package/.claude/commands/tlc/guard.md +9 -0
  10. package/.claude/commands/tlc/init.md +12 -1
  11. package/.claude/commands/tlc/plan.md +31 -0
  12. package/.claude/commands/tlc/quick.md +31 -0
  13. package/.claude/commands/tlc/review.md +50 -0
  14. package/.claude/hooks/tlc-session-init.sh +14 -3
  15. package/CODING-STANDARDS.md +217 -10
  16. package/bin/setup-autoupdate.js +316 -87
  17. package/bin/setup-autoupdate.test.js +454 -34
  18. package/package.json +1 -1
  19. package/scripts/project-docs.js +1 -1
  20. package/server/lib/careful-patterns.js +142 -0
  21. package/server/lib/careful-patterns.test.js +164 -0
  22. package/server/lib/cli-dispatcher.js +98 -0
  23. package/server/lib/cli-dispatcher.test.js +249 -0
  24. package/server/lib/command-router.js +171 -0
  25. package/server/lib/command-router.test.js +336 -0
  26. package/server/lib/field-report.js +92 -0
  27. package/server/lib/field-report.test.js +195 -0
  28. package/server/lib/orchestration/worktree-manager.js +133 -0
  29. package/server/lib/orchestration/worktree-manager.test.js +198 -0
  30. package/server/lib/overdrive-command.js +31 -9
  31. package/server/lib/overdrive-command.test.js +25 -26
  32. package/server/lib/prompt-packager.js +98 -0
  33. package/server/lib/prompt-packager.test.js +185 -0
  34. package/server/lib/review-fixer.js +107 -0
  35. package/server/lib/review-fixer.test.js +152 -0
  36. package/server/lib/routing-command.js +159 -0
  37. package/server/lib/routing-command.test.js +290 -0
  38. package/server/lib/scope-checker.js +127 -0
  39. package/server/lib/scope-checker.test.js +175 -0
  40. package/server/lib/skill-validator.js +165 -0
  41. package/server/lib/skill-validator.test.js +289 -0
  42. package/server/lib/standards/standards-injector.js +6 -0
  43. package/server/lib/task-router-config.js +142 -0
  44. package/server/lib/task-router-config.test.js +428 -0
  45. package/server/lib/test-selector.js +127 -0
  46. package/server/lib/test-selector.test.js +172 -0
  47. package/server/setup.sh +271 -271
  48. package/server/templates/CLAUDE.md +6 -0
  49. package/server/templates/CODING-STANDARDS.md +356 -10
@@ -122,6 +122,23 @@ src/modules/{entity}/
122
122
  - No credentials — use environment variables.
123
123
  - No magic numbers or strings — use named constants or enums.
124
124
 
125
+ ### Configuration
126
+ - All `process.env` access MUST be in a config module — never in services or controllers.
127
+ - Validate all required env vars at startup with a schema (Zod/Joi).
128
+ - No silent empty-string fallbacks for secrets or connection strings.
129
+
130
+ ### Security
131
+ - Every data-access endpoint MUST check resource ownership, not just authentication.
132
+ - Never return secrets (API keys, tokens, passwords) in API responses or HTML.
133
+ - Hash OTPs, reset tokens, and session secrets before storing — never plaintext.
134
+ - Escape all dynamic values in HTML output — no raw interpolation.
135
+ - No inline HTML string builders for new pages — use a proper frontend or templating engine.
136
+ - Tests MUST prove that user A cannot read/modify user B's data.
137
+
138
+ ### Dependency Injection
139
+ - Never manually instantiate services/providers with `new` — use DI.
140
+ - Register all providers in the DI container.
141
+
125
142
  ### File and Folder Limits
126
143
  - Files: warn at 500 lines, error at 1000 lines.
127
144
  - Folders: warn at 8 files, error at 15 files.
@@ -52,6 +52,11 @@ Run `auditProject(projectPath)` which executes:
52
52
  | **Missing Return Types** | Exported functions without explicit return type | warning |
53
53
  | **Missing Parameter Types** | Function parameters without type annotations | error |
54
54
  | **Weak tsconfig** | `strict: true` not enabled in tsconfig.json | warning |
55
+ | **Direct `process.env`** | `process.env.` usage outside config module files | error |
56
+ | **Unescaped HTML** | Template literals containing HTML tags with `${` interpolation | error |
57
+ | **Secrets in Responses** | Response objects containing fields named `apiKey`, `secret`, `token`, `password` | error |
58
+ | **Manual Instantiation** | `new .*Provider(` or `new .*Service(` in application code | warning |
59
+ | **Missing Ownership Check** | Controller methods with `@Param('id')` but no ownership/authorization guard | warning |
55
60
 
56
61
  ### Step 3: Generate Report
57
62
 
@@ -109,6 +114,13 @@ Status: FAILED (18 issues found)
109
114
  JSDoc Coverage: 8 issues (42% of exports undocumented)
110
115
  Import Style: PASSED
111
116
 
117
+ SECURITY & CONFIG
118
+ Direct process.env: 3 issues (outside config module)
119
+ Unescaped HTML: 2 issues
120
+ Secrets in Responses: 1 issue
121
+ Manual Instantiation: 1 issue
122
+ Missing Ownership: 2 issues
123
+
112
124
  Report saved to: .planning/AUDIT-REPORT.md
113
125
 
114
126
  Fix automatically? Run /tlc:cleanup
@@ -2,6 +2,37 @@
2
2
 
3
3
  Run tests, analyze failures, and automatically apply fixes for common error patterns.
4
4
 
5
+ ## Routing
6
+
7
+ This command supports multi-model routing via `~/.tlc/config.json`.
8
+
9
+ **Before executing this command:**
10
+
11
+ 1. Read routing config:
12
+ ```bash
13
+ node -e "
14
+ const { resolveRouting } = require('./server/lib/task-router-config');
15
+ const flagModel = (process.argv.find(a => a.startsWith("--model")) || "").replace("--model=", "").replace("--model ", "") || null;
16
+ const r = resolveRouting({ command: 'autofix', flagModel, projectDir: process.cwd(), homeDir: process.env.HOME });
17
+ console.log(JSON.stringify(r));
18
+ " 2>/dev/null
19
+ ```
20
+
21
+ 2. If `models[0]` is NOT `claude` (i.e., routed to external model):
22
+ - Read PROJECT.md, current phase PLAN.md, CODING-STANDARDS.md
23
+ - Package the agent prompt below with project context using `prompt-packager`
24
+ - Dispatch to the target CLI using `cli-dispatcher`
25
+ - Display the CLI output and stop — do NOT execute the agent prompt below
26
+
27
+ 3. If `models[0]` IS `claude` (or no routing config exists):
28
+ - Execute the agent prompt below as normal (current behavior)
29
+
30
+ 4. If `strategy` is `parallel`:
31
+ - Execute inline (Claude) AND dispatch to CLI models simultaneously
32
+ - Collect and merge results
33
+
34
+ **Override:** Pass `--model <name>` to route this specific run to a different model.
35
+
5
36
  ## What This Does
6
37
 
7
38
  1. Runs test suite and captures failures
@@ -2,6 +2,37 @@
2
2
 
3
3
  Write failing tests, then implement to make them pass.
4
4
 
5
+ ## Routing
6
+
7
+ This command supports multi-model routing via `~/.tlc/config.json`.
8
+
9
+ **Before executing this command:**
10
+
11
+ 1. Read routing config:
12
+ ```bash
13
+ node -e "
14
+ const { resolveRouting } = require('./server/lib/task-router-config');
15
+ const flagModel = (process.argv.find(a => a.startsWith("--model")) || "").replace("--model=", "").replace("--model ", "") || null;
16
+ const r = resolveRouting({ command: 'build', flagModel, projectDir: process.cwd(), homeDir: process.env.HOME });
17
+ console.log(JSON.stringify(r));
18
+ " 2>/dev/null
19
+ ```
20
+
21
+ 2. If `models[0]` is NOT `claude` (i.e., routed to external model):
22
+ - Read PROJECT.md, current phase PLAN.md, CODING-STANDARDS.md
23
+ - Package the agent prompt below with project context using `prompt-packager`
24
+ - Dispatch to the target CLI using `cli-dispatcher`
25
+ - Display the CLI output and stop — do NOT execute the agent prompt below
26
+
27
+ 3. If `models[0]` IS `claude` (or no routing config exists):
28
+ - Execute the agent prompt below as normal (current behavior)
29
+
30
+ 4. If `strategy` is `parallel`:
31
+ - Execute inline (Claude) AND dispatch to CLI models simultaneously
32
+ - Collect and merge results
33
+
34
+ **Override:** Pass `--model <name>` to route this specific run to a different model.
35
+
5
36
  ## Engineering Standards
6
37
 
7
38
  **Code like a senior engineer with 15+ years experience.** Every line should reflect:
@@ -344,11 +375,45 @@ Task(resume="AGENT_ID", prompt="Continue from where you left off. Fix any errors
344
375
  - When user asks "check on agents"
345
376
  - After each agent completes
346
377
 
347
- **After all agents complete:**
348
- 1. Run full test suite
378
+ **Before spawning agents (integration branch):**
379
+
380
+ Create an integration branch so all worktrees merge into one place, producing a single clean PR:
381
+
382
+ ```javascript
383
+ const { createIntegrationBranch } = require('./server/lib/orchestration/worktree-manager');
384
+ const { branch } = createIntegrationBranch(phaseNumber, { exec, baseBranch: 'main' });
385
+ // branch = 'phase/42'
386
+ ```
387
+
388
+ All worktrees branch off `phase/{N}`, not `main`. This means each worktree's diff is small and relative to the integration branch, not the entire main history.
389
+
390
+ **After all agents complete — sequential merge-back:**
391
+
392
+ ```javascript
393
+ const { mergeAllWorktrees, listWorktrees } = require('./server/lib/orchestration/worktree-manager');
394
+
395
+ // Filter to only THIS phase's worktrees — don't merge unrelated work
396
+ const allWorktrees = listWorktrees({ exec });
397
+ const worktrees = allWorktrees.filter(wt => wt.name.startsWith(`phase-${phaseNumber}-`));
398
+ const result = mergeAllWorktrees(worktrees, `phase/${phaseNumber}`, { exec });
399
+
400
+ // result.merged = ['task-1', 'task-3', 'task-4'] — successfully merged
401
+ // result.conflicts = ['task-2'] — needs manual resolution
402
+ ```
403
+
404
+ `mergeAllWorktrees` does the following automatically:
405
+ 1. **Analyzes file overlap** — worktrees touching disjoint files merge first
406
+ 2. **Merges one at a time** into `phase/{N}`
407
+ 3. **Rebases remaining worktrees** onto the updated `phase/{N}` after each merge
408
+ 4. **Skips conflicting worktrees** — preserves them for manual resolution, continues with others
409
+ 5. **Cleans up** merged worktrees (removes worktree dir + branch)
410
+
411
+ After merge-back:
412
+ 1. Run full test suite on the integration branch
349
413
  2. Verify all tasks pass
350
- 3. Report results
351
- 4. Continue to Step 8 (verification)
414
+ 3. If conflicts exist, report them with file lists
415
+ 4. If clean, the integration branch is ready for a single PR to main
416
+ 5. Continue to Step 8 (verification)
352
417
 
353
418
  ### Step 1c: Sync and Claim (Multi-User, Sequential Only)
354
419
 
@@ -712,11 +777,17 @@ git diff --name-status main...HEAD
712
777
  1. **Test Coverage** - Every implementation file has a test file
713
778
  2. **TDD Compliance** - Commits show test-first pattern (score ≥ 50%)
714
779
  3. **Security Scan** - No hardcoded secrets, eval(), innerHTML, etc.
715
- 4. **File Size** - No file exceeds 1000 lines (warning at 500+)
716
- 5. **Folder Size** - No folder exceeds 15 files (warning at 8+)
717
- 6. **Strict Typing** - No `any` types in new/changed files
718
- 7. **Return Types** - All exported functions have explicit return types
719
- 8. **Module Structure** - Files grouped by domain entity, not by type
780
+ 4. **Authorization** - Every data-access endpoint has ownership checks, not just auth guards
781
+ 5. **Secrets Exposure** - No API keys, tokens, or passwords returned in responses/HTML
782
+ 6. **Config Hygiene** - No `process.env` outside config module; config validated at startup
783
+ 7. **Output Encoding** - No unescaped `${...}` interpolation in HTML template strings
784
+ 8. **Sensitive Data** - OTPs, reset tokens, session secrets are hashed before storage
785
+ 9. **DI Compliance** - No manual `new Service()` / `new Provider()` in application code
786
+ 10. **File Size** - No file exceeds 1000 lines (warning at 500+)
787
+ 11. **Folder Size** - No folder exceeds 15 files (warning at 8+)
788
+ 12. **Strict Typing** - No `any` types in new/changed files
789
+ 13. **Return Types** - All exported functions have explicit return types
790
+ 14. **Module Structure** - Files grouped by domain entity, not by type
720
791
 
721
792
  **Review output:**
722
793
 
@@ -727,8 +798,11 @@ git diff --name-status main...HEAD
727
798
  Test Coverage: ✅ 5/5 files covered
728
799
  TDD Score: 75% ✅
729
800
  Security: ✅ No issues
801
+ Authorization: ✅ All endpoints have ownership checks
802
+ Secrets Exposure: ✅ No secrets in responses
803
+ Config Hygiene: ✅ No process.env outside config
804
+ Output Encoding: ✅ All HTML output escaped
730
805
  File Sizes: ✅ All under 1000 lines
731
- Folder Sizes: ✅ All under 15 files
732
806
  Strict Typing: ✅ No `any` found
733
807
  Return Types: ✅ All exports typed
734
808
 
@@ -899,10 +973,10 @@ Found: 2-PLAN.md (4 tasks)
899
973
  🚀 Overdrive Mode Available (Opus 4.6)
900
974
 
901
975
  Phase 2 has 4 independent tasks:
902
- - Task 1: Create API routes [sonnet] (standard)
903
- - Task 2: Add input validation [sonnet] (standard)
904
- - Task 3: Write error handlers [sonnet] (standard)
905
- - Task 4: Add rate limiting config [haiku] (light)
976
+ - Task 1: Create API routes [opus]
977
+ - Task 2: Add input validation [opus]
978
+ - Task 3: Write error handlers [opus]
979
+ - Task 4: Add rate limiting config [opus]
906
980
 
907
981
  Recommended: 4 agents (one per task)
908
982
 
@@ -916,17 +990,17 @@ User: 1
916
990
  Claude: 🚀 Launching Overdrive Mode (Opus 4.6)
917
991
 
918
992
  Spawning 4 agents...
919
- [Agent 1] Task 1: Create API routes [sonnet] - STARTED
920
- [Agent 2] Task 2: Add input validation [sonnet] - STARTED
921
- [Agent 3] Task 3: Write error handlers [sonnet] - STARTED
922
- [Agent 4] Task 4: Add rate limiting config [haiku] - STARTED
993
+ [Agent 1] Task 1: Create API routes [opus] - STARTED
994
+ [Agent 2] Task 2: Add input validation [opus] - STARTED
995
+ [Agent 3] Task 3: Write error handlers [opus] - STARTED
996
+ [Agent 4] Task 4: Add rate limiting config [opus] - STARTED
923
997
 
924
998
  ... agents working in background ...
925
999
 
926
- [Agent 4] ✅ Task 4 complete (1 commit) [haiku - fast]
927
- [Agent 2] ✅ Task 2 complete (3 commits) [sonnet]
928
- [Agent 1] ✅ Task 1 complete (4 commits) [sonnet]
929
- [Agent 3] ✅ Task 3 complete (2 commits) [sonnet]
1000
+ [Agent 4] ✅ Task 4 complete (1 commit) [opus]
1001
+ [Agent 2] ✅ Task 2 complete (3 commits) [opus]
1002
+ [Agent 1] ✅ Task 1 complete (4 commits) [opus]
1003
+ [Agent 3] ✅ Task 3 complete (2 commits) [opus]
930
1004
 
931
1005
  All agents complete. Running full test suite...
932
1006
  ✅ 24 tests passing
@@ -957,7 +1031,7 @@ Phase 2 complete. Ready for /tlc:verify 2
957
1031
  - Merge conflicts → Agents working on same files (rare if tasks are truly independent)
958
1032
  - One agent failed → Other agents continue; resume failed agent or fix manually
959
1033
  - Want sequential instead → Use `--sequential` flag: `/tlc:build 2 --sequential`
960
- - Cost too high → Use `--model haiku` to force all agents to haiku
1034
+ - Cost too high → Use `--agents 2` to limit parallelism
961
1035
  - Agent running too long → Use `--max-turns 30` to limit execution
962
1036
 
963
1037
  ## Flags
@@ -966,7 +1040,7 @@ Phase 2 complete. Ready for /tlc:verify 2
966
1040
  |------|-------------|
967
1041
  | `--sequential` | Force sequential execution even if tasks are independent |
968
1042
  | `--agents N` | Limit parallel agents to N (default: one per independent task) |
969
- | `--model MODEL` | Force all agents to use a specific model (opus, sonnet, haiku) |
1043
+ | `--model opus` | Force all agents to opus (default all tiers use opus) |
970
1044
  | `--max-turns N` | Limit each agent's execution to N turns (default: 50) |
971
1045
  | `--providers claude,codex` | Force specific providers (default: auto-detect from router state) |
972
1046
  | `--no-tmux` | Skip tmux panes, run worktree agents in background |
@@ -2,6 +2,37 @@
2
2
 
3
3
  Scan existing code, identify what's untested, and offer to write retrospective tests.
4
4
 
5
+ ## Routing
6
+
7
+ This command supports multi-model routing via `~/.tlc/config.json`.
8
+
9
+ **Before executing this command:**
10
+
11
+ 1. Read routing config:
12
+ ```bash
13
+ node -e "
14
+ const { resolveRouting } = require('./server/lib/task-router-config');
15
+ const flagModel = (process.argv.find(a => a.startsWith("--model")) || "").replace("--model=", "").replace("--model ", "") || null;
16
+ const r = resolveRouting({ command: 'coverage', flagModel, projectDir: process.cwd(), homeDir: process.env.HOME });
17
+ console.log(JSON.stringify(r));
18
+ " 2>/dev/null
19
+ ```
20
+
21
+ 2. If `models[0]` is NOT `claude` (i.e., routed to external model):
22
+ - Read PROJECT.md, current phase PLAN.md, CODING-STANDARDS.md
23
+ - Package the agent prompt below with project context using `prompt-packager`
24
+ - Dispatch to the target CLI using `cli-dispatcher`
25
+ - Display the CLI output and stop — do NOT execute the agent prompt below
26
+
27
+ 3. If `models[0]` IS `claude` (or no routing config exists):
28
+ - Execute the agent prompt below as normal (current behavior)
29
+
30
+ 4. If `strategy` is `parallel`:
31
+ - Execute inline (Claude) AND dispatch to CLI models simultaneously
32
+ - Collect and merge results
33
+
34
+ **Override:** Pass `--model <name>` to route this specific run to a different model.
35
+
5
36
  ## When to Use
6
37
 
7
38
  - After `/tlc:init` to add tests to existing code
@@ -2,6 +2,37 @@
2
2
 
3
3
  Capture implementation preferences before planning.
4
4
 
5
+ ## Routing
6
+
7
+ This command supports multi-model routing via `~/.tlc/config.json`.
8
+
9
+ **Before executing this command:**
10
+
11
+ 1. Read routing config:
12
+ ```bash
13
+ node -e "
14
+ const { resolveRouting } = require('./server/lib/task-router-config');
15
+ const flagModel = (process.argv.find(a => a.startsWith("--model")) || "").replace("--model=", "").replace("--model ", "") || null;
16
+ const r = resolveRouting({ command: 'discuss', flagModel, projectDir: process.cwd(), homeDir: process.env.HOME });
17
+ console.log(JSON.stringify(r));
18
+ " 2>/dev/null
19
+ ```
20
+
21
+ 2. If `models[0]` is NOT `claude` (i.e., routed to external model):
22
+ - Read PROJECT.md, current phase PLAN.md, CODING-STANDARDS.md
23
+ - Package the agent prompt below with project context using `prompt-packager`
24
+ - Dispatch to the target CLI using `cli-dispatcher`
25
+ - Display the CLI output and stop — do NOT execute the agent prompt below
26
+
27
+ 3. If `models[0]` IS `claude` (or no routing config exists):
28
+ - Execute the agent prompt below as normal (current behavior)
29
+
30
+ 4. If `strategy` is `parallel`:
31
+ - Execute inline (Claude) AND dispatch to CLI models simultaneously
32
+ - Collect and merge results
33
+
34
+ **Override:** Pass `--model <name>` to route this specific run to a different model.
35
+
5
36
  ## What This Does
6
37
 
7
38
  Gathers your preferences for HOW a phase should be built through adaptive questioning. Saves decisions to guide planning and test writing.
@@ -2,6 +2,37 @@
2
2
 
3
3
  Automatically maintain your project's documentation, screenshots, and wiki.
4
4
 
5
+ ## Routing
6
+
7
+ This command supports multi-model routing via `~/.tlc/config.json`.
8
+
9
+ **Before executing this command:**
10
+
11
+ 1. Read routing config:
12
+ ```bash
13
+ node -e "
14
+ const { resolveRouting } = require('./server/lib/task-router-config');
15
+ const flagModel = (process.argv.find(a => a.startsWith("--model")) || "").replace("--model=", "").replace("--model ", "") || null;
16
+ const r = resolveRouting({ command: 'docs', flagModel, projectDir: process.cwd(), homeDir: process.env.HOME });
17
+ console.log(JSON.stringify(r));
18
+ " 2>/dev/null
19
+ ```
20
+
21
+ 2. If `models[0]` is NOT `claude` (i.e., routed to external model):
22
+ - Read PROJECT.md, current phase PLAN.md, CODING-STANDARDS.md
23
+ - Package the agent prompt below with project context using `prompt-packager`
24
+ - Dispatch to the target CLI using `cli-dispatcher`
25
+ - Display the CLI output and stop — do NOT execute the agent prompt below
26
+
27
+ 3. If `models[0]` IS `claude` (or no routing config exists):
28
+ - Execute the agent prompt below as normal (current behavior)
29
+
30
+ 4. If `strategy` is `parallel`:
31
+ - Execute inline (Claude) AND dispatch to CLI models simultaneously
32
+ - Collect and merge results
33
+
34
+ **Override:** Pass `--model <name>` to route this specific run to a different model.
35
+
5
36
  ## Usage
6
37
 
7
38
  ```bash
@@ -2,6 +2,37 @@
2
2
 
3
3
  Analyze code and generate comprehensive edge case tests to improve test coverage.
4
4
 
5
+ ## Routing
6
+
7
+ This command supports multi-model routing via `~/.tlc/config.json`.
8
+
9
+ **Before executing this command:**
10
+
11
+ 1. Read routing config:
12
+ ```bash
13
+ node -e "
14
+ const { resolveRouting } = require('./server/lib/task-router-config');
15
+ const flagModel = (process.argv.find(a => a.startsWith("--model")) || "").replace("--model=", "").replace("--model ", "") || null;
16
+ const r = resolveRouting({ command: 'edge-cases', flagModel, projectDir: process.cwd(), homeDir: process.env.HOME });
17
+ console.log(JSON.stringify(r));
18
+ " 2>/dev/null
19
+ ```
20
+
21
+ 2. If `models[0]` is NOT `claude` (i.e., routed to external model):
22
+ - Read PROJECT.md, current phase PLAN.md, CODING-STANDARDS.md
23
+ - Package the agent prompt below with project context using `prompt-packager`
24
+ - Dispatch to the target CLI using `cli-dispatcher`
25
+ - Display the CLI output and stop — do NOT execute the agent prompt below
26
+
27
+ 3. If `models[0]` IS `claude` (or no routing config exists):
28
+ - Execute the agent prompt below as normal (current behavior)
29
+
30
+ 4. If `strategy` is `parallel`:
31
+ - Execute inline (Claude) AND dispatch to CLI models simultaneously
32
+ - Collect and merge results
33
+
34
+ **Override:** Pass `--model <name>` to route this specific run to a different model.
35
+
5
36
  ## What This Does
6
37
 
7
38
  1. Analyzes target file/function
@@ -89,6 +89,15 @@ For a phase that's been (partially) built, verify TLC compliance:
89
89
  - [ ] No hardcoded secrets, URLs, or credentials (check for patterns)
90
90
  - [ ] No skipped tests (`.skip`, `xit`, `xdescribe`)
91
91
 
92
+ **Security & Config (CODING-STANDARDS §6, §21, §22):**
93
+ - [ ] Every data-access endpoint has ownership check (not just auth — verify user owns the resource)
94
+ - [ ] No secrets (API keys, tokens, passwords) returned in API responses or rendered in HTML
95
+ - [ ] No `process.env` in services/controllers — all config through validated config module
96
+ - [ ] No unescaped `${...}` interpolation in HTML template strings
97
+ - [ ] OTPs, reset tokens, session secrets are hashed before storage (not plaintext)
98
+ - [ ] No `new ServiceClass()` / `new ProviderClass()` — use DI container
99
+ - [ ] Tests prove user A cannot read/modify user B's data (ownership test)
100
+
92
101
  **Process:**
93
102
  - [ ] Phase plan exists and tasks are checked off
94
103
  - [ ] Implementation matches what was planned (no scope creep)
@@ -207,7 +207,18 @@ Start writing tests now, or save backlog for later?
207
207
 
208
208
  **If "Start now":** Begin writing tests for the first critical path item using Red-Green-Refactor (but code already exists, so focus on capturing current behavior).
209
209
 
210
- ### 9. Create CLAUDE.md
210
+ ### 9. Inject Standards (CLAUDE.md + CODING-STANDARDS.md)
211
+
212
+ **First, inject both standards files using the standards-injector module:**
213
+
214
+ ```javascript
215
+ const { injectStandards } = require('./lib/standards/standards-injector');
216
+ const results = await injectStandards(projectPath);
217
+ // Creates CLAUDE.md and CODING-STANDARDS.md from templates if missing
218
+ // Appends TLC section to existing CLAUDE.md if present
219
+ ```
220
+
221
+ **If the module is not available** (e.g., TLC server not installed locally), create `CLAUDE.md` manually and copy `CODING-STANDARDS.md` from the TLC templates directory.
211
222
 
212
223
  Create `CLAUDE.md` to enforce TLC workflow over Claude's default behaviors:
213
224
 
@@ -2,6 +2,37 @@
2
2
 
3
3
  Research and create implementation plans with clear tasks.
4
4
 
5
+ ## Routing
6
+
7
+ This command supports multi-model routing via `~/.tlc/config.json`.
8
+
9
+ **Before executing this command:**
10
+
11
+ 1. Read routing config:
12
+ ```bash
13
+ node -e "
14
+ const { resolveRouting } = require('./server/lib/task-router-config');
15
+ const flagModel = (process.argv.find(a => a.startsWith("--model")) || "").replace("--model=", "").replace("--model ", "") || null;
16
+ const r = resolveRouting({ command: 'plan', flagModel, projectDir: process.cwd(), homeDir: process.env.HOME });
17
+ console.log(JSON.stringify(r));
18
+ " 2>/dev/null
19
+ ```
20
+
21
+ 2. If `models[0]` is NOT `claude` (i.e., routed to external model):
22
+ - Read PROJECT.md, current phase PLAN.md, CODING-STANDARDS.md
23
+ - Package the agent prompt below with project context using `prompt-packager`
24
+ - Dispatch to the target CLI using `cli-dispatcher`
25
+ - Display the CLI output and stop — do NOT execute the agent prompt below
26
+
27
+ 3. If `models[0]` IS `claude` (or no routing config exists):
28
+ - Execute the agent prompt below as normal (current behavior)
29
+
30
+ 4. If `strategy` is `parallel`:
31
+ - Execute inline (Claude) AND dispatch to CLI models simultaneously
32
+ - Collect and merge results
33
+
34
+ **Override:** Pass `--model <name>` to route this specific run to a different model.
35
+
5
36
  ## Architectural Standards
6
37
 
7
38
  **Plan like a principal engineer designing for scale:**
@@ -2,6 +2,37 @@
2
2
 
3
3
  For ad-hoc tasks that don't need full phase planning, but still deserve tests.
4
4
 
5
+ ## Routing
6
+
7
+ This command supports multi-model routing via `~/.tlc/config.json`.
8
+
9
+ **Before executing this command:**
10
+
11
+ 1. Read routing config:
12
+ ```bash
13
+ node -e "
14
+ const { resolveRouting } = require('./server/lib/task-router-config');
15
+ const flagModel = (process.argv.find(a => a.startsWith("--model")) || "").replace("--model=", "").replace("--model ", "") || null;
16
+ const r = resolveRouting({ command: 'quick', flagModel, projectDir: process.cwd(), homeDir: process.env.HOME });
17
+ console.log(JSON.stringify(r));
18
+ " 2>/dev/null
19
+ ```
20
+
21
+ 2. If `models[0]` is NOT `claude` (i.e., routed to external model):
22
+ - Read PROJECT.md, current phase PLAN.md, CODING-STANDARDS.md
23
+ - Package the agent prompt below with project context using `prompt-packager`
24
+ - Dispatch to the target CLI using `cli-dispatcher`
25
+ - Display the CLI output and stop — do NOT execute the agent prompt below
26
+
27
+ 3. If `models[0]` IS `claude` (or no routing config exists):
28
+ - Execute the agent prompt below as normal (current behavior)
29
+
30
+ 4. If `strategy` is `parallel`:
31
+ - Execute inline (Claude) AND dispatch to CLI models simultaneously
32
+ - Collect and merge results
33
+
34
+ **Override:** Pass `--model <name>` to route this specific run to a different model.
35
+
5
36
  ## Engineering Standards
6
37
 
7
38
  Even quick tasks follow senior engineer standards:
@@ -2,6 +2,37 @@
2
2
 
3
3
  Review changes on current branch before pushing. **Runs in a loop until clean.**
4
4
 
5
+ ## Routing
6
+
7
+ This command supports multi-model routing via `~/.tlc/config.json`.
8
+
9
+ **Before executing this command:**
10
+
11
+ 1. Read routing config:
12
+ ```bash
13
+ node -e "
14
+ const { resolveRouting } = require('./server/lib/task-router-config');
15
+ const flagModel = (process.argv.find(a => a.startsWith("--model")) || "").replace("--model=", "").replace("--model ", "") || null;
16
+ const r = resolveRouting({ command: 'review', flagModel, projectDir: process.cwd(), homeDir: process.env.HOME });
17
+ console.log(JSON.stringify(r));
18
+ " 2>/dev/null
19
+ ```
20
+
21
+ 2. If `models[0]` is NOT `claude` (i.e., routed to external model):
22
+ - Read PROJECT.md, current phase PLAN.md, CODING-STANDARDS.md
23
+ - Package the agent prompt below with project context using `prompt-packager`
24
+ - Dispatch to the target CLI using `cli-dispatcher`
25
+ - Display the CLI output and stop — do NOT execute the agent prompt below
26
+
27
+ 3. If `models[0]` IS `claude` (or no routing config exists):
28
+ - Execute the agent prompt below as normal (current behavior)
29
+
30
+ 4. If `strategy` is `parallel`:
31
+ - Execute inline (Claude) AND dispatch to CLI models simultaneously
32
+ - Collect and merge results
33
+
34
+ **Override:** Pass `--model <name>` to route this specific run to a different model.
35
+
5
36
  ## What This Does
6
37
 
7
38
  1. Compares current branch to main/master
@@ -116,6 +147,8 @@ git log --oneline --name-status main..HEAD
116
147
 
117
148
  Scan diff for common security issues:
118
149
 
150
+ **Pattern-Based Checks:**
151
+
119
152
  | Pattern | Issue | Severity |
120
153
  |---------|-------|----------|
121
154
  | `password = "..."` | Hardcoded password | HIGH |
@@ -126,6 +159,17 @@ Scan diff for common security issues:
126
159
  | `exec("..." + var)` | Command injection | HIGH |
127
160
  | `SELECT...WHERE...+` | SQL injection | HIGH |
128
161
 
162
+ **Semantic Security Checks (read the code, not just grep):**
163
+
164
+ | Check | What to Look For | Severity |
165
+ |-------|-----------------|----------|
166
+ | **Ownership/IDOR** | Controller methods that take an ID param (`req.params.id`, `@Param('id')`) and query data without checking the requesting user owns the resource. Every data-access endpoint MUST verify ownership, not just authentication. | HIGH |
167
+ | **Secrets in responses** | Response objects, DTOs, or `res.json()`/`res.send()` calls that include fields like `apiKey`, `secret`, `token`, `password`, `webhookSecret`. Secrets are write-only — never return them. | HIGH |
168
+ | **Direct `process.env`** | `process.env.` usage in service, controller, or middleware files. All env access MUST go through a validated config module. Grep: `process\.env\.` in non-config files. | MEDIUM |
169
+ | **Unescaped HTML** | Template literals that build HTML with `${...}` interpolation of variables (e.g., `` `<h1>${user.name}</h1>` ``). All dynamic values in HTML MUST be escaped. | HIGH |
170
+ | **Plaintext sensitive data** | OTP codes, reset tokens, or session secrets stored without hashing. Look for database inserts/updates of these values without a hash step. | HIGH |
171
+ | **Manual instantiation** | `new SomeProvider(...)` or `new SomeService(...)` in application code instead of using DI. | MEDIUM |
172
+
129
173
  **Fail if:** Any HIGH severity issues found.
130
174
 
131
175
  ### Step 5b: Coding Standards Check
@@ -311,6 +355,12 @@ After Steps 2-6 complete, if ANY issues were found:
311
355
  | `any` type | Replace with proper interface | If domain type unclear |
312
356
  | File >1000 lines | Split into sub-modules | If split strategy unclear |
313
357
  | Security vulnerability | Patch it | If fix might break behavior |
358
+ | Missing ownership check | Add guard/check | If ownership model unclear |
359
+ | Secrets in response | Remove or mask fields | If field is needed by client |
360
+ | Direct `process.env` | Move to config module | If config module doesn't exist yet |
361
+ | Unescaped HTML | Add escapeHtml() | If templating engine preferred |
362
+ | Plaintext sensitive data | Add hash step | - |
363
+ | Manual `new Service()` | Convert to DI | If DI container not set up |
314
364
  | Codex-flagged bug | Apply suggestion | If suggestion conflicts with Claude |
315
365
  | Merge conflict | - | Always human |
316
366
 
@@ -10,6 +10,17 @@ fi
10
10
 
11
11
  echo "TLC project detected. All work goes through /tlc commands. Run /tlc for current status and next action."
12
12
 
13
+ # ─── TLC Update Notification ─────────────────────────────
14
+ UPDATE_FILE="$HOME/.tlc/.update-available"
15
+ if [ -f "$UPDATE_FILE" ]; then
16
+ CURRENT=$(grep '^current=' "$UPDATE_FILE" | cut -d= -f2)
17
+ LATEST=$(grep '^latest=' "$UPDATE_FILE" | cut -d= -f2)
18
+ CMD=$(grep '^command=' "$UPDATE_FILE" | cut -d= -f2-)
19
+ if [ -n "$CURRENT" ] && [ -n "$LATEST" ]; then
20
+ echo "TLC update available: ${CURRENT} → ${LATEST}. Run: ${CMD}"
21
+ fi
22
+ fi
23
+
13
24
  PROJECT_DIR="${CLAUDE_PROJECT_DIR:-$(pwd)}"
14
25
 
15
26
  # ─── TLC Server ───────────────────────────────────────────
@@ -53,9 +64,9 @@ fi
53
64
 
54
65
  if [ "$STALE" = true ]; then
55
66
  # Probe each provider
56
- CLAUDE_PATH=$(which claude 2>/dev/null || echo "")
57
- CODEX_PATH=$(which codex 2>/dev/null || echo "")
58
- GEMINI_PATH=$(which gemini 2>/dev/null || echo "")
67
+ CLAUDE_PATH=$(command -v claude 2>/dev/null || echo "")
68
+ CODEX_PATH=$(command -v codex 2>/dev/null || echo "")
69
+ GEMINI_PATH=$(command -v gemini 2>/dev/null || echo "")
59
70
 
60
71
  CLAUDE_OK="false"
61
72
  CODEX_OK="false"