tlc-claude-code 2.4.3 → 2.4.5

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 (42) hide show
  1. package/.claude/commands/tlc/build.md +33 -13
  2. package/.claude/commands/tlc/recall.md +59 -87
  3. package/.claude/commands/tlc/remember.md +76 -71
  4. package/.claude/commands/tlc/review.md +76 -21
  5. package/.claude/hooks/tlc-capture-exchange.sh +50 -21
  6. package/.claude/hooks/tlc-session-init.sh +30 -0
  7. package/bin/init.js +12 -3
  8. package/package.json +1 -1
  9. package/server/lib/capture/classifier.js +71 -0
  10. package/server/lib/capture/classifier.test.js +71 -0
  11. package/server/lib/capture/claude-capture.js +140 -0
  12. package/server/lib/capture/claude-capture.test.js +152 -0
  13. package/server/lib/capture/codex-capture.js +79 -0
  14. package/server/lib/capture/codex-capture.test.js +161 -0
  15. package/server/lib/capture/codex-event-parser.js +76 -0
  16. package/server/lib/capture/codex-event-parser.test.js +83 -0
  17. package/server/lib/capture/ensure-ready.js +56 -0
  18. package/server/lib/capture/ensure-ready.test.js +135 -0
  19. package/server/lib/capture/envelope.js +77 -0
  20. package/server/lib/capture/envelope.test.js +169 -0
  21. package/server/lib/capture/extractor.js +51 -0
  22. package/server/lib/capture/extractor.test.js +92 -0
  23. package/server/lib/capture/generic-capture.js +96 -0
  24. package/server/lib/capture/generic-capture.test.js +171 -0
  25. package/server/lib/capture/index.js +117 -0
  26. package/server/lib/capture/index.test.js +263 -0
  27. package/server/lib/capture/redactor.js +68 -0
  28. package/server/lib/capture/redactor.test.js +93 -0
  29. package/server/lib/capture/spool-processor.js +155 -0
  30. package/server/lib/capture/spool-processor.test.js +278 -0
  31. package/server/lib/health-check.js +255 -0
  32. package/server/lib/health-check.test.js +243 -0
  33. package/server/lib/orchestration/cli-dispatch.js +200 -0
  34. package/server/lib/orchestration/cli-dispatch.test.js +242 -0
  35. package/server/lib/orchestration/prompt-builder.js +118 -0
  36. package/server/lib/orchestration/prompt-builder.test.js +200 -0
  37. package/server/lib/orchestration/standalone-compat.js +39 -0
  38. package/server/lib/orchestration/standalone-compat.test.js +144 -0
  39. package/server/lib/orchestration/worktree-manager.js +43 -0
  40. package/server/lib/orchestration/worktree-manager.test.js +50 -0
  41. package/server/lib/task-router-config.js +22 -5
  42. package/server/lib/task-router-config.test.js +46 -13
@@ -83,16 +83,18 @@ process.stdout.write(JSON.stringify(result));" 2>/dev/null
83
83
  ```
84
84
 
85
85
  2. If `models[0]` is NOT `claude` (i.e., routed to external model):
86
- - Read PROJECT.md, current phase PLAN.md, CODING-STANDARDS.md
87
- - Package the agent prompt below with project context using `prompt-packager`
88
- - Dispatch to the target CLI using `cli-dispatcher`
89
- - Display the CLI output and stop — do NOT execute the agent prompt below
86
+ - Resolve 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 via unified CLI routing with `dispatch` from `orchestration/cli-dispatch`
89
+ - Capture provider output for memory with `captureFromProvider` from `capture`, display the CLI output, and stop — do NOT execute the agent prompt below
90
90
 
91
91
  3. If `models[0]` IS `claude` (or no routing config exists):
92
92
  - Execute the agent prompt below as normal (current behavior)
93
93
 
94
94
  4. If `strategy` is `parallel`:
95
- - Execute inline (Claude) AND dispatch to CLI models simultaneously
95
+ - Resolve modules with fallback: try `tlc-claude-code/server/lib/...` first, then `$PROJECT_DIR/server/lib/...`
96
+ - Execute inline (Claude) AND dispatch each external provider via `dispatch` from `orchestration/cli-dispatch`
97
+ - After each provider completes, capture its output with `captureFromProvider` from `capture`
96
98
  - Collect and merge results
97
99
 
98
100
  **Override:** Pass `--model <name>` to route this specific run to a different model.
@@ -934,15 +936,33 @@ Verdict: ❌ CHANGES REQUESTED
934
936
  ───────────────────────────────
935
937
  ```
