name: plugin-core-builtin-migration description: > 将 MindOS 渲染器插件从“可选插件”升级为“完全内置能力(core builtin)”的通用流程。 当用户要求“把某插件改成内置/核心”“插件不应可关闭”“插件主程序化”或需要将旧入口迁移到 新主流程并保留兼容迁移能力时触发。
Plugin Core Built-in Migration
把单个插件改造成“稳定、默认、不可缺席”的产品能力,并沉淀可复用迁移步骤。
适用场景:
- 某插件已经成为核心体验(例如 TODO、CSV、配置、变更中心)
- 旧插件入口要退役,但历史数据要可迁移
- 需要避免“某页面漏 import 导致插件空列表”这类注册漂移
目标定义(先对齐)
在本项目中,“完全内置”建议同时满足:
- 注册稳定:渲染器注册有且仅有一个客户端根入口(推荐
SidebarLayout/ShellLayout) - 默认可用:
manifest.builtin = true - 不可禁用(如需真正 core):
manifest.core = true(registry会强制启用) - 可观测可维护:插件页、设置页、文档、测试一致
- 历史兼容:旧入口数据有迁移方案,不丢内容
- 表层语义清晰:区分“插件(可管理)”和“应用内建能力(不在插件面板展示)”
质量闸门(必走)
每次执行本 Skill 时,默认同时应用以下质量视角(按顺序):
产品设计视角(
product-designer)- 检查信息层级、任务路径、主次操作、反馈时机
- 明确“主路径 3 步内可完成”,避免迁移后流程变长
UI/UX 视角(
ui-design-patterns)- 检查按钮层级、交互一致性、空状态/错误状态/加载状态
- 禁止无意义下划线链接滥用;主 CTA 与次级 CTA 视觉层级明确
- 深色模式可读性必须通过(按钮文字对比、tag 对比、focus 可见)
实现质量视角
- 迁移逻辑幂等(重复执行不重复导入)
- 注册机制单点化(禁止多处散落 import 造成漂移)
- 避免仅服务端注册导致客户端
0/0空列表- 兼容代码失败不阻断主流程(best-effort + 可观测)
- 验证视角
- 最少通过:core/API 回归测试 + lint
- UI 变更至少进行一次人工检查(亮色/暗色)
若任一步不满足,迁移不得判定完成。
执行流程(通用)
Step 1) 盘点现状与边界
先确认插件的四类事实来源:
- 代码入口:
packages/web/components/renderers/<plugin>/manifest.ts - 注册入口:
packages/web/lib/renderers/index.ts(自动生成) - 使用入口:
resolveRenderer()调用链(如ViewPageClient) - 展示入口:插件面板/设置页(优先使用
getPluginRenderers())
并回答:
- 该插件是否应 core(不可关闭)?
- 是否存在旧文件协议/旧入口(如
Agent-Diff.md)需要迁移?
Step 2) 升级插件声明
在 manifest 中设置:
builtin: true(内置)core: true(若要完全内置且不可关闭)appBuiltinFeature: true(若是“应用内建能力”且不应出现在插件管理面板)match保持明确,避免误匹配
如果插件要被替换/下线:
- 删除旧 renderer 文件
- 重新生成
packages/web/lib/renderers/index.ts
Step 3) 统一注册机制(防漂移)
必须收敛为单点初始化(客户端):
- 在客户端根组件(推荐
SidebarLayout)引入@/lib/renderers/index - 移除其他页面/组件分散 import(避免重复与遗漏并存)
验收标准:
- 任意路由进入插件页,插件列表不应出现
0/0的假空状态 - 在“应用内建能力”模式下,被标记能力应从插件面板消失但渲染仍正常
Step 4) 历史兼容迁移(关键)
如果旧插件依赖旧文件格式:
- 在核心数据层实现“懒迁移”:
- 首次读取时自动导入旧格式
- 写入新格式(结构化 JSON)
- 迁移后清理旧入口文件(防止双写和重复导入)
- 提供一次性脚本(离线/手动修复):
scripts/migrate-*.js
Step 5) UI/UX 对齐
- 插件页:状态、可开关策略与 core 语义一致
- 设置页:显示 builtin/core 标签逻辑一致
- 若设为
appBuiltinFeature:在插件页/设置页/首页 Extensions 一致隐藏 - 新主流程页面补齐筛选、空状态、加载、已读等基本交互
Step 6) 文档与知识同步
至少同步:
wiki/plugins/README.mdwiki/60-stage-plugins.md- 相关 spec / pitfalls / refs(若行为模型发生变化)
并记录迁移决策:
- 为什么从插件入口转主程序能力
- 旧入口如何兼容、何时清理
Step 7) 测试与回归
最低测试集合:
- core 层迁移测试(旧格式 -> 新格式)
- API 层筛选/查询测试(若有 changes/feed 类接口)
- UI 基础 smoke(插件列表非空、核心按钮可用)
- 分类测试(
appBuiltinFeature能否正确从插件表层隐藏)
推荐命令:
npm --prefix app run test -- __tests__/core/content-changes.test.ts __tests__/api/changes.test.ts
AgentDiff -> Built-in 的参考映射
这次迁移可作为样板:
- 旧:
Agent-Diff.md+agent-diffrenderer - 新:
.mindos/change-log.json+/api/changes+/changes主页面 + 全局提醒 - 兼容:读取旧 block 自动导入;导入后删除
Agent-Diff.md - 治理:删除
diff-viewerrenderer 与文档旧入口,保留结构化审计链路
常见坑位清单
- 只删插件没迁移旧数据 -> 用户历史丢失
- 注册入口分散/仅服务端注册 -> 客户端插件面板出现
0/0 - 文档未同步 -> 用户看到过时入口
- core/builtin/appBuiltinFeature 语义混淆 -> 本应“应用内建”的能力仍出现在插件面板
- 迁移不幂等 -> 每次读取重复导入同一批旧数据
交付 Checklist(可复制)
- manifest 层完成 builtin/core 定义
- 如需“非插件化”,manifest 增加
appBuiltinFeature: true - 全局注册单点化(客户端根入口统一引入)
- 旧入口迁移逻辑已实现且幂等
- 迁移后旧文件可清理
- 提供一次性迁移脚本
- 插件页/设置页状态正确(含 appBuiltinFeature 隐藏策略)
- 文档已同步更新
- 测试通过