skills/schema-unify/SKILL.md
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. Collapses 94 noisy types to 15 canonical with subtypes, alias rows, and link rows. Triggers when an agent notices pack_upgrade_available, type_proliferation, or asks "what is the canonical taxonomy / how do I clean up my page types".
npx skillsauth add garrytan/gbrain schema-unifyInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
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: [email protected]+<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 per D17) — autopilot will never auto-fire it. Submit explicitly:
gbrain jobs submit unify-types \
--allow-protected \
--params '{"target_pack":"gbrain-base-v2"}'
Watch progress per phase:
gbrain jobs follow <job_id>
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> per D8. Restore types via:
UPDATE pages SET type = frontmatter->>'legacy_type'
WHERE source_id = 'default' AND frontmatter->>'legacy_type' IS NOT NULL;
Page-to-alias and page-to-link source pages soft-delete with 72h TTL. Restore within that window:
gbrain pages 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).--allow-protected).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 pages restore <slug>).cache.ttl_seconds.--type X alias-expands via expandTypeFilter (D14 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 directly via the MCP submit_job op without --allow-protected. PROTECTED handlers require trusted local callers; 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 per D17 — autopilot deliberately never auto-fires it because pack upgrades are one-time consenting taxonomy decisions.gbrain pages 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)
═══════════════════════════════════════════════════════════
JSON output (gbrain jobs follow <id> --json) returns the structured UnifyTypesResult shape with per_phase, pack_identity_after, active_pack_flipped.
~/.claude/plans/system-instruction-you-are-working-transient-elephant.mddocs/architecture/type-taxonomy.mddocs/architecture/pack-upgrade-mechanism.mdtools
--- name: query-helper triggers: - find a page tools: - search - query writes_pages: false --- # query-helper This skill helps you query the brain. The first prose line becomes the description when no `description:` frontmatter is present.
testing
# broken This SKILL.md has no YAML frontmatter fence. It must still be listed (with the directory name as its name and empty triggers), never throw.
documentation
Read, enrich, and write brain pages with source attribution.
testing
Schedule management with staggering, quiet hours, and wake-up override. Validates schedules, prevents collisions, and gates delivery during quiet hours.