---
status: ACTIVE
---
# CEO Plan: v0.38 Schema Packs — Bring Your Own Shape

Generated by /plan-ceo-review on 2026-05-19
Branch: garrytan/houston-v1 | Mode: EXPANSION
Repo: garrytan/gbrain

## Definitions (terms used throughout)

- **Primitive** — a named bundle of (default link verbs, default
  frontmatter fields, expert-routing flag, enrichment rubric slot).
  Five built-in: `entity`, `media`, `temporal`, `annotation`,
  `concept`. A pack type extends one primitive by name, inheriting
  its defaults, then optionally overriding specific fields. Not a
  table shape, not a schema in the SQL sense — a behavioral
  template the engine consults at inference and search time.
- **Alias closure** — for read paths, when a pack declares type
  `researcher` aliases base type `person`, queries for `researcher`
  expand the WHERE clause to `type IN ('researcher','person', + any
  other type aliasing person)`. The closure is computed once at
  pack load, cached on the pack object, and inlined into search
  SQL. Aliasing is one-directional (researcher → person; querying
  `person` does NOT surface `researcher` rows unless the inverse is
  declared).
- **Pack resolution chain (7 tiers)** — extends model-config's
  6-tier pattern. Order: (1) per-call `schema_pack` opt, (2)
  `GBRAIN_SCHEMA_PACK` env, (3) per-source `--source <id>` override
  via DB config key `schema_pack:source:<id>`, (4) brain-wide DB
  config key `schema_pack`, (5) `gbrain.yml schema:` section,
  (6) `~/.gbrain/config.json schema_pack`, (7) default `gbrain-base`.
  Tier 3 is the new tier introduced in v0.38; tiers 1, 2, 4-7
  mirror existing patterns.

## Vision

### 10x Check
The plan as accepted ships a self-EXPANDING engine, not just a
self-describing one. The differences from the baseline plan:

- The brain watches what you create and proposes schema refinements
  you didn't think to ask for (`schema suggest`)
- Schema is per-source (ISOLATED reads), so ~/git/brain and
  ~/git/zion-brain hold different mental models in the same engine
  without renames. Cross-source federated reads still see per-source
  packs in isolation — a query joining results across mounts does
  NOT compute a closure across both packs. Federation (closure
  across mounts) is explicitly deferred to v0.39.
- The pack is inspectable: ASCII graph, plain-English explanation,
  consistency lint against actual content
- First unknown-type write asks "Add to pack?" with a primitive
  inference, instead of silently logging
- Schema packs distribute as `.gbrain-schema` tarballs through the
  v0.37 skillpack pipeline; skillpacks rename to `.gbrain-skillpack`
  for symmetry. Community schema packs propagate the same way
  community skillpacks do.

### Platonic Ideal
A new user clones gbrain and types `gbrain init`. Within 30 seconds
gbrain has read their existing markdown anywhere on disk, proposed a
schema matching their organic shape, asked 3-5 yes/no questions to
refine, and the brain is live. They never author YAML unless they
want to. They can publish their pack as a `.gbrain-schema` tarball
for anyone to install and fork.

The 12-month state: `gbrain init` runs `schema detect` automatically,
proposes a primitive structure, and 90% of users never see the
manifest format. The 10% who want to customize see a clean YAML they
can edit. Community packs cover the long tail of domains.

## Scope Decisions

| # | Proposal | Effort | Decision | Reasoning |
|---|----------|--------|----------|-----------|
| 0C-bis | Approach C (Full Cathedral) | ~4 weeks | ACCEPTED | User explicitly chose the most ambitious of three approaches; ecosystem + engine in one ship |
| D2 | Per-source schema packs | ~1 week | ACCEPTED | User owns two brains today; v0.34.1.0 source-isolation makes the seam architecturally clean |
| D3 | `gbrain schema suggest` (LLM-powered) | ~3-5 days | ACCEPTED | Closes the gap from "what exists" to "what your brain implies"; bounded cost via sampling |
| D4 | `schema graph` + `lint` + `explain` | ~2 days | ACCEPTED | Schema becomes legible and self-documenting; tiny effort, large UX delta |
| D5 | Auto-prompt on first unknown type | ~1-2 days | ACCEPTED | TTY-gated + per-type silenceable; turns lenient-mode from fallback to feature |
| D6-orig | `fork-from <brain-path>` (live-brain) | ~3-5 days | REJECTED | Privacy hazard (read access to whole repo); unclear value vs published tarballs |
| D6-reframed | Skillpack tarball reuse + extension expansion | ~3-5 days | ACCEPTED | Schema packs ship as `.gbrain-schema`; skillpacks gain `.gbrain-skillpack` extension alongside existing `.tgz`; both ride v0.37 pipeline parameterized on manifest discriminator. Extension is the install-time type detector — lets validation route to the right manifest validator before extraction. |

Total budget: **revised 9-11 weeks** (vs ~6.5-7 initial estimate;
spec review surfaced LLM prompt-tuning loops for `schema suggest`,
primitive-inference heuristics for auto-prompt, 7-tier × federated-
read interaction edges, full rename-migration surface, and 400-600
test cases at v0.36/v0.37 scope precedent). If budget pressure
emerges, the safest cuts in order are: D5 auto-prompt (~2 days),
D4 inspect triad (~2 days), reduce examples 7→3 (~3 days), defer
suggest LLM polish to v0.38.1 (~1 week).

## Accepted Scope (added to this plan)

- **Engine layer:** gbrain-base universal starter pack; 5 composable
  primitives (entity, media, temporal, annotation, concept); alias
  closure for read paths; lenient-by-default with audit for write
  paths; strict mode opt-in.
- **Detect layer:** `gbrain schema detect` SQL-driven heuristic
  clustering proposing a pack manifest matching brain shape.
- **Suggest layer:** `gbrain schema suggest` LLM-powered refinement
  via gateway.chat() over a bounded sample.
- **Inspect layer:** `gbrain schema graph` (ASCII viz),
  `gbrain schema lint` (consistency check), `gbrain schema explain
  <type>` (plain English).
- **Author layer:** `gbrain schema init/use/fork/edit/validate/
  diff/review-candidates` CLI.
- **Source layer:** per-source schema-pack resolution; pack
  resolution gets a 7th tier (per-source override before per-brain);
  `--source <id>` flag on every relevant command.
- **Auto-prompt layer:** TTY-gated interrupt on first unknown-type
  `put_page` with primitive inference; per-type "always silent"
  escape hatch.
- **Distribution layer:** `.gbrain-schema` tarball format; rename
  skillpacks to `.gbrain-skillpack`; v0.37 skillpack pipeline
  parameterized on artifact type (manifest discriminator drives
  type-specific validation); both extensions accepted on install
  for back-compat.
- **Examples:** 7 example packs in-tree (minimal, person-first,
  media-archive, temporal-archive, research-notebook, founder-ops,
  personal-archive) explicitly framed as sketches not products.
- **gbrain-base:** byte-for-byte reproduces today's hardcoded
  behavior so existing brains see zero change after upgrade.
- **Migrations:** v76 drops `takes.kind` CHECK constraint;
  validation moves to runtime against active pack's declared kinds.
- **Doctor checks:** schema_pack_active, schema_pack_consistency,
  per-source pack drift.
- **Engine refactor coverage:** the v0.38 plan parameterizes EVERY
  hardcoded type-coupling site listed in the original exploration,
  not just `takes.kind`. Concretely: `inferType` path-prefix table,
  `inferLinkType` regex bank, `FRONTMATTER_FIELD_OVERRIDES` table,
  `find_experts` SQL (`type IN (…)`), `whoknows` `DEFAULT_TYPES`,
  `enrichment-service` person/company restriction,
  `completeness.ts` rubric map, dream-cycle entity-type prompts.
  gbrain-base reproduces today's values for each.
- **Cache + rollback story:**
  - `query_cache.knobs_hash` (v0.32.3 column) folds `schema_pack`
    name + version into the hash so a cache row written under
    `vc` is unreachable when `research-state` is active. Cross-
    pack contamination structurally impossible.
  - `eval_candidates` rows (v0.25.0) gain a `schema_pack` column
    so `gbrain eval replay` reproduces the same retrieval space.
    Migration v77 adds the column NULL-tolerant; pre-v0.38 rows
    fall back to active pack during replay.
  - HNSW indexes are pack-agnostic (vector columns don't change
    shape across packs); no reindex needed on pack switch.
  - Rollback: every `gbrain schema use` operation writes the
    previous pack name to `~/.gbrain/schema-pack-history.jsonl`
    so `gbrain schema use --previous` is one keystroke. Strict-
    mode failures on switch surface the offending pages with
    paste-ready "rename type to X" hints before any data
    mutation runs. Soft-deletes from autopilot purge are NOT
    triggered by pack changes.
- **Test budget:** ~400-600 cases across unit + e2e per the
  v0.36/v0.37 precedent. Specifically: ~150 cases for engine layer
  + alias closure, ~50 for detect heuristic accuracy, ~50 for
  suggest LLM prompts (hermetic via stubbed gateway), ~30 for per-
  source resolution × 7-tier matrix, ~40 for auto-prompt UX
  states, ~30 for inspect triad output stability, ~30 for tarball
  type-detection + parameterized install, ~50 for migration v76 +
  v77 + bootstrap parity, ~50 for examples × byte-for-byte
  gbrain-base equivalence regression. **gbrain-base byte-for-byte
  parity is a CI gate**, not a hope — pinned by
  `test/regressions/gbrain-base-equivalence.test.ts` asserting the
  pre-v0.38 hardcoded behavior reproduces from the pack-driven
  paths on a fixture brain.

## Deferred to TODOS.md (v0.39+)

- Live-brain `fork-from <brain-path>` (rejected for privacy; revisit
  if a sandboxed schema-only extraction path is designed)
- Per-source pack FEDERATION across mounts (a query crossing
  multiple sources can use closure over each source's schema; right
  now per-source is isolated reads only)
- Schema versioning + semver compatibility checks between pack
  versions
- Skillpack ↔ schema-pack cross-reference (a skillpack can declare
  "I work best with these primitives present in your pack")
- Live schema migration helpers (when you add a type, auto-suggest
  backfill of existing pages)
- Schema diff in PR review (rendering pack changes as human-readable
  diffs for community pack PRs)

## Reviewer Concerns (from spec review loop, partially addressed)

- Quality score on first pass: 6.5/10. Issues addressed in this
  revision: definitions block (primitive, alias closure, 7-tier
  resolution chain), per-source isolation vs federation contradiction
  clarified, skillpack extension framing changed from rename to
  expansion, full hardcoded-site coverage enumerated, cache +
  rollback story added, test budget enumerated, budget revised to
  9-11 weeks honestly.
- Issues NOT fully addressed, surfaced for the 11-section review:
  - `schema suggest` LLM prompt-tuning iteration budget remains a
    range estimate, not a measured number. The 11-section review
    should pin a specific eval fixture set (size + diversity) and
    a target accuracy threshold before code lands.
  - 7-tier resolution × v0.34.1 federated_read OAuth scoping has
    edge cases at the intersection that the 11-section review must
    enumerate (specifically: an OAuth client with read scope across
    federated sources but no source-specific pack override — which
    pack drives the alias closure for cross-source queries?).
  - The 7→3 example pack reduction is a real cut consideration. The
    11-section review should decide whether 7 examples is the right
    number or whether 3 + community-derived is more honest.

## Cathedral risks worth surfacing in 11-section review

1. The 7-week budget vs 4-week original ask. If pressure emerges,
   D5 (auto-prompt) and D4 (inspect triad) are the safest cuts.
2. v0.37 skillpack registry currently has zero published packs.
   The `.gbrain-schema` rename and tarball reuse doubles down on a
   distribution layer with no usage signal.
3. Per-source pack resolution adds a 7th tier to the resolution
   chain. The model-config 6-tier pattern is already cognitively
   dense; tier 7 is an inflection point.
4. `schema suggest` introduces ongoing LLM cost per invocation.
   Bounded by sampling, but sets a precedent for "gbrain commands
   that cost money."
5. Auto-prompt UX is novel. TTY gate + per-type silencing helps,
   but bulk-import flows could hit unexpected interruption patterns.
