agentleFS
catcatcatstudiocatcatcatstudio/cat-skills/.cursor/skills/fortify/SKILL.md

fortify

Skill3 starsChanged 3 months agoMITView on GitHub

Testing infrastructure, coverage, and verified test quality for any project. Detects stack, installs testing ecosystem, audits untested critical paths, writes thorough tests weighted toward error paths, runs them, verifies via mutation testing. Use when user says '/fortify', 'add tests', 'set up testing', 'I need tests', 'test this', or wants to audit coverage. NOT for: running existing tests directly or improving prompt quality.

1 other project uses a version of this.

Adopted by

Most recently taken up by

The file

Show its rules and text

We split this skill into the rules it gives an agent

41 rules. About 0 are common, 37 are distinctive, and 4 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈37

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 4

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Read the project root. Identify everything about the stack.

    line 49
  2. Distinctive:

    Read all of these that exist:

    line 53
  3. Distinctive:

    Existing test setup: Check for test config files, test directories, test scripts

    line 66
  4. Distinctive:

    Before moving on, research what commonly goes wrong for this specific stack.

    line 89
  5. Very specific:

    If _docs/pitfalls.md exists (from /recon), read it — it contains pre-researched intelligence about this project's domain.

    line 94
  6. Distinctive:

    Use these findings to inform what to test for in Phase 5 — test for bugs that commonly appear in projects like this, even if the code …

    line 96
  7. Distinctive:

    If existing test setup is found, read the config and understand what's already configured before changing anything.

    line 110
  8. Very specific:

    If a references/ file exists for this stack in the skill directory, use it.

    line 129
  9. Distinctive:

    Ask: "This is what I want to install.

    line 144
  10. Distinctive:

    Add all testing dependencies as dev dependencies:

    line 150
  11. Distinctive:

    Use compatible version ranges

    line 152
  12. Distinctive:

    Test file patterns, module resolution (aliases, paths)

    line 158
  13. Distinctive:

    Run the test command to verify:

    line 172
  14. Distinctive:

    Every item gets an explicit priority label:

    line 198
  15. Distinctive:

    If you write 2 happy-path tests for a function, write at least 3 error-path tests.

    line 243
  16. Distinctive:

    Every public function/method has at least one test

    line 248
  17. Distinctive:

    Import the module under test

    line 266
  18. Distinctive:

    Follow AAA pattern: Arrange → Act → Assert

    line 270
  19. Distinctive:

    API endpoints: Test every status code the endpoint can return.

    line 275
  20. Distinctive:

    Database: Test CRUD, constraints, edge queries, concurrent access.

    line 277
  21. Distinctive:

    UI components: Test rendering, interaction, accessibility.

    line 279
  22. Distinctive:

    External APIs: Test response handling, retry logic, timeouts, rate limits.

    line 281
  23. Distinctive:

    Auth: Test EVERY auth path — valid credentials, invalid credentials, expired tokens, missing tokens, malformed tokens, insufficient …

    line 283
  24. Distinctive:

    Write tests for the batch

    line 288
  25. Distinctive:

    Run them immediately (see Phase 5)

    line 289
  26. Distinctive:

    Do NOT write all tests then run them at the end.

    line 293
  27. Distinctive:

    After each batch from Phase 4:

    line 301
  28. Distinctive:

    If tests fail: Read the error output. Fix the test (not the code — the test is wrong if the code works).

    line 304
  29. Distinctive:

    Run coverage: Check the coverage report.

    line 306
  30. Distinctive:

    If dependencies aren't installed and you can't run tests, tell the user:

    line 308
  31. Distinctive:

    After all tests are green, verify they actually catch bugs:

    line 323
  32. Distinctive:

    Remove an error handler

    line 334
  33. Distinctive:

    Remove an auth check

    line 336
  34. Distinctive:

    Run the test suite. The tests MUST fail.

    line 343
  35. Distinctive:

    Write a test that specifically catches this mutation

    line 349
  36. Distinctive:

    Run tests again — should be green

    line 351
  37. Very specific:

    Don't duplicate existing setup: If vitest is configured, don't install jest.

    line 406
  38. Distinctive:

    Test YOUR code, not dependencies: Don't test that Prisma can insert a row.

    line 408
  39. Distinctive:

    No test theater: Every test must be capable of failing for the right reason.

    line 410
  40. Distinctive:

    P0 first, always: If you run out of context, the user has verified tests on the code that matters most.

    line 418
  41. Very specific:

    Check for recon: If _docs/pitfalls.md or _docs/security-notes.md exist, read them.

    line 426

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 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.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

