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 agentmods add skills/pingfanfan/hello-dsh/test-firstnpx skills add pingfanfan/hello-dsh --skill test-firstgit clone --depth 1 https://github.com/pingfanfan/hello-dshWrote 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/pingfanfan/hello-dsh/test-first)<a href="https://agentmods.dev/skills/pingfanfan/hello-dsh/test-first"><img src="https://agentmods.dev/badge/skills/pingfanfan/hello-dsh/test-first.svg" alt="Measured on agentmods" 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 | $0.00048 | $0.01028 |
| Opus 5 | $0.00024 | $0.00514 |
| Sonnet 5 | $0.00010 | $0.00206 |
| Haiku 4.5 | $0.00005 | $0.00103 |
Grade A, and why
test-first 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.
What it actually says
先写测试
核心判断标准只有一条:把实现回退掉,这个测试会不会失败?
不会失败的测试等于没有。它不保护任何东西,只制造覆盖率数字和维护成本。
顺序
先写测试有个具体的好处,跟"纪律"无关:它是唯一能证明测试有效的方法。
如果你先写实现再补测试,测试一上来就是绿的,你无法知道它是因为实现正确而绿,还是因为它根本没断言到关键的东西。先写测试的话,你会亲眼看到它从红变绿,这就是证明。
修 bug
- 写一个能复现这个 bug 的测试,跑,看它失败
- 确认失败信息就是这个 bug 的表现,不是别的原因
- 修实现
- 跑,看它变绿
第 2 步经常被跳过。测试失败了不代表它失败在你以为的地方,可能只是参数写错了。
加功能
- 写一个描述期望行为的测试,跑,看它失败
- 用最简单的方式让它通过
- 重构,保持绿
- 下一个行为,回到第 1 步
「最简单的方式」是认真的:如果硬编码返回值能让第一个测试通过,就先硬编码。第二个测试会逼你写出真实逻辑。这不是浪费,它避免了你一上来就构造一个想象中的通用方案。
测什么
测行为,不测实现。
| 测这个 | 不测这个 |
|---|---|
| 输入 X 得到输出 Y | 内部调用了哪个私有方法 |
| 出错时抛什么、状态如何 | 中间变量的值 |
| 副作用(写了什么、发了什么事件) | 具体的调用次数(除非次数本身是契约) |
| 边界:空、单个、超长、零、负数 | 私有字段 |
判断方法:重构实现但不改行为时,这个测试要不要跟着改? 要改,说明它测的是实现。
断言要具体
// 没用:任何非空返回都能过
expect(result).toBeTruthy()
// 有用
expect(result).toEqual({ id: 'a1', status: 'active', retries: 0 })
// 没用:任何错误都能过,包括拼写错误导致的 TypeError
expect(() => parse(bad)).toThrow()
// 有用
expect(() => parse(bad)).toThrow(/unexpected token at line 3/)
一个测试一件事
测试名要能说清它在测什么。如果名字里出现「以及」,就该拆。
✗ test('创建会话并加载历史并处理错误')
✓ test('创建会话时生成唯一 id')
✓ test('加载不存在的会话时返回 undefined')
好处是失败时你直接从名字就知道哪儿坏了,不用读测试体。
覆盖率的真相
覆盖率只说明代码被执行过,不说明行为被验证过。
一个真实的例子:DSH 的 ACP 服务器曾经有 178 个绿色测试、100% 行覆盖率,但真实编辑器一连上就崩。因为所有测试都是手动挂载插件的,绕过了真实的加载路径,那条路径上的 bug 一个都没碰到。
所以:覆盖率是必要条件,不是证据。 100% 覆盖率的测试套件完全可能对真实的失败模式一无所知。
补充的判断:
- 有没有测失败路径,还是只测了成功路径
- 有没有走真实的入口(真实的 CLI、真实的加载器、真实的子进程),还是全在测试专用的挂载方式上
- 边界条件覆盖了吗
不要做的事
- 不要写只调用一下函数就
expect(true)的测试 - 不要为了覆盖率数字写测试
- 不要在测试里复述实现逻辑(那样实现错了测试也跟着错)
- 不要 mock 掉你真正想验证的那个东西
- 不要跳过"看它失败"这一步
- 不要相信「测试全绿」等于「功能正确」
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 · 100 lines · 48 tokens per session scan A 2501a91f7505
test-first is a skill published in the GitHub repository pingfanfan/hello-dsh (87 stars, last pushed 20d ago), licensed MIT. It adds 48 tokens to every session and 1,028 once invoked, about $0.0002 per session on Opus 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-08-30.
Other skills, from other repositories
dsh-plugin-guide
Use when developing, reviewing, packaging, debugging, or answering questions about DeepSeek Harness (DSH) plugins — the plugin-based agent harness on vendored Cordis. Applies the official plugin-development constraints (plugin contract, cordis.yml layers, services/events/effects, tool DSL, bundles/profiles) backed by…
tdd
测试驱动开发(Test-Driven Development)。当用户希望以测试优先的方式构建功能或修复 bug、提到 "red-green-refactor"(红-绿-重构),或需要集成测试时使用。.
tdd
Test-driven development. Use when the user wants to build features or fix bugs test-first, mentions "red-green-refactor", or wants integration tests.
dsh-web-release
Release and publish the dsh-web monorepo (DSH Web GUI plugin family + skin collection) — bump all packages to one unified version, commit and tag (tags are cut from main after dev integration; dev is the integration branch), push the vX.Y.Z tag that triggers the GitHub Actions publish pipeline, and verify the npm…
dsh-web-community-plugin-developer
Develop a DSH community plugin and register it in the dsh-web Community Plugins index — author the plugin in the contributor's own repository following the official cordis bundle standard, add its entry to packages/dsh-community-plugins/community.json, regenerate the index with scripts/community-index, rebuild and…
dsh-web-skin-developer
Build a new skin for the dsh-web skin collection (DSH Web GUI) and publish it into the Skin Center — the first-level settings section — scaffold with scripts/dsh-skin-new, author the v2 skin.json manifest plus skin.css token remap (pure asset directory, no package.json, no build step), validate with scripts/dsh-skin…