tlc-claude-code 2.9.2 → 2.10.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.
@@ -106,14 +106,14 @@ process.stdout.write(JSON.stringify(result));" 2>/dev/null
106
106
  After `resolveRouting` returns, immediately write `.tlc/.build-routing-active` with the active provider name from `models[0]` before doing any other build work. Remove `.tlc/.build-routing-active` on completion, cancellation, or failure cleanup.
107
107
 
108
108
  **Routing decision:**
109
- - If routing says external provider (`models[0] !== 'claude'`), follow **ONLY Orchestrator Mode** below.
110
- - If routing says Claude (`models[0] === 'claude'`), follow **Inline Mode** below.
109
+ - **ALWAYS use Orchestrator Mode.** Claude never writes code inline. The routing config determines which provider the orchestrator dispatches TO (codex, claude session, gemini), but Claude in this conversation is always the PM.
110
+ - If the orchestrator is unreachable, auto-recover it (restart container, deploy latest code). If recovery fails, STOP do not fall back to inline code.
111
111
 
112
- ## ORCHESTRATOR MODE
112
+ ## ORCHESTRATOR MODE (ALWAYS)
113
113
 
114
- Use this mode only when `models[0]` is **NOT** `claude`.
114
+ Claude is the **project manager**. Claude reads the plan, breaks tasks into small prompts, and dispatches each to the tlc-core orchestrator. Claude does NOT write code. This is not conditional on routing — it is always the mode.
115
115
 
116
- Claude is the **project manager**. Claude reads the plan, breaks tasks into small prompts, and dispatches each to the tlc-core orchestrator. Claude does NOT write code.
116
+ The `models[0]` value from routing determines which provider the orchestrator uses (`codex`, `claude`, `gemini`), not whether Claude writes code inline.
117
117
 
118
118
  ### Step O1: Read the Plan
119
119
 
@@ -254,11 +254,9 @@ After PR is created (or phase completes):
254
254
  - Mark completed tasks `[x]` in PLAN.md
255
255
  - Report final summary
256
256
 
257
- ## INLINE MODE
257
+ ## AGENT INSTRUCTIONS (Reference for Dispatched Sessions)
258
258
 
259
- Use this mode only when `models[0]` **IS** `claude`.
260
-
261
- The existing build instructions below are the Inline Mode instructions and should be followed unchanged.
259
+ **These instructions are NOT for Claude in the main conversation.** They are the reference for what the dispatched orchestrator agent (Codex, Claude session, or Gemini) should do inside its tmux session. Claude packages these into the dispatch prompt — Claude does not execute them inline.
262
260
 
263
261
  ## Engineering Standards
264
262
 
@@ -19,9 +19,62 @@ For brand new projects with no code, use `/tlc:new-project` instead.
19
19
 
20
20
  ## Process
21
21
 
22
- ### 0. Upgrade Check (runs first, always)
22
+ ### 0. Orchestrator Enforcement (runs first, always)
23
23
 
24
- **Before anything else**, check if this is already a TLC project:
24
+ **Before anything else**, verify the orchestrator is available. All code execution goes through it — no exceptions.
25
+
26
+ ```bash
27
+ # Check orchestrator health
28
+ if curl -sf --max-time 2 http://localhost:3100/health > /dev/null 2>&1; then
29
+ echo "Orchestrator: ✅ healthy"
30
+ else
31
+ echo "Orchestrator: ❌ not running — attempting recovery..."
32
+ # Try to find and restart the orchestrator container
33
+ ORCH_CONTAINER=$(docker ps -a --format '{{.Names}}' 2>/dev/null | grep "orchestrator" | head -1)
34
+ if [ -n "$ORCH_CONTAINER" ]; then
35
+ docker start "$ORCH_CONTAINER" 2>/dev/null
36
+ sleep 3
37
+ fi
38
+ # If still down and tlc-core source exists, deploy and start
39
+ if ! curl -sf --max-time 2 http://localhost:3100/health > /dev/null 2>&1; then
40
+ if command -v tlc-core >/dev/null 2>&1; then
41
+ tlc-core start &
42
+ sleep 5
43
+ fi
44
+ fi
45
+ # Final check
46
+ if curl -sf --max-time 2 http://localhost:3100/health > /dev/null 2>&1; then
47
+ echo "Orchestrator: ✅ recovered"
48
+ else
49
+ echo "Orchestrator: ❌ FAILED — code execution will not work"
50
+ echo "Install tlc-core: git clone git@github.com:TwentyTwoLabs22/tlc-core.git && cd cli && npm i && npm link"
51
+ echo "Then run: tlc-core start"
52
+ fi
53
+ fi
54
+ ```
55
+
56
+ Also verify CodeDB and agent runner:
57
+
58
+ ```bash
59
+ # CodeDB
60
+ if ! curl -sf --max-time 1 http://localhost:7719/health > /dev/null 2>&1; then
61
+ if command -v codedb >/dev/null 2>&1; then
62
+ codedb serve . &
63
+ echo "CodeDB: ✅ started"
64
+ else
65
+ echo "CodeDB: ❌ not installed — run: npx tlc-claude-code"
66
+ fi
67
+ fi
68
+
69
+ # Agent runner container
70
+ if ! docker ps --format '{{.Names}}' 2>/dev/null | grep -q "tlc-agent-runner"; then
71
+ docker start tlc-agent-runner 2>/dev/null && echo "Agent Runner: ✅ started" || echo "Agent Runner: ❌ not available"
72
+ fi
73
+ ```
74
+
75
+ ### 0b. Upgrade Check
76
+
77
+ **After orchestrator is verified**, check if this is already a TLC project:
25
78
 
