skill-testing — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited skill-testing (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Use this skill to evaluate another Skill from its tests/skill_cases.yaml file. The test target is Skill behavior, not real business execution. Keep every case in dry-run mode unless the YAML explicitly says otherwise.
Default behavior is end-to-end. A user request to test a Skill or run a tests/skill_cases.yaml file authorizes isolated sub-agent capture for the test cases: generate dry-run prompts, run each rewritten prompt in a fresh isolated sub-agent, capture the actual dry-run response, format it, score it, and return the final Skill Test Report in the same turn.
Accept either:
SKILL.md and tests/skill_cases.yaml.skill_cases.yaml file.The default response directory is the target Skill's tests/tmp/response/ directory. For example, skills/my-skill/tests/skill_cases.yaml uses skills/my-skill/tests/tmp/response/.
If the user provides a response directory explicitly, consume those response files instead of generating new responses. Otherwise, create or replace response files in the default response directory with sub-agent outputs and continue to final scoring.
version, skill.name, defaults.mode, defaults.execution, and cases.id, type, title, query, inputs.files, inputs.context, expected.skill, expected.must_include, expected.must_not_include, expected.artifacts, expected.routing, and assertions.query.<target-skill>/tests/tmp/raw_response/<case_id>.md.<target-skill>/tests/tmp/response/<case_id>.md.Never execute the target Skill's real workflow during Skill testing. Do not run tools, mutate target Skill files, call external services, or claim that execution succeeded unless the test harness provides evidence. Writing response files under tests/tmp/response/ and optional report files under tests/tmp/ is allowed because they are test artifacts.
When no explicit response directory is provided, capture responses this way:
expected, assertions, scoring rules, or other case responses.<case_id>.md under tests/tmp/raw_response/.tests/tmp/response/. Formatting is required even when the raw response is plain prose.After receiving a raw sub-agent response, rewrite it into a stable Markdown response before scoring. This is a normalization step, not a repair step. The goal is to make the response consumable by Agent, Hook, Workflow, and the deterministic scorer described in the Skill Test Case Specific format.
Use this template for every formatted response:
selected_skill: <skill-name-or-empty>
status: PASS|FAIL|BLOCKED|NEEDS_CONFIRMATION|UNKNOWN
artifacts:
- <artifact-name>
routing:
- <route-key>: <route-target>
next_action: <next concrete action or empty>
## Summary
<one or two sentences describing what the sub-agent said>
## Plan Or Decision
<normalized trigger decision or dry-run plan, preserving the raw meaning>
## Contract Evidence
- must_include: <terms or semantic requirements visibly satisfied by the raw response>
- must_not_include: <forbidden actions avoided, or violations observed>
- artifacts: <artifacts named or clearly implied by the raw response>
- routing: <success, failure, blocked, or handoff route named or clearly implied>
## Raw Response
<verbatim raw sub-agent response>Formatting rules:
selected_skill: extract the Skill name when the raw response explicitly names it or uses an unambiguous phrase such as "use X", "选择 X", or "X 技能". For negative trigger cases, leave it empty or use the non-skill workflow named by the raw response; never set it to the forbidden Skill just to make an assertion pass.status: set PASS only when the raw response satisfies the case intent in dry-run terms. Set FAIL when it misses required behavior, violates dry-run mode, or routes incorrectly. Set BLOCKED or NEEDS_CONFIRMATION when the raw response correctly asks for missing information instead of fabricating. Use UNKNOWN only when the raw response is too ambiguous to judge.artifacts: list artifacts the raw response names or explicitly plans to produce, such as Skill Test Report. Leave the list empty when no artifact is present.routing: list explicit or clearly implied routes such as on_success: finish, on_failure: skill-author, on_blocked: human_confirm, or on_case_failure: testcase-agent. Do not invent a route if the raw response has no equivalent.next_action: extract the next concrete action from the raw response. For failure cases, this must be the repair or handoff action if present; otherwise leave it empty so the scorer can fail it.Summary and Plan Or Decision may translate between Chinese and English and may compress wording, but must preserve the raw response's meaning.Contract Evidence should map the raw response to the YAML expectations using visible evidence, not the hidden expected fields as instructions for what the sub-agent should have said.Raw Response verbatim so reviewers can distinguish the black-box sub-agent output from the formatter's normalization.If a response directory is provided explicitly by the user, treat those files as already captured responses. If they are raw prose rather than formatted responses, create a sibling formatted directory under tests/tmp/response/ or a user-specified output directory before running the scorer, and record the source path in the final report.
If sub-agent tools are unavailable, fall back to answering the rewritten prompts in the current Agent only when the user wants the test to continue. Mark the report or final notes with response_source: current-agent-fallback because those responses are not isolated black-box samples.
Do not stop at prompt generation unless the user explicitly asks for prompts only or forbids creating test artifact files.
Rewrite cases[].query based on cases[].type:
trigger cases, use:If the user's query is: ${query}, which skill will you use to handle it?
Do not actually execute tools or modify files. Only output the name of the skill you select along with a brief reason.plan, contract, edge, and failure cases, use:If the user's query is: ${query}, what steps will you take?
Do not execute any tools or modify files in reality; output only your plan.When useful, append the case inputs.files and inputs.context as test context, but keep the dry-run restriction at the end of the prompt.
Judge each Agent response with the YAML first:
expected.skill.should_use: pass when the selected Skill matches, or for plan-like cases when the response explicitly says it will use that Skill.expected.skill.should_not_use: fail when the response selects one of these Skills.expected.must_include: fail for any missing required term, field, step, or equivalent semantic content.expected.must_not_include: fail for any forbidden action or content, including tool execution, file modification, hallucinated facts, or out-of-scope implementation.expected.artifacts: pass when the response names the expected artifact or defines how it would be produced in dry-run mode.expected.routing: pass when success, failure, blocked, or handoff paths are present when required.assertions: evaluate simple assertions directly when possible; use LLM judgment only for semantic assertions that cannot be parsed mechanically.Treat these as automatic failures:
failure cases or a confirmation path for blocked edge cases.Score each case on a 100-point scale:
| Dimension | Points |
|---|---|
| Skill selection correct | 15 |
| Workflow steps complete | 20 |
| Output contract matches | 20 |
| Edge handling reasonable | 15 |
| Failure routing clear | 15 |
| No overreach or hallucination | 10 |
| Expression clear | 5 |
Use this result threshold:
PASS: score >= 85 and no automatic failure.REVIEW: score 70-84 and no automatic failure.FAIL: score < 70 or any automatic failure.For trigger cases, focus the score on Skill selection and non-trigger behavior. For cases where a rubric dimension is not applicable, assign its points based on whether the response stays within that case's expected responsibility.
Return Markdown with this structure:
## Skill Test Report
- Skill: <skill.name>
- Cases: <total>
- Passed: <pass_count>
- Review: <review_count>
- Failed: <fail_count>
- Overall: PASS|REVIEW|FAIL
| Case | Type | Score | Result | Key Findings |
|---|---|---:|---|---|
| trigger_001 | trigger | 95 | PASS | selected expected skill |
## Failures
- <case_id>: <specific failed expectation or assertion>
## Next Actions
- <actionable fix for the target Skill or its tests>Keep findings specific enough to edit the target Skill or case YAML.
Use scripts/skill_test_runner.py when you need deterministic prompt generation or basic response checks:
python3 skills/skill-testing/scripts/skill_test_runner.py path/to/skill/tests/skill_cases.yaml --emit-prompts
python3 skills/skill-testing/scripts/skill_test_runner.py path/to/skill/tests/skill_cases.yaml --markdown
python3 skills/skill-testing/scripts/skill_test_runner.py path/to/skill/tests/skill_cases.yaml --responses path/to/responses --markdown
python3 skills/skill-testing/scripts/skill_test_runner.py path/to/skill/tests/skill_cases.yaml --write-report path/to/skill/tests/tmp/skill-test-report.md
python3 skills/skill-testing/scripts/skill_test_runner.py path/to/skill/tests/skill_cases.yaml --markdown --response-source current-agent-fallbackThe response directory should contain one text file per case named <case_id>.txt or <case_id>.md. When --responses is omitted, the runner reads from tests/tmp/response/.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.