Kernel & Runtime¶
The Kernel is the mediator that connects the five ports and the hook
registry. Runtime is a thin convenience wrapper that owns a kernel plus an
event loop for host code that wants a batteries-included entry point.
Kernel¶
dna.kernel.Kernel ¶
Mediator that orchestrates 5 ports + hooks to produce ManifestInstance.
Create a Kernel.
tenant binds this kernel to a tenant — all subsequent
write/read ops route to that tenant's storage. Use
with_tenant(other) for per-call cross-tenant operations
(Stripe Connect pattern). Pass None (default) for the
unbound kernel — only GLOBAL kinds may be written; TENANTED
kinds raise TenantRequired.
active_event_bus
property
¶
The KernelEventBus registered via event_bus(), or None.
active_source
property
¶
The SourcePort registered via source() / storage(), or None.
Read-only accessor. The setter method is source(src). Named
active_source to avoid collision between a method and a property
of the same name.
source_type
property
¶
Source adapter class name (empty string when no source wired) — safe for capability checks. Thin facade over the SourceFacade collaborator (s-kernel-decomp-f5-satellites).
active_writers
property
¶
WriterPorts registered via writer(w). Read-only view — mutating the returned tuple has no effect on the Kernel's internal list.
active_readers
property
¶
ReaderPorts registered via reader(r). Read-only view — mirror of
active_writers (s-dna-rw-roundtrip-suite: the round-trip
conformance kit enumerates registered pairs through this surface).
embedding_dims
property
¶
Output dimensionality of the active embedding provider.
embedding_model_id
property
¶
Identity of the active embedding space (vectors from different
model_ids are NOT comparable).
register_main_loop ¶
Register the long-lived event loop that owns this kernel's source pool. After registration, sync API calls from worker threads dispatch back to this loop via run_coroutine_threadsafe instead of spawning a new loop. Idempotent.
with_tenant ¶
Return a shallow-copy Kernel bound to tenant.
Original Kernel is unchanged — call sites can hand off the
copy to per-request handlers without mutating shared state
(Sanity client.withConfig({dataset: X}) pattern).
Pass tenant=None to obtain an unbound kernel (writes
only allowed for GLOBAL kinds).
kind_port_for ¶
Public lookup for a registered KindPort by kind name.
Use from tooling that needs to consult Kind metadata
(is_runtime_artifact, scope, storage, ...) without
reaching into Kernel internals. Returns None if the kind
isn't registered. Pass api_version= for exact resolution when
the kind name is ambiguous (i-195 — e.g. the Reference pair).
kind_plane ¶
Two-planes (spec 2026-06-09): the declared plane of a Kind by
name — 'record' or 'composition'. Unknown Kinds default to
'composition' (fail-safe: behaves exactly as today). Pass
api_version= for exact resolution on ambiguous names (i-195).
embeddable_kinds ¶
F3 D4 (spec 2026-06-10-kinds-descriptor-f3): kind names whose
port declares embed_fields — via descriptor embed: or a
class-level embed_fields (the KindBase parity hook for
not-yet-migrated classes). The embeddings sidecar derives its
eligible set from this instead of a hardcoded frozenset
(dna_shared.embeddings.embeddable_kinds unions it with the
shrinking legacy fallback).
use ¶
Register middleware on a hook point (e.g., 'pre_build_prompt').
on ¶
Register event subscriber (e.g., 'post_save').
on_veto ¶
Register a veto listener (e.g., 'pre_save') — raising vetoes the
operation. See HookRegistry.on_veto for priority/key semantics.
source ¶
Register THE SourcePort — where manifest documents live (filesystem, SQLite, Postgres...). One per kernel; registering again replaces it.
This is a boot gate, not a plain setter: the port is structurally
validated here (validate_source_port) so a malformed source
fails loudly at registration with the missing members named,
instead of deep inside the first load_all. Sources that are
KernelAttachable are auto-attached (fail-soft) so direct
kernel.source(s) callers get the same reader wiring as
Kernel.auto(source=s).
on_write ¶
Register a callback invoked after each successful write_document or delete_document. Callback signature: callback(scope: str, kind: str, name: str, op: Literal["write", "delete"]) -> None
Used by long-lived holders (e.g., MIHolder) to invalidate their own caches when Temporal workers or other in-process writers mutate docs.
Observers must not raise — exceptions are swallowed to avoid breaking the write path.
DEPRECATED in Phase 15.1 PR4 (planned): superseded by
register_holder() + cross-process KernelEventBus. Remains
available through PR3 for back-compat with existing wiring.
register_holder ¶
Register a long-lived MIHolder so cross-process invalidation
events from KernelEventBus can reach it.
On kernel.invalidate(scope=..., ...), every registered holder
whose holder.scope matches gets holder.reload() called.
Idempotent: re-registering the same holder is a no-op.
unregister_holder ¶
Unregister a holder. Idempotent — unregistering an unknown holder is silently ignored.
event_bus ¶
Register a KernelEventBus implementation. The harness/worker
bootstrap calls await bus.start(kernel) after registration.
Registering a bus is a declarative step; it does NOT auto-start the bus (start needs an active event loop). Callers control lifecycle. Replacing a previously registered bus replaces the reference but does NOT stop the previous bus — callers manage teardown explicitly.
batch_writes ¶
Suppress per-write reload + observer fan-out for the duration of the block. On exit, fires ONE consolidated invalidation per touched scope.
Solves the architectural problem where N sequential writes each triggered a full scope reload (load_all of hundreds of docs + bundle entries). Pre-2026-05-11 a 22-Story backfill cost 22 reloads × ~10s each = ~4min. With this context manager, same backfill = 1 reload at exit = ~10s.
Usage: with kernel.batch_writes(): kernel.write_document(scope, k, n, raw1) kernel.write_document(scope, k, n, raw2) ... # → exit fires one invalidate per touched scope
Reentrant: nested batch_writes() blocks coalesce — only
the outermost block's exit fires the consolidated invalidation.
Caveats: - Reads INSIDE the block see stale MI (no reload between writes). For backfill loops that don't re-read what they just wrote, this is fine. For workflows that read-modify-write, structure each pair OUTSIDE the block (or accept the staleness). - Cross-process invalidation (EventBus → other harness instance) still fires per-write through the outbox; only the LOCAL holder reload + observer fan-out is suppressed.
Delegates to self._invctl (s-kernel-decompose-god-object). Returns
the controller's context manager (state stays on the kernel).
invalidate ¶
Invalidate all in-process caches for a (scope, tenant) tuple in response to a write/delete event from the EventBus.
Idempotent — calling for the same event multiple times is safe; the EventBus replay logic relies on this.
Phase 15.1 contract:
1. Drop _base_instance_cache[scope] if present.
2. For each registered holder with matching scope, call
holder.reload().
3. Skip if kind == "Evidence" (preserves the audit-churn-
avoidance rule from the legacy _reload_on_write; centralized
here so future authors don't need to remember it on each
subscription site).
Note: tenant is currently informational. Phase 15.2 (MIHolder immutability + tenant-resolved view caching) consumes this so a tenant-specific overlay invalidation can drop only the matching resolved view instead of the whole holder.
batch_writes(): when called from inside a batch_writes()
block (depth > 0), this records the event but skips the
expensive reload + observer fan-out. The outermost block's
exit drains the pending list with one consolidated invalidate
per scope.
Delegates to self._invctl (s-kernel-decompose-god-object).
list_scopes_async
async
¶
Proxy to source.list_scopes() — normalises sync (FS) vs async
(SQLite/Postgres) adapters. Thin facade over the SourceFacade
collaborator (s-kernel-decomp-f5-satellites).
source_metadata ¶
Read-only whitelisted snapshot of source adapter metadata (type / dsn / schema / base_dir; private state stays in the adapter). Thin facade over the SourceFacade collaborator (s-kernel-decomp-f5-satellites).
preview_document
async
¶
Pure preview — returns target, serialized files, exists_already.
Does NOT touch disk. exists_already is a UI hint so callers
can render "create" vs "overwrite" affordances.
write_document
async
¶
write_document(
scope: str,
kind: str,
name: str,
raw: dict,
author: str | None = None,
skip_hooks: bool = False,
*,
tenant: str | None = None,
layer: tuple[str, str] | None = None,
invalidate_mode: str = "scope",
write_class: str = "substantive"
) -> str | None
Persist a document through the registered WritableSourcePort.
Public facade (Fase 2, s-kernel-decomp-f2-writepipeline): this method
owns the guardrails — invalidate_mode validation, the
_REMOVED_KINDS block, the record-plane scope→doc demotion
(two-planes F1, resolved from the doc's own apiVersion — i-195), and the
OTel kernel.write_document span. The FAT execution (tenant resolve,
capability-gated adapter kwargs, layer-policy check, the pre_save
veto gate, persist, and the ordered invalidation fan-out) lives in
WritePipeline.write — see its docstring for the full write contract
(tenant/layer semantics, the three invalidate tiers, the always-on
observer fan-out).
Returns the adapter version id (or None if the adapter is version-less).
Emits post_save on success unless skip_hooks is True.
Raises: NotWritableError — no / read-only source. TenantRequired — TENANTED kind without a tenant. TenantNotAllowed — GLOBAL kind with a tenant. InvalidTenantSlug — tenant has invalid characters or is reserved. LayerPolicyViolationError — declared policy forbids the write. ValueError — invalidate_mode not in {scope, doc, none}. KindRetiredError — Kind is in _REMOVED_KINDS (writes blocked).
delete_document
async
¶
delete_document(
scope: str,
kind: str,
name: str,
author: str | None = None,
skip_hooks: bool = False,
*,
tenant: str | None = None,
layer: tuple[str, str] | None = None,
invalidate_mode: str = "scope",
api_version: str | None = None
) -> None
Delete a document through the registered WritableSourcePort.
Tenant resolution mirrors write_document. See its docstring
for the full contract — invalidate_mode also follows the same
semantics (scope | doc | none, default scope).
cache ¶
Register THE CachePort — where resolved external dependencies
are installed (e.g. FilesystemCache under .dna/cache/).
One per kernel; dependency resolution writes through it and
instance loading reads installed items back.
resolver ¶
Register a ResolverPort for a URI scheme ("local",
"github", "http"...) — how external dependencies declared
in a Genome are fetched. One resolver per scheme; registering the
same scheme again replaces the previous resolver.
reader ¶
Register a ReaderPort — a bundle-format detector/parser (SKILL.md, SOUL.md, AGENTS.md...). Readers are tried in registration order during scans.
H1 conformance gate: the object must satisfy the
runtime-checkable ReaderPort Protocol, so a typo'd
detect/read fails here (ReaderRegistrationError) instead of
in production scans. Re-registering the same class is an
idempotent no-op.
writer ¶
Register a WriterPort — the serialize/write half of a bundle
format, mirror of reader().
Same H1 conformance gate: raises WriterRegistrationError
unless the object satisfies the WriterPort Protocol
(can_write/write/serialize — serialize is part of the
contract since s-dna-rw-roundtrip-suite). Re-registering the same
class is an idempotent no-op.
kind ¶
Register a KindPort. Thin facade over the H1 validation funnel (Protocol / dup-key / dup-alias / BUNDLE-marker / plane-lint / i-195 name-collision + alias generation), which lives in the KindRegistry collaborator (s-kernel-decomp-f3-kindregistry).
kind_from_descriptor ¶
Register a BUILTIN Kind from a kinds/*.kind.yaml descriptor
(KindDefinition package data). Thin facade over the KindRegistry funnel
(s-kernel-decomp-f3-kindregistry); returns the registered port.
get_tool ¶
Return a tool definition by name, or None if unknown.
get_tools ¶
get_tools(
*,
group: str | None = None,
groups: list[str] | set[str] | None = None
) -> list[ToolDefinition]
Return registered tool definitions, optionally filtered by group(s).
Delegates to self._toolreg (s-kernel-decompose-god-object).
list_tool_groups ¶
Reverse-build {group: [tool_names...]} from the registry.
describe_kind ¶
Return a summary dict for a registered kind, including resolved docs.
Delegates to self._kindreg.
composition_profile ¶
Register a composition profile that declares how an orchestrator kind connects to other kinds.
resolve_dep_filter_target ¶
Canonical dep_filter target resolution — alias contract +
deprecated legacy kind= shim. Delegates to self._kindreg
(s-unify-composition-subsystems; TS twin:
Kernel.resolveDepFilterTarget).
validate_dep_filters ¶
s-alias-generated-not-typed — every dep_filter target of an
EXTENSION-registered Kind must resolve to a registered alias. Thin
facade over the KindRegistry funnel (s-kernel-decomp-f3-kindregistry);
raises KindRegistrationError on an unknown/legacy extension target,
warns for per-scope declarative ports. Called at the end of
Kernel.auto(); harness boots hit it too.
load ¶
Load an Extension — the way Kinds, readers, writers and tools
enter the kernel (Kernel.auto() calls this for every
entry-point-discovered extension).
Validates the WHOLE Extension contract fail-loud before calling
ext.register(self) (s-dna-extension-host-contract): a callable
register() plus non-empty name and version — a blank
name used to be accepted silently and resurface later as None
alias owners. During register() the extension's
alias_owner/name is the owner context for generated Kind
aliases (s-alias-generated-not-typed). Registration-validation
errors (duplicate Kind, malformed reader/writer) always propagate
— they are configuration problems the operator must fix; other
runtime errors route to the extension_error hook when one is
subscribed, and propagate otherwise.
list_templates ¶
Aggregate templates() from every loaded extension.
The templates() method is feature-tested via hasattr so
extensions that predate Phase 0 (and don't declare the method)
still work. A misbehaving extension that raises inside its
templates() is logged as a warning but never breaks discovery
for the other extensions.
scaffold ¶
Materialize a template by id into target_root.
Raises KeyError if no loaded extension advertises a template
with the given id. on_conflict is passed through to
:func:dna.kernel.templates.materialize.
container_for_kind ¶
Return the storage container directory for a kind, or None. Delegates
to self._kindreg.
storage_for_kind ¶
Return the StorageDescriptor for a kind, or None. Delegates to
self._kindreg.
fetch_bundle_entry ¶
fetch_bundle_entry(
scope: str,
kind: str,
name: str,
entry: str,
*,
tenant: str | None = None
) -> bytes
Phase 14w — fetch a binary entry from a bundle through the source adapter (port-respecting; works on filesystem today, SQLite/Postgres when those adapters land their impls).
Use case: tools (and the harness REST surface) reading large
artifacts that the kernel did NOT inline into doc.spec — most
notably the graph.json payload of a GraphifyArtifact
bundle (Phase 14w). Resolves kind → container via the
registered KindPort's StorageDescriptor and delegates the read
to source.fetch_bundle_entry(...).
Honors tenant overlay routing: when tenant is passed and
the adapter supports it, the tenant copy is preferred over
the base layer.
Raises:
- ValueError if the kind is not registered.
- NotImplementedError if the source adapter doesn't
implement bundle entry fetch (acceptable until SQL adapters
ship the method).
- FileNotFoundError if the bundle or entry is absent.
Delegates to self._bundleio (s-kernel-decompose-god-object).
fetch_bundle_entry_async
async
¶
fetch_bundle_entry_async(
scope: str,
kind: str,
name: str,
entry: str,
*,
tenant: str | None = None
) -> bytes
Async variant of fetch_bundle_entry. Delegates to
self._bundleio (s-kernel-decompose-god-object).
write_bundle_entry_async
async
¶
write_bundle_entry_async(
scope: str,
kind: str,
name: str,
entry: str,
content: bytes | str,
*,
tenant: str | None = None
) -> None
Persist a single bundle entry payload via the active source.
Use this instead of touching kernel._source + _pool
directly. Source-agnostic: dispatches to whichever adapter is
active (FS / SQLite / Postgres), so the caller doesn't need
to know the backing store.
The bundle entry write happens AFTER the parent doc exists
(caller must have done write_document first). The doc
owns the tenant identity — passing the same tenant here
keeps the bundle row's tenant column aligned with the
dna_documents row, so subsequent delete_document
sees and cleans both atomically.
Bug-of-record: 2026-05-21 — multiple tools were doing
INSERT INTO dna_bundle_entries with hardcoded
tenant='' while the doc index had the real tenant. The
delete couldn't find the bundle row (tenant mismatch) and
bytes leaked. This API closes that gap.
Raises:
- ValueError if the kind is unknown or has no bundle
container.
- NotImplementedError if the source adapter doesn't
declare BundleEntryWritable.
Delegates to self._bundleio (s-kernel-decompose-god-object).
digest_manifest
async
¶
digest_manifest(
scope: str,
*,
tenant: str | None = None,
include: "Callable[[dict], bool] | None" = None,
source: "Any | None" = None
) -> "dict[tuple[str, str], str]"
s-sync-s2 — content map of a scope: {(kind, name): digest}.
Each digest is the Kind-aware canonical_digest (s-sync-s1) of the
doc's authored identity, combined with a Merkle hash of its non-marker
bundle entries (so binary assets — fonts, images — are covered too).
Source-independent by construction: the SAME scope in two sources (FS
git ↔ Postgres runtime) yields IDENTICAL manifests when in sync, so a
diff is a set-diff of two manifests (no content transfer).
include(raw) -> bool optionally filters docs (s-sync-s4 passes an
authored-vs-generated predicate). Default: every local doc of the scope.
source overrides the source read from (default: the registered one)
— the kernel's Kinds drive the digest, so a manifest can be built for
ANY source with the current Kind set (s-sync-s4 diffs two sources).
s-kernel-decompose-god-object: delegates to self._sync (SourceSync).
diff_manifests
staticmethod
¶
diff_manifests(
a: "dict[tuple[str, str], str]",
b: "dict[tuple[str, str], str]",
) -> "dict[str, list[tuple[str, str]]]"
s-sync-s4 — set-diff two digest manifests. Pure + O(n). Delegates to
SourceSync.diff_manifests (s-kernel-decompose-god-object).
push_scope
async
¶
push_scope(
scope: str,
to_source: "Any",
*,
tenant: str | None = None,
include: "Callable[[dict], bool] | None" = None,
dry_run: bool = False,
prune: bool = False
) -> "dict[str, list]"
s-sync-s5 — reconcile to_source to match THIS kernel's source
(the source-of-truth, e.g. FS git) for scope.
Computes the minimal diff (s-sync-s4) and applies it: each added/changed
doc is read from the current source (resolved doc + its bundle entries)
and written to to_source via save_document — so the s-sync-s3
atomic net persists doc + bundle entries together. prune deletes docs
that exist only in to_source. include (e.g. authored-only)
narrows the set. dry_run returns the diff without writing.
Returns {added, changed, removed, applied} where applied lists
("write"|"delete", kind, name). Idempotent: a second push finds an
empty diff and applies nothing.
s-kernel-decompose-god-object: delegates to self._sync (SourceSync).
kind_by_container ¶
Return the kind name whose StorageDescriptor.container matches.
Delegates to self._kindreg (None for empty/unregistered).
serialize_document ¶
Serialize a document to files without writing. Delegates to
self._bundleio (s-kernel-decompose-god-object).
build ¶
build(
raw_docs: list[dict],
scope: str,
layers: dict[str, str] | None = None,
layer_docs: list[dict] | None = None,
dep_docs: list[dict] | None = None,
resolve_errors: list[str] | None = None,
*,
skip_async_rescan: bool = False
) -> "ManifestInstance"
Build ManifestInstance from pre-loaded data. Pure computation, no I/O.
For async contexts (server), the caller loads docs via await and passes them here. For sync contexts (CLI), use instance() which handles the async bridging.
skip_async_rescan (set by instance_async when it will run the
rescan post-build): suppress the sync rescan path. Delegates to
self._builder (s-kernel-decompose-god-object).
list_documents
async
¶
list_documents(
scope: str,
*,
kind: str | None = None,
tenant: str | None = None
) -> list[tuple[str, str]]
Lista (kind, name) de docs no scope. Filtrável por kind.
Não constrói ManifestInstance. Custo ~10ms PG / ~5ms SQLite / ~30ms FS (este último cai no fallback load_all).
Cache: per (scope, kind, tenant) com TTL 30s. Invalidado pelo kernel.write_document via _invalidate_granular_cache. Single- flight via lock — N requests concorrentes na mesma key compartilham a fetch.
get_document
async
¶
get_document(
scope: str,
kind: str,
name: str,
*,
tenant: str | None = None
) -> dict[str, Any] | None
Carrega UM doc por (scope, kind, name). Retorna raw dict ou None.
Delegado ao self._query (s-kernel-decompose-god-object). Cache
bounded 2000/TTL 60s + V1 _INHERITABLE_KINDS parent fallback vivem
lá; a API pública (Studio reads, agent routes, deps) é intacta.
resolve_document
async
¶
Resolve a doc through the composition chain — Phase 17 primitive.
Returns ResolvedDocument with merged doc + full provenance.
Bootstrap Kinds (Genome, LayerPolicy, KindDefinition) bypass inheritance entirely — read local-only, single-layer provenance.
For all other Kinds:
1. Look up composition rule for kind in scope's LayerPolicy.
2. Determine resolution chain (walking parent_scope when
scope_inheritance=enabled; just [(scope, tenant),
(scope, None)] otherwise).
3. For each chain layer, query source via cache.
4. Apply merge strategy (override_full or field_level).
5. Build ResolvedDocument with provenance + is_inherited.
Cache: layer-level via _granular_doc_cached (same TTL/bound
as get_document). Resolution chain itself is recomputed each
call (cheap — Genome walk).
composition_summary
async
¶
Phase 17 (s-comp-f7-composition-summary, 2026-05-28) — cheap aggregate of the scope's parent chain + per-Kind counts.
Single endpoint replaces N list calls from the Sidebar. Returns:
{
"scope": "innovec-prod",
"parent_chain": ["innovec-base", "_lib"],
"resources": {
"Agent": {"local": 1, "inherited": 11, "total": 12},
"LottieAsset": {"local": 0, "inherited": 6, "total": 6},
...
},
}
Performance: each Kind takes 1 source.query (local-only push-down) + 1 source.query (parent push-down dedup) ≈ 10ms ¢. Cached server-side 60s via outer HTTP cache (see API route).
NB: kept inline (NOT extracted to the CompositionResolver collaborator in
Fase 5) because it needs the query push-down, and widening
CompositionResolverHost with RecordQuery would break the frozen
F1 FakeKernelSlice guard (whose composition fake exposes no query).
It is a thin aggregation over the query facade + _compute_resolution_chain.
personalize_document
async
¶
personalize_document(
target_scope: str,
kind: str,
name: str,
*,
tenant: str | None = None,
overwrite: bool = False
)
Phase 17 (s-comp-f6-personalize-primitive, 2026-05-28) —
clone an inherited doc into target_scope as a local override.
Resolves the doc via composition chain; if the effective layer
is THIS scope (not inherited), raises ValueError. Otherwise
clones spec + bundle entries to target_scope atomically.
Args: target_scope: where the override should land. kind, name: doc identity. tenant: writes go to base layer (tenant=None) by default; pass a tenant slug for tenant-overlay personalization. overwrite: if False (default) raises when target_scope already has a local doc with this name.
Returns:
ResolvedDocument of the freshly written local copy.
Raises: ValueError: doc isn't inherited / target already exists (without overwrite=True).
query
async
¶
query(
scope: str,
kind: str,
*,
filter: dict | None = None,
projection: list[str] | None = None,
limit: int | None = None,
offset: int | None = None,
order_by: list[str] | None = None,
tenant: str | None = None,
origin: str = "all",
scopes: list[str] | None = None
)
Marco A kernel-level query — push-down delegado ao source.
Delegado ao self._query (s-kernel-decompose-god-object). Tenant
auto-stamp (kwarg > Kernel.tenant > None), origin filter
(local/inherited/all), a chain de scope-inheritance e o cross-scope
scopes= (F2.4 — queries locais por scope, concat sem dedup;
scopes ganha do scope posicional) vivem lá. Mantido como
async generator aqui pra preservar a assinatura exata (callers
fazem async for + inspect.isasyncgenfunction). API intacta.
count
async
¶
count(
scope: str,
kind: str,
*,
filter: dict | None = None,
group_by: str | None = None,
tenant: str | None = None,
scopes: list[str] | None = None
) -> dict
F2 D2 — aggregation count público ao lado de query.
Push-down ao source (PG: SELECT count(*) … GROUP BY nativo;
FS/SQLite: protocol-default). Retorna CountResult:
{"total": int, "groups": [{"key", "count"}] | None} (groups
por count DESC, key ASC None-last).
SEM origin de propósito — records são por-scope; herança não
se aplica a count (spec D5). Cross-scope via scopes= (soma
totals + merge de groups por key; ganha do scope posicional).
Example (Studio velocity): res = await kernel.count( "dna-development", "Story", group_by="spec.status", ) # {"total": 950, "groups": [{"key": "done", "count": 700}, …]}
record_search_provider ¶
Register the semantic-search provider (two-planes F2). One per kernel; later registration replaces (boot-time wiring) and resets the failure-warning damper (new provider → fresh episode).
embedding_provider ¶
Register the embedding provider (rec-embedding-port). One per kernel;
later registration replaces (boot-time wiring). Sibling to
record_search_provider — a real provider (ONNX all-MiniLM-L6-v2)
registers itself at app boot; without one, embed uses the
deterministic FakeEmbeddingProvider floor.
embed
async
¶
Embed texts into dense vectors (rec-embedding-port). Uses the
registered EmbeddingPort when present, else the deterministic
zero-dep fake floor. Returns one dims-length vector per input, in
order; empty input → empty list. Read the space via
kernel.embedding_dims / kernel.embedding_model_id.
search
async
¶
search(
scope: str,
query_text: str,
*,
kind: str | None = None,
k: int = 10,
tenant: str | None = None
) -> dict[str, Any]
Public record search (F2 D2). Provider registered → semantic (pgvector/RRF, degraded=False); no provider OR provider error → lexical token-match fallback (degraded=True). Thin facade over the SearchEngine collaborator (s-kernel-decomp-f5-satellites).
query_list_sync ¶
query_list_sync(
scope: str,
kind: str,
*,
filter: dict | None = None,
tenant: str | None = None
) -> list[Document]
Sync wrapper around query returning parsed Document objects
(drop-in for mi.all(kind)). Delegado ao self._query
(s-kernel-decompose-god-object); _run_sync_helper + main-loop
binding vivem lá. API intacta (CLI, workers, tool executors).
get_document_sync ¶
get_document_sync(
scope: str,
kind: str,
name: str,
*,
tenant: str | None = None
) -> Document | None
Sync wrapper around get_document returning a parsed Document
(drop-in for mi.one(kind, name)). Delegado ao self._query
(s-kernel-decompose-god-object). API intacta.
instance ¶
Sync wrapper around instance_async. Use this from sync
contexts (CLI, tests). From inside an event loop, prefer
await kernel.instance_async(scope, layers) directly to avoid
the asyncio.run-in-thread fallback that orphans pool-based
adapters. Delegates to self._builder (s-kernel-decompose-god-object).
instance_async
async
¶
instance_async(
scope: str,
layers: dict[str, str] | None = None,
*,
lazy: bool | None = None
) -> "ManifestInstance"
Async-native version of instance. Use directly from async
contexts (FastAPI lifespan, Temporal activities) to keep the
source pool tied to the caller's event loop.
Phase 9: tenant binding auto-promotes into layers so load_bootstrap_docs + load_layer pick up the right tenant overlay.
Story s-miholder-transient (2026-05-14): lazy kwarg lets
callers explicitly opt into lazy MI construction (bootstrap
docs only; mi.all/one delegate to kernel.query). Default
None honors DNA_LAZY_MI env var. True/False
override.
resolve_layers ¶
Resolve layers on an existing MI (sync wrapper). Delegates to
self._builder (s-kernel-decompose-god-object).
resolve_layers_async
async
¶
Async-native layer resolver — MI.resolve_async() delegates here, then
through self._builder (s-kernel-decompose-god-object).
model_profile
async
¶
Resolve a ModelProfile from the _lib registry by model_id, then by
aliases[]. Returns the RAW DICT row (callers read profile["spec"][...])
or None. _lib-direct + fail-soft. Thin facade over the RegistryAccessor
collaborator (s-kernel-decomp-f5-satellites).
voice_policy
async
¶
Resolve a VoicePolicy from the _lib registry by metadata name (falls back to the first policy). Returns the RAW DICT row or None. _lib-direct + fail-soft. Thin facade over the RegistryAccessor collaborator (s-kernel-decomp-f5-satellites).
embedding_profile
async
¶
Resolve the embedding profile from the _lib CognitivePolicy by name.
Returns a RAW-DICT-shaped row whose spec is the doc's embedding
section, or None. _lib-direct + fail-soft. Thin facade over the
RegistryAccessor collaborator (s-kernel-decomp-f5-satellites).
quick
classmethod
¶
Quick-start: a filesystem Kernel with every discoverable extension
loaded, returning the ManifestInstance for scope. Thin facade over
build_quick_manifest (kernel decomposition, Fase 4 —
s-kernel-decomp-f4-bootstrap). cls is threaded through so a
subclass (e.g. Runtime) is what gets built.
auto
classmethod
¶
Create a Kernel with all discoverable extensions loaded.
Thin facade over build_auto_kernel (kernel decomposition, Fase 4 —
s-kernel-decomp-f4-bootstrap): entry-point discovery + H8
deterministic topo-sort boot ordering + source/cache/resolver wiring +
validate_dep_filters gate. cls is threaded through so a subclass
(e.g. Runtime) is what gets built. See the collaborator module for
the full recipe + rationale.
Runtime¶
dna.kernel.runtime.Runtime ¶
Bases: Kernel
Runtime that integrates any agent configuration standard.