agentleFS
dayvisonassisdayvisonassis/sdd-skills/skills/qa-preflight/SKILL.md

qa-preflight

Skill3 starsChanged 32 days agoMITView on GitHub

The gate between a finished feature and the human QA. Investigates the delivered feature against its spec and the running screen, executes what is automatable, dispatches the existing correctors for defects that are objectively wrong, leaves a permanent guard so each defect cannot return unnoticed, and writes a QA plan (md + csv) plus a findings report carrying only what needs human judgement. Invoked by a HUMAN when the feature is done — never by spec-writer, implement-feature or evaluator.

The file

Show its rules and text

We split this skill into the rules it gives an agent

15 rules. About 0 are common, 13 are distinctive, and 2 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈13

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 2

    Very specific

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

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Standalone by decision: No other skill invokes this one.

    line 22
  2. Distinctive:

    Run these before anything else and stop at the first failure, naming it.

    line 65
  3. Distinctive:

    Every divergence goes through the fix × escalate rule below.

    line 149
  4. Distinctive:

    If this skill is ever dispatched non-interactively, it does not skip the checkpoint: it stops and reports that it needs one.

    line 162
  5. Distinctive:

    Before presenting the lists, ask the person who watched the headed run one question:

    line 168
  6. Distinctive:

    Re-execute what was corrected: before moving on. The plan must describe the fixed product.

    line 195
  7. Very specific:

    Write the three artifacts using references/report-template.md verbatim for structure, and derive the cases with references/qa-practices.md.

    line 244
  8. Distinctive:

    Do not write the files if any of these holds.

    line 261
  9. Distinctive:

    Run the environment preflight first, and name the failing check.

    line 303
  10. Distinctive:

    Stop at the checkpoint and wait for approval before any correction.

    line 304
  11. Distinctive:

    Ask, at the checkpoint, what the watcher saw that the run did not report.

    line 308
  12. Very specific:

    Leave Status empty — the verdict is the QA's.

    line 312
  13. Distinctive:

    Write the blocking reason whenever a case cannot be executed.

    line 314
  14. Distinctive:

    Run the investigation headless — that is the visual gate's job, not this one's.

    line 322
  15. Distinctive:

    Write an assertion into a visual suite that is not enabled — deliver it ready in the findings report instead.

    line 323

≈ “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

QA Preflight

A gate, not a plan generator. A plan generator moves work onto the human; this removes work from the human and uses what remains as the definition of what actually needs a person.

References, loaded on demand: references/qa-practices.md (how cases are derived) and references/report-template.md (the exact output skeletons). Both travel with this skill, so both resolve wherever it is installed.

The rationale — why each rule exists and what this skill deliberately does NOT do — is in docs/Skill_QA_Preflight.md of the sdd-skills repository, which is where the skill is maintained. That file is not part of an installed copy, and the relative path this note used to give (../../docs/) resolved to nothing outside the source repository. Everything needed to RUN the skill is in the folder you are reading; go to the rationale only to change a rule, and change it there.

Standalone by decision. No other skill invokes this one. It runs when the feature is done, on explicit human request. Running it mid-implementation produces noise about code that is still moving.

It owns no correction logic. Defects are fixed by dispatching the correctors that already exist, with the discipline they already have.

One carve-out, and only one: the visual guard. A permanent guard that is a test goes to the matching test-writer — a guard for a user flow goes to e2e-test-writer when the project has an e2e suite (GATES.md lists an e2e gate proven green). A guard that is a gate rule stays a proposal in the findings report: building gates is gate-builder's job. The exception is a computed-value assertion (contrast, height, density): no test-writer covers the visual suite, so when the visual gate is enabled the skill writes that assertion itself. This is guard code, not product behaviour — it changes what is checked, never what the application does. Production code stays off-limits under every circumstance, and the guard still goes through the checkpoint like any other change.

INPUT

  • Target feature (ID, e.g. F08).
  • Auto-discovers: the feature's spec.md / plan.md / contract.md, its PRD section, progress.json, the routes and permission blocks it added, and its diff against the integration branch.
  • Reads the project's design-system doc when one exists, found by the resolution order of the design-system skill (../design-system/SKILL.md, Step 1), for the numeric values the accessibility axis asserts. Without a doc, the accessibility axis falls back to the generic WCAG floors in references/qa-practices.md; a value that comes only from that skill's bundled baseline is never asserted as a defect.

OUTPUT

  • docs/qa/QA-<FEATURE>.md — the plan the human QA executes.
  • docs/qa/QA-<FEATURE>.csv — the same matrix, importable as a database.
  • docs/qa/ACHADOS-<FEATURE>.md — what was found, what was fixed, what was escalated, and the permanent guard proposed for each finding.
  • Zero or more correction commits, made by the dispatched skills, never by this one.

PHASE 1 — Investigation

1.1 Environment preflight

Run these before anything else and stop at the first failure, naming it. A session that dies in timeouts teaches nothing about the product.

CheckOn failure, say
Frontend answers on the base URL"the app is not answering at <url> — bring the stack up"
The served bundle is current"the dev server is serving a stale bundle — its last build failed: <error>"
Backend answers"the API is not answering at <url> — the screen will render empty"
Browser runner installed"@playwright/test is declared but not installed — run the install at the repo root"
Automated login workssee below
The account's tenant has data for this feature"the account <login> sees no data for this feature — seed it, or nothing can be measured"

HTTP 200 does not mean the code under test is the code on disk. A dev server whose last build failed keeps serving the previous bundle, happily and indefinitely. Read the dev server's log for a build error before trusting anything measured afterwards — in a real run, the dev server had been stuck on leftover merge-conflict markers for hours, the preflight passed it, and a CSS fix appeared not to work because the browser was three hours behind the tree.

On login, and this is not negotiable:

Never seed a session, forge a token, or bypass an anti-bot protection. Check whether the development environment offers a documented non-production escape hatch (a flag that disables verification outside production). If it does, use it and say so in the plan's prerequisites. If it does not, stop and report — an environment that cannot be driven is a finding for the team, not an obstacle to work around.

Log in once and reuse the session. Save the authenticated storage state after the first login and reuse it for every case. Logging in per case throws dozens of attempts at the auth endpoint and trips the rate limiter: a real run produced HTTP 429 midway, and three cases failed in a way that looked exactly like a product defect. When a 429 appears, say so — it is an artefact of how the run was driven, not a finding about the feature.

Reusing a session you obtained legitimately is not forging one. The rule above forbids manufacturing access the application did not grant; it does not require throwing away access it did.

1.2 Read

Spec, plan, contract and the PRD section. The routes the feature added and the permission required by each. The templates it changed. The tests and gates that already cover it — that is where the Verificado por column comes from.

1.3 Execute

Always drive the browser headed — playwright-cli open --headed. The default is headless; passing the flag is not optional here.

This is not a preference about watching a robot work. The human running this skill watches the session live, and what they catch is what the skill did not: a misaligned element, copy that reads wrong, a transition that stutters, a control nobody thought to enumerate. A hidden screen turns that person into a reader of reports; a visible one makes them a second pair of eyes on the product itself. Every gap they spot is a gap in this file, and the way the skill gets better (see 2.1).

A headed run is also why dark theme comes first — someone is looking at the screen, and the light pass is kept as short as possible.

Do not confuse this with the visual gate, which runs headless on purpose: the gate is an unattended check in a pipeline, this is an attended investigation.

Drive the real screen with the playwright-cli skill:

  • every control, one at a time — a screen that loads is not a screen that works;
  • every filter with a value that returns results — an empty result validates nothing;
  • the empty state, and the failure state, which must not look alike;
  • both themes, dark first;
  • each profile that sees the feature, when more than one does.

Record for each case whether it was executed and what was observed. Anything not exercised is inconclusive — never recorded as working.

Measure only after the value settles. An element that is still animating reports a smaller box: poll the measurement until it repeats, then assert. Waiting on the element's own animations is not enough — a dialog's scale usually lives on an overlay above it, so its subtree reports nothing to wait for. Polling the value is animation-agnostic and measures the thing you care about rather than a proxy for it.

A value that changes with something it cannot depend on is a measurement bug, not a defect. A height that differs between colour themes is the clearest example. Re-measure before classifying: a real run reported a 33px field that did not exist, and the settled value was exactly the 38px the design system specifies.

1.4 Classify

Every divergence goes through the fix × escalate rule below. The output of phase 1 is a short inventory — surfaces, actors, non-obvious rules, risks in order — plus the classified findings. No file is written yet.


PHASE 2 — Checkpoint (mandatory)

Present the inventory and the findings split in two lists: what will be fixed, and what goes to the QA. Then stop.

No correction happens before human approval — including the mechanical ones.

If this skill is ever dispatched non-interactively, it does not skip the checkpoint: it stops and reports that it needs one. Editing already-validated code with nobody looking is the failure mode this phase exists to prevent.

2.1 Ask what the screen showed that the report did not

Before presenting the lists, ask the person who watched the headed run one question:

"What did you see that I did not report?"

Anything they name is treated like any other finding — classified, fixed or escalated. But it carries one extra obligation: a finding that came from the human and not from the run is a gap in this skill. Record it in the findings report under Guardas permanentes propostas with what the derivation would have needed to catch it — a new check in the accessibility axis, a control the enumeration skipped, a state nobody modelled.

This is the loop that makes the skill improve instead of ossify. It only exists because the run is watched, which is why 1.3 is headed and not negotiable.


PHASE 3 — Correction (by dispatch)

For each approved finding, emit an entry in the report schema (../evaluator/references/evaluation-report-schema.md) and dispatch by kind:

kindMeaningDispatch to
gatea declared gate is violatedfix-runner
observable-criteriona contract criterion is not metfix-runner
qa-findinga real defect no contract criterion covered — ref is the QA case IDfix-runner
testcoverage missing for a rule already in the code — or, for e2e, the guard of a defect about to be fixedthe matching test-writer (unit / integration / e2e)

Re-execute what was corrected before moving on. The plan must describe the fixed product; writing it first would document the defect as if it were the behaviour.

Confirm every test a writer returns — unit, integration or e2e, written for coverage or as a guard — with the matching test-validator before trusting it, passing the feature's contract.md (when it has one) and the writer's checklist.

  • PASS or PASS WITH WARNINGS → the test stands and the finding is corrected. The warnings are listed in the findings report, and the test file is left uncommitted and listed there, for the human to commit with the QA artifacts.
  • FAIL → the finding moves to the escalated list, with the validator's findings: a test that does not conform guards nothing. Its file stays where the writer left it, uncommitted, and is listed in the findings report as not conforming — not as a guard to commit. The writer is not dispatched again: one finding, one dispatch.

A fix-runner signal can carry "test to correct: <file> — <title>": a test its correction made stale. Check the claim against the spec, then dispatch the matching test-writer for that test in correction mode and confirm it like any other; a claim that does not hold escalates the finding. The fix is committed and the rewritten test is not, so say in the findings report that the fix's commit passes its tests only together with that file. When the correction came back uncommitted — a commit hook ran that test — list the correction and the rewritten test together in the findings report, for the human to commit as one.

One finding per dispatch — except an e2e-guarded defect, which is one sequence of three (guard, fix, guard re-run). If a correction comes back "not resolved", the finding moves to the escalated list with that reason — it is never silently dropped. The e2e guard is the one exception: its expected first answer is "not resolved — product diverges", and that is the red-before-fix proof, not a failure. The guard re-run is this skill's own: run that one test headless with the e2e config (GATES.md) — the headed rule is for the investigation, not for this check — after confirming the dev server rebuilt. Escalate the finding instead when the guard comes back green before the fix (it does not reproduce the defect — remove only the guard test from its file — the file itself when it held nothing else — and only its own entry from the writer's checklist and coverage table, it guards nothing), when its validator verdict is FAIL, when it answers "environment", or when it is still red after the fix-runner reported the correction applied — unless that re-run is red for an environment reason, which is reported as such. The guard file is left uncommitted and listed in the findings report, next to the fix's commit, for the human to commit with the QA artifacts.

A unit or integration writer's done can carry lines that mean the coverage is not what was asked for: "no seam: …" — no test could be written for what it names — and "spec mismatch: …" — the test asserts what the code does, against the spec. Either one moves the finding to the escalated list, with the line: opening a seam changes code that was already validated, and when spec and behaviour disagree, which one is wrong is a product decision (the fix × escalate rule). A test the writer wrote on the way is left uncommitted and listed in the findings report, like a guard file.


PHASE 4 — Delivery

Write the three artifacts using references/report-template.md verbatim for structure, and derive the cases with references/qa-practices.md.

The matrix carries one block per area. Functional blocks use the feature's own area names (CT-PEDIDOS, CT-DATAS…). The four cross-cutting axes are always present, with reserved names and a fixed derivation technique:

BlockDerived by
Functional blocksstate transition + decision table for interacting controls
CT-FRONTEIRAequivalence partitioning + boundary values on every input
CT-PERMISSOESprofile × action matrix, including the disabled state and the reason in its tooltip
CT-FALHAper load: success, legitimate empty, error, and the business 409/422
CT-ACESSIBILIDADEthe WCAG 2.2 AA checklist, dark theme first, contrast composed over the real background

Self-audit — refuse your own output

Do not write the files if any of these holds; fix first:

  • an acceptance criterion of the feature has no case;
  • a case has more than one expected result;
  • a case depends on a previous one;
  • an expected result requires judgement instead of observation;
  • any case was left with an empty Verificado por;
  • a case the skill did not execute carries a filled Resultado Obtido.

The fix × escalate rule

When in doubt, escalate. The cost of escalating something fixable is a few minutes of a human's time. The cost of "fixing" something ambiguous is a silent behaviour change in code that was already validated.

Fix (mechanical, verifiable, no judgement)Escalate (always)
A deterministic rule a gate already encodesSpec and behaviour disagree — which one is wrong is a product decision
Contrast below the floor when a correct token exists, measured before and afterA business rule that is ambiguous or written nowhere
UI copy factually wrong against the implemented behaviourAny change to an API contract, schema or migration
A message key that does not exist falling back to the wrong labelAny file outside the feature — third-party legacy, another line of work
Missing coverage for a rule already in the code → dispatch the test-writerAesthetics, density, hierarchy — visual judgement
Anything the skill could not execute (hardware, telephony, credentials, a second tenant)

The golden rule

"Nothing to measure" is inconclusive, never passed. A case the skill could not exercise goes to the QA marked as such — screen without data, element that never appeared, assertion that never ran.

This rule exists because a real visual suite reported green while three of its assertions skipped themselves for lack of data, and the contrast assertion — the reason the suite existed — had never executed once. When it finally ran, it found a badge at 4.15:1 against a 4.5 floor.


RULES

Always:

  • Run the environment preflight first, and name the failing check.
  • Stop at the checkpoint and wait for approval before any correction.
  • Dispatch the existing correctors; re-execute what they corrected.
  • Confirm every test a writer returns with its test-validator before trusting it.
  • Drive the browser headed, so the person running this can see what you see.
  • Ask, at the checkpoint, what the watcher saw that the run did not report.
  • Log in once and reuse the session across every case.
  • Confirm the dev server's last build succeeded before trusting a measurement.
  • Let a measured value settle before asserting on it.
  • Leave Status empty — the verdict is the QA's.
  • Record provenance in Verificado por for every case.
  • Write the blocking reason whenever a case cannot be executed.

Never:

  • Edit production code directly — the only code this skill writes is a visual-suite guard.
  • Skip the checkpoint, even when dispatched non-interactively.
  • Seed a session, forge a token, or bypass an anti-bot protection.
  • Mark an unexecuted case as verified, or fill Resultado Obtido for one.
  • Report a rate-limit or stale-bundle artefact as a product defect.
  • Run the investigation headless — that is the visual gate's job, not this one's.
  • Write an assertion into a visual suite that is not enabled — deliver it ready in the findings report instead.
  • Touch files outside the feature under validation.
  • Validate a filter with a value that returns an empty result.

Edge cases

The feature has no contract.md — derive from spec.md and the PRD section, and record in the plan's non-scope that traceability is partial. Do not invent criteria retroactively.

The screen cannot be reached at all (route missing, permission denied for every test account) — stop after the preflight. A plan derived from code alone would describe intent, not the product.

A finding is fixable but the fix would touch a file outside the feature — escalate. The boundary is the file, not the difficulty.

The correction breaks something else — the dispatched corrector revalidates locally and returns "not resolved"; move the finding to escalated with that reason and continue.

Two profiles disagree about what should be visible and the spec is silent — that is a CT-PERMISSOES case escalated with both observations, not a defect to fix.

The visual gate is enabled in this project — then, and only then, the proposed assertions are written into the suite and proven to fail before the fix and pass after it.

The guard is a user flow — when the project has an e2e suite, dispatch e2e-test-writer with a kind: test entry (testSuite: e2e, ref = the QA case id, targetSurface = the surface and its route when it has one, the QA case's expected result in message, no testFile): with no existing test to fix, it runs in guard mode and writes the new one, judging it against that expected result — a qa-finding has no contract line. Order it like a visual guard: dispatch the guard before the fix — it must come back red ("product diverges") — then the fix-runner, then re-run the guard green. Confirm the guard with e2e-test-validator, as Phase 3 says of every test a writer returns: the contract and the writer's checklist are what let it check the tags. Without an e2e suite, deliver the flow ready in the findings report, like an assertion for a visual suite that is not enabled.

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.