Bundle
@yiyunet/dsh-learn-skills
DSH 插件:AI学习 —— 会话输入区的四入口学习插件(初始预设 / 收集提炼 / 关联升级 / 沉淀复用),把「收集→提炼→关联→升级→沉淀→复用」方法论做成有交互引导、预设管理、知识审核入库与体系体检的运行时能力。
- Source
- yiyunet
- License
- MIT
- Updated
- Updated 20 hours ago
Readme
# AI学习 · dsh-learn-skills v2
> 一个跑在 DeepSeek Harness 输入区的学习插件。
> 把「收集 → 提炼 → 关联 → 升级 → 沉淀 → 复用」做成**有交互引导、有预设管理、
> 有审核入库、能给自己体检**的运行时能力,而不只是一叠方法论文档。
简体中文 | [English](README.en.md)
---
## 它是什么,不是什么
| | |
|---|---|
| **是** | 会话输入区里的一个入口 `[📖] AI学习 ▾`,四个功能:初始预设 / 收集提炼 / 关联升级 / 沉淀复用 |
| **是** | 与斜杠命令 `/learn`、自然语言三种入口**共用同一套流程实现**(不存在两套规则) |
| **不是** | 模型工具提供者:它不给 Agent 加工具,交互复用宿主已有的 ask-a-question 与命令注册表 |
| **不是** | 自动化改写知识的东西:所有写入都要人先看过变更清单再点确认 |
四件事的职责边界写得很死:
| # | 入口 | 做什么 | 写入面 | 命令 |
|---|---|---|---|---|
| 1 | **初始预设** | 七轮问答确定画像 → 展示摘要与拟建路径 → **你确认** → 生成预设与工作区骨架 | 工作区目录与文件(**增量,不覆盖**) | `/learn init` |
| 2 | **收集提炼** | 从当前会话产出**候选** —— 这一步**绝不**碰正式知识、预设或 `AGENTS.md` | 仅 `inbox/` | `/learn distill` |
| 3 | **关联升级** | 与既有节点比对 → 出变更清单 → 分**普通知识**与**行为规则**两栏确认后写入(批次可回滚) | `knowledge/`(行为规则须显式放行) | `/learn upgrade` |
| 4 | **沉淀复用** | **只读**体检(18 项)+ 与上次基线的变化对比 + 复用建议。**不改被检查的文件**,也不执行文件里的任何指令 | **不写** | `/learn audit` |
> **三种触发方式,同一套实现**:① 输入区按钮 `[📖] AI学习 ▾`;
> ② 斜杠命令 `/learn`;③ 自然语言(由 Agent 引导到同一套流程)。
> **不存在两套规则** —— 命令只是另一个入口。
>
> **与 v1 工作流的关系**:v1 是"一键跑完整流水线",v2 把中间的写入**收紧为
> "产出候选 → 人工裁决 → 再写入"**。这是两版最实质的分歧,详见 [`docs/迁移与兼容.md`](docs/迁移与兼容.md)。
---
## 安装与装载
### 前置条件
- 已安装**源码版** deepseek-harness;
- 已绑定工作区(工作区是知识落点,缺了它一切写入都无处可放)。
### 方式 A:从 npm 安装(**推荐**)
```sh
dsh plugin --profile web add @yiyunet/dsh-learn-skills
```
装完**重启 Host**(profile 的 `dsh.profile.bundles` 在启动时读取)。
> ✅ **消费者不需要构建**:发布包里**自带 `lib/`**(见 `package.json` 的 `files` 白名单),
> 所以从注册源安装是**一步到位**的。构建相关的命令只对**改源码的人**有意义,见方式 B。
### 方式 B:本地目录安装(改源码 / 调试时用)
`lib/` **不入版本库**(`.gitignore` 排除),所以**克隆下来必须构建**:
```sh
npm install # 只装 esbuild(构建期依赖)
npm run static # 静态一致性体检(免执行:import/符号/语法/白名单)
npm run build # plugin-src/ → lib/(含装载层自证)
npm test # 真实行为测试
npm run verify # 发布契约断言
```
```sh
# 把本机该目录装进 web profile(路径按你的实际位置替换)
dsh plugin --profile web add link:<本仓库绝对路径>
# 或在 profile 目录里直接:
pnpm add link:<本仓库绝对路径>
```
> 📌 `npm install` 结束时**会自动构建一次**(`prepare` 钩子,钩子名 `scripts/postinstall.mjs`)。
> 上面那句 `npm run build` 因此是**幂等的复跑**,不是必做步骤 —— 保留它是为了让"构建"
> 在流程里**显式可见**。
### 检查装载是否成功
- 输入区工具行出现 `[📖] AI学习 ▾`(在「工作区内修改」控件右侧);
- 斜杠菜单里出现 `/learn`;
- `/learn help` 列出四个入口。
---
## 用法
### 按钮
点 `AI学习 ▾` → 选一个入口。菜单顺序固定:初始预设 / 收集提炼 / 关联升级 / 沉淀复用。
- 执行中会显示状态;**重复点击不会产生并发写入** —— 同一工作区同时只允许一个流程,
第二次会被明确拒绝;
- 有「取消」按钮:取消后**不再启动后续写入步骤**,已完成的步骤如实汇报;
- 未绑定工作区时菜单里直接给出引导;
- 尚未初始化时,后三项会先识别已有知识库:识别到就直接用,识别不到才引导你先做「初始预设」。
### 斜杠命令
```
/learn help 列出四入口
/learn init 七轮问答(确认创建要在界面上点,见下)
/learn distill 从当前会话产出候选
/learn upgrade [批次号] 出变更清单 / 写入
/learn audit 只读体检
/learn rollback <批次号> 回滚某个变更批次
```
命令与按钮背后是**同一个** `flows` 实现:命令只是另一个入口,不附带第二套规则。
需要"确认"的步骤(创建预设、写入变更)在命令侧用 `--confirm` 表达,
但**默认路径是界面上确认** —— 因为要让人先看清变更清单。
### 自然语言
插件不拥有模型工具,所以"自然语言入口"由工作区技能 `learn-*` 承担:你直接说
「帮我初始化学习体系」「把这次会话里的内容提炼成候选」,Agent 读技能后调用同一套流程。
---
## 七个问题问了什么
前两题固定,**第 3 题起由模型逐轮现场生成**(每轮带上已采集的全部信息、剩余轮次与已问话题);
模型不可用时逐轮回退到硬编码题库,流程不中断。
| # | 主题 | 要点 |
|---|---|---|
| 1 | 名字 | 自由输入;空值/长度/保留名/非法字符都校验;**重名请你换名**,不覆盖也不替你改名 |
| 2 | 身份 · 面向 · 期望 | **三段式一条文本**:`职业 | 面向什么(人群或事情)| 期望达到什么`,带例子;回显第 1 题;只填一段就只当职业,其余保持未知;**不索要**单位/真名等无关信息 |
| 3 | 关注方向 | 模型按你的三参数出题与选项;降级时按「场景池 → 职业池 → 通用池」三级匹配给 **7 个方向** +「其他,请输入」;支持多选与自定义 |
| 4 | 学习目标与典型任务 | 模型按上下文出题;降级时围绕固定主题给候选与自定义 |
| 5 | 当前基础与实际困难 | 同上 |
| 6 | 学习方式与输出偏好 | 同上 |
| 7 | 最想先解决的一件事 | 模型出题;降级时给"越快越好/先打基础/固定节奏"等候选 —— 这一项决定先做什么、后做什么 |
设计上刻意的三件事:
- **未填写 = 未知**。跳过项在画像里是 `null` 并标注"未知 —— 未填写",不编造画像。
- **推荐就是推荐**。关注方向的措辞是"**可能**关注",不伪称统计出来的"职业最高关注度"。
每题都能「返回修改」;改前置答案时,后续题**每轮现取**,天然重算。
- **模型只定题面,落库槽位固定**。模型的自主性在"问什么、给哪些选项";答案写进哪个
画像字段由插件固定,避免模型报的维度绕过"未填写=未知"的归一化而静默丢数据。
七题结束后展示:画像摘要 / 预设定位 / 知识框架草案 / 拟创建或修改的路径清单,
然后你才能点「确认创建」。创建完会给出结构自证、**安装指引**,并提示:
> 请**安装**该 bundle(本插件不代为安装),然后**新建会话**,选择预设 `<名字>`。
> ⚠️ 预设在一个进程内按 standing scope 挂载一次(源码:`packages/preset/agent-preset-registry`
> 的 `src/mount.ts` roster/standing mount)。**新预设不会在当前会话即时生效** —— 本插件不宣称热更新。
> 🔐 **为什么"安装"这一步不代做**:安装 bundle 会在 **Host 进程执行新代码**。官方入口
> `plugin_manager` 工具为此**强制**弹 `danger-full-access` 审批(源码:
> `packages/boot/plugin-manager/src/tools.ts:34-41`),而服务方法 `installBundle()`
> **本身没有审批闸**(同包 `src/index.ts:417-447`)—— 插件直接调它,等于**替你越权**。
> 所以本插件只生成、只出指引,点头的动作留给你:
```sh
# ① 终端一行(最省事)
dsh plugin --profile web add link:<刚生成的那个 bundle 目录>
# ② 或在「创造模式」会话里让 Agent 调 plugin_manager(会弹审批卡)
# action=install_bundle, target=<该目录>
# 复核:plugin_manager 的 list_plugins(找 preset-<id> 行)或 GUI「设置 → Agent 预设」看它是否进名册
# 撤销:dsh plugin --profile web remove @local/dsh-learn-preset-<id>
```
> 🗑 **要删掉一个预设("干净删除"的完整四步)**:见 [`docs/删除预设.md`](docs/删除预设.md)。
> 先记住三件事:① 新版**没有"删除预设"按钮**(设置页只能查看/选择/设为默认),能删的是
> **它所在的那个 bundle**;② **卸载之后还要删** `<工作区>/.dsh/preset-bundles/<id>/` 目录,
> 并且**清掉 `known.json` 里的占用**(否则同名重建会拿到 `-2` 后缀);③ 同包多预设时**不能卸整包**。
> ⚠️ 那个 bundle 目录在**工作区内**(`<工作区>/.dsh/preset-bundles/<id>/`),它是**活的**:
> 宿主重启时按预设 id 在当前配置里解析,**定义缺失的会话会被拒绝恢复**。
> 所以**不要删也不要移动它**;要撤掉请先用上面的 `remove` 摘掉 bundle
> (完整步骤与"删错了怎么救":[`docs/删除预设.md`](docs/删除预设.md))。
---
## 工作区结构
```
AGENTS.md 工作区原则与知识入口(精炼、稳定)
index/ 外部原始材料(保留来源与原文)
inbox/ 标准化材料、待审核候选、提炼批次
knowledge/
framework.md 正式知识体系的唯一总索引
nodes/ 正式知识节点
data/ 待分析数据(不默认转为知识或长期记忆)
task/ 学习任务、执行状态与待办
reports/ 体检报告、复盘与变化记录
.dsh/
skills/ 工作区技能
learn-skills/ 本插件状态:批次账 / 体检基线 / 变更日志 / 断点
preset-bundles/ 本插件生成的预设 bundle(★2.1.0 起落在这里;删它会连带废掉对应预设)
```
关于 `skills/`:**默认不与 `.dsh/skills/` 重复存技能**。宿主的 skill-filesystem
只扫 `<工作区>/.dsh/skills`(rank 100),根目录下的 `skills/` **不会被加载**;
如果确有需要独立分发的技能,请用 `.agents/skills`(rank 200)并在文档里写明用途。
### 增量迁移既有工作区
初始化是**增量**的,绝不清空:
- 目录:不存在才建,已存在无操作;
- 文件:内容相同 → 跳过;内容不同 → 标为 `conflict` 并**一个字都不写**,
在结果里明确告诉你哪个文件被挡下了、为什么;
- 重复运行幂等:不会重复创建,也不会覆盖你后来的修改。
### 迁移与 v1
本版(v2)是**完全重写**:四个入口是**运行时能力**,不再以"一叠方法论技能"的形态分发。
- **不提供 v1 技能的迁移路径** —— v1 的 `skills/learn-*` 技能包已从本仓移除;
- 需要 v1 方法论文本的作者,请见本仓的历史版本(若已归档);
- v2 的**功能不依赖任何 v1 技能**:装好插件即可用四个入口与 `/learn` 命令。
---
## 数据与状态
全部状态都在工作区内的 `.dsh/learn-skills/`,**不写宿主配置**:
| 文件 | 内容 | 寿命 |
|---|---|---|
| `session.json` | 单次流程的断点(可取消、可续办) | 流程结束即清 |
| `batches.json` | 已处理批次账 + 内容指纹 → 批次("不重复创建候选"的判据) | 长期 |
| `audit.json` | 上次成功保存的体检基线 | 长期(只增) |
| `known.json` | 已分配过的节点 id 与预设占用 | 长期(不回收) |
| `changes/<批次>.json` | 变更日志(回滚依据;含写入前内容) | 长期 |
预设本体是一个**可安装的 bundle**,落在 `<工作区>/.dsh/preset-bundles/<预设 id>/`
(恰好两件:`package.json` + `cordis.patch.yml`)。目录名可用 `config.presetDir` 改,
整个根也可用 `config.presetRoot`(绝对路径)覆盖。
> 🗑 **删掉一个预设**:见 [`docs/删除预设.md`](docs/删除预设.md) ——
> 独立成包的走**四步法**(关行确认 → 卸包 → 删目录 → 清 `known.json` 占用);
> **与别人共用一个组合包时不能卸包**(会带走同包所有预设),只能改那份 patch 的声明段;
> 以及删错了的**黄金窗口**(重启之前补回声明=零损失)。
> ⚠️ **DSH 0.1.7-alpha.1 起预设改为声明式**(提交 `feat(preset): declare Agent
> compositions in profile YAML`):旧的 `<dshHome>/.agent-presets/<id>/` 目录
> **已无人读取**,预设必须是 `@deepseek-ai/dsh-agent-preset` 的一个 Loader 条目。
> **只写盘不算预设存在** —— 必须安装该 bundle 才会进名册;安装由**你**经
> `plugin_manager`(强制审批)或一行 CLI 完成,本插件**不代做**(见上文"为什么")。
> 0.1.6-alpha.2 及更早生成的旧式目录预设**不会**自动迁移,需手动转成 bundle
> (见 `docs/迁移与兼容.md`)。
> 🧭 **身份判据来自宿主名册**:`init` 会先读 `ctx.agentPresets.list()`(注册表 roster)
> 再判重 —— 因为新架构里**预设身份=声明行里的 `config.id`**,而注册表**不扫描目录**
> (一份组合包可以声明很多个预设:本机 `dsh-migrated-presets` 一个文件里就有 12 个)。
> 名册读不到时**直接拒绝创建**(`ROSTER_UNAVAILABLE`,一个文件都不写)——
> 宁可不出件,也不出一个与既有预设重复的 `config.id`
> (官方原话:「重复的 preset ID 会导致声明加载失败」)。
### 回滚
```
/learn rollback <批次号>
```
- 新建的节点被删除,更新过的被还原;
- **写入之后被你改过的文件一律不动**,并列入"跳过"如实上报 —— 回滚不会变成第二次覆盖;
- 日志在 `.dsh/learn-skills/changes/<批次号>.json`。
---
## 配置
`cordis.patch.yml` 里的全部字段都有中文注释。默认值的关键两条:
```yaml
allowWrite: true # 总闸。关掉后四项功能变纯只读(初始预设只出预览)
allowBehaviorRules: false # 行为规则(预设提示词 / AGENTS.md / 技能)默认不放行
```
第二条是刻意的:**一条知识被认可,不会自动变成长期指令**。会影响 Agent 行为的那类变更,
必须由人显式打开这个开关,才会在「关联升级」的确认里被执行。
### 语义增强(方案 B-1:双轨并存 + 冲突标记)
**默认关闭**,开关与预算都在 `cordis.patch.yml`:
```yaml
allowModelSemantics: false # 打开后:提炼会把会话原文发给模型做语义判定
semanticBatchSize: 8 # 一次调用判多少条(越大越省,延迟越高)
semanticBudgetMs: 60000 # 总预算;用尽即停,剩余候选走基线轨
```
**为什么默认关**:打开后**会话原文会发给模型**。会话里可能有客户信息、平台账号线索、
内部报价 —— 这是数据出站,属合规红线,故默认不启用。
**它做什么**:给「收集提炼」加一条**语义轨**——模型判定每条候选的**类型**、以及它与
**已有节点**的关系(`new`/`supplement`/`correction`/`conflict`/`duplicate`/`supersede`/`unverified`),
并给出 `why`(依据哪几个字得出的)。
**为什么不覆盖基线(这是设计地基)**:模型输出**不可复现**——同一份内容两次提炼可能给
不同判定。若覆盖基线,就会出现"同一知识两次入库分类不同 → 版本号无故 +1 → 索引抖动",
**留痕与可回溯性当场失效**。所以采用**双轨并存**:
| 轨 | 谁产生 | 可复现 | 落盘字段 |
|---|---|---|---|
| 基线轨 | 关键词正则 + 词面重合 | ✅ | `type` / `relations`(`confidence: 'heuristic'`) |
| 语义轨 | 模型 | ❌ | `typeSemantic` / `relationsSemantic`(`confidence: 'model'`)+ `why` |
两轨**一致**时不产生额外字段;**不一致**时并排显示并标 `typeDivergence` /
`relationsDivergence`,审核面板会把模型建议明确标注为「模型」——**最终判定仍由你裁决**。
**降级纪律**:没有模型 / 超时 / 输出不是合法 JSON / 超预算 ⇒ **静默回退基线轨**,
候选照常产出,提炼流程一秒不停(与「初始预设」的"模型优先、硬编码兜底"同构)。
> ⚠️ **两个如实标注**:① 语义增强**部分生效**时(达到预算或某批失败),界面与批次文件都会
> 标明"未跑完",不会假装全部完成;② 批次文件里的 `semantic` 摘要记录了几次调用、几处
> 分歧,便于事后回溯。模型输出一律**严格校验、绝不修补**——编造的候选 id、非法 type/relation
> 一律丢弃。
---
## 开发
```sh
npm run static # 免执行静态体检(import/符号/语法/白名单)
npm run build # 构建(宿主半侧复制 + 客户端 esbuild 打包 + 装载层自证)
npm test # node --test:真实行为测试(真跑文件系统)
npm run verify # 10 组发布契约断言
npm run check # ★ 上面四步一次跑完:static → build → test → verify
npm run inspect # 产物体检
```
架构约定(与生态基准件 `@yiyunet/dsh-dingtalk-connector` 对位):
- `plugin-src/` 是**唯一真源**,`lib/` 是产物,改产物会被下次构建覆盖;
- 宿主半侧只用 Node 内置模块与宿主运行时提供的包,**不得**把 `@deepseek-ai/dsh-*`
写进依赖节(运行包用模块局部 Symbol 做 key,装第二份物理副本会破坏 Host 查找);
- 客户端半侧**只能引 react 系**(平台冻结模块表),第三方依赖一律不许进;
- 客户端产物必须由 wrapper 把 bundle 嵌进 `__ModuleLoader__.load` 的 factory **内部** ——
放在外面会在脚本顶层执行到 `require("react")`,整个 `/plugins` 拼接 bundle 会全灭。
---
## 排错
按**症状**查。每条都给出"为什么"和"下一步"。
### 装完看不到 `[📖] AI学习 ▾`
| 检查 | 说明 |
|---|---|
| **重启 Host 了吗** | ★ **最常见的原因**。`dsh.profile.bundles` 在**启动时**读取,改完 profile 必须重启才生效 |
| 装对 profile 了吗 | 必须是 `--profile web`(客户端半侧只在 web profile 注册) |
| 包真的在吗 | `dsh plugin --profile web list`,或直接看 profile 的 bundles 列表 |
### 菜单能弹,但点了报 `HTTP 404`
报错形如 `transport failure for /api/dsh-learn-skills: HTTP 404`。
**根因**:HTTP RPC 端点没注册上。`connection` 服务属于 **Web 运行时那一层**,
在插件 `apply()` 那一刻**可能尚未就绪** ⇒ 注册机会被错过。
**为什么本插件不该出这个问题**:它**不把 `connection` 写进静态 `inject`**(那会让插件在
无 Web 运行时的部署里**整体 inactive**),而是**挂到它就绪之后**再注册。
`npm run verify` 的 ⑤-b 组断言专门钉住这一点。
⇒ 若你**确实**看到这个 404:把 `~/.dsh/` 下的宿主日志里 `learn-skills` 相关行发出来。
### 点「初始预设」立刻报"无法读取宿主预设名册(agentPresets)"
**这是刻意设计,不是 bug。** 拿不到名册就无法保证不生成重复的 `config.id`
(官方明写"重复的 preset ID 会导致声明加载失败")⇒ **宁可不落盘**。
⇒ 此时**其余三个入口不受影响**,手工加预设照旧。
### 点「确认创建」后提示"尚未安装"
**这也是刻意的**(2.1.0 起**不代装**):安装 bundle 会在 **Host 进程执行新代码**,
官方入口 `plugin_manager` 为此强制弹 `danger-full-access` 审批,而服务方法
`installBundle()` **本身没有审批闸** ⇒ 插件直接调它等于**替你越权**。
⇒ 照提示跑那行 `dsh plugin --profile web add link:<该目录>`,或按 README
「七个问题问了什么」末尾的说明操作。
### 「收集提炼」产出为空或候选很少
| 原因 | 判据 |
|---|---|
| 本次会话内容被判为**噪声** | 寒暄、空内容不计入(`isNoise`,宁可漏判) |
| 这段消息**已被处理过** | 会标 `alreadyProcessed`,不重复创建 |
| 会话历史**不完整** | 报告里会标"部分范围";`historyComplete: false` 说明发生过 replace 压缩 |
| 上限截断 | `stats` 里如实反映,不静默丢失 |
### 语义增强(`allowModelSemantics`)没生效
**默认就是关的**(打开会把**会话原文发给模型**,属数据出站,须显式开启)。
打开后仍不生效时,按**降级纪律**逐条查 —— 以下任一都会**静默回退基线轨**(不抛错):
无模型 / 超时 / 输出不是合法 JSON / 超预算。批次文件里的 `semantic` 摘要会记
"几次调用、几处分歧",以及**是否跑完**(部分生效会明确标"未跑完",不假装完成)。
### 想确认"模型到底有没有在工作"
判据只有一条 —— **宿主日志**:
```
第 N 题未由模型生成,已回退到通用候选:<原因>
```
看到它就说明那一轮是降级跑的。**别用"问题看起来够具体"当判据** —— 硬编码兜底候选
里也有具体选项,没有区分力。
### `npm run check` 报"缺少必需文件"或断言失败
先看它**具体报哪一组**。10 组断言每组对应一个真实失败模式,
`scripts/verify-package.mjs` 里每条都有注释说明"为什么钉这一条"。
最常见的一类是 **`lib/` 与 `plugin-src/` 不同步** —— 改完源码**没重建**:
```sh
npm run build && npm run verify
```
---
## 卸载
### 第一步:摘掉插件
```sh
dsh plugin --profile web remove @yiyunet/dsh-learn-skills
```
或走 GUI:**设置 → 插件**,找到它移除。**改完重启 Host。**
> ⚠️ 卸载只是"不再装载",**不会删你的数据**。
### 第二步(可选):清掉插件留下的状态
**都在工作区内**,插件**不写宿主配置**:
| 路径 | 内容 | 删掉的后果 |
|---|---|---|
| `<工作区>/.dsh/learn-skills/` | 批次账 / 体检基线 / 变更日志 / 断点 / `known.json` | 丢"上次基线"与回滚依据;**知识节点本身不受影响** |
| `<工作区>/.dsh/preset-bundles/<预设 id>/` | 本插件生成的**预设本体** | ⚠️ **会连带废掉对应预设**(宿主重启时解析不到定义,**该预设的会话会被拒绝恢复**) |
> 🗑 **要删预设,请走四步法**,不要直接删目录 ——
> 见 [`docs/删除预设.md`](docs/删除预设.md):关行确认 → 卸包 → 删目录 → 清
> `known.json` 占用。**同包多预设时不能卸整包**(会带走同包里所有预设)。
### 第三步:你的知识库**不会**被删
`AGENTS.md` / `index/` / `inbox/` / `knowledge/` / `data/` / `task/` / `reports/`
都是**你的资产**,插件从不删它们。卸载后它们原样保留,可用任何工具继续使用。
> 回滚写入而非整个卸载?用 `/learn rollback <批次号>` —— 它**只还原本插件写过的**,
> 且**写入之后被你改过的文件一律不动**。
---
## 许可
MIT。见 [LICENSE](LICENSE)。
Install
dsh plugin --profile web add github:yiyunet/dsh-learn-skills
Profile: web
With the hub plugin installed, ask your agent to install it by name — it resolves the same plan shown here.
dsh plugin --profile web add github:stvlynn/dsh.fish#path:packages/dsh-plugin-hub
install yiyunet-dsh-learn-skills from the hub
- This package builds from source on install. pnpm will ask you to allow its build script — that is permission to run the package’s code on your machine, outside the agent sandbox. Only allow sources you trust.
- This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.