Pack-Upgrade Mechanism (v0.41.22)
How gbrain-base@1.x → gbrain-base-v2@1.0.0 (and any future pack
succession) wires through the onboard cathedral.
The contract
A schema pack manifest can declare amigration_from field:
mapping_rules: block is
populated, the pack registers itself as the successor to
(parent_pack, version_range). Any brain whose active pack matches
that tuple lights up the pack_upgrade_available onboard check.
End-to-end flow
Version-range semantics
migration_from.version accepts three shapes:
* is accepted as an alias for x.
Implementation: _versionRangeMatches(version, range) in
src/core/schema-pack/load-active.ts. Pinned by
test/schema-pack-find-pack-successors.test.ts.
findPackSuccessors discovery
WalksBUNDLED_PACK_NAMES (currently gbrain-base,
modusbrain-recommended, modusbrain-creator, modusbrain-investor,
modusbrain-engineer, modusbrain-everything, gbrain-base-v2). For each
candidate ≠ the active pack name, loads the manifest via
loadActivePack({ perCall: candidate }), checks
migration_from.pack === activeName && _versionRangeMatches(activeVer, migration_from.version). Returns matching packs sorted by version
descending.
v0.41.22 covers bundled packs only. v0.43+ TODO: enumerate user-installed
packs at ~/.modusbrain/schema-packs/*/pack.yaml (defer to v0.43 since the
filesystem-scan cost needs the cache invalidation strategy from
registry.ts).
The manual_only apply policy
The shipped onboard contract has 3 apply_policy values:pack_upgrade_available emits a RemediationStep with protected: true + job: 'unify-types'. toOnboardRecommendation in
src/core/onboard/render.ts maps this to manual_only via the
MANUAL_ONLY_PROTECTED_JOBS allowlist (which also contains
extract-takes-from-pages per v0.41.18 A12+A24).
Rationale: pack upgrades change the brain’s taxonomy. Taxonomy is a
user judgment call — not autopilot’s call. Even with --auto-with- prompt, prompting the user to confirm a pack upgrade mid-tick is the
wrong UX (the user came to fix orphans, not to be interrupted with
“hey want to migrate your taxonomy?”). Explicit submission is the
right boundary.
Authoring a successor pack
Minimal example for an academic-research brain that adds aresearcher canonical:
~/.modusbrain/schema-packs/modusbrain-academic-v1/pack.yaml.
Discoverable via modusbrain schema list. Activatable via
modusbrain schema use modusbrain-academic-v1. Once active, the
pack_upgrade_available check fires for any brain on
gbrain-base-v2@1.x and surfaces a unify-types RemediationStep
targeting your pack.
Lock + concurrency
modusbrain-unify is a dedicated modusbrain_cycle_locks row name (60min
TTL). The handler acquires it before any apply phase + releases in
finally. Two simultaneous modusbrain jobs submit unify-types
invocations: second one fails fast at lock acquisition with a clear
error. Same pattern as modusbrain-sync (v0.22.13 PR #490).
Audit trail
Every unify run writes to~/.modusbrain/audit/schema-unify-YYYY-Www.jsonl
(ISO-week rotation, mirrors existing audit channels). Records: pack
identities (before + after), per-phase counts (would_apply + applied),
warnings, completion timestamp. Privacy: page slugs are NOT logged in
bulk (only the per-rule sample_slugs[≤10]); for forensic debugging
add MODUSBRAIN_AUDIT_FULL=1 (v0.43+ TODO; not yet wired).
What’s NOT yet supported
- Subprocess sandbox for the publish-gate (v0.43+ TODO)
- Per-source pack-upgrade (the handler accepts
sourceIdbutfindPackSuccessorsdoesn’t yet pass it through) - Cross-brain federated mounts that disagree on canonical packs
- Automatic rollback (today: manual SQL or
modusbrain pages restore) - LLM-assisted mapping_rules codegen from production data (
modusbrain schema detect-mappings; deferred to v0.43+)
Reference
- Pack file:
src/core/schema-pack/base/gbrain-base-v2.yaml - Manifest extension:
src/core/schema-pack/manifest-v1.ts - Successor walker:
src/core/schema-pack/load-active.ts:findPackSuccessors - Onboard check:
src/core/onboard/checks.ts:checkPackUpgradeAvailable - Render allowlist:
src/core/onboard/render.ts:MANUAL_ONLY_PROTECTED_JOBS - Handler:
src/core/schema-pack/unify-types-handler.ts - Migration:
src/core/migrate.ts:105(slug_aliases table) - Type taxonomy doc:
docs/architecture/type-taxonomy.md - Skill:
skills/schema-unify/SKILL.md