mcpField
S
schema-unify

schema-unify

github.com/garrytan生产力31.3k171 次安装今天更新
代码仓库

关于 schema-unify

schema-unify 是 gbrain 的迁移技能,指导将 gbrain-base 脑库升级到 gbrain-base-v2 的规范类型体系。它涵盖预览、执行、验证与回滚,并强调受保护操作需经本地 CLI 手动确认。

主要功能

  1. 01检查当前 schema 与升级状态
  2. 02预览类型重映射和页面转换
  3. 03迁移页面类型并保留旧类型
  4. 04验证迁移结果并提供回滚路径

适用场景

  1. 01处理类型膨胀或可用升级提示
  2. 02将重定向页面转换为别名记录
  3. 03将边类型页面转换为链接记录

MCP 相关

说明指出,受保护的 unify-types 操作必须通过脑库主机上的本地 CLI 提交,不能通过远程 MCP submit_job 操作提交。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/garrytan/gbrain --skill schema-unify

安装后在 Claude Code 中输入/schema-unify确认已加载。

详细介绍

Schema Unification(gbrain-base → gbrain-base-v2)

v0.41.22 发布了 gbrain-base-v2,这是一套 15 类 DRY/MECE 分类体系(14 个标准类型加 note 兜底类型),作为新 brain 的默认安装配置。已使用 gbrain-base 的现有 brain 可以通过 onboard 的 pack_upgrade_available 检查结果,以及 unify-types PROTECTED Minion 处理程序选择升级。

本 skill 是该迁移的操作手册。

brain_first:豁免

本 skill 针对的是 brain 的结构本身,它不能依赖正在重塑的 brain。因此无需先执行 gbrain search 查询,直接进入 onboard。

触发时机

  • Agent 运行 gbrain onboard --check 并看到 pack_upgrade_available 或 type_proliferation 警告
  • 用户询问"什么是标准分类体系 / 如何清理页面类型 / 如何迁移到 v2"
  • 出现 dangling_aliases 检查结果(统一后的垃圾回收)
  • 从自定义 pack 导入内容的 Agent 需要参考 v2 分类体系

思维模型(一段话)

生产环境中的 gbrain brain 经过多年导入,积累了 94 个不同的 pages.type 值:tweet、tweet-thread、tweet-bundle、tweet-single、media/x-tweet/bundle、tweet-stub 并存;5.5K 个概念重定向页面;本应是链接的 atom-partner-link 页面;以及 civic、framework、insight、memo、anecdote 等零散类型。解决办法是将其合并为 15 个标准类型(person、company、media、tweet、social-digest、analysis、atom、concept、source、deal、email、slack、writing、project、note):子类型、格式和来源信息移入 frontmatter;重定向改为 alias 行;边缘型页面改为真正的链接行;并设置兜底规则,将长尾未知类型归入 note,同时保存 frontmatter.legacy_type = <原始类型> 以便回滚。

工作流程

阶段 1:探查

确认 brain 确实仍在 gbrain-base 上(而非已升级到 v2)。

gbrain schema active --json | jq -r '.identity'

预期输出为 [email protected]+<sha>。如果看到 gbrain-base-v2@...,说明 brain 已在 v2 上,跳过迁移。

然后运行 onboard,查看将会发生哪些变化:

gbrain onboard --check

查找 pack_upgrade_available 检查结果。如果结果为 ok,则说明当前 pack 没有声明后继版本,无需继续。

阶段 2:预览

运行按类别输出的说明:

gbrain onboard --check --explain

该命令以 dry-run 模式调用 unify-types 处理程序,并输出:

  • 每个类别(tweet、article、company 等)将重新分类的页面数量
  • 将转换为 alias 行的概念重定向页面数量
  • 将转换为真正链接的边缘型页面数量
  • 针对未知类型合成的兜底规则

请仔细检查输出。如果建议的变更看起来有误,请勿继续执行——请提交 issue,或编写一个调整了 mapping_rules 的自定义 pack。

阶段 3:执行

托管大脑:预览后停止。 托管大脑(已开启托管持久化)暂不支持执行迁移:重新分类(retype)直接写入页面,而不是通过协调写入器,因此执行任务会在修改任何内容之前被拒绝(writer_coordinator_required)。这类大脑上的 pack_upgrade_available 检查结果会说明这一点。请继续使用 gbrain onboard --check --explain 进行预览,告知用户 pack 升级需等待支持协调重新分类后再进行,并且不要提交下面的执行任务。唯一例外:当预览显示没有需要重新分类、建立链接或别名的内容时,执行任务只会切换当前激活的 pack,此时可在用户同意后提交。

该处理程序受保护(manual_only),自动驾驶永远不会自动触发它。需显式提交:

