案例采集/拆解/归档技能包(case-library 配套,可独立分发)

FmodeAgent c41345d83f fix: slug 兜底下沉到 storage-bridge(中文标题 slugify 为空 → 内容指纹) 5 hours ago
bin 2cb6f5dc13 feat: skill-case-get v1.0.0 — 案例采集/拆解/归档技能包(可独立分发) 7 hours ago
references 1f008c9e7e feat: 归档双通道(云函数 + Parse 直写回落);probe 自检;线上落库与幂等实测通过 6 hours ago
scripts c41345d83f fix: slug 兜底下沉到 storage-bridge(中文标题 slugify 为空 → 内容指纹) 5 hours ago
.gitignore 6e13ee2ff1 release: v1.0.1 — 素材真上传(storage-bridge)+ key 兜底区分度 + vision PII 并入隐私发现 5 hours ago
README.md 6e13ee2ff1 release: v1.0.1 — 素材真上传(storage-bridge)+ key 兜底区分度 + vision PII 并入隐私发现 5 hours ago
SKILL.md 6e13ee2ff1 release: v1.0.1 — 素材真上传(storage-bridge)+ key 兜底区分度 + vision PII 并入隐私发现 5 hours ago
package.json 6e13ee2ff1 release: v1.0.1 — 素材真上传(storage-bridge)+ key 兜底区分度 + vision PII 并入隐私发现 5 hours ago
skill-package-manifest.json 6e13ee2ff1 release: v1.0.1 — 素材真上传(storage-bridge)+ key 兜底区分度 + vision PII 并入隐私发现 5 hours ago

README.md

skill-case-get

案例采集 / 拆解 / 归档技能包 —— 把各种素材变成可入库的案例。

npx skill-case-get@latest workspace          # 装进 ./.claude/skills/skill-case-get
npx skill-case-get@latest selftest           # 本机自检(不联网)
收到素材 → 拆解分析 → 能否进案例库 → 打标 → 上传归档(待审清单)

解决什么问题

同事在微信里连发 9 张图,说「这是上次 IC 那个学生的案例」。 这 不是 9 个素材,是 1 个案例,图要按九宫格阅读顺序排。以前只能手工数、手工起名、手工打标。

本技能把它变成一条可重复的管线:

  1. 识别来源:连续多图 / Word / PPT / 图文混合 / 裸图 / 视频
  2. 拆解:图片走 OCR + 语义理解;.docx/.pptx 用 python3 标准库解包;视频抽帧 + 转写
  3. 分组排序:尺寸 / 时间 / 内容三信号判同组,九宫格给显式 order(左上 → 右下)
  4. 分离:「案例说明」进案例字段,「图片视频」进 materialAssets[],不混
  5. 合规:能不能进库?是客诉负面吗?有无授权?
  6. 打标:静态属性 + 跟进状态七段 + 亮点/场景/异议 + 学校别名归一
  7. 归档:caseSubmit 写待审清单(pending,不进公共素材库)
  8. 自进化:新标签追加回 references/tag-dictionary.json

30 秒上手

# 只看分组对不对(不调模型、不联网)
npx skill-case-get@latest plan -- --image g1.jpg --image g2.jpg --image g9.jpg

# 完整采集(推荐先 dry-run,确认后再 submit)——本地素材默认真上传,拿公网 URL
npx skill-case-get@latest ingest -- \
  --image g1.jpg --image g9.jpg \
  --doc 案例稿.docx \
  --authorization authorized

# 离线自测 / 不想联网:关掉上传,只按前缀派生 URL
npx skill-case-get@latest ingest -- --image g1.jpg --no-upload \
  --asset-base-url https://s3.fmode.cn/user/<uid>/case-library/20261010

# 确认顺序无误 → 提交待审
npx skill-case-get@latest submit -- \
  --package case-get-outputs/<runId>/case-package.json

plan / ingest / submit 之后要加 --,参数透传给运行器。

归档通道:submit 先试云函数 caseSubmit;若该环境未挂载函数运行时(本部署 server.lumistedu.com 即如此),自动回落 Parse 直写,落库字段逐字对齐、仍只进待审清单。通道自检:npx skill-case-get@latest probe。

目录结构

skills/skill-case-get/
├── SKILL.md                      技能正文(frontmatter 参照 skill-vision / skill-listen)
├── README.md                     本文件
├── package.json                  name/version/bin
├── skill-package-manifest.json   分发清单
├── bin/skill-case-get.js         安装器 + 运行器透传
├── references/tag-dictionary.json  标签字典(维度/取值/别名,可增量更新)
└── scripts/
    ├── case-intake.mjs           主入口:plan / ingest / submit / reorder / dictionary / selftest
    ├── office_extract.py         .docx/.pptx 解包(纯标准库 zipfile + ElementTree)
    ├── vision-bridge.mjs         图片理解(复用 skill-vision)
    ├── storage-bridge.mjs        素材上传(复用 fmode-storage 第 0 级免密钥通道)
    ├── listen-bridge.mjs         视频抽帧 + 转写(ffmpeg + skill-listen)
    ├── cloud-client.mjs          云函数 caseSubmit / casePendingList
    ├── grouping.mjs              分组 + 九宫格顺序
    ├── classify.mjs              案例/素材分离、打标、别名归一、合规判断
    ├── image-size.mjs            零依赖图片尺寸探测(PNG/JPEG/GIF/WebP/BMP)
    ├── lib.mjs                   共享工具(路径/字典/幂等/素材规范化)
    ├── smoke.mjs                 冒烟检查
    └── tests/                    node --test 单测(34 个)

关键设计

为什么用 python3 标准库解包 .docx / .pptx? 本机没有 python-docx / python-pptx,Node 也没有对应库,而 .docx/.pptx 本质就是 zip。 zipfile + xml.etree.ElementTree 足够抽出文字段落、表格、内嵌媒体、超链接。 零依赖意味着技能可以直接被拷进 ~/.claude/skills/ 而不用 npm install。

分组为什么要求「至少 2 种信号」? 只看内容相似度会把两份不同学生的相似截图并成一组;只看时间会把同一时刻收到的不同素材并成一组。 尺寸(同源同排版)+ 时间(连发)+ 内容(共同话术)三者取二,才既不漏并也不误并。

为什么不再只靠 --asset-base-url 派生 URL? 检索侧只看 materialAssets[].url,本地路径不算数。过去 ingest 只把本地文件名拼到 --asset-base-url 前缀上:没给前缀就留空(线上真实故障:案例有 localPath 但 url 全空),给了也只是拼一个并不存在的假链接。 现在 ingest 默认真上传(--upload):本地素材走兄弟技能 fmode-storage 的第 0 级免密钥通道 (云函数预签名直传,AK/SK 始终留在云函数侧)拿到公网 URL,key 规范 case-library/<YYYYMMDD>/<caseSlug>-<order>.<ext>。--asset-base-url 保留为显式回退 (--no-upload 或上传失败时),拿不到 URL 就留空并告警——任何情况下都不伪造 URL。

上传失败不会拖垮整批 ingest:单张降级留空 + 定位到具体文件的 warning,其余照常,最后汇总「N 张上传失败」。 离线自测用 --no-upload。

依赖

依赖 必需 用途
Node ≥ 18 ✅ 运行器(含 fetch、node --test)
python3 ≥ 3.8 ✅ .docx / .pptx 解包(仅标准库)
skill-vision 推荐 图片 OCR + 语义理解;宿主自带多模态时由宿主读图
fmode-storage 推荐 素材上传(第 0 级云函数免密钥通道),--upload 默认依赖它
skill-listen 可选 视频音轨转写(走 Fmode 网关,凭据仅服务端)
ffmpeg / ffprobe 可选 视频抽帧、时长探测

缺任何一个可选依赖都不会伪造结果——会在 warnings 里说清楚。

安全红线

  • 只处理已获授权素材:authorizationStatus != authorized 一律不入库。
  • 新案例不进公共素材库:只写 reviewStatus='pending' + readyForUse=false,等 caseApprove 放行。
  • PII 不落库:privacyFindings[].snippet 是掩码后的(138****5678),真实 PII 只在内存里过一遍。
  • 凭据不落盘:token / AK / SK 只在服务端或进程内存中,绝不打日志、不进报告;素材上传走云函数免密钥通道,技能内不内联任何对象存储凭据。

详见 SKILL.md 与仓库 CLAUDE.md / .claude/rules/data-and-compliance.md。

开发

npm run smoke    # 冒烟(含单测)
npm test         # node --test scripts/tests/
node scripts/case-intake.mjs selftest

License

MPL-2.0 — Copyright (c) 2026 未来飞马 Fmode