26
79
  ```bash
27
80
  # Check for existing TLC markers
@@ -100,14 +100,12 @@ process.stdout.write(JSON.stringify(result));" 2>/dev/null
100
100
  After `resolveRouting` returns, immediately write `.tlc/.quick-routing-active` with the active provider name from `models[0]` before doing any other quick work. Remove `.tlc/.quick-routing-active` on completion, cancellation, or failure cleanup.
101
101
 
102
102
  **Routing decision:**
103
- - If routing says external provider (`models[0] !== 'claude'`), follow **ONLY ORCHESTRATOR MODE** below.
104
- - If routing says Claude (`models[0] === 'claude'`), follow **INLINE MODE** below.
103
+ - **ALWAYS use Orchestrator Mode.** Claude never writes code inline. Routing determines which provider the orchestrator dispatches to.
104
+ - If orchestrator is down, auto-recover. If recovery fails, STOP do not fall back to inline.
105
105
 
106
- ## ORCHESTRATOR MODE
106
+ ## ORCHESTRATOR MODE (ALWAYS)
107
107
 
108
- Use this mode only when `models[0]` is **NOT** `claude`.
109
-
110
- Claude does not execute the quick-task instructions inline in this path. Claude acts as the orchestrator for the routed provider run:
108
+ Claude acts as the orchestrator dispatches the quick task to the orchestrator, monitors completion, verifies result. Claude does NOT write code.
111
109
 
112
110
  1. Treat Claude as the orchestrator for a small, test-first routed task rather than executing the work inline.
113
111
  2. Gather the minimal project context needed for the quick task, then package a focused prompt with the task request, expected failing test, implementation scope, and verification target.
@@ -123,12 +121,9 @@ Claude does not execute the quick-task instructions inline in this path. Claude
123
121
  - If the provider returns incomplete code or missing tests, issue a targeted retry for the missing part.
124
122
  7. When finished, display the routed provider result, persist any captured memory, remove `.tlc/.quick-routing-active`, and stop. Do **not** execute Inline Mode afterward.
125
123
 
126
- ## INLINE MODE
127
-
128
- Use this mode only when `models[0]` **IS** `claude`.
129
-
130
- The existing quick-task instructions below are the Inline Mode instructions and should be followed unchanged.
124
+ ## AGENT INSTRUCTIONS (Reference for Dispatched Sessions)
131
125
 
126
+ **These instructions are NOT for Claude in the main conversation.** They are packaged into the dispatch prompt for the orchestrator agent.
132
127
 
133
128
  ## Engineering Standards
134
129
 
@@ -181,6 +181,31 @@ Only mention upgrade details in `--verbose` mode.
181
181
 
182
182
  ## One-Pass Detection
183
183
 
184
+ ### Step 0: Quick Health Check
185
+
186
+ Before phase detection, run a fast health check (no auto-recovery — that's the SessionStart hook's job). Just report status in one line:
187
+
188
+ ```bash
189
+ # Check key systems in parallel (each with 1s timeout)
190
+ CODEDB=$(curl -sf --max-time 1 http://localhost:7719/health > /dev/null 2>&1 && echo "✅" || echo "❌")
191
+ ORCH=$(curl -sf --max-time 1 http://localhost:3100/health > /dev/null 2>&1 && echo "✅" || echo "❌")
192
+ RUNNER=$(docker ps --format '{{.Names}}' 2>/dev/null | grep -q "tlc-agent-runner" && echo "✅" || echo "❌")
193
+ ```
194
+
195
+ Print one compact line:
196
+
197
+ ```
198
+ Systems: CodeDB ${CODEDB} | Orchestrator ${ORCH} | Agent Runner ${RUNNER}
199
+ ```
200
+
201
+ If any system is ❌, **auto-recover immediately** before continuing:
202
+
203
+ 1. CodeDB ❌ → run `codedb serve . &` (or `npx tlc-claude-code` if binary missing), wait 2s, re-check
204
+ 2. Orchestrator ❌ → find orchestrator container (`docker ps | grep orchestrator`), deploy latest code from `../tlc-core/orchestrator/`, restart container, wait 3s, re-check
205
+ 3. Agent Runner ❌ → `docker start tlc-agent-runner` if stopped, report if container doesn't exist
206
+
207
+ After recovery attempts, print updated status. Only continue to phase detection after all recoverable systems are up. If recovery fails, print the failure and continue anyway — don't block indefinitely.
208
+
184
209
  ### Step 1: Load Core Context
185
210
 
186
211
  Read, in this order:
@@ -256,11 +281,22 @@ Backward compatibility:
256
281
 
257
282
  ## Output Format
258
283
 
259
- Normal output must stay within 3-5 lines.
284
+ Normal output must stay compact health line + phase status + action.
260
285
 
261
286
  Use this pattern:
262
287
 
263
288
  ```text
289
+ Systems: CodeDB ✅ | Orchestrator ✅ | Agent Runner ✅
290
+ TLC v{version} | Phase {PHASE_ID}: {Name} | {done}/{total} tasks done
291
+ Next: {action summary}
292
+ Running /tlc:{command} {PHASE_ID}...
293
+ ```
294
+
295
+ If any system is down:
296
+
297
+ ```text
298
+ Systems: CodeDB ✅ | Orchestrator ❌ | Agent Runner ✅
299
+ ⚠️ Orchestrator down — run /tlc:init to recover
264
300
  TLC v{version} | Phase {PHASE_ID}: {Name} | {done}/{total} tasks done
265
301
  Next: {action summary}
266
302
  Running /tlc:{command} {PHASE_ID}...
@@ -269,6 +305,7 @@ Running /tlc:{command} {PHASE_ID}...
269
305
  If there is nothing safe to auto-run:
270
306
 
271
307
  ```text
308
+ Systems: CodeDB ✅ | Orchestrator ✅ | Agent Runner ✅
272
309
  TLC v{version} | All phases complete
273
310
  Next: release or start the next milestone
274
311
  Run /tlc:complete or /tlc:new-milestone
@@ -338,7 +375,8 @@ Run /tlc:complete or /tlc:new-milestone
338
375
  ## Example
339
376
 
340
377
  ```text
341
- TLC v2.4.2 | Phase TLC-8: Auth System | 3/5 tasks done
378
+ Systems: CodeDB | Orchestrator | Agent Runner
379
+ TLC v2.9.2 | Phase TLC-8: Auth System | 3/5 tasks done
342
380
  Next: build task 4 (JWT middleware)
343
381
  Running /tlc:build TLC-8...
344
382
  ```
@@ -26,8 +26,15 @@ if [ "$INSTALLED_VER" = "not-installed" ]; then
26
26
  echo " TLC Package: ❌ not installed (run: npm i -g tlc-claude-code)"
27
27
  ERRORS=$((ERRORS + 1))
28
28
  elif [ "$INSTALLED_VER" != "$LATEST_VER" ] && [ "$LATEST_VER" != "unknown" ]; then
29
- echo " TLC Package: ⚠️ ${INSTALLED_VER} (latest: ${LATEST_VER})run: npm i -g tlc-claude-code"
30
- WARNINGS=$((WARNINGS + 1))
29
+ echo " TLC Package: ${INSTALLED_VER} ${LATEST_VER} — auto-updating..."
30
+ npm i -g tlc-claude-code@latest > /dev/null 2>&1
31
+ NEW_VER=$(node -e "try{console.log(require('tlc-claude-code/package.json').version)}catch{console.log('?')}" 2>/dev/null)
32
+ if [ "$NEW_VER" = "$LATEST_VER" ]; then
33
+ echo " TLC Package: ✅ updated to v${NEW_VER}"
34
+ else
35
+ echo " TLC Package: ⚠️ update failed — still on v${INSTALLED_VER}"
36
+ WARNINGS=$((WARNINGS + 1))
37
+ fi
31
38
  else
32
39
  echo " TLC Package: ✅ v${INSTALLED_VER} (latest)"
33
40
  fi
@@ -100,8 +107,20 @@ MCPEOF
100
107
  echo " CodeDB MCP: ✅ created .mcp.json"
101
108
  fi
102
109
  else
103
- echo " CodeDB: ❌ not installed (run: npx tlc-claude-code)"
104
- ERRORS=$((ERRORS + 1))
110
+ # Auto-install CodeDB binary
111
+ echo " CodeDB: ⏳ not installed — auto-installing..."
112
+ if npx -y tlc-claude-code 2>/dev/null | tail -1; then
113
+ if command -v codedb >/dev/null 2>&1; then
114
+ codedb serve "$PROJECT_DIR" > /dev/null 2>&1 &
115
+ echo " CodeDB: ✅ installed and started"
116
+ else
117
+ echo " CodeDB: ❌ install failed"
118
+ ERRORS=$((ERRORS + 1))
119
+ fi
120
+ else
121
+ echo " CodeDB: ❌ install failed"
122
+ ERRORS=$((ERRORS + 1))
123
+ fi
105
124
  fi
106
125
 
107
126
  # ─── 4. tlc-core Orchestrator + Containers ────────────────
@@ -125,17 +144,49 @@ elif curl -sf --max-time 2 "http://localhost:${TLC_CORE_PORT}/health" > /dev/nul
125
144
 
126
145
  # Check session monitor + watchdog
127
146
  ORCH_LOGS=$(docker logs tlc-core-orchestrator-1 --tail 50 2>&1)
147
+ MONITOR_OK=false
148
+ WATCHDOG_OK=false
128
149
  if echo "$ORCH_LOGS" | grep -q "Session monitor started"; then
150
+ MONITOR_OK=true
129
151
  echo " Session Monitor: ✅ active (10s interval)"
130
- else
131
- echo " Session Monitor: ❌ not running — orchestrator needs restart"
132
- ERRORS=$((ERRORS + 1))
133
152
  fi
134
153
  if echo "$ORCH_LOGS" | grep -q "Watchdog started\|watchdog.*Started"; then
154
+ WATCHDOG_OK=true
135
155
  echo " Watchdog: ✅ active (60s interval)"
136
- else
137
- echo " Watchdog: ⚠️ not detected in logs"
138
- WARNINGS=$((WARNINGS + 1))
156
+ fi
157
+
158
+ # Auto-recover: if monitor or watchdog missing, deploy latest code and restart
159
+ if [ "$MONITOR_OK" = false ] || [ "$WATCHDOG_OK" = false ]; then
160
+ echo " Monitor/Watchdog: ⏳ missing — deploying latest code and restarting..."
161
+ # Find orchestrator source
162
+ ORCH_SRC=""
163
+ if [ -d "$PROJECT_DIR/../tlc-core/orchestrator" ]; then
164
+ ORCH_SRC="$PROJECT_DIR/../tlc-core/orchestrator"
165
+ elif [ -d "$(dirname "$PROJECT_DIR")/tlc-core/orchestrator" ]; then
166
+ ORCH_SRC="$(dirname "$PROJECT_DIR")/tlc-core/orchestrator"
167
+ fi
168
+ if [ -n "$ORCH_SRC" ]; then
169
+ ORCH_CONTAINER=$(docker ps --format '{{.Names}}' 2>/dev/null | grep "orchestrator" | head -1)
170
+ if [ -n "$ORCH_CONTAINER" ]; then
171
+ docker cp "$ORCH_SRC/lib/." "$ORCH_CONTAINER:/app/lib/" 2>/dev/null
172
+ docker cp "$ORCH_SRC/index.js" "$ORCH_CONTAINER:/app/index.js" 2>/dev/null
173
+ docker cp "$ORCH_SRC/migrations/." "$ORCH_CONTAINER:/app/migrations/" 2>/dev/null
174
+ docker restart "$ORCH_CONTAINER" > /dev/null 2>&1
175
+ sleep 3
176
+ if curl -sf --max-time 2 "http://localhost:${TLC_CORE_PORT}/health" > /dev/null 2>&1; then
177
+ echo " Monitor/Watchdog: ✅ restarted with latest code"
178
+ else
179
+ echo " Monitor/Watchdog: ❌ restart failed"
180
+ ERRORS=$((ERRORS + 1))
181
+ fi
182
+ else
183
+ echo " Monitor/Watchdog: ❌ orchestrator container not found"
184
+ ERRORS=$((ERRORS + 1))
185
+ fi
186
+ else
187
+ [ "$MONITOR_OK" = false ] && echo " Session Monitor: ❌ not running (tlc-core source not found)" && ERRORS=$((ERRORS + 1))
188
+ [ "$WATCHDOG_OK" = false ] && echo " Watchdog: ⚠️ not detected" && WARNINGS=$((WARNINGS + 1))
189
+ fi
139
190
  fi
140
191
  else
141
192
  if command -v tlc-core >/dev/null 2>&1; then
@@ -180,6 +231,14 @@ PROVIDER_LIST=$(echo "$PROVIDER_LIST" | sed 's/, $//')
180
231
 
181
232
  if [ "$PROVIDER_COUNT" -gt 0 ]; then
182
233
  echo " LLM Providers: ✅ ${PROVIDER_COUNT} available — ${PROVIDER_LIST}"
234
+ # Check for updates (non-blocking, just warn)
235
+ if [ "$CODEX_VER" != "not installed" ]; then
236
+ CODEX_LATEST=$(npm view @openai/codex version 2>/dev/null || echo "")
237
+ if [ -n "$CODEX_LATEST" ] && [ "$CODEX_VER" != *"$CODEX_LATEST"* ] 2>/dev/null; then
238
+ echo " Codex Update: ⚠️ latest: ${CODEX_LATEST} — run: npm i -g @openai/codex"
239
+ WARNINGS=$((WARNINGS + 1))
240
+ fi
241
+ fi
183
242
  else
184
243
  echo " LLM Providers: ❌ none found"
185
244
  ERRORS=$((ERRORS + 1))
@@ -209,6 +268,8 @@ cat > "$STATE_FILE" <<STATEEOF
209
268
  STATEEOF
210
269
 
211
270
  # ─── 6. Git + Remote Sync ────────────────────────────────
271
+ # Fetch remote to get accurate ahead/behind counts
272
+ git fetch --quiet 2>/dev/null
212
273
  CURRENT_BRANCH=$(git branch --show-current 2>/dev/null)
213
274
  BEHIND=$(git rev-list --count HEAD..@{u} 2>/dev/null || echo "?")
214
275
  AHEAD=$(git rev-list --count @{u}..HEAD 2>/dev/null || echo "?")
@@ -254,11 +315,16 @@ if [ -n "$WORKSPACE_FILE" ]; then
254
315
  const rp = path.resolve(wsRoot, repo.path);
255
316
  try {
256
317
  fs.accessSync(rp);
318
+ // Fetch remote for accurate state
319
+ try { execSync('git -C ' + JSON.stringify(rp) + ' fetch --quiet', { stdio: ['pipe','pipe','pipe'], timeout: 10000 }); } catch {}
257
320
  const branch = execSync('git -C ' + JSON.stringify(rp) + ' branch --show-current', { encoding: 'utf8', stdio: ['pipe','pipe','pipe'] }).trim();
258
321
  let status = 'unknown';
259
322
  try {
260
323
  const behind = execSync('git -C ' + JSON.stringify(rp) + ' rev-list --count HEAD..@{u}', { encoding: 'utf8', stdio: ['pipe','pipe','pipe'] }).trim();
261
- status = behind === '0' ? 'in sync' : behind + ' behind';
324
+ const ahead = execSync('git -C ' + JSON.stringify(rp) + ' rev-list --count @{u}..HEAD', { encoding: 'utf8', stdio: ['pipe','pipe','pipe'] }).trim();
325
+ if (behind === '0' && ahead === '0') status = 'in sync';
326
+ else if (behind !== '0') status = behind + ' behind — needs pull';
327
+ else status = ahead + ' ahead — push pending';
262
328
  } catch { status = 'no remote tracking'; }
263
329
  console.log(' [' + repo.prefix + '] ' + branch + ': ' + status);
264
330
  } catch {
package/CLAUDE.md CHANGED
@@ -10,6 +10,7 @@
10
10
  4. **No direct implementation.** User says "build X" → run `/tlc:progress` then `/tlc:build`.
11
11
  5. **No Co-Authored-By in commits.** The user is the author. Claude is a tool.
12
12
  6. **Ask before `git push`.** Never push without explicit approval.
13
+ 7. **Claude NEVER writes code.** All code execution goes through the orchestrator (tlc-core :3100). Claude is PM — read, plan, dispatch, review. Sub-agents writing code is a bug. If the orchestrator is down, recover it first — never fall back to inline code.
13
14
 
14
15
  ## CodeDB
15
16
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tlc-claude-code",
3
- "version": "2.9.2",
3
+ "version": "2.10.0",
4
4
  "description": "TLC - Test Led Coding for Claude Code",
5
5
  "bin": {
6
6
  "tlc-claude-code": "./bin/install.js",