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-hang-watchdoggit 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-hang-watchdog)<a href="https://agentmods.dev/skills/niki914/zafiro/test-hang-watchdog"><img src="https://agentmods.dev/badge/skills/niki914/zafiro/test-hang-watchdog/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-hang-watchdog"><img src="https://agentmods.dev/badge/skills/niki914/zafiro/test-hang-watchdog.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.00066 | $0.01662 |
| Opus 5.5 | $0.00026 | $0.00665 |
| Sonnet 5.5 | $0.00013 | $0.00332 |
| Haiku 4.5 | $0.00007 | $0.00166 |
Grade A, and why
test-hang-watchdog 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 4d 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 — 115 lines — stays where its author put it; the contents beside it link to each section on GitHub.
Test Hang Watchdog
在本项目中,针对特定类的单元测试(testDebugUnitTest --tests "...")正常执行时间为 2 ~ 8 秒;全模块单测执行时间通常在 15 秒以内。
任何单测执行超过 30 秒,100% 存在死锁、挂起或桩缺失。 无限等待是零拦截力且严重浪费人机协同时间的行为。
1. 运行看门狗协议(主动介入,杜绝傻等)
运行单元测试命令时,必须遵循以下看门狗守则:
- 背景任务倒计时:
- 若
./gradlew testDebugUnitTest转入后台任务,严禁无限期挂起等待。 - 任务运行达到 15 秒 时主动查看一次进度与输出;
- 任务运行达到 30 秒 且仍在运行,判定为异常挂起,立即触发下文的「现场解剖 SOP」,绝不等待用户提醒。
- 若
- 测试超时防御:
- 涉及挂起函数(
suspend)、CompletableDeferred、Channel、Flow收集的用例,尽量在runTest中使用backgroundScope或以withTimeout(2_000)保护,杜绝裸runBlocking无界等待。
- 涉及挂起函数(
2. 现场解剖 SOP(30 秒内定位挂死点)
一旦测试任务超过 30 秒未结束,按以下步骤定位并熔断:
Step 1: 定位 Test Worker 进程
jps -v | grep GradleWorkerMain
(输出第一列即为运行当前测试用例的 JVM Worker 进程 PID,例如 82065)
Step 2: 抓取线程快照
jstack <worker-pid> | head -n 45
Step 3: 读取案发现场调用栈
在 jstack 输出的头部直接寻找 "Test worker" 线程(通常为 #3),查看第 20 ~ 30 行栈帧:
"Test worker" #3 prio=5 os_prio=31 ... waiting on condition
at jdk.internal.misc.Unsafe.park(Native Method)
- parking to wait for <0x...> (a kotlinx.coroutines.BlockingCoroutine)
...
at com.niki914.zafiro.business.agent.AgentManagerImplTest.switchTo_reusesExistingActiveAgent(AgentManagerImplTest.kt:50)
- 定位被测用例:栈顶清晰指示出是哪个测试类、哪个
@Test方法。 - 定位挂起原语:
LockSupport.parkNanos/CompletableDeferred.await:协程 deferred 从未被 complete;awaitSettingsGateway():缺少依赖注入/全局桩环境;runBlockingImpl:主线程等待子协程终态,子协程未退出。
Step 4: 果断熔断
立即终止挂起任务与 Worker 进程,避免占用 Gradle Daemon 槽位:
manage_task(Action='kill', TaskId='<task-id>')
kill -9 <worker-pid>
3. 四大典型挂死病灶与速治清单
通过调用栈定位到测试方法与具体行后,对照以下四大病灶对号入座:
病灶 ①:自引用状态死锁(Self-Referential Job State)
- 现象:测试在等待某组任务全部完成,例如
jobs.values.all { it.isCompleted }。 - 病理:在协程体执行内部去查询自身的 Job 状态——当前协程体未退出前,自身的
job.isCompleted恒为false,形成闭环死锁。 - 解法:解耦状态。使用独立的并发数据结构(如
ConcurrentHashMap<Key, Result>)显式记录各任务的结果,不要用未退出的 Job 生命周期代替语义结果。
病灶 ②:运行时测试桩缺失(Missing Test Doubles / Gateway)
- 现象:栈停在
RuntimeEnvironment.awaitSettingsGateway()或其他await*延迟装配门禁。 - 病理:生产代码依赖全局环境(如 Application 启动时安装的 Bridge/Gateway),而新写的单元测试
@Before setUp()中仅 mock 了局部 Store,漏掉了运行时 Gateway,导致协程无限等待 Bridge 安装。 - 解法:在测试的
@Before中安装测试专用 Stub(如StubRuntimeSettingsGateway),并在@After tearDown()中显式清理。
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.
- 4d ago First seen · 115 lines · 66 tokens per session scan A 196ef0d36c88
test-hang-watchdog is a skill published in the GitHub repository niki914/zafiro (259 stars, last pushed yesterday), licensed MIT. It adds 66 tokens to every session and 1,662 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-12.
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…
reproduce-bug
Reproduce a reported bug in googleapis/mcp-toolbox and decide whether it is real, delivering an evidence-backed verdict: confirmed, already fixed, misconfiguration, client-side, works as intended, not reproducible, or blocked. Use whenever a maintainer asks you to reproduce, verify, confirm, or investigate a bug…
fix-failing-tests
Diagnose a failing test in the googleapis/mcp-toolbox repo and land a fix by reasoning from the actual error: read the failure, reproduce it, shrink it until the cause is forced into the open, then fix the cause. Use this whenever a test or CI job is red, a build breaks after a change, many packages fail at once, or a…
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.
tricorder-cli
Full CLI reference for the tricorder daemon (build diagnostics, test results, source lookup, eval comments, logs). This is the fallback invoked by the tricorder skill when the tricorder-mcp MCP tools aren't available or aren't working — invoke tricorder first; it decides whether this is needed.
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.