npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

dsh-blast-radius

v0.1.0

Published

DeepSeek Harness plugin: semantic blast radius for agent code edits — who calls what the agent just changed, and which of those callers have no test covering them

Readme

dsh-blast-radius

DeepSeek Harness 插件:agent 改了代码,这次改动会波及什么?

diff 告诉你改了 5 行。它不会告诉你这 5 行在一个被另外 3 个文件调用的函数里, 而那些调用点一个测试都没有。前者是文本视角,后者是风险视角。

用真实的 TypeScript 语义分析(tsserver)回答后者:改动落在哪个符号上、谁依赖这个 符号、那些依赖里有多少受测试保护。

[高] applyDiscount                                   src/money.ts
     3 处生产调用点,且该符号没有任何测试引用
     影响 2 个其他文件:src/cart.ts、src/pricing.ts
     ↳ src/cart.ts:6      const total = applyDiscount(subtotal, discountPct)
     ↳ src/pricing.ts:10  return applyDiscount(cents, 10)
     ↳ src/pricing.ts:19  return applyDiscount(this.cents, pct)

两条不会妥协的原则

这两条决定了插件的所有行为,也决定了默认配置:

1. 分析失败永不阻断 agent。 TypeScript 没装、tsserver 崩了、查询超时 —— 全部放行。 即使 enforce: true 也一样。一个会因为子进程死掉就卡住 agent 的质量工具,比没有这个 工具更糟。

2. 「不知道」永不伪装成「安全」。 分析不出结论时明确说出来,而不是渲染成一条干净 的结果。这也是 enforce 默认关闭的原因:一个第一天就开始拦你写入的插件,会在赢得 信任之前先被卸载。

功能

  • 语义影响面:tsserver 的 references + navtree,按符号(不是行号)归因
  • 测试覆盖缺口:区分生产调用点与测试引用 —— 这是最值钱的信号
  • 风险分级:低 / 中 / 高,规则确定可复现(不用模型判断)
  • 写入前拦截:tools/pre-execute waterfall,超阈值走 ask
  • 仪表盘:shell.overlay 角落面板,4s 轮询
  • 零额外安装:typescript 包自带 tsserver.js,优先用被分析项目自己的版本

安装

dsh plugin --profile web add dsh-blast-radius

默认 report-only:只记录、只显示,不拒绝任何写入。

配置

见 cordis.patch.yml。关键项:

| 键 | 默认 | 含义 | |---|---:|---| | enforce | false | 超阈值时是否要求确认。默认只报告 | | enforceAtRisk | high | 触发确认的风险等级:medium | high | | timeoutMs | 3000 | 单次语义查询预算,超时降级为「未分析」并放行 | | highProductionRefs | 12 | 调用点超过此数即为高风险(即使有测试) | | testPatterns | [] | 追加的测试路径正则(内置已覆盖 *.test.* / test/ / __tests__/) | | maxProjectFiles | 2000 | 无 tsconfig 时扫描上限,触顶会明确报告 | | verbose | false | 每次分析打一行日志,调阈值时有用 |

风险分级规则

| 条件 | 等级 | |---|---| | 无人引用 / 仅被测试引用 / 仅被导入未调用 | 低 | | 有生产调用点,无测试引用,且跨文件 | 高 | | 有生产调用点,无测试引用,但都在本文件内 | 中 | | 有生产调用点且有测试引用,调用面 ≥ highProductionRefs | 高 | | 有生产调用点且有测试引用 | 中 |

排序刻意如此:「跨文件且完全没有测试」排在「调用点很多」之前,因为前者是改错了会 静默上线的情形,后者至少有测试兜着。

设计取舍

这些取舍都是在真实仓库上跑出来的,不是设计阶段想出来的。

只分析符号,不分析行

变更行 → navtree 定位所属符号 → 查该符号引用。变更区间用前后缀剪裁计算,分散编辑 会连带包含中间范围。刻意选这个方向:多分析几个符号只是多花几毫秒,漏掉符号就是漏掉 了插件存在的理由。

局部变量不参与分析

第一次在真实文件上跑,30 条结果里大部分是噪音 —— splitSentences.start 报告"2 处生产 调用点",那是个循环变量。

按 kind 过滤不够:模块级 const 和函数内 let 在 tsserver 里 kind 相同。真正的判据是 是否在可调用体内 —— 模块常量能被任何地方读,局部变量跑不出它所在的函数体。修完 30 条降到 6 条真实符号。

import 不算调用点

import { applyDiscount } from './money.ts' 引用了符号,但不依赖它的行为。算进去会让 影响面虚高一倍(fixture 里 3 处真实调用被报成 5 处)。

import 仍计入「波及文件」 —— 依赖关系是真的,只是不是"使用"。

测试文件不算「波及范围」

测试引用一个符号是保护,不是风险传播。算进去会让"测试写得好的符号"看起来比裸符号 更危险,正好反了。

补丁式编辑明确拒绝分析

str_replace_editor 表达的是"把 A 换成 B",不是"文件最终长这样"。要还原结果就得重新 实现一遍该工具的语义,而还原错了的话,下游每条结论都在描述一个不存在的文件。

所以报告为「未分析」、放行、且不记入已审查记录 —— 免得让人以为这次改动被看过了。

无 tsconfig 的项目:合成项目范围,但不落盘

没有 tsconfig.json 时,tsserver 退化成 inferred project,只知道显式打开的那个文件。 实测后果(在一个真实仓库上):

inferred project:  1 refs -> src/segmenter.ts        ← 假的「没有引用」
declared project:  4 refs -> src/segmenter.ts, src/index.ts ✓

用 openExternalProject 在内存里声明项目范围,刻意不写 tsconfig.json 到用户仓库 —— 那会出现在 git status 里、可能被它正在监视的 agent 提交进去、还可能改变项目真实 构建行为。有测试断言分析前后 readdir 结果一致。

代价是范围靠扫描推断,可能漏文件。所以结果带 approximate 标记,且 enforce 时 推断范围的结论不参与拦截 —— 低估风险在"报告"里可以接受,作为"打断别人工作的理由" 则不行。

架构

tools/pre-execute waterfall
  └── extract.ts   工具调用 → 待写入内容(认不出的明确报 opaque)
        └── radius.ts   变更行 → 符号 → 引用 → 分桶 → 分级
              └── lsp.ts   tsserver 长驻会话(超时/崩溃/未就绪全部降级)
                    └── discover.ts   无 tsconfig 时的有界文件扫描

GET /dsh-blast-radius-api/status → { records, enforce, enforceAtRisk, projectRoot }

| 文件 | 职责 | |---|---| | src/lsp.ts | tsserver 会话:帧解析、超时降级、崩溃重启、pending 内容同步 | | src/radius.ts | 纯逻辑:符号定位、引用分桶、风险分级(不碰子进程) | | src/discover.ts | 无 tsconfig 时的项目文件发现(有界) | | src/extract.ts | 从工具调用还原待写入内容 | | src/index.ts | 插件入口:配置、闸门、status 路由 | | src/client.tsx | 仪表盘面板 |

性能

在一个真实仓库上实测:

| 指标 | 数值 | |---|---| | tsserver 冷启动 + 项目加载 | ~450ms(每会话一次) | | 单符号引用查询 | 1–20ms | | 一个文件(含多符号) | 40–120ms |

会话长驻、跨编辑复用。冷启动只付一次,所以不会把 0.5s 摊到每次写入上。

测试

npm test        # 166 用例
npm run typecheck

| 套件 | 用例 | 说明 | |---|---:|---| | src/radius.test.ts | 65 | 纯逻辑,不碰子进程 | | src/extract.test.ts | 28 | 工具调用识别与 opaque 判定 | | src/client.test.tsx | 18 | 面板(jsdom) | | src/discover.test.ts | 16 | 文件发现的边界与截断 | | tests/lsp.spec.ts | 19 | 真实 tsserver,含无 tsconfig 场景 | | tests/plugin.spec.ts | 20 | 真实 cordis,闸门与 status 路由 |

LSP 层刻意不 mock:它是唯一有真实失败模式的组件(子进程、帧协议、项目加载), mock 掉就等于没测到唯一的难点。

原型工具

仓库里带一个 probe 脚本,可以在任意真实仓库上直接跑分析、打印结果 —— 用来判断信号 质量、调阈值,不需要先装成插件。只在源码仓库里可用(未随 npm 包发布):

git clone https://github.com/haoku123/dsh-blast-radius
cd dsh-blast-radius && npm install --legacy-peer-deps
node scripts/probe.ts ~/your-project src/some-file.ts [symbolName]

需要 Node ≥ 22.6(原生运行 TypeScript)。输出示例见本文开头。

限制

  • 只支持 TypeScript / JavaScript。Python 需要另装 pyright,选型与降级策略完全不同, 架构上留了 provider 接口但 v1 不做。
  • references 拿不到动态调用:反射、字符串索引、eval、跨语言边界。
  • 补丁式编辑工具无法分析(见上)。
  • 无 tsconfig 时项目范围是推断的,可能漏掉调用点。
  • 不做「AI 判断风险」。全部基于确定性事实 —— 一个会给出不可复现结论的质量门是 负资产。

License

MIT