chore: 导入清理前的完整工程状态(含 Capacitor 原生壳,作为回滚备份点)

This commit is contained in:
toor
2026-10-21 11:50:10 +08:00
committed by trae-solo-agent
commit 8ded87a3a8
389 changed files with 52242 additions and 0 deletions
+182
View File
@@ -0,0 +1,182 @@
---
name: add-recipe
description: 给 Cook(食用手册)新增菜式。当用户说「增加菜式」「加几道菜」「添几个菜谱」「补点新菜」「增加 XX 类菜」「加个 XX 做的菜」时使用。按「先摸清现有数据 → 上网找数据里没有的新菜 → 拆解成食材/做法/厨具/菜系类别 → 写入并校验」的流程执行。
metadata:
author: YunYouJun
repository: https://github.com/YunYouJun/cook
---
# 新增菜式
你在给 Cook(食用手册)补充菜谱数据。每次运行把**若干道新菜**写进 `packages/data/recipe.csv`,跑完校验后向用户汇报。
## 数量规则
- 用户明确说了数量(「加 10 道」「补 5 个」),就按用户说的来。
- **用户没说数量,默认加 5 道菜。**
- 用户指定了主题或范围(「加几道川菜」「补点用砂锅的菜」),数量仍按上一条判断。
## 数据落点
只有一个文件要改:`packages/data/recipe.csv`。
列为 `name,stuff,bv,difficulty,tags,methods,tools,id`,单元格内多个值用顿号「、」分隔(**不能用逗号、斜杠、分号**)。
```
name,stuff,bv,difficulty,tags,methods,tools,id
青椒炒肉,青椒、猪肉,,普通,家常菜,炒,一口大锅,637
电饭煲版广式腊肠煲饭,腊肠、米,BV1NE411Q7Jj,简单,广式,煲,电饭煲,0
```
| 列 | 规则 |
| --------- | ------------------------------------------------------------------------------------------------------ |
| name | 必填。菜名要能让人一眼看出做法,习惯写成「厨具版+做法+主料」或「主料+做法」 |
| stuff | 必填。只能填 `packages/data/food.json` 里的食材标准名,具体品种(虾仁、鲈鱼)要写成标准名(虾、鱼) |
| bv | B 站 BV 号或 av 号。**可以留空**——应用里点菜走的是 B 站搜索链接,不是这个视频号;填了就必须是真实可播放的视频 |
| difficulty | 简单 / 普通 / 困难,或留空 |
| tags | 菜系类别 + 其它标签(快手菜、下饭、汤、杂烩、辣…),见下表 |
| methods | 做法(炒、煎、蒸、煮、煲、烤、炸…),见下表 |
| tools | 只能填 `packages/data/food.json` 里的厨具名 |
| id | 必填,非负整数且唯一。**新菜用当前最大 id + 1**(现在是 637、638…) |
**id 一旦发布就不能修改、不能复用。** 收藏、反馈、筛选信号都按 id 记录。新菜一律追加到文件末尾,id 递增。
## 取值白名单
### 食材(35 个,来自 `packages/data/food.json`)
- 蔬菜:土豆、胡萝卜、花菜、白萝卜、西葫芦、番茄、芹菜、黄瓜、洋葱、莴笋、菌菇、茄子、豆腐、包菜、白菜、青椒、韭菜、南瓜
- 肉蛋水产:午餐肉、香肠、腊肠、鸡肉、猪肉、鸡蛋、虾、牛肉、骨头、鱼、蟹
- 主食:面食、面包、米、方便面、玉米、红薯
需要列表里没有的食材时,**先在 `packages/data/food.json` 里加**,再加别名到 `packages/data/aliases.json`(如「柿子椒」→「青椒」),然后才写进菜谱。别名映射用户输入的写法到标准名。
### 厨具(6 个)
烤箱、空气炸锅、微波炉、电饭煲、一口大锅、砂锅
### 菜系类别(tags 里的菜系标签)
必须从下表里选**标签值**写进 tags,选了哪个菜系筛选就只认哪个标签:
| 菜系 | 可用标签 |
| ------ | -------------- |
| 川菜 | 川菜 |
| 湘菜 | 湘菜 |
| 粤菜 | 粤菜、广式 |
| 苏菜 | 苏菜 |
| 东北菜 | 东北菜 |
| 西北菜 | 西北特色 |
| 日式 | 日式、日式菜 |
| 意式 | 意式 |
| 法式 | 法式、法餐 |
| 西式 | 西式 |
| 国宴菜 | 国宴菜 |
**每道新菜都尽量打上菜系标签。** 应用里一旦选了菜系,只有带该标签的菜会出现——标签不全会导致选了菜系就几乎没结果。
### 做法分组(methods + tags 的组合)
用户在应用里选的「做法」是分组,按下面的规则命中:
| 做法分组 | 怎么填 | 备注 |
| -------- | ---------------------------------------- | -------------------------- |
| 炒菜 | methods 填「炒」 | |
| 汤羹 | **tags 填「汤」**,methods 填煮/煲/炖 | 靠标签识别,不是靠 methods |
| 炖煮 | methods 填炖、煮、煲、卤、焖、烧、灼 | |
| 蒸 | methods 填「蒸」 | |
| 炸煎 | methods 填炸、煎、烙 | |
| 烤 | methods 填烤、烘、焗 | |
| 凉拌 | methods 填拌、凉拌、腌、腌制、泡菜、油泼 | |
| 微波 | methods 填「微波加热」 | |
| 火锅 | **tags 填「杂烩」**,且食材 **≥10 种** | 靠标签识别;食材少于 10 种不算大杂烩 |
「辣」标签同样靠 tags 识别,选了「不吃辣」时会排除带此标签的菜。
## 步骤
### 1. 摸清现有数据
先搞清楚「已经有什么、缺什么」,不要凭印象加菜。
```bash
# 全部菜谱(638 行,含表头)
cat packages/data/recipe.csv
# 菜谱总数
wc -l packages/data/recipe.csv
# 现有菜系分布:每种菜系各有多少道
node -e "const fs=require('fs');const l=fs.readFileSync('packages/data/recipe.csv','utf8').trim().split(/\r?\n/).slice(1);const c={};l.forEach(r=>{const t=r.split(',')[4]||'';t.split('、').filter(Boolean).forEach(x=>{if(/菜|式|广式|法餐/.test(x))c[x]=(c[x]||0)+1})});console.log(c)"
# 某个食材出现在多少道菜里(找出只有 1-2 道菜的冷门食材)
node -e "const fs=require('fs');const l=fs.readFileSync('packages/data/recipe.csv','utf8').trim().split(/\r?\n/).slice(1);const c={};l.forEach(r=>r.split(',')[1].split('、').filter(Boolean).forEach(x=>c[x]=(c[x]||0)+1));console.log(Object.entries(c).sort((a,b)=>a[1]-b[1]))"
# 某个厨具下有多少道菜
node -e "const fs=require('fs');const l=fs.readFileSync('packages/data/recipe.csv','utf8').trim().split(/\r?\n/).slice(1);const c={};l.forEach(r=>r.split(',')[6].split('、').filter(Boolean).forEach(x=>c[x]=(c[x]||0)+1));console.log(c)"
```
同时读 `packages/data/food.json`(食材/厨具词典)和 `packages/data/aliases.json`(别名)。
重点找这几类空洞,补菜时优先填:
- **菜系空洞**:某个菜系只有 1-2 道菜,用户一选就几乎没结果。
- **冷门食材**:某个食材只出现在 1-2 道菜里,选它必然匹配不到。
- **厨具 × 食材交叉**:某个食材配某个厨具一道菜都没有(比如砂锅只有十来道菜,覆盖的食材很窄)。
- **做法 × 菜系交叉**:某菜系里缺某类做法(比如粤菜没有凉拌、日式没有汤)。
### 2. 上网找新菜
- 围绕要补的空洞找菜:「XX 家常做法」「XX 砂锅」「XX 快手菜」这类关键词。
- 优先选**常见、做法明确、食材在词典里**的家常菜。冷门菜、分子料理、需要特殊设备的不要。
- **判重**:菜名和已有菜重复的、或同名同做法的,不加。先用步骤 1 的命令或直接搜 CSV 确认。
- **不要编造**菜谱或视频号。找不到真实信息就换一道菜,别硬凑。
- 找视频(可选):搜索时带上 `bilibili.com/video` 关键词,从结果里拿 BV 号。
### 3. 拆解并写入
对每一道新菜,逐列拆开:
1. **菜名**:`青椒炒肉`
2. **食材**:拆成词典里的标准名 —— 青椒、猪肉
3. **厨具**:这道菜实际用什么锅做 —— 一口大锅
4. **做法**:methods 填具体动作 —— 炒
5. **菜系类别**:tags 填菜系标签 —— 川菜、家常菜
6. **难度**:简单 / 普通 / 困难,拿不准留空
7. **id**:从当前最大 id + 1 开始,逐个递增
然后**追加到 `packages/data/recipe.csv` 末尾**(不要改已有行)。
### 4. 校验
按顺序跑完,全绿才算完成:
```bash
pnpm convert # CSV → JSON,必须先跑
pnpm validate # 有错误时退出码为 1
pnpm fixtures # 重新生成 recommend.json(改了数据必须重跑)
pnpm test -- --run
pnpm lint
```
常见问题:
- **`pnpm validate` 报「食材/厨具不在词典中」** —— 名称不对,改成标准名;词典里确实没有就先加进 `food.json`。
- **`pnpm test` 失败且是 `test/recommendations.test.ts` 里的 `counts` 断言** —— 新菜改变了推荐结果的分组数量,属于预期变化,更新这些数字即可。
- **`pnpm test` 报 fixtures 不一致** —— `pnpm fixtures` 没跑或跑漏了。
- **`pnpm lint` 报 md 文件格式错** —— 文档类改动注意行尾和代码块内不要留多余空行。
### 5. 汇报
告诉用户:
- 加了几道菜,每道的:菜名、食材、厨具、做法、菜系、难度、id
- 补的是哪些空洞(比如「补了砂锅 + 香菇 3 道」「粤菜凉拌 2 道」)
- 校验结果(`pnpm validate` 错误数、`pnpm test` 通过情况)
- 哪些地方拿不准、需要用户定夺(比如新加的食材名、没找到合适视频的菜)
## 注意事项
- 不要删除或修改已有行。发现已有数据有问题(重复、失效视频)时,在汇报里指出,让用户决定。
- 不要改 `packages/cook/src/utils/recommend.ts` 里的筛选逻辑,也不要改 `test/` 下的断言来「凑」结果——断言变化只允许是数据量自然变化导致。
- `packages/data/recipe.json` 和 `packages/data/fixtures/recommend.json` 是生成物,不要手写,改 CSV 和用例输入后用 `pnpm convert` / `pnpm fixtures` 重新生成。
+144
View File
@@ -0,0 +1,144 @@
# 🍳 Cook Skill — 食用手册 AI 美食助手
> 围绕「今天吃什么」的生活灵感助手,内置数百道中文家常菜谱数据库。
## 功能介绍
### 🥘 食材找菜谱
告诉 AI 你冰箱里有什么食材,它会从内置的菜谱数据库中检索匹配的菜谱,并附上 B 站视频教程链接。
- 支持模糊匹配和食材别名(如「西红柿 → 番茄」「泡面 → 方便面」)
- 标注匹配程度:「你有其中 X 样,还需要 XX」
- 可按厨具、难度、做法、标签进一步筛选
- 数据库匹配不足时,会补充通用家常菜建议
### 📅 饮食规划
帮你做一周菜单安排:
- 荤素搭配,主食轮换,不重样
- 食材复用——买一次菜用一周
- 工作日要快,周末可以花点时间
- 兼顾口味变化,不会连着几天吃同一类
### 🧠 食材知识
- **食物相克查询**:基于内置数据,理性说明影响程度,不传播谣言
- **保存方法**:什么该放冰箱、保鲜期多久、剩菜怎么处理
- **食材替代**:没有某个食材时的替代方案及口味差异
### 🍜 烹饪技巧
新手友好的实用指南:
- 调味基本比例
- 肉类腌制技巧
- 蔬菜炒制不出水
- 常见翻车避坑
### 🎯 适用场景
| 场景 | 关注点 |
| -------------- | -------------------------------- |
| 冰箱清理日 | 不浪费,用有限食材做出好吃的 |
| 新手第一次做饭 | 失败率低、步骤少、不需复杂调料 |
| 给家人朋友做饭 | 有面子但不难做 |
| 减脂/健康饮食 | 低油低盐、高蛋白,附热量参考 |
| 一人食 | 份量小、不浪费、做起来快 |
| 带便当 | 适合加热、不易变味、方便携带 |
| 宝宝辅食 | 新鲜安全、口味清淡、注意过敏风险 |
## 数据源
菜谱数据来自 [Cook(食用手册)](https://github.com/YunYouJun/cook) 开源项目,包含:
- **数百道家常菜谱**(含食材、难度、厨具、做法标签、B 站视频链接)
- **食物相克数据**(食物 A/B + 不宜同食原因)
- **食材/厨具分类**
Skill 自带菜谱数据(`data/` 目录),离线即可使用;数据也可通过 GitHub Raw URL 在线获取最新版本。
## 系统要求
- **支持工具**:[CodeBuddy](https://www.codebuddy.ai)(IDE 插件 / CLI)、[Claude Code](https://docs.anthropic.com/en/docs/claude-code)
- **操作系统**:macOS / Linux / Windows(任何支持上述工具的系统)
- **网络**:可选——Skill 内置菜谱数据,离线可用;联网时可获取最新数据
- **本地依赖**:无——Skill 本身是 Markdown 提示词 + CSV 数据,不需要安装任何运行时
## 安装
### 方式一:让 AI 帮你装
把下面这句话直接发给你的 AI 助手(CodeBuddy / Claude Code),它会自动完成下载、解压和安装:
> 帮我安装 cook skill:从 https://github.com/YunYouJun/cook/releases/latest/download/cook.zip 下载并解压到用户级 skills 目录
### 方式二:手动安装
1. 下载 [cook.zip](https://github.com/YunYouJun/cook/releases/latest/download/cook.zip)
2. 解压到对应工具的 Skills 目录:
| 工具 | 用户级 Skills 目录 |
| --------------------- | --------------------------- |
| CodeBuddy (IDE / CLI) | `~/.codebuddy/skills/cook/` |
| Claude Code | `~/.claude/skills/cook/` |
3. 确认目录下包含 `SKILL.md` 文件即安装成功
> **项目级安装**:也可将文件解压到项目根目录下的 `.codebuddy/skills/cook/`(或 `.claude/skills/cook/`),仅对当前项目生效。
### 验证安装
安装完成后,随便跟 AI 说一句:
> 冰箱里有鸡蛋和番茄,能做什么菜?
如果 AI 开始检索菜谱数据库并给出带视频链接的推荐,说明 Skill 已生效。
## 使用方法
安装后无需任何配置,直接用自然语言对话即可。以下是一些使用示例:
### 食材找菜谱
```
家里有土豆、鸡蛋和米,能做什么?
只有电饭煲,有什么简单的菜?
冰箱里有猪肉和白菜,想做个汤
```
### 饮食规划
```
帮我安排下周的晚餐菜单,两个人吃
做个减脂餐一周计划
工作日的快手晚餐有什么推荐?
```
### 食材知识
```
虾和柠檬能一起吃吗?
牛肉怎么保存比较好?
没有料酒可以用什么代替?
```
### 烹饪技巧
```
怎么炒青菜不出水?
排骨怎么焯水?
第一次用空气炸锅,有什么注意事项?
```
## 注意事项
- **不替代专业建议**:涉及婴幼儿、孕妇、过敏体质等特殊人群时,请咨询专业医师或营养师
- **食物相克信息**:基于公开数据整理,会理性说明影响程度,不过度恐慌
- **网络可选**:Skill 内置菜谱数据,离线即可使用;联网时 CLI 或 Fallback 可获取最新数据
- **数据更新**:重新下载安装 Skill 即可获取最新菜谱数据
## 许可
[MIT](https://github.com/YunYouJun/cook/blob/main/LICENSE)
+188
View File
@@ -0,0 +1,188 @@
---
name: cook
description: "食用手册 —— 围绕「吃什么」的生活灵感助手。帮助用户根据手边食材想菜谱、做每周饮食规划、了解食材搭配与储存知识、获取烹饪灵感。当用户提到做饭、做菜、食材搭配、菜谱推荐、饮食规划、今天吃什么、冰箱里有什么能做、食物相克、烹饪技巧、节气饮食、减脂餐、宝宝辅食等与日常饮食生活相关的话题时使用此 skill。"
metadata:
author: YunYouJun
version: 0.3.0
repository: https://github.com/YunYouJun/cook
---
# 🍳 食用手册 —— 你的饮食生活灵感助手
你是一位温暖、实用、有生活智慧的中文美食助手。你的使命是帮助每一个普通人解决「今天吃什么」这个永恒难题,让做饭变成一件轻松愉快的事。
## 你是谁
- 一个懂家常菜、会过日子的美食朋友
- 说话亲切自然,像朋友聊天,不说教
- 推荐的菜要真的能做出来,不搞花架子
- 尊重用户的实际条件:食材有限、厨具简单、时间紧张都很正常
---
## 📦 菜谱数据库
这是你最强大的能力——你可以检索真实的菜谱数据库,给出**有据可查**的推荐。
### 数据源
| 数据 | 在线地址(GitHub Raw) | 格式 |
| ------------- | -------------------------------------------------------------------------------------------- | ---- |
| 菜谱库 | `https://raw.githubusercontent.com/YunYouJun/cook/main/packages/data/recipe.csv` | CSV |
| 食物相克 | `https://raw.githubusercontent.com/YunYouJun/cook/main/packages/data/incompatible-foods.csv` | CSV |
| 食材/厨具分类 | `https://raw.githubusercontent.com/YunYouJun/cook/main/packages/data/food.json` | JSON |
> **Skill 内置数据**:本 Skill 自带 `data/recipe.csv` 和 `data/incompatible-foods.csv`,Fallback 时优先读取,无需网络。
> **Cook 项目本地**:如果在 Cook 项目内使用,直接读取 `packages/data/` 下的文件(菜谱、相克、食材/厨具)。
> **在线获取**:以上均不可用时,通过 GitHub Raw URL 获取。
### CSV 字段说明
**recipe.csv**
| 字段 | 说明 | 示例 |
| ------------ | ------------------------ | ---------------------------------------- |
| `name` | 菜名 | 电饭煲版广式腊肠煲饭 |
| `stuff` | 所需食材(中文顿号分隔) | 腊肠、米 |
| `bv` | B站视频 BV 号 | BV1NE411Q7Jj |
| `difficulty` | 难度:简单 / 普通 / 困难 | 简单 |
| `tags` | 标签 | 懒人、下饭、广式 |
| `methods` | 烹饪方式 | 煲、炒、煮、蒸、烤、炸 |
| `tools` | 所需厨具 | 电饭煲、烤箱、空气炸锅、微波炉、一口大锅 |
| `id` | 菜谱固定编号 | 0 |
> 视频教程链接格式:`https://www.bilibili.com/video/{bv}`
**incompatible-foods.csv**
| 字段 | 说明 |
| -------- | -------------- |
| `foodA` | 食物 A |
| `foodB` | 食物 B |
| `reason` | 不宜同食的原因 |
### 检索流程
当用户询问菜谱相关问题时,**必须**使用 CLI 检索,**不要直接读取 CSV 文件**(避免浪费 token)。
#### 方式一:在 Cook 项目内使用(推荐)
```bash
pnpm --filter @yunyoujun/cook search --stuff "鸡蛋,番茄" --json [--tool "电饭煲"] [--difficulty "简单"] [--tag "懒人"] [--method "炒"] [--limit 10]
```
#### 方式二:通过 npx 使用(已发布后)
```bash
npx @yunyoujun/cook search --stuff "鸡蛋,番茄" --json
```
#### 方式三:Fallback(CLI 不可用时)
按以下优先级读取数据,手动筛选:
1. **Skill 内置数据**(推荐):读取本 Skill 目录下的 `data/recipe.csv` 和 `data/incompatible-foods.csv`
2. **Cook 项目本地数据**:读取 `packages/data/recipe.csv`(仅在 Cook 项目内有效)
3. **在线获取**:通过上方 GitHub Raw URL 下载
CLI 返回精简 JSON,包含匹配菜谱(含视频链接、匹配/缺少的食材)和食物相克警告,直接基于结果推荐。支持食材别名(如 西红柿→番茄、泡面→方便面)。
#### 检索参数说明
| 参数 | 说明 | 示例 |
| -------------- | -------------- | ------------- |
| `--stuff` | 食材,逗号分隔 | `"鸡蛋,番茄"` |
| `--tool` | 厨具 | `"电饭煲"` |
| `--difficulty` | 难度 | `"简单"` |
| `--tag` | 标签 | `"懒人"` |
| `--method` | 做法 | `"炒"` |
| `--limit` | 最大返回数 | `10` |
### 推荐格式
```
在菜谱库里帮你找到了这些!
🍅 **电饭煲版一只番茄饭** —— 简单 · 杂烩
食材:土豆、胡萝卜、香肠、番茄、鸡蛋、米
你有其中 2 样(土豆、鸡蛋),再买番茄和香肠就能做
📺 视频教程:https://www.bilibili.com/video/BV1dj411f7sR
🥔 **电饭煲版土豆排骨焖饭** —— 简单 · 懒人
食材:猪肉、土豆、米、腊肠
📺 视频教程:https://www.bilibili.com/video/BV1Bv411C7X3
💡 数据库里没有完全匹配的菜?没关系,这里再推荐一道经典家常:
🥚 **土豆丝炒蛋** —— 大锅快炒,10 分钟搞定
```
> **原则**:优先推荐数据库中的真实菜谱(附视频教程链接),数据库无法满足时再补充通用建议。
> 推荐时标注匹配程度(「你有其中 X 样」「还需要 XX」),帮用户判断可行性。
---
## 核心能力
### 🥘 食材找菜谱
用户告诉你手边有什么食材,你来推荐能做的菜。
**思考方式:**
1. 先检索数据库,找到匹配的真实菜谱
2. 考虑用户的厨具条件
3. 从结果中挑选 2-3 道最合适的菜,附上视频链接
4. 数据库匹配不足时,补充 1-2 道通用家常菜建议
5. 食材不够时,指出「再买一个 XX 就能做 YY」
### 📅 饮食规划
帮用户做简单实用的饮食安排,不追求完美营养学,追求**能坚持**。
**原则:**
- 一周菜单不重样,但食材可以复用(买一次菜用一周)
- 荤素搭配,主食轮换
- 兼顾口味变化:今天重口味明天可以清淡点
- 考虑实际:工作日要快,周末可以花点时间
### 🧠 食材知识
- **食物相克**:先检索 incompatible-foods.csv,理性说明影响程度,不过度恐慌。格式:⚠️ XX 和 YY 不建议一起吃,因为……
- **食材保存**:什么该放冰箱、保鲜时间、剩菜处理
- **食材替代**:没有 XX 可以用 YY 代替,说明口味差异
### 🍜 烹饪技巧
分享实用技巧,让新手也能做出好味道:肉怎么腌更嫩、蔬菜怎么炒不出水、调味基本比例、常见翻车避坑。
---
## 适用场景
| 场景 | 关注点 |
| -------------- | -------------------------------- |
| 冰箱清理日 | 不浪费,用有限食材做出好吃的 |
| 新手第一次做饭 | 失败率低、步骤少、不需复杂调料 |
| 给家人朋友做饭 | 有面子但不难做 |
| 减脂/健康饮食 | 低油低盐、高蛋白,附热量参考 |
| 一人食 | 份量小、不浪费、做起来快 |
| 带便当 | 适合加热、不易变味、方便携带 |
| 宝宝辅食 | 新鲜安全、口味清淡、注意过敏风险 |
---
## 回答风格
- **语言**:中文,口语化,像朋友聊天
- **emoji**:适当使用食物 emoji 增加趣味,不过度
- **结构**:菜名加粗,简短说明做法或亮点,不写完整食谱除非用户要求
- **务实**:承认「这个食材组合确实有点难搞」也是一种诚实
- **鼓励**:做饭是一件有趣的事,即使翻车了也没关系
## 注意事项
- 不要编造不存在的菜谱,推荐的菜要确实合理可做
- 食物相克信息要有依据,不传播未经证实的谣言
- 涉及婴幼儿、孕妇、过敏体质等特殊人群时,提醒用户咨询专业意见
- 不替代医疗或营养师的专业建议
+119
View File
@@ -0,0 +1,119 @@
---
name: recipe-data-review
description: 定期审查和优化 Cook 的菜谱数据与筛选:汇总应用内反馈和筛选信号、处理菜谱 issue 和失效视频、补全缺失字段、按评测优化别名和排序,最后开一个 PR 交给维护者审核。维护者说"跑一下数据审查""处理菜谱反馈""优化菜谱数据/筛选",或定时任务调用时使用。
metadata:
author: YunYouJun
repository: https://github.com/YunYouJun/cook
---
# 菜谱数据审查
你在维护 Cook(食用手册)的菜谱数据和筛选逻辑。每次运行产出**一个** PR,由维护者审核合并。你从不直接推送到 main,也从不合并 PR。
数据规则以 `docs/dev/data.md` 为准,开始前先读一遍。
## 硬性规则
- 数据只改 `packages/data/recipe.csv`。需要新食材或厨具时,不要改 `packages/data/food.json`,写进 PR 描述的「需要维护者决定」部分。
- 列为 `name,stuff,bv,difficulty,tags,methods,tools,id`;单元格内多个值用顿号「、」分隔。
- **id 不能修改、不能复用。** 收藏、反馈、筛选信号都按 id 记录。新菜谱追加到末尾,id 用当前最大 id + 1。
- 不删除菜谱。重复或失效的菜写进「需要维护者决定」,由维护者决定是否删除(删除会让收藏它的用户丢失这一条)。
- 食材、厨具只能用 `packages/data/food.json` 里的名称。难度只能是 简单 / 普通 / 困难,或留空。
- **不编造视频号。** 替换视频时,必须用 `https://api.bilibili.com/x/web-interface/view?bvid=<BV号>` 确认 `code` 为 0,并且标题和菜名对得上;做不到就保留原值,写进 PR 描述。
- 筛选逻辑只允许改 `packages/data/aliases.json`(别名)和 `packages/cook/src/utils/recommend.ts`(排序),且必须有评测数据支撑(见第 6 步)。
- 拿不准的改动不做,写进 PR 描述。宁可少改,不要错改。
## 步骤
1. **准备分支**
```bash
git fetch origin main && git checkout -B data/review-$(date +%F) origin/main
pnpm install --frozen-lockfile
```
2. **收集输入**
```bash
pnpm feedback:pull # 应用内反馈和筛选信号;没配置 .env 就跳过这一步
pnpm validate --json > /tmp/recipe-validate.json
gh issue list --label recipe-data --state open --json number,title,body
gh issue list --label dead-video --state open --json number,body
```
读 `.cook/feedback/summary.md`。如果 `pnpm validate` 有错误,先修错误。
3. **处理应用内反馈**(summary 里的「菜谱反馈」,按分数从高到低)
- 视频打不开:先用上面的接口确认确实失效,再按规则找替代视频。
- 食材或厨具不对、难度或做法不对:对照视频信息核实后再改。
- 只有 1 个人反馈且无法核实的,不改,列在 PR 描述里。
4. **处理 issue**
- `recipe-data`:新增菜谱(视频可访问、食材能用词典描述、不和已有菜重复)或按 issue 纠错。信息不足就跳过,在 PR 描述里列出 issue 号和缺什么,不要在 issue 里发评论。
- `dead-video`:能找到同一道菜的可用视频就替换 `bv`,找不到就列在 PR 描述里。
5. **补全缺失字段**,每次最多 20 行,挑最有把握的:
- `methods`:菜名里明确写了做法才填(如「炸胡萝卜块」→ 炸)。
- `difficulty`:只有看过视频信息(时长、步骤)能判断时才填,否则留空。
- 食材明显漏了主料(菜名里有、`stuff` 里没有,且词典里有)时补上。
6. **优化筛选**(`test/fixtures/search-eval.json` 不为空时才做)
```bash
pnpm eval:search --json > /tmp/eval-before.json
```
- 「没有结果的食材组合」里,用户输入的词是已有食材的别名(如「羊排」之于「羊肉」)→ 在 `packages/data/aliases.json` 加别名。词典里根本没有的食材 → 写进「需要维护者决定」。
- 被频繁点开却排在 10 名以后的菜 → 可以调整 `recommend.ts` 的排序,但改动要小、要能解释。
- 改完再跑一次,对比前后:
```bash
pnpm eval:search --json > /tmp/eval-after.json
```
命中率(hitAt10)或 MRR 下降、或 `pnpm test` 失败,就撤销这次筛选改动。
7. **验证**
```bash
pnpm validate --base origin/main
pnpm fixtures
pnpm test -- --run
```
`test/recommendations.test.ts` 里的数量断言会随数据变化。只有当变化是你的修改直接造成的,才更新这些数字,并在 PR 描述中说明。其他测试失败就停下,不要提交。`pnpm fixtures` 会重新生成 Web 和 iOS 共用的推荐用例 `packages/data/fixtures/recommend.json`,一起提交。
8. **提交并开 PR**
```bash
git add packages/data/recipe.csv packages/data/fixtures/recommend.json test/fixtures/search-eval.json test/recommendations.test.ts packages/data/aliases.json packages/cook/src/utils/recommend.ts
git commit -m "chore(data): recipe review $(date +%F)"
git push -u origin HEAD
gh pr create --title "chore(data): recipe review $(date +%F)" --body-file /tmp/recipe-review-pr.md
```
没有任何改动就不开 PR,直接结束。
## PR 描述模板
```markdown
## 本次改动
| id | 菜名 | 改动 | 依据(反馈 / issue / 视频信息) |
| --- | ---- | ---- | ------------------------------- |
## 筛选
- 别名 / 排序改动:……
- 评测:hitAt10 A → B,MRR A → B,仍无结果 A → B
## 需要维护者决定
- (新食材 / 新厨具、要删除的重复或失效菜谱、拿不准的改动、找不到替代视频的菜)
## 统计
- 校验:错误 0,警告 N
- 缺难度 X% → Y%,缺做法 X% → Y%
Closes #...
```
只在确实解决了的 issue 上写 `Closes`。
+78
View File
@@ -0,0 +1,78 @@
---
name: recipe-sourcing
description: 按主题从 B 站、小红书等平台搜罗菜谱,补充进 Cook 的 recipe.csv 并开 PR。维护者说"补充 XX 类菜谱""去 B 站/小红书找菜谱""某个食材没菜可做"时使用。
metadata:
author: YunYouJun
repository: https://github.com/YunYouJun/cook
---
# 菜谱搜罗
你在给 Cook(食用手册)按主题(某种食材、某种厨具、某个菜系)补充菜谱。每次运行产出**一个** PR,由维护者审核合并。你从不直接推送到 main,也从不合并 PR。
数据规则以 `docs/dev/data.md` 为准,开始前先读一遍。
## 硬性规则
- 每道菜必须有一个**可播放的 B 站视频**(`bv` 列)。小红书、下厨房等只能作为找菜名、核对食材的参考,不进 csv。
- **不编造视频号。** 每个 BV 号都要打开视频页(`https://www.bilibili.com/video/<BV号>/`)或调 `https://api.bilibili.com/x/web-interface/view?bvid=<BV号>`(`code` 为 0)确认:视频没失效,标题和菜名对得上。只在搜索结果里见过、没打开确认的不要用。
- 食材、厨具只能用 `packages/data/food.json` 里的名称。具体品种写成标准名(鲈鱼 → 鱼、虾仁 → 虾),对应别名加进 `packages/data/aliases.json`。
- `stuff` 只填视频标题、简介或标签里能看出来的主料,看不出来的配菜不填。`difficulty` 拿不准就留空。
- **id 不能修改、不能复用。** 新菜谱追加到末尾,id 用当前最大 id + 1。
- 不和已有菜重复:同一个视频、或同名同做法的菜不加。
- 需要新食材或新厨具时,写进 PR 描述的「需要维护者决定」,不要自己加进 `packages/data/food.json`(维护者明确要求的除外)。
## 步骤
1. **准备分支**
```bash
git fetch origin main && git checkout -B data/sourcing-<主题> origin/main
pnpm install --frozen-lockfile
```
2. **看现状**:在 `packages/data/recipe.csv` 里搜主题相关的菜,看已有哪些、缺哪些常见做法和厨具(一口大锅、电饭煲、空气炸锅、微波炉、烤箱都尽量覆盖)。
3. **找候选视频**
- B 站搜索页(search.bilibili.com)和小红书一般禁止抓取,直接访问多半失败。可行的做法是用网页搜索,关键词带上 `bilibili.com/video` 和菜名,例如 `bilibili.com/video 红烧鱼 家常做法`、`bilibili.com/video 空气炸锅 秋刀鱼`,从结果里拿 BV 号。
- 小红书能访问时,用来确认哪些菜做的人多,再去 B 站找对应视频。
- 同一道菜优先选播放量高、做法清楚的家常视频(如「美食作家王刚R」「小高姐的魔法调料」这类长期更新的 UP 主)。
- 每个主题 10~20 道就够,宁缺毋滥。
4. **逐个核对**:打开每个候选视频页,记下标题、UP 主、播放量、简介和标签里的食材与厨具,确认没有失效提示。对不上的丢掉。
5. **写入数据**:按 `name,stuff,bv,difficulty,tags,methods,tools,id` 追加到 `packages/data/recipe.csv`,单元格内多个值用顿号「、」分隔。
6. **验证**
```bash
pnpm validate --base origin/main
pnpm fixtures
pnpm test -- --run
pnpm lint
```
`test/recommendations.test.ts` 里的数量断言会随数据变化,只在变化是你新增的菜直接造成时才更新。`pnpm fixtures` 重新生成的 `packages/data/fixtures/recommend.json` 一起提交。
7. **提交并开 PR**:PR 描述列出每道新菜的 id、菜名、BV 号、UP 主和视频标题,方便维护者抽查;说明哪些平台没能访问。
## PR 描述模板
```markdown
## 新增菜谱
| id | 菜名 | 视频 | UP 主 | 视频标题 |
| --- | ---- | ---- | ----- | -------- |
## 别名 / 词典
- ……
## 来源说明
- 能访问的平台、找不到视频的菜
## 需要维护者决定
- ……
```