diff --git a/.github/workflows/ci-lite.yml b/.github/workflows/ci-lite.yml index b0b9bbc18a..0477b2d743 100644 --- a/.github/workflows/ci-lite.yml +++ b/.github/workflows/ci-lite.yml @@ -558,7 +558,13 @@ jobs: # # This asserts the calibration still holds. If it fails, every # projection built on the simulator is suspect until it is fixed. - run: python3 scripts/dep-sim.py --cut-nothing --expect-names 264 + # + # The number is the Linux name count of the `flows` profile, so it moves + # whenever scripts/kernel-floor.limits does and belongs in the same PR. + # 264 -> 265 on 2026-08-21: the tinymemory #76/#77 bump adds exactly one + # name, `tinymemory-bus`. macOS resolves one higher (266) per the host + # skew recorded in the limits history — this expects the CI host. + run: python3 scripts/dep-sim.py --cut-nothing --expect-names 265 - name: Guard — new feature-gated test modules must be acknowledged # Self-maintaining coverage: the set of source files that #[cfg]-gate a test on diff --git a/AGENTS.md b/AGENTS.md index 7b8f4ff558..a3a61df331 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -684,7 +684,7 @@ before touching `src/openhuman/memory/`. **The contract is `tinymemory-api`, and `crate::openhuman::memory::api` is a re-export of it — not a copy.** `3ee5a3cad` inlined that crate as 10,894 lines under `src/openhuman/memory/api/`, every file byte-identical to -`vendor/tinymemory/api/src/` apart from doc-comment paths. Nothing behaved +`vendor/tinymemory/crates/tinymemory-api/src/` apart from doc-comment paths. Nothing behaved differently, which is what made it worth undoing: the contract is the vocabulary the host, `ModuleMemoryProvider`, and the separately compiled module all speak, and the module compiles against the **crate**. A verbatim copy made the host's diff --git a/Cargo.lock b/Cargo.lock index f131954bc5..68a8e5522c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1618,6 +1618,15 @@ dependencies = [ "dirs-sys 0.4.1", ] +[[package]] +name = "dirs" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e" +dependencies = [ + "dirs-sys 0.5.0", +] + [[package]] name = "dirs-sys" version = "0.4.1" @@ -2448,11 +2457,11 @@ dependencies = [ [[package]] name = "hashlink" -version = "0.11.1" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "824e001ac4f3012dd16a264bec811403a67ca9deb6c102fc5049b32c4574b35f" +checksum = "32069d97bb81e38fa67eab65e3393bf804bb85969f2bc06bf13f64aef5aba248" dependencies = [ - "hashbrown 0.16.1", + "hashbrown 0.17.1", ] [[package]] @@ -3284,9 +3293,9 @@ dependencies = [ [[package]] name = "libsqlite3-sys" -version = "0.38.1" +version = "0.38.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6c19a05435c21ac299d71b6a9c13db3e3f47c520517d58990a462a1397a61db" +checksum = "f1d20bef17f513b9b3004532233187769cd072d790971f4e4da0e346eb6401e8" dependencies = [ "cc", "pkg-config", @@ -4129,7 +4138,7 @@ dependencies = [ "curve25519-dalek", "dhat", "directories", - "dirs", + "dirs 5.0.1", "dotenvy", "ed25519-dalek", "enigo", @@ -5293,9 +5302,9 @@ dependencies = [ [[package]] name = "rusqlite" -version = "0.40.0" +version = "0.40.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b3492ea85308705c3a5cc24fb9b9cf77273d30590349070db42991202b214c4" +checksum = "23f2a97da3e3873c73cb2a2e71b35c40ff95e0b1eefa8d72d8499a6928c3b5b3" dependencies = [ "bitflags 2.13.1", "fallible-iterator", @@ -6418,7 +6427,7 @@ dependencies = [ "async-trait", "block2 0.6.2", "chrono", - "dirs", + "dirs 5.0.1", "futures", "git2", "hex", @@ -6502,7 +6511,7 @@ dependencies = [ [[package]] name = "tinymemory" -version = "1.0.1" +version = "1.1.0" dependencies = [ "anyhow", "async-trait", @@ -6518,11 +6527,21 @@ version = "0.1.1" dependencies = [ "anyhow", "async-trait", - "chrono", "log", "schemars", "serde", "serde_json", + "tinymemory-bus", +] + +[[package]] +name = "tinymemory-bus" +version = "0.1.0" +dependencies = [ + "anyhow", + "chrono", + "serde", + "serde_json", "sha2 0.11.0", "thiserror 2.0.18", "uuid", @@ -6535,17 +6554,17 @@ dependencies = [ "anyhow", "async-trait", "chrono", - "dirs", + "dirs 6.0.0", "futures", "log", "parking_lot", - "rand 0.8.6", + "rand 0.10.1", "regex", "reqwest", "rusqlite", "serde", "serde_json", - "sha2 0.10.9", + "sha2 0.11.0", "thiserror 2.0.18", "tinyagents", "tinycortex", @@ -6575,7 +6594,7 @@ dependencies = [ "serde_json", "tinymemory-api", "tokio", - "toml 0.9.12+spec-1.1.0", + "toml 1.1.2+spec-1.1.0", "tracing", "uuid", "walkdir", @@ -6828,21 +6847,6 @@ dependencies = [ "toml_edit 0.22.27", ] -[[package]] -name = "toml" -version = "0.9.12+spec-1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf92845e79fc2e2def6a5d828f0801e29a2f8acc037becc5ab08595c7d5e9863" -dependencies = [ - "indexmap", - "serde_core", - "serde_spanned 1.1.1", - "toml_datetime 0.7.5+spec-1.1.0", - "toml_parser", - "toml_writer", - "winnow 0.7.15", -] - [[package]] name = "toml" version = "1.1.2+spec-1.1.0" @@ -6867,15 +6871,6 @@ dependencies = [ "serde", ] -[[package]] -name = "toml_datetime" -version = "0.7.5+spec-1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347" -dependencies = [ - "serde_core", -] - [[package]] name = "toml_datetime" version = "1.1.1+spec-1.1.0" diff --git a/Cargo.toml b/Cargo.toml index 07334defab..f9f6d2c4c4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -244,9 +244,9 @@ tinycortex-api = { path = "vendor/tinycortex/api" } # rather than the one pinned inside the tinymemory submodule. # # After cloning: `git submodule update --init --recursive vendor/tinymemory`. -tinymemory = { path = "vendor/tinymemory" } -tinymemory-api = { path = "vendor/tinymemory/api" } -tinymemory-tinycortex = { path = "vendor/tinymemory/adapters/tinycortex" } +tinymemory = { path = "vendor/tinymemory/crates/tinymemory" } +tinymemory-api = { path = "vendor/tinymemory/crates/tinymemory-api" } +tinymemory-tinycortex = { path = "vendor/tinymemory/crates/tinymemory-tinycortex" } # `tinymemory-core` is the *substance* of the memory subsystem, extracted out of # `src/openhuman/memory/` — the SQLite/vector store, the markdown summary tree, # the provider sync pipelines, ingestion, recall/query/search, the ingest queue, @@ -263,7 +263,7 @@ tinymemory-tinycortex = { path = "vendor/tinymemory/adapters/tinycortex" } # The `schemars` feature is enabled because the memory config *section* structs # (`MemoryConfig`, `MemoryTreeConfig`, …) now live in `tinymemory_api::host` and # are still fields of OpenHuman's `Config`, which derives `JsonSchema`. -tinymemory-core = { path = "vendor/tinymemory/core" } +tinymemory-core = { path = "vendor/tinymemory/crates/tinymemory-core" } tinychannels = { version = "0.1", features = ["relay-websocket"] } # tinybus — the message bus. Owns what `src/core/event_bus/` used to: the typed # pub/sub surface (`EventBus`, `EventHandler`, `SubscriptionHandle`), the @@ -370,7 +370,7 @@ tokio-util = { version = "0.7", features = ["rt", "io"] } # (native-tls on Windows, rustls on macOS / Linux) matches the reqwest # backend selected at each TLS call site. futures = "0.3" -rusqlite = { version = "=0.40.0", features = ["bundled"] } +rusqlite = { version = "=0.40.2", features = ["bundled"] } chrono = { version = "0.4", features = ["serde"] } iana-time-zone = "0.1" cron = "0.12" @@ -576,7 +576,7 @@ coins-bip39 = { version = "0.8" } # They were `#[cfg(test)]` items in this crate before the memory extraction; a # downstream test harness cannot see those across a crate boundary, so the # extracted crate exposes them behind `test-support` instead. -tinymemory-core = { path = "vendor/tinymemory/core", features = ["test-support"] } +tinymemory-core = { path = "vendor/tinymemory/crates/tinymemory-core", features = ["test-support"] } # Dual-declared on purpose (same shape as the `sentry`/`axum` entries): the # optional dependency above is bin-only behind `bin-tools`, but # `agent_orchestration::tools::tools_e2e_tests` (a #[cfg(test)] LIB module), @@ -1142,7 +1142,7 @@ while_let_loop = "allow" # deleted, reintroduced by dependency resolution. Same entry tinymemory's own # workspace carries; the key has no `.git` suffix, matching the dep URL. [patch."https://github.com/tinyhumansai/tinymemory"] -tinymemory-api = { path = "vendor/tinymemory/api" } +tinymemory-api = { path = "vendor/tinymemory/crates/tinymemory-api" } [patch.crates-io] # Upstream 0.2.1 enables reqwest's default native-tls backend even though it diff --git a/app/src-tauri/Cargo.lock b/app/src-tauri/Cargo.lock index 5975af6208..2d8ff8b742 100644 --- a/app/src-tauri/Cargo.lock +++ b/app/src-tauri/Cargo.lock @@ -2557,6 +2557,9 @@ name = "hashbrown" version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" +dependencies = [ + "foldhash 0.2.0", +] [[package]] name = "hashify" @@ -2572,11 +2575,11 @@ dependencies = [ [[package]] name = "hashlink" -version = "0.11.1" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "824e001ac4f3012dd16a264bec811403a67ca9deb6c102fc5049b32c4574b35f" +checksum = "32069d97bb81e38fa67eab65e3393bf804bb85969f2bc06bf13f64aef5aba248" dependencies = [ - "hashbrown 0.16.1", + "hashbrown 0.17.1", ] [[package]] @@ -5416,9 +5419,9 @@ dependencies = [ [[package]] name = "rusqlite" -version = "0.40.0" +version = "0.40.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b3492ea85308705c3a5cc24fb9b9cf77273d30590349070db42991202b214c4" +checksum = "23f2a97da3e3873c73cb2a2e71b35c40ff95e0b1eefa8d72d8499a6928c3b5b3" dependencies = [ "bitflags 2.13.1", "fallible-iterator", @@ -7189,7 +7192,7 @@ dependencies = [ [[package]] name = "tinymemory" -version = "1.0.1" +version = "1.1.0" dependencies = [ "anyhow", "async-trait", @@ -7205,11 +7208,21 @@ version = "0.1.1" dependencies = [ "anyhow", "async-trait", - "chrono", "log", "schemars 1.2.2", "serde", "serde_json", + "tinymemory-bus", +] + +[[package]] +name = "tinymemory-bus" +version = "0.1.0" +dependencies = [ + "anyhow", + "chrono", + "serde", + "serde_json", "sha2 0.11.0", "thiserror 2.0.20", "uuid", @@ -7222,17 +7235,17 @@ dependencies = [ "anyhow", "async-trait", "chrono", - "dirs 5.0.1", + "dirs 6.0.0", "futures", "log", "parking_lot", - "rand 0.8.7", + "rand 0.10.2", "regex", "reqwest 0.12.28", "rusqlite", "serde", "serde_json", - "sha2 0.10.9", + "sha2 0.11.0", "thiserror 2.0.20", "tinyagents", "tinycortex", @@ -7262,7 +7275,7 @@ dependencies = [ "serde_json", "tinymemory-api", "tokio", - "toml 0.9.12+spec-1.1.0", + "toml 1.1.4+spec-1.1.0", "tracing", "uuid", "walkdir", diff --git a/app/src-tauri/Cargo.toml b/app/src-tauri/Cargo.toml index 75c14e9d1d..c904f6d809 100644 --- a/app/src-tauri/Cargo.toml +++ b/app/src-tauri/Cargo.toml @@ -103,7 +103,7 @@ anyhow = "1.0" # platforms — the store persists on Windows/Linux/macOS. Pinned to match the # core crate so a single bundled SQLite is linked. (The macOS-only iMessage # scanner also uses rusqlite; this general dep covers it too.) -rusqlite = { version = "=0.40.0", features = ["bundled"] } +rusqlite = { version = "=0.40.2", features = ["bundled"] } parking_lot = "0.12" chrono = "0.4" async-trait = "0.1" @@ -265,7 +265,7 @@ e2e-test-support = ["openhuman_core/e2e-test-support"] # deleted, reintroduced by dependency resolution. Same entry tinymemory's own # workspace carries; the key has no `.git` suffix, matching the dep URL. [patch."https://github.com/tinyhumansai/tinymemory"] -tinymemory-api = { path = "../../vendor/tinymemory/api" } +tinymemory-api = { path = "../../vendor/tinymemory/crates/tinymemory-api" } [patch.crates-io] # Keep reqwest defaults disabled in this independent Cargo world too. Without diff --git a/docs/specs/memory-guard-allowlist.md b/docs/specs/memory-guard-allowlist.md index 6dbdc58351..4f6e404a7c 100644 --- a/docs/specs/memory-guard-allowlist.md +++ b/docs/specs/memory-guard-allowlist.md @@ -170,7 +170,7 @@ are recorded here so M4c starts from the real set. `integrations/composio/ops_tests.rs`, `core/runtime/context.rs` (its `#[cfg(test)]` module). -`vendor/tinymemory/core/src/tinycortex/sync.rs` also has an inline `#[cfg(test)]` +`vendor/tinymemory/crates/tinymemory-core/src/engine/sync.rs` also has an inline `#[cfg(test)]` module whose isolated-workspace fixtures construct `MemoryClient` directly; it is counted because the scanner does not brace-track inline test modules. diff --git a/gitbooks/features/obsidian-wiki/scoring.md b/gitbooks/features/obsidian-wiki/scoring.md index f1c0d57039..6bc18a60be 100644 --- a/gitbooks/features/obsidian-wiki/scoring.md +++ b/gitbooks/features/obsidian-wiki/scoring.md @@ -10,7 +10,7 @@ icon: scale Not every chunk deserves a place in the Memory Tree. A "thanks!" reply, an email footer, or a calendar auto-notification carry almost no signal, and folding them into summary trees only dilutes the result and burns LLM tokens. Scoring is the gate: a per-chunk pass that runs **after chunking and before the chunk is appended to the L0 buffer**, deciding whether the chunk is worth keeping, enriching it with extracted entities, and indexing it for retrieval. -The entry point is `score_chunk` in [`src/openhuman/memory/tree/score/mod.rs`](https://github.com/tinyhumansai/tinymemory/blob/main/core/src/tree/score/mod.rs). It is a pure function - it computes a result but does not touch the store; callers persist based on `ScoreResult::kept`. +The entry point is `score_chunk` in [`src/openhuman/memory/tree/score/mod.rs`](https://github.com/tinyhumansai/tinymemory/blob/1d6b997874a06600ba0c4922708b5613497c9ffe/crates/tinymemory-core/src/tree/score/mod.rs). It is a pure function - it computes a result but does not touch the store; callers persist based on `ScoreResult::kept`. --- @@ -25,7 +25,7 @@ Two goals, both in service of a dense, relevant tree: ## The signals -`score_chunk` computes a bag of independent signals, each normalised to `[0.0, 1.0]`, defined in [`score/signals/`](https://github.com/tinyhumansai/tinymemory/tree/main/core/src/tree/score/signals). They are combined into a single weighted total and stored alongside it in `mem_tree_score` so every admit/drop decision stays auditable. +`score_chunk` computes a bag of independent signals, each normalised to `[0.0, 1.0]`, defined in [`score/signals/`](https://github.com/tinyhumansai/tinymemory/tree/1d6b997874a06600ba0c4922708b5613497c9ffe/crates/tinymemory-core/src/tree/score/signals). They are combined into a single weighted total and stored alongside it in `mem_tree_score` so every admit/drop decision stays auditable. | Signal | What it measures | Default weight | | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------ | -------------- | @@ -75,7 +75,7 @@ Dropped chunks still get a score row written for diagnostics, with a `drop_reaso ## Entity extraction -Extraction enriches a chunk and feeds both the `entity_density` / `llm_importance` signals and the index. It is pluggable via the `EntityExtractor` trait in [`score/extract/`](https://github.com/tinyhumansai/tinymemory/tree/main/core/src/tree/score/extract), and runs in two stages: +Extraction enriches a chunk and feeds both the `entity_density` / `llm_importance` signals and the index. It is pluggable via the `EntityExtractor` trait in [`score/extract/`](https://github.com/tinyhumansai/tinymemory/tree/1d6b997874a06600ba0c4922708b5613497c9ffe/crates/tinymemory-core/src/tree/score/extract), and runs in two stages: - **`RegexEntityExtractor`** - always on, deterministic, cheap. Once-compiled patterns pull mechanical identifiers: email, URL, handle (`@alice` and Discord-style `alice#1234`), and hashtag. UTF-8 safe (spans are char offsets). - **`LlmEntityExtractor`** - consulted only on borderline chunks. A single structured-JSON call asks the model for semantic NER (Person / Organization / Location / Topic / …) plus an importance rating, with span recovery and a soft warn-and-empty fallback on transport failure. @@ -86,7 +86,7 @@ The two are chained by **`CompositeExtractor`**, which runs a sequence of extrac ## The entity index & graph -Canonical entities for each kept chunk are written to **`mem_tree_entity_index`**, an inverted index mapping `entity_id → node_id` ([`store.rs`](https://github.com/tinyhumansai/tinymemory/blob/main/core/src/tree/score/store.rs)). This is the connective tissue the rest of the Memory Tree reads from: +Canonical entities for each kept chunk are written to **`mem_tree_entity_index`**, an inverted index mapping `entity_id → node_id` ([`store.rs`](https://github.com/tinyhumansai/tinymemory/blob/1d6b997874a06600ba0c4922708b5613497c9ffe/crates/tinymemory-core/src/tree/score/store.rs)). This is the connective tissue the rest of the Memory Tree reads from: - **Retrieval** resolves a query's entities against the index to find candidate nodes. - **Topic routing** uses entity hotness to decide which entities deserve their own topic tree. @@ -96,9 +96,9 @@ Canonical entities for each kept chunk are written to **`mem_tree_entity_index`* ## Embeddings for semantic recall -Scoring also produces vectors. The embedder in [`score/embed/`](https://github.com/tinyhumansai/tinymemory/tree/main/core/src/tree/score/embed) turns each chunk (and later, summary) into a fixed `EMBEDDING_DIM = 1024`-float `Vec`, packed into a SQLite BLOB, so retrieval can rerank candidates by cosine similarity rather than relying on the entity index alone. +Scoring also produces vectors. The embedder in [`score/embed/`](https://github.com/tinyhumansai/tinymemory/tree/1d6b997874a06600ba0c4922708b5613497c9ffe/crates/tinymemory-core/src/tree/score/embed) turns each chunk (and later, summary) into a fixed `EMBEDDING_DIM = 1024`-float `Vec`, packed into a SQLite BLOB, so retrieval can rerank candidates by cosine similarity rather than relying on the entity index alone. -The active embedder is selected by `build_embedder_from_config` ([`embed/factory.rs`](https://github.com/tinyhumansai/tinymemory/blob/main/core/src/tree/score/embed/factory.rs)) walking a resolution ladder, identical for read and write paths: +The active embedder is selected by `build_embedder_from_config` ([`embed/factory.rs`](https://github.com/tinyhumansai/tinymemory/blob/1d6b997874a06600ba0c4922708b5613497c9ffe/crates/tinymemory-core/src/tree/score/embed/factory.rs)) walking a resolution ladder, identical for read and write paths: 1. **Explicit Ollama override** (`memory_tree.embedding_endpoint` + `embedding_model`) - power users / E2E rigs. 2. **Local Ollama** via the unified `embeddings` workload setting - the "Memory embeddings" checkbox in [Local AI](../model-routing/local-ai.md) Settings. diff --git a/scripts/kernel-floor.limits b/scripts/kernel-floor.limits index ddca09e1cf..e4df41a888 100644 --- a/scripts/kernel-floor.limits +++ b/scripts/kernel-floor.limits @@ -13,6 +13,45 @@ # Simulate with: scripts/dep-sim.py --cut # # History +# 283/265/2 2026-08-21 tinymemory bumped past its #76/#77 line (-2 packages, +# +1 NAME). The name is `tinymemory-bus`, and it is a +# RAISE, so: tinymemory#74 moved the wire vocabulary — +# member names, payload types, the error-name table — out +# of `tinymemory-api` into a crate beneath it, so anything +# linking the api now also resolves the bus crate. No new +# third-party code enters: `tinymemory-bus` is deliberately +# dependency-light (serde, serde_json, chrono, sha2, uuid, +# anyhow, thiserror — every one already in this profile, +# and it is forbidden an async runtime, rusqlite, git2, +# reqwest or regex by a guard in its own manifest). It is +# also the crate that makes the opposite direction +# possible: a host that later talks to the loadable +# TinyMemory module links THIS and drops the engine, which +# is a shed this ratchet should want. +# The -2 packages are real departures, not a re-count: +# `hashbrown 0.16.1`, `toml 0.9.12`, `toml_datetime 0.7.5` +# and `winnow 0.7.15` leave; `dirs 6.0.0` and +# `tinymemory-bus 0.1.0` enter, so four out and two in. +# `dirs 6.0.0` moves the package count without moving the +# name count: `dirs 5.0.1` is a DIRECT dependency of +# `openhuman` itself, so it cannot leave on any host and +# the two versions coexist. The +1 name is therefore +# `tinymemory-bus` alone. Everything else in the diff is a +# version bump the pin carries: rusqlite 0.40.0 -> 0.40.2 +# (and libsqlite3-sys 0.38.1 -> 0.38.2, hashlink 0.11 -> +# 0.12), which is `tinymemory-core`'s exact pin, and +# tinymemory 1.0.1 -> 1.1.0. Native builds unchanged at 2. +# Measured on CI (Linux): 283/265/2. Both hosts move by the +# same -2/+1: at this branch's base (5cd5b3a) Linux +# resolves 285/264 and macOS 286/265, landing at 283/265 +# and 284/266 — the host skew is +1 package and +1 name, +# before and after. Note the 2026-08-19 entry below reads +# 286/264: its lockfile is name-for-name identical to this +# branch's base, so that 286 is the macOS package count +# paired with the Linux name count, i.e. one package +# looser than a Linux run of `scripts/kernel-floor.sh +# flows` measures. Re-measure on one host before quoting a +# delta against it. # 286/264/2 2026-08-19 tinymemory bumped across its #18 arc (-4 names, 0 # packages net, native unchanged). A shed, not a gate, and # a downstream one: tinymemory#43 (§D2) moved `axum` from @@ -332,4 +371,4 @@ # (libsqlite3-sys, ring) — see docs/plans MIGRATION-PLAN G6. # 307/284 2026-08-12 Re-baseline after the upstream lockfile resolution; # `flows` remains at two native packages. -flows:286:264:2 +flows:283:265:2 diff --git a/src/openhuman/memory/README.md b/src/openhuman/memory/README.md index bc879ef7fa..e24891a2f9 100644 --- a/src/openhuman/memory/README.md +++ b/src/openhuman/memory/README.md @@ -56,7 +56,7 @@ tinymemory_core::::*;` plus the handler/schema modules that name ## What lives in the extracted crate (for reference) -See [`vendor/tinymemory/core/src/`](https://github.com/tinyhumansai/tinymemory/tree/main/core/src) for +See [`vendor/tinymemory/crates/tinymemory-core/src/`](https://github.com/tinyhumansai/tinymemory/tree/1d6b997874a06600ba0c4922708b5613497c9ffe/crates/tinymemory-core/src) for the storage primitives (`store/`), ingestion queue (`ingestion/`), sync lifecycle types (`sync_events.rs`), remember classification (`remember.rs`), ingest orchestration (`ingest_pipeline.rs`), the `Memory`/`MemoryEntry`/etc. diff --git a/src/openhuman/memory/bypass_allowlist_tests.rs b/src/openhuman/memory/bypass_allowlist_tests.rs index 4c0bca1287..5541e381cc 100644 --- a/src/openhuman/memory/bypass_allowlist_tests.rs +++ b/src/openhuman/memory/bypass_allowlist_tests.rs @@ -246,7 +246,7 @@ const ALLOWED: &[(&str, &str, &str)] = &[ "this is the construction path the lint protects (fail-closed fallback)", ), ( - "vendor/tinymemory/core/src/global.rs", + "vendor/tinymemory/crates/tinymemory-core/src/global.rs", "MemoryClient::from_workspace_dir(", "the process-global slot itself; it is what global::client hands out", ), @@ -307,33 +307,33 @@ const ALLOWED: &[(&str, &str, &str)] = &[ "inline #[cfg(test)] module only; the scanner does not brace-track test blocks", ), ( - "vendor/tinymemory/core/src/store/client.rs", + "vendor/tinymemory/crates/tinymemory-core/src/store/client.rs", ".profile_conn(", "sole in-family call; wraps the raw handle in ProfileStore. profile_conn is pub(in crate::openhuman::memory), so the compiler — not this lint — is the primary enforcement", ), // ── Composio memory sync: profile_store + &MemoryClientRef ── ( - "vendor/tinymemory/core/src/sync/composio/providers/profile.rs", + "vendor/tinymemory/crates/tinymemory-core/src/sync/composio/providers/profile.rs", ".profile_store(", "typed profile writes; the contract has no profile family, so still unguarded", ), ( - "vendor/tinymemory/core/src/sync/composio/providers/profile.rs", + "vendor/tinymemory/crates/tinymemory-core/src/sync/composio/providers/profile.rs", "global::client_if_ready(", "resolved only to reach profile_store()", ), ( - "vendor/tinymemory/core/src/sync/composio/providers/types.rs", + "vendor/tinymemory/crates/tinymemory-core/src/sync/composio/providers/types.rs", "MemoryClient::from_workspace_dir(", "provider trait takes &MemoryClientRef; the contract has no such shape", ), ( - "vendor/tinymemory/core/src/sync/composio/providers/types.rs", + "vendor/tinymemory/crates/tinymemory-core/src/sync/composio/providers/types.rs", "global::client_if_ready(", "same provider trait shape", ), ( - "vendor/tinymemory/core/src/sync/composio/providers/user_scopes.rs", + "vendor/tinymemory/crates/tinymemory-core/src/sync/composio/providers/user_scopes.rs", "global::client_if_ready(", "same provider trait shape", ), @@ -366,22 +366,22 @@ const ALLOWED: &[(&str, &str, &str)] = &[ // `#[cfg(test)]` modules (the #61 connection-guard tests), which the // scanner does not brace-track. ( - "vendor/tinymemory/core/src/engine/sync.rs", + "vendor/tinymemory/crates/tinymemory-core/src/engine/sync.rs", "MemoryClient::from_workspace_dir(", "inline #[cfg(test)] module only; the scanner does not brace-track test blocks", ), ( - "vendor/tinymemory/core/src/engine/sync.rs", + "vendor/tinymemory/crates/tinymemory-core/src/engine/sync.rs", "global::client_if_ready(", "the TinyCortex engine seam; it sits beneath the contract, not above it", ), ( - "vendor/tinymemory/core/src/sync/pipelines/host.rs", + "vendor/tinymemory/crates/tinymemory-core/src/sync/pipelines/host.rs", "MemoryClient::from_workspace_dir(", "inline #[cfg(test)] module only (the connection-guard tests); not brace-tracked", ), ( - "vendor/tinymemory/core/src/sync/pipelines/host.rs", + "vendor/tinymemory/crates/tinymemory-core/src/sync/pipelines/host.rs", "global::client_if_ready(", "the engine-free sync runner's seam over the bound client; beneath the contract, \ the same way the engine seam beside it is", @@ -428,14 +428,24 @@ fn scan() -> BTreeSet<(String, String)> { // the files this lint counts went with it. Scanning only this crate's `src` // would quietly drop them from the tally — which would read as "the // bypasses were cleaned up" rather than "they moved out of view". - collect_rs_files( - &root - .join("vendor") - .join("tinymemory") - .join("core") - .join("src"), - &mut files, + let tinymemory_core = root + .join("vendor") + .join("tinymemory") + .join("crates") + .join("tinymemory-core") + .join("src"); + // `collect_rs_files` returns quietly when a directory is missing, so a + // moved vendor tree would empty this half of the scan and read as "the + // bypasses were cleaned up" — the exact misreading the comment above warns + // about. tinymemory#73 moved this path from `core/src` to + // `crates/tinymemory-core/src` and proved the point. Fail loudly instead. + assert!( + tinymemory_core.is_dir(), + "the vendored tinymemory core is not at {} — it moved again. \ + Point this scan at the new path; do not let the scan run half-blind.", + tinymemory_core.display() ); + collect_rs_files(&tinymemory_core, &mut files); let mut found = BTreeSet::new(); for path in &files { @@ -491,7 +501,7 @@ fn bypass_scanner_finds_the_known_bypasses() { module would pass vacuously. Fix the scanner, not the assertion." ); let canary = ( - "vendor/tinymemory/core/src/store/client.rs".to_string(), + "vendor/tinymemory/crates/tinymemory-core/src/store/client.rs".to_string(), ".profile_conn(".to_string(), ); assert!( diff --git a/vendor/tinymemory b/vendor/tinymemory index 38a34d2ea1..1d6b997874 160000 --- a/vendor/tinymemory +++ b/vendor/tinymemory @@ -1 +1 @@ -Subproject commit 38a34d2ea10e7eedda1b50cdc786016c0f73b6dc +Subproject commit 1d6b997874a06600ba0c4922708b5613497c9ffe