Getting it into your agent
One page per mod, every tool's command on it. A separate URL per tool would split the same page into five that compete with each other.
npx skills add niki914/zafiro --skill test-triagegit clone --depth 1 https://github.com/niki914/zafiroWrote this? Show the measurements
A badge with what this costs and how it scanned, read live from this page, so it follows the numbers instead of freezing them. Markdown for a README, HTML for a documentation site or a project page.
[](https://agentmods.dev/skills/niki914/zafiro/test-triage)<a href="https://agentmods.dev/skills/niki914/zafiro/test-triage"><img src="https://agentmods.dev/badge/skills/niki914/zafiro/test-triage/github.svg" alt="Measured on agentmods" height="20"></a>Or the 80×15 button, for a site that already has a row of RSS and ATOM ones. Only the verdict fits; the numbers stay here.
<a href="https://agentmods.dev/skills/niki914/zafiro/test-triage"><img src="https://agentmods.dev/badge/skills/niki914/zafiro/test-triage.svg" alt="Reviewed on agentmods" width="80" height="20"></a>What it costs to keep this loaded
Counted locally with the o200k_base tokenizer, which is exact for GPT models; Claude uses its own tokenizer and its counts differ. Treat this as one consistent yardstick across the catalogue rather than a bill. Prices are per million input tokens.
| Model | Per session | Once invoked |
|---|---|---|
| Fable 5.1 | $0.00071 | $0.02182 |
| Opus 5.5 | $0.00028 | $0.00873 |
| Sonnet 5.5 | $0.00014 | $0.00436 |
| Haiku 4.5 | $0.00007 | $0.00218 |
Grade A, and why
test-triage scanned grade A with 0 findings against 26 rules in 11 categories — prompt injection, anti-refusal, data exfiltration, privilege escalation, supply chain, agent snooping, system-prompt leakage, SSRF and excessive agency — measured 9d ago.
A static scan of the body, not an audit. Every finding is printed with the line that produced it so you can judge whether it matters here. A mod is markdown that instructs an agent; that is exactly why what it instructs is worth reading.
Nothing flagged
None of the 26 patterns this scan looks for appear in this file: no shell pipes, no recursive deletes, no credential paths, no hidden text, no instruction-override or anti-refusal phrasing, no agent-config snooping. That is not a guarantee, it is the absence of the things that are checkable.
How it starts
The opening of the file, as written. The whole thing — 156 lines — stays where its author put it; the contents beside it link to each section on GitHub.
Test Triage
写测试前先分诊:这个测试该不该存在。通过了才谈怎么写。
一个测试的全部价值来自它的拦截力——删掉它,哪个真实 bug 会漏到用户手上?答不上来的测试拦截力为零:不要写,已经写了的删掉。
测试膨胀的根源不是测试写得不好,是没经过分诊就写下去了。
门禁
动手写 @Test 之前,先回答一句话:
删掉这个测试,哪一个真实发生过、或真实可能发生的改动,会让 bug 漏出去?
答案必须是一个具体的改动:谁改什么、怎么改坏、漏出去之后用户看到什么。答得出来 → 往下写;指不出来 → 不写。
"我想确认它是对的"不是答案。那是静态分析、类型系统、编译器的工作。
改已有测试,也要过同一道门禁
动任何一个已存在的 @Test 之前,拿同一句话再问它一遍,另外加一句:
如果这个测试今天要我从零写一遍,我还会写吗?
不会 → 删掉它,而不是改两行让它继续绿。
改测试只有两种正当理由:被测契约变了(该重写),或测试本身有缺陷(该重写)。"让它变绿"不是理由。
一票否决:看到这些,直接不写
不需要判断,也不需要"至少测一下"。
| 被测对象 | 为什么拦不住 bug | 处置 |
|---|---|---|
data class 的字段、copy()、equals/toString |
编译器已经保证 | 不写 |
| 常量、枚举成员、默认参数值 | 编译器已经保证 | 不写 |
| getter / setter / 纯委托的转发方法 | 没有分叉点 | 不写 |
| private 辅助方法的单独测试 | 通过 public 行为间接覆盖 | 不写 |
| 资源字符串、文案、提示语的措辞 | 文案不是行为 | 不写 |
| 日志有没有打、打成什么 | 不是行为 | 不写 |
| ServiceRegistry 装配、DI 注册、构造注入 | 装配错了启动就崩,不用断言 | 不写 |
| 断言某字段"以后仍然是 null / 仍然不会被赋值" | 拦的是一个尚不存在的变化 | 不写 |
| 断言某个已删除 / 遗留的东西不存在 | 拦的是过去的影子 | 不写 |
| 另一个测试已经完整覆盖的同一契约 | 两个测试守一个契约 = 只有一个 | 不写,删重复的那个 |
一票通过:这些是拦截力的来源
行为会分叉,而分叉点在静态分析里看不出来——这才是值得写的。
| 形态 | 为什么值得 |
|---|---|
| 状态机迁移,含非法迁移与出错后停在哪 | 迁移关系不在类型里 |
if / when 的条件分支、边界值、空集合、超长输入 |
分支覆盖不可静态推导 |
| 解析、序列化、编解码的畸形输入 | 真实数据会超出预期 |
| 权限、降级、兜底、重试路径 | 出错路径最容易写坏 |
| 并发、取消、顺序、重复调用的既定契约 | 时序不可静态推导 |
| 曾经真实回归过的点 | 已证实的拦截力,最高优先 |
| ViewModel / Reducer 的状态计算 | 是逻辑,不是渲染 |
UI 的硬边界
不给 UI 写测试。 渲染、布局、点击、滚动、主题、动画、文案换行——这些都是 UI,由人工和 QA 验证,不写 @Test。这条不开放讨论。
要测的是 UI 背后的状态机:ViewModel / Reducer / Controller 里那段"输入什么、状态变成什么"的纯计算。它和 Compose 无关,只是恰好被 UI 调用。
一个测试里如果出现了 Compose 的 @Composable、createComposeRule、semantics、onNodeWithText——放错地方了,删掉。
拦截力为零的四种形态
四类都归零,原因各不相同。给它们起了名字,方便在提交和评审里直接点名。
① 回声测试
构造一个对象,再断言它等于自己刚塞进去的值。
val model = ToolSpec(name = "a", enabled = true)
assertEquals("a", model.name)
它拦的是字段改名导致的编译错误——而编译错误不需要断言兜着。唯一能让它变红的方式是改坏赋值,那时候编译器先红。
② 钉文案
断言某个 message 等于一句写死的文案。
assertEquals("接口返回为空", error.message)
文案不是行为:它进资源、换措辞、做本地化,测试就为一个字而碎,与功能正确性无关。
What this file has done since we first saw it
Hashed on every crawl. A supply-chain change to an agent config is a question of when, not whether, so the history is kept rather than the latest state alone.
- 9d ago First seen · 156 lines · 71 tokens per session scan A d7d64b0b8f33
test-triage is a skill published in the GitHub repository niki914/zafiro (263 stars, last pushed 2d ago), licensed MIT. It adds 71 tokens to every session and 2,182 once invoked, about $0.0003 per session on Opus 5.5. A static security scan graded it A with 0 findings. No closer match exists in the catalogue, so it is treated as the original; first seen 2026-10-08.
Other skills, from other repositories
testing-expert
Ultimate Kotlin testing skill. Use this whenever writing, reviewing, or debugging ANY Kotlin test — unit, integration, property-based, or coroutine. Covers TDD (RED/GREEN/REFACTOR), Kotest + MockK + Kover, anti-pattern detection, and four-pillar quality framework. Triggers on: write a test, add coverage, why is this…
flutter-bloc-state-management
Implement BLoC/Cubit state, events, transitions, and async concurrency in Flutter. Use for BLoC/Cubit feature logic, debounced/cancellable events, state rendering, or bloc tests—not generic widget-only work.
knowledge-engineering-quality-and-delivery-unit-integration-and-shared-test-harnesses
A testing guide for the CLI and web interfaces, covering unit, integration, end-to-end, and real-process test setup with shared fixtures and cleanup.
test-writer
Write high-quality unit tests.
tdd-workflow
Use this skill when writing new features, fixing bugs, or refactoring code. Enforces test-driven development with 80%+ coverage including unit, integration, and E2E tests.
cpp-testing
Use only when writing/updating/fixing C++ tests, configuring GoogleTest/CTest, diagnosing failing or flaky tests, or adding coverage/sanitizers.