Migrate a brain from gbrain-base (or any pack) to gbrain-base-v2's 14-canonical-type taxonomy via gbrain onboard --check + the unify-types Minion handler. Colla
复制下面这句话,粘贴给 Claude Code、Codex、Cursor 等 AI 编程工具,它会读取安装说明并在你确认后完成安装。
请阅读 https://ai.atlankj.com/install/asset/gh-schema-unify-235ab76d7fc9 ,按照其中的说明把「schema-unify」安装到你(当前 AI 工具)中。执行前先告诉我将运行的命令和写入的位置,等我确认。
查看 AI 将读取的安装说明正在读取 GitHub 原文…
内容来自 GitHub 原始文件,由原作者维护。在 GitHub 查看
v0.41.22 ships gbrain-base-v2 — a 15-type DRY/MECE taxonomy (14 canonical + note catch-all) — as the install default for new brains. Existing brains on gbrain-base can opt in via the pack_upgrade_available onboard finding + the unify-types PROTECTED Minion handler.
This skill is the playbook for that migration.
This skill is ABOUT the brain's shape — it can't depend on the brain it's reshaping. No gbrain search lookup first; jump straight to onboard.
gbrain onboard --check and sees pack_upgrade_available or type_proliferation warningsdangling_aliases finding surfaces (post-unify GC)A production gbrain brain accreted 94 distinct pages.type values over years of ingestion: tweet / tweet-thread / tweet-bundle / tweet-single / media/x-tweet/bundle / tweet-stub all coexisting; 5.5K concept-redirect pages; atom-partner-link pages that should be links; civic / framework / insight / memo / anecdote one-offs. The cure: collapse to 15 canonical types (person, company, media, tweet, social-digest, analysis, atom, concept, source, deal, email, slack, writing, project, note) with subtypes/format/origin pushed to frontmatter, alias-rows for redirects, real link-rows for edge-shaped pages, and a catch-all that bins long-tail unknowns to note with frontmatter.legacy_type = <original> for rollback.
Confirm the brain is actually on gbrain-base (not already on v2).
gbrain schema active --json | jq -r '.identity'
Expected: gbrain-base@1.0.0+<sha>. If you see gbrain-base-v2@..., the brain is already on v2 — skip the migration.
Then run onboard to see what would change:
gbrain onboard --check
Look for the pack_upgrade_available finding. If it's ok, there's no successor declared for the active pack — done.
Run the per-cluster narrative:
gbrain onboard --check --explain
This invokes the unify-types handler in dry-run mode and prints:
Review the output. If the proposed changes look wrong, don't proceed — file an issue or write a custom pack with adjusted mapping_rules.
The handler is PROTECTED (manual_only) — autopilot will never auto-fire it. Submit explicitly:
gbrain jobs submit unify-types \
--params '{"target_pack":"gbrain-base-v2","apply":true}'
On PGLite (the install default), or on any setup without a running gbrain jobs work worker or supervisor daemon, add --follow so the job executes inline:
gbrain jobs submit unify-types \
--follow \
--params '{"target_pack":"gbrain-base-v2","apply":true}'
The persistent worker daemon is Postgres-only. Without --follow on PGLite, the job sits queued forever and the migration never runs.
apply defaults to false (dry-run) per the handler contract, so
"apply":true is required here or the job reports success having retyped
nothing and left the active pack unflipped. Omit it to preview.
Watch progress per phase (worker-daemon runs; with --follow the same progress streams inline):
gbrain jobs get <job_id> # one job: status, progress, result
gbrain jobs watch --follow # live dashboard of the whole queue
A job that stays queued here means no worker is running; resubmit with --follow to execute it inline.
On a 186K-page brain expect ~10 minutes. The handler runs:
mapping_rules:)gbrain-unify db-lock (60min TTL)gbrain onboard --check
gbrain schema stats
Expected:
pack_upgrade_available → ok (active pack is now v2)type_proliferation → ok (≤16 distinct typed values)dangling_aliases → ok (slug_aliases all point at active canonicals)gbrain schema stats shows ≤16 distinct typesAnything that used --type article keeps working post-unify if your CLI calls go through the expandTypeFilter helper (it expands article to media+subtype=article automatically). Direct SQL against pages.type needs updating to the canonical types.
Search queries get a small ranking signal: pages reached via slug_aliases (canonicals of one or more aliases) get a 1.05x boost. Visible via gbrain search --explain.
Every retyped page preserves frontmatter.legacy_type = <original>.
Restore types in bulk (Postgres/Supabase deployments only; requires direct DB access):
UPDATE pages SET type = frontmatter->>'legacy_type'
WHERE source_id = 'default' AND frontmatter->>'legacy_type' IS NOT NULL;
On PGLite there is no SQL shell, so use the CLI surface instead: frontmatter.legacy_type persists per page, so individual retypes can be reverted through the normal put_page/CLI surface, and the soft-delete restore and pack-flip revert below work on every engine.
Page-to-alias and page-to-link source pages soft-delete with 72h TTL. Restore within that window:
gbrain restore <slug>
Revert the active pack flip:
gbrain schema use gbrain-base
*unknown*) for the long tail. Pages get retyped to note with legacy_type preserved.[[old-redirect-slug]] keeps working via engine.resolveSlugWithAlias short-circuit.--explain before applying. The trust delta is real.gbrain-unify db-lock serializes them; the second submission rejects with "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.
Inputs:
gbrain-base (or any pack with migration_from: gbrain-base-v2).gbrain jobs submit grants the PROTECTED-handler opt-in itself for protected names; the remote MCP submit_job op cannot.Outputs:
frontmatter.legacy_type preserved (per-page rollback signal).slug_aliases rows for concept-redirect pages (alias table IS the resolver — no link rewrite).links rows for edge-shaped pages (atom-partner-link, symlink, etc.).gbrain-base-v2 atomically at end of successful run.Side effects:
gbrain restore <slug>).cache.ttl_seconds.--type X alias-expands via expandTypeFilter (back-compat).Failure modes:
gbrain-unify db-lock; second call exits gracefully.page_to_link + page_to_alias source types (caught in E2E pre-merge).active_pack_flipped; partial state restorable via op_checkpoint resume.DON'T:
unify-types via the remote MCP submit_job op. PROTECTED handlers require trusted local callers (gbrain jobs submit on the brain host); remote MCP rejection is the intentional trust boundary.mapping_rules in gbrain-base-v2.yaml to skip clusters you don't trust. Fork the pack instead (gbrain schema fork) so the source-of-truth migration stays consistent across brains.unify-types from inside an autopilot tick. The check is manual_only — autopilot deliberately never auto-fires it because pack upgrades are one-time consenting taxonomy decisions.gbrain restore <slug> first if rollback is needed.frontmatter.legacy_type survives every roundtrip. The marker is canonical for the immediate post-migration window; downstream re-imports may overwrite it.Per phase, the handler emits to 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
Final celebration summary to 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)
═══════════════════════════════════════════════════════════
For structured JSON, gbrain call get_job '{"id": <id>}' returns the job row; its result field carries the UnifyTypesResult shape with per_phase, pack_identity_after, active_pack_flipped (gbrain jobs get <id> prints the same result inline).