Summary
The TinyMemory engine already runs as a TinyBus module — memory::binding states plainly that "the built-in driver is the compiled TinyMemory TinyBus module. The host no longer exposes an embedded engine class for memory." But tinymemory-core is still linked into the shipped binary, because the agent-tool and query paths call the crate's implementation directly instead of going through the MemoryProvider seam. Route those call sites through the provider so the crate can leave the build.
Problem / Context
The module extraction is half-applied, and the measurement makes the gap concrete. On 90dabbb5b, with the product feature set:
| Module |
In the shipped build? |
tinydocs |
no |
tinyjuice |
no |
tinyvoice |
no |
tinymemory / tinymemory-core |
yes — still a path dependency |
tinywallet |
yes (deliberate — see #5559) |
tinymemory_core is 1.44 MB of .text, the 7th largest crate in the binary.
There are two live paths to memory. The driver binding goes over the bus, but 107 direct tinymemory_core:: references and 46 tinymemory_api:: references in src/ bypass it. They cluster in four places:
| Call site |
Direct refs |
What it reaches for |
memory/tools/ |
9 files |
tree::retrieval, store::chunks |
memory/query/ |
8 files |
tree::retrieval, tree::score |
memory/tree/ |
6 files |
tree::tree, tree::health, tree::tree_runtime |
memory/sync/ |
6 files |
sync::composio, sync::sync_status |
Plus chat::build_chat_runtime / build_chat_provider, source_scope::current_source_scope, tool_memory, thread_context.
This matters beyond binary size. A capability reachable by two different paths is one whose behaviour can diverge — the bus path enforces the error mapping in memory::api::wire, and ModuleMemoryProvider::verify cross-checks the module's declared capabilities against Capabilities::all. A direct crate call gets none of that. modules/memory.rs already documents why the error table is shared by both ends: reimplementing the mapping is "what would let a PathEscape arrive as an Invalid, silently reclassifying a sandbox escape as a caller mistake." Direct calls sidestep that reasoning entirely.
Context on why this is worth finishing rather than leaving: measured across the module extractions (127.1 MB → 116.9 MB), the binary's first-party share of .text rose from 73.4% to 75.7% and the monomorphization tax was identical at 16.7 MB. Modules are the only lever that removes dependency code from the build outright — documents went from 39 crates to none. Leaving tinymemory-core linked forfeits that for the largest domain in the tree.
Scope
In scope
- Route
memory/tools/, memory/query/, memory/tree/ and memory/sync/ through MemoryProvider (or add the bus methods they need if the trait does not cover them).
- Decide the fate of
tinymemory-api: it is the host-owned contract, so it plausibly stays. State the decision either way — the point is that it is deliberate.
- Drop the
tinymemory / tinymemory-core path dependencies once nothing names them, and remove the matching [package.metadata.cargo-machete] ignored entries.
Not in scope
tinywallet — tracked separately.
- The
memory-git gate. git2 / libgit2-sys / libz-sys are shed by that gate already and are a separate axis.
Implementation notes
ModuleMemoryProvider::new is synchronous and does no I/O by contract: memory::binding::build is called from CoreContext::memory_binding, which "roughly four thousand pre-boot tests invoke with no tokio runtime at all." Any new seam has to keep that property.
capabilities() is answered statically as Capabilities::all and cross-checked on first use. Widening the surface means keeping that cross-check honest.
- The
tinymemory and tinymemory-tinycortex deps exist for driver admission, not for calls — see the 2026-08-10 entry in scripts/kernel-floor.limits. Do not remove them as "unused" without checking admission still resolves an engine; cargo machete flags them precisely because they have no use.
Acceptance criteria
Related
Summary
The TinyMemory engine already runs as a TinyBus module —
memory::bindingstates plainly that "the built-in driver is the compiled TinyMemory TinyBus module. The host no longer exposes an embedded engine class for memory." Buttinymemory-coreis still linked into the shipped binary, because the agent-tool and query paths call the crate's implementation directly instead of going through theMemoryProviderseam. Route those call sites through the provider so the crate can leave the build.Problem / Context
The module extraction is half-applied, and the measurement makes the gap concrete. On
90dabbb5b, with the product feature set:tinydocstinyjuicetinyvoicetinymemory/tinymemory-coretinywallettinymemory_coreis 1.44 MB of.text, the 7th largest crate in the binary.There are two live paths to memory. The driver binding goes over the bus, but 107 direct
tinymemory_core::references and 46tinymemory_api::references insrc/bypass it. They cluster in four places:memory/tools/tree::retrieval,store::chunksmemory/query/tree::retrieval,tree::scorememory/tree/tree::tree,tree::health,tree::tree_runtimememory/sync/sync::composio,sync::sync_statusPlus
chat::build_chat_runtime/build_chat_provider,source_scope::current_source_scope,tool_memory,thread_context.This matters beyond binary size. A capability reachable by two different paths is one whose behaviour can diverge — the bus path enforces the error mapping in
memory::api::wire, andModuleMemoryProvider::verifycross-checks the module's declared capabilities againstCapabilities::all. A direct crate call gets none of that.modules/memory.rsalready documents why the error table is shared by both ends: reimplementing the mapping is "what would let aPathEscapearrive as anInvalid, silently reclassifying a sandbox escape as a caller mistake." Direct calls sidestep that reasoning entirely.Context on why this is worth finishing rather than leaving: measured across the module extractions (127.1 MB → 116.9 MB), the binary's first-party share of
.textrose from 73.4% to 75.7% and the monomorphization tax was identical at 16.7 MB. Modules are the only lever that removes dependency code from the build outright —documentswent from 39 crates to none. Leavingtinymemory-corelinked forfeits that for the largest domain in the tree.Scope
In scope
memory/tools/,memory/query/,memory/tree/andmemory/sync/throughMemoryProvider(or add the bus methods they need if the trait does not cover them).tinymemory-api: it is the host-owned contract, so it plausibly stays. State the decision either way — the point is that it is deliberate.tinymemory/tinymemory-corepath dependencies once nothing names them, and remove the matching[package.metadata.cargo-machete] ignoredentries.Not in scope
tinywallet— tracked separately.memory-gitgate.git2/libgit2-sys/libz-sysare shed by that gate already and are a separate axis.Implementation notes
ModuleMemoryProvider::newis synchronous and does no I/O by contract:memory::binding::buildis called fromCoreContext::memory_binding, which "roughly four thousand pre-boot tests invoke with no tokio runtime at all." Any new seam has to keep that property.capabilities()is answered statically asCapabilities::alland cross-checked on first use. Widening the surface means keeping that cross-check honest.tinymemoryandtinymemory-tinycortexdeps exist for driver admission, not for calls — see the 2026-08-10 entry inscripts/kernel-floor.limits. Do not remove them as "unused" without checking admission still resolves an engine;cargo macheteflags them precisely because they have nouse.Acceptance criteria
grep -r 'tinymemory_core::' src/returns nothing outsidemodules/memory.rsand the binding.cargo tree -e normal --no-default-features --features "$(bash scripts/ci/product-features.sh)"no longer liststinymemory-core; verified withscripts/assert-shed.sh, notcargo tree -i.scripts/kernel-floor.limits. An unratcheted improvement grows back unnoticed. Measure on Linux; macOS resolves +1/+1 fromcore-foundation/security-framework.ignoredlist in the rootCargo.tomlno longer names crates that are gone.AGENTS.md's memory section reflects the single path.Related
cargo bloatmeasurements quoted here.scripts/kernel-floor.limits— 2026-08-10 entry, whytinymemory/tinymemory-tinycortexare always-on driver-admission deps.src/openhuman/modules/memory.rs,src/openhuman/memory/binding.rs— the module seam and its contracts.