936
938
 
937
- **Actions on failure:**
938
- 1. Add missing test files
939
- 2. Fix security issues
940
- 3. Split oversized files (>1000 lines) into focused sub-modules
941
- 4. Replace `any` types with proper interfaces or `unknown`
942
- 5. Add explicit return types to all exported functions
943
- 6. Re-run `/tlc:build {phase}` to retry
939
+ **Review-Fix Loop (automatic — do not ask, just do it):**
944
940
 
945
- **CRITICAL: Phase is NOT complete until review passes.**
941
+ When the review finds issues, fix them immediately and re-review. This is a loop, not a hand-off:
942
+
943
+ ```
944
+ Iteration 1: Review → found 3 issues
945
+ → Fix: add missing tests, remove hardcoded secret, split oversized file
946
+ → Run tests (must still pass after fixes)
947
+ → Commit fixes: "fix: review findings - phase {N}"
948
+
949
+ Iteration 2: Re-review → found 1 issue
950
+ → Fix: replace `any` type with interface
951
+ → Run tests
952
+ → Commit fix
953
+
954
+ Iteration 3: Re-review → clean
955
+ → Verdict: ✅ APPROVED
956
+ ```
957
+
958
+ **Loop rules:**
959
+ - Max 5 iterations. If still failing after 5, report remaining issues and stop.
960
+ - Run the full test suite after each fix batch (never break tests to fix review issues).
961
+ - Commit after each fix batch — don't accumulate.
962
+ - Each iteration re-runs ALL checks, not just the ones that failed (fixes can introduce new issues).
963
+ - Security issues are fixed first (highest priority), then coverage, then style.
964
+
965
+ **CRITICAL: Phase is NOT complete until review passes. The loop runs automatically — do not stop after reporting issues.**
946
966
 
947
967
  ### Step 11: Push Branch and Create PR (Mandatory)
948
968
 
