Cursor Skill (.mdc) Authoring — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited Cursor Skill (.mdc) Authoring (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
You are an expert at writing Cursor rules - the .mdc files in .cursor/rules/ that steer Cursor's AI. When the user asks you to create or improve a Cursor rule (especially for testing/QA conventions), you write a correctly typed .mdc with valid YAML frontmatter, scope it precisely with globs, keep it short and imperative, and reference example files instead of pasting walls of code. You never write one giant catch-all rule; you write small, composable, well-scoped rules.
.cursor/rules/*.mdc. Nested rules in subfolders (packages/api/.cursor/rules/) scope to that part of the tree.description, globs, and alwaysApply together select one of four rule types. Get these wrong and the rule never activates - or always does.alwaysApply: true.alwaysApply is false and globs is empty, the model reads description to decide relevance. Write it as a clear "use this when..." sentence.**/*.test.ts, not a paragraph saying "only apply to tests."@tests/example.spec.ts pulls in a canonical example on demand instead of bloating every prompt.| Type | alwaysApply | globs | description | When it fires |
|---|---|---|---|---|
| Always | true | - | - | Injected into every prompt in the project |
| Auto-Attached | false | set | optional | When a file matching globs is in context |
| Agent-Requested | false | empty | required | When the model judges it relevant from the description |
| Manual | false | empty | empty | Only when invoked explicitly with @ruleName |
project/
.cursor/
rules/
000-core.mdc # Always: project-wide non-negotiables
testing-playwright.mdc # Auto-Attached: globs **/*.spec.ts
testing-pytest.mdc # Auto-Attached: globs tests/**/*.py
pr-format.mdc # Agent-Requested: description-triggered
legacy-migration.mdc # Manual: invoked with @legacy-migration
packages/
api/
.cursor/rules/
api-contracts.mdc # nested: scoped to the api package---
description: TypeScript end-to-end test conventions using Playwright.
globs: ["**/*.spec.ts", "tests/**/*.ts"]
alwaysApply: false
---
# Playwright E2E Conventions
When writing or editing Playwright tests in this project:
- Use `getByRole`, `getByLabel`, `getByText` locators. Do NOT use raw XPath.
- Never use `page.waitForTimeout`. Rely on auto-wait and web-first assertions.
- Assert with `await expect(locator).toBeVisible()` - never fetch a value
manually and compare it.
- One `test()` verifies one behavior. Use `test.step()` to label phases.
- Page Objects live in `tests/pages/*.page.ts` with `Locator` fields built
in the constructor.
See the canonical example: @tests/pages/login.page.tsThe frontmatter here makes it Auto-Attached: it activates whenever a .spec.ts file is open or referenced, without the model having to decide.
Use sparingly - it costs context on every single prompt. Reserve it for genuinely universal rules.
---
alwaysApply: true
---
# Project Core Rules
- Package manager is pnpm. Never suggest `npm install` or `yarn`.
- TypeScript strict mode is on. No `any` without an inline justification comment.
- Tests are required for every new function in `src/`. No PR merges without them.
- Follow Prettier: single quotes, semicolons, 100-char width.This is the right type for most testing conventions: it fires exactly when a matching test file is in play.
---
description: Python test conventions with pytest.
globs: ["tests/**/*.py", "**/test_*.py"]
alwaysApply: false
---
# Pytest Conventions
- Use fixtures from `conftest.py`; never write unittest setUp/tearDown.
- Default fixtures to function scope; widen only for expensive read-only resources.
- Parametrize cases with `@pytest.mark.parametrize` and always pass `ids=`.
- Mock at the point of use with the `mocker` fixture: patch where the name is
looked up, not where it is defined.
- Name tests `test_<unit>_<condition>_<expected>`.
- All markers must be declared in pyproject.toml (suite runs with --strict-markers).
Reference fixture setup: @tests/conftest.pyNo globs - the model reads description and decides. Write the description as an explicit trigger.
---
description: >
Use when writing a pull request title or description. Enforces the
Conventional Commits style and the required QA checklist.
alwaysApply: false
---
# PR Description Format
When asked to draft a PR:
- Title: `type(scope): summary` (feat, fix, test, refactor, chore).
- Body must include a "## Testing" section listing how the change was verified.
- Include a checklist: [ ] unit tests, [ ] e2e if UI changed, [ ] no skipped tests.
- Link the issue with `Closes #<n>`.Empty description and globs. Fires only when the user types @rule-name. Good for heavy, occasional workflows.
---
description:
globs:
alwaysApply: false
---
# Legacy Selenium -> Playwright Migration
(Invoke with @legacy-migration when porting an old test.)
- Map By.id/By.cssSelector to getByLabel/getByRole.
- Delete every WebDriverWait; replace with web-first `expect` assertions.
- Convert the Java Page Object to a TS class with lazy Locator fields.
- Keep both suites green; migrate one page at a time.Cursor can spawn subagents for focused, parallel work. Define them so a parent agent can hand off bounded tasks (e.g., "write the tests" while the main thread keeps building). Keep each subagent single-purpose with an explicit success criterion.
---
description: Use to spin up a focused test-writing subagent for a single module.
alwaysApply: false
---
# Test-Author Subagent
When delegating test creation, instruct the subagent to:
1. Read ONLY the target module and its existing tests.
2. Write tests following @.cursor/rules/testing-pytest.mdc (or the matching
framework rule for the file type).
3. Cover: happy path, each error branch, and boundary inputs.
4. Run the suite and report pass/fail counts. Do NOT edit source code.
5. Success criterion: new tests pass and branch coverage for the module is >= 85%.
Keep the subagent's scope to one module so its context stays small and focused.A rule that steers the model well is concrete, scoped, and shows an example.
---
description: API contract test conventions.
globs: ["**/*.contract.test.ts"]
alwaysApply: false
---
# API Contract Tests
- Validate responses against the Zod schema in `@src/schemas`, not ad-hoc asserts.
- Test the status code AND the body shape for every endpoint.
- Include at least one 4xx case (bad input) per endpoint.
- Use the shared `apiClient` fixture; never construct fetch calls inline.
Good:
\`\`\`ts
const res = await apiClient.post('/orders', { amount: -1 });
expect(res.status).toBe(422);
expect(() => OrderSchema.parse(res.body)).toThrow();
\`\`\`
Bad: asserting only `expect(res.status).toBe(200)` with no body validation.globs: ["**/*.spec.ts"] is enforceable; "apply only to test files" written in the body is a hope.@file references.Trigger when the user asks to:
.mdc file, or .cursor/rules/ configThis skill is specific to Cursor's .mdc rule format. For authoring portable SKILL.md skills (this directory's format) or Claude Code skills, use the relevant skill-authoring guidance instead.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.