Skip to content

Close the last contract gaps openhuman#5560 needs to drop the engine crate - #101

Merged
YellowSnnowmann merged 2 commits into
tinyhumansai:mainfrom
YellowSnnowmann:feat/5560-close-the-last-contract-gap
Aug 25, 2026
Merged

Close the last contract gaps openhuman#5560 needs to drop the engine crate#101
YellowSnnowmann merged 2 commits into
tinyhumansai:mainfrom
YellowSnnowmann:feat/5560-close-the-last-contract-gap

Conversation

@YellowSnnowmann

Copy link
Copy Markdown
Contributor

Final upstream piece for openhuman#5560. With this released and pinned, the host can remove tinymemory-core and tinymemory-tinycortex from its [dependencies] in one pass.

The gap is measured, not estimated

Deleting both crates from the host's manifest and compiling the product profile gives 89 errors across 31 distinct symbols. That set is the whole remaining ask — closing all of it in one release is deliberate, because a gap left open costs another merge-release-repin cycle.

It splits in two: types the host reaches only through pub use shims, and behaviour with no member at all. I checked the second half against every member of all thirteen families at HEAD — 140 members, zero hits.

Two new families

MemorySyncrun_connection_sync, source_sync_state, sync_audit_log, estimate_sync_cost_usd, sync_statuses, raw_archive_coverage, rebuild_from_raw_archive.

run_connection_sync is worth a note: #100 moved the periodic loops into the module, but the host's five call sites are manual "sync now" paths. A user pressing a button is still the host's to trigger, so the on-demand half needs a door.

MemorySessionscoding_session_status, ingest_coding_sessions.

MemoryMaintenance::diagnose answers a structured Diagnosis, replacing the host's reach for the engine's async_run_doctor. It is a separate member from doctor rather than a widening of it, because the two return different things.

Why estimate_sync_cost_usd is a member

It is pure arithmetic and the host could do it — but the same constants back SyncAuditEntry's own cost field. A host-side copy becomes a second price that drifts from the one the audit rows were actually written with, so the cost stays computed where those rows are.

The types, moved rather than copied

~20 types — source descriptors, the composio provider vocabulary, tree scoring and summarising, retrieval types, diff ops, a facet class — move to tinymemory-bus, with the engine re-exporting from there so there is exactly one definition. Copying them would create the drifting-duplicate problem where a field added on one side is a decode failure on the other with nothing to catch it.

Two carve-outs:

  • SyncState moves; load/save do not. They do I/O, and the contract crate stays free of storage engines, HTTP clients and async runtimes. They become the PersistedSyncState extension trait in the engine, beside the SyncStateStore seam that was already there.
  • apply_kind_defaults moves to tinymemory-sources so a host can fill a new entry's caps without linking the engine. Its defaults are what the retroactive Composio caps migration applies, so a change here changes what already-registered sources reconcile against — the tests say so out loud.

Additive throughout

Every new trait member defaults to Unsupported, so no existing driver stops compiling; every new field is #[serde(default)]. The host and module are separately compiled and released, so an older peer decodes a newer payload rather than failing to load.

All new bus methods are registered in the four places that must agree — interface impl, module manifest, tinymemory_bus::METHODS (plus its length and the doc count), and EXPECTED_METHODS — in declaration order, because the drift assertion compares sequences rather than sets.

Validation

cargo check --workspace --all-targets clean in both workspaces. cargo test --workspace 2034 passing. cargo clippy --all-targets --all-features -D warnings clean on the root and the module workspace, cargo fmt clean on both, and engine-containment.sh holds. Module lane: 69 unit tests and every isolated loader case, which is what proves the four-place registration agrees.

…crate

The host is down from 285 direct references to the memory engine to 89, and
every one that remains is here: something it asks for that the contract cannot
express. This is measured rather than estimated — deleting both memory crates
from the host's `[dependencies]` and compiling the product profile yields
exactly those 89 errors across 31 distinct symbols. Closing all of them in one
release is the point; a gap left open is another release cycle.

## Two new families

`MemorySync` carries the seven sync surfaces the host still reaches into the
engine for: `run_connection_sync` (the host's five call sites are manual "sync
now" paths — the periodic loops moved into the module in tinyhumansai#100, but a user
pressing a button is still the host's to trigger), `source_sync_state`,
`sync_audit_log`, `estimate_sync_cost_usd`, `sync_statuses`,
`raw_archive_coverage` and `rebuild_from_raw_archive`.

`MemorySessions` carries the coding-session pipeline: `coding_session_status`
and `ingest_coding_sessions`.

`MemoryMaintenance::diagnose` replaces the host's reach for the engine's
`async_run_doctor`, answering a structured `Diagnosis` rather than the
maintenance report `doctor` already returns.

`estimate_sync_cost_usd` is a member rather than something the host could
compute, and deliberately: the same constants back `SyncAuditEntry`'s own cost
field, so a host-side copy becomes a second price that drifts from the one audit
rows were written with.

## Types that were never engine-internal

About twenty types reached the host only through `pub use tinymemory_core::…`
shims — source descriptors, the composio provider vocabulary, tree scoring and
summarising, retrieval types, diff ops, a facet class. They are data, so they
move to `tinymemory-bus` and the engine re-exports them from there. Moving
rather than copying is the whole point: a copy is the drifting-duplicate failure
where a field added on one side is a decode failure on the other with nothing to
catch it.

`SyncState` moves with them, but `load` and `save` do not — they do I/O, and the
contract crate stays free of storage engines, HTTP clients and async runtimes.
They become the `PersistedSyncState` extension trait in the engine, which is
where the `SyncStateStore` seam already lives.

`apply_kind_defaults` moves to `tinymemory-sources` so a host can fill a new
entry's caps without linking the engine. Its defaults are the ones the
retroactive Composio caps migration applies, so a change here is a change to
what already-registered sources reconcile against — the tests say so.

## Additive throughout

Every new trait member has a default body returning `Unsupported`, so no
existing driver stops compiling, and every new field is `#[serde(default)]`.
The host and module are separately compiled and separately released; an older
peer must decode a newer payload rather than fail to load.

All new bus methods are registered in the four places that have to agree, in
declaration order, because the drift assertion compares sequences rather than
sets.
@coderabbitai

coderabbitai Bot commented Aug 25, 2026

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 52df578e-5812-4dec-a450-b3b41be9bdac

Warning

Your free Security trial is over. An organization admin can activate billing to continue.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@tinysweeper tinysweeper Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tinysweeper found nothing blocking. Approving.

$0.0000 · 0 in / 0 out

`Self` has no meaning in a `//!` comment — it is module documentation, not an
impl — so rustdoc could not resolve the target and the docs lane fails the whole
crate under `-D warnings`.
@tinysweeper tinysweeper Bot added the priority: p3 Whenever. Cosmetic, a nicety, or a cleanup with no user visible effect. label Aug 25, 2026
@YellowSnnowmann
YellowSnnowmann merged commit 94d4a98 into tinyhumansai:main Aug 25, 2026
27 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

priority: p3 Whenever. Cosmetic, a nicety, or a cleanup with no user visible effect.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant