Evaluator
Spec-driven development skills for Claude Code: PRD → spec/contract → implement → contract-based evaluation with auto-fix
npx -y skills add dayvisonassis/sdd-skills --skill evaluatorAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Externally evaluates an already-implemented feature against its contract.md (environment, quality gates, coverage manifest, observable criteria), producing screenshots, a report, and chat findings. Owns the evaluation loop — keeps the attempt counter in progress.json, decides the state (CLEAN/FAIL/PENDING/ABORTED), and routes each failure: code failures (gate/observable) to fix-runner, test failures to the matching test-writer (then confirmed by the matching test-validator) before resuming. Loops until CLEAN, PENDING, or ABORTED.
SKILL.md
13.2 KB, as published. Nobody here has run it
Evaluator
A second, independent layer of validation. After implement-feature finishes a feature, the evaluator looks at it from the outside and confirms — against contract.md — whether the delivery conforms. It finds deviations the implementer's self-check missed. It does not fix code; it evaluates and orchestrates the correction loop, dispatching fix-runner on failure.
Base docs:
https://github.com/dayvisonassis/sdd-skills/blob/main/docs/Skill_Evaluator.md(full rationale),https://github.com/dayvisonassis/sdd-skills/blob/main/docs/Contrato_de_Feature.md(contract structure),https://github.com/dayvisonassis/sdd-skills/blob/main/docs/Como_criar_gates.md(gates),https://github.com/dayvisonassis/sdd-skills/blob/main/docs/Fluxo_SDD_e_Implementacao_das_Skills.md(flow, states, progress.json schema). Report schema:references/evaluation-report-schema.md.
The evaluator complements automated tests — it does not replace them.
INPUT
Free-form. The skill needs:
- The target feature (ID/name) — explicit and required. Abort if absent or ambiguous (list candidates).
- Auto-discovers:
progress.json(root ofdocs/) and the feature'scontract.md(indocs/<feature-id>-<kebab>/). - Optional free-form overrides at the end — e.g. "no screenshots", "gates only", "max 5 attempts" (overrides
maxFixAttemptsfor this run).
If the feature has no contract.md, abort: "No contract.md for F<ID> — generate it with spec-writer first."
OUTPUT
- Screenshots — visual evidence of observable UI criteria (when applicable).
- Report — consolidated ✓ / ✗ / — per contract criterion and gate.
- Findings in chat — textual summary for the user.
- State in
progress.json— CLEAN | FAIL | PENDING | ABORTED for the feature. - On FAIL: a structured
evaluation-report.jsonin the feature folder, with each failure classified bykind(consumed byfix-runnerfor code, or a test-writer for tests). - The evaluator does not edit code or tests itself. Code corrections →
fix-runner; test corrections → the matching test-writer (confirmed by the matching test-validator).
EXECUTION STEPS
Step 1: Resolve Input
- Resolve the target feature (ID/name). Abort if absent or ambiguous, listing candidates.
- Locate
progress.json(root ofdocs/) and the feature'scontract.md. Ifcontract.mdis missing → abort ("generate the contract first withspec-writer"). Ifprogress.jsonis missing, create it withconfig.maxFixAttemptsdefault 3. - Parse any overrides (e.g.
max N attempts,gates only,no screenshots) and record them for the report.
Step 2: Load Context
- Read
contract.md: Environment Contract, Quality Gates (withids), Coverage Manifest, Surfaces & Behaviors, Observable Criteria (withids). - Read
progress.json: this feature'sstate,attempt, andconfig.maxFixAttempts(N). - The contract is the single source of acceptance criteria. Do NOT invent criteria outside it.
Step 3: Verify Environment Contract
- Check each environment prerequisite (runtime up, services reachable, tools available — e.g. dev server serving
/, Playwright CLI present). - If the environment is not satisfied → do NOT proceed to evaluation. Set
state: PENDING(human/environment intervention needed), explain that this is an environment problem (not an implementation failure), and stop. Environment-invalid ≠ implementation-wrong.
Step 4: Run Quality Gates
- Execute each gate declared in the contract (typecheck, lint, build, tests, arch...). Use the exact commands from the contract.
- Any gate failing is a contract violation. Collect the command + log as evidence.
- Classify each failure by cause (this drives the correction routing in Step 7):
- The failure is a code failure (
kind: gateorobservable-criterion) when production code is wrong — a type error, lint/build/arch violation, or a missing observable behavior. - The failure is a test failure (
kind: test) when the test itself is broken/non-conforming — e.g. thetestsgate fails and the cause is the test file (missing/incorrect mock, wrong pattern, a test that no longer matches correct behavior), not the production code. For akind: testfailure, fill the routing fields (testSuite,testFile,targetFile) perreferences/evaluation-report-schema.md. - When ambiguous (a failing test that might reflect a real code bug), prefer
kind: gate/observable-criterionand letfix-runnerhandle the code; only route to a test-writer when the test is clearly the thing that is wrong.
- The failure is a code failure (
- (If
gates onlyoverride is set, skip Step 5 and go to Step 6 with just gate results.)
Step 5: Validate Surfaces & Observable Criteria
- For each surface in the Coverage Manifest, start from its declared initial state and exercise the concrete behaviors (e.g. navigate the route via Playwright CLI, capturing screenshots).
- For each Observable Criterion, collect verifiable evidence (e.g. CTA present, login in top nav, redirect behavior, visual identity). A criterion with no observable evidence is a failure (
kind: observable-criterion,ref: <crit-id>). - Map every PRD-derived acceptance back to a contract criterion/gate (the contract already did this traceability; honor it).
Step 6: Decide State
Determine the feature's state strictly from contract adherence — never from "looks ok":
- CLEAN — no failures: all gates pass, all observable criteria met. → record state, proceed to Step 9.
- FAIL — at least one correctable failure (gate/test/observable). → go to Step 7 (loop).
- PENDING — something the evaluator cannot test by itself (needs a human, or an environment it cannot bring up). → record state with a note, proceed to Step 9.
- ABORTED — decided in Step 7 when attempts are exhausted.
List exactly which gates/criteria failed.
Step 7: Correction Loop (when FAIL) — route by failure kind
- Read
attemptandmaxFixAttempts(N) fromprogress.json. - If
attempt >= N→ setstate: ABORTED; stop and report (the loop tried N times without converging). Proceed to Step 9. - Else:
- Write/refresh
evaluation-report.jsonin the feature folder (schema inreferences/evaluation-report-schema.md) with the currentattemptand the classifiedfailures[]. - Set
state: FAILinprogress.jsonand persist the report path inlastEvaluationReport. - Route each failure by
kind:kind: gate/observable-criterion(code) → dispatchfix-runner, passing the feature ID and the report path. Unchanged behavior — the on-disk report is the source of truth.kind: test→ run the test-correction sub-flow (Step 8) for that failure. Never send test failures tofix-runner.
- When the dispatched correction returns:
- Correction applied → increment
attemptinprogress.json, then re-evaluate: go back to Step 3. - "not resolved — <reason>" → still increment
attempt; ifattempt >= NsetABORTED, else re-evaluate. Do not loop without incrementing.
- Correction applied → increment
- Write/refresh
The evaluator owns the counter, the limit N, and the ABORTED decision. Correction skills are stateless and never decide when to stop.
Step 8: Test-correction sub-flow (kind: test)
For a test failure, correcting the code is the wrong move — fix the test, then re-confirm it
conforms. Select the suite from testSuite/testFile (deterministic rule in the schema):
unit → unit-test-*, integration → integration-test-*, monorepo → monorepo-unit-test-*.
- Fix the test — dispatch the matching test-writer in correction mode (autonomous),
passing the feature ID, the
evaluation-report.jsonpath,testFile, andtargetFile. It fixes only the flagged test (smallest footprint), never production code. - Confirm conformance — dispatch the matching test-validator on the corrected
testFile.- Verdict PASS (or PASS WITH WARNINGS) → the test now conforms; resume the evaluation where it left off (re-run Step 3+ / the failing gate) and continue.
- Verdict FAIL → the correction did not conform. Treat this round as a spent attempt:
increment
attempt; ifattempt >= N→ABORTED; else loop (dispatch the test-writer again with the validator's findings, then re-validate).
- Only after the test-validator returns PASS does the evaluator continue its own evaluation.
The test-writer/validator pair is a sub-loop inside the evaluator's main loop. It still consumes the single
attempt/N budget — never iterate the sub-loop without incrementing.
Step 9: Persist State & Report
- Write the final
state(CLEAN | PENDING | ABORTED) andupdatedAtfor the feature inprogress.json. Preserveconfigand other features' entries (merge, don't replace). - On CLEAN, you may clear or keep
lastEvaluationReport(a stale FAIL report should not imply a current failure — prefer clearing it). - Output the report to chat:
Feature F<ID> — <name>
State: CLEAN | FAIL→(looped) | PENDING | ABORTED
Attempts used: <attempt> / <maxFixAttempts>
Quality gates:
✓ <gate-id> passed
✗ <gate-id> failed: <message> (<command>)
Observable criteria:
✓ <crit-id> — <evidence / screenshot path>
✗ <crit-id> — <what was missing>
Surfaces evaluated:
- <surface-id>: <result>
Environment:
✓ contract met | ✗ not met → PENDING (<which prerequisite>)
Findings:
- <key deviations the evaluation found>
Next:
- CLEAN → feature ready for the next stage
- PENDING → needs human intervention: <what>
- ABORTED → tried <N> fixes without converging; see last evaluation-report.json
RULES
Always:
- Treat
contract.mdas the single source of acceptance criteria. - Abort the evaluation if the Environment Contract is not met, and say it is an environment problem (→ PENDING).
- Run the contract's Quality Gates as objective checks before/with functional inspection.
- Derive the state from contract adherence, with evidence per criterion.
- Own the loop: keep
attempt/maxFixAttemptsinprogress.jsonand decide CLEAN/FAIL/PENDING/ABORTED. - Classify each failure by kind and route it:
gate/observable-criterion→fix-runner;test→ the matching test-writer (then confirmed by the matching test-validator). - After a
kind: testcorrection, require the test-validator PASS before resuming the evaluation. - Re-evaluate after each correction until CLEAN, PENDING, or ABORTED.
- Increment
attemptonce per correction round (code or test); never loop without incrementing.
Never:
- Alter production code or "fix" the feature yourself — code corrections are the
fix-runner's job, test corrections are the test-writers' job. - Send a
kind: testfailure tofix-runner, or akind: gate/observable-criterionfailure to a test-writer. - Approve based on visual perception without running the objective gates.
- Evaluate a feature without a
contract.md. - Invent criteria not present in the contract.
- Exceed
maxFixAttemptswithout marking ABORTED (the test sub-loop shares the same budget). - Write
PENDING_EVALUATIONintoprogress.json— that is the implementer's pre-state; the evaluator writes CLEAN/FAIL/PENDING/ABORTED. - Confuse an environment failure (PENDING) with an implementation failure (FAIL).
Edge Cases
No contract.md for the feature: abort and direct the user to spec-writer.
progress.json missing: create it with config.maxFixAttempts = 3 and this feature's entry.
Environment Contract not met: state = PENDING, clearly labeled as environment, no fix-runner dispatch.
Gate command not runnable in this environment (e.g. missing toolchain): treat as PENDING for that gate (needs environment), not FAIL — do not send the fix-runner after an environment gap. Note it in the report.
maxFixAttempts reached: state = ABORTED; keep the last evaluation-report.json for inspection.
fix-runner reports "not resolved": increment attempt; abort to ABORTED if the limit is hit, otherwise re-evaluate.
Override max N attempts: use N for maxFixAttempts this run (and persist it to config if the user intends it to stick — otherwise apply for the session only and note it).
Observable criterion is runtime-only and the runtime can't be exercised: PENDING for that criterion (human/environment), not FAIL.
Feature already CLEAN in progress.json: re-running is allowed (idempotent re-check); report the result and refresh state.
Cross-feature criteria: if the contract references behavior provided by another feature, evaluate only this feature's surface; note cross-feature dependencies in findings rather than failing on another feature's gap.