tlc-claude-code 2.5.0 → 2.6.1
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/.claude/commands/tlc/autofix.md +34 -1
- package/.claude/commands/tlc/build.md +164 -6
- package/.claude/commands/tlc/ci.md +178 -414
- package/.claude/commands/tlc/coverage.md +34 -0
- package/.claude/commands/tlc/deploy.md +19 -6
- package/.claude/commands/tlc/discuss.md +34 -0
- package/.claude/commands/tlc/docs.md +35 -1
- package/.claude/commands/tlc/e2e.md +300 -0
- package/.claude/commands/tlc/edge-cases.md +35 -1
- package/.claude/commands/tlc/init.md +38 -8
- package/.claude/commands/tlc/new-project.md +46 -4
- package/.claude/commands/tlc/plan.md +33 -0
- package/.claude/commands/tlc/quick.md +33 -0
- package/.claude/commands/tlc/release.md +85 -135
- package/.claude/commands/tlc/restore.md +14 -0
- package/.claude/commands/tlc/review.md +76 -1
- package/.claude/commands/tlc/tlc.md +134 -0
- package/.claude/commands/tlc/verify.md +64 -65
- package/.claude/commands/tlc/watchci.md +10 -0
- package/.claude/hooks/tlc-block-tools.sh +13 -0
- package/.claude/hooks/tlc-session-init.sh +29 -0
- package/CODING-STANDARDS.md +35 -10
- package/package.json +1 -1
- package/server/lib/block-tools-hook.js +23 -0
- package/server/lib/e2e/acceptance-parser.js +132 -0
- package/server/lib/e2e/acceptance-parser.test.js +110 -0
- package/server/lib/e2e/framework-detector.js +47 -0
- package/server/lib/e2e/framework-detector.test.js +94 -0
- package/server/lib/e2e/log-assertions.js +107 -0
- package/server/lib/e2e/log-assertions.test.js +68 -0
- package/server/lib/e2e/test-generator.js +159 -0
- package/server/lib/e2e/test-generator.test.js +121 -0
- package/server/lib/e2e/verify-runner.js +191 -0
- package/server/lib/e2e/verify-runner.test.js +167 -0
- package/server/lib/hooks/block-tools-hook.test.js +54 -0
- package/server/lib/orchestration/cli-dispatch.js +16 -1
- package/server/lib/orchestration/cli-dispatch.test.js +94 -8
- package/server/lib/orchestration/completion-checker.js +101 -0
- package/server/lib/orchestration/completion-checker.test.js +177 -0
- package/server/lib/orchestration/result-verifier.js +143 -0
- package/server/lib/orchestration/result-verifier.test.js +291 -0
- package/server/lib/orchestration/session-dispatcher.js +99 -0
- package/server/lib/orchestration/session-dispatcher.test.js +215 -0
- package/server/lib/orchestration/session-status.js +147 -0
- package/server/lib/orchestration/session-status.test.js +130 -0
- package/server/lib/release/agent-runner-updates.js +24 -0
- package/server/lib/release/agent-runner-updates.test.js +22 -0
- package/server/lib/release/changelog-generator.js +142 -0
- package/server/lib/release/changelog-generator.test.js +113 -0
- package/server/lib/release/ci-watcher.js +83 -0
- package/server/lib/release/ci-watcher.test.js +81 -0
- package/server/lib/release/health-checker.js +111 -0
- package/server/lib/release/health-checker.test.js +121 -0
- package/server/lib/release/release-pipeline.js +187 -0
- package/server/lib/release/release-pipeline.test.js +262 -0
- package/server/lib/release/version-bumper.js +183 -0
- package/server/lib/release/version-bumper.test.js +142 -0
- package/server/lib/routing-preamble.integration.test.js +12 -0
- package/server/lib/routing-preamble.js +13 -2
- package/server/lib/routing-preamble.test.js +49 -0
- package/server/lib/scaffolding/ci-detector.js +139 -0
- package/server/lib/scaffolding/ci-detector.test.js +198 -0
- package/server/lib/scaffolding/ci-scaffolder.js +347 -0
- package/server/lib/scaffolding/ci-scaffolder.test.js +157 -0
- package/server/lib/scaffolding/deploy-detector.js +135 -0
- package/server/lib/scaffolding/deploy-detector.test.js +106 -0
- package/server/lib/scaffolding/health-scaffold.js +374 -0
- package/server/lib/scaffolding/health-scaffold.test.js +99 -0
- package/server/lib/scaffolding/logger-scaffold.js +196 -0
- package/server/lib/scaffolding/logger-scaffold.test.js +146 -0
- package/server/lib/scaffolding/migration-detector.js +78 -0
- package/server/lib/scaffolding/migration-detector.test.js +127 -0
- package/server/lib/scaffolding/snapshot-manager.js +142 -0
- package/server/lib/scaffolding/snapshot-manager.test.js +225 -0
- package/server/lib/task-router-config.js +50 -20
- package/server/lib/task-router-config.test.js +29 -15
|
@@ -97,6 +97,39 @@ process.stdout.write(JSON.stringify(result));" 2>/dev/null
|
|
|
97
97
|
|
|
98
98
|
**Override:** Pass `--model <name>` to route this specific run to a different model.
|
|
99
99
|
|
|
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
|
+
|
|
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.
|
|
105
|
+
|
|
106
|
+
## ORCHESTRATOR MODE
|
|
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:
|
|
111
|
+
|
|
112
|
+
1. Treat Claude as the orchestrator for a small, test-first routed task rather than executing the work inline.
|
|
113
|
+
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.
|
|
114
|
+
3. Dispatch through the provider CLI path, using `codex exec` for Codex-style providers or `gemini -p` for Gemini-style providers, preferably via the shared dispatch layer when available.
|
|
115
|
+
4. Verify the routed result before accepting it:
|
|
116
|
+
- Confirm a failing test or equivalent pre-change verification was part of the work when appropriate.
|
|
117
|
+
- Confirm the implementation actually addresses the user's quick task and stays scoped.
|
|
118
|
+
- Confirm post-change verification was run or the provider clearly explained why not.
|
|
119
|
+
5. If the routed work is partial, off-scope, or skips verification, dispatch a narrow corrective follow-up instead of treating it as complete.
|
|
120
|
+
6. Handle failures explicitly:
|
|
121
|
+
- If dispatch fails because of model mismatch, auth, or missing CLI, check `.tlc/.router-state.json` for the provider's actual available model and retry once with the corrected model.
|
|
122
|
+
- If retry still fails, stop and report the exact failure to the user. Do not silently fall back to Claude inline execution.
|
|
123
|
+
- If the provider returns incomplete code or missing tests, issue a targeted retry for the missing part.
|
|
124
|
+
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
|
+
|
|
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.
|
|
131
|
+
|
|
132
|
+
|
|
100
133
|
## Engineering Standards
|
|
101
134
|
|
|
102
135
|
Even quick tasks follow senior engineer standards:
|
|
@@ -1,135 +1,85 @@
|
|
|
1
|
-
# /tlc:release - Release
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
## Usage
|
|
6
|
-
|
|
7
|
-
```
|
|
8
|
-
/tlc:release
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
-
|
|
52
|
-
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
Task 2: Add validation [>@alice] → [ ]
|
|
88
|
-
|
|
89
|
-
✓ Committed: release: task 2 - Add validation (@alice)
|
|
90
|
-
✓ Pushed
|
|
91
|
-
|
|
92
|
-
Task 2 is now available for others.
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
## With Task Number
|
|
96
|
-
|
|
97
|
-
```
|
|
98
|
-
> /tlc:release 2
|
|
99
|
-
|
|
100
|
-
Task 2: Add validation [>@alice] → [ ]
|
|
101
|
-
|
|
102
|
-
✓ Committed: release: task 2 - Add validation (@alice)
|
|
103
|
-
✓ Pushed
|
|
104
|
-
|
|
105
|
-
Task 2 is now available for others.
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
## Error Handling
|
|
109
|
-
|
|
110
|
-
**Not your task:**
|
|
111
|
-
```
|
|
112
|
-
Task 2 is claimed by @bob, not you.
|
|
113
|
-
You can only release your own tasks.
|
|
114
|
-
|
|
115
|
-
Your tasks: 5
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
**Task not claimed:**
|
|
119
|
-
```
|
|
120
|
-
Task 2 is not claimed (already available).
|
|
121
|
-
Nothing to release.
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
**No tasks claimed:**
|
|
125
|
-
```
|
|
126
|
-
You have no claimed tasks in Phase 1.
|
|
127
|
-
Use /tlc:claim to claim a task.
|
|
128
|
-
```
|
|
129
|
-
|
|
130
|
-
## Notes
|
|
131
|
-
|
|
132
|
-
- Releasing doesn't undo any work you've done
|
|
133
|
-
- Your commits remain in history
|
|
134
|
-
- Another teammate can claim and continue where you left off
|
|
135
|
-
- Consider adding a note to the task if you made partial progress
|
|
1
|
+
# /tlc:release - Run the Release Pipeline
|
|
2
|
+
|
|
3
|
+
Run the full TLC release pipeline for the current project.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
/tlc:release
|
|
9
|
+
/tlc:release --detached
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## What This Does
|
|
13
|
+
|
|
14
|
+
1. Watches CI for the release commit or branch state
|
|
15
|
+
2. Bumps the version
|
|
16
|
+
3. Updates the changelog
|
|
17
|
+
4. Publishes the release
|
|
18
|
+
5. Runs a mandatory post-release health check
|
|
19
|
+
|
|
20
|
+
This is the "prepare, publish, and verify the release" command.
|
|
21
|
+
|
|
22
|
+
## Process
|
|
23
|
+
|
|
24
|
+
### Step 1: Watch CI
|
|
25
|
+
|
|
26
|
+
- Confirm the branch is in a releasable state
|
|
27
|
+
- Watch the relevant CI run and stop on failure
|
|
28
|
+
- Do not continue to versioning or publish while CI is red
|
|
29
|
+
|
|
30
|
+
### Step 2: Bump Version
|
|
31
|
+
|
|
32
|
+
- Determine the next version according to the project's release rules
|
|
33
|
+
- Update the version in the canonical project files
|
|
34
|
+
- Keep the version bump in the release commit
|
|
35
|
+
|
|
36
|
+
### Step 3: Update Changelog
|
|
37
|
+
|
|
38
|
+
- Generate or update the changelog entry for the new version
|
|
39
|
+
- Summarize the user-facing changes included in the release
|
|
40
|
+
- Ensure the changelog and version stay in sync
|
|
41
|
+
|
|
42
|
+
### Step 4: Publish
|
|
43
|
+
|
|
44
|
+
- Publish the package, artifact, or release target configured for the project
|
|
45
|
+
- Surface any publish failure immediately
|
|
46
|
+
- Do not mark the release complete until publish succeeds
|
|
47
|
+
|
|
48
|
+
### Step 5: Run Health Check
|
|
49
|
+
|
|
50
|
+
- Read `deploy.healthUrl` from project configuration
|
|
51
|
+
- Block the release if `deploy.healthUrl` is missing
|
|
52
|
+
- Perform the health check after publish and fail the release if the deployed system is unhealthy
|
|
53
|
+
|
|
54
|
+
The health check is mandatory. If there is no `deploy.healthUrl`, stop and report that release verification cannot proceed.
|
|
55
|
+
|
|
56
|
+
## Detached Mode
|
|
57
|
+
|
|
58
|
+
`/tlc:release --detached` dispatches the release pipeline to the local orchestrator instead of running inline.
|
|
59
|
+
|
|
60
|
+
- Dispatch via `POST` to the orchestrator at `http://localhost:3100`
|
|
61
|
+
- The orchestrator owns the long-running release session
|
|
62
|
+
- Return the dispatched session details to the user so they can monitor progress separately
|
|
63
|
+
|
|
64
|
+
Detached mode still requires the same release stages:
|
|
65
|
+
|
|
66
|
+
1. CI watch
|
|
67
|
+
2. Version bump
|
|
68
|
+
3. Changelog update
|
|
69
|
+
4. Publish
|
|
70
|
+
5. Mandatory health check
|
|
71
|
+
|
|
72
|
+
Detached mode does not relax the health-check requirement. If `deploy.healthUrl` is not configured, the orchestrated release must block rather than skipping verification.
|
|
73
|
+
|
|
74
|
+
## Guard Rails
|
|
75
|
+
|
|
76
|
+
- Do not publish while CI is failing or still running
|
|
77
|
+
- Do not skip the changelog for a versioned release
|
|
78
|
+
- Do not treat publish success as release success until the health check passes
|
|
79
|
+
- Do not continue when `deploy.healthUrl` is missing; the release blocks until health-check configuration exists
|
|
80
|
+
|
|
81
|
+
## When to Use
|
|
82
|
+
|
|
83
|
+
- Shipping a new version after CI is green
|
|
84
|
+
- Running the standard TLC release flow end-to-end
|
|
85
|
+
- Handing a long-running release to the orchestrator with `--detached`
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# /tlc:restore - Restore DB Snapshot
|
|
2
|
+
|
|
3
|
+
## What This Does
|
|
4
|
+
|
|
5
|
+
Lists available snapshots and restores the selected one.
|
|
6
|
+
|
|
7
|
+
## Process
|
|
8
|
+
|
|
9
|
+
1. List snapshots from `.tlc/snapshots/` sorted newest first
|
|
10
|
+
2. Show table: date, git ref, DB name, size
|
|
11
|
+
3. Ask user to pick one
|
|
12
|
+
4. Confirm: `Restore {snapshot}? This will overwrite the current database. (Y/n)`
|
|
13
|
+
5. Run restore command based on DB type
|
|
14
|
+
6. Report success or failure
|
|
@@ -101,6 +101,39 @@ process.stdout.write(JSON.stringify(result));" 2>/dev/null
|
|
|
101
101
|
|
|
102
102
|
**Override:** Pass `--model <name>` to route this specific run to a different model.
|
|
103
103
|
|
|
104
|
+
After `resolveRouting` returns, immediately write `.tlc/.review-routing-active` with the active provider name from `models[0]` before doing any other review work. Remove `.tlc/.review-routing-active` on completion, cancellation, or failure cleanup.
|
|
105
|
+
|
|
106
|
+
**Routing decision:**
|
|
107
|
+
- If routing says external provider (`models[0] !== 'claude'`), follow **ONLY ORCHESTRATOR MODE** below.
|
|
108
|
+
- If routing says Claude (`models[0] === 'claude'`), follow **INLINE MODE** below.
|
|
109
|
+
|
|
110
|
+
## ORCHESTRATOR MODE
|
|
111
|
+
|
|
112
|
+
Use this mode only when `models[0]` is **NOT** `claude`.
|
|
113
|
+
|
|
114
|
+
Claude does not execute the review instructions inline in this path. Claude acts as the orchestrator for the routed provider run:
|
|
115
|
+
|
|
116
|
+
1. Read the full review context, including project standards, changed files, base branch, router state, and any configured review providers.
|
|
117
|
+
2. Package the exact review task for the routed provider and dispatch it through the provider CLI path, using `codex exec` for Codex-style providers or `gemini -p` for Gemini-style providers, preferably via the shared dispatch layer when available.
|
|
118
|
+
3. Require the provider run to produce concrete review findings, approval state, coverage gaps, TDD observations, and security concerns aligned to the command intent.
|
|
119
|
+
4. Verify the returned review before accepting it:
|
|
120
|
+
- Confirm the review actually inspected the current diff against the intended base.
|
|
121
|
+
- Confirm the findings are specific, actionable, and tied to the changed code rather than generic advice.
|
|
122
|
+
- Reject empty, shallow, or unverifiable review output and dispatch a focused retry.
|
|
123
|
+
5. If the command is expected to fix issues in a review loop, orchestrate the fix dispatches as separate routed tasks, then re-run the external review until the result is clean or an explicit blocker remains.
|
|
124
|
+
6. Handle failures explicitly:
|
|
125
|
+
- If dispatch fails because of model mismatch, auth, or missing CLI, check `.tlc/.router-state.json` for the provider's actual available model and retry once with the corrected model.
|
|
126
|
+
- If retry still fails, stop and report the exact failure to the user. Do not silently fall back to Claude inline execution.
|
|
127
|
+
- If the provider returns malformed or partial review output, issue a narrowed follow-up dispatch instead of continuing as if review succeeded.
|
|
128
|
+
7. When finished, display the routed provider review result, persist any captured memory, remove `.tlc/.review-routing-active`, and stop. Do **not** execute Inline Mode afterward.
|
|
129
|
+
|
|
130
|
+
## INLINE MODE
|
|
131
|
+
|
|
132
|
+
Use this mode only when `models[0]` **IS** `claude`.
|
|
133
|
+
|
|
134
|
+
The existing review instructions below are the Inline Mode instructions and should be followed unchanged.
|
|
135
|
+
|
|
136
|
+
|
|
104
137
|
## What This Does
|
|
105
138
|
|
|
106
139
|
1. Compares current branch to main/master
|
|
@@ -240,7 +273,49 @@ Scan diff for common security issues:
|
|
|
240
273
|
|
|
241
274
|
**Fail if:** Any HIGH severity issues found.
|
|
242
275
|
|
|
243
|
-
### Step 5b:
|
|
276
|
+
### Step 5b: Run E2E Tests
|
|
277
|
+
|
|
278
|
+
Detect whether the project uses Playwright or a Supertest-based E2E setup, then execute the matching command:
|
|
279
|
+
|
|
280
|
+
```bash
|
|
281
|
+
# Framework detection
|
|
282
|
+
if [ -f playwright.config.ts ] || [ -f playwright.config.js ] || [ -d tests/e2e ] || [ -d e2e ]; then
|
|
283
|
+
mkdir -p .tlc/screenshots
|
|
284
|
+
npx playwright test
|
|
285
|
+
elif rg -l "supertest" package.json test tests src >/dev/null 2>&1; then
|
|
286
|
+
mkdir -p .tlc/screenshots
|
|
287
|
+
npx supertest
|
|
288
|
+
else
|
|
289
|
+
echo "WARN: No E2E tests detected"
|
|
290
|
+
fi
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
**Execution rules:**
|
|
294
|
+
- Use `npx playwright test` when Playwright is detected.
|
|
295
|
+
- Use `npx supertest` when a Supertest-based E2E framework is detected.
|
|
296
|
+
- If E2E tests fail, include the failure in the report as **CHANGES_REQUESTED**.
|
|
297
|
+
- If no E2E tests exist, add a warning to the report.
|
|
298
|
+
- On failure, save screenshots to `.tlc/screenshots/`.
|
|
299
|
+
|
|
300
|
+
**Report example:**
|
|
301
|
+
```text
|
|
302
|
+
E2E Tests:
|
|
303
|
+
✅ Playwright suite passed
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
```text
|
|
307
|
+
E2E Tests:
|
|
308
|
+
❌ Playwright suite failed
|
|
309
|
+
Screenshots: .tlc/screenshots/
|
|
310
|
+
Verdict impact: CHANGES_REQUESTED
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
```text
|
|
314
|
+
E2E Tests:
|
|
315
|
+
⚠️ No E2E tests detected
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
### Step 5c: Coding Standards Check
|
|
244
319
|
|
|
245
320
|
Scan all changed/added files for coding standards violations:
|
|
246
321
|
|
|
@@ -2,6 +2,140 @@
|
|
|
2
2
|
|
|
3
3
|
Detect the current TLC state in one pass, print a minimal status, and run the next safe action automatically.
|
|
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 "const fs = require('fs');
|
|
14
|
+
const path = require('path');
|
|
15
|
+
const os = require('os');
|
|
16
|
+
function readJson(filePath, fileSystem) {
|
|
17
|
+
try {
|
|
18
|
+
return JSON.parse(fileSystem.readFileSync(filePath, 'utf8'));
|
|
19
|
+
} catch {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
function loadPersonalConfig(options) {
|
|
24
|
+
const configPath = path.join(options.homeDir, '.tlc', 'config.json');
|
|
25
|
+
return readJson(configPath, options.fs);
|
|
26
|
+
}
|
|
27
|
+
function loadProjectOverride(options) {
|
|
28
|
+
const configPath = path.join(options.projectDir, '.tlc.json');
|
|
29
|
+
const data = readJson(configPath, options.fs);
|
|
30
|
+
return data && data.task_routing_override ? data.task_routing_override : null;
|
|
31
|
+
}
|
|
32
|
+
function resolveRouting(options) {
|
|
33
|
+
let models = ['claude'];
|
|
34
|
+
let strategy = 'single';
|
|
35
|
+
let source = 'shipped-defaults';
|
|
36
|
+
let providers;
|
|
37
|
+
const personal = loadPersonalConfig({ homeDir: options.homeDir, fs: options.fs });
|
|
38
|
+
if (personal) {
|
|
39
|
+
if (personal.model_providers) {
|
|
40
|
+
providers = personal.model_providers;
|
|
41
|
+
}
|
|
42
|
+
const personalRouting = personal.task_routing && personal.task_routing[options.command];
|
|
43
|
+
if (personalRouting) {
|
|
44
|
+
if (Array.isArray(personalRouting.models)) {
|
|
45
|
+
models = personalRouting.models.slice();
|
|
46
|
+
} else if (typeof personalRouting.model === 'string') {
|
|
47
|
+
models = [personalRouting.model];
|
|
48
|
+
}
|
|
49
|
+
if (personalRouting.strategy) {
|
|
50
|
+
strategy = personalRouting.strategy;
|
|
51
|
+
}
|
|
52
|
+
source = 'personal-config';
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
const projectOverride = loadProjectOverride({ projectDir: options.projectDir, fs: options.fs });
|
|
56
|
+
if (projectOverride) {
|
|
57
|
+
const overrideEntry = projectOverride[options.command];
|
|
58
|
+
if (overrideEntry) {
|
|
59
|
+
if (Array.isArray(overrideEntry.models)) {
|
|
60
|
+
models = overrideEntry.models.slice();
|
|
61
|
+
} else if (typeof overrideEntry.model === 'string') {
|
|
62
|
+
models = [overrideEntry.model];
|
|
63
|
+
}
|
|
64
|
+
if (overrideEntry.strategy) {
|
|
65
|
+
strategy = overrideEntry.strategy;
|
|
66
|
+
}
|
|
67
|
+
source = 'project-override';
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
if (options.flagModel) {
|
|
71
|
+
models = [options.flagModel];
|
|
72
|
+
strategy = 'single';
|
|
73
|
+
source = 'flag-override';
|
|
74
|
+
}
|
|
75
|
+
const result = { models, strategy, source };
|
|
76
|
+
if (providers) {
|
|
77
|
+
result.providers = providers;
|
|
78
|
+
}
|
|
79
|
+
return result;
|
|
80
|
+
}
|
|
81
|
+
const result = resolveRouting({ command: "tlc", flagModel: process.argv[1], projectDir: process.cwd(), homeDir: process.env.HOME || os.homedir(), fs });
|
|
82
|
+
process.stdout.write(JSON.stringify(result));" 2>/dev/null
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
2. If `models[0]` is NOT `claude` (i.e., routed to external model):
|
|
86
|
+
- Resolve orchestration modules with fallback: try `tlc-claude-code/server/lib/...` first, then `$PROJECT_DIR/server/lib/...`
|
|
87
|
+
- Build the full prompt with `buildFullPrompt` from `orchestration/prompt-builder`
|
|
88
|
+
- Dispatch to the target provider CLI through unified routing, using `codex exec` or `gemini -p` as appropriate
|
|
89
|
+
- Capture provider output for memory with `captureFromProvider` from `capture`, display the CLI output, and stop — do NOT execute the agent prompt below
|
|
90
|
+
|
|
91
|
+
3. If `models[0]` IS `claude` (or no routing config exists):
|
|
92
|
+
- Execute the agent prompt below as normal (current behavior)
|
|
93
|
+
|
|
94
|
+
4. If `strategy` is `parallel`:
|
|
95
|
+
- Resolve orchestration modules with fallback: try `tlc-claude-code/server/lib/...` first, then `$PROJECT_DIR/server/lib/...`
|
|
96
|
+
- Execute inline (Claude) AND dispatch each external provider through unified routing
|
|
97
|
+
- After each provider completes, capture its output with `captureFromProvider` from `capture`
|
|
98
|
+
- Collect and merge results
|
|
99
|
+
- **CRITICAL: If a provider fails (wrong model, auth error, CLI missing), do NOT silently fall back to single-provider.** Instead:
|
|
100
|
+
1. Check `.tlc/.router-state.json` for the provider's actual available model and retry
|
|
101
|
+
2. If retry fails, ask the user: "[Provider] failed: [reason]. Run with [other provider] only, or fix and retry?"
|
|
102
|
+
3. Never say "proceeding with X-only" without user consent
|
|
103
|
+
|
|
104
|
+
**Override:** Pass `--model <name>` to route this specific run to a different model.
|
|
105
|
+
|
|
106
|
+
After `resolveRouting` returns, immediately write `.tlc/.tlc-routing-active` with the active provider name from `models[0]` before doing any other tlc work. Remove `.tlc/.tlc-routing-active` on completion, cancellation, or failure cleanup.
|
|
107
|
+
|
|
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.
|
|
111
|
+
|
|
112
|
+
## ORCHESTRATOR MODE
|
|
113
|
+
|
|
114
|
+
Use this mode only when `models[0]` is **NOT** `claude`.
|
|
115
|
+
|
|
116
|
+
Claude does not execute the auto-runner instructions inline in this path. Claude acts as the orchestrator for the routed provider run:
|
|
117
|
+
|
|
118
|
+
1. Claude acts as the orchestrator for the routed `/tlc` auto-runner flow instead of executing the detection logic inline.
|
|
119
|
+
2. Read the roadmap, phase artifacts, version context, and any routing or state files needed to determine the next safe action before dispatching.
|
|
120
|
+
3. Package a prompt that asks the routed provider to perform the one-pass TLC state detection, choose the next non-destructive command, and produce the compact status output required by this command.
|
|
121
|
+
4. Dispatch through the provider CLI path, using `codex exec` for Codex-style providers or `gemini -p` for Gemini-style providers, preferably via the shared dispatch layer when available.
|
|
122
|
+
5. Verify the routed result before accepting it:
|
|
123
|
+
- Confirm it chose the active phase and next action from the actual repository state.
|
|
124
|
+
- Confirm it preserved the command's safety rules and did not auto-run destructive actions.
|
|
125
|
+
- Reject verbose, menu-driven, or repo-disconnected output that does not match `/tlc` behavior.
|
|
126
|
+
6. If the routed result mis-detects state or picks the wrong next action, dispatch a corrective follow-up using the exact missing or conflicting evidence.
|
|
127
|
+
7. Handle failures explicitly:
|
|
128
|
+
- If dispatch fails because of model mismatch, auth, or missing CLI, check `.tlc/.router-state.json` for the provider's actual available model and retry once with the corrected model.
|
|
129
|
+
- If retry still fails, stop and report the exact failure to the user. Do not silently fall back to Claude inline execution.
|
|
130
|
+
- If the provider returns incomplete status or action selection, reject it and request a constrained retry.
|
|
131
|
+
8. When finished, display the routed `/tlc` result, persist any captured memory, remove `.tlc/.tlc-routing-active`, and stop. Do **not** execute Inline Mode afterward.
|
|
132
|
+
|
|
133
|
+
## INLINE MODE
|
|
134
|
+
|
|
135
|
+
Use this mode only when `models[0]` **IS** `claude`.
|
|
136
|
+
|
|
137
|
+
The existing auto-runner instructions below are the Inline Mode instructions and should be followed unchanged.
|
|
138
|
+
|
|
5
139
|
## What This Does
|
|
6
140
|
|
|
7
141
|
`/tlc` is the default entry point. It should:
|