plugins/deriving-a-quality-contract/skills/deriving-a-quality-contract/SKILL.md
Derives a project-specific quality contract from three axes - risk profile, team maturity, and product surface - labelling each testing practice MUST, SHOULD, or COULD, then produces a PRESENT/PARTIAL/MISSING/WAIVED gap matrix with an ordered remediation plan. Use when a project has no agreed testing strategy, when a team argues about which practices are mandatory, when onboarding a legacy or inherited repository, when a quality strategy document has to be derived from evidence instead of opinion, or when someone asks "what testing should we actually be doing here".
npx skillsauth add jaktestowac/awesome-copilot-for-testers deriving-a-quality-contractInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Use this skill when a team needs to know which testing practices are mandatory for this project, which are expected, which are optional, and which of them are actually in place today.
"We should test more" is not a strategy. A quality contract is: a named list of practices, each labelled MUST, SHOULD, or COULD for this specific project, each with an exit criterion, an owner, and a current state. The label is derived from three axes, not from taste - which is what makes the contract survive an argument.
Read the repo and ask what the repo cannot tell you.
Stack and tooling - from package.json, lockfiles, tsconfig.json, test config, CI workflows. Record the test runner, assertion style, and CI provider.
Product surface - what the thing actually exposes, because it decides which practices are even applicable:
| Surface | Evidence to look for |
| --- | --- |
| web-ui | React/Vue/Svelte/Angular deps, public/index.html, route components |
| http-api | Express/Fastify/Nest/Hono deps, routes/, controllers/, handler files |
| wire-schema | openapi.*, swagger.*, *.proto, *.graphql, tRPC routers |
| ai-llm | openai, @anthropic-ai/sdk, ai, langchain, llamaindex, prompts/, *.prompt.* |
| data-store | migration folders, ORM schema files, seed scripts |
| library | package exports/main with no server entry point, published to a registry |
| cli | bin field, commander/yargs/clipanion |
A repo has several surfaces. Record all of them with the evidence, and record what is confidently absent - absence is what lets you drop rows.
Profile - the risk class. Ask, do not guess:
Map the answers onto a profile from ./resources/profiles.md (critical-regulated, standard, prototype-internal) and write down the one sentence that justifies it.
Maturity - where the team is now, from ./resources/maturity-model.md (crawl, walk, run). Read it from the repo, not from ambition: no test script at all is crawl, however senior the team.
Write the triple down and confirm it with a human before continuing. Everything downstream is derived from it, so a wrong triple produces a confidently wrong contract.
Walk ./resources/approach-catalog.md. For each practice:
requires-surface names a surface this repo confidently lacks. Record it as N/A with the reason - do not silently omit it.introduced-at maturity is above the team's current level. Record it as deferred to <level>, because it is the next contract, not this one.The output is a table of practices with levels and exit criteria. That is the contract.
For each contracted practice, look for the evidence listed in ./resources/detection-signals.md and assign one of four states:
| State | Meaning | | --- | --- | | PRESENT | Configured and wired into CI, with evidence for both | | PARTIAL | Configured but not enforced, enforced but not on all relevant paths, or present but demonstrably stale | | MISSING | No credible evidence | | WAIVED | Absent by a recorded decision with reason, owner, and expiry |
Rules that keep this honest:
devDependencies that no script and no workflow invokes is PARTIAL, not PRESENT.tool || true, continue-on-error: true, or || echo "non-blocking" is PARTIAL - it runs and cannot fail.A MUST in state MISSING is a blocker. Blockers are not waivable; they are either fixed or the profile was wrong. If a blocker list is long, that is usually a signal the profile was set aspirationally - revisit Phase 0 with the human rather than issuing a 20-item blocker list.
Order everything else by risk × effort using the effort labels in the catalog (XS ≈ 1h, S ≈ half a day, M ≈ 2 days, L ≈ a week). Front-load the practices that protect the surfaces you identified as critical.
Use ./resources/contract-template.md. The deliverable has four parts:
Save to .qa/quality-contract.md. If the project wants a machine-readable copy for gate tooling, also emit .qa/quality-contract.yaml in the shape shown in the template.
Then say plainly what the contract does not cover: practices dropped for missing surface, practices deferred to the next maturity level, and anything marked UNKNOWN.
A contract is a living artifact. On a re-run, diff against the previous one and report direction: practices that moved to PRESENT, practices that regressed, waivers that expired, blockers that remain. Hand that diff to tracking-quality-trends if a trend history is being kept. A contract that only ever gets written once becomes wallpaper.
critical-regulated produces a contract nobody can satisfy, and the whole document gets ignored.npx openapi-typescript ./openapi.yaml -o src/types/api.ts is../resources/approach-catalog.md - the practice catalog: tier, maturity, MUST/SHOULD/COULD per profile, tool, exit criterion, effort./resources/profiles.md - the three risk profiles, how to choose one, and their metric thresholds./resources/maturity-model.md - crawl / walk / run, entry criteria, and what each level unlocks./resources/detection-signals.md - per-practice evidence for PRESENT / PARTIAL in a JS/TS repo./resources/contract-template.md - output structure for the contract, gap matrix, and remediation planscoping-change-relevance - when the question is which contracted practices apply to one specific diffgoverning-quality-waivers - when a practice will not be done and the skip needs a reason, an owner, and a dategenerating-quality-gate-workflows - when the agreed contract has to be enforced in CItech-debt-analysis - when the question is code, test, and dependency health rather than which practices are mandatoryassessing-release-readiness - when the contract and gap matrix become evidence for a go/no-go callanalyzing-quality-metrics - when the contract's metric thresholds need definitions and honest interpretationThis skill is complete when:
testing
Tests the customization assets themselves - skills, prompts, custom agents, instructions - the way a product is tested: activation cases that check an asset fires when it should and stays quiet when it should not, output-contract cases, safety cases, collision cases between assets competing for the same trigger, a weighted rubric scored blind, and a baseline-versus-candidate gate before an edit ships. Use when a skill is edited and nobody knows whether behaviour changed, when two skills fight over the same request, when a description is being tuned for discoverability, when a collection has grown past manual spot-checking, or when the request mentions skill evals, prompt regression, or "does this skill actually work".
development
Shapes QA output for the person who has to act on it: result and blocker in the first two lines, one decision per report, findings ordered by what they cost, the long artifact in a file and the decisions in the message, and magnitude stated in units the reader can count. Use when a report is accurate but nobody acts on it, when a finding set is too long to read under time pressure, when the same findings must be retold for a developer, a release manager, and an on-call engineer, or when the request mentions "too long", "make this readable", "just tell me what to do", "so what", or "summarize this for stakeholders". Pairs with unslop-answers, which makes the same report honest.
testing
Verifies that the lines and branches a change actually touched are executed by tests, using LCOV or Cobertura diff coverage instead of whole-repo percentages, and escalates uncovered high-risk changes into a blocking finding. Use when a pull request needs a coverage gate that unrelated tests cannot satisfy, when total coverage looks healthy but the diff is untested, when wiring diff coverage into CI, or when someone claims a change is covered because the suite is green.
development
Cuts AI tells from test code: tests that pass without proving anything, tautological assertions, mock-only tests, hardcoded waits, coverage theater, vague names, swallowed errors, retries used as fixes. Use whenever test code is written, changed, or reviewed, including tests produced as a side effect of a feature task, and when the request mentions "review these tests", "are these tests any good", "this test always passes", "this suite is flaky", or "clean up these tests". Must always apply to test code.