tlc-claude-code 0.6.4 → 0.7.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.md +59 -0
- package/README.md +164 -121
- package/autofix.md +327 -0
- package/bin/install.js +23 -2
- package/bug.md +255 -0
- package/build.md +167 -21
- package/ci.md +414 -0
- package/claim.md +189 -0
- package/config.md +236 -0
- package/deploy.md +516 -0
- package/docs.md +494 -0
- package/edge-cases.md +340 -0
- package/export.md +456 -0
- package/help.md +84 -1
- package/init.md +56 -7
- package/issues.md +376 -0
- package/new-project.md +68 -4
- package/package.json +4 -2
- package/plan.md +15 -1
- package/progress.md +17 -0
- package/quality.md +273 -0
- package/release.md +135 -0
- package/server/dashboard/index.html +708 -0
- package/server/index.js +406 -0
- package/server/lib/plan-parser.js +146 -0
- package/server/lib/project-detector.js +301 -0
- package/server/package.json +19 -0
- package/server.md +742 -0
- package/who.md +151 -0
package/build.md
CHANGED
|
@@ -24,14 +24,63 @@ This is the core TLC command. Tests before code, one task at a time.
|
|
|
24
24
|
|
|
25
25
|
Read all `.planning/phases/{phase}-*-PLAN.md` files for this phase.
|
|
26
26
|
|
|
27
|
+
### Step 1b: Sync and Claim (Multi-User)
|
|
28
|
+
|
|
29
|
+
Before starting work, coordinate with teammates:
|
|
30
|
+
|
|
31
|
+
1. **Pull latest:** `git pull --rebase`
|
|
32
|
+
2. **Get user identity:**
|
|
33
|
+
```bash
|
|
34
|
+
if [ -n "$TLC_USER" ]; then
|
|
35
|
+
user=$TLC_USER
|
|
36
|
+
else
|
|
37
|
+
user=$(git config user.name | tr '[:upper:]' '[:lower:]' | tr ' ' '-')
|
|
38
|
+
fi
|
|
39
|
+
```
|
|
40
|
+
3. **Parse task status:** Read `[>@user]` and `[x@user]` markers from plan
|
|
41
|
+
4. **Show availability:**
|
|
42
|
+
```
|
|
43
|
+
Phase 1 Tasks:
|
|
44
|
+
[x@alice] 1. Create schema (done)
|
|
45
|
+
[ ] 2. Add validation (available)
|
|
46
|
+
[>@bob] 3. Write migrations (bob is working)
|
|
47
|
+
[ ] 4. Integration tests (available)
|
|
48
|
+
|
|
49
|
+
Work on task 2? (Y/n)
|
|
50
|
+
```
|
|
51
|
+
5. **Claim selected task:** Update `[ ]` → `[>@{user}]`
|
|
52
|
+
6. **Commit claim:** `git commit -m "claim: task 2 (@{user})"`
|
|
53
|
+
7. **Push:** Prompt user or auto-push
|
|
54
|
+
|
|
55
|
+
If no markers exist in PLAN.md, skip this step (single-user mode).
|
|
56
|
+
|
|
27
57
|
### Step 2: Detect Test Framework
|
|
28
58
|
|
|
59
|
+
#### Check TLC Config First
|
|
60
|
+
|
|
61
|
+
If `.tlc.json` exists, use configured frameworks:
|
|
62
|
+
|
|
63
|
+
```json
|
|
64
|
+
{
|
|
65
|
+
"testFrameworks": {
|
|
66
|
+
"primary": "mocha",
|
|
67
|
+
"installed": ["mocha", "chai", "sinon", "proxyquire"],
|
|
68
|
+
"run": ["mocha"]
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
#### Auto-Detection (No Config)
|
|
74
|
+
|
|
29
75
|
Check what's already set up:
|
|
76
|
+
- `.tlc.json` → Use configured framework
|
|
77
|
+
- `mocha` in package.json → Mocha (TLC default)
|
|
78
|
+
- `.mocharc.*` or `mocha.opts` → Mocha
|
|
30
79
|
- `vitest.config.*` → Vitest
|
|
31
80
|
- `jest.config.*` → Jest
|
|
32
81
|
- `pytest.ini` or `pyproject.toml` with pytest → pytest
|
|
33
82
|
- `spec/` directory → RSpec
|
|
34
|
-
- None found → Set up
|
|
83
|
+
- None found → Set up mocha stack (TLC default)
|
|
35
84
|
|
|
36
85
|
### Step 3: Plan Tests for Each Task
|
|
37
86
|
|
|
@@ -84,7 +133,49 @@ Follow the project's test patterns. Test names should describe expected behavior
|
|
|
84
133
|
✗ "test login" (too vague)
|
|
85
134
|
```
|
|
86
135
|
|
|
87
|
-
**
|
|
136
|
+
**Mocha/Chai (TLC Default):**
|
|
137
|
+
```javascript
|
|
138
|
+
const { expect } = require('chai')
|
|
139
|
+
const sinon = require('sinon')
|
|
140
|
+
const proxyquire = require('proxyquire')
|
|
141
|
+
|
|
142
|
+
describe('login', () => {
|
|
143
|
+
let login, dbStub
|
|
144
|
+
|
|
145
|
+
beforeEach(() => {
|
|
146
|
+
dbStub = sinon.stub()
|
|
147
|
+
login = proxyquire('../src/auth/login', {
|
|
148
|
+
'./db': { findUser: dbStub }
|
|
149
|
+
})
|
|
150
|
+
})
|
|
151
|
+
|
|
152
|
+
afterEach(() => {
|
|
153
|
+
sinon.restore()
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
it('returns user object for valid credentials', async () => {
|
|
157
|
+
dbStub.resolves({ id: 1, email: 'user@test.com' })
|
|
158
|
+
|
|
159
|
+
const result = await login('user@test.com', 'password123')
|
|
160
|
+
|
|
161
|
+
expect(result.user).to.exist
|
|
162
|
+
expect(result.user.email).to.equal('user@test.com')
|
|
163
|
+
})
|
|
164
|
+
|
|
165
|
+
it('throws AuthError for invalid password', async () => {
|
|
166
|
+
dbStub.resolves(null)
|
|
167
|
+
|
|
168
|
+
try {
|
|
169
|
+
await login('user@test.com', 'wrong')
|
|
170
|
+
expect.fail('Should have thrown')
|
|
171
|
+
} catch (err) {
|
|
172
|
+
expect(err.message).to.equal('Invalid credentials')
|
|
173
|
+
}
|
|
174
|
+
})
|
|
175
|
+
})
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
**Vitest/Jest (Alternative):**
|
|
88
179
|
```typescript
|
|
89
180
|
import { describe, it, expect } from 'vitest'
|
|
90
181
|
import { login } from '../src/auth/login'
|
|
@@ -223,7 +314,15 @@ git add src/auth/login.ts tests/auth/login.test.ts
|
|
|
223
314
|
git commit -m "feat: {task-title} - phase {N}"
|
|
224
315
|
```
|
|
225
316
|
|
|
226
|
-
#### 7e.
|
|
317
|
+
#### 7e. Mark Task Complete (Multi-User)
|
|
318
|
+
|
|
319
|
+
If using multi-user mode (task had `[>@user]` marker):
|
|
320
|
+
|
|
321
|
+
1. Update marker: `[>@{user}]` → `[x@{user}]`
|
|
322
|
+
2. Commit: `git commit -m "complete: task {N} - {title} (@{user})"`
|
|
323
|
+
3. Push to share progress with team
|
|
324
|
+
|
|
325
|
+
#### 7f. Move to next task
|
|
227
326
|
Repeat 7a-7d for each task in the phase.
|
|
228
327
|
|
|
229
328
|
**Critical Rules:**
|
|
@@ -255,31 +354,78 @@ Status: ✅ All tests passing (Green)
|
|
|
255
354
|
{test runner output showing all pass}
|
|
256
355
|
```
|
|
257
356
|
|
|
258
|
-
## Framework Defaults
|
|
357
|
+
## Framework Defaults
|
|
259
358
|
|
|
260
|
-
|
|
359
|
+
### TLC Default: Mocha Stack
|
|
261
360
|
|
|
262
|
-
|
|
263
|
-
|---------------------|-----------|-------|
|
|
264
|
-
| Next.js, React, Vite | Vitest | `npm install -D vitest`, create `vitest.config.ts` |
|
|
265
|
-
| Node.js, Express | Vitest | `npm install -D vitest`, create `vitest.config.ts` |
|
|
266
|
-
| Python, FastAPI, Flask | pytest | `pip install pytest`, create `pytest.ini` |
|
|
267
|
-
| Go | go test | Built-in, create `*_test.go` files |
|
|
268
|
-
| Ruby, Rails | RSpec | `gem install rspec`, `rspec --init` |
|
|
361
|
+
For JavaScript/TypeScript projects, TLC defaults to the mocha ecosystem:
|
|
269
362
|
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
363
|
+
| Library | Purpose | Install |
|
|
364
|
+
|---------|---------|---------|
|
|
365
|
+
| **mocha** | Test runner | `npm install -D mocha` |
|
|
366
|
+
| **chai** | Assertions | `npm install -D chai` |
|
|
367
|
+
| **sinon** | Mocks/stubs/spies | `npm install -D sinon` |
|
|
368
|
+
| **proxyquire** | Module mocking | `npm install -D proxyquire` |
|
|
273
369
|
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
370
|
+
Full setup:
|
|
371
|
+
```bash
|
|
372
|
+
npm install -D mocha chai sinon proxyquire @types/mocha @types/chai @types/sinon
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
Default `.mocharc.json`:
|
|
376
|
+
```json
|
|
377
|
+
{
|
|
378
|
+
"extension": ["js", "ts"],
|
|
379
|
+
"spec": "test/**/*.test.{js,ts}",
|
|
380
|
+
"require": ["ts-node/register"],
|
|
381
|
+
"timeout": 5000
|
|
382
|
+
}
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
Default `package.json` scripts:
|
|
386
|
+
```json
|
|
387
|
+
{
|
|
388
|
+
"scripts": {
|
|
389
|
+
"test": "mocha",
|
|
390
|
+
"test:watch": "mocha --watch"
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
### Alternative Frameworks
|
|
396
|
+
|
|
397
|
+
| Stack | Framework | Setup |
|
|
398
|
+
|-------|-----------|-------|
|
|
399
|
+
| Vite projects | Vitest | `npm install -D vitest` |
|
|
400
|
+
| React/Meta ecosystem | Jest | `npm install -D jest` |
|
|
401
|
+
| Python | pytest | `pip install pytest` |
|
|
402
|
+
| Go | go test | Built-in |
|
|
403
|
+
| Ruby | RSpec | `gem install rspec` |
|
|
404
|
+
|
|
405
|
+
To use an alternative, run `/tlc:config` to configure.
|
|
406
|
+
|
|
407
|
+
### Multi-Framework Support
|
|
408
|
+
|
|
409
|
+
Projects can have multiple test frameworks. Configure in `.tlc.json`:
|
|
410
|
+
|
|
411
|
+
```json
|
|
412
|
+
{
|
|
413
|
+
"testFrameworks": {
|
|
414
|
+
"primary": "mocha",
|
|
415
|
+
"installed": ["mocha", "chai", "sinon", "jest"],
|
|
416
|
+
"run": ["mocha", "jest"]
|
|
278
417
|
},
|
|
279
|
-
|
|
418
|
+
"commands": {
|
|
419
|
+
"mocha": "npx mocha 'test/**/*.test.js'",
|
|
420
|
+
"jest": "npx jest",
|
|
421
|
+
"all": "npm test"
|
|
422
|
+
}
|
|
423
|
+
}
|
|
280
424
|
```
|
|
281
425
|
|
|
282
|
-
|
|
426
|
+
When running tests, TLC will execute all frameworks in the `run` array.
|
|
427
|
+
|
|
428
|
+
Default pytest.ini (Python):
|
|
283
429
|
```ini
|
|
284
430
|
[pytest]
|
|
285
431
|
testpaths = tests
|
package/ci.md
ADDED
|
@@ -0,0 +1,414 @@
|
|
|
1
|
+
# /tlc:ci - CI/CD Integration
|
|
2
|
+
|
|
3
|
+
Generate CI/CD pipeline configuration for your TLC project.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
/tlc:ci [provider]
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Providers: `github`, `gitlab`, `bitbucket`, `azure`, `circle`
|
|
12
|
+
|
|
13
|
+
If no provider specified, auto-detects from git remote.
|
|
14
|
+
|
|
15
|
+
## What This Does
|
|
16
|
+
|
|
17
|
+
1. Detects your CI/CD platform from git remote
|
|
18
|
+
2. Generates appropriate config file
|
|
19
|
+
3. Includes test-first validation
|
|
20
|
+
4. Adds regression test gates
|
|
21
|
+
|
|
22
|
+
## GitHub Actions
|
|
23
|
+
|
|
24
|
+
Creates `.github/workflows/tlc.yml`:
|
|
25
|
+
|
|
26
|
+
```yaml
|
|
27
|
+
name: TLC Pipeline
|
|
28
|
+
|
|
29
|
+
on:
|
|
30
|
+
push:
|
|
31
|
+
branches: [main, develop]
|
|
32
|
+
pull_request:
|
|
33
|
+
branches: [main]
|
|
34
|
+
|
|
35
|
+
jobs:
|
|
36
|
+
test:
|
|
37
|
+
runs-on: ubuntu-latest
|
|
38
|
+
steps:
|
|
39
|
+
- uses: actions/checkout@v4
|
|
40
|
+
|
|
41
|
+
- name: Setup Node.js
|
|
42
|
+
uses: actions/setup-node@v4
|
|
43
|
+
with:
|
|
44
|
+
node-version: '20'
|
|
45
|
+
cache: 'npm'
|
|
46
|
+
|
|
47
|
+
- name: Install dependencies
|
|
48
|
+
run: npm ci
|
|
49
|
+
|
|
50
|
+
- name: Run tests
|
|
51
|
+
run: npm test
|
|
52
|
+
|
|
53
|
+
- name: Upload coverage
|
|
54
|
+
uses: codecov/codecov-action@v4
|
|
55
|
+
if: always()
|
|
56
|
+
|
|
57
|
+
lint:
|
|
58
|
+
runs-on: ubuntu-latest
|
|
59
|
+
steps:
|
|
60
|
+
- uses: actions/checkout@v4
|
|
61
|
+
- uses: actions/setup-node@v4
|
|
62
|
+
with:
|
|
63
|
+
node-version: '20'
|
|
64
|
+
cache: 'npm'
|
|
65
|
+
- run: npm ci
|
|
66
|
+
- run: npm run lint
|
|
67
|
+
|
|
68
|
+
regression:
|
|
69
|
+
runs-on: ubuntu-latest
|
|
70
|
+
needs: [test]
|
|
71
|
+
if: github.event_name == 'pull_request'
|
|
72
|
+
steps:
|
|
73
|
+
- uses: actions/checkout@v4
|
|
74
|
+
with:
|
|
75
|
+
fetch-depth: 0
|
|
76
|
+
|
|
77
|
+
- uses: actions/setup-node@v4
|
|
78
|
+
with:
|
|
79
|
+
node-version: '20'
|
|
80
|
+
cache: 'npm'
|
|
81
|
+
|
|
82
|
+
- run: npm ci
|
|
83
|
+
|
|
84
|
+
- name: Check for untested code
|
|
85
|
+
run: |
|
|
86
|
+
# Get changed files
|
|
87
|
+
CHANGED=$(git diff --name-only origin/main...HEAD | grep -E '\.(ts|js|tsx|jsx)$' | grep -v '\.test\.' || true)
|
|
88
|
+
|
|
89
|
+
if [ -n "$CHANGED" ]; then
|
|
90
|
+
echo "Changed source files:"
|
|
91
|
+
echo "$CHANGED"
|
|
92
|
+
|
|
93
|
+
# Check each has corresponding test
|
|
94
|
+
for file in $CHANGED; do
|
|
95
|
+
testfile="${file%.*}.test.${file##*.}"
|
|
96
|
+
if [ ! -f "$testfile" ]; then
|
|
97
|
+
echo "::warning file=$file::No test file found for $file"
|
|
98
|
+
fi
|
|
99
|
+
done
|
|
100
|
+
fi
|
|
101
|
+
|
|
102
|
+
- name: Run regression tests
|
|
103
|
+
run: npm test -- --coverage
|
|
104
|
+
|
|
105
|
+
- name: Coverage diff
|
|
106
|
+
run: |
|
|
107
|
+
# Compare coverage with base branch
|
|
108
|
+
echo "Coverage report generated"
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## GitLab CI
|
|
112
|
+
|
|
113
|
+
Creates `.gitlab-ci.yml`:
|
|
114
|
+
|
|
115
|
+
```yaml
|
|
116
|
+
stages:
|
|
117
|
+
- test
|
|
118
|
+
- regression
|
|
119
|
+
|
|
120
|
+
default:
|
|
121
|
+
image: node:20
|
|
122
|
+
cache:
|
|
123
|
+
paths:
|
|
124
|
+
- node_modules/
|
|
125
|
+
|
|
126
|
+
test:
|
|
127
|
+
stage: test
|
|
128
|
+
script:
|
|
129
|
+
- npm ci
|
|
130
|
+
- npm test
|
|
131
|
+
coverage: '/Lines\s*:\s*(\d+\.?\d*)%/'
|
|
132
|
+
artifacts:
|
|
133
|
+
reports:
|
|
134
|
+
coverage_report:
|
|
135
|
+
coverage_format: cobertura
|
|
136
|
+
path: coverage/cobertura-coverage.xml
|
|
137
|
+
|
|
138
|
+
lint:
|
|
139
|
+
stage: test
|
|
140
|
+
script:
|
|
141
|
+
- npm ci
|
|
142
|
+
- npm run lint
|
|
143
|
+
allow_failure: true
|
|
144
|
+
|
|
145
|
+
regression:
|
|
146
|
+
stage: regression
|
|
147
|
+
only:
|
|
148
|
+
- merge_requests
|
|
149
|
+
script:
|
|
150
|
+
- npm ci
|
|
151
|
+
- |
|
|
152
|
+
CHANGED=$(git diff --name-only $CI_MERGE_REQUEST_DIFF_BASE_SHA...HEAD | grep -E '\.(ts|js)$' | grep -v '\.test\.' || true)
|
|
153
|
+
if [ -n "$CHANGED" ]; then
|
|
154
|
+
echo "Checking tests for changed files..."
|
|
155
|
+
for file in $CHANGED; do
|
|
156
|
+
testfile="${file%.*}.test.${file##*.}"
|
|
157
|
+
if [ ! -f "$testfile" ]; then
|
|
158
|
+
echo "WARNING: No test file for $file"
|
|
159
|
+
fi
|
|
160
|
+
done
|
|
161
|
+
fi
|
|
162
|
+
- npm test -- --coverage
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
## Bitbucket Pipelines
|
|
166
|
+
|
|
167
|
+
Creates `bitbucket-pipelines.yml`:
|
|
168
|
+
|
|
169
|
+
```yaml
|
|
170
|
+
image: node:20
|
|
171
|
+
|
|
172
|
+
definitions:
|
|
173
|
+
caches:
|
|
174
|
+
npm: ~/.npm
|
|
175
|
+
|
|
176
|
+
pipelines:
|
|
177
|
+
default:
|
|
178
|
+
- step:
|
|
179
|
+
name: Test
|
|
180
|
+
caches:
|
|
181
|
+
- npm
|
|
182
|
+
script:
|
|
183
|
+
- npm ci
|
|
184
|
+
- npm test
|
|
185
|
+
|
|
186
|
+
pull-requests:
|
|
187
|
+
'**':
|
|
188
|
+
- step:
|
|
189
|
+
name: Test
|
|
190
|
+
caches:
|
|
191
|
+
- npm
|
|
192
|
+
script:
|
|
193
|
+
- npm ci
|
|
194
|
+
- npm test
|
|
195
|
+
- step:
|
|
196
|
+
name: Regression Check
|
|
197
|
+
caches:
|
|
198
|
+
- npm
|
|
199
|
+
script:
|
|
200
|
+
- npm ci
|
|
201
|
+
- npm test -- --coverage
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
## Azure Pipelines
|
|
205
|
+
|
|
206
|
+
Creates `azure-pipelines.yml`:
|
|
207
|
+
|
|
208
|
+
```yaml
|
|
209
|
+
trigger:
|
|
210
|
+
- main
|
|
211
|
+
- develop
|
|
212
|
+
|
|
213
|
+
pool:
|
|
214
|
+
vmImage: 'ubuntu-latest'
|
|
215
|
+
|
|
216
|
+
stages:
|
|
217
|
+
- stage: Test
|
|
218
|
+
jobs:
|
|
219
|
+
- job: Test
|
|
220
|
+
steps:
|
|
221
|
+
- task: NodeTool@0
|
|
222
|
+
inputs:
|
|
223
|
+
versionSpec: '20.x'
|
|
224
|
+
|
|
225
|
+
- script: npm ci
|
|
226
|
+
displayName: Install dependencies
|
|
227
|
+
|
|
228
|
+
- script: npm test
|
|
229
|
+
displayName: Run tests
|
|
230
|
+
|
|
231
|
+
- task: PublishCodeCoverageResults@2
|
|
232
|
+
inputs:
|
|
233
|
+
summaryFileLocation: '$(System.DefaultWorkingDirectory)/coverage/cobertura-coverage.xml'
|
|
234
|
+
|
|
235
|
+
- stage: Regression
|
|
236
|
+
condition: eq(variables['Build.Reason'], 'PullRequest')
|
|
237
|
+
jobs:
|
|
238
|
+
- job: Regression
|
|
239
|
+
steps:
|
|
240
|
+
- task: NodeTool@0
|
|
241
|
+
inputs:
|
|
242
|
+
versionSpec: '20.x'
|
|
243
|
+
- script: npm ci
|
|
244
|
+
- script: npm test -- --coverage
|
|
245
|
+
displayName: Regression tests
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
## CircleCI
|
|
249
|
+
|
|
250
|
+
Creates `.circleci/config.yml`:
|
|
251
|
+
|
|
252
|
+
```yaml
|
|
253
|
+
version: 2.1
|
|
254
|
+
|
|
255
|
+
executors:
|
|
256
|
+
node:
|
|
257
|
+
docker:
|
|
258
|
+
- image: cimg/node:20.0
|
|
259
|
+
|
|
260
|
+
jobs:
|
|
261
|
+
test:
|
|
262
|
+
executor: node
|
|
263
|
+
steps:
|
|
264
|
+
- checkout
|
|
265
|
+
- restore_cache:
|
|
266
|
+
keys:
|
|
267
|
+
- npm-{{ checksum "package-lock.json" }}
|
|
268
|
+
- run: npm ci
|
|
269
|
+
- save_cache:
|
|
270
|
+
paths:
|
|
271
|
+
- node_modules
|
|
272
|
+
key: npm-{{ checksum "package-lock.json" }}
|
|
273
|
+
- run: npm test
|
|
274
|
+
- store_test_results:
|
|
275
|
+
path: test-results
|
|
276
|
+
- store_artifacts:
|
|
277
|
+
path: coverage
|
|
278
|
+
|
|
279
|
+
regression:
|
|
280
|
+
executor: node
|
|
281
|
+
steps:
|
|
282
|
+
- checkout
|
|
283
|
+
- restore_cache:
|
|
284
|
+
keys:
|
|
285
|
+
- npm-{{ checksum "package-lock.json" }}
|
|
286
|
+
- run: npm ci
|
|
287
|
+
- run:
|
|
288
|
+
name: Check for untested code
|
|
289
|
+
command: |
|
|
290
|
+
CHANGED=$(git diff --name-only origin/main...HEAD | grep -E '\.(ts|js)$' | grep -v '\.test\.' || true)
|
|
291
|
+
if [ -n "$CHANGED" ]; then
|
|
292
|
+
echo "Changed files: $CHANGED"
|
|
293
|
+
fi
|
|
294
|
+
- run: npm test -- --coverage
|
|
295
|
+
|
|
296
|
+
workflows:
|
|
297
|
+
test-and-deploy:
|
|
298
|
+
jobs:
|
|
299
|
+
- test
|
|
300
|
+
- regression:
|
|
301
|
+
filters:
|
|
302
|
+
branches:
|
|
303
|
+
ignore: main
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
## Regression Test Features
|
|
307
|
+
|
|
308
|
+
### Automatic Detection
|
|
309
|
+
|
|
310
|
+
The CI config includes regression checks that:
|
|
311
|
+
|
|
312
|
+
1. **Identify changed files** in the PR/MR
|
|
313
|
+
2. **Verify test coverage** for changed files
|
|
314
|
+
3. **Run full test suite** to catch regressions
|
|
315
|
+
4. **Report coverage diff** vs base branch
|
|
316
|
+
|
|
317
|
+
### Configuring Regression Behavior
|
|
318
|
+
|
|
319
|
+
In `.tlc.json`:
|
|
320
|
+
|
|
321
|
+
```json
|
|
322
|
+
{
|
|
323
|
+
"ci": {
|
|
324
|
+
"requireTestsForNewFiles": true,
|
|
325
|
+
"coverageThreshold": 80,
|
|
326
|
+
"failOnCoverageDecrease": true,
|
|
327
|
+
"regressionOnPR": true
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
### Coverage Requirements
|
|
333
|
+
|
|
334
|
+
Set minimum coverage in `package.json`:
|
|
335
|
+
|
|
336
|
+
```json
|
|
337
|
+
{
|
|
338
|
+
"jest": {
|
|
339
|
+
"coverageThreshold": {
|
|
340
|
+
"global": {
|
|
341
|
+
"branches": 80,
|
|
342
|
+
"functions": 80,
|
|
343
|
+
"lines": 80,
|
|
344
|
+
"statements": 80
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
Or for mocha with nyc:
|
|
352
|
+
|
|
353
|
+
```json
|
|
354
|
+
{
|
|
355
|
+
"nyc": {
|
|
356
|
+
"check-coverage": true,
|
|
357
|
+
"lines": 80,
|
|
358
|
+
"functions": 80,
|
|
359
|
+
"branches": 80
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
## Import/Merge Regression
|
|
365
|
+
|
|
366
|
+
When importing external code (`/tlc:import-project`), automatically run regression:
|
|
367
|
+
|
|
368
|
+
```
|
|
369
|
+
> /tlc:import-project ../legacy-api
|
|
370
|
+
|
|
371
|
+
Importing legacy-api...
|
|
372
|
+
|
|
373
|
+
Found 47 source files without tests.
|
|
374
|
+
|
|
375
|
+
Running regression tests on merge...
|
|
376
|
+
✓ 23 existing tests pass
|
|
377
|
+
⚠ 12 new files need tests
|
|
378
|
+
|
|
379
|
+
Create tasks for missing tests? (Y/n)
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
## Example Session
|
|
383
|
+
|
|
384
|
+
```
|
|
385
|
+
> /tlc:ci
|
|
386
|
+
|
|
387
|
+
Detecting CI/CD platform...
|
|
388
|
+
Remote: git@github.com:acme/myproject.git
|
|
389
|
+
Platform: GitHub
|
|
390
|
+
|
|
391
|
+
Generating .github/workflows/tlc.yml...
|
|
392
|
+
|
|
393
|
+
Created CI pipeline with:
|
|
394
|
+
✓ Test job (runs on all pushes)
|
|
395
|
+
✓ Lint job (runs on all pushes)
|
|
396
|
+
✓ Regression job (runs on PRs)
|
|
397
|
+
✓ Coverage reporting (Codecov)
|
|
398
|
+
|
|
399
|
+
Commit this file? (Y/n) y
|
|
400
|
+
|
|
401
|
+
Committed: ci: add TLC GitHub Actions pipeline
|
|
402
|
+
|
|
403
|
+
Next steps:
|
|
404
|
+
1. Push to GitHub
|
|
405
|
+
2. Add CODECOV_TOKEN secret (optional)
|
|
406
|
+
3. PRs will now require passing tests
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
## Notes
|
|
410
|
+
|
|
411
|
+
- CI config respects `.tlc.json` settings
|
|
412
|
+
- Coverage thresholds match project config
|
|
413
|
+
- Regression checks are PR-only by default
|
|
414
|
+
- Use `/tlc:ci --dry-run` to preview without creating files
|