@@ -1,87 +1,59 @@
1
- # /tlc:recall - Semantic Memory Search
2
-
3
- Search your project's memory by meaning. "What did we decide about X?"
4
-
5
- ## Usage
6
-
7
- ```
8
- /tlc:recall <query>
9
- ```
10
-
11
- ## What This Does
12
-
13
- 1. Searches the vector memory store using semantic similarity
14
- 2. Ranks results by: similarity (50%) + recency (25%) + project relevance (25%)
15
- 3. Returns top-5 results with scores, types, and excerpts
16
- 4. Permanent memories get a 1.2x boost in scoring
17
-
18
- ## Options
19
-
20
- ```
21
- /tlc:recall database architecture
22
- /tlc:recall --scope workspace authentication approach
23
- /tlc:recall --type decision deployment strategy
24
- /tlc:recall --limit 10 API design
25
- ```
26
-
27
- | Flag | Values | Default | Description |
28
- |------|--------|---------|-------------|
29
- | `--scope` | `project`, `workspace`, `global` | `project` | Search scope (auto-widens if few results) |
30
- | `--type` | `decision`, `gotcha`, `conversation`, `all` | `all` | Filter by memory type |
31
- | `--limit` | 1-20 | 5 | Maximum results |
32
-
33
- ## Process
34
-
35
- ### Step 1: Parse Query
36
-
37
- Extract the search query and any flags from the arguments.
38
-
39
- ### Step 2: Semantic Search
40
-
41
- 1. Generate embedding for the query
42
- 2. Search vector store for nearest neighbors
43
- 3. Score results: `similarity * 0.5 + recency * 0.25 + projectRelevance * 0.25`
44
- 4. Boost permanent memories by 1.2x
45
- 5. Apply scope, type, and limit filters
46
-
47
- ### Step 3: Display Results
48
-
49
- ```
50
- ## Memory Recall: "database architecture"
51
-
52
- 1. **Use SQLite for vector storage** (92% match) [decision]
53
- Date: 2026-02-09
54
- Zero infrastructure, single file, ships with TLC
55
- Source: memory/decisions/2026-02-09-use-sqlite-for-vector-storage.md
56
-
57
- 2. **[PERMANENT] Always use WAL mode** (87% match) [gotcha]
58
- Date: 2026-02-08
59
- WAL mode required for concurrent reads during indexing
60
- Source: memory/gotchas/2026-02-08-always-use-wal-mode.md
61
-
62
- 3. **Database migration strategy** (81% match) [conversation]
63
- Date: 2026-02-07
64
- Discussed migration approach, decided on schema-first
65
- Source: memory/conversations/2026-02-07-database-migration.md
66
- ```
67
-
68
- ### Step 4: Fallback
69
-
70
- If the vector store is unavailable (Ollama not running, no embeddings):
71
- - Falls back to keyword-based text search
72
- - Shows a notice that semantic search is unavailable
73
-
74
- ## Examples
75
-
76
- ```
77
- /tlc:recall what database should we use
78
- /tlc:recall deployment strategy --scope global
79
- /tlc:recall --type decision authentication
80
- /tlc:recall testing approach --limit 10
81
- ```
82
-
83
- ## Graceful Degradation
84
-
85
- - **No Ollama**: Falls back to text search with keyword matching
86
- - **Empty store**: Shows "No memories indexed yet" with guidance to run `/tlc:remember`
87
- - **No results**: Shows "No matching memories" with search suggestions
1
+ # /tlc:recall - Team Memory Search
2
+
3
+ Search TLC team memory using plain grep. This is intentional: no vector search, no extra services.
4
+
5
+ ## Usage
6
+
7
+ ```text
8
+ /tlc:recall <query>
9
+ ```
10
+
11
+ ## What This Does
12
+
13
+ 1. Searches `.tlc/memory/team/` with `grep -rl "query" .tlc/memory/team/`.
14
+ 2. Looks in both `.tlc/memory/team/decisions/` and `.tlc/memory/team/gotchas/`.
15
+ 3. Shows the file path, date from the filename, and a matching excerpt.
16
+ 4. Uses grep only because it works everywhere.
17
+
18
+ ## Search Rules
19
+
20
+ - Search both `decisions/` and `gotchas/`.
21
+ - Do not use vector search.
22
+ - Do not depend on embeddings, databases, or external services.
23
+ - Prefer simple recursive grep so the command works across projects.
24
+
25
+ ## Process
26
+
27
+ ### Step 1: Find matching files
28
+
29
+ ```bash
30
+ grep -rl "query" .tlc/memory/team/
31
+ ```
32
+
33
+ ### Step 2: Display matches
34
+
35
+ For each matching file, show:
36
+
37
+ - File path
38
+ - Date parsed from the filename prefix
39
+ - A short matching excerpt from the file body
40
+
41
+ ## Example Output
42
+
43
+ ```text
44
+ Memory recall: "utc"
45
+
46
+ File: .tlc/memory/team/decisions/2026-03-28-use-utc-timestamps.md
47
+ Date: 2026-03-28
48
+ Excerpt: Always use UTC timestamps in the database and in exported logs.
49
+
50
+ File: .tlc/memory/team/gotchas/2026-03-21-local-time-breaks-reporting.md
51
+ Date: 2026-03-21
52
+ Excerpt: Local timezone conversion caused reporting drift in scheduled jobs.
53
+ ```
54
+
55
+ ## Notes
56
+
57
+ - If there are no matches, say so directly.
58
+ - Keep excerpts short and relevant.
59
+ - Search TLC memory under `.tlc/memory/team/`, not Claude-managed memory.
@@ -1,71 +1,76 @@
1
- # /tlc:remember - Permanent Memory Capture
2
-
3
- Save important context permanently so it survives context compaction.
4
-
5
- ## Usage
6
-
7
- ```
8
- /tlc:remember <text>
9
- ```
10
-
11
- Or without arguments to capture recent exchanges:
12
- ```
13
- /tlc:remember
14
- ```
15
-
16
- ## What This Does
17
-
18
- 1. Captures the provided text (or recent conversation) as a **permanent memory**
19
- 2. Writes it to `memory/conversations/` with `[PERMANENT]` prefix and `permanent: true` frontmatter
20
- 3. Indexes it in the vector store for semantic recall
21
- 4. Permanent memories are **never pruned** and get a **1.2x boost** in recall scoring
22
-
23
- ## Process
24
-
25
- ### Step 1: Determine What to Remember
26
-
27
- **With text argument:**
28
- - Use the provided text as the memory content
29
-
30
- **Without arguments:**
31
- - Capture the recent conversation exchanges from the current session
32
- - Generate a summary from the exchanges
33
-
34
- ### Step 2: Write Permanent Memory
35
-
36
- 1. Create a conversation chunk with `permanent: true`
37
- 2. Title prefixed with `[PERMANENT]`
38
- 3. Write to `memory/conversations/YYYY-MM-DD-{slug}.md`
39
- 4. YAML frontmatter includes `permanent: true`
40
-
41
- ### Step 3: Index in Vector Store
42
-
43
- 1. Generate embedding for the memory content
44
- 2. Store in vector database with `permanent = 1` flag
45
- 3. This memory will be boosted 1.2x in future recall searches
46
-
47
- ### Step 4: Confirm
48
-
49
- ```
50
- Remembered permanently: {summary}
51
- File: memory/conversations/2026-02-09-always-use-utc.md
52
- ```
53
-
54
- ## Examples
55
-
56
- ```
57
- /tlc:remember Always use UTC timestamps in the database, never local time
58
-
59
- /tlc:remember The API rate limit is 100 requests per minute per user
60
-
61
- /tlc:remember
62
- (captures recent conversation context)
63
- ```
64
-
65
- ## When to Use
66
-
67
- - **Architecture decisions** that should never be forgotten
68
- - **Environment gotchas** that are hard to rediscover
69
- - **Team conventions** that must be consistent
70
- - **Critical constraints** from stakeholders
71
- - Any knowledge you want to survive across sessions and context compaction
1
+ # /tlc:remember - Team Decision Capture
2
+
3
+ Save an important decision into TLC's shared team memory.
4
+
5
+ ## Usage
6
+
7
+ ```text
8
+ /tlc:remember <decision text>
9
+ ```
10
+
11
+ Or without arguments:
12
+
13
+ ```text
14
+ /tlc:remember
15
+ ```
16
+
17
+ ## What This Does
18
+
19
+ 1. Captures the provided decision text, or extracts decisions from the recent conversation context if no argument is given.
20
+ 2. Writes a markdown file to `.tlc/memory/team/decisions/{date}-{slug}.md`.
21
+ 3. Stores TLC-owned frontmatter for later grep-based recall.
22
+ 4. Never writes to `~/.claude/projects/.../memory/` because that is Claude memory, not TLC memory.
23
+
24
+ ## Write Format
25
+
26
+ Write the decision as a markdown file with YAML frontmatter:
27
+
28
+ ```yaml
29
+ ---
30
+ provider: claude
31
+ source: manual
32
+ timestamp: 2026-03-28T12:34:56Z
33
+ type: decision
34
+ scope: team
35
+ ---
36
+ ```
37
+
38
+ The filename must be:
39
+
40
+ ```text
41
+ .tlc/memory/team/decisions/{date}-{slug}.md
42
+ ```
43
+
44
+ Example:
45
+
46
+ ```text
47
+ .tlc/memory/team/decisions/2026-03-28-use-utc-timestamps.md
48
+ ```
49
+
50
+ ## Process
51
+
52
+ ### With an argument
53
+
54
+ - Use the argument as the decision content.
55
+ - Generate a short slug from the decision.
56
+ - Write the file under `.tlc/memory/team/decisions/`.
57
+
58
+ ### Without an argument
59
+
60
+ - Review the recent conversation context.
61
+ - Extract concrete decisions, conventions, or constraints worth preserving.
62
+ - Summarize them clearly.
63
+ - Write one decision file under `.tlc/memory/team/decisions/`.
64
+
65
+ ## Confirmation
66
+
67
+ ```text
68
+ Remembered: {summary}
69
+ File: .tlc/memory/team/decisions/2026-03-28-use-utc-timestamps.md
70
+ ```
71
+
72
+ ## Notes
73
+
74
+ - Prefer concise, durable statements over raw transcript dumps.
75
+ - Record decisions, not general chatter.
76
+ - Use `.tlc/memory/team/gotchas/` for gotchas, not this command.
@@ -127,7 +127,7 @@ TLC automatically uses ALL providers configured for the `review` capability in `
127
127
 
128
128
  **With this config, `/tlc:review` will:**
129
129
  1. Run Claude's review (current session)
130
- 2. Invoke Codex CLI for second opinion: `codex "Review this diff: ..."`
130
+ 2. Invoke Codex CLI for second opinion: `codex exec review --base main -m gpt-5.4 --json --ephemeral`
131
131
  3. Combine verdicts - both must approve for APPROVED
132
132
 
133
133
  ## Usage
@@ -295,31 +295,86 @@ Coding Standards:
295
295
 
296
296
  **Fail if:** Any `any` types in new code, or files >1000 lines.
297
297
 
298
- ### Step 6: Invoke External Providers (Codex, Gemini)
298
+ ### Step 6: Invoke External Providers (Codex, Gemini)
299
299
 
300
300
  **CRITICAL: This step runs automatically when providers are configured.**
301
301
 
302
302
  For each provider in `reviewProviders` (except `claude` which is the current session):
303
303
 
304
- **How to invoke:**
305
-
306
- **Codex** — use its built-in `review` subcommand. It reads the git diff natively, no need to pipe files:
307
-
308
- ```bash
309
- # Review current branch against main (default)
310
- codex review --base main "Focus on: bugs, security issues, missing edge cases, test coverage gaps. End with APPROVED or CHANGES_REQUESTED."
311
-
312
- # Review uncommitted changes only
313
- codex review --uncommitted
314
-
315
- # Review a specific commit
316
- codex review --commit <sha>
317
-
318
- # Custom instructions via prompt
319
- codex review --base main "Check for TDD compliance: were tests written before implementation? Flag any implementation without corresponding test files."
320
- ```
321
-
322
- `codex review` outputs a structured review to stdout. No `--print` flag needed — it's already non-interactive.
304
+ **How to invoke:**
305
+
306
+ **Codex** — use `codex exec review` with explicit model selection, JSON output, and `--ephemeral` for CI-style stateless runs. It reads the git diff natively, no need to pipe files.
307
+
308
+ Before invoking Codex, compute diff stats:
309
+
310
+ ```bash
311
+ FILES=$(git diff --name-only main...HEAD | wc -l)
312
+ LINES=$(git diff --stat main...HEAD | tail -1 | grep -oE '[0-9]+ insertion|[0-9]+ deletion' | grep -oE '[0-9]+' | paste -sd+ | bc)
313
+ ```
314
+
315
+ **Size-aware Codex review strategy:**
316
+
317
+ **Small diff (`<=15` files, `<=1200` lines):**
318
+
319
+ Single pass:
320
+
321
+ ```bash
322
+ codex exec review --base main -m gpt-5.4 --json --ephemeral
323
+ ```
324
+
325
+ **Medium diff (`15-25` files, `1200-2500` lines):**
326
+
327
+ Two passes:
328
+
329
+ 1. Broad pass:
330
+ ```bash
331
+ codex exec review --base main -m gpt-5.4 --json --ephemeral
332
+ ```
333
+ 2. Focused pass on the highest-risk area via `codex exec` with a targeted prompt:
334
+ ```bash
335
+ codex exec -m gpt-5.4 --json --ephemeral "Review the changes against main. Focus only on these files: <highest-risk file list>. Focus only on: correctness bugs, behavioral regressions, broken assumptions across module boundaries, missing validation/auth/error handling, schema/API compatibility. Do not spend time on style or naming. Prefer findings with: severity, why it is a bug, exact file/line, minimal breaking scenario."
336
+ ```
337
+
338
+ **Large diff (`25+` files, `2500+` lines):**
339
+
340
+ Multi-pass:
341
+
342
+ 1. Per-commit:
343
+ ```bash
344
+ codex exec review --commit <sha> -m gpt-5.4 --json --ephemeral
345
+ ```
346
+ Run once for each non-merge commit.
347
+ 2. Per-area:
348
+ Chunk by directory, then run `codex exec` with a prompt listing the chunk files:
349
+ ```bash
350
+ codex exec -m gpt-5.4 --json --ephemeral "Review the changes against main. Focus only on these files: <chunk file list>. Focus only on: correctness bugs, behavioral regressions, broken assumptions across module boundaries, missing validation/auth/error handling, schema/API compatibility. Do not spend time on style or naming. Prefer findings with: severity, why it is a bug, exact file/line, minimal breaking scenario."
351
+ ```
352
+ 3. Integration sweep:
353
+ ```bash
354
+ codex exec -m gpt-5.4 --json --ephemeral "Review the full diff against main but do not re-check every local edit. Focus only on cross-file regressions: changed call sites vs function contracts, schema changes vs readers/writers, auth/permission drift, partial migrations."
355
+ ```
356
+
357
+ **Confidence escalation:**
358
+
359
+ - Finding repeated across passes -> high confidence
360
+ - Finding from only one broad pass -> medium confidence
361
+ - Zero findings on huge diff -> LOW CONFIDENCE (not "clean"); flag for human review
362
+
363
+ **Prompt templates:**
364
+
365
+ Per-commit/per-area prompt:
366
+
367
+ ```text
368
+ Review the changes against main. Focus only on: correctness bugs, behavioral regressions, broken assumptions across module boundaries, missing validation/auth/error handling, schema/API compatibility. Do not spend time on style or naming. Prefer findings with: severity, why it is a bug, exact file/line, minimal breaking scenario.
369
+ ```
370
+
371
+ Integration sweep prompt:
372
+
373
+ ```text
374
+ Review the full diff against main but do not re-check every local edit. Focus only on cross-file regressions: changed call sites vs function contracts, schema changes vs readers/writers, auth/permission drift, partial migrations.
375
+ ```
376
+
377
+ Use `codex exec review`, not plain `codex review`, for better automation controls. Always include `-m gpt-5.4`, `--json`, and `--ephemeral` in automated runs.
323
378
 
324
379
  **Gemini** — no built-in review command, so save diff and invoke:
325
380
 
@@ -15,35 +15,64 @@ INPUT=$(cat)
15
15
  # Quick exit if no input
16
16
  [ -z "$INPUT" ] && exit 0
17
17
 
18
- # Use the capture-bridge Node.js module for reliable processing
19
18
  PROJECT_DIR="${CLAUDE_PROJECT_DIR:-$(pwd)}"
20
- BRIDGE_SCRIPT="$PROJECT_DIR/server/lib/capture-bridge.js"
19
+ CAPTURE_MOD=""
20
+ if node -e "require('tlc-claude-code/server/lib/capture/claude-capture')" 2>/dev/null; then
21
+ CAPTURE_MOD="tlc-claude-code/server/lib/capture/claude-capture"
22
+ elif [ -f "$PROJECT_DIR/server/lib/capture/claude-capture.js" ]; then
23
+ CAPTURE_MOD="$PROJECT_DIR/server/lib/capture/claude-capture"
24
+ fi
25
+
26
+ if [ -n "$CAPTURE_MOD" ]; then
27
+ # Resolve spool processor for same-session drain
28
+ SPOOL_MOD=""
29
+ if node -e "require('tlc-claude-code/server/lib/capture/spool-processor')" 2>/dev/null; then
30
+ SPOOL_MOD="tlc-claude-code/server/lib/capture/spool-processor"
31
+ elif [ -f "$PROJECT_DIR/server/lib/capture/spool-processor.js" ]; then
32
+ SPOOL_MOD="$PROJECT_DIR/server/lib/capture/spool-processor"
33
+ fi
21
34
 
22
- if [ -f "$BRIDGE_SCRIPT" ]; then
23
35
  echo "$INPUT" | node -e "
24
- const bridge = require('$BRIDGE_SCRIPT');
36
+ const { captureClaudeExchange } = require('$CAPTURE_MOD');
25
37
  let input = '';
26
38
  process.stdin.on('data', d => input += d);
27
39
  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);
40
+ captureClaudeExchange({ hookInput: input, projectDir: '$PROJECT_DIR' });
41
+ // Drain spool so memories are available same-session
42
+ try {
43
+ const { processSpool } = require('$SPOOL_MOD');
44
+ await processSpool('$PROJECT_DIR');
45
+ } catch {}
45
46
  });
46
47
  " 2>/dev/null
48
+ else
49
+ BRIDGE_SCRIPT="$PROJECT_DIR/server/lib/capture-bridge.js"
50
+ if [ -f "$BRIDGE_SCRIPT" ]; then
51
+ echo "$INPUT" | node -e "
52
+ const bridge = require('$BRIDGE_SCRIPT');
53
+ let input = '';
54
+ process.stdin.on('data', d => input += d);
55
+ process.stdin.on('end', async () => {
56
+ const parsed = bridge.parseStopHookInput(input);
57
+ if (!parsed || !parsed.assistantMessage) process.exit(0);
58
+
59
+ const userMessage = parsed.transcriptPath
60
+ ? bridge.extractLastUserMessage(parsed.transcriptPath)
61
+ : null;
62
+
63
+ await bridge.captureExchange({
64
+ cwd: parsed.cwd || '$PROJECT_DIR',
65
+ assistantMessage: parsed.assistantMessage,
66
+ userMessage,
67
+ sessionId: parsed.sessionId,
68
+ });
69
+
70
+ const path = require('path');
71
+ const spoolDir = path.join(parsed.cwd || '$PROJECT_DIR', '.tlc', 'memory');
72
+ await bridge.drainSpool(spoolDir);
73
+ });
74
+ " 2>/dev/null
75
+ fi
47
76
  fi
48
77
 
49
78
  # Always exit 0 - never block Claude
@@ -43,6 +43,23 @@ else
43
43
  done
44
44
  fi
45
45
 
46
+ # ─── Memory System Init ─────────────────────────────
47
+ mkdir -p "$PROJECT_DIR/.tlc/memory/team/decisions" \
48
+ "$PROJECT_DIR/.tlc/memory/team/gotchas" \
49
+ "$PROJECT_DIR/.tlc/memory/.local/sessions"
50
+
51
+ # ─── Spool Drain ─────────────────────────────────────
52
+ # Try to drain any pending spool entries from previous sessions
53
+ SPOOL_DRAIN=""
54
+ if node -e "require('tlc-claude-code/server/lib/capture/spool-processor')" 2>/dev/null; then
55
+ SPOOL_DRAIN="require('tlc-claude-code/server/lib/capture/spool-processor').processSpool('$PROJECT_DIR')"
56
+ elif [ -f "$PROJECT_DIR/server/lib/capture/spool-processor.js" ]; then
57
+ SPOOL_DRAIN="require('$PROJECT_DIR/server/lib/capture/spool-processor').processSpool('$PROJECT_DIR')"
58
+ fi
59
+ if [ -n "$SPOOL_DRAIN" ]; then
60
+ node -e "$SPOOL_DRAIN" 2>/dev/null
61
+ fi
62
+
46
63
  # ─── LLM Router: Probe Providers ─────────────────────────
47
64
  #
48
65
  # Writes .tlc/.router-state.json with provider availability.
@@ -132,3 +149,16 @@ else
132
149
  echo "LLM Router: ${COUNT} providers available (cached). State at .tlc/.router-state.json."
133
150
  fi
134
151
  fi
152
+
153
+ # ─── Health Check (runs AFTER router probe so provider state is fresh) ───
154
+ HEALTH_MOD=""
155
+ if node -e "require('tlc-claude-code/server/lib/health-check')" 2>/dev/null; then
156
+ HEALTH_MOD="tlc-claude-code/server/lib/health-check"
157
+ elif [ -f "$PROJECT_DIR/server/lib/health-check.js" ]; then
158
+ HEALTH_MOD="$PROJECT_DIR/server/lib/health-check"
159
+ fi
160
+ if [ -n "$HEALTH_MOD" ]; then
161
+ node -e "require('$HEALTH_MOD').runHealthChecks('$PROJECT_DIR').then(r => r.warnings.forEach(w => console.error(w)))" 2>/dev/null
162
+ fi
163
+
164
+ exit 0
package/bin/init.js CHANGED
@@ -9,6 +9,7 @@ const fs = require('fs');
9
9
  const path = require('path');
10
10
 
11
11
  const projectDir = process.cwd();
12
+ const TLC_GITIGNORE_BLOCK = '.tlc/*\n!.tlc/memory/\n.tlc/memory/.local/\n';
12
13
 
13
14
  // Windows batch file content
14
15
  const batContent = `@echo off
@@ -217,8 +218,16 @@ if (fs.existsSync(gitignorePath)) {
217
218
  gitignore += '\n# TLC dev server (local only)\ntlc-start.*\n';
218
219
  updated = true;
219
220
  }
220
- if (!gitignore.includes('.tlc/')) {
221
- gitignore += '.tlc/\n';
221
+ // Remove legacy ".tlc/" ignore that blocks team memory in upgraded repos
222
+ if (gitignore.includes('.tlc/') && !gitignore.includes('.tlc/*')) {
223
+ gitignore = gitignore.replace(/^\.tlc\/\s*$/gm, '');
224
+ updated = true;
225
+ }
226
+ if (!gitignore.includes('.tlc/*') || !gitignore.includes('!.tlc/memory/') || !gitignore.includes('.tlc/memory/.local/')) {
227
+ if (!gitignore.endsWith('\n')) {
228
+ gitignore += '\n';
229
+ }
230
+ gitignore += TLC_GITIGNORE_BLOCK;
222
231
  updated = true;
223
232
  }
224
233
  if (updated) {
@@ -226,7 +235,7 @@ if (fs.existsSync(gitignorePath)) {
226
235
  console.log('[TLC] Updated .gitignore');
227
236
  }
228
237
  } else {
229
- fs.writeFileSync(gitignorePath, '# TLC dev server (local only)\ntlc-start.*\n.tlc/\n');
238
+ fs.writeFileSync(gitignorePath, '# TLC dev server (local only)\ntlc-start.*\n' + TLC_GITIGNORE_BLOCK);
230
239
  console.log('[TLC] Created .gitignore');
231
240
  }
232
241
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tlc-claude-code",
3
- "version": "2.4.3",
3
+ "version": "2.4.5",
4
4
  "description": "TLC - Test Led Coding for Claude Code",
5
5
  "bin": {
6
6
  "tlc-claude-code": "./bin/install.js",