test-report
Use this skill when analyzing promptfoo test results and generating evidence reports. Consumes pre-computed data from test-report-prepare.js, generates categorized markdown report with failure diagnosis and fix plan. Triggers on: test report, analyze test results, promptfoo report, test evidence, test failures, generate evidence.
- License 许可
- MIT
- 最近更新
- 2026-09-05
- Stars
- ★ 0
- Forks
- 6
01 前言 Front Matter
- name
- test-report
- description
- Use this skill when analyzing promptfoo test results and generating evidence reports. Consumes pre-computed data from test-report-prepare.js, generates categorized markdown report with failure diagnosis and fix plan. Triggers on: test report, analyze test results, promptfoo report, test evidence, test failures, generate evidence.
02 资源文件 1
- 脚本test-report-prepare.js15.2 KB
03 SKILL.md 正文
Analyzing Promptfoo Test Results
Consume pre-computed test data from test-report-prepare.js and generate a
detailed evidence report in .evidences/ with failure categorization, root
cause analysis, and a prioritized fix plan.
When to Use This Skill
- After running
promptfoo evaland wanting a structured evidence report - When asked to analyze test results, failures, or generate a test evidence file
- When the
/test-reportcommand delegates here after runningtest-report-prepare.js
Step 0 — Run the Prepare Script
VERBATIM — Run this bash block exactly as written. Do not modify, rephrase, or simplify the commands.
# Safe: test-report-prepare.js ships only under .claude/skills/ (repo-level), never under plugins/sdlc-utilities/scripts/, so this find never matches a plugin-cache copy and cannot carry #485's contamination.
SCRIPT=$(find ~/.claude/plugins -name "test-report-prepare.js" 2>/dev/null | sort -V | tail -1)
[ -z "$SCRIPT" ] && [ -f ".claude/skills/test-report/test-report-prepare.js" ] && SCRIPT=".claude/skills/test-report/test-report-prepare.js"
[ -z "$SCRIPT" ] && { echo "ERROR: Could not locate test-report-prepare.js. Is the sdlc plugin installed?" >&2; exit 2; }
DATA_FILE=$(node "$SCRIPT" --output-file $ARGUMENTS)
EXIT_CODE=$?
- If exit code 1: Read the JSON, surface
errors[]to the user, stop. - If exit code 2: Report the script crash, stop.
- If exit code 0: Read
DATA_FILEintoREPORT_DATA_JSON.
Error-to-GitHub issue proposal:
For exit code 2 (script crash), locate the procedure: Glob for **/error-report-sdlc/REFERENCE.md
under ~/.claude/plugins, then retry with cwd. If found, follow the procedure with:
- Skill: test-report
- Step: Step 0 — test-report-prepare.js execution
- Operation: Running test-report-prepare.js to pre-compute test data
- Error: Exit code 2 — script crash (full error on stderr)
- Suggested investigation: Check Node.js version; inspect stderr for stack trace; verify test-report-prepare.js is accessible via the plugin path
If not found, skip — the capability is not installed.
Clean up DATA_FILE after writing the report.
Step 1 — Consume Context
Read REPORT_DATA_JSON. Display a brief orientation:
Eval: {evalMeta.evalId} ({evalMeta.createdAt})
Type: {evalMeta.configType}
Passed: {summary.passed}/{summary.executed} ({summary.passRate}%)
Failed: {summary.failed} | Missing: {summary.missing}
Key fields reference:
| Field | Description |
|---|---|
evalMeta.evalId |
Eval run identifier |
evalMeta.configType |
behavioral or exec |
summary.passRate |
Integer percentage |
passingTests[] |
Tests with success=1 |
failingTests[] |
Tests with success=0; each has assertions[], responsePreview, gradingReason |
missingTests[] |
Tests defined in datasets but absent from results |
comparison |
null or {regressions[], improvements[], unchanged} |
Step 2 (PLAN) — Categorize Failures and Draft Report
Analyze failingTests[] and classify each into exactly one category:
Category A — Infrastructure Failures
latencyMs < 10000AND (responsePreviewis empty OR contains "Command failed")- Root cause: CLI crash, rate limit, concurrent session exhaustion
Category B — Assertion Failures
- LLM produced meaningful output (non-empty
responsePreview, no "Command failed") - Specific assertions in
assertions[]havepass: false - Sub-classify:
- B-false-positive: Failing assertion is
not-regexornot-icontainsAND response shows correct behavior (e.g., explicitly refuses or negates the thing being checked). Most other assertions passed. - B-true-failure: LLM genuinely produced incorrect output — the assertion correctly caught a real behavioral problem.
- B-false-positive: Failing assertion is
Category C — Missing Tests
- Items from
missingTests[]
For each Category B failure, draft:
- Failed assertion(s) with type and value
- Diagnosis (why the assertion fired, whether behavior is correct)
- Response preview excerpt (from
responsePreview— do not fabricate) - Specific fix suggestion (e.g., change assertion value, narrow regex, fix skill)
Draft the full markdown report using this template:
# Promptfoo {configType|title} Test Report
**Generated:** {current timestamp YYYY-MM-DD HH:MM:SS}
**Eval ID:** `{evalMeta.evalId}`
**Config:** `tests/promptfoo/promptfooconfig{-exec if exec}.yaml`
---
## Summary
| Metric | Value |
|--------|-------|
| Tests defined | {summary.totalTests} |
| Tests executed | {summary.executed} |
| Tests missing | {summary.missing} |
| Passed | {summary.passed} ({summary.passRate}%) |
| Failed — infrastructure | {count of Category A} |
| Failed — assertion | {count of Category B} |
| Avg latency | {summary.avgLatencyMs}ms |
| Total cost | ${summary.totalCost} |
**Overall health: {HEALTHY if passRate >= 90 | WARNING if 70-89 | CRITICAL if < 70} — {summary.passRate}% pass rate**
---
## Passing Tests ({summary.passed}/{summary.executed})
| Test | Skill | Score |
|------|-------|-------|
{one row per passing test}
---
## Category A — Infrastructure Failures ({count} tests)
{Description of the common failure pattern and root cause}
| Test | Skill | Latency |
|------|-------|---------|
{one row per Cat-A failure}
---
## Category B — Assertion Failures ({count} tests)
### B{n}: {test description}
- **Score:** {score} ({passed_count}/{total_count} assertions passed)
- **Failed assertion:** `{type} "{value}"`
- **Diagnosis:** {root cause analysis}
- **LLM behavior:** Correct/Incorrect — {explanation}
- **Response preview:**
{responsePreview, max 400 chars}
- **Fix:** {specific, actionable fix}
---
## Category C — Missing Tests ({count} tests)
| Test | Source |
|------|--------|
{one row per missing test}
---
## Failure Attribution
| Root Cause | Tests Affected | Fix |
|------------|---------------|-----|
{one row per distinct root cause}
**True behavioral failures:** {count of B-true-failure} — {summary sentence}
---
{IF comparison is not null:}
## Comparison with Previous Run
**Previous eval:** `{comparison.previousEvalId}` ({comparison.previousCreatedAt})
### Regressions ({count})
| Test | Previous Score | Current Score |
|------|---------------|--------------|
### Improvements ({count})
| Test | Previous Score | Current Score |
|------|---------------|--------------|
### Unchanged
- Still passing: {comparison.unchanged.stillPassing}
- Still failing: {comparison.unchanged.stillFailing}
{END IF}
---
## Fix Plan
### Priority 1 — Infrastructure ({count} tests affected)
{numbered action items: config changes, concurrency settings}
### Priority 2 — Assertion Corrections ({count} tests affected)
{numbered action items with file paths and specific assertion changes}
### Priority 3 — Behavioral Fixes ({count} tests affected)
{numbered action items with skill paths and what needs to change}
---
## Conclusion
{1-2 paragraph summary of overall health, key takeaways, and recommended next steps}
Step 3 (CRITIQUE) — Self-Review the Report
Check these gates before proceeding:
| Gate | Check |
|---|---|
| Completeness | Every failingTests[] entry appears in exactly one category |
| Count accuracy | Category A + B counts + missing = summary.failed + summary.missing |
| Passing count | Passing tests table row count = summary.passed |
| No fabrication | All response previews and assertion details come from REPORT_DATA_JSON |
| Actionability | Every failure has a concrete fix (not "investigate further") |
| Attribution | Every distinct root cause has a row in Failure Attribution table |
| No DB queries | Skill never runs sqlite3 — all data from script |
List any issues found.
Step 4 (IMPROVE) — Revise the Report
Fix all issues from Step 3. Repeat critique/improve up to 2 times until all gates pass.
Step 5 (DO) — Write the Report
-
Create
.evidences/directory if it does not exist:mkdir -p .evidences -
Generate filename using current timestamp:
TIMESTAMP=$(date '+%Y-%m-%d_%H-%M-%S') REPORT_FILE=".evidences/promptfoo-${CONFIG_TYPE}-report-${TIMESTAMP}.md" -
Write the final report to
REPORT_FILE. -
Clean up the temp data file (
DATA_FILE).
Step 6 (CRITIQUE) — Self-Review the Fix Plan
Only if summary.failed > 0. Check:
| Gate | Check |
|---|---|
| Ordering | Infrastructure fixes listed before assertion fixes before skill fixes |
| Specificity | Each action references a specific file path and/or assertion value |
| No eval runs | Does not suggest running promptfoo eval automatically |
| Completeness | All root causes from Attribution table have a fix action item |
List any issues.
Step 7 (IMPROVE) — Revise the Fix Plan
Fix all issues from Step 6. Up to 2 iterations.
Step 8 — Present Summary to User
Show:
Report written to: {REPORT_FILE}
Health: {HEALTHY|WARNING|CRITICAL} — {passRate}%
Passed: {summary.passed}/{summary.executed}
Category A (infra): {count}
Category B (assert): {count}
Category C (missing): {count}
Top fix priorities:
1. {first priority action}
2. {second priority action}
3. {third priority action}
{IF --compare: "Regressions: {count} | Improvements: {count}"}
Error Recovery
Flow: detect → diagnose → auto-recover (retry once if transient) → invoke
error-report-sdlcfor persistent actionable failures.
| Error | Recovery | Invoke error-report-sdlc? |
|---|---|---|
test-report-prepare.js exit 1 |
Show errors[], stop |
No — user input error |
test-report-prepare.js exit 2 (crash) |
Show stderr, stop | Yes |
| Zero test results (empty eval) | List available evals; ask user to verify | No — expected (empty run) |
.evidences/ directory not writable |
Show error; ask user to check permissions | No — environment issue |
When invoking error-report-sdlc, provide:
- Skill: test-report
- Step: Step 0 — test-report-prepare.js execution
- Operation: Running test-report-prepare.js to pre-compute test report data
- Error: Exit code 2 — script crash (full error on stderr)
- Suggested investigation: Check Node.js version; inspect stderr for stack trace; verify promptfoo DB exists at
tests/promptfoo/.promptfoo-data/promptfoo.db
DO NOT
- Run
sqlite3queries — all data comes from the prepare script JSON - Run
promptfoo evalor suggest running it automatically - Fabricate response content not present in
REPORT_DATA_JSON - Write to any file other than the
.evidences/report - Skip the plan-critique-improve cycle
Learning Capture
If analysis reveals patterns (e.g., "Cat-A failures correlate with concurrency > N",
"specific skill consistently produces false-positive assertion failures"), append
entries to .sdlc/learnings/log.md.
04 同仓库更多 Skills
example-skill
Test fixture — passing case for script-resolution-version rule.
example-skill
Test fixture — failing case for script-resolution-version rule.
example-skill
Test fixture — passing case for the orchestrator-await-barrier rule (#487). Marks a fan-out dispatch as await-barrier-required and states the guard.
example-skill
Test fixture — failing case for the orchestrator-await-barrier rule (#487). Marks a fan-out dispatch as await-barrier-required but never states the guard.
pr-sdlc
Creates or updates GitHub pull requests with auto-generated 8-section descriptions.
example-skill
Fixture skill for validate-cost-tiers drift tests.