tlc-claude-code 2.0.1 → 2.2.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.
- package/.claude/agents/builder.md +144 -0
- package/.claude/agents/planner.md +143 -0
- package/.claude/agents/reviewer.md +160 -0
- package/.claude/commands/tlc/build.md +4 -0
- package/.claude/commands/tlc/deploy.md +194 -2
- package/.claude/commands/tlc/e2e-verify.md +214 -0
- package/.claude/commands/tlc/guard.md +191 -0
- package/.claude/commands/tlc/help.md +32 -0
- package/.claude/commands/tlc/init.md +73 -37
- package/.claude/commands/tlc/llm.md +19 -4
- package/.claude/commands/tlc/preflight.md +134 -0
- package/.claude/commands/tlc/review-plan.md +363 -0
- package/.claude/commands/tlc/review.md +172 -57
- package/.claude/commands/tlc/watchci.md +159 -0
- package/.claude/hooks/tlc-block-tools.sh +41 -0
- package/.claude/hooks/tlc-capture-exchange.sh +50 -0
- package/.claude/hooks/tlc-post-build.sh +38 -0
- package/.claude/hooks/tlc-post-push.sh +22 -0
- package/.claude/hooks/tlc-prompt-guard.sh +69 -0
- package/.claude/hooks/tlc-session-init.sh +123 -0
- package/CLAUDE.md +13 -0
- package/bin/install.js +268 -2
- package/bin/postinstall.js +102 -24
- package/bin/setup-autoupdate.js +206 -0
- package/bin/setup-autoupdate.test.js +124 -0
- package/bin/tlc.js +0 -0
- package/dashboard-web/dist/assets/index-CdS5CHqu.css +1 -0
- package/dashboard-web/dist/assets/index-CwNPPVpg.js +483 -0
- package/dashboard-web/dist/assets/index-CwNPPVpg.js.map +1 -0
- package/dashboard-web/dist/index.html +2 -2
- package/docker-compose.dev.yml +18 -12
- package/package.json +4 -2
- package/scripts/project-docs.js +1 -1
- package/server/index.js +228 -2
- package/server/lib/capture-bridge.js +242 -0
- package/server/lib/capture-bridge.test.js +363 -0
- package/server/lib/capture-guard.js +140 -0
- package/server/lib/capture-guard.test.js +182 -0
- package/server/lib/command-runner.js +159 -0
- package/server/lib/command-runner.test.js +92 -0
- package/server/lib/cost-tracker.test.js +49 -12
- package/server/lib/deploy/runners/dependency-runner.js +106 -0
- package/server/lib/deploy/runners/dependency-runner.test.js +148 -0
- package/server/lib/deploy/runners/secrets-runner.js +174 -0
- package/server/lib/deploy/runners/secrets-runner.test.js +127 -0
- package/server/lib/deploy/security-gates.js +11 -24
- package/server/lib/deploy/security-gates.test.js +9 -2
- package/server/lib/deploy-engine.js +182 -0
- package/server/lib/deploy-engine.test.js +147 -0
- package/server/lib/docker-api.js +137 -0
- package/server/lib/docker-api.test.js +202 -0
- package/server/lib/docker-client.js +297 -0
- package/server/lib/docker-client.test.js +308 -0
- package/server/lib/input-sanitizer.js +86 -0
- package/server/lib/input-sanitizer.test.js +117 -0
- package/server/lib/launchd-agent.js +225 -0
- package/server/lib/launchd-agent.test.js +185 -0
- package/server/lib/memory-api.js +3 -1
- package/server/lib/memory-api.test.js +3 -5
- package/server/lib/memory-bridge-e2e.test.js +160 -0
- package/server/lib/memory-committer.js +18 -4
- package/server/lib/memory-committer.test.js +21 -0
- package/server/lib/memory-hooks-capture.test.js +69 -4
- package/server/lib/memory-hooks-integration.test.js +98 -0
- package/server/lib/memory-hooks.js +42 -4
- package/server/lib/memory-store-adapter.js +105 -0
- package/server/lib/memory-store-adapter.test.js +141 -0
- package/server/lib/memory-wiring-e2e.test.js +93 -0
- package/server/lib/nginx-config.js +114 -0
- package/server/lib/nginx-config.test.js +82 -0
- package/server/lib/ollama-health.js +91 -0
- package/server/lib/ollama-health.test.js +74 -0
- package/server/lib/orchestration/agent-dispatcher.js +114 -0
- package/server/lib/orchestration/agent-dispatcher.test.js +110 -0
- package/server/lib/orchestration/orchestrator.js +130 -0
- package/server/lib/orchestration/orchestrator.test.js +192 -0
- package/server/lib/orchestration/tmux-manager.js +101 -0
- package/server/lib/orchestration/tmux-manager.test.js +109 -0
- package/server/lib/orchestration/worktree-manager.js +132 -0
- package/server/lib/orchestration/worktree-manager.test.js +129 -0
- package/server/lib/port-guard.js +44 -0
- package/server/lib/port-guard.test.js +65 -0
- package/server/lib/project-scanner.js +37 -2
- package/server/lib/project-scanner.test.js +152 -0
- package/server/lib/remember-command.js +2 -0
- package/server/lib/remember-command.test.js +23 -0
- package/server/lib/review/plan-reviewer.js +260 -0
- package/server/lib/review/plan-reviewer.test.js +269 -0
- package/server/lib/review/review-schemas.js +173 -0
- package/server/lib/review/review-schemas.test.js +152 -0
- package/server/lib/security/crypto-utils.test.js +2 -2
- package/server/lib/semantic-recall.js +1 -1
- package/server/lib/semantic-recall.test.js +17 -0
- package/server/lib/ssh-client.js +184 -0
- package/server/lib/ssh-client.test.js +127 -0
- package/server/lib/vps-api.js +184 -0
- package/server/lib/vps-api.test.js +208 -0
- package/server/lib/vps-bootstrap.js +124 -0
- package/server/lib/vps-bootstrap.test.js +79 -0
- package/server/lib/vps-monitor.js +126 -0
- package/server/lib/vps-monitor.test.js +98 -0
- package/server/lib/workspace-api.js +182 -1
- package/server/lib/workspace-api.test.js +474 -0
- package/server/package-lock.json +737 -0
- package/server/package.json +3 -0
- package/server/setup.sh +271 -271
- package/dashboard-web/dist/assets/index-Uhc49PE-.css +0 -1
- package/dashboard-web/dist/assets/index-W36XHPC5.js +0 -431
- package/dashboard-web/dist/assets/index-W36XHPC5.js.map +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# /tlc:review - Review Current Branch
|
|
2
2
|
|
|
3
|
-
Review changes on current branch before pushing.
|
|
3
|
+
Review changes on current branch before pushing. **Runs in a loop until clean.**
|
|
4
4
|
|
|
5
5
|
## What This Does
|
|
6
6
|
|
|
@@ -9,7 +9,10 @@ Review changes on current branch before pushing.
|
|
|
9
9
|
3. Checks test coverage for all changed files
|
|
10
10
|
4. Analyzes commit order for TDD compliance
|
|
11
11
|
5. Scans for security issues
|
|
12
|
-
6.
|
|
12
|
+
6. If issues found → **fix them automatically, then re-review**
|
|
13
|
+
7. **Repeats until both Claude and Codex approve** — no arbitrary limit, runs until clean
|
|
14
|
+
|
|
15
|
+
**This is an iterative review loop, not a single pass.** Think of it as RL-mode: keep fixing and re-checking until the code is foolproof.
|
|
13
16
|
|
|
14
17
|
**This runs automatically at the end of `/tlc:build`.**
|
|
15
18
|
|
|
@@ -41,19 +44,32 @@ TLC automatically uses ALL providers configured for the `review` capability in `
|
|
|
41
44
|
|
|
42
45
|
## Process
|
|
43
46
|
|
|
44
|
-
### Step 1: Load Router
|
|
47
|
+
### Step 1: Load Router State (Persistent)
|
|
45
48
|
|
|
46
|
-
|
|
49
|
+
**Always read from the router state file first**, then fall back to config:
|
|
47
50
|
|
|
48
51
|
```javascript
|
|
52
|
+
// 1. Read persistent router state (written by session-init hook)
|
|
53
|
+
const routerState = JSON.parse(fs.readFileSync('.tlc/.router-state.json', 'utf-8'));
|
|
54
|
+
|
|
55
|
+
// 2. Read config for capability mappings
|
|
49
56
|
const config = JSON.parse(fs.readFileSync('.tlc.json', 'utf-8'));
|
|
50
57
|
const reviewProviders = config.router?.capabilities?.review?.providers || ['claude'];
|
|
51
58
|
const providers = config.router?.providers || {};
|
|
59
|
+
|
|
60
|
+
// 3. Filter to only AVAILABLE providers (from state file)
|
|
61
|
+
const availableReviewers = reviewProviders.filter(p =>
|
|
62
|
+
routerState.providers[p]?.available === true
|
|
63
|
+
);
|
|
52
64
|
```
|
|
53
65
|
|
|
54
|
-
**
|
|
66
|
+
**The state file (`.tlc/.router-state.json`) is authoritative for availability.** It's written by the `SessionStart` hook, re-probed every hour, and persists across skill invocations. Never run `which codex` yourself — read the state file.
|
|
67
|
+
|
|
68
|
+
If the state file is missing or stale (>1 hour), probe manually and write a fresh one.
|
|
55
69
|
|
|
56
|
-
|
|
70
|
+
**Default providers for review:** `['claude', 'codex']` — but only invoked if the state file confirms they're available.
|
|
71
|
+
|
|
72
|
+
If Codex is configured AND available in state, it WILL be invoked automatically.
|
|
57
73
|
|
|
58
74
|
### Step 2: Identify Changes
|
|
59
75
|
|
|
@@ -179,52 +195,38 @@ For each provider in `reviewProviders` (except `claude` which is the current ses
|
|
|
179
195
|
|
|
180
196
|
**How to invoke:**
|
|
181
197
|
|
|
182
|
-
|
|
198
|
+
**Codex** — use its built-in `review` subcommand. It reads the git diff natively, no need to pipe files:
|
|
199
|
+
|
|
183
200
|
```bash
|
|
184
|
-
#
|
|
185
|
-
|
|
186
|
-
line_count=$(wc -l < /tmp/review-diff-full.patch)
|
|
201
|
+
# Review current branch against main (default)
|
|
202
|
+
codex review --base main "Focus on: bugs, security issues, missing edge cases, test coverage gaps. End with APPROVED or CHANGES_REQUESTED."
|
|
187
203
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
# Split by file for targeted review
|
|
192
|
-
git diff --name-only main...HEAD | while read file; do
|
|
193
|
-
git diff main...HEAD -- "$file" > "/tmp/review-chunk-${file//\//_}.patch"
|
|
194
|
-
done
|
|
195
|
-
|
|
196
|
-
# Or truncate with warning
|
|
197
|
-
head -500 /tmp/review-diff-full.patch > /tmp/review-diff.patch
|
|
198
|
-
echo "... truncated (showing first 500 of $line_count lines)" >> /tmp/review-diff.patch
|
|
199
|
-
else
|
|
200
|
-
cp /tmp/review-diff-full.patch /tmp/review-diff.patch
|
|
201
|
-
fi
|
|
202
|
-
```
|
|
204
|
+
# Review uncommitted changes only
|
|
205
|
+
codex review --uncommitted
|
|
203
206
|
|
|
204
|
-
|
|
207
|
+
# Review a specific commit
|
|
208
|
+
codex review --commit <sha>
|
|
205
209
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
210
|
+
# Custom instructions via prompt
|
|
211
|
+
codex review --base main "Check for TDD compliance: were tests written before implementation? Flag any implementation without corresponding test files."
|
|
212
|
+
```
|
|
209
213
|
|
|
210
|
-
|
|
211
|
-
2. **Bugs**: Identify potential bugs, edge cases, null checks
|
|
212
|
-
3. **Security**: SQL injection, XSS, command injection, auth issues
|
|
213
|
-
4. **Performance**: N+1 queries, unnecessary loops, memory leaks
|
|
214
|
-
5. **Code Quality**: Naming, duplication, complexity, SOLID principles
|
|
215
|
-
6. **Test Coverage**: Are the changes properly tested?
|
|
214
|
+
`codex review` outputs a structured review to stdout. No `--print` flag needed — it's already non-interactive.
|
|
216
215
|
|
|
217
|
-
|
|
218
|
-
- File and line number
|
|
219
|
-
- Severity (critical/high/medium/low)
|
|
220
|
-
- What's wrong
|
|
221
|
-
- How to fix it
|
|
216
|
+
**Gemini** — no built-in review command, so save diff and invoke:
|
|
222
217
|
|
|
223
|
-
|
|
218
|
+
```bash
|
|
219
|
+
# Save diff for Gemini
|
|
220
|
+
git diff main...HEAD > /tmp/review-diff.patch
|
|
221
|
+
line_count=$(wc -l < /tmp/review-diff.patch)
|
|
224
222
|
|
|
225
|
-
|
|
223
|
+
# Truncate if too large
|
|
224
|
+
if [ "$line_count" -gt 500 ]; then
|
|
225
|
+
head -500 /tmp/review-diff.patch > /tmp/review-diff-truncated.patch
|
|
226
|
+
echo "... truncated (showing first 500 of $line_count lines)" >> /tmp/review-diff-truncated.patch
|
|
227
|
+
mv /tmp/review-diff-truncated.patch /tmp/review-diff.patch
|
|
228
|
+
fi
|
|
226
229
|
|
|
227
|
-
# For Gemini - detailed review prompt
|
|
228
230
|
gemini --print "Review this code diff as a senior engineer. Provide:
|
|
229
231
|
- Specific line-by-line feedback
|
|
230
232
|
- Security vulnerabilities with file:line references
|
|
@@ -232,14 +234,10 @@ gemini --print "Review this code diff as a senior engineer. Provide:
|
|
|
232
234
|
- Code quality issues
|
|
233
235
|
- Missing test coverage
|
|
234
236
|
|
|
235
|
-
Be thorough and specific.
|
|
236
|
-
```
|
|
237
|
+
Be thorough and specific. End with APPROVED or CHANGES_REQUESTED.
|
|
237
238
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
- Each file's changes reviewed separately
|
|
241
|
-
- Results aggregated across all chunks
|
|
242
|
-
- Alternative: truncate with warning (shows first 500 lines)
|
|
239
|
+
$(cat /tmp/review-diff.patch)"
|
|
240
|
+
```
|
|
243
241
|
|
|
244
242
|
**Note:** Each CLI has its own syntax. Check `codex --help` and `gemini --help` for exact flags. The `--print` flag outputs the response without interactive mode.
|
|
245
243
|
|
|
@@ -264,7 +262,124 @@ Invoking Codex (GPT-5.2) for review...
|
|
|
264
262
|
- Any CHANGES_REQUESTED = overall CHANGES_REQUESTED
|
|
265
263
|
- Issues from all providers are combined in the report
|
|
266
264
|
|
|
267
|
-
### Step 7:
|
|
265
|
+
### Step 7: Fix-and-Recheck Loop (RL Mode)
|
|
266
|
+
|
|
267
|
+
**This is the core innovation. Reviews are not one-shot — they loop until clean.**
|
|
268
|
+
|
|
269
|
+
After Steps 2-6 complete, if ANY issues were found:
|
|
270
|
+
|
|
271
|
+
```
|
|
272
|
+
┌─────────────────────────────────────────────┐
|
|
273
|
+
│ REVIEW LOOP (runs until clean) │
|
|
274
|
+
│ │
|
|
275
|
+
│ 1. Collect all issues from Claude + Codex │
|
|
276
|
+
│ 2. Fix each issue: │
|
|
277
|
+
│ - Missing tests → write them │
|
|
278
|
+
│ - Security issues → patch the code │
|
|
279
|
+
│ - Coding standards → refactor │
|
|
280
|
+
│ - Codex feedback → apply fixes │
|
|
281
|
+
│ 3. Run tests to verify fixes don't break │
|
|
282
|
+
│ 4. Commit fixes │
|
|
283
|
+
│ 5. Re-run Steps 2-6 (full review again) │
|
|
284
|
+
│ 6. If new issues → loop back to 1 │
|
|
285
|
+
│ 7. If clean → exit loop, generate report │
|
|
286
|
+
└─────────────────────────────────────────────┘
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
**Iteration rules:**
|
|
290
|
+
|
|
291
|
+
1. **No arbitrary limit** — keep looping until BOTH providers return APPROVED. The code isn't done until it's clean.
|
|
292
|
+
2. **Each iteration runs the FULL check** — don't skip steps. Fresh eyes each time.
|
|
293
|
+
3. **Re-invoke Codex each iteration** — `codex review --base main` sees the latest fixes
|
|
294
|
+
4. **Commit after each fix round** — `git commit -m "fix: address review feedback (round N)"`
|
|
295
|
+
5. **Track what was fixed** — maintain a running list for the final report
|
|
296
|
+
6. **Stuck detection** — if the SAME issue appears 3 times after being "fixed", stop and escalate to the user with context on what was tried. This is the only exit condition besides clean.
|
|
297
|
+
|
|
298
|
+
**Fix priority order:**
|
|
299
|
+
1. Security issues (HIGH severity) — fix these first, they block everything
|
|
300
|
+
2. Missing tests — write them before touching implementation
|
|
301
|
+
3. Implementation bugs flagged by Codex — apply fixes
|
|
302
|
+
4. Coding standards (file size, `any` types, return types) — refactor
|
|
303
|
+
5. Style/naming/docs — lowest priority, fix if time permits
|
|
304
|
+
|
|
305
|
+
**What gets auto-fixed vs flagged for human:**
|
|
306
|
+
|
|
307
|
+
| Issue Type | Auto-Fix | Human Review |
|
|
308
|
+
|-----------|----------|--------------|
|
|
309
|
+
| Missing test file | Write it | - |
|
|
310
|
+
| Hardcoded secret | Replace with env var | If unclear what var to use |
|
|
311
|
+
| `any` type | Replace with proper interface | If domain type unclear |
|
|
312
|
+
| File >1000 lines | Split into sub-modules | If split strategy unclear |
|
|
313
|
+
| Security vulnerability | Patch it | If fix might break behavior |
|
|
314
|
+
| Codex-flagged bug | Apply suggestion | If suggestion conflicts with Claude |
|
|
315
|
+
| Merge conflict | - | Always human |
|
|
316
|
+
|
|
317
|
+
**Example iteration:**
|
|
318
|
+
|
|
319
|
+
```
|
|
320
|
+
───────────────────────────────────────
|
|
321
|
+
Review Round 1/5
|
|
322
|
+
───────────────────────────────────────
|
|
323
|
+
Claude: CHANGES_REQUESTED
|
|
324
|
+
- Missing test for src/utils.js
|
|
325
|
+
- Hardcoded API key in src/config.js
|
|
326
|
+
Codex: CHANGES_REQUESTED
|
|
327
|
+
- Missing null check in src/parser.js:42
|
|
328
|
+
- No error handling in src/api.js:88
|
|
329
|
+
|
|
330
|
+
Fixing 4 issues...
|
|
331
|
+
✅ Created src/utils.test.js (3 tests)
|
|
332
|
+
✅ Replaced hardcoded key with process.env.API_KEY
|
|
333
|
+
✅ Added null check in parser.js:42
|
|
334
|
+
✅ Added try/catch in api.js:88
|
|
335
|
+
✅ All tests pass
|
|
336
|
+
✅ Committed: fix: address review feedback (round 1)
|
|
337
|
+
|
|
338
|
+
───────────────────────────────────────
|
|
339
|
+
Review Round 2/5
|
|
340
|
+
───────────────────────────────────────
|
|
341
|
+
Claude: CHANGES_REQUESTED
|
|
342
|
+
- src/utils.test.js missing edge case for empty input
|
|
343
|
+
Codex: APPROVED
|
|
344
|
+
|
|
345
|
+
Fixing 1 issue...
|
|
346
|
+
✅ Added empty input edge case test
|
|
347
|
+
✅ All tests pass
|
|
348
|
+
✅ Committed: fix: address review feedback (round 2)
|
|
349
|
+
|
|
350
|
+
───────────────────────────────────────
|
|
351
|
+
Review Round 3/5
|
|
352
|
+
───────────────────────────────────────
|
|
353
|
+
Claude: APPROVED
|
|
354
|
+
Codex: APPROVED
|
|
355
|
+
|
|
356
|
+
✅ All providers agree — exiting loop.
|
|
357
|
+
───────────────────────────────────────
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
**Stuck detection (only exit besides clean):**
|
|
361
|
+
|
|
362
|
+
```
|
|
363
|
+
───────────────────────────────────────
|
|
364
|
+
Review Round 7
|
|
365
|
+
───────────────────────────────────────
|
|
366
|
+
Claude: APPROVED
|
|
367
|
+
Codex: CHANGES_REQUESTED
|
|
368
|
+
- Complex refactor needed in src/legacy.js ← appeared 3 times
|
|
369
|
+
|
|
370
|
+
⚠️ STUCK: This issue has reappeared 3 times after being fixed.
|
|
371
|
+
Escalating to human review.
|
|
372
|
+
|
|
373
|
+
Attempts made:
|
|
374
|
+
Round 3: Extracted helper function → Codex still flagged
|
|
375
|
+
Round 5: Split into two modules → Codex still flagged
|
|
376
|
+
Round 7: Added interface layer → Codex still flagged
|
|
377
|
+
|
|
378
|
+
This needs human judgment. Run /tlc:review again after manual fix.
|
|
379
|
+
───────────────────────────────────────
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
### Step 8: Generate Report
|
|
268
383
|
|
|
269
384
|
```markdown
|
|
270
385
|
# Code Review Report
|
|
@@ -292,14 +407,11 @@ Invoking Codex (GPT-5.2) for review...
|
|
|
292
407
|
- TDD Score: 75%
|
|
293
408
|
```
|
|
294
409
|
|
|
295
|
-
### Step
|
|
410
|
+
### Step 9: Return Verdict
|
|
296
411
|
|
|
297
|
-
**APPROVED** - All
|
|
412
|
+
**APPROVED** - All providers agree after N iterations. Ready to push/merge.
|
|
298
413
|
|
|
299
|
-
**CHANGES_REQUESTED** -
|
|
300
|
-
- Missing tests → Add tests for flagged files
|
|
301
|
-
- Low TDD score → Consider reordering commits or adding test commits
|
|
302
|
-
- Security issues → Fix flagged patterns
|
|
414
|
+
**CHANGES_REQUESTED** - Max iterations reached with remaining issues. Needs human review.
|
|
303
415
|
|
|
304
416
|
## Example Output
|
|
305
417
|
|
|
@@ -420,6 +532,9 @@ Action required:
|
|
|
420
532
|
| `--providers <list>` | Override providers (e.g., `--providers codex,gemini`) |
|
|
421
533
|
| `--codex-only` | Use only Codex for review |
|
|
422
534
|
| `--no-external` | Skip external providers, use Claude only |
|
|
535
|
+
| `--stuck-threshold <N>` | How many times the same issue reappears before escalating to human (default: 3) |
|
|
536
|
+
| `--no-fix` | Single-pass review only — report issues but don't auto-fix |
|
|
537
|
+
| `--fix-all` | Fix even low-priority style issues (default: skip style) |
|
|
423
538
|
|
|
424
539
|
## Integration
|
|
425
540
|
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# /tlc:watchci - Watch CI and Fix Until Green
|
|
2
|
+
|
|
3
|
+
After pushing code, monitor the GitHub Actions run and fix failures in a loop until CI passes.
|
|
4
|
+
|
|
5
|
+
## What This Does
|
|
6
|
+
|
|
7
|
+
1. **Identifies the GH Actions run** triggered by the latest push
|
|
8
|
+
2. **Polls until complete** (or fails)
|
|
9
|
+
3. **On failure**: reads the logs, identifies the issue, fixes it, commits, pushes again
|
|
10
|
+
4. **Repeats** until green or max attempts reached
|
|
11
|
+
5. **Reports** final status
|
|
12
|
+
|
|
13
|
+
This is the "I pushed, now babysit CI for me" command.
|
|
14
|
+
|
|
15
|
+
## Usage
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
/tlc:watchci
|
|
19
|
+
/tlc:watchci 3 # max 3 fix attempts (default: 5)
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Process
|
|
23
|
+
|
|
24
|
+
### Step 1: Find the Active Run
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
gh run list --limit 5 --json databaseId,status,conclusion,headBranch,event,name,createdAt
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
- Find the most recent run on the current branch
|
|
31
|
+
- If no run is in progress or recently completed, tell the user and exit
|
|
32
|
+
- Show: workflow name, run ID, status
|
|
33
|
+
|
|
34
|
+
### Step 2: Wait for Completion
|
|
35
|
+
|
|
36
|
+
Poll the run status every 30 seconds:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
gh run view <run_id> --json status,conclusion
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
While status is `in_progress` or `queued`:
|
|
43
|
+
- Print a brief status update every 60 seconds (not every poll)
|
|
44
|
+
- Continue waiting
|
|
45
|
+
|
|
46
|
+
### Step 3: Check Result
|
|
47
|
+
|
|
48
|
+
If `conclusion` is `success`:
|
|
49
|
+
- Report green and exit
|
|
50
|
+
|
|
51
|
+
If `conclusion` is `failure`:
|
|
52
|
+
- Move to Step 4
|
|
53
|
+
|
|
54
|
+
### Step 4: Read Failure Logs
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
gh run view <run_id> --log-failed
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
- Parse the failed step(s) and their log output
|
|
61
|
+
- Identify the root cause:
|
|
62
|
+
- **Test failure**: Which test, what assertion, what file
|
|
63
|
+
- **Build failure**: Which compilation error, what file/line
|
|
64
|
+
- **Lint failure**: Which rule, what file/line
|
|
65
|
+
- **Dependency issue**: Which package, what version conflict
|
|
66
|
+
- **Other**: Extract the relevant error message
|
|
67
|
+
|
|
68
|
+
### Step 5: Fix the Issue
|
|
69
|
+
|
|
70
|
+
Based on the failure type:
|
|
71
|
+
|
|
72
|
+
**Test failure:**
|
|
73
|
+
- Read the failing test file and the source file it tests
|
|
74
|
+
- Understand what broke
|
|
75
|
+
- Fix the source code (not the test, unless the test itself is wrong)
|
|
76
|
+
- Run the test locally first to verify: `npm test` or `npx vitest run <file>`
|
|
77
|
+
|
|
78
|
+
**Build failure:**
|
|
79
|
+
- Read the file with the compilation error
|
|
80
|
+
- Fix the type error, missing import, etc.
|
|
81
|
+
- Verify locally: `npm run build` or `npx tsc --noEmit`
|
|
82
|
+
|
|
83
|
+
**Lint failure:**
|
|
84
|
+
- Read the file and fix the lint issue
|
|
85
|
+
- Verify locally: `npm run lint`
|
|
86
|
+
|
|
87
|
+
**Dependency issue:**
|
|
88
|
+
- Fix package.json or lock file as needed
|
|
89
|
+
- Verify locally: `npm ci`
|
|
90
|
+
|
|
91
|
+
### Step 6: Commit and Push
|
|
92
|
+
|
|
93
|
+
- Stage only the files you changed
|
|
94
|
+
- Commit with message: `fix: resolve CI failure - <brief description>`
|
|
95
|
+
- Push to the same branch
|
|
96
|
+
- **Ask user before pushing** (per TLC rules)
|
|
97
|
+
|
|
98
|
+
### Step 7: Loop Back
|
|
99
|
+
|
|
100
|
+
- Return to Step 1 to watch the new run
|
|
101
|
+
- Track attempt count
|
|
102
|
+
- If max attempts (default 5) reached without green, stop and report:
|
|
103
|
+
- What was tried
|
|
104
|
+
- What's still failing
|
|
105
|
+
- Suggestion for manual investigation
|
|
106
|
+
|
|
107
|
+
## Guard Rails
|
|
108
|
+
|
|
109
|
+
- **Never push without asking.** Even in a fix loop, confirm before each push.
|
|
110
|
+
- **Never modify tests to make CI pass** unless the test itself has a genuine bug (not a "make the assertion match the wrong output" fix).
|
|
111
|
+
- **Local verification first.** Always run the fix locally before pushing.
|
|
112
|
+
- **Max attempts.** Default 5. Don't loop forever.
|
|
113
|
+
- **Don't mask failures.** If a test is legitimately catching a bug, fix the bug. Don't skip the test.
|
|
114
|
+
|
|
115
|
+
## Example
|
|
116
|
+
|
|
117
|
+
```
|
|
118
|
+
> /tlc:watchci
|
|
119
|
+
|
|
120
|
+
Watching CI for branch: feature/auth-module
|
|
121
|
+
Run #4521 (CI) — in progress...
|
|
122
|
+
|
|
123
|
+
⏳ Waiting... (2m elapsed)
|
|
124
|
+
⏳ Waiting... (3m elapsed)
|
|
125
|
+
|
|
126
|
+
❌ Run #4521 failed
|
|
127
|
+
|
|
128
|
+
Failed step: "Run tests"
|
|
129
|
+
Error: FAIL server/lib/auth/auth.test.js
|
|
130
|
+
● validateToken › should reject expired tokens
|
|
131
|
+
Expected: "TOKEN_EXPIRED"
|
|
132
|
+
Received: "INVALID_TOKEN"
|
|
133
|
+
|
|
134
|
+
Reading auth.test.js and auth.service.js...
|
|
135
|
+
|
|
136
|
+
Found: validateToken returns generic "INVALID_TOKEN" for expired tokens
|
|
137
|
+
instead of the specific "TOKEN_EXPIRED" error code.
|
|
138
|
+
|
|
139
|
+
Fix: Update the expiry check in auth.service.js to return "TOKEN_EXPIRED"
|
|
140
|
+
|
|
141
|
+
Running locally... ✅ Test passes
|
|
142
|
+
|
|
143
|
+
Ready to commit and push fix? (Y/n)
|
|
144
|
+
> y
|
|
145
|
+
|
|
146
|
+
Pushed. Watching new run...
|
|
147
|
+
|
|
148
|
+
Run #4522 (CI) — in progress...
|
|
149
|
+
⏳ Waiting... (2m elapsed)
|
|
150
|
+
|
|
151
|
+
✅ Run #4522 passed! CI is green.
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## When to Use
|
|
155
|
+
|
|
156
|
+
- After pushing and you want CI monitored automatically
|
|
157
|
+
- After `/tlc:build` when you've pushed your work
|
|
158
|
+
- When CI keeps failing and you want the fix loop automated
|
|
159
|
+
- Pair with `/tlc:e2e-verify` for full verification after CI is green
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# TLC Enforcement Layer 1: Hard-block non-TLC planning tools
|
|
3
|
+
# Fires on PreToolUse for banned tools and DENIES them.
|
|
4
|
+
# Claude cannot bypass this - the tool call never executes.
|
|
5
|
+
|
|
6
|
+
INPUT=$(cat)
|
|
7
|
+
TOOL=$(echo "$INPUT" | jq -r '.tool_name // empty')
|
|
8
|
+
|
|
9
|
+
case "$TOOL" in
|
|
10
|
+
EnterPlanMode)
|
|
11
|
+
REASON="BLOCKED by TLC. Use /tlc:plan instead. Plans go in .planning/phases/ files."
|
|
12
|
+
;;
|
|
13
|
+
TaskCreate)
|
|
14
|
+
REASON="BLOCKED by TLC. Tasks live in .planning/phases/{N}-PLAN.md with [ ] markers."
|
|
15
|
+
;;
|
|
16
|
+
TaskUpdate)
|
|
17
|
+
REASON="BLOCKED by TLC. Update task markers in .planning/phases/{N}-PLAN.md files."
|
|
18
|
+
;;
|
|
19
|
+
TaskGet)
|
|
20
|
+
REASON="BLOCKED by TLC. Read tasks from .planning/phases/{N}-PLAN.md files."
|
|
21
|
+
;;
|
|
22
|
+
TaskList)
|
|
23
|
+
REASON="BLOCKED by TLC. Use /tlc:progress to check task status."
|
|
24
|
+
;;
|
|
25
|
+
ExitPlanMode)
|
|
26
|
+
REASON="BLOCKED by TLC. Plans are approved via /tlc:build, not ExitPlanMode."
|
|
27
|
+
;;
|
|
28
|
+
*)
|
|
29
|
+
exit 0
|
|
30
|
+
;;
|
|
31
|
+
esac
|
|
32
|
+
|
|
33
|
+
cat <<EOF
|
|
34
|
+
{
|
|
35
|
+
"hookSpecificOutput": {
|
|
36
|
+
"hookEventName": "PreToolUse",
|
|
37
|
+
"permissionDecision": "deny",
|
|
38
|
+
"permissionDecisionReason": "${REASON}"
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
EOF
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# TLC Memory Capture - Claude Code Stop Hook
|
|
3
|
+
#
|
|
4
|
+
# Reads Stop hook JSON from stdin, extracts the assistant response,
|
|
5
|
+
# and sends it to the TLC server for memory processing.
|
|
6
|
+
# Falls back to local spool when server is unreachable.
|
|
7
|
+
#
|
|
8
|
+
# This script MUST exit 0 always - capture failures never block Claude.
|
|
9
|
+
|
|
10
|
+
set -o pipefail
|
|
11
|
+
|
|
12
|
+
# Read stdin (Stop hook provides JSON)
|
|
13
|
+
INPUT=$(cat)
|
|
14
|
+
|
|
15
|
+
# Quick exit if no input
|
|
16
|
+
[ -z "$INPUT" ] && exit 0
|
|
17
|
+
|
|
18
|
+
# Use the capture-bridge Node.js module for reliable processing
|
|
19
|
+
PROJECT_DIR="${CLAUDE_PROJECT_DIR:-$(pwd)}"
|
|
20
|
+
BRIDGE_SCRIPT="$PROJECT_DIR/server/lib/capture-bridge.js"
|
|
21
|
+
|
|
22
|
+
if [ -f "$BRIDGE_SCRIPT" ]; then
|
|
23
|
+
echo "$INPUT" | node -e "
|
|
24
|
+
const bridge = require('$BRIDGE_SCRIPT');
|
|
25
|
+
let input = '';
|
|
26
|
+
process.stdin.on('data', d => input += d);
|
|
27
|
+
process.stdin.on('end', async () => {
|
|
28
|
+
const parsed = bridge.parseStopHookInput(input);
|
|
29
|
+
if (!parsed || !parsed.assistantMessage) process.exit(0);
|
|
30
|
+
|
|
31
|
+
const userMessage = parsed.transcriptPath
|
|
32
|
+
? bridge.extractLastUserMessage(parsed.transcriptPath)
|
|
33
|
+
: null;
|
|
34
|
+
|
|
35
|
+
await bridge.captureExchange({
|
|
36
|
+
cwd: parsed.cwd || '$PROJECT_DIR',
|
|
37
|
+
assistantMessage: parsed.assistantMessage,
|
|
38
|
+
userMessage,
|
|
39
|
+
sessionId: parsed.sessionId,
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
const path = require('path');
|
|
43
|
+
const spoolDir = path.join(parsed.cwd || '$PROJECT_DIR', '.tlc', 'memory');
|
|
44
|
+
await bridge.drainSpool(spoolDir);
|
|
45
|
+
});
|
|
46
|
+
" 2>/dev/null
|
|
47
|
+
fi
|
|
48
|
+
|
|
49
|
+
# Always exit 0 - never block Claude
|
|
50
|
+
exit 0
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# TLC Plugin: Post-build and post-plan automation chain
|
|
3
|
+
# Fires on PostToolUse for Skill.
|
|
4
|
+
#
|
|
5
|
+
# After /tlc:build (code written):
|
|
6
|
+
# guard → preflight → review (Claude + Codex) → if APPROVED → offer push + PR
|
|
7
|
+
#
|
|
8
|
+
# After /tlc:plan:
|
|
9
|
+
# guard plan → validate structure
|
|
10
|
+
#
|
|
11
|
+
# After /tlc:quick:
|
|
12
|
+
# preflight → review → offer push
|
|
13
|
+
|
|
14
|
+
INPUT=$(cat)
|
|
15
|
+
TOOL=$(echo "$INPUT" | jq -r '.tool_name // empty')
|
|
16
|
+
|
|
17
|
+
# Only care about Skill tool
|
|
18
|
+
[ "$TOOL" != "Skill" ] && exit 0
|
|
19
|
+
|
|
20
|
+
SKILL=$(echo "$INPUT" | jq -r '.tool_input.skill // empty')
|
|
21
|
+
|
|
22
|
+
case "$SKILL" in
|
|
23
|
+
tlc:build)
|
|
24
|
+
echo "[TLC-PLUGIN] Build phase complete. Mandatory post-build chain:
|
|
25
|
+
(1) Run /tlc:guard to validate TLC process compliance (test-first, coverage, no skipped tests).
|
|
26
|
+
(2) Run /tlc:preflight to check for gaps (references, registries, configs, distribution).
|
|
27
|
+
(3) Run /tlc:review to invoke multi-LLM review — Claude reviews in-session, THEN invoke Codex CLI for second opinion. BOTH must APPROVE.
|
|
28
|
+
(4) If review APPROVED: ask user for permission to push to remote and create a PR for main.
|
|
29
|
+
(5) If review CHANGES_REQUESTED: fix the issues and re-run the review. Do NOT push.
|
|
30
|
+
Do NOT skip any step. Do NOT push without review approval."
|
|
31
|
+
;;
|
|
32
|
+
tlc:plan)
|
|
33
|
+
echo "[TLC-PLUGIN] Plan created. Now automatically run /tlc:guard plan to validate the plan has proper task breakdown, acceptance criteria, and dependency ordering. Do NOT skip."
|
|
34
|
+
;;
|
|
35
|
+
tlc:quick)
|
|
36
|
+
echo "[TLC-PLUGIN] Quick task complete. Run /tlc:preflight then /tlc:review (Claude + Codex). If APPROVED, ask user for permission to push and create PR."
|
|
37
|
+
;;
|
|
38
|
+
esac
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# TLC Plugin: Post-push automation chain
|
|
3
|
+
# Fires on PostToolUse for Bash. Detects git push.
|
|
4
|
+
#
|
|
5
|
+
# After git push:
|
|
6
|
+
# watchci (monitor GH Actions) → if green → e2e-verify (screenshots + logs)
|
|
7
|
+
|
|
8
|
+
INPUT=$(cat)
|
|
9
|
+
TOOL=$(echo "$INPUT" | jq -r '.tool_name // empty')
|
|
10
|
+
|
|
11
|
+
# Only care about Bash tool
|
|
12
|
+
[ "$TOOL" != "Bash" ] && exit 0
|
|
13
|
+
|
|
14
|
+
# Check if the command was a git push
|
|
15
|
+
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty')
|
|
16
|
+
if echo "$COMMAND" | grep -qE '^git push'; then
|
|
17
|
+
echo "[TLC-PLUGIN] git push detected. Mandatory post-push chain:
|
|
18
|
+
(1) Run /tlc:watchci — monitor the GitHub Actions run, read failure logs, fix issues, and push again until CI is green.
|
|
19
|
+
(2) Once CI is green, run /tlc:e2e-verify — start the app, take screenshots, read them visually, check server and console logs for errors.
|
|
20
|
+
(3) If e2e-verify finds issues, fix them and push again (which restarts this chain).
|
|
21
|
+
Do NOT skip any step."
|
|
22
|
+
fi
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# TLC Enforcement Layer 2: Smart intent detection + routing
|
|
3
|
+
# Fires on every UserPromptSubmit. Parses user message for intent and
|
|
4
|
+
# injects specific TLC command routing — not a generic reminder.
|
|
5
|
+
#
|
|
6
|
+
# Output appears as <user-prompt-submit-hook> and Claude treats it as user instruction.
|
|
7
|
+
# Survives context compaction because it is re-injected every turn.
|
|
8
|
+
|
|
9
|
+
# Only active in TLC projects
|
|
10
|
+
[ ! -f ".tlc.json" ] && exit 0
|
|
11
|
+
|
|
12
|
+
# Read user's message from stdin
|
|
13
|
+
INPUT=$(cat)
|
|
14
|
+
MSG=$(echo "$INPUT" | jq -r '.user_prompt // empty' 2>/dev/null)
|
|
15
|
+
|
|
16
|
+
# If we can't parse the message, fall back to generic reminder
|
|
17
|
+
if [ -z "$MSG" ]; then
|
|
18
|
+
echo "[TLC PROJECT] All work uses /tlc commands. Never write code without tests. Run /tlc if unsure."
|
|
19
|
+
exit 0
|
|
20
|
+
fi
|
|
21
|
+
|
|
22
|
+
# Lowercase for matching
|
|
23
|
+
MSG_LOWER=$(echo "$MSG" | tr '[:upper:]' '[:lower:]')
|
|
24
|
+
|
|
25
|
+
# Detect intent and inject specific routing
|
|
26
|
+
# Priority order: most specific first
|
|
27
|
+
|
|
28
|
+
# Plan intent
|
|
29
|
+
if echo "$MSG_LOWER" | grep -qE '\b(plan|break.*(down|into)|design|architect|roadmap)\b'; then
|
|
30
|
+
if ! echo "$MSG_LOWER" | grep -qE '/tlc'; then
|
|
31
|
+
echo "[TLC-ENFORCE] Planning detected. You MUST use /tlc:plan for this. Plans go in .planning/phases/ files, not in chat. Invoke Skill(skill=\"tlc:plan\") now."
|
|
32
|
+
exit 0
|
|
33
|
+
fi
|
|
34
|
+
fi
|
|
35
|
+
|
|
36
|
+
# Build/implement intent
|
|
37
|
+
if echo "$MSG_LOWER" | grep -qE '\b(build|implement|create|add|code|write|develop|make)\b.*(feature|function|module|component|endpoint|api|page|service|handler|route|model)'; then
|
|
38
|
+
if ! echo "$MSG_LOWER" | grep -qE '/tlc'; then
|
|
39
|
+
echo "[TLC-ENFORCE] Implementation detected. You MUST use /tlc:build for this. Tests before code — Red, Green, Refactor. Run /tlc:progress first, then invoke Skill(skill=\"tlc:build\"). Do NOT write code directly."
|
|
40
|
+
exit 0
|
|
41
|
+
fi
|
|
42
|
+
fi
|
|
43
|
+
|
|
44
|
+
# Fix/bug intent
|
|
45
|
+
if echo "$MSG_LOWER" | grep -qE '\b(fix|bug|broken|not working|failing|crash|error)\b'; then
|
|
46
|
+
if ! echo "$MSG_LOWER" | grep -qE '/tlc'; then
|
|
47
|
+
echo "[TLC-ENFORCE] Bug/fix detected. Use /tlc:quick for small fixes (still test-first) or /tlc:autofix if tests are failing. Do NOT write code directly without tests."
|
|
48
|
+
exit 0
|
|
49
|
+
fi
|
|
50
|
+
fi
|
|
51
|
+
|
|
52
|
+
# Refactor intent
|
|
53
|
+
if echo "$MSG_LOWER" | grep -qE '\b(refactor|clean.?up|restructure|reorganize|simplify)\b'; then
|
|
54
|
+
if ! echo "$MSG_LOWER" | grep -qE '/tlc'; then
|
|
55
|
+
echo "[TLC-ENFORCE] Refactoring detected. Use /tlc:refactor for step-by-step standards refactoring with tests. Invoke Skill(skill=\"tlc:refactor\")."
|
|
56
|
+
exit 0
|
|
57
|
+
fi
|
|
58
|
+
fi
|
|
59
|
+
|
|
60
|
+
# Deploy intent
|
|
61
|
+
if echo "$MSG_LOWER" | grep -qE '\b(deploy|ship|release|publish|push to prod|staging)\b'; then
|
|
62
|
+
if ! echo "$MSG_LOWER" | grep -qE '/tlc'; then
|
|
63
|
+
echo "[TLC-ENFORCE] Deployment detected. Use /tlc:deploy for deployment. Secrets must come from HashiCorp Vault or environment — never hardcode. Invoke Skill(skill=\"tlc:deploy\")."
|
|
64
|
+
exit 0
|
|
65
|
+
fi
|
|
66
|
+
fi
|
|
67
|
+
|
|
68
|
+
# Generic fallback for TLC projects
|
|
69
|
+
echo "[TLC PROJECT] All work uses /tlc commands. Never write code without tests. Run /tlc if unsure."
|