qv-sdk-e2e-create
Skill697 starsChanged 18 days agoApache-2.0View on GitHub
Plans and scaffolds e2e tests in packages/sdk/e2e for a new or changed public SDK API. Use when adding or modifying SDK functionality that is exposed to consumers. Enforces happy / sad / error coverage, deterministic model-output assertions, desktop/mobile/Electron consumer coverage, smoke-suite selection, and local validation with run:local.
We split this skill into the rules it gives an agent
14 rules. About 0 are common, 9 are distinctive, and 5 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈9
Distinctive · estimate
This author's own choices. Worth a look.
5
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 26
Do NOT use for:
- Very specific: line 38
Find comparable tests: Look for an analogous existing feature in tests/test-definitions.ts and its executor.
- Distinctive: line 74
If the model's output is inherently non-deterministic and cannot be constrained, say so in the plan and justify why shape-only or …
- Distinctive: line 80
Every public-API feature MUST have at minimum:
- Very specific: line 98
Never import node:* from tests/shared/ or tests/mobile/.
- Very specific: line 107
If a consumer cannot support the tests, add a documented SkipExecutor.
- Distinctive: line 119
If the feature cannot run on mobile at all, document the skip reason.
- Very specific: line 124
Only tag suites: ["smoke"] if the feature has no existing smoke coverage.
- Distinctive: line 127
Must be deterministic, fast, and stable on both desktop and mobile.
- Distinctive: line 128
If no test meets the bar, do not tag any and flag it explicitly in the plan.
- Distinctive: line 182
After scaffolding, provide the exact commands for every compatible local consumer.
- Very specific: line 198
Always use install:build:full once packages/sdk itself changed, even if packages/inference has no diff lines of its own — install:build:sdk …
- Distinctive: line 221
Before presenting the plan:
- Distinctive: line 231
Before marking scaffolding complete:
≈ “Common” is an estimate: at least 1 in 5 of the 308,232 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
SDK e2e Test Creation
Plan and scaffold e2e tests in packages/sdk/e2e for a new or changed SDK feature exposed through
the public API.
When to use this skill
Applies to SDK changes in packages/sdk/ that touch the public API surface.
Use when:
- Adding a new public SDK function, model type, or capability.
- Changing an existing public SDK API in a way that affects runtime behaviour.
- User invokes
/qv-sdk-e2e-create. - User asks to "add e2e tests for
<feature>" or similar.
Do NOT use for:
- Internal refactors that don't change the public surface.
- Unit tests inside
packages/sdk/(this skill covers only the e2e suite underpackages/sdk/e2e).
Approach
Investigate first, then propose a concrete plan. Only ask the user for information that cannot be recovered from code or context.
- Read the feature. Identify the new/changed exports, inputs, return type, model dependencies, and
any existing examples under
packages/sdk/examples/or tests underpackages/sdk/e2e/tests/. - Find comparable tests. Look for an analogous existing feature in
tests/test-definitions.tsand its executor. Mirror its style unless there's reason to deviate. - Determine model-output testability (see §"Model-output strategy"). Propose a specific validator and a specific prompt/input that makes the output deterministic enough to assert.
- Draft happy / sad / error cases as a concrete test-definition sketch.
- Decide executor placement, consumer registration, and mobile constraints (see §"Placement and consumer constraints").
- Select at most one smoke candidate (see §"Smoke policy").
- Present the plan to the user. Include: feature summary, chosen validators with rationale, test
definitions sketch, placement decision, desktop/mobile/Electron registrations, platform concerns,
smoke pick. Ask clarifying questions only where genuine ambiguity remains (e.g. expected model
behaviour on an edge case, preferred tolerance for a
numeric-range). - After approval, scaffold the files and prompt the user to run locally with the exact commands
for every consumer. Always run
run:local:electron --filter <feature>-to verify either the handler or an intentional skip for Electron/Snap.
Model-output strategy
For any feature that invokes a model, do not default to shape-only checks. type validation proves
nothing about model correctness and must be a last resort.
Pick the strongest achievable strategy:
- Exact-ish output — constrain the prompt + deterministic params (
temperature: 0, fixedseed,top_k: 1) so a known token must appear. Assert withcontains-all. Example: prompt "Reply with only the word APPLE." → assert result containsAPPLE. - Closed-set — enum-style prompt (known set of valid answers) →
contains-any. - Numeric range — a score, similarity, duration, or embedding magnitude with known bounds →
numeric-range. Pick bounds tolerant to minor model drift. - Regex structure — structured output (JSON keys, date format, language tag) →
regex. Keep the pattern anchored and stable. - Shape-only fallback —
typewithminLength. Flag as weak coverage in the plan. - Error path —
throws-errorwith a substring that is stable across SDK versions. - Custom
function— use for deterministic but non-trivial checks like cosine similarity against a reference vector.
If the model's output is inherently non-deterministic and cannot be constrained, say so in the plan and justify why shape-only or range-based coverage is the best achievable — do not silently ship a weak assertion.
Happy / sad / error minimum
Every public-API feature MUST have at minimum:
- Happy path — valid input, canonical output, strongest assertion achievable.
- Sad path — boundary or edge case that must still succeed (empty input, minimum ctx, longest accepted input, unusual but valid locale, streaming vs non-streaming).
- Error path — invalid/malformed input, missing asset, or exceeded constraint. Must throw with a
matchable message via
throws-error.
More cases are encouraged for multi-branch features.
Placement and consumer constraints
Executor placement (from packages/sdk/e2e/AGENTS.md):
- Pure SDK API, no Node stdlib, no RN APIs →
tests/shared/executors/. - Needs
node:fs,node:path,process.cwd(), or other Node-only APIs →tests/desktop/executors/. - Needs RN
Platform, bundled assets, or anything specific to React Native →tests/mobile/executors/.
Never import node:* from tests/shared/ or tests/mobile/.
Placement under tests/shared/executors/ does not register an executor automatically. Explicitly check
and update every compatible consumer:
tests/desktop/consumer.tstests/mobile/consumer.tstests/electron/consumer.ts— also used by the Snap consumer
If a consumer cannot support the tests, add a documented SkipExecutor; do not leave scheduled tests
without a matching handler, which fails at runtime with No handler found.
Mobile concerns to address in the plan:
- Memory — can the target device RAM hold the model? If not, propose a smaller model variant on
mobile, or a
SkipExecutorentry. - Filesystem —
node:fsis unavailable. Assets must be bundled viaqvac-test.config.js→consumers.mobile.assets.patterns. - Platform-specific limitations — known iOS/Android issues (OOM, missing native lib, backend
unsupported). Add a
SkipExecutorat the top oftests/mobile/consumer.tswith a clear reason.
If the feature cannot run on mobile at all, document the skip reason. Evaluate Electron/Snap compatibility independently rather than treating desktop-only coverage as automatic.
Smoke policy
- Only tag
suites: ["smoke"]if the feature has no existing smoke coverage. - Cap at 1-2 smoke tests per feature.
- Pick the happy path with the most meaningful assertion (not shape-only).
- Must be deterministic, fast, and stable on both desktop and mobile. Verify before tagging.
- If no test meets the bar, do not tag any and flag it explicitly in the plan.
Scaffolding templates
Test definition (tests/<feature>-tests.ts)
import type { TestDefinition } from "@qvac/test-suite";
export const <feature>Tests: TestDefinition[] = [
{
testId: "<feature>-happy",
params: { /* canonical input */ },
expectation: { validation: "contains-all", contains: ["EXPECTED_TOKEN"] },
suites: ["smoke"], // only if this test qualifies
metadata: { category: "<feature>", estimatedDurationMs: 10_000 },
},
{
testId: "<feature>-edge",
params: { /* boundary case */ },
expectation: { validation: "type", expectedType: "string" },
metadata: { category: "<feature>", estimatedDurationMs: 10_000 },
},
{
testId: "<feature>-error",
params: { /* invalid input */ },
expectation: { validation: "throws-error", errorContains: "specific message" },
metadata: { category: "<feature>", estimatedDurationMs: 2_000 },
},
];Register in tests/test-definitions.ts:
import { <feature>Tests } from "./<feature>-tests.js";
// ...
export const allTests: TestDefinition[] = [
// ...
...<feature>Tests,
];Executor
Extend AbstractModelExecutor (base: tests/shared/executors/abstract-model-executor.ts) or use
createExecutor with TestHandler for ad-hoc cases. Bind handlers per testId, and use
ResourceManager.ensureLoaded("<resource-name>") to obtain model IDs.
Register the new executor in every compatible handlers: [...] array: desktop, mobile, and Electron
(which also covers Snap). Add a documented SkipExecutor for intentionally unsupported consumers.
Local validation (required before landing)
After scaffolding, provide the exact commands for every compatible local consumer. Do not mark the task complete until the user confirms those tests pass locally.
cd packages/sdk/e2e
# If packages/sdk (outside e2e) or packages/inference changed
npm run install:build:full
# Otherwise (only test code in packages/sdk/e2e changed)
npm run install:build
npx qvac-test run:local:desktop --filter <feature>-
npx qvac-test run:local:electron --filter <feature>- # verifies the handler or intentional skipAlways use install:build:full once packages/sdk itself changed, even if packages/inference has no
diff lines of its own — install:build:sdk trusts the published @qvac/inference range, which can already
be behind the checked-out packages/inference source from unrelated merged work.
For mobile verification of a smoke candidate (required before tagging suites: ["smoke"]):
npx qvac-test run:local:android --filter <feature>- # or run:local:iosExpectation reference
| Validation | Use for | Notes |
contains-all / contains-any | Keyword or closed-set answers | Preferred over type when achievable |
regex | Structured output (JSON keys, date, lang ID) | Keep pattern anchored and stable |
numeric-range | Scores, latencies, embedding magnitude | Pick bounds tolerant to minor model drift |
type (+ minLength) | Last-resort shape check | Shallow; flag as weak coverage |
throws-error | Every error path | errorContains must be stable across bumps |
function | Complex deterministic checks |
Quality checklist
Before presenting the plan:
- Feature surface understood from code; any genuine gaps raised as targeted clarifying questions.
- Model-output strategy picked and justified — not defaulted to
type. - Happy, sad, and error cases drafted.
- Executor placement chosen; desktop, mobile, Electron/Snap registration checked; mobile memory / filesystem / platform concerns addressed.
- Smoke candidate selected or explicitly skipped with reason.
- Local validation command prepared with the correct
--filterprefix.
Before marking scaffolding complete:
- Test definitions aggregated in
tests/test-definitions.ts. - Executors registered or explicitly skipped in every relevant consumer entry, including Electron when compatible (which also covers Snap).
- User has confirmed the new tests pass through each compatible local consumer command.
- User reminded to run
/qv-docs-updatewhen the tested surface is user-facing. Never auto-run it — the skill is manual-only.
References
- Executor placement, smoke policy, rebuild flow →
packages/sdk/e2e/AGENTS.mdandpackages/sdk/e2e/README.md. - Expectation schema →
@qvac/test-suitedist/schemas/expectations.js. - Existing examples:
- Strong output assertion:
packages/sdk/e2e/tests/translation-salamandra-tests.ts(contains-anyover expected Spanish tokens). - Error path:
packages/sdk/e2e/tests/vision-tests.ts(throws-errorwitherrorContains). - Shape fallback:
packages/sdk/e2e/tests/completion-tests.ts(type: "string").
- Strong output assertion:
In this repository56 other files it gives its agents.
- AGENTS.mdAGENTS.md
- .github/AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- .cursor/rules/agent-integrations.mdcCursor rule
- .cursor/rules/cpp/string-api-conventions.mdcCursor rule
- .cursor/rules/devops/main.mdcCursor rule
- .cursor/rules/no-remote-code-execution.mdcCursor rule
- .cursor/rules/qip-triage.mdcCursor rule
- .cursor/rules/sdk/commit-and-pr-format.mdcCursor rule
- .cursor/rules/sdk/error-handling.mdcCursor rule
- .cursor/rules/sdk/first-class-product-parity.mdcCursor rule
- .cursor/rules/sdk/main.mdcCursor rule
- .cursor/rules/sdk/public-constants-contract.mdcCursor rule
- .cursor/rules/sdk/request-lifecycle-primitives.mdcCursor rule
- .cursor/rules/sdk/sdk-pod-packages.mdcCursor rule
- .cursor/rules/sdk/skill-authoring-guidelines.mdcCursor rule
- cpp-string-api-reviewSkill
- qv-addon-changelogSkill
- qv-addon-pr-createSkill
- qv-addon-release-notesSkill
- qv-agent-stack-syncSkill
- qv-asana-syncSkill
- qv-daily-work-updateSkill
- qv-dev-diary-setupSkill
- qv-dev-diarySkill
- qv-devops-daily-updateSkill
- qv-devops-pr-createSkill
- qv-devops-pr-reviewSkill
- qv-devops-pr-statusSkill
- qv-devops-runner-queueSkill
- qv-devops-why-my-pr-notSkill
- qv-docs-solution-createSkill
- qv-docs-updateSkill
- qv-holepunch-devSkill
- qv-merge-guard-wireSkill
- qv-mobile-test-dispatchSkill
- qv-notice-generateSkill
- qv-pr-mineSkill
- qv-pr-reviewSkill
- qv-pr-testSkill
- qv-qip-createSkill
- qv-qip-reviewSkill
- qv-qip-triageSkill
- qv-quality-reportingSkill
- qv-registry-autobase-patternsSkill
- qv-release-trainSkill
- qv-sdk-backmergeSkill
- qv-sdk-changelogSkill
- qv-sdk-inference-versionSkill
- qv-sdk-pr-createSkill
- qv-sdk-pr-statusSkill
- qv-sdk-update-modelsSkill
- qv-skill-listSkill
- setupSkill
- setupSkill
- qv-nx-ciSkill
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