/fortify — Testing That Proves Your Code Works

Drop into any project, detect its stack, install the professional testing ecosystem, write thorough tests, run them until green, and verify they catch real bugs. The output isn't test files — it's proof your code works.

When NOT to use this skill

  • Project has comprehensive, verified test coverage already → run the tests, don't re-fortify
  • You just need to run existing tests → npm test / pytest / whatever directly
  • You want to review build plans or design docs → /architect
  • You want to optimize a skill's prompt quality → that's eval optimization, different thing

Quick Reference

ModeWhat happens
/fortify or /fortify fullDetect → Install → Audit → Write → Run → Verify → Report
/fortify setupDetect → Install → Done
/fortify checkDetect → Audit → Report gaps → Done (no installs, no test writing)

The difference from just asking Claude to "add tests": Phases 6 and 7. Tests that aren't run are fiction. Tests that don't catch bugs are theater.


Phase 1: Detect

Read the project root. Identify everything about the stack.

1a. Package Manifests

Read all of these that exist:

  • package.json, pnpm-lock.yaml, yarn.lock, bun.lockb
  • pyproject.toml, setup.py, setup.cfg, Pipfile, requirements.txt
  • Cargo.toml, go.mod, Gemfile, composer.json
  • build.gradle, pom.xml, Package.swift, mix.exs, pubspec.yaml

1b. Framework Detection

From the manifest and source files, identify:

  • Language(s): TypeScript, Python, Rust, Go, Swift, etc.
  • Framework(s): Next.js, React, Vue, Svelte, Express, FastAPI, Django, Rails, etc.
  • Runtime: Node, Bun, Deno, CPython, etc.
  • Package manager: npm, pnpm, yarn, bun, pip, poetry, cargo, etc.
  • Existing test setup: Check for test config files, test directories, test scripts

1c. Domain Detection

Scan the codebase to identify what types of code exist:

SignalDomain
Route handlers, controllers, API filesAPI endpoints
ORM models, migrations, schema filesDatabase layer
Fetch calls, SDK clients, webhook handlersExternal API integrations
React/Vue/Svelte componentsUI components
CLI entry points, arg parsingCLI tools
WebSocket handlers, SSE, real-timeReal-time
Queue workers, cron jobs, async tasksBackground jobs
Auth middleware, session handling, token logicAuth/security
State machines, workflow enginesState machines
File upload/download, media processingFile I/O
Cache layers, memoizationCaching
Config loaders, env parsing, feature flagsConfiguration

1d. Common Bug Research

Before moving on, research what commonly goes wrong for this specific stack. This isn't generic — it's targeted:

  • What bugs do [framework] apps commonly ship?
  • What are the known gotchas for [ORM/DB layer]?
  • What are the "works in dev, breaks in production" patterns for this stack?

If _docs/pitfalls.md exists (from /recon), read it — it contains pre-researched intelligence about this project's domain.

Use these findings to inform what to test for in Phase 5 — test for bugs that commonly appear in projects like this, even if the code doesn't obviously have them yet.

1e. Report Detection Results

State clearly:

Stack: [language] + [framework] on [runtime]
Package manager: [manager]
Domains found: [list]
Existing test setup: [what exists, or "none"]
Common pitfalls for this stack: [top 3-5 from research]

If existing test setup is found, read the config and understand what's already configured before changing anything.


Phase 2: Install

2a. Determine the Testing Ecosystem

For the detected stack, identify the complete professional testing toolchain:

  • Test runner: vitest, jest, pytest, go test, cargo test, etc.
  • Assertion library: built-in or chai, should, etc.
  • Component testing (if UI): @testing-library/react, Vue Test Utils, etc.
  • API testing: supertest, httpx, net/http/httptest, etc.
  • Mock/stub tools: built-in mocking, MSW, nock, responses, etc.
  • HTTP mocking (if external APIs): MSW, nock, responses, httpmock, etc.
  • Coverage: v8, istanbul, coverage.py, tarpaulin, etc.
  • Testing-specific lint rules: eslint-plugin-testing-library, ruff PT rules, etc.

If a references/ file exists for this stack in the skill directory, use it. Otherwise, use context7 to check current best practices for the framework's recommended testing approach.

2b. Present Before Installing

Show the user what you plan to install:

## Testing Ecosystem for [stack]

### Test Runner: [tool] — [why]
### Libraries: [list with purposes]
### Mocking: [list with what each mocks]
### Coverage: [tool and config approach]

Ask: "This is what I want to install. Anything to add or skip?"

Wait for confirmation.

2c. Install Dependencies

