A workspace keeps your databases in one conversation without inviting them to share a toothbrush.
1. Motivation
Without one owner, schema setup happens in a migration script, provider clients live in global variables, the CLI chooses another config, and the MCP server quietly opens a second copy. Each piece works alone while the application loses one coherent identity. AHeavenBase workspace binds one stable id to canonical Entity classes, named Backend instances, field placement, row and query services, fixed metadata entities, requested Extension roots, and agent-facing tools. The owning Context supplies machine configuration, module resolution, and durable workspace registration.
This matters because one logical row may span SQL, vector, search, graph, or file providers, but application code still needs one place to register, write, query, inspect, and explain it.
2. Create or Compatibly Reopen a Durable Workspace
HeavenBase("shop", ...) is idempotent at the durable identity. It creates and registers an absent workspace, or opens the existing compatible definition. It never activates the workspace implicitly.
An explicit preset= or backends= value is a construction assertion. A conflict with the stored construction raises FileExistsError. With neither setting, an existing id reuses its persisted construction instead of reinterpreting today’s defaults.
Use load() when absence should be an error:
HeavenBase.load("shop") requires a registered workspace and raises KeyError on a miss. Name-free load() checks the active selection, then the configured default; it never creates a workspace as a side effect.
3. Bind Isolation to a Context
hb.DEFAULT_CONTEXT is only the convenience owner for unbound calls.
The stable workspace id also derives its configuration layer: shop overlays heavenbase.shop on the base heavenbase config. Reopen a workspace after material configuration changes when already-built resources must observe the new snapshot.
4. Start with a Preset or Explicit Backends
Thedebug preset needs no external services:
main and vec are workspace-local names. Each type resolves a canonical backend_type record through the Context. Ready Backend instances use the same identity contract; after process restart, reconstruction needs compatible live instances or explicit replacement configuration.
5. Register Schema Before Row CRUD
register() establishes the canonical Entity class, resolves placement, ensures physical schema, and publishes MetaSchema rows. Ordinary upsert, set, delete, get, exists, count, ids, and rows operate only on an already-present canonical class. They never create schema state as a hidden side effect.
Every row has a stable object_id. If a row omits it but provides name, HeavenBase derives a deterministic identifier from the Entity schema and that name.
6. Query Through One Logical Surface
hb.Query values. execute() recomputes and returns a detached ResultFrame; use explicit exits such as rows(), scalar(), or a typed dataframe export.
The workspace resolves placement, registered operations, handlers, and provider execution. explain() reports the actual native, adapter, scan, fallback, or unsupported route instead of treating a module tag as proof.
7. Inspect Foundation Entities and Extensions
Catalog and MetaSchema are fixed, non-replaceable workspace foundation entities. Catalog describes concrete objects. MetaSchema describes canonical schemas, fields, placement, active Extensions, and safe Registry-backed metadata.
8. Export a Reconstructive Shell, Not the Data
Workspace manifest version 2 stores oneconstruction envelope, requested optional Extension roots, and user Entity schemas:
preset= or backends= value, but it does not recursively merge partial Backend settings.
9. Use Detached Lifecycle Deliberately
load(). Detached is a lifecycle policy, not a storage promise. It does not imply temporary or isolated data, and cleanup is not automatic.
release() removes a durable workspace facade from its owning Context’s live lookup while preserving Backend data. drop() is the destructive physical-data operation. Retain the correct facade and call these methods explicitly.
10. Know the Coordination Limit
One live workspace serializes its public schema, CRUD, query, refresh, repair, release, and drop operations. Independent routed Backends still do not form a distributed transaction or cross-process serialization boundary. A failed multi-backend write can require explicit audit and convergence. Usews.audit() for Catalog consistency and ws.repair(dry_run=True) before intentional repair. Use Query.explain() before promising provider-native behavior.
Summary
- A workspace owns schema, placement, rows, routing, and attached domain APIs.
- Durable construction, loading, activation, and detached lifecycle are separate decisions.
- Manifests reconstruct the shell; Backends and applications own physical data guarantees.

