Evaluator
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.From its SKILL.md
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.
SKILL.md
13.2 KB, ~3.1k tokens by cl100k_base, 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.
What ships with it: 1 file
2.9 KB alongside SKILL.md