Add all testing dependencies as dev dependencies:

  • Group logically (runner, libraries, mocks, coverage)
  • Use compatible version ranges
  • Respect existing lockfiles

2d. Configure

Test runner config:

  • Test file patterns, module resolution (aliases, paths)
  • Setup files if needed (global mocks, env vars, polyfills)
  • Coverage config (thresholds starting at 60-70%, reporters)
  • Environment settings (jsdom for React, node for APIs)

Test scripts in package manifest:

  • test — run all tests
  • test:watch — watch mode
  • test:coverage — with coverage report

Test directory structure — follow existing conventions. If project has __tests__/, use it. If co-located tests, match that. Don't impose a structure.

2e. Verify Setup

Run the test command to verify:

  • Runner starts and exits cleanly
  • Config is valid
  • No dependency conflicts

Fix anything that fails before moving on.

Stop here if mode is setup.


Phase 3: Audit

Scan the entire codebase and identify what needs tests.

3a. Map All Code

For every source file, classify:

  • What it does (route handler, component, utility, model, service, hook, middleware)
  • Blast radius — if this breaks, what's the user impact? (P0: auth, payments, data mutation / P1: core features / P2: standard CRUD / P3: cosmetic, logging)
  • Complexity — branching logic, async flows, state management
  • Has tests? — check for corresponding test files
  • Known pitfall? — cross-reference against common bugs from Phase 1d

3b. Produce the Audit with Priority Labels

Every item gets an explicit priority label:

## Test Coverage Audit

### P0 — Critical (test immediately)
- src/routes/auth.ts — handles login/register, high blast radius
- src/middleware/auth.ts — JWT verification, every request depends on this
- src/lib/validations.ts — data integrity boundary

### P1 — Important (test soon)
- src/components/PaymentForm.tsx — complex state, user-facing
- src/services/pricing.ts — business logic with edge cases

### P2 — Standard (test when possible)
- src/routes/users.ts — standard CRUD
- src/components/UserCard.tsx — simple display component

### P3 — Low priority
- src/utils/format.ts — formatting helpers

### Summary
[X] files, [Y] have tests, [Z]% coverage estimate
[N] P0 items need immediate testing
[M] known stack pitfalls to test for: [list]

Stop here if mode is check.


Phase 4: Write Tests

Work through the priority list: all P0, then P1, then P2. Stop at P2 unless user asks for P3.

The Error Path Rule

For every function tested, error/edge-case tests must outnumber happy-path tests. This is the single most important testing principle. Happy paths work because you test them by hand while developing. Bugs live in:

  • What happens with empty/null/undefined input?
  • What happens when a dependency is down?
  • What happens with malformed data?
  • What happens at boundary values?
  • What happens with concurrent access?
  • What happens when the user does something unexpected?

If you write 2 happy-path tests for a function, write at least 3 error-path tests. This ratio is enforced, not aspirational.

Testing Standards

Unit tests:

  • Every public function/method has at least one test
  • Happy path + at least TWO unhappy paths per function
  • Boundary values (empty string, zero, negative, null/undefined, max values)
  • Type edge cases (unexpected types, missing fields)

Integration tests:

  • Components work together correctly
  • Data flows end-to-end through the pipeline
  • Prior integrations still work (regression)

Error path tests:

  • Dependencies unavailable (DB down, API unreachable, file missing)
  • Malformed input (wrong types, missing fields, extra fields)
  • Resource constraints (timeout, rate limit, large payload)
  • Error messages are useful, not generic
  • Security boundaries (unauthorized access, token expiry, privilege escalation)

For each test file:

  1. Import the module under test
  2. Set up fixtures/mocks at the top
  3. Group tests by function or behavior (describe blocks)
  4. Name tests as sentences: "returns 401 when token is expired"
  5. Follow AAA pattern: Arrange → Act → Assert
  6. Clean up after each test

Domain-Specific Patterns

API endpoints: Test every status code the endpoint can return. Not just 200 — test 400, 401, 403, 404, 409, 422, 429, 500. Each is a different failure mode.

Database: Test CRUD, constraints, edge queries, concurrent access. Use transaction rollback or test containers for isolation.

UI components: Test rendering, interaction, accessibility. Query by role, not test ID.

External APIs: Test response handling, retry logic, timeouts, rate limits. Mock the HTTP layer.

Auth: Test EVERY auth path — valid credentials, invalid credentials, expired tokens, missing tokens, malformed tokens, insufficient permissions, role boundaries.

Batching

Work in batches of 2-3 related files:

  1. Write tests for the batch
  2. Run them immediately (see Phase 5)
  3. Fix any failures
  4. Move to next batch

Do NOT write all tests then run them at the end. That's how you end up with 50 broken test files.


Phase 5: Run Until Green

This phase is mandatory. Tests that aren't run are fiction.

After each batch from Phase 4:

  1. Run the test suite. Execute the actual test command (npm test, pytest, etc.)
  2. If tests fail: Read the error output. Fix the test (not the code — the test is wrong if the code works). Re-run.
  3. Loop until all tests pass with exit code 0.
  4. Run coverage. Check the coverage report. If critical paths (P0) have gaps, write more tests.

If dependencies aren't installed and you can't run tests, tell the user:

Tests written but I can't verify them — dependencies need to be installed first.
Run: [install command]
Then: [test command]

This is the fallback, not the default. Always try to run tests.


Phase 6: Verify — Mutation Testing

This phase is what separates real tests from test theater.

After all tests are green, verify they actually catch bugs:

6a. Select Mutation Targets

Pick 3-5 P0 functions — the most critical code. For each:

6b. Break the Code

Make one small, realistic mutation:

  • Comment out a validation check
  • Swap === to !== or > to <
  • Remove an error handler
  • Change a return value
  • Remove an auth check
  • Swap the order of operations

These aren't random — they simulate real bugs. Pick mutations that would cause real user impact.

6c. Run Tests Again

Run the test suite. The tests MUST fail. If they don't, the tests are theater — they pass regardless of whether the code is correct.

6d. Fix or Add Tests

For each mutation that tests didn't catch:

  1. The code has an untested critical behavior
  2. Write a test that specifically catches this mutation
  3. Revert the mutation
  4. Run tests again — should be green
  5. Re-apply the mutation — should be red
  6. Revert the mutation (leave the code correct)

6e. Report Mutations

## Mutation Testing Results

### Mutations tested: [N]
### Caught by tests: [M] / [N]

| Code | Mutation | Caught? | Test that caught it |
|------|----------|---------|---------------------|
| auth.ts:24 | Removed token expiry check | Yes | "returns 401 when token is expired" |
| products.ts:55 | Changed price > 0 to price >= 0 | No → FIXED | Added "rejects product with price of 0" |
| ...

Phase 7: Report

## Fortify Complete

### Installed
- [list of testing tools]

### Tests Written
- [X] test files, [Y] total test cases
- P0: [N] files tested ([list])
- P1: [N] files tested ([list])
- P2: [N] files tested ([list])
- Error path tests: [N] / Happy path tests: [M] (ratio: [N/M])

### Verification
- All tests passing: Yes/No
- Coverage: [X]% overall, [Y]% on P0 code
- Mutations tested: [N], caught: [M]/[N]

### Remaining Gaps
- [anything not tested and why]
- [any mutations that revealed weak test coverage — now fixed]

### How to Run
- `[test command]` — run all tests
- `[coverage command]` — run with coverage
- `[watch command]` — run in watch mode

Behavioral Rules

  1. Don't duplicate existing setup. If vitest is configured, don't install jest. If __tests__/ exists, use it. The goal is testing, not reformatting.
  2. Test YOUR code, not dependencies. Don't test that Prisma can insert a row. Test that your service method handles the result correctly.
  3. No test theater. Every test must be capable of failing for the right reason. If you're unsure, break the code and check (that's Phase 6).
  4. Error paths > happy paths. This ratio is enforced. If a function has 2 happy-path tests, it needs at least 3 error-path tests. Happy paths work because you tested them by hand. Bugs live in the sad paths.
  5. Run the tests. Tests that aren't executed are fiction. Phase 5 is not optional. If you can't run them (missing deps), say so explicitly and tell the user exactly what to run.
  6. Mutations prove quality. Phase 6 is what makes this skill worth invoking. Anyone can write test files. Proving they catch real bugs is the value.
  7. P0 first, always. If you run out of context, the user has verified tests on the code that matters most.
  8. Coverage thresholds start low. 60-70% on day one. Going from 0% to 65% is a massive win. Don't set 90% and create pressure to write garbage tests.
  9. Present before installing. Show the user what you plan to install. They may have constraints you don't know about.
  10. Respect existing conventions. Co-located tests? Keep co-locating. camelCase names? Match them. The goal is coverage, not your preferred structure.
  11. Check for recon. If _docs/pitfalls.md or _docs/security-notes.md exist, read them. They contain pre-researched intelligence about common problems for this type of project. Use them to inform what to test for.

Download now (ZIP)

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
What did you use it for? e.g. Reviewing pull requests in a Rails app

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.