tlc-claude-code 2.4.10 → 2.6.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/commands/tlc/autofix.md +34 -1
- package/.claude/commands/tlc/build.md +203 -27
- 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/issues.md +46 -0
- package/.claude/commands/tlc/new-project.md +46 -4
- package/.claude/commands/tlc/plan.md +76 -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 +80 -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 +9 -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/github/config.js +458 -0
- package/server/lib/github/config.test.js +385 -0
- package/server/lib/github/gh-client.js +303 -0
- package/server/lib/github/gh-client.test.js +499 -0
- package/server/lib/github/gh-projects.js +594 -0
- package/server/lib/github/gh-projects.test.js +583 -0
- package/server/lib/github/index.js +19 -0
- package/server/lib/github/plan-sync.js +456 -0
- package/server/lib/github/plan-sync.test.js +805 -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
|
@@ -95,7 +95,40 @@ process.stdout.write(JSON.stringify(result));" 2>/dev/null
|
|
|
95
95
|
- Execute inline (Claude) AND dispatch to CLI models simultaneously
|
|
96
96
|
- Collect and merge results
|
|
97
97
|
|
|
98
|
-
**Override:** Pass `--model <name>` to route this specific run to a different model.
|
|
98
|
+
**Override:** Pass `--model <name>` to route this specific run to a different model.
|
|
99
|
+
|
|
100
|
+
After `resolveRouting` returns, immediately write `.tlc/.autofix-routing-active` with the active provider name from `models[0]` before doing any other autofix work. Remove `.tlc/.autofix-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 autofix instructions inline in this path. Claude acts as the orchestrator for the routed provider run:
|
|
111
|
+
|
|
112
|
+
1. Claude acts as the orchestrator for routed test-failure recovery rather than applying the autofix flow inline.
|
|
113
|
+
2. Gather the failing test context, error output, project conventions, and relevant files before dispatching each fix attempt.
|
|
114
|
+
3. Dispatch focused repair prompts 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 every routed fix before accepting it:
|
|
116
|
+
- Confirm the proposed change addresses the actual failure mode rather than masking symptoms.
|
|
117
|
+
- Confirm the relevant tests were re-run or that the provider clearly identified what still needs verification.
|
|
118
|
+
- Reject speculative or unverified fixes and dispatch a narrower retry using the latest failure data.
|
|
119
|
+
5. Continue the dispatch, verify, and retry loop until the targeted failures are fixed or an explicit blocker is reported.
|
|
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 a routed fix worsens the state or returns partial edits, stop that branch and issue a corrective follow-up with the exact observed regression.
|
|
124
|
+
7. When finished, display the routed autofix result, persist any captured memory, remove `.tlc/.autofix-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 autofix instructions below are the Inline Mode instructions and should be followed unchanged.
|
|
131
|
+
|
|
99
132
|
|
|
100
133
|
## What This Does
|
|
101
134
|
|
|
@@ -96,9 +96,48 @@ process.stdout.write(JSON.stringify(result));" 2>/dev/null
|
|
|
96
96
|
- Execute inline (Claude) AND dispatch each external provider via `dispatch` from `orchestration/cli-dispatch`
|
|
97
97
|
- After each provider completes, capture its output with `captureFromProvider` from `capture`
|
|
98
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
|
|
99
103
|
|
|
100
104
|
**Override:** Pass `--model <name>` to route this specific run to a different model.
|
|
101
105
|
|
|
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
|
+
|
|
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 build instructions inline in this path. Claude acts as the orchestrator for the routed provider run:
|
|
117
|
+
|
|
118
|
+
1. Read the full build plan and break the work into the smallest practical execution slices for Codex-style `exec` dispatches.
|
|
119
|
+
2. For each slice, prepare the exact task context, success criteria, test target, and file scope before dispatch.
|
|
120
|
+
3. Resolve orchestration modules with fallback: try `tlc-claude-code/server/lib/...` first, then `$PROJECT_DIR/server/lib/...`.
|
|
121
|
+
4. Build the full prompt with `buildFullPrompt` from `orchestration/prompt-builder`.
|
|
122
|
+
5. Dispatch through unified CLI routing with `dispatch` from `orchestration/cli-dispatch`.
|
|
123
|
+
6. After each provider response, capture output for memory with `captureFromProvider` from `capture`.
|
|
124
|
+
7. Verify every returned result:
|
|
125
|
+
- Confirm the requested change was actually made.
|
|
126
|
+
- Confirm tests relevant to that slice were run or explain why not.
|
|
127
|
+
- Reject incomplete, unverifiable, or off-plan output.
|
|
128
|
+
8. Handle failures explicitly:
|
|
129
|
+
- 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.
|
|
130
|
+
- If retry still fails, stop and report the exact failure to the user. Do not silently fall back to Claude inline execution.
|
|
131
|
+
- If a dispatched task returns partial or broken work, issue a focused follow-up dispatch for the fix instead of continuing blindly.
|
|
132
|
+
9. Continue dispatch/verify/fix until the routed provider work is complete and validated.
|
|
133
|
+
10. When finished, display the provider output summary, persist captured memory, remove `.tlc/.build-routing-active`, and stop. Do **not** execute Inline Mode instructions afterward.
|
|
134
|
+
|
|
135
|
+
## INLINE MODE
|
|
136
|
+
|
|
137
|
+
Use this mode only when `models[0]` **IS** `claude`.
|
|
138
|
+
|
|
139
|
+
The existing build instructions below are the Inline Mode instructions and should be followed unchanged.
|
|
140
|
+
|
|
102
141
|
## Engineering Standards
|
|
103
142
|
|
|
104
143
|
**Code like a senior engineer with 15+ years experience.** Every line should reflect:
|
|
@@ -276,8 +315,7 @@ This is the core TLC command. Tests before code, one task at a time.
|
|
|
276
315
|
```
|
|
277
316
|
/tlc:build <phase_number>
|
|
278
317
|
/tlc:build <phase_number> --sequential # Force sequential mode
|
|
279
|
-
/tlc:build <phase_number> --model
|
|
280
|
-
/tlc:build <phase_number> --model haiku # Force all agents to use haiku (fast/cheap)
|
|
318
|
+
/tlc:build <phase_number> --model opus # All agents use opus (this is the default)
|
|
281
319
|
/tlc:build <phase_number> --max-turns 30 # Limit agent execution length
|
|
282
320
|
/tlc:build <phase_number> --agents 5 # Limit parallel agents to 5
|
|
283
321
|
```
|
|
@@ -333,7 +371,7 @@ After loading plans, analyze task dependencies and available providers to pick t
|
|
|
333
371
|
|-----------|----------|--------------|
|
|
334
372
|
| 2+ independent tasks, Claude + Codex available, tmux available | **Worktree + Tmux** | Each task gets own git worktree + tmux pane. Claude and Codex work simultaneously. |
|
|
335
373
|
| 2+ independent tasks, Claude + Codex available, no tmux | **Worktree + Background** | Same but without tmux visibility. |
|
|
336
|
-
| 2+ independent tasks, single provider only | **In-process agents** | Agent tool spawns parallel sub-agents (
|
|
374
|
+
| 2+ independent tasks, single provider only | **In-process agents** | Agent tool spawns parallel sub-agents (all opus). |
|
|
337
375
|
| All tasks have dependencies | **Sequential** | One task at a time, in dependency order. |
|
|
338
376
|
| 1 task only | **Sequential** | Just build it. |
|
|
339
377
|
|
|
@@ -359,9 +397,9 @@ Providers: claude (1 available)
|
|
|
359
397
|
Strategy: in-process agents (parallel)
|
|
360
398
|
|
|
361
399
|
Task 1: Create user schema → opus (heavy)
|
|
362
|
-
Task 2: Add validation helpers →
|
|
363
|
-
Task 3: Write migration scripts →
|
|
364
|
-
Task 4: Create seed data →
|
|
400
|
+
Task 2: Add validation helpers → opus (standard)
|
|
401
|
+
Task 3: Write migration scripts → opus (standard)
|
|
402
|
+
Task 4: Create seed data → opus (light)
|
|
365
403
|
|
|
366
404
|
Launching...
|
|
367
405
|
```
|
|
@@ -377,17 +415,18 @@ Strategy: sequential
|
|
|
377
415
|
Starting Task 1...
|
|
378
416
|
```
|
|
379
417
|
|
|
380
|
-
**Model
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
|
385
|
-
|
|
418
|
+
**Model selection (in-process agent mode):**
|
|
419
|
+
|
|
420
|
+
All agents use **opus**. No opus, no opus. Cost is not a concern — quality is.
|
|
421
|
+
|
|
422
|
+
| Task | Model |
|
|
423
|
+
|------|-------|
|
|
424
|
+
| Any | opus |
|
|
386
425
|
|
|
387
426
|
**Provider round-robin (worktree mode):**
|
|
388
427
|
Tasks alternate between available providers. If Claude + Codex are both available, odd tasks go to Claude, even to Codex. Respects router state — never dispatches to unavailable providers.
|
|
389
428
|
|
|
390
|
-
### Step
|
|
429
|
+
### Step 1c: Execute Parallel Build
|
|
391
430
|
|
|
392
431
|
**Worktree + Tmux mode** (multi-provider):
|
|
393
432
|
|
|
@@ -397,9 +436,9 @@ Tasks alternate between available providers. If Claude + Codex are both availabl
|
|
|
397
436
|
Spawning 4 agents in parallel...
|
|
398
437
|
|
|
399
438
|
Agent 1: Task 1 - Create user schema [opus]
|
|
400
|
-
Agent 2: Task 2 - Add validation helpers [
|
|
401
|
-
Agent 3: Task 3 - Write migration scripts [
|
|
402
|
-
Agent 4: Task 4 - Create seed data [
|
|
439
|
+
Agent 2: Task 2 - Add validation helpers [opus]
|
|
440
|
+
Agent 3: Task 3 - Write migration scripts [opus]
|
|
441
|
+
Agent 4: Task 4 - Create seed data [opus]
|
|
403
442
|
|
|
404
443
|
[All agents spawned - working in background]
|
|
405
444
|
```
|
|
@@ -416,9 +455,9 @@ Agent 4: Task 4 - Create seed data [haiku]
|
|
|
416
455
|
|
|
417
456
|
```
|
|
418
457
|
Task(description="Agent 1: Task 1", prompt="...", subagent_type="general-purpose", model="opus", max_turns=50, run_in_background=true)
|
|
419
|
-
Task(description="Agent 2: Task 2", prompt="...", subagent_type="general-purpose", model="
|
|
420
|
-
Task(description="Agent 3: Task 3", prompt="...", subagent_type="general-purpose", model="
|
|
421
|
-
Task(description="Agent 4: Task 4", prompt="...", subagent_type="general-purpose", model="
|
|
458
|
+
Task(description="Agent 2: Task 2", prompt="...", subagent_type="general-purpose", model="opus", max_turns=50, run_in_background=true)
|
|
459
|
+
Task(description="Agent 3: Task 3", prompt="...", subagent_type="general-purpose", model="opus", max_turns=50, run_in_background=true)
|
|
460
|
+
Task(description="Agent 4: Task 4", prompt="...", subagent_type="general-purpose", model="opus", max_turns=50, run_in_background=true)
|
|
422
461
|
```
|
|
423
462
|
|
|
424
463
|
**Live Progress Monitoring (TaskOutput):**
|
|
@@ -449,9 +488,9 @@ Display format:
|
|
|
449
488
|
| Agent | Task | Model | Tests | Phase |
|
|
450
489
|
|-------|------|-------|-------|-------|
|
|
451
490
|
| a1b2c3 | User Schema | opus | 29 ✓ | committed |
|
|
452
|
-
| d4e5f6 | Validation |
|
|
453
|
-
| g7h8i9 | Migrations |
|
|
454
|
-
| j0k1l2 | Seed Data |
|
|
491
|
+
| d4e5f6 | Validation | opus | 18 ✓ | implementing |
|
|
492
|
+
| g7h8i9 | Migrations | opus | - | writing-tests |
|
|
493
|
+
| j0k1l2 | Seed Data | opus | 5 ✓ | committed |
|
|
455
494
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
456
495
|
```
|
|
457
496
|
|
|
@@ -515,7 +554,7 @@ After merge-back:
|
|
|
515
554
|
4. If clean, the integration branch is ready for a single PR to main
|
|
516
555
|
5. Continue to Step 8 (verification)
|
|
517
556
|
|
|
518
|
-
### Step
|
|
557
|
+
### Step 1d: Sync and Claim (Multi-User, Sequential Only)
|
|
519
558
|
|
|
520
559
|
**Note:** Skip this step if using Overdrive mode - agents handle claiming automatically.
|
|
521
560
|
|
|
@@ -547,6 +586,19 @@ Before starting work, coordinate with teammates:
|
|
|
547
586
|
|
|
548
587
|
If no markers exist in PLAN.md, skip this step (single-user mode).
|
|
549
588
|
|
|
589
|
+
### Step 1b: Migration Snapshot
|
|
590
|
+
|
|
591
|
+
Check for migration files in the current diff:
|
|
592
|
+
```bash
|
|
593
|
+
MIGRATION_FILES=$(git diff --name-only main...HEAD | grep -E "prisma/migrations|drizzle/|migrations/.*\.(ts|js|sql)|alembic/versions" | grep -v "\.test\.")
|
|
594
|
+
```
|
|
595
|
+
|
|
596
|
+
If `MIGRATION_FILES` is not empty:
|
|
597
|
+
1. Detect DB connection from `.env` or config
|
|
598
|
+
2. Take snapshot: run `server/lib/scaffolding/snapshot-manager.js takeSnapshot()`
|
|
599
|
+
3. Report: `DB snapshot taken: .tlc/snapshots/{filename}. Run /tlc:restore to rollback if needed.`
|
|
600
|
+
4. If snapshot fails (DB not running): warn but continue build
|
|
601
|
+
|
|
550
602
|
### Step 2: Detect Test Framework
|
|
551
603
|
|
|
552
604
|
#### Check TLC Config First
|
|
@@ -701,7 +753,24 @@ def test_login_raises_for_invalid_password():
|
|
|
701
753
|
login("user@test.com", "wrong")
|
|
702
754
|
```
|
|
703
755
|
|
|
704
|
-
#### 4b.
|
|
756
|
+
#### 4b. Generate E2E Tests
|
|
757
|
+
|
|
758
|
+
After writing the unit test file for the task, generate matching end-to-end coverage from the task's acceptance criteria in `PLAN.md`.
|
|
759
|
+
|
|
760
|
+
Process:
|
|
761
|
+
- Parse acceptance criteria for the current task from `PLAN.md` using `server/lib/e2e/acceptance-parser.js`
|
|
762
|
+
- Detect the existing E2E framework, or scaffold one if missing, using `server/lib/e2e/framework-detector.js`
|
|
763
|
+
- Generate E2E test files for the current task using `server/lib/e2e/test-generator.js`
|
|
764
|
+
- Place generated E2E coverage alongside the task's unit tests in the same red/green workflow
|
|
765
|
+
|
|
766
|
+
Requirements:
|
|
767
|
+
- E2E tests must map directly to acceptance criteria for the current task
|
|
768
|
+
- Generated files must follow the detected or scaffolded framework conventions
|
|
769
|
+
- If no E2E framework exists, scaffold it before generating tests
|
|
770
|
+
- E2E tests should be committed alongside the unit tests for that task
|
|
771
|
+
- Do NOT write implementation code while generating tests
|
|
772
|
+
|
|
773
|
+
#### 4c. Run this test file
|
|
705
774
|
|
|
706
775
|
```bash
|
|
707
776
|
npm test -- tests/auth/login.test.ts # vitest
|
|
@@ -713,16 +782,18 @@ Verify:
|
|
|
713
782
|
- ✅ Tests FAIL (not pass, not skip)
|
|
714
783
|
- ❌ If import errors, add mocks/stubs and retry
|
|
715
784
|
|
|
716
|
-
####
|
|
785
|
+
#### 4d. Commit this test file
|
|
717
786
|
|
|
718
787
|
```bash
|
|
719
788
|
git add tests/auth/login.test.ts
|
|
720
789
|
git commit -m "test: add login tests (red) - phase {N}"
|
|
721
790
|
```
|
|
722
791
|
|
|
723
|
-
|
|
792
|
+
If E2E files were generated for the task, stage and commit them in the same commit as the unit tests.
|
|
724
793
|
|
|
725
|
-
|
|
794
|
+
#### 4e. Move to next task
|
|
795
|
+
|
|
796
|
+
Repeat 4a-4d for each task in the test plan.
|
|
726
797
|
|
|
727
798
|
**Critical Rules:**
|
|
728
799
|
- Tests must be **syntactically valid** and **runnable**
|
|
@@ -787,6 +858,33 @@ Review the task's:
|
|
|
787
858
|
- Acceptance criteria
|
|
788
859
|
- Test cases (now written and failing)
|
|
789
860
|
|
|
861
|
+
#### 7a-gh. GitHub: Mark In Progress
|
|
862
|
+
|
|
863
|
+
If GitHub sync is enabled, update the linked GitHub issue for this task:
|
|
864
|
+
|
|
865
|
+
```bash
|
|
866
|
+
node -e "
|
|
867
|
+
const path = require('path');
|
|
868
|
+
const fs = require('fs');
|
|
869
|
+
const { execSync } = require('child_process');
|
|
870
|
+
let gh;
|
|
871
|
+
try { gh = require('tlc-claude-code/server/lib/github'); }
|
|
872
|
+
catch { gh = require(path.join(process.cwd(), 'server/lib/github')); }
|
|
873
|
+
try {
|
|
874
|
+
const cfg = gh.loadGitHubConfig(process.cwd(), { fs }).config;
|
|
875
|
+
if (!cfg) process.exit(0);
|
|
876
|
+
const exec = (cmd) => execSync(cmd, { encoding: 'utf-8', stdio: ['pipe','pipe','pipe'] });
|
|
877
|
+
const user = execSync('git config user.name', { encoding: 'utf-8' }).trim();
|
|
878
|
+
const issueNumber = process.argv[1];
|
|
879
|
+
if (issueNumber) {
|
|
880
|
+
gh.assignIssue({ owner: cfg.owner, repo: cfg.repo, number: Number(issueNumber), assignees: [user], exec });
|
|
881
|
+
}
|
|
882
|
+
} catch (e) { console.error('[TLC] GitHub status update failed:', e.message); }
|
|
883
|
+
" "{issue_number}" 2>/dev/null
|
|
884
|
+
```
|
|
885
|
+
|
|
886
|
+
If no issue is linked to this task, skip silently. Failures warn but never block.
|
|
887
|
+
|
|
790
888
|
#### 7b. Implement the code
|
|
791
889
|
Write the minimum code needed to pass the tests:
|
|
792
890
|
- Create files specified in the task
|
|
@@ -828,6 +926,35 @@ This keeps the plan file as the single source of truth for task status. Do NOT w
|
|
|
828
926
|
|
|
829
927
|
If in multi-user mode, also push to share progress with team.
|
|
830
928
|
|
|
929
|
+
#### 7e-gh. GitHub: Mark Done
|
|
930
|
+
|
|
931
|
+
If GitHub sync is enabled, update the linked issue status after marking the task `[x]`:
|
|
932
|
+
|
|
933
|
+
```bash
|
|
934
|
+
node -e "
|
|
935
|
+
const path = require('path');
|
|
936
|
+
const fs = require('fs');
|
|
937
|
+
const { execSync } = require('child_process');
|
|
938
|
+
let gh;
|
|
939
|
+
try { gh = require('tlc-claude-code/server/lib/github'); }
|
|
940
|
+
catch { gh = require(path.join(process.cwd(), 'server/lib/github')); }
|
|
941
|
+
try {
|
|
942
|
+
const cfg = gh.loadGitHubConfig(process.cwd(), { fs }).config;
|
|
943
|
+
if (!cfg) process.exit(0);
|
|
944
|
+
const planPath = process.argv[1];
|
|
945
|
+
const r = gh.updateTaskStatuses({
|
|
946
|
+
planPath,
|
|
947
|
+
config: cfg,
|
|
948
|
+
ghClient: { exec: (cmd) => execSync(cmd, { encoding: 'utf-8', stdio: ['pipe','pipe','pipe'] }) },
|
|
949
|
+
fs
|
|
950
|
+
});
|
|
951
|
+
console.log(JSON.stringify(r));
|
|
952
|
+
} catch (e) { console.error('[TLC] GitHub status sync failed:', e.message); }
|
|
953
|
+
" ".planning/phases/{N}-PLAN.md" 2>/dev/null
|
|
954
|
+
```
|
|
955
|
+
|
|
956
|
+
Failures warn but never block the build.
|
|
957
|
+
|
|
831
958
|
#### 7f. Move to next task
|
|
832
959
|
Repeat 7a-7e for each task in the phase.
|
|
833
960
|
|
|
@@ -991,6 +1118,14 @@ After user approval:
|
|
|
991
1118
|
# Push branch
|
|
992
1119
|
git push -u origin "$branchName"
|
|
993
1120
|
|
|
1121
|
+
# Warn if the PR will have no automated CI checks
|
|
1122
|
+
node -e "const fs = require('fs');
|
|
1123
|
+
const { detectCI } = require('./server/lib/scaffolding/ci-detector.js');
|
|
1124
|
+
const result = detectCI({ projectDir: process.cwd(), fs });
|
|
1125
|
+
if (result.platform === 'none') {
|
|
1126
|
+
console.warn('No CI configured. PR will not have automated checks. Run /tlc:ci to set up.');
|
|
1127
|
+
}" 2>/dev/null
|
|
1128
|
+
|
|
994
1129
|
# Create PR with phase summary
|
|
995
1130
|
gh pr create \
|
|
996
1131
|
--base "$mainBranch" \
|
|
@@ -1008,6 +1143,47 @@ gh pr create \
|
|
|
1008
1143
|
{test runner summary}"
|
|
1009
1144
|
```
|
|
1010
1145
|
|
|
1146
|
+
**Merge strategy:** When merging PRs, ALWAYS use `--merge` (not `--squash`):
|
|
1147
|
+
```bash
|
|
1148
|
+
gh pr merge <number> --merge
|
|
1149
|
+
```
|
|
1150
|
+
- `--merge` preserves commit history and shows the correct PR title
|
|
1151
|
+
- `--squash` only when the user explicitly asks for it (messy WIP branches)
|
|
1152
|
+
- Sync PRs (dev → test, test → main) MUST use `--merge` — never squash a sync
|
|
1153
|
+
|
|
1154
|
+
#### Step 11-gh: GitHub: Link PR to Project
|
|
1155
|
+
|
|
1156
|
+
If GitHub sync is enabled, after the PR is created:
|
|
1157
|
+
|
|
1158
|
+
1. Add `Closes #N` references to the PR body for all completed task issues (parse `<!-- gh:N -->` markers from PLAN.md)
|
|
1159
|
+
2. Add the PR to the GitHub project board if configured
|
|
1160
|
+
3. Set the phase issue Status to "In review"
|
|
1161
|
+
|
|
1162
|
+
```bash
|
|
1163
|
+
node -e "
|
|
1164
|
+
const path = require('path');
|
|
1165
|
+
const fs = require('fs');
|
|
1166
|
+
const { execSync } = require('child_process');
|
|
1167
|
+
let gh;
|
|
1168
|
+
try { gh = require('tlc-claude-code/server/lib/github'); }
|
|
1169
|
+
catch { gh = require(path.join(process.cwd(), 'server/lib/github')); }
|
|
1170
|
+
try {
|
|
1171
|
+
const cfg = gh.loadGitHubConfig(process.cwd(), { fs }).config;
|
|
1172
|
+
if (!cfg) process.exit(0);
|
|
1173
|
+
const exec = (cmd) => execSync(cmd, { encoding: 'utf-8', stdio: ['pipe','pipe','pipe'] });
|
|
1174
|
+
const prNumber = Number(process.argv[1]);
|
|
1175
|
+
const planPath = process.argv[2];
|
|
1176
|
+
const content = fs.readFileSync(planPath, 'utf-8');
|
|
1177
|
+
const issueRefs = [...content.matchAll(/<!-- gh:(\d+) -->/g)].map(m => Number(m[1]));
|
|
1178
|
+
if (issueRefs.length > 0) {
|
|
1179
|
+
gh.linkPrToIssue({ ...cfg, prNumber, issueNumbers: issueRefs, exec });
|
|
1180
|
+
}
|
|
1181
|
+
} catch (e) { console.error('[TLC] GitHub PR link failed:', e.message); }
|
|
1182
|
+
" "{pr_number}" ".planning/phases/{N}-PLAN.md" 2>/dev/null
|
|
1183
|
+
```
|
|
1184
|
+
|
|
1185
|
+
Failures warn but never block.
|
|
1186
|
+
|
|
1011
1187
|
**The PR is the deliverable, not the commits.** CI runs on the PR. Merge when green.
|
|
1012
1188
|
|
|
1013
1189
|
**If the user has already been working on main** (e.g., first time using branching): push main directly but note that future phases MUST use branches.
|