@sixfactors-ai/codeloop 0.1.1 → 0.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/README.md +133 -71
- package/dist/commands/install.d.ts +2 -0
- package/dist/commands/install.js +125 -0
- package/dist/commands/install.js.map +1 -0
- package/dist/commands/list.d.ts +2 -0
- package/dist/commands/list.js +35 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/commands/login.d.ts +2 -0
- package/dist/commands/login.js +77 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/publish.d.ts +2 -0
- package/dist/commands/publish.js +125 -0
- package/dist/commands/publish.js.map +1 -0
- package/dist/commands/remove.d.ts +2 -0
- package/dist/commands/remove.js +31 -0
- package/dist/commands/remove.js.map +1 -0
- package/dist/commands/search.d.ts +2 -0
- package/dist/commands/search.js +85 -0
- package/dist/commands/search.js.map +1 -0
- package/dist/commands/status.d.ts +1 -0
- package/dist/commands/status.js +85 -11
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/update.js +10 -22
- package/dist/commands/update.js.map +1 -1
- package/dist/commands/watch.d.ts +6 -0
- package/dist/commands/watch.js +111 -0
- package/dist/commands/watch.js.map +1 -0
- package/dist/index.js +17 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/__tests__/scaffold.test.js +24 -0
- package/dist/lib/__tests__/scaffold.test.js.map +1 -1
- package/dist/lib/__tests__/smoke.test.js +41 -3
- package/dist/lib/__tests__/smoke.test.js.map +1 -1
- package/dist/lib/__tests__/validate-config.test.d.ts +1 -0
- package/dist/lib/__tests__/validate-config.test.js +109 -0
- package/dist/lib/__tests__/validate-config.test.js.map +1 -0
- package/dist/lib/scaffold.js +32 -3
- package/dist/lib/scaffold.js.map +1 -1
- package/dist/registry/__tests__/installer.test.d.ts +1 -0
- package/dist/registry/__tests__/installer.test.js +122 -0
- package/dist/registry/__tests__/installer.test.js.map +1 -0
- package/dist/registry/__tests__/local-index.test.d.ts +1 -0
- package/dist/registry/__tests__/local-index.test.js +73 -0
- package/dist/registry/__tests__/local-index.test.js.map +1 -0
- package/dist/registry/__tests__/lockfile.test.d.ts +1 -0
- package/dist/registry/__tests__/lockfile.test.js +93 -0
- package/dist/registry/__tests__/lockfile.test.js.map +1 -0
- package/dist/registry/__tests__/security.test.d.ts +1 -0
- package/dist/registry/__tests__/security.test.js +100 -0
- package/dist/registry/__tests__/security.test.js.map +1 -0
- package/dist/registry/__tests__/skill-schema.test.d.ts +1 -0
- package/dist/registry/__tests__/skill-schema.test.js +102 -0
- package/dist/registry/__tests__/skill-schema.test.js.map +1 -0
- package/dist/registry/index.d.ts +7 -0
- package/dist/registry/index.js +8 -0
- package/dist/registry/index.js.map +1 -0
- package/dist/registry/installer.d.ts +30 -0
- package/dist/registry/installer.js +133 -0
- package/dist/registry/installer.js.map +1 -0
- package/dist/registry/local-index.d.ts +32 -0
- package/dist/registry/local-index.js +58 -0
- package/dist/registry/local-index.js.map +1 -0
- package/dist/registry/lockfile.d.ts +40 -0
- package/dist/registry/lockfile.js +85 -0
- package/dist/registry/lockfile.js.map +1 -0
- package/dist/registry/security.d.ts +25 -0
- package/dist/registry/security.js +100 -0
- package/dist/registry/security.js.map +1 -0
- package/dist/registry/skill-schema.d.ts +30 -0
- package/dist/registry/skill-schema.js +95 -0
- package/dist/registry/skill-schema.js.map +1 -0
- package/dist/ui/404.html +1 -1
- package/dist/ui/index.html +1 -1
- package/dist/ui/index.txt +1 -1
- package/dist/watch/__tests__/config.test.d.ts +1 -0
- package/dist/watch/__tests__/config.test.js +53 -0
- package/dist/watch/__tests__/config.test.js.map +1 -0
- package/dist/watch/__tests__/signals.test.d.ts +1 -0
- package/dist/watch/__tests__/signals.test.js +41 -0
- package/dist/watch/__tests__/signals.test.js.map +1 -0
- package/dist/watch/__tests__/triggers.test.d.ts +1 -0
- package/dist/watch/__tests__/triggers.test.js +92 -0
- package/dist/watch/__tests__/triggers.test.js.map +1 -0
- package/dist/watch/index.d.ts +21 -0
- package/dist/watch/index.js +88 -0
- package/dist/watch/index.js.map +1 -0
- package/dist/watch/reporter.d.ts +11 -0
- package/dist/watch/reporter.js +44 -0
- package/dist/watch/reporter.js.map +1 -0
- package/dist/watch/signals.d.ts +38 -0
- package/dist/watch/signals.js +119 -0
- package/dist/watch/signals.js.map +1 -0
- package/dist/watch/triggers.d.ts +10 -0
- package/dist/watch/triggers.js +67 -0
- package/dist/watch/triggers.js.map +1 -0
- package/package.json +3 -2
- package/registry/index.json +106 -0
- package/starters/generic.yaml +37 -0
- package/starters/go.yaml +39 -0
- package/starters/node-typescript.yaml +39 -0
- package/starters/python.yaml +42 -0
- package/templates/commands/debug.md +142 -0
- package/templates/commands/deploy.md +144 -0
- package/templates/commands/design.md +102 -0
- package/templates/commands/manage.md +1 -1
- package/templates/commands/plan.md +4 -3
- package/templates/commands/qa.md +155 -0
- package/templates/commands/ship.md +187 -0
- package/templates/commands/test.md +133 -0
- package/templates/seeds/go-gotchas.md +28 -0
- package/templates/seeds/go-patterns.md +22 -0
- package/templates/seeds/node-typescript-gotchas.md +30 -0
- package/templates/seeds/node-typescript-patterns.md +27 -0
- package/templates/seeds/python-gotchas.md +30 -0
- package/templates/seeds/python-patterns.md +19 -0
- package/templates/seeds/universal-gotchas.md +11 -0
- package/templates/seeds/universal-patterns.md +11 -0
- /package/dist/ui/_next/static/{uiiPJR68HihKQsXtPj0fm → Z7X6LpFN441Kvx1ZYF2iY}/_buildManifest.js +0 -0
- /package/dist/ui/_next/static/{uiiPJR68HihKQsXtPj0fm → Z7X6LpFN441Kvx1ZYF2iY}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Quality gate — run all checks before promoting a task
|
|
3
|
+
argument-hint: [--strict] [--skip-tests]
|
|
4
|
+
allowed-tools: Bash, Read, Write, Edit, Glob, Grep, AskUserQuestion
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
<!-- codeloop-version: 0.2.0 -->
|
|
8
|
+
|
|
9
|
+
# /qa
|
|
10
|
+
|
|
11
|
+
The quality gate between coding and deployment. Runs all configured checks and gates task promotion.
|
|
12
|
+
|
|
13
|
+
> **When to use `/qa` vs `/test`**: `/test` is for quick dev feedback — run a suite, check coverage, iterate. `/qa` is the formal gate — it runs everything (`quality_checks` + `diff_scan` + full test suite + coverage threshold + integrity checks) and sets the `env:local-pass` label that unlocks `/deploy staging`. Use `/qa` when the task is code-complete and ready for promotion.
|
|
14
|
+
|
|
15
|
+
## Usage
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
/qa # Run full QA suite for active task
|
|
19
|
+
/qa --strict # Fail on warnings too (not just errors)
|
|
20
|
+
/qa --skip-tests # Skip test suite (only run static checks)
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Phase 1: Gather Context
|
|
24
|
+
|
|
25
|
+
1. Read `.codeloop/config.yaml` — load `test`, `quality_checks`, `diff_scan` sections
|
|
26
|
+
2. Read `.codeloop/board.json` — find the active task (first `in_progress`, then `planned`)
|
|
27
|
+
3. Get the git diff since the task started:
|
|
28
|
+
- If the task has commits, diff from the first commit to HEAD
|
|
29
|
+
- If no commits yet, diff from HEAD (unstaged + staged changes)
|
|
30
|
+
4. Map changed files to scopes (same logic as `/commit` Phase 1)
|
|
31
|
+
|
|
32
|
+
## Phase 2: Run Checks
|
|
33
|
+
|
|
34
|
+
Execute each check category in order. A failure in any REQUIRED check blocks promotion.
|
|
35
|
+
|
|
36
|
+
### 2.1 Static Analysis
|
|
37
|
+
|
|
38
|
+
Run `quality_checks` from config for active scopes:
|
|
39
|
+
|
|
40
|
+
```yaml
|
|
41
|
+
quality_checks:
|
|
42
|
+
backend:
|
|
43
|
+
- name: "Typecheck"
|
|
44
|
+
command: "npx tsc --noEmit 2>&1 | tail -20"
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Each check: run command, capture output, exit 0 = PASS, non-zero = FAIL.
|
|
48
|
+
|
|
49
|
+
### 2.2 Diff Scan
|
|
50
|
+
|
|
51
|
+
Run `diff_scan` rules from config against the diff (same as `/commit` Phase 1.5):
|
|
52
|
+
|
|
53
|
+
```yaml
|
|
54
|
+
diff_scan:
|
|
55
|
+
- pattern: "console\\.log"
|
|
56
|
+
files: "*.ts,*.js"
|
|
57
|
+
severity: CRITICAL
|
|
58
|
+
message: "console.log in production code"
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### 2.3 Test Suite
|
|
62
|
+
|
|
63
|
+
Run the test command from config (same as `/test`):
|
|
64
|
+
|
|
65
|
+
```yaml
|
|
66
|
+
test:
|
|
67
|
+
command: "npm test"
|
|
68
|
+
coverage_threshold: 80
|
|
69
|
+
integrity_checks: true
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Parse results: pass/fail/skip counts and coverage percentage.
|
|
73
|
+
|
|
74
|
+
If `integrity_checks: true`, scan test output for suspicious patterns:
|
|
75
|
+
- Tests with zero assertions
|
|
76
|
+
- `expect(true).toBe(true)` or equivalent no-op assertions
|
|
77
|
+
- Skipped tests (`.skip`, `@pytest.mark.skip`) — count but don't fail
|
|
78
|
+
- Caught exceptions that are silently swallowed
|
|
79
|
+
|
|
80
|
+
### 2.4 Coverage Gate
|
|
81
|
+
|
|
82
|
+
If `test.coverage_threshold` is set:
|
|
83
|
+
- Coverage >= threshold → PASS
|
|
84
|
+
- Coverage < threshold → FAIL with gap report
|
|
85
|
+
|
|
86
|
+
Pass `--skip-tests` to bypass 2.3 and 2.4 (only run static checks).
|
|
87
|
+
|
|
88
|
+
## Phase 3: Report
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
## QA Report
|
|
92
|
+
|
|
93
|
+
**Task**: t-003 — Add user authentication
|
|
94
|
+
**Scopes**: backend, tests
|
|
95
|
+
**Mode**: standard (--strict would fail on warnings too)
|
|
96
|
+
|
|
97
|
+
### Results
|
|
98
|
+
|
|
99
|
+
| Check | Status | Details |
|
|
100
|
+
|-------|--------|---------|
|
|
101
|
+
| Typecheck | ✓ PASS | Clean |
|
|
102
|
+
| Lint | ✓ PASS | Clean |
|
|
103
|
+
| Diff scan | ⚠ WARN | 1 TODO comment found |
|
|
104
|
+
| Tests | ✓ PASS | 42/42 passed (3.2s) |
|
|
105
|
+
| Coverage | ✓ PASS | 84% (threshold: 80%) |
|
|
106
|
+
| Integrity | ✓ PASS | No suspicious patterns |
|
|
107
|
+
|
|
108
|
+
### Verdict: PASS (1 warning)
|
|
109
|
+
|
|
110
|
+
Ready to promote to review.
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Verdicts:
|
|
114
|
+
- **PASS** — all required checks pass, warnings are informational
|
|
115
|
+
- **WARN** — warnings present but no failures (blocked in `--strict` mode)
|
|
116
|
+
- **FAIL** — one or more required checks failed, promotion blocked
|
|
117
|
+
|
|
118
|
+
### On FAIL
|
|
119
|
+
|
|
120
|
+
Show each failure with details:
|
|
121
|
+
- What failed and why
|
|
122
|
+
- The specific output or pattern that triggered it
|
|
123
|
+
- Suggestion for how to fix
|
|
124
|
+
|
|
125
|
+
Use AskUserQuestion:
|
|
126
|
+
- **Fix issues** — stop, user fixes and re-runs `/qa`
|
|
127
|
+
- **Override and promote** — bypass the gate (adds `qa:override` label)
|
|
128
|
+
- **Abort** — stop entirely
|
|
129
|
+
|
|
130
|
+
### On PASS
|
|
131
|
+
|
|
132
|
+
Continue to Phase 4.
|
|
133
|
+
|
|
134
|
+
## Phase 4: Promote
|
|
135
|
+
|
|
136
|
+
If all checks pass (or user overrides):
|
|
137
|
+
|
|
138
|
+
1. **Board sync** — update the active task:
|
|
139
|
+
- Set status to `review`
|
|
140
|
+
- Add label: `env:local-pass`
|
|
141
|
+
- Add label: `qa:pass` (or `qa:override` if overridden)
|
|
142
|
+
- Remove any existing `qa:fail` label
|
|
143
|
+
- Write updated board
|
|
144
|
+
|
|
145
|
+
2. **History** — append to `.codeloop/test-history.json` if tests were run
|
|
146
|
+
|
|
147
|
+
3. Report: "Task t-003 promoted to review. Ready for `/deploy staging`."
|
|
148
|
+
|
|
149
|
+
## Rules
|
|
150
|
+
|
|
151
|
+
- **The gate is the contract.** `/qa` is what prevents "it works on my machine."
|
|
152
|
+
- **Don't skip tests unless asked.** The `--skip-tests` flag exists for iteration speed, not for cheating.
|
|
153
|
+
- **Warnings are informational in standard mode.** They don't block unless `--strict`.
|
|
154
|
+
- **Override is tracked.** `qa:override` label is visible on the board — it's a code smell, not a secret.
|
|
155
|
+
- **Run before every deploy.** `/deploy` checks for the `env:local-pass` label.
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Close the loop — QA, deploy staging, deploy prod, verify, close task
|
|
3
|
+
argument-hint: [--from-staging] [--dry-run]
|
|
4
|
+
allowed-tools: Bash, Read, Write, Edit, Glob, Grep, AskUserQuestion
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
<!-- codeloop-version: 0.2.0 -->
|
|
8
|
+
|
|
9
|
+
# /ship
|
|
10
|
+
|
|
11
|
+
Orchestrate the full pipeline from QA to production. Takes a task from code-complete to done.
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
/ship # Full pipeline: QA → staging → prod → close
|
|
17
|
+
/ship --from-staging # Skip QA + staging (already staging-verified)
|
|
18
|
+
/ship --dry-run # Show what would happen without executing
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Overview
|
|
22
|
+
|
|
23
|
+
`/ship` chains together existing skills in sequence:
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
/qa → /deploy staging → /deploy prod → /manage close
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Each step is a gate. If any step fails, the pipeline stops and creates a regression task.
|
|
30
|
+
|
|
31
|
+
## Phase 1: Pre-Flight
|
|
32
|
+
|
|
33
|
+
1. Read `.codeloop/config.yaml` — verify `deploy` section exists with non-empty staging and production commands (empty string = not configured → stop)
|
|
34
|
+
2. Read `.codeloop/board.json` — find the active task
|
|
35
|
+
3. If no active task → stop: "No active task found. Use `/plan` to create one."
|
|
36
|
+
4. Check current task labels to determine starting point:
|
|
37
|
+
- Has `env:prod-pass` → "Task already production-verified. Use `/manage close` to finish."
|
|
38
|
+
- Has `env:staging-pass` (or `--from-staging`) → skip to production deploy
|
|
39
|
+
- Has `env:local-pass` → skip to staging deploy
|
|
40
|
+
- No env labels → start from QA
|
|
41
|
+
|
|
42
|
+
5. If `--dry-run`, show the plan and stop:
|
|
43
|
+
```
|
|
44
|
+
## Ship Plan (dry run)
|
|
45
|
+
|
|
46
|
+
**Task**: t-003 — Add user authentication
|
|
47
|
+
**Starting from**: QA (no env labels)
|
|
48
|
+
|
|
49
|
+
Steps:
|
|
50
|
+
1. Run /qa (quality gate)
|
|
51
|
+
2. Deploy to staging + verify
|
|
52
|
+
3. Deploy to production + verify
|
|
53
|
+
4. Close task + archive
|
|
54
|
+
|
|
55
|
+
No actions taken.
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Phase 2: QA Gate
|
|
59
|
+
|
|
60
|
+
Skip if task already has `env:local-pass`.
|
|
61
|
+
|
|
62
|
+
1. Run the same checks as `/qa`:
|
|
63
|
+
- Quality checks for active scopes
|
|
64
|
+
- Diff scan
|
|
65
|
+
- Test suite
|
|
66
|
+
- Coverage gate
|
|
67
|
+
2. If **FAIL** → stop pipeline, report which check failed, create regression task
|
|
68
|
+
3. If **PASS** → add `env:local-pass` label, continue
|
|
69
|
+
|
|
70
|
+
Report progress:
|
|
71
|
+
```
|
|
72
|
+
## Ship Progress
|
|
73
|
+
|
|
74
|
+
[✓] QA gate passed
|
|
75
|
+
[ ] Deploy to staging
|
|
76
|
+
[ ] Deploy to production
|
|
77
|
+
[ ] Close task
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Phase 3: Deploy Staging
|
|
81
|
+
|
|
82
|
+
Skip if task already has `env:staging-pass`.
|
|
83
|
+
|
|
84
|
+
1. Run staging deploy command from config
|
|
85
|
+
2. If deploy fails → stop pipeline, add `env:staging-fail` label, create regression task
|
|
86
|
+
3. Wait 5 seconds, run staging verify command
|
|
87
|
+
4. If verify fails → stop pipeline, add `env:staging-fail` label, create regression task
|
|
88
|
+
5. If both succeed → add `env:staging-pass` label, continue
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
## Ship Progress
|
|
92
|
+
|
|
93
|
+
[✓] QA gate passed
|
|
94
|
+
[✓] Staging deployed + verified
|
|
95
|
+
[ ] Deploy to production
|
|
96
|
+
[ ] Close task
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Phase 4: Deploy Production
|
|
100
|
+
|
|
101
|
+
**Always confirm before production deploy:**
|
|
102
|
+
|
|
103
|
+
```
|
|
104
|
+
## Production Deploy
|
|
105
|
+
|
|
106
|
+
Task t-003 has passed QA and staging verification.
|
|
107
|
+
|
|
108
|
+
Ready to deploy to production?
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Use AskUserQuestion: **Deploy to production** / **Stop here** / **Abort and rollback**
|
|
112
|
+
|
|
113
|
+
If confirmed:
|
|
114
|
+
1. Run production deploy command from config
|
|
115
|
+
2. If deploy fails → stop, add `env:prod-fail` label, create regression task
|
|
116
|
+
3. Wait 5 seconds, run production verify command
|
|
117
|
+
4. If verify fails → stop, add `env:prod-fail` label, create regression task
|
|
118
|
+
5. If both succeed → add `env:prod-pass` label, continue
|
|
119
|
+
|
|
120
|
+
```
|
|
121
|
+
## Ship Progress
|
|
122
|
+
|
|
123
|
+
[✓] QA gate passed
|
|
124
|
+
[✓] Staging deployed + verified
|
|
125
|
+
[✓] Production deployed + verified
|
|
126
|
+
[ ] Close task
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## Phase 5: Close
|
|
130
|
+
|
|
131
|
+
1. Update the board task:
|
|
132
|
+
- Set status to `done`
|
|
133
|
+
- Add label: `shipped`
|
|
134
|
+
2. Archive the task file:
|
|
135
|
+
- Move `tasks/todo.md` to `tasks/done/<task-slug>.md` (create dir if needed)
|
|
136
|
+
3. Final report
|
|
137
|
+
|
|
138
|
+
## Phase 6: Report
|
|
139
|
+
|
|
140
|
+
### On Success
|
|
141
|
+
|
|
142
|
+
```
|
|
143
|
+
## Shipped ✓
|
|
144
|
+
|
|
145
|
+
**Task**: t-003 — Add user authentication
|
|
146
|
+
**Pipeline**: QA → staging → production → done
|
|
147
|
+
|
|
148
|
+
| Stage | Status | Duration |
|
|
149
|
+
|-------|--------|----------|
|
|
150
|
+
| QA | ✓ pass | 12s |
|
|
151
|
+
| Staging | ✓ deployed + verified | 45s |
|
|
152
|
+
| Production | ✓ deployed + verified | 52s |
|
|
153
|
+
|
|
154
|
+
Task archived to `tasks/done/add-user-authentication.md`.
|
|
155
|
+
Board updated: t-003 → done.
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### On Failure
|
|
159
|
+
|
|
160
|
+
```
|
|
161
|
+
## Ship Failed at: staging deploy
|
|
162
|
+
|
|
163
|
+
**Task**: t-003 — Add user authentication
|
|
164
|
+
**Failed step**: Deploy to staging
|
|
165
|
+
**Error**: Exit code 1 — "Error: no instances available"
|
|
166
|
+
|
|
167
|
+
Regression task t-006 created: "Fix: staging deploy failure for auth feature"
|
|
168
|
+
Pipeline stopped. Fix the issue and re-run `/ship --from-staging`.
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## Regression Task Creation
|
|
172
|
+
|
|
173
|
+
When any step fails:
|
|
174
|
+
1. Create a new task on the board:
|
|
175
|
+
- Title: "Fix: <failure summary>"
|
|
176
|
+
- Status: `backlog`
|
|
177
|
+
- Labels: `regression`, `env:<stage>-fail`
|
|
178
|
+
- Description: full error output, which step failed, and the original task reference
|
|
179
|
+
2. The original task stays at its current status (not moved to done)
|
|
180
|
+
|
|
181
|
+
## Rules
|
|
182
|
+
|
|
183
|
+
- **Always confirm production.** Never auto-deploy to production — the human makes the final call.
|
|
184
|
+
- **The pipeline is sequential.** QA → staging → prod. No skipping without explicit flags.
|
|
185
|
+
- **Failure creates tracking.** Every failure gets a regression task — nothing falls through the cracks.
|
|
186
|
+
- **Idempotent resumption.** `/ship` checks labels and skips already-passed stages. Safe to re-run after fixing a failure.
|
|
187
|
+
- **`--from-staging` trusts staging.** Use when you've already verified staging manually or in a previous run.
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Run tests, parse results, track coverage history
|
|
3
|
+
argument-hint: [suite] [--watch] [--coverage]
|
|
4
|
+
allowed-tools: Bash, Read, Write, Edit, Glob, Grep
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
<!-- codeloop-version: 0.2.0 -->
|
|
8
|
+
|
|
9
|
+
# /test
|
|
10
|
+
|
|
11
|
+
Run tests, parse results, and track coverage over time.
|
|
12
|
+
|
|
13
|
+
> **When to use `/test` vs `/qa`**: Use `/test` for quick feedback during development — run a specific suite, check coverage, iterate. Use `/qa` when you're ready to promote a task — it runs the full test suite plus static analysis, coverage gates, and integrity checks, and sets the `env:local-pass` label that unlocks `/deploy`. `/test` does NOT set env labels.
|
|
14
|
+
|
|
15
|
+
## Usage
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
/test # Run default test command from config
|
|
19
|
+
/test <suite> # Run specific test suite or file pattern
|
|
20
|
+
/test --watch # Run in watch mode (if runner supports it)
|
|
21
|
+
/test --coverage # Run with coverage reporting
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Phase 1: Detect
|
|
25
|
+
|
|
26
|
+
1. Read `.codeloop/config.yaml` for the `test` section:
|
|
27
|
+
```yaml
|
|
28
|
+
test:
|
|
29
|
+
command: "npm test"
|
|
30
|
+
coverage_threshold: 80
|
|
31
|
+
```
|
|
32
|
+
2. If no `test.command` configured, auto-detect the test runner:
|
|
33
|
+
- `package.json` with `scripts.test` → use `npm test`
|
|
34
|
+
- `vitest.config.*` → `npx vitest run`
|
|
35
|
+
- `jest.config.*` → `npx jest`
|
|
36
|
+
- `pyproject.toml` with `[tool.pytest]` → `pytest`
|
|
37
|
+
- `go.mod` → `go test ./...`
|
|
38
|
+
- `Cargo.toml` → `cargo test`
|
|
39
|
+
- If nothing detected → ask the user what command to run
|
|
40
|
+
|
|
41
|
+
## Phase 2: Run
|
|
42
|
+
|
|
43
|
+
1. If `<suite>` argument provided, append it to the test command (e.g., `npm test -- src/auth/`)
|
|
44
|
+
2. If `--watch` flag, append watch flag for the detected runner:
|
|
45
|
+
- vitest: already defaults to watch in dev, use `npx vitest`
|
|
46
|
+
- jest: `--watch`
|
|
47
|
+
- pytest: use `pytest-watch` or `ptw`
|
|
48
|
+
- go: no native watch — inform user
|
|
49
|
+
3. If `--coverage` flag, append coverage flag:
|
|
50
|
+
- vitest/jest: `--coverage`
|
|
51
|
+
- pytest: `--cov`
|
|
52
|
+
- go: `-cover`
|
|
53
|
+
4. Run the command, capture stdout and stderr
|
|
54
|
+
|
|
55
|
+
## Phase 3: Parse Results
|
|
56
|
+
|
|
57
|
+
Parse the test runner output to extract:
|
|
58
|
+
|
|
59
|
+
| Field | Example |
|
|
60
|
+
|-------|---------|
|
|
61
|
+
| Total tests | 42 |
|
|
62
|
+
| Passed | 40 |
|
|
63
|
+
| Failed | 1 |
|
|
64
|
+
| Skipped | 1 |
|
|
65
|
+
| Duration | 3.2s |
|
|
66
|
+
| Coverage % | 82% (if available) |
|
|
67
|
+
| Failed test names | List of specific failures |
|
|
68
|
+
|
|
69
|
+
If tests **failed**, show:
|
|
70
|
+
- Each failed test name and file
|
|
71
|
+
- The failure message / assertion error
|
|
72
|
+
- Suggestion: which code is likely broken based on the test file path
|
|
73
|
+
|
|
74
|
+
## Phase 4: Track History
|
|
75
|
+
|
|
76
|
+
Update `.codeloop/test-history.json` (create if not exists):
|
|
77
|
+
|
|
78
|
+
```json
|
|
79
|
+
{
|
|
80
|
+
"runs": [
|
|
81
|
+
{
|
|
82
|
+
"timestamp": "2026-02-21T10:30:00Z",
|
|
83
|
+
"suite": "all",
|
|
84
|
+
"total": 42,
|
|
85
|
+
"passed": 40,
|
|
86
|
+
"failed": 1,
|
|
87
|
+
"skipped": 1,
|
|
88
|
+
"coverage": 82,
|
|
89
|
+
"duration": 3.2,
|
|
90
|
+
"commit": "abc1234"
|
|
91
|
+
}
|
|
92
|
+
]
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Keep the last 50 runs. Older entries are dropped.
|
|
97
|
+
|
|
98
|
+
Include the current git commit SHA (from `git rev-parse --short HEAD`).
|
|
99
|
+
|
|
100
|
+
## Phase 5: Report
|
|
101
|
+
|
|
102
|
+
```
|
|
103
|
+
## Test Results
|
|
104
|
+
|
|
105
|
+
**Suite**: all | **Runner**: vitest
|
|
106
|
+
**Result**: 40/42 passed, 1 failed, 1 skipped (3.2s)
|
|
107
|
+
**Coverage**: 82% (threshold: 80% ✓)
|
|
108
|
+
|
|
109
|
+
### Failures
|
|
110
|
+
- `src/auth/login.test.ts` → "expected 200, got 401"
|
|
111
|
+
|
|
112
|
+
### Trend (last 5 runs)
|
|
113
|
+
42 ████████████████████ 100%
|
|
114
|
+
42 ████████████████████ 100%
|
|
115
|
+
42 ███████████████████░ 95%
|
|
116
|
+
42 ████████████████████ 100%
|
|
117
|
+
42 ███████████████████░ 95% ← current
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Phase 6: Board Sync
|
|
121
|
+
|
|
122
|
+
If `.codeloop/board.json` exists:
|
|
123
|
+
- Find the active task (first `in_progress`, then `planned`)
|
|
124
|
+
- Add label: `tests:pass` or `tests:fail` (replace any existing `tests:*` label)
|
|
125
|
+
- If coverage available, add label: `coverage:82%` (replace any existing `coverage:*` label)
|
|
126
|
+
- Write updated board
|
|
127
|
+
|
|
128
|
+
## Rules
|
|
129
|
+
|
|
130
|
+
- **Never modify test files.** This skill only runs and reports — it doesn't fix tests.
|
|
131
|
+
- **Respect the config.** If `test.command` is set, use it. Don't override with auto-detection.
|
|
132
|
+
- **Track everything.** Even skipped tests matter — a rising skip count is a warning sign.
|
|
133
|
+
- **Show the trend.** History makes patterns visible — one failure vs. recurring failure.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
|
|
2
|
+
## Backend
|
|
3
|
+
|
|
4
|
+
### Goroutine leaks [freq:1]
|
|
5
|
+
Goroutines that block on channels or I/O without exit conditions leak memory. Always ensure goroutines can be cancelled via `context.Context` or channel close signals.
|
|
6
|
+
|
|
7
|
+
### Interface nil check is not what you expect [freq:1]
|
|
8
|
+
A typed nil pointer assigned to an `interface{}` variable is not `== nil`. The interface value has a non-nil type, so the nil check passes. Check the concrete value or use reflection.
|
|
9
|
+
|
|
10
|
+
### Slice append can mutate shared backing array [freq:1]
|
|
11
|
+
`append(slice, elem)` reuses the backing array if capacity allows. Two slices from the same source can interfere with each other. Use `copy()` or full-slice expressions (`s[:len(s):len(s)]`) for safety.
|
|
12
|
+
|
|
13
|
+
### `defer` evaluates arguments immediately [freq:1]
|
|
14
|
+
`defer fmt.Println(x)` captures the current value of `x`, not the value at function exit. Use a closure (`defer func() { fmt.Println(x) }()`) to capture the final value.
|
|
15
|
+
|
|
16
|
+
### Error wrapping needs `%w` for unwrapping [freq:1]
|
|
17
|
+
`fmt.Errorf("failed: %v", err)` creates a new error that breaks `errors.Is()` and `errors.As()`. Use `%w` instead: `fmt.Errorf("failed: %w", err)`.
|
|
18
|
+
|
|
19
|
+
### Forgetting to check `rows.Err()` after iteration [freq:1]
|
|
20
|
+
`database/sql` `rows.Next()` can stop due to an error, not just end-of-results. Always check `rows.Err()` after the loop.
|
|
21
|
+
|
|
22
|
+
## Testing
|
|
23
|
+
|
|
24
|
+
### Table-driven tests need subtests [freq:1]
|
|
25
|
+
Table-driven tests without `t.Run(name, ...)` report failures against the parent test — impossible to tell which case failed. Always use `t.Run`.
|
|
26
|
+
|
|
27
|
+
### Race conditions in tests [freq:1]
|
|
28
|
+
Tests that spawn goroutines without `-race` detection pass locally but fail in CI. Always run `go test -race ./...` in CI.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
|
|
2
|
+
## Backend
|
|
3
|
+
|
|
4
|
+
### Accept interfaces, return structs [confidence:HIGH]
|
|
5
|
+
Function parameters should accept interfaces for flexibility. Return concrete types so callers know exactly what they get. This maximizes testability and minimizes coupling.
|
|
6
|
+
|
|
7
|
+
### Errors are values, handle them immediately [confidence:HIGH]
|
|
8
|
+
Check errors on the line after the call. Don't defer error handling or collect errors for later. Each error gets handled where it occurs.
|
|
9
|
+
|
|
10
|
+
### Context propagation through the call chain [confidence:HIGH]
|
|
11
|
+
Pass `context.Context` as the first parameter through every function that does I/O or could be cancelled. Never store contexts in structs.
|
|
12
|
+
|
|
13
|
+
### Functional options for configuration [confidence:MEDIUM]
|
|
14
|
+
Use `WithTimeout(5*time.Second)` style option functions instead of large config structs. Extensible without breaking existing callers.
|
|
15
|
+
|
|
16
|
+
## Testing
|
|
17
|
+
|
|
18
|
+
### Table-driven tests with subtests [confidence:HIGH]
|
|
19
|
+
Define test cases as a slice of structs. Run each with `t.Run(name, func(t *testing.T) {...})`. Clear, extensible, easy to add new cases.
|
|
20
|
+
|
|
21
|
+
### Test helpers return errors, don't t.Fatal [confidence:MEDIUM]
|
|
22
|
+
Helper functions return errors so the caller decides how to handle them. Only call `t.Fatal` at the test level, not in helpers — it makes helpers reusable.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
|
|
2
|
+
## Backend
|
|
3
|
+
|
|
4
|
+
### Async without await silently drops errors [freq:1]
|
|
5
|
+
Calling an async function without `await` returns a Promise that nobody listens to. If it throws, the error is swallowed. Always `await` or explicitly handle the returned Promise.
|
|
6
|
+
|
|
7
|
+
### `transform: true` converts missing params to NaN [freq:1]
|
|
8
|
+
In NestJS with `class-validator`, `@Query() n?: number` becomes `NaN` when omitted (because `Number(undefined) === NaN`). Always guard with `isNaN()` before using numeric query params.
|
|
9
|
+
|
|
10
|
+
### `.save()` has race conditions [freq:1]
|
|
11
|
+
Mongoose `doc.save()` overwrites the entire document. If two processes load the same doc and save, the last write wins. Use `findByIdAndUpdate()` with `$set` for atomic field updates.
|
|
12
|
+
|
|
13
|
+
### Import order matters with circular dependencies [freq:1]
|
|
14
|
+
TypeScript circular imports cause `undefined` at runtime when the execution order doesn't match expectations. Move shared types to a separate file that both modules import.
|
|
15
|
+
|
|
16
|
+
## Frontend
|
|
17
|
+
|
|
18
|
+
### Stale closures in React effects [freq:1]
|
|
19
|
+
`useEffect` closures capture variable values at render time. If a cleanup function or interval references state, it sees the stale value. Use refs or `useCallback` with proper deps.
|
|
20
|
+
|
|
21
|
+
### `key` prop on list items must be stable [freq:1]
|
|
22
|
+
Using array index as `key` causes incorrect renders when items are reordered or deleted. Use a unique, stable identifier from the data.
|
|
23
|
+
|
|
24
|
+
## Testing
|
|
25
|
+
|
|
26
|
+
### Mock cleanup between tests [freq:1]
|
|
27
|
+
Mocks that aren't restored between tests leak state. Use `afterEach(() => vi.restoreAllMocks())` or `jest.restoreAllMocks()` to prevent flaky cross-test contamination.
|
|
28
|
+
|
|
29
|
+
### Async test assertions need `await` [freq:1]
|
|
30
|
+
`expect(asyncFn()).rejects.toThrow()` without `await` passes even if the assertion fails — the test completes before the Promise resolves. Always `await expect(...)`.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
|
|
2
|
+
## Backend
|
|
3
|
+
|
|
4
|
+
### DTOs at API boundaries [confidence:HIGH]
|
|
5
|
+
Never pass raw database objects to API responses. Use DTOs (Data Transfer Objects) to control exactly which fields are exposed. Prevents accidental data leaks and decouples internal schema from public API.
|
|
6
|
+
|
|
7
|
+
### Dependency injection over direct imports [confidence:HIGH]
|
|
8
|
+
Import the interface, inject the implementation. Makes testing trivial (swap with mocks) and keeps modules loosely coupled.
|
|
9
|
+
|
|
10
|
+
### Index files for module exports [confidence:MEDIUM]
|
|
11
|
+
Each module directory has an `index.ts` that re-exports its public API. Internal files stay private. Consumers import from the directory, not deep paths.
|
|
12
|
+
|
|
13
|
+
## Frontend
|
|
14
|
+
|
|
15
|
+
### Server components by default [confidence:MEDIUM]
|
|
16
|
+
Start with server components. Only add `'use client'` when you need interactivity (event handlers, state, effects). This keeps bundle size small and data fetching simple.
|
|
17
|
+
|
|
18
|
+
### Colocate state with its consumer [confidence:HIGH]
|
|
19
|
+
State lives in the closest common parent of the components that need it. Don't hoist to a global store unless multiple unrelated features need the same data.
|
|
20
|
+
|
|
21
|
+
## Testing
|
|
22
|
+
|
|
23
|
+
### Test behavior, not implementation [confidence:HIGH]
|
|
24
|
+
Tests should verify what the code does, not how it does it. Avoid asserting on internal method calls or implementation details — they break on refactors without catching real bugs.
|
|
25
|
+
|
|
26
|
+
### Arrange-Act-Assert structure [confidence:HIGH]
|
|
27
|
+
Every test has three clear sections: set up the data (Arrange), perform the action (Act), check the result (Assert). Keeps tests readable and focused.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
|
|
2
|
+
## Backend
|
|
3
|
+
|
|
4
|
+
### Mutable default arguments are shared [freq:1]
|
|
5
|
+
`def foo(items=[])` — the default list is created once and shared across all calls. Mutations persist between invocations. Use `items=None` and create inside the function.
|
|
6
|
+
|
|
7
|
+
### `is` vs `==` for comparisons [freq:1]
|
|
8
|
+
`is` checks identity (same object in memory), `==` checks equality (same value). Use `is` only for `None`, `True`, `False`. For everything else, use `==`.
|
|
9
|
+
|
|
10
|
+
### Silent exception swallowing [freq:1]
|
|
11
|
+
Bare `except:` or `except Exception:` with just `pass` hides real bugs. Always log the exception or re-raise. If you must catch broadly, at least log at warning level.
|
|
12
|
+
|
|
13
|
+
### Circular imports cause ImportError at runtime [freq:1]
|
|
14
|
+
Two modules importing each other works in some cases but fails unpredictably depending on import order. Move shared types/interfaces to a third module.
|
|
15
|
+
|
|
16
|
+
### `datetime.now()` uses local timezone [freq:1]
|
|
17
|
+
`datetime.now()` returns naive local time. For servers, always use `datetime.now(timezone.utc)` or `datetime.utcnow()` to avoid timezone confusion.
|
|
18
|
+
|
|
19
|
+
## Database
|
|
20
|
+
|
|
21
|
+
### SQLAlchemy session not committed [freq:1]
|
|
22
|
+
Forgetting `session.commit()` after inserts/updates — changes exist in memory but never reach the database. Use context managers or explicit commit calls.
|
|
23
|
+
|
|
24
|
+
## Testing
|
|
25
|
+
|
|
26
|
+
### Fixtures that share mutable state [freq:1]
|
|
27
|
+
`@pytest.fixture(scope="module")` with mutable objects (dicts, lists) causes test pollution. Use `scope="function"` (default) for isolation, or return fresh copies.
|
|
28
|
+
|
|
29
|
+
### Async test functions need pytest-asyncio [freq:1]
|
|
30
|
+
`async def test_something()` silently passes without actually running unless `pytest-asyncio` is installed and `@pytest.mark.asyncio` is applied.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
|
|
2
|
+
## Backend
|
|
3
|
+
|
|
4
|
+
### Pydantic models at API boundaries [confidence:HIGH]
|
|
5
|
+
Use Pydantic `BaseModel` for request/response validation. Never pass raw dicts through API layers — models enforce schema, generate docs, and catch invalid data early.
|
|
6
|
+
|
|
7
|
+
### Context managers for resource cleanup [confidence:HIGH]
|
|
8
|
+
Database connections, file handles, temporary directories — use `with` statements to guarantee cleanup. Prevents resource leaks on exceptions.
|
|
9
|
+
|
|
10
|
+
### Type hints everywhere [confidence:MEDIUM]
|
|
11
|
+
All function signatures have type hints. Use `mypy` or `pyright` in CI. Catches bugs at static analysis time instead of runtime.
|
|
12
|
+
|
|
13
|
+
## Testing
|
|
14
|
+
|
|
15
|
+
### Factories over fixtures for test data [confidence:MEDIUM]
|
|
16
|
+
Use factory functions (or `factory_boy`) to create test data with sensible defaults. Override only the fields relevant to each test. More readable than complex fixture chains.
|
|
17
|
+
|
|
18
|
+
### Test behavior, not implementation [confidence:HIGH]
|
|
19
|
+
Verify what the function returns or what side effects occur — not which internal methods were called. Implementation-coupled tests break on every refactor.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
|
|
2
|
+
## General
|
|
3
|
+
|
|
4
|
+
### Never commit secrets [freq:1]
|
|
5
|
+
API keys, tokens, passwords in code or config files. Use environment variables or a secrets manager. Even if you "remove it later," git history is forever.
|
|
6
|
+
|
|
7
|
+
### Merge conflicts need manual review [freq:1]
|
|
8
|
+
Auto-resolved merge conflicts (especially in lock files, generated code, or schema files) can silently break things. Always verify the merged result compiles and tests pass.
|
|
9
|
+
|
|
10
|
+
### File permissions in git [freq:1]
|
|
11
|
+
Accidentally committing executable bits (`chmod +x`) on files that don't need it. Check `git diff --stat` for mode changes before committing.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
|
|
2
|
+
## General
|
|
3
|
+
|
|
4
|
+
### Error-first control flow [confidence:HIGH]
|
|
5
|
+
Check error conditions and return/throw early. Keep the happy path at the lowest indentation level. Reduces nesting, improves readability.
|
|
6
|
+
|
|
7
|
+
### One logical change per commit [confidence:HIGH]
|
|
8
|
+
Each commit should be a single, reviewable unit. Mixing refactors with features makes review harder and reverts riskier.
|
|
9
|
+
|
|
10
|
+
### Config in version control [confidence:HIGH]
|
|
11
|
+
All configuration (except secrets) lives in the repo. If a new developer can't `git clone && make dev` and have a working setup, something is missing.
|
/package/dist/ui/_next/static/{uiiPJR68HihKQsXtPj0fm → Z7X6LpFN441Kvx1ZYF2iY}/_buildManifest.js
RENAMED
|
File without changes
|
/package/dist/ui/_next/static/{uiiPJR68HihKQsXtPj0fm → Z7X6LpFN441Kvx1ZYF2iY}/_ssgManifest.js
RENAMED
|
File without changes
|