Skip to content

feat: 使用反馈、按任务找技能、技能引用与元技能检查 - #11

Merged
Arismemo merged 4 commits into
mainfrom
feat/usage-feedback-suggest
Sep 29, 2026
Merged

Arismemo merged 4 commits into
mainfrom
feat/usage-feedback-suggest

Conversation

@Arismemo

@Arismemo Arismemo commented Sep 29, 2026 •

Copy link
Copy Markdown
Owner

为什么

技能库目前只负责存储和分发:不知道技能用得怎么样,Agent 要猜对关键词才找得到技能,重复的技能和重复的操作也只能靠人发现。本 PR 让技能库知道「哪些技能好用、哪些该修、哪些重复了」,并把技能之间的引用变成有约定、能检查、本地 Agent 能落地的东西。

改了什么

1. 使用记录与反馈

  • 新表 skill_events:安装(记下装到哪台机器)、阅读(ash show)、反馈。actor_id 与技能主人分开,为团队库、技能广场预留。
  • ash feedback <slug> ok|fail "原因":反馈对应本机已装的修订号,技能更新后旧版本的失败不再计入当前版本。
  • 安装时在 SKILL.md 末尾附一段说明(引用的技能在本机哪里、用完怎么反馈)。推送回库时服务端只去掉这一段,Agent 写在后面的修改会保留。
  • 「需关注」视图按严重程度排序:常失败 → 引用失效 → 疑似重复 → 抄了元技能步骤 → 可提炼元技能 → 元技能缺契约 → 长期未用 → 从未使用。
    • 「从未使用」「长期未用」从开始记录使用的那天起算,上线第一天不会把老技能全标出来。

2. 按任务找技能

  • ash suggest "<任务描述>":逐字段 BM25(中文二元组、英文词),描述和名称权重最高,附带一份小型中英对照表;不依赖外部模型。
  • ash search 关键词全部命中、结果为空时,退回到按相关度给出候选(仍限定在 --folder / --tag 范围内)。
  • 用 139 个真实技能校准过阈值。

3. 审核依据与查重

  • 推送新技能时,如果库里已有相近的,推送结果会当场提示推送的 Agent。
  • 审核条显示:
    • 新技能:相似的已有技能、与已有技能相同的步骤、技能检查
    • 更新:当前版本的失败反馈;如果是元技能,列出会受影响的技能;只改了 frontmatter 时标出「只改了元数据」

4. 双语描述(修复跨语言查重)

  • description 用任一语言写,再用 description_en / description_zh 补另一种(也接受 metadata 里的同名键,以符合 Agent Skills 规范)。缺一种语言时推送和 ash lint 会提示。
  • 相似度:主语言不同的两个技能,再按语言分别比较(同语言的同系列技能不分语言比,避免共享套话造成误判)。
  • 实测:中文 systematic-debugging 与英文 debugging-and-error-recovery 的相似度,补上 description_en 后从 0.137 升到 0.361,从比对不出变成「相近」。同时误报分布没有变化(≥0.4 的配对仍是 10 对)。
  • 只要求元数据双语,不要求正文写两份:两份正文会漂移,而读正文的 Agent 中英文都懂。

5. 技能之间的引用与元技能

  • 引用写法:slug、@账号/slug(为团队库预留,目前只解析自己的账号)、slug@版本(版本不符时提示)。
  • 约定:depends_on 声明 + 正文写「用元技能 `slug`」,只补本技能特有的参数(与 meta-skill-spec 一致)。
  • 检查项(ash lint、推送结果、详情页「引用关系」、审核条共用同一套):
    • frontmatter 解析失败、缺双语描述
    • 引用写法不对 / 引用的技能缺失 / 还在待审核 / 跨账号 / 版本不符
    • 正文引用了却没写进 depends_on、用了绝对路径
    • 引用链超过两层、引用成环
    • 元技能缺「## 契约」「## 被谁引用」或与实际不符、调用方少于 2 个
    • 与元技能有相同的命令(应改为引用)、3 个以上技能重复同一段操作(可以提炼)
  • 重复操作识别:从 shell 代码块抽取命令并归一化(占位符替换路径、IP、变量、引号串,跳过 heredoc 和数据行),在 3 条以上连续相同命令上比对。在 139 个本地技能上找出 2 处真实重复,没有误报。

本地 Agent 能不能调用被引用的技能

按 Claude Code 官方文档核实:技能格式没有依赖字段,不认识的 frontmatter 字段会被静默忽略;Claude 只能按名字调用 ~/.claude/skills 或项目 .claude/skills 里的技能。所以引用要靠三件事落地:

  1. ash pull 把 depends_on 里的技能装在同一个目录下;
  2. 已装的 SKILL.md 末尾列出它们的相对路径 ../<slug>/SKILL.md,任何能读文件的 Agent 都能顺着找到;
  3. 在 Claude Code 里(CLAUDECODE=1)运行 ash pull 时默认装到 ~/.claude/skills,技能和它引用的技能都能按名字调用。

测试覆盖了这几点:装完后相对链接能打开真实文件,Claude Code 下装到正确目录,推送回库时这段说明被去掉。

顺带修复

  • gray-matter 会在解析之前按原文缓存结果:同一段坏掉的 frontmatter 第二次解析会静默返回空数据、不再报错,缓存还会无限增长。所有调用都改为传入 options 对象来绕过缓存。
  • 单独的 meta 标签不再视为元技能(它常指「关于技能本身」的技能,比如种子技能 writing-skills)。

上线须知

  • 数据库只新增 skill_events、app_meta 两张表,启动时自动创建,不改动已有数据。
  • 安装脚本、agent.md 由服务端生成,部署后立即生效。ash suggest、ash feedback、ash lint 是新命令,各机器需要先运行一次 ash update。
  • 已有技能大多没有双语描述:可以让 Agent 按 ash lint 的输出批量补上。这类更新在审核条会标为「只改了元数据」,方便快速审核。

第二轮:解决已知局限 + 本地 Agent 调用被引用技能的完整方案

跨语言查重(没有双语描述的技能)

  • 可选语义层:设置 ASH_EMBED_URL(Ollama 或 OpenAI 兼容接口,默认模型 bge-m3)后,服务端为每个技能的名称、描述、标题算向量。向量存进 skill_embeddings,内容不变就不重算;模型服务不可用时退回文本比对。
  • 只在文本比对看不见的地方补位:实测发现,语义上同系列技能(如 lark-doc ↔ lark-wiki 0.87)比真正的重复(deploy-to-vercel ↔ deploy-with-vercel 0.76)还要像。所以技能之间只对主语言不同的一对用语义分数;找技能时取文本、语义两者中较高的相关度。
  • 阈值用 bge-m3 在 139 个真实技能上校准:跨语言无关配对的 99% 分位是 0.62,真正的跨语言重复在 0.75 以上。换模型时可用环境变量覆盖阈值。
  • 实测:中文 systematic-debugging 与英文 debugging-and-error-recovery,不加任何翻译就被标为「疑似重复 · 语义」。
  • 补双语描述几乎零成本:只改 description_en/zh、title_en/zh 的更新直接发布(Agent 框架不读这些字段);ash lint --only bilingual 列出缺的技能。

重复的文字步骤

  • 编号列表、复选框里的步骤也参与比对:切词后按重合度模糊匹配,用倒排索引找候选。
  • 在 139 个本地技能上耗时 18ms,找出 3 处真实重复:understand-* 四个技能共用同一组 4 个步骤,已达到三次法则。

固定版本真正生效

  • 历史快照记录版本号,旧快照从 frontmatter 回填。
  • slug@1.2.0 和依赖里的固定版本从历史安装;ash pull --all / ash outdated 不再升级它。
  • lint 区分「固定在可用的历史版本」和「这个版本不存在」。

本地 Agent 能不能调用被引用的技能(完整方案)

  1. 装对位置:各家 Agent 只从自己的目录加载技能——Claude Code 用 ~/.claude/skills,Codex 用 ~/.agents/skills(已按官方文档核实),Hermes 用 ~/.hermes/skills。--agent all(或 ASH_AGENT=all)装进本机每个 Agent 的目录,依赖同样装在每一份旁边。
  2. 运行时规则:已装技能末尾和 agent.md 都写明了找被引用技能的顺序——Claude Code 按名字调用 → 其他 Agent 读 ../<slug>/SKILL.md → 本机没有就 ash pull <slug>。
  3. 能否被调用的检查:name 不符合规范或与 slug 不一致、缺 description 或超过 1024 字符、被引用的技能设置了 disable-model-invocation。
  4. 本机体检:ash doctor [--fix] 检查引用的技能在不在旁边、所在目录有没有 Agent 加载,--fix 自动补装;ash installed 也会标出缺的引用。
  5. 真实 Agent 端到端验证:用 ash pull 把「调用方 + 元技能」装进一个项目,元技能里放一个随机暗号(调用方里没有)。codex exec(gpt-5.5)读了调用方 → 顺着「用元技能 x」读了旁边的 ../x/SKILL.md → 答出了正确的暗号,还按末尾说明运行了 ash feedback。
    • 同样的 Claude Code 无头运行没能跑:本机 claude CLI 走的是一个本地 router,它的 key 脚本缺失,API 连接被拒。这是本机配置问题,与本 PR 无关。

上线须知(补充)

  • 要在线上启用语义层,需要在服务器上运行 Ollama 并 ollama pull bge-m3(约 1.2GB,CPU 即可),然后给容器设置 ASH_EMBED_URL(从容器里访问宿主机,例如 http://host.docker.internal:11434)。本 PR 没有改动线上配置。
  • 不设置 ASH_EMBED_URL 时,行为与原来完全一样。

验证

  • 服务端测试 99 个(新增 usage-suggest.test.js、references.test.js、semantic-agents.test.js;语义层用一个独立进程的假向量服务测试),前端测试 38 个,构建通过。
  • 在沙盒里用真实 bge-m3 验证了跨语言查重;用 Codex 实际跑通了引用技能的调用。
  • 在本地沙盒实例里用真实技能逐一检查了:需关注视图、详情页的使用情况与引用关系、审核条的各项依据、明暗两种主题、/docs 使用手册。

🤖 Generated with Claude Code

Arismemo and others added 4 commits September 29, 2026 03:30
…-skill checks

使用记录与反馈
- skill_events 记录安装 / 阅读 / 反馈(actor_id 与技能主人分开,为团队库、技能广场预留)
- ash feedback <slug> ok|fail:反馈对应本机已装的修订号,技能更新后旧版本的失败不再计入
- 安装时在 SKILL.md 末尾附一段说明(引用的技能在哪、用完怎么反馈),推送时只去掉这一段
- 健康信号 + 「需关注」视图:常失败、引用失效、疑似重复、抄了元技能步骤、可提炼元技能、元技能缺契约、长期未用、从未使用

按任务找技能与查重
- ash suggest:进程内逐字段 BM25(中文二元组、英文词、中英对照扩展),ash search 零结果时退回候选
- 相似度:意图字段 TF-IDF 余弦;主语言不同的两个技能再按语言分别比较
- 双语描述 description_en / description_zh:检索与跨语言查重都用上;缺一种语言时提示

技能之间的引用与元技能
- 引用写法 slug / @账号/slug / slug@版本;depends_on + 正文「用元技能 `slug`」
- 反向索引(被谁引用)、引用链深度与成环、元技能「## 契约」「## 被谁引用」检查
- 从 shell 代码块抽命令、归一化后找多个技能共有的操作:提示改为引用元技能或提炼元技能
- ash lint、推送结果、详情页「引用关系」、审核条统一给出检查结果
- 在 Claude Code 里运行 ash pull 默认装到 ~/.claude/skills(它只从这里加载技能)

其他
- gray-matter 调用传 options 绕过其内置缓存(坏掉的 frontmatter 第二次解析会静默返回空数据)
- 单独的 meta 标签不再视为元技能

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…uggest

# Conflicts:
#	client/src/components/SkillDetail.jsx
…rsion pins, multi-agent install and ash doctor

跨语言查重与找技能
- 可选语义层(ASH_EMBED_URL:Ollama 或 OpenAI 兼容接口,默认 bge-m3):向量按「模型+文本」哈希存进 skill_embeddings,
  后台补齐,服务不可用时退回文本比对
- 只在文本比对看不见的地方补位:技能之间仅对主语言不同的一对用语义分数(同语言同系列技能语义上很像却不是重复),
  找技能取文本、语义两者较高的相关度;阈值用 bge-m3 在 139 个真实技能上校准,可用环境变量覆盖
- 只改双语字段(description_en/zh、title_en/zh)的更新直接发布:Agent 框架不读这些字段;ash lint --only bilingual 批量补齐

重复操作
- 编号列表、复选框里的文字步骤也参与比对(切词后按重合度模糊匹配,倒排索引找候选)

固定版本
- skill_versions 记录版本号(旧快照从 frontmatter 回填);slug@1.2.0 与依赖里的固定版本从历史安装,.ash 记为固定,
  ash pull --all / outdated 不再升级它;lint 区分「固定在可用的历史版本」与「版本不存在」

本地 Agent 调用被引用的技能
- --agent all(或 ASH_AGENT=all)装进本机每个 Agent 各自加载技能的目录,依赖同样装在每个目录旁边
- 已装技能末尾写明用到被引用技能时怎么办:Claude Code 按名字调用、其他 Agent 读 ../<slug>/SKILL.md、本机没有就 ash pull
- ash doctor [--fix]:检查引用的技能是否在旁边、目录有没有 Agent 加载、被引用的技能能否被调用;ash installed 标出缺的
- lint:name 不符合规范或与 slug 不一致、缺 description / 超过 1024 字符、被引用的技能设置了 disable-model-invocation

修复
- 语义层在途任务的标记可能在设置之前就被清除,导致后续调用无限链式等待(内存耗尽)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…idge, compose env)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Arismemo
Arismemo merged commit fa1049a into main Sep 29, 2026
2 checks passed
@Arismemo
Arismemo deleted the feat/usage-feedback-suggest branch October 9, 2026 10:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant