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-req-tree

v0.2.2

Published

把 req-tree 需求派生树搬进 DeepSeek Harness:右侧栏一个只读 Tab,直接看到当前工作区的需求树状态、收口进度与告警。

Readme

dsh-req-tree

把 req-tree 的需求派生树搬进 DeepSeek Harness: 右侧栏多一个只读 Tab,不用切窗口就能看到当前工作区的需求树、各条需求线的收口进度,以及 todoctl check 会报的那些告警。


它做什么 / 不做什么

| 做 | 不做 | |---|---| | 读取工作区的 tree.json,渲染成树 | 不写任何东西 —— 没有 start / done / close 按钮 | | 显示位置编号(1.3.2)与不可变 ID(R-0007) | 不改 tree.json,不碰 journal.jsonl | | 按需求线算收口进度(closed / (total - dropped)) | 不代替 todoctl check 的强校验(面板只显示 W 类告警) | | 显示 W1~W9 告警,点一下定位到对应节点 | 不重新发明 req-tree 的规则 —— 阈值全部从 todoctl.py 移植 | | 轮询真源,变了就刷新(默认 3 秒) | 不缓存、不落盘、不联网 |

为什么是只读

req-tree 的第一条铁律是所有写入只走 CLI:手改真源会制造第二个真源,而那是这套系统最大的威胁。

面板如果能做 close,就必须在浏览器里重写一遍 close 的证据门和 --override-reason 确认流程 —— 而浏览器里的那一份一定比命令行弱。所以这里只看,todoctl 负责判断。


安装

dsh plugin --profile <你的 profile> add dsh-req-tree

装完在右侧栏点开 需求树 Tab(或从引导页的入口进)。右侧栏是按会话停靠的,所以这个 Tab 会跟着当前会话走。

dsh plugin add 透传 pnpm,所以不依赖 npm 的源同样能用:

# 直接从 GitHub(可指定版本/分支/tag)
dsh plugin --profile <你的 profile> add github:putaomeiyoupi/dsh-req-tree
dsh plugin --profile <your-profile> add github:putaomeiyoupi/dsh-req-tree#v0.2.1

若安装报 ERR_PNPM_MINIMUM_RELEASE_AGE_VIOLATION,那是你 profile 里另一个包 刚发布过 rc 版本、尚未过 DSH 的 24 小时供应链冷却期,与本插件无关 —— 等冷却期过去即可。

确认装的是哪一版

面板头部会显示版本号(如「面板 0.2.2」)。它必须与 package.json 的 version 一致 —— 测试里有这条断言,因为版本号曾经横跨多个修复停在 0.1.0,导致装在 profile 里的旧副本 和最新代码看起来一模一样。

npm view dsh-req-tree version   # registry 上的最新版

前提

面板需要一个已经存在的真源。先用 CLI 建一个:

cd /path/to/your-project
python /path/to/req-tree/scripts/todoctl.py init --project my-project
python /path/to/req-tree/scripts/todoctl.py add --title "第一条需求" --why "为什么会有它" --done-when "怎样才算收口"
python /path/to/req-tree/scripts/todoctl.py render

真源位置由面板按 todoctl 完全相同的优先级自动判定:

--root(插件配置 root)> $TODOCTL_ROOT > 当前目录已是真源(含 tree.json)
  > 已预建 docs/requirements 或 .req-tree/requirements
  > <git 仓库根>/docs/requirements
  > <当前目录>/.req-tree/requirements

面板底部会显示它实际读的是哪个目录、以及判定依据 —— 落点和 CLI 不一致时能立刻看出来。


开销:面板不看着的时候,它什么也不做

右侧栏会为每个会话保留 Tab,后台会话的 Tab 也在。所以一个天真实现会永远轮询、永远重渲染 一棵没人看的树。这里有两道闸:

| 闸 | 行为 | 效果 | |---|---|---| | 可见性 | tab.visible 为 false 时(侧栏收起 / 选中了别的 Tab / 后台会话),不发请求、不起定时器 | 完全归零 | | 版本号 | 宿主半返回 revision(tree.json + journal.jsonl 的 mtime+size 指纹)。与上次相同就丢弃响应,不做 setState | 一次 fetch + 零渲染 |

于是:

  • 你没在看这个 Tab → 一次请求都没有
  • 你在看,但树没变 → 一个请求,不重渲染
  • 你在看,树变了 → 解析 + 投影 + 渲染(这才是真正该花的那次)

宿主半还有一层:版本号没变时直接命中内存缓存,连 tree.json 都不重新读。 所以「没变化」那一轮的完整成本 ≈ 两个 stat。

代价是多了一个 revision 字段。两端必须同时认这个字段 —— 宿主不发或客户端不读, 闸门就会静默退化成「永远重渲染」,不报错、只是回到原来的开销。 test/cost.test.mjs 里有这条契约的断言。

配置

在 profile 的 cordis.patch.yml 里覆盖:

- id: req-tree
  name: 'dsh-req-tree'
  config:
    pollSeconds: 3      # 面板轮询间隔(秒)
    maxNodes: 5000      # 单个工作区最多返回多少节点(超出会在面板里明说,不会静默截断)
    root: ''            # 留空 = 自动判定;填绝对路径 = 钉死真源

面板里能看到什么

  • 总览:未收口 / 已收口 / 已放弃 / 共 N 条,整体收口百分比
  • 需求线:每条顶层需求一根进度条(closed / (total - dropped)) —— dropped 既不进分子也不进分母,因为「判定不做」不是进度
  • 树:位置编号 + 状态字形(○ ▶ ⛔ ✔ ✅ ⏹,和 CLI 同一套符号),点开看 why / done_when / next_step / blocked_by / 收口证据
  • 告警:W1~W9,点一下展开并滚动到对应节点
  • 最近变动:读 journal.jsonl 的最近 12 条(坏行跳过,和 log 一样)
  • 真源位置:实际读的是哪个目录、怎么判定到的

默认视图是 req-tree 看板的**「待办视野」:已收口 / 已放弃的叶子节点折叠掉。 但一个已收口/已放弃的父节点,只要底下还有未收口的子项,就仍然显示** —— 否则未完成的工作会被它自己那个「已完成」的祖先藏起来,而那看起来就像「这件事做完了」。


目录结构

plugin/
├── cordis.patch.yml      # bundle patch:把插件挂进 profile
├── package.json
├── lib/
│   ├── index.js          # 宿主半:读真源、注册 /plugins/dsh-req-tree/* 路由
│   ├── project.js        # 纯投影:tree.json → 面板要画的模型(无依赖,可单测)
│   ├── client.js         # 浏览器半:Tab 正文(手写 JSX,可读)
│   └── client.bundle.js  # 生成物:`window.__ModuleLoader__` 格式(勿手改)
├── scripts/
│   └── build-client.mjs  # 把 client.js 打包成 loader 认的格式
└── test/
    ├── fixtures/tree.json
    ├── project.test.mjs  # 投影契约测试
    └── panel.test.mjs    # 真 DOM 渲染测试

lib/project.js 与 lib/index.js 分开,是因为宿主半依赖 @deepseek-ai/schemastery (只有宿主解析得到),而投影是纯函数,拆开后就能脱离宿主单测。


开发

npm install        # 只装 React / jsdom 用于测试
npm run verify     # = build + test

npm run build 会把 lib/client.js 包成 lib/client.bundle.js。 浏览器侧的模块加载器只认裸模块名(react、@deepseek-ai/...), 相对路径 ./client.js 在浏览器里根本不存在 —— 所以产物必须自包含, 这也是这个脚本存在的唯一原因(lib/client.js 本身保持可读 ESM)。

改完 lib/client.js 别忘了重新 npm run build。脚本会用 vm.Script 真的解析一遍产物,重写有 bug 就在这里炸,而不是变成一个空白 Tab。

测试覆盖什么

  • 投影:位置编号按渲染顺序算、ID 才是身份;每线进度用 closed/(total-dropped); W6(绕行)与 W8(计划失效)不混淆;成环 / 断链 / 未知状态都不崩; 截断会明说且总数仍是全树计数
  • 面板:真 DOM 挂载。断言「读不到 ≠ 空树」—— 200 带 ok:false 必须渲染成错误, 绝不能退化成「0 节点,一切正常」;两个语言字典必须键完全对齐

许可

MIT。上游 req-tree 亦为 MIT。