@lark-project/cli
Version:
飞书项目插件开发工具
375 lines (296 loc) • 16.6 kB
Markdown
# Meegle Plugin Skills 合并方案
> 把当前 7 个 `meegle-plugin-*` skill 合并为单一入口 `meegle-plugin`,
> 保留 `meegle-plugin-cli`(独立活动)。
> 通过 `install-skills.js` postinstall 对称通道完成存量用户零感知迁移。
---
## 1. 背景与决策
### 1.1 现状
仓库 `skills/` 下当前有 **8 个 skill**:
| skill | 角色 | 合并后去向 |
| --- | --- | --- |
| `meegle-plugin-create` | 创建空壳工程 | 合并 → `meegle-plugin` (phase=create) |
| `meegle-plugin-feature` | 加 / 改 feature(前端 + 混合后端) | 合并 → `meegle-plugin` (phase=feature) |
| `meegle-plugin-polish` | 完善插件元信息 | 合并 → `meegle-plugin` (phase=polish) |
| `meegle-plugin-publish` | 构建 / 上传 / 发版 | 合并 → `meegle-plugin` (phase=publish) |
| `meegle-plugin-workflow` | 从零做插件全流程 | 合并 → `meegle-plugin` (phase=workflow) |
| `meegle-plugin-backend` | 后端 webhook / OpenAPI / lpm perm | 合并 → `meegle-plugin` (phase=backend) |
| `meegle-plugin-shared` | 跨 skill 共享规则 | 合并 → `meegle-plugin/references/shared.md` |
| `meegle-plugin-cli` | lpm CLI 命令查询 / 诊断 | **保留独立**(与开发流程是不同活动) |
### 1.2 已识别问题(来自 `2026-05-19` 复盘)
- **路由失败无声**:5 段 description 重叠,模型挑错 skill 不会报错。复盘实证 `create` 截胡 `workflow`,导致 polish 缺席、publish 失败 5 次。
- **跨 skill 契约脆**:`orchestrated=true` 等隐性参数在 skill 间传递,无类型检查。
- **pipeline context 重复 reload**:全流程场景下 5 个 SKILL.md header 依次加载,且模型把"进入新 mode"误解为"重新 Skill()"导致 3 次重复 invoke 同一 skill。
- **task_create 反复重建**:`using-superpowers` default 行为 + 多次 invoke = 4 次 task_create(理想 1 次)。
- **publish pre-check 未卡 metadata**:绕开 workflow 直接 publish 时无护栏,被后端打回 5 次。
### 1.3 决策
**3+→1 合并**:合并 7 个 `meegle-plugin-*`(`-cli` 除外)为单一 `meegle-plugin` skill。
理由(按权重):
1. 路由层从"5 段重叠 description LLM 概率挑"降级为"1 段 description 命中插件领域",路由错误率显著下降。
2. 阶段选择从隐式 skill 选择转为 skill 内确定性 SOP(`test -f` + 关键词表 + state 文件)。
3. 跨 skill 契约消失,变成 skill 内部状态机。
4. 前后端混合 feature 路径减少跨 skill 跳转。
5. 符合 Anthropic 官方"cohesive skill around an activity + progressive disclosure"模式。
6. `install-skills.js` postinstall 已是对称通道(add 默认执行),加 remove 即可零感知迁移。
**`meegle-plugin-backend` 一并合并**(不保留独立):外部后端仓场景靠 `context` 维度 + references 子文件区分,不需要 skill 边界。
---
## 2. 目标终态
### 2.1 仓库 `skills/` 结构
```
skills/
├── meegle-plugin/ ← 新主 skill
│ ├── SKILL.md # < 500 行,含 phase router
│ └── references/
│ ├── shared.md # 原 meegle-plugin-shared 内容
│ ├── checkpoint.md # state.json 协议
│ ├── errors.md
│ ├── source-attribution.md
│ │
│ ├── create-setup.md # 原 meegle-plugin-create/references/setup.md
│ ├── create-plan.md
│ ├── create-apply.md
│ ├── create-verify.md
│ │
│ ├── feature-code-setup.md # 原 meegle-plugin-feature/references/*
│ ├── feature-code-plan.md
│ ├── feature-code-apply.md
│ ├── feature-code-verify.md
│ ├── feature-config-plan.md
│ ├── feature-config-apply.md
│ ├── feature-point-types/ # 整目录搬迁
│ │ ├── button/index.md
│ │ ├── componentSchedule/index.md
│ │ ├── control/{form-control,index,table-cell}.md
│ │ ├── customField/{index,value-shape}.md
│ │ ├── dashboard/index.md
│ │ ├── liteAppComponent/{index,read-props,write-outputs}.md
│ │ ├── context-only.md
│ │ └── shared-scenes.md
│ │
│ ├── polish-analyze.md
│ ├── polish-generate.md
│ ├── polish-confirm.md
│ ├── polish-apply.md
│ │
│ ├── publish-pre-check.md # 含新增 PC0 metadata gate
│ ├── publish-apply.md
│ ├── publish-verify.md
│ │
│ ├── workflow-phase-0-context.md
│ ├── workflow-phase-1-scaffold.md
│ ├── workflow-phase-2-feature.md
│ ├── workflow-phase-3-release.md
│ │
│ ├── backend-setup.md # 含目录解析 SOP
│ ├── backend-contract.md
│ ├── backend-impl.md
│ ├── backend-perm.md
│ └── backend-integ-test.md
│
└── meegle-plugin-cli/ ← 保持不变
├── SKILL.md
└── references/{commands,diagnose}.md
```
### 2.2 SKILL.md 顶层结构(草案)
```markdown
---
name: meegle-plugin
description: |
Meegle / 飞书项目插件开发的统一入口。覆盖:
- 插件工程内:创建空壳、加 / 改 feature(前端 / 后端 / 混合)、
完善插件元信息、构建发布、从零全流程编排
- 外部后端仓:处理 Meegle webhook、调 OpenAPI、申请 lpm perm scope
触发关键词:
- 工程类:lpm、plugin.config.json、点位、builder_comp、视图配置、
工作项 UI 元素、字段类型、看板、详情区块
- 后端类:webhook、回调、验签、OpenAPI 数据、lpm perm、scope、
申请权限、自建后端、对接 Meegle
- 流程类:从零做、新建插件、加功能、改功能、完善插件信息、
改名 / 描述 / 分类、发布插件、上线、release、publish
本 skill 自动检测 cwd 是否插件工程并路由到对应 phase;
断点续跑通过 .lpm-cache/state.json 恢复。
---
# Meegle Plugin
> 本 skill 一次加载即完整。phase 切换通过 `Read references/<file>.md` 推进,
> **不要再次 Skill(meegle-plugin)**。被异步中断(如 ask_user)后继续即可。
>
> 本 skill 不主动 task_create。状态追踪走 `.lpm-cache/state.json`
> (见 `references/checkpoint.md`)。已有 todo 时只 task_update。
## 0. Always Read First
- `references/shared.md` — 共享规则(认证、权限、安全)
- `references/checkpoint.md` — state.json 协议
## 1. Context Detection (确定性逻辑,不询问 LLM)
```
A. CWD 守卫
test -f ./plugin.config.json
存在 → context=plugin-project
不存在 → context=external-backend OR not-applicable
(后续 phase 检测会再分流)
B. 读 .lpm-cache/state.json
存在 .currentPhase → 优先使用(断点续跑)
```
## 2. Phase Detection(关键词表,确定性匹配)
按以下优先级匹配用户原话,命中即停:
| 关键词 / 句式 | phase | 适用 context |
| --- | --- | --- |
| "从零做"、"新建一个"、"我需要一个 xxx 插件"、"做个 xxx 插件" | workflow | plugin-project (cwd 不在工程内时先建) |
| "创建空壳"、"初始化插件骨架" | create | not-applicable → 切到目标父目录 |
| "发布"、"上线"、"release"、"publish"、"打包到市场" | publish | plugin-project |
| "完善插件信息"、"改名"、"改描述"、"改分类" | polish | plugin-project |
| "webhook"、"回调"、"验签"、"OpenAPI 调用"、"lpm perm"、"申请 scope" | backend | plugin-project OR external-backend |
| "加功能"、"加点位"、"加按钮"、"加 Tab"、"加视图"、"实现 xxx 功能" | feature | plugin-project |
无命中 → 询问用户意图(4 选 1 + 自定义)。
## 3. Phase Routing
按 phase 直接 `Read references/<phase>-*.md` 序列执行。
phase 间跳转走状态机(见 `references/checkpoint.md`),不重新 Skill()。
### Phase 关键 SOP(细节在对应 references/)
- **create**: setup → plan → apply → verify
- **feature**: code-setup → code-plan → config-plan → config-apply → code-apply → code-verify
- 内含"是否需要 backend 子分支"判断(关键词 + 用户确认)
- **polish**: analyze → generate → confirm → apply
- **publish**: pre-check (PC0/PC1/PC1.5/PC2) → apply → verify
- **workflow**: phase-0-context → phase-1-scaffold → phase-2-feature → phase-3-release
- **backend**: setup(含目录解析 SOP)→ contract → perm → impl → integ-test
## 4. Backend 目标目录解析(SOP 节选,详见 backend-setup.md)
```
1. 读 .lpm-cache/state.json 的 backend.targetDir → 命中即用
2. context=external-backend → targetDir = cwd(确认即可)
3. context=plugin-project → 按优先级扫描候选目录:
plugin.config.json: backend.dir 字段
./server/ ./backend/ ./api/
./packages/*-{be,server,api}/
./apps/*-{server,api}/
4. 1 候选 → 询问确认;多候选 → 让用户选;无候选 → 默认 ./server/ 询问
5. 写回 state.json,后续复用
```
```
---
## 3. 迁移步骤(一次性切换,不灰度)
### Step 1:仓库内构建新 skill 目录(不影响线上)
**3.1.1 拷贝并重命名 references**
```bash
mkdir -p skills/meegle-plugin/references
# shared
cp skills/meegle-plugin-shared/references/{checkpoint,errors,source-attribution}.md \
skills/meegle-plugin/references/
# create
for f in setup plan apply verify; do
cp skills/meegle-plugin-create/references/$f.md \
skills/meegle-plugin/references/create-$f.md
done
# feature
cp -r skills/meegle-plugin-feature/references/point-types \
skills/meegle-plugin/references/feature-point-types
for f in code-setup code-plan code-apply code-verify config-plan config-apply; do
cp skills/meegle-plugin-feature/references/$f.md \
skills/meegle-plugin/references/feature-$f.md
done
# polish / publish / workflow / backend 同理(前缀化)
```
**3.1.2 写新 SKILL.md**
按 §2.2 草案落地,重点:
- description 是当前 7 段 description 触发词的**严格超集**(用脚本 grep 验证)
- header < 500 行,符合 Anthropic 推荐
- 顶部加"一次加载不重复 invoke"和"不主动 task_create"两条约束(解决复盘 P0 问题 2、3)
**3.1.3 references 内部链接重写**
原跨 skill 引用如 `meegle-plugin-create/references/setup.md` → `references/create-setup.md`,全仓 grep 替换。
### Step 2:把复盘 P0 修复纳入新 SOP
| P0 问题 | 修复位置 |
| --- | --- |
| publish 没卡 metadata | `references/publish-pre-check.md` 加 **PC0: metadata completeness**:检查 `name` 不是临时工作名、`shortDescription` / `detailDescription` / `categoryIds` 非空,缺失自动转 phase=polish |
| skill 被重复 invoke | SKILL.md 顶部约束(合并后只有 1 个 skill,问题自然消失) |
| task_create 反复重建 | SKILL.md 顶部"不主动 task_create"约束 |
| 路由错误(create 截胡 workflow) | 合并消除,phase 检测靠关键词表确定性匹配 |
### Step 3:改造 `scripts/install-skills.js` 加 remove 通道
在 `main()` 内、`addArgs` 调用之前插入旧 skill 清理:
```js
const LEGACY_SKILLS = [
'meegle-plugin-create',
'meegle-plugin-feature',
'meegle-plugin-polish',
'meegle-plugin-publish',
'meegle-plugin-workflow',
'meegle-plugin-backend',
'meegle-plugin-shared',
];
function removeLegacy(cmdResolver) {
for (const name of LEGACY_SKILLS) {
runSkillsCommand(
cmdResolver.cmd,
[...cmdResolver.prefix, 'remove', name, '-g'],
skillsDir,
{ ignoreFailure: true, silentNotFound: true, timeoutMs: 10_000 }
);
}
}
```
要点:
- 复用现有的 bundled / global / npx 兜底链
- 单条失败不阻断后续(`ignoreFailure: true`)
- "skill not found" 不打 warning(对没装过旧版本的新用户是正常的)
- 单条 timeout 缩短到 10s(本地操作)
- 复用现有 `shouldSkip()` 跳过条件(`LPM_SKIP_SKILLS=1` / `CI=true` / `--ignore-scripts`)
### Step 4:行为等价性回归
**用复盘 session 当回归用例**:
1. 准备 fixture 工程(空目录 / 已有插件工程)
2. 跑当前 5-skill 架构下的 N 条典型 prompt,记录 stdout / 文件改动 / state.json 变化
3. 切到新 `meegle-plugin` 跑同样 prompt,diff 输出
4. 差异分类:
- 等价(不同顺序但等效)→ 接受
- 优化(新流程更顺,如混合 feature 少跨 skill)→ 接受
- 退化(缺步骤 / 缺产物)→ 修
5. 必须覆盖的场景:
- 从零做插件全流程(复盘场景)
- 给已有插件加纯前端 feature
- 给已有插件加前后端混合 feature
- 直接发布(不走 workflow)
- 完善元信息后发布
- 外部后端仓接 webhook
- 断点续跑(state.json 恢复)
### Step 5:发版与 description 触发覆盖审计
发版前 checklist:
- [ ] 新 description 包含原 7 段所有关键触发词(grep diff)
- [ ] SKILL.md < 500 行
- [ ] references 路径无残留旧前缀
- [ ] `install-skills.js` 单测:模拟存量用户(已有 7 个旧 skill)→ 升级后 → `npx skills list | grep meegle-plugin` 只剩 `meegle-plugin` + `meegle-plugin-cli`
- [ ] CHANGELOG / release notes 写明合并 + 自动清理 + 手动备选命令
- [ ] 文档(`docs/v2/architecture.md` `docs/v2/extending.md`)同步
---
## 4. 风险与回滚
### 4.1 风险矩阵
| 风险 | 严重度 | 缓解 |
| --- | --- | --- |
| 新 SOP 行为不等价(漏步骤) | 高 | Step 4 回归覆盖;保留 fixture 持续跑 |
| description 漏触发词 | 中 | 发版前 grep diff + 灰度第一周观察新 skill 触发率 |
| 用户在旧 skill references 里有本地修改 / 私货 | 中 | 文档明示"自定义请放 skill 目录之外";postinstall 不主动 grep(沿用 add 的隐式约定) |
| `npx skills remove` 网络 / 权限失败 | 低 | 单条失败不阻断;打 manual hint;env var 跳过 |
| 老会话已 load 旧 skill 进内存 | 低 | release notes 提示重启 AI 工具 |
| 用户记忆的旧 slash 名(`/meegle-plugin-publish` 等)失效 | 中 | 新 description 包含旧关键词;自然语言触发覆盖;文档说明 |
### 4.2 回滚路径
**用户侧**:装回旧版本 `lpm`,旧 postinstall 自动 add 回 7 个 skill(天然回滚,单向锁不存在)。
**仓库侧**:revert 合并 PR,下个版本发出后用户升级即恢复。
回滚成本与"装新版本"对称——这是 postinstall 通道带来的最大红利。
---
## 5. 不在本次范围
- `meegle-plugin-cli` 不动(属于独立活动:CLI 命令查询/诊断,不是开发流程)
- `meego` skill 不动(飞书项目业务数据查询,与插件开发无关)
- 不做灰度双轨期(postinstall 通道使其无必要)
- 不写 forwarder skill(无外部死链需要兜的硬证据)
- 不主动检测用户私货文件(沿用 add 的隐式约定即可)
---
## 6. 实施 checklist
- [ ] **Step 1.1** 拷贝 references 到 `skills/meegle-plugin/references/` 并加前缀重命名
- [ ] **Step 1.2** 写 `skills/meegle-plugin/SKILL.md`(含 description 超集 + phase router + 顶部约束)
- [ ] **Step 1.3** 重写所有 references 内部链接
- [ ] **Step 2** 把复盘 P0 的 4 条修复落进新 SOP(PC0 metadata gate 等)
- [ ] **Step 3** 修改 `scripts/install-skills.js` 加 LEGACY_SKILLS 清理逻辑
- [ ] **Step 4** 准备并跑通 7 类回归 fixture
- [ ] **Step 5** description 触发词 grep diff + SKILL.md 行数检查 + 文档同步
- [ ] **Step 6** 删除仓库内的旧 7 个 skill 目录(`skills/meegle-plugin-{create,feature,polish,publish,workflow,backend,shared}`)
- [ ] **Step 7** 发版(含 release notes 说明)
---
## 7. 一句话
把 7 个 `meegle-plugin-*` 合并成 1 个 `meegle-plugin`,靠 `install-skills.js`
的 postinstall 对称通道(add 新 + remove 旧)做存量用户零感知迁移。
路由从"5 段重叠 description LLM 概率挑"降级为"1 段命中 + skill 内 SOP 确定性分流",
回到 Anthropic 官方推荐的 cohesive skill + progressive disclosure 模式。
回滚路径与升级路径对称,零额外运营复杂度。