rivet-dev/driver-test-runner
Methodically run the RivetKit driver test suite file by file across the native (NAPI) and wasm runtimes, tracking progress in ~/.agents/notes/driver-test-progress.md. Use when you need to validate the driver test suite after changes, bring up a new driver, or debug test failures systematically.
npx skills add https://github.com/rivet-dev/rivet --skill driver-test-runner
Methodically run the RivetKit driver test suite one file group at a time across the native (NAPI) and wasm runtimes, tracking progress in ~/.agents/notes/driver-test-progress.md.
The skill accepts optional arguments:
reset — Clear progress and start from the beginning.resume — Pick up from where we left off (default behavior).only <file> — Run only a specific test file group (e.g., only actor-conn).from <file> — Start from a specific file group, skipping earlier ones.runtime <native|wasm|both> — Which runtime(s) to run (default: both).encoding <bare|cbor|json> — Override encoding (default: bare).registry <static> — Override registry type (default: static).The driver suite runs over a runtime × SQLite-backend × encoding matrix defined in rivetkit-typescript/packages/rivetkit/tests/driver/shared-matrix.ts. The runtime dimension has two values:
native — NAPI bindings (@rivetkit/rivetkit-napi). Pairs with sqlite=local for the primary native driver pass.wasm — WebAssembly bindings (@rivetkit/rivetkit-wasm). Wasm cannot use local SQLite; it must pair with sqlite=remote (executes SQL through the engine over the wire).The skill defaults to running each test file twice: once on native/local and once on wasm/remote, each at encoding=bare. A file is checked off only when both runtimes pass.
The test harness does not read environment variables for matrix selection. Always select matrix cells with Vitest -t using the full inner describe name: runtime (<runtime>) / sqlite (<backend>) / encoding (<encoding>).
If a RivetKit driver test fails because native or Rust behavior diverges from the old runtime, do this before inventing a separate debugging workflow:
rivetkit-typescript/packages/rivetkit driver tests as the primary oracle.feat/sqlite-vfs-v2 using git show or git diff.If a test passes on native but fails on wasm (or vice versa), the divergence is in the runtime adapter (packages/rivetkit/src/registry/wasm-runtime.ts or napi-runtime.ts) or in rivetkit-core's wasm/native feature gates — not in user-facing actor code.
Native unit tests are allowed only after the failing TypeScript driver test has reproduced the bug and after the fix is validated against that same TypeScript driver test.
Both runtime adapters need their build outputs on disk before the suite can load them. A fresh checkout, a Rust edit under packages/rivetkit-napi / packages/sqlite-native, or any change under packages/rivetkit-wasm invalidates these.
NAPI (@rivetkit/rivetkit-napi) — produces a platform-specific .node next to package.json:
ls rivetkit-typescript/packages/rivetkit-napi/*.node 2>/dev/null
# missing? rebuild:
pnpm --filter @rivetkit/rivetkit-napi run build:force
After Rust changes, always use build:force (per rivetkit-typescript/CLAUDE.md); the non-:force variant can skip the rebuild and leave the suite running against a stale .node.
Wasm (@rivetkit/rivetkit-wasm) — produces packages/rivetkit-wasm/pkg/rivetkit_wasm.{js,wasm,d.ts}:
ls rivetkit-typescript/packages/rivetkit-wasm/pkg/rivetkit_wasm.wasm 2>/dev/null
# missing? rebuild (uses the package-pinned wasm-pack, do not use npx):
pnpm --filter @rivetkit/rivetkit-wasm run build
Skip the wasm build only if runtime is native and you're certain the wasm fixture path won't be loaded. With the default runtime=both, the wasm build is always required.
Before running any tests, check if the RocksDB engine is already running:
curl -sf http://127.0.0.1:6420/health || echo "NOT RUNNING"
If it's not running, start it:
./scripts/run/engine-rocksdb.sh >/tmp/rivet-engine-startup.log 2>&1 &
Wait for health check to pass (poll every 2 seconds, up to 60 seconds).
The progress file lives at ~/.agents/notes/driver-test-progress.md. If it doesn't exist or reset was passed, create it with the template below. If it exists and resume was passed, read it and pick up from the first file with an unchecked runtime box.
Each file row gets two checkboxes — one for each runtime. Check off a runtime independently as soon as it passes, and only advance to the next file when both runtimes for the current file are checked.
Progress file template:
# Driver Test Suite Progress
Started: <timestamp>
Config: registry (static), encoding (bare), runtimes (native, wasm)
Each row: `[native] [wasm] <file> | <suite description>`
## Fast Tests
- [ ] [ ] manager-driver | Manager Driver Tests
- [ ] [ ] actor-conn | Actor Connection Tests
- [ ] [ ] actor-conn-state | Actor Connection State Tests
- [ ] [ ] conn-error-serialization | Connection Error Serialization Tests
- [ ] [ ] actor-destroy | Actor Destroy Tests
- [ ] [ ] request-access | Request Access in Lifecycle Hooks
- [ ] [ ] actor-handle | Actor Handle Tests
- [ ] [ ] action-features | Action Features Tests
- [ ] [ ] access-control | access control
- [ ] [ ] actor-vars | Actor Variables
- [ ] [ ] actor-metadata | Actor Metadata Tests
- [ ] [ ] actor-onstatechange | Actor State Change Tests
- [ ] [ ] actor-db | Actor Database
- [ ] [ ] actor-db-raw | Actor Database Raw Tests
- [ ] [ ] actor-db-init-order | Actor Db Init Order
- [ ] [ ] actor-workflow | Actor Workflow Tests
- [ ] [ ] actor-error-handling | Actor Error Handling Tests
- [ ] [ ] actor-queue | Actor Queue Tests
- [ ] [ ] actor-kv | Actor KV Tests
- [ ] [ ] actor-stateless | Actor Stateless Tests
- [ ] [ ] raw-http | raw http
- [ ] [ ] raw-http-request-properties | raw http request properties
- [ ] [ ] raw-websocket | raw websocket
- [ ] [ ] actor-inspector | Actor Inspector Tests
- [ ] [ ] gateway-query-url | Gateway Query URL Tests
- [ ] [ ] actor-db-pragma-migration | Actor Database Pragma Migration
- [ ] [ ] actor-state-zod-coercion | Actor State Zod Coercion
- [ ] [ ] actor-conn-status | Connection Status Changes
- [ ] [ ] gateway-routing | Gateway Routing
- [ ] [ ] lifecycle-hooks | Lifecycle Hooks
- [ ] [ ] serverless-handler | Serverless Handler Tests
## Slow Tests
- [ ] [ ] actor-state | Actor State Tests
- [ ] [ ] actor-save-state | Actor Save State Tests
- [ ] [ ] actor-schedule | Actor Schedule Tests
- [ ] [ ] actor-sleep | Actor Sleep Tests
- [ ] [ ] actor-sleep-db | Actor Sleep Database Tests
- [ ] [ ] actor-lifecycle | Actor Lifecycle Tests
- [ ] [ ] actor-conn-hibernation | Actor Connection Hibernation Tests
- [ ] [ ] actor-run | Actor Run Tests
- [ ] [ ] hibernatable-websocket-protocol | hibernatable websocket protocol
- [ ] [ ] actor-db-stress | Actor Database Stress Tests
## Excluded
- [ ] [ ] actor-agent-os | Actor agentOS Tests (skip unless explicitly requested)
## Log
For each unchecked row in order, run the runtimes selected by the runtime arg (default both). For each runtime:
a) Pick the runtime/sqlite pair:
| Runtime | SQLite backend |
|---------|----------------|
| native | local |
| wasm | remote |
b) Build the filter command:
Each suite lives in its own file under rivetkit-typescript/packages/rivetkit/tests/driver/<file>.test.ts. The describe block nesting is:
<Outer Suite> > static registry > runtime (<runtime>) / sqlite (<backend>) / encoding (<encoding>) > <Suite Description>
Always use Vitest -t for driver matrix cells. Include runtime, SQLite backend, and encoding in the pattern so a partial match does not accidentally select another matrix cell.
Base command (native):
cd rivetkit-typescript/packages/rivetkit && \
pnpm test tests/driver/<FILE>.test.ts \
-t "runtime \(native\) / sqlite \(local\) / encoding \(bare\)" \
> /tmp/driver-test-current.log 2>&1
echo "EXIT: $?"
Base command (wasm):
cd rivetkit-typescript/packages/rivetkit && \
pnpm test tests/driver/<FILE>.test.ts \
-t "runtime \(wasm\) / sqlite \(remote\) / encoding \(bare\)" \
> /tmp/driver-test-current.log 2>&1
echo "EXIT: $?"
Replace <FILE> with the file name stem (part before the | in the progress file) and <SUITE_DESCRIPTION> with the suite description (part after the |). Escape parentheses in the description if present. Forward slashes inside the describe path do not need to be escaped.
Important: The suite description in the -t filter must match the inner describe(...) text in the test file exactly. Some mappings:
| File | Suite Description Text |
|------|----------------------|
| manager-driver | Manager Driver Tests |
| actor-conn | Actor Connection Tests |
| actor-conn-state | Actor Connection State Tests |
| conn-error-serialization | Connection Error Serialization Tests |
| actor-destroy | Actor Destroy Tests |
| request-access | Request Access in Lifecycle Hooks |
| actor-handle | Actor Handle Tests |
| action-features | Action Features Tests |
| access-control | access control |
| actor-vars | Actor Variables |
| actor-metadata | Actor Metadata Tests |
| actor-onstatechange | Actor State Change Tests |
| actor-db | Actor Database |
| actor-db-raw | Actor Database Raw Tests |
| actor-db-init-order | Actor Db Init Order |
| actor-workflow | Actor Workflow Tests |
| actor-error-handling | Actor Error Handling Tests |
| actor-queue | Actor Queue Tests |
| actor-kv | Actor KV Tests |
| actor-stateless | Actor Stateless Tests |
| raw-http | raw http |
| raw-http-request-properties | raw http request properties |
| raw-websocket | raw websocket |
| actor-inspector | Actor Inspector Tests |
| gateway-query-url | Gateway Query URL Tests |
| actor-db-pragma-migration | Actor Database Pragma Migration |
| actor-state-zod-coercion | Actor State Zod Coercion |
| actor-conn-status | Connection Status Changes |
| gateway-routing | Gateway Routing |
| lifecycle-hooks | Lifecycle Hooks |
| serverless-handler | Serverless Handler Tests |
| actor-state | Actor State Tests |
| actor-save-state | Actor Save State Tests |
| actor-schedule | Actor Schedule Tests |
| actor-sleep | Actor Sleep Tests |
| actor-sleep-db | Actor Sleep Database Tests |
| actor-lifecycle | Actor Lifecycle Tests |
| actor-conn-hibernation | Actor Connection Hibernation Tests |
| actor-run | Actor Run Tests |
| hibernatable-websocket-protocol | hibernatable websocket protocol |
| actor-db-stress | Actor Database Stress Tests |
| actor-agent-os | Actor agentOS Tests |
c) Pipe output to file and analyze:
Always pipe test output to /tmp/driver-test-current.log so you can grep it afterward. Then analyze:
grep -E "Tests|FAIL|PASS|Error|✓|✗|×" /tmp/driver-test-current.log | tail -30
d) If all tests pass for that runtime: Check off only that runtime's box in the progress file and append to the log:
- <timestamp> <file> [<runtime>]: PASS (<N> tests, <duration>)
If both runtime boxes are now checked, the file is fully done; advance to the next file.
e) If tests fail:
-t pattern.- <timestamp> <file> [<runtime>]: FAIL - <brief description of failure>
wasm but passes on native)If a file group fails, keep the full matrix selector and append enough test-name text to isolate the failing test:
cd rivetkit-typescript/packages/rivetkit && \
pnpm test tests/driver/<FILE>.test.ts \
-t "runtime \(<runtime>\) / sqlite \(<backend>\) / encoding \(bare\).*<test name>" \
> /tmp/driver-test-narrow.log 2>&1
Do not use -t as a flake workaround. It is only for selecting the intended matrix cell and, when needed, a specific failing test.
If the bug only appears on one runtime, that's a strong signal — focus the diff hunt on the corresponding runtime adapter (napi-runtime.ts / wasm-runtime.ts) and any wasm-feature-gated code in rivetkit-core and rivetkit-typescript/packages/rivetkit-wasm.
When all rows are fully checked (both runtime boxes), append to the log:
- <timestamp> ALL TESTS COMPLETE
Report summary:
runtime=both). Run native, then wasm, on the same file. Check off each independently as it passes, but do not advance to the next file until both are checked./tmp/driver-test-current.log and grep afterward.-t for matrix selection. Include runtime, SQLite backend, and encoding in the selector. Do not scope the driver matrix with env vars.wasm with local SQLite. The harness throws on this combination. If a wasm run somehow needs local SQLite to repro a bug, that's a bug in the matrix, not a workaround to apply.Take rivet-dev/driver-test-runner from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.