You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
onboard: use offload collect for vitest duplicate name verification
Move the vitest duplicate check from Step 2 (manual npx vitest list)
to new Step 5 (after offload.toml creation) using offload collect.
The agent now iterates on offload collect until all duplicate
space-separated test names are resolved.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: skills/offload-onboard/SKILL.md
+53-13Lines changed: 53 additions & 13 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -19,7 +19,7 @@ Investigate how the repository runs its tests:
19
19
2. Look for existing CI workflows (`.github/workflows/`, `.gitlab-ci.yml`, etc.) to see how tests are currently invoked
20
20
3. Look for test directories: `tests/`, `test/`, `**/test_*.py`, `**/*_test.go`, `src/**/tests/`, etc.
21
21
4. Determine:
22
-
-**Framework**: `pytest`, `cargo`, or `default` (generic)
22
+
-**Framework**: `pytest`, `cargo`, `vitest`, or `default` (generic)
23
23
-**Test paths**: Where tests live (e.g. `["tests/"]`, `["src/"]`)
24
24
-**Python runner**: If pytest, determine if the project uses `uv`, `poetry`, `pip`, or plain `python`
25
25
-**Extra args**: Any special invocation needed (e.g. `["run", "--group", "test"]` for uv with dependency groups)
@@ -176,7 +176,31 @@ Configuration reference for fields used above:
176
176
-`retry_count`: Number of retries for failed tests (0 = no retries, 1 = catches transient failures)
177
177
-`filters`: Filter string passed to the framework during discovery (e.g. `-m 'not slow'`)
178
178
179
-
### Step 5: Add JUnit ID Normalization (pytest only)
179
+
### Step 5: Verify Vitest Test Discovery (vitest only)
180
+
181
+
**Skip this step if the framework is not `vitest`.**
182
+
183
+
Offload's vitest integration uses `--testNamePattern` to select specific tests for parallel execution. This flag matches tests by their **space-separated** describe/test chain — not by file path. When two tests in different files share the same space-separated name, Offload cannot distinguish them and **will error during discovery**, blocking all test execution.
184
+
185
+
Run `offload collect` to verify that test discovery works:
186
+
187
+
```bash
188
+
offload collect
189
+
```
190
+
191
+
If Offload reports **"Duplicate test names found (space-separated)"**, stop and present the duplicates to the user. Explain:
192
+
193
+
> Offload cannot run vitest tests that share the same space-separated name across different files. This is a requirement of Offload's `--testNamePattern`-based test selection — without unique names, Offload will error during test discovery and no tests will run.
194
+
195
+
Then ask: **"Would you like me to deduplicate these test names by making them more descriptive? This typically involves wrapping tests in uniquely named `describe()` blocks or renaming `test()`/`it()` calls to include more context."**
196
+
197
+
If the user agrees, rename the tests to make the space-separated names unique. Prefer wrapping in descriptive `describe()` blocks over renaming individual tests, as this preserves the existing test names while adding disambiguation.
198
+
199
+
After making changes, run `offload collect` again. **Repeat until `offload collect` succeeds with no duplicate name errors.**
200
+
201
+
If the user declines deduplication, **do not proceed with Offload onboarding** — inform them that Offload's vitest integration cannot function with duplicate test names and they will need to resolve this before onboarding can continue.
202
+
203
+
### Step 6: Add JUnit ID Normalization (pytest only)
180
204
181
205
**Skip this step if the framework is not `pytest`.**
Ensure imports (`os`, `pytest`) are not duplicated if the file already has them.
254
278
255
-
### Step 6: Create Local Invocation Script
279
+
### Step 7: Create Local Invocation Script
256
280
257
281
Create `scripts/offload-tests.sh`:
258
282
@@ -281,7 +305,7 @@ The `--copy-dir` flag tells Offload to bake the local directory into the sandbox
281
305
282
306
If the project uses a Makefile, justfile, or Taskfile instead of scripts/, add the invocation there instead to be consistent with existing practice.
283
307
284
-
### Step 7: Update .gitignore
308
+
### Step 8: Update .gitignore
285
309
286
310
Append Offload artifacts to `.gitignore`:
287
311
@@ -292,15 +316,31 @@ test-results/
292
316
293
317
NOTE: `.offload-image-cache` should be checked in to git — it tracks the base image ID and speeds up subsequent runs. Do not confuse `.gitignore` (which controls what git tracks) with `.dockerignore` (which controls what gets copied into the sandbox image). The `.dockerignore` is only created if needed during troubleshooting — see the Troubleshooting section.
294
318
295
-
### Step 8: Run Offload Locally and Verify
319
+
### Step 9: Run Offload Locally and Verify
296
320
297
321
Install offload if not already present:
298
322
299
323
```bash
300
324
cargo install offload@0.5.0
301
325
```
302
326
303
-
Run the tests using the invocation script from Step 6:
327
+
Run the tests using the invocation script from Step 7:
328
+
329
+
**First, verify test discovery with `offload collect`:**
330
+
331
+
```bash
332
+
offload collect
333
+
```
334
+
335
+
This runs test discovery locally without creating sandboxes or executing tests. Fix any errors until `offload collect` succeeds and lists the expected tests. Common issues:
336
+
337
+
1.**"No tests discovered"**: Check that `paths` in `offload.toml` points to the correct test directories and the framework command is correct.
338
+
2.**"Duplicate test names found"** (vitest): Duplicate space-separated test names exist. Return to Step 5 and resolve them.
339
+
3.**Discovery command failed**: The framework tool (`pytest`, `cargo nextest`, `npx vitest`) is not installed or not on PATH.
340
+
341
+
Do not proceed to execution until `offload collect` lists the expected tests.
342
+
343
+
**Then, run the full test suite:**
304
344
305
345
```bash
306
346
./scripts/offload-tests.sh
@@ -315,7 +355,7 @@ Run the tests using the invocation script from Step 6:
315
355
316
356
Do not proceed to optimization until all tests pass.
317
357
318
-
### Step 9: Optimize Parallelism
358
+
### Step 10: Optimize Parallelism
319
359
320
360
Run a simple linear search over `max_parallel` to minimize total runtime:
321
361
@@ -328,11 +368,11 @@ The optimal `max_parallel` depends on the number of test files and per-test dura
328
368
329
369
Report the results as a table to the user and set the optimal values in `offload.toml`.
**First, ask the user:** "Would you like to configure Offload as the default test runner for AI agents working in this repository? This requires agents to have access to Modal API credentials."
334
374
335
-
**If the user declines**, skip this step entirely and proceed to Step 11.
375
+
**If the user declines**, skip this step entirely and proceed to Step 12.
336
376
337
377
**If the user agrees**, ensure that future AI agents working in this repository know to use Offload for running tests:
338
378
@@ -365,9 +405,9 @@ Report the results as a table to the user and set the optimal values in `offload
365
405
366
406
6. Preserve the existing tone and formatting of the file. If it uses a digraph, bullet lists, or a specific heading style, match that style. Do not restructure or reformat existing content.
367
407
368
-
### Step 11: Set Up CI Job (if desired)
408
+
### Step 12: Set Up CI Job (if desired)
369
409
370
-
Ask the user if they want to set up a CI job to run Offload tests automatically on push/PR. If they decline, skip Steps 11 and 12.
410
+
Ask the user if they want to set up a CI job to run Offload tests automatically on push/PR. If they decline, skip Steps 12 and 13.
371
411
372
412
If they want CI, detect the CI system from the repository:
373
413
-`.github/workflows/` → GitHub Actions
@@ -444,7 +484,7 @@ jobs:
444
484
445
485
For other CI systems, adapt the same pattern: install Offload + Modal CLI, set Modal secrets as env vars, run `offload run`.
446
486
447
-
### Step 12: Configure CI Secrets
487
+
### Step 13: Configure CI Secrets
448
488
449
489
Tell the user they need to add two repository secrets:
450
490
- `MODAL_TOKEN_ID`: Their Modal API token ID
@@ -505,7 +545,7 @@ node_modules
505
545
|------|---------|
506
546
| `.devcontainer/Dockerfile` (or existing) | Base image for Modal sandboxes |
507
547
| `.dockerignore` | (If needed) Exclude local artifacts from sandbox — see Troubleshooting |
508
-
| `conftest.py` | (pytest only) JUnit ID normalization hook — see Step 5 |
548
+
| `conftest.py` | (pytest only) JUnit ID normalization hook — see Step 6 |
509
549
| `offload.toml` | Offload configuration |
510
550
| `scripts/offload-tests.sh` (or Makefile target) | Local invocation convenience |
0 commit comments