gbrain jobs submit unify-types \
  --params '{"target_pack":"gbrain-base-v2","apply":true}'

在 PGLite(安装默认配置)上,或在没有运行 gbrain jobs work 工作进程或守护进程的任何环境中,请添加 --follow,使任务内联执行:

gbrain jobs submit unify-types \
  --follow \
  --params '{"target_pack":"gbrain-base-v2","apply":true}'

持久化工作进程守护进程仅适用于 Postgres。在 PGLite 上若不加 --follow,任务会一直处于排队状态,迁移永远不会运行。

apply 默认为 false(试运行),这是处理程序约定的。因此此处必须加上 "apply":true,否则任务会报告成功,但没有重新分类任何内容,也不会切换激活的 pack。若只想预览,省略该参数即可。

按阶段查看进度(工作进程守护进程运行时;使用 --follow 时,相同的进度会内联输出):

gbrain jobs get <job_id>      # one job: status, progress, result
gbrain jobs watch --follow    # live dashboard of the whole queue

若任务在此处一直保持 queued 状态,说明没有运行中的工作进程;请加上 --follow 重新提交,以内联执行。

在包含 18.6 万页面的大脑上,预计耗时约 10 分钟。处理程序按以下步骤运行:

  1. 预检(验证目标 pack 含有 mapping_rules:)
  2. 统计快照(为庆祝摘要记录迁移前状态)
  3. 获取 gbrain-unify 数据库锁(TTL 60 分钟)
  4. 执行各阶段:
    • 显式重新分类规则(tweets、articles、companies 等)
    • 兜底重新分类(未知类型 → 带有 legacy_type 的 note)
    • 页面转链接规则(atom-partner-link、symlink)
    • 页面转别名规则(concept-redirect)
  5. 最终同步(按路径前缀同步未分类的行)
  6. 切换激活的 pack 为 gbrain-base-v2
  7. 验证并输出庆祝摘要
阶段 4:验证
gbrain onboard --check
gbrain schema stats

预期结果:

  • pack_upgrade_available → ok(激活的 pack 现已是 v2)
  • type_proliferation → ok(不同的类型取值不超过 16 个)
  • dangling_aliases → ok(slug_aliases 全部指向激活的规范页面)
  • gbrain schema stats 显示的不同类型数量不超过 16 个
阶段 5:迁移后

迁移后,搜索及 --type article 查询仍会返回这些页面:media 将 article 声明为别名,因此类型过滤会通过激活 pack 的别名闭包进行扩展(结果中还会包含其他 media 页面)。直接对 pages.type 执行的 SQL 需要更新为规范类型。

搜索查询会获得一个小幅排序加权:通过 slug_aliases(一个或多个别名的规范页面)访问到的页面会获得 1.05 倍的提升。可通过 gbrain search --explain 查看。

回滚

每个被重新分类的页面都会保留 frontmatter.legacy_type = <原始类型>。

批量恢复类型(仅适用于 Postgres/Supabase 部署;需要直接访问数据库):

UPDATE pages SET type = frontmatter->>'legacy_type'
WHERE source_id = 'default' AND frontmatter->>'legacy_type' IS NOT NULL;

在 PGLite 上没有 SQL 命令行,因此请改用 CLI:frontmatter.legacy_type 会按页面持久保存,因此可通过常规的 put_page/CLI 接口逐个撤销重新分类。软删除恢复和 pack 切换回滚在所有引擎上均可使用。

页面转别名和页面转链接的源页面会以 72 小时 TTL 进行软删除。请在该时间窗口内恢复:

gbrain restore <slug>

撤销激活 pack 的切换:

gbrain schema use gbrain-base

反模式

  • 不要在自动驾驶模式下运行 unify-types。 它按设计是 manual_only。自动驾驶修复绝不应悄悄改动你的分类体系。
  • 不要指望 mapping_rules 显式覆盖每个遗留类型。 对长尾类型使用兜底规则(*unknown*)。页面会被重新类型化为 note,并保留 legacy_type。
  • 不要改写正文中的 wikilink。 slug_aliases 表就是解析器。[[old-redirect-slug]] 通过 engine.resolveSlugWithAlias 短路逻辑继续生效。
  • 不要跳过 dry-run。 在应用之前务必先运行 --explain。信任度的变化是真实存在的。
  • 不要并发运行两个 unify 任务。 gbrain-unify 数据库锁会让它们串行执行;第二个提交会以 "already in progress" 被拒绝。

决策树

Active pack already gbrain-base-v2?
  → Skip migration.

Custom pack with own mapping_rules?
  → Run --check --explain to see if your pack declares migration_from
    for the active pack. If yes, target_pack = your pack name.

Brain has many custom types not covered by gbrain-base-v2 mapping_rules?
  → The catch-all retype binds them to `note` with legacy_type preserved.
    Review by inspecting frontmatter.legacy_type after the migration.

Federated brain (multiple sources)?
  → Add --params source_id to scope the migration per-source. Each
    source can be migrated independently.

Worried about a specific cluster's mapping?
  → Fork gbrain-base-v2 (`gbrain schema fork gbrain-base-v2 my-pack`),
    edit mapping_rules in your fork, then target the fork.

约定

输入:

  • 一个位于 gbrain-base(或任何带有 migration_from: gbrain-base-v2 的包)上的 brain。
  • 在 brain 主机上拥有可信的本地 CLI 访问权限:gbrain jobs submit 会为受保护的名称自行授予 PROTECTED 处理程序的启用许可;远程 MCP submit_job 操作则无法做到这一点。
  • 在 186K 页面的 brain 上大约需要 10 分钟的实际耗时。

输出:

  • 页面被重新类型化为规范类型,并保留 frontmatter.legacy_type(每页的回滚信号)。
  • 为概念重定向页面生成 slug_aliases 记录(别名表本身就是解析器,无需改写链接)。
  • 为边形态页面(如 atom-partner-link、symlink 等)生成真实的 links 记录。
  • 成功运行结束时,活动包原子性地切换为 gbrain-base-v2。

副作用:

  • 源页面被软删除,恢复 TTL 为 72 小时(gbrain restore <slug>)。
  • KNOBS_HASH_VERSION 升级(5→6)时会进行一次性缓存失效;会在 cache.ttl_seconds 内自行修复。
  • 搜索/查询中的 --type X 会展开活动包的别名闭包(向后兼容)。

失败模式:

  • 并发提交会被 gbrain-unify 数据库锁拒绝;第二次调用会优雅退出。
  • 兜底重新类型化会排除 page_to_link 和 page_to_alias 源类型(在合并前的 E2E 测试中发现)。
  • 阶段失败会在 active_pack_flipped 之前中止运行;部分状态可通过 op_checkpoint 续跑恢复。

出现故障时

对于任何 gbrain 错误 code、退出码、[AGENT] 块或通知块,请遵循智能体操作协议。针对本技能的具体情况:

  • 第二次 unify 提交因 gbrain-unify 锁被占用而被拒绝("already in progress"):请等待正在运行的任务(gbrain jobs get <id>);不要重新提交。
  • 某阶段在 active_pack_flipped 之前失败:包未发生变化;应从检查点续跑,而不是从头重启。
  • 运行报告了成本信息:重新类型化可能会调用模型,因此在大型 brain 上提交前,请先与用户确认预算。

反模式

请勿:

  • 通过远程 MCP submit_job 操作提交 unify-types。PROTECTED 处理程序要求可信的本地调用方(在 brain 主机上执行 gbrain jobs submit);远程 MCP 拒绝属于有意设置的信任边界。
  • 为跳过你不信任的聚类而编辑 gbrain-base-v2.yaml 中的 mapping_rules。应改为分叉该包(gbrain schema fork),以保证跨 brain 的迁移源保持一致。
  • 在自动驾驶 tick 内运行 unify-types。该检查为 manual_only——自动驾驶刻意不会自动触发它,因为包升级属于一次性的、需经同意的分类体系决策。
  • 在 72 小时恢复窗口之前硬删除已软删除的源页面。如需回滚,请先使用 gbrain restore <slug>。
  • 假设 frontmatter.legacy_type 在每次往返中都会保留。该标记仅在迁移后的近期窗口内是权威的;下游重新导入可能会覆盖它。

输出格式

每个阶段,处理程序会向 stderr 输出:

[unify-types] phase=retype-explicit applied=N skipped=M  cost=USD  ttl=Ns
[unify-types] phase=retype-catch-all applied=N
[unify-types] phase=page-to-link converted=N pages soft-deleted
[unify-types] phase=page-to-alias aliased=N pages soft-deleted
[unify-types] phase=sync residual=N
[unify-types] active_pack flipped from gbrain-base to gbrain-base-v2

最终的完成摘要输出到 stderr:

═══════════════════════════════════════════════════════════
  gbrain-base-v2 migration complete
═══════════════════════════════════════════════════════════
  Before: 94 distinct page types
  After:  15 canonical types
  Retyped:      25,632 pages
  Aliased:       5,521 redirects → slug_aliases table
  Linkified:        65 ghost pages → real link rows
  Soft-deleted:  5,586 pages (restorable for 72h)
═══════════════════════════════════════════════════════════

如需结构化 JSON,gbrain call get_job '{"id": <id>}' 会返回任务记录;其 result 字段包含 UnifyTypesResult 结构,内有 per_phase、pack_identity_after、active_pack_flipped(gbrain jobs get <id> 会直接内联打印相同结果)。

Reference

评论

支持 Markdown