Skip to content

fix(memory): bridge the four defaulted module members instead of refusing - #5808

Merged
M3gA-Mind merged 1 commit into
tinyhumansai:mainfrom
M3gA-Mind:fix/5801-module-bridge-source-sync
Aug 27, 2026
Merged

M3gA-Mind merged 1 commit into
tinyhumansai:mainfrom
M3gA-Mind:fix/5801-module-bridge-source-sync

Conversation

@M3gA-Mind

@M3gA-Mind M3gA-Mind commented Aug 26, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Implements the four module_call! arms the host's module bridge was missing, so they dispatch to the module instead of being answered by a refusing trait default.
  • Fixes the manual "Sync now" / "All in" button, which failed for every source with unsupported capability: source_sync while scheduled sync worked normally.
  • Found four members with this defect, not the one the symptom showed: run_source_sync, bootstrap_connection, is_toolkit_syncable and diagnose.
  • Adds a test that asserts the dispatch itself, with no module required, and revert-checked each of the four independently.
  • Does not touch ARTIFACT_CAPABILITIES or assume_full_capabilities. The capability list was already correct; changing it would have papered over the real gap.

Problem

MemorySourceSync and MemoryMaintenance carry members with default bodies that unconditionally refuse:

// tinymemory-api/src/provider/sync.rs:153
async fn run_source_sync(&self, source_id: &str) -> Result<SyncRunOutcome, MemoryError> {
    let _ = source_id;
    Err(MemoryError::unsupported(Capability::SourceSync))
}

ModuleMemoryProvider implemented every required member and silently inherited the defaults. A defaulted trait member cannot break an implementor at compile time, so when these were added to the contract the bridge kept compiling and began refusing at runtime.

The refusal is raised inside the host and never reaches the wire. In the reported session three sources refused in 13ms total, while a genuine module round-trip in the same session took 30s to time out.

The artifact was never the problem. All four are declared in the module's METHODS list (tinymemory-module/src/lib.rs:770-776) and their wire names are canonical bus constants (tinymemory-bus/src/names.rs:287-300). Before this change:

$ grep -rn "RunSourceSync" src/
(no matches)

Solution

Four module_call! arms following the pattern the neighbouring members already use, placed to mirror the trait's own member order:

member wire name trait default was at
MemorySourceSync::run_source_sync RunSourceSync sync.rs:153
MemorySourceSync::bootstrap_connection BootstrapConnection sync.rs:193
MemorySourceSync::is_toolkit_syncable IsToolkitSyncable sync.rs:227
MemoryMaintenance::diagnose Diagnose records.rs:470

Plus the Diagnosis import diagnose needs. That is the whole production change.

How the siblings were found

Rather than guess, I diffed every trait member carrying a refusing default against what the bridge implements. 17 members across 8 traits have such a default; 13 are implemented; these 4 were not. The other three defaulted MemorySourceSync members and MemoryMaintenance::diagnose were the complete set — no others need a decision.

Blast radius beyond the reported button

All four have live host call sites, all dead before this change:

  • run_source_syncmemory/sources/rpc.rs:574 (per-source Sync) and rpc.rs:1055 (Sources → All in). The reported symptom.
  • is_toolkit_syncablememory/sync/composio/bus.rs:137. The host could not determine whether a toolkit was syncable.
  • bootstrap_connectionmemory/sync/composio/bus.rs:811. First-time bootstrap of a newly authorised connection failed silently.
  • diagnose — the typed maintenance diagnosis an operator or agent reads.

Testing

The test asserts dispatch, not a live module

With the module host disabled, proxy() fails with MemoryError::Other (memory.rs:342-357), while an unbridged member returns MemoryError::Unsupported. Asserting "not Unsupported" therefore asserts that the call went through module_call! at all — which is precisely the thing that was missing — and needs no module, no network and no artifact.

Revert-check, one member at a time

A single combined revert would stop at the first assertion and prove only one member. Each of the four was reverted individually and the failure names that member:

reverted failure
run_source_sync run_source_sync answered from the trait default ... Got Unsupported { capability: "source_sync" }
bootstrap_connection bootstrap_connection answered from the trait default ... Got Unsupported { capability: "source_sync" }
is_toolkit_syncable is_toolkit_syncable answered from the trait default ... Got Unsupported { capability: "source_sync" }
diagnose diagnose answered from the trait default ... Got Unsupported { capability: "maintenance" }

diagnose reporting maintenance rather than source_sync is the check that the test discriminates per member rather than catching one capability generically. The run_source_sync failure reproduces the production error string exactly.

With the fix in place all four pass, and openhuman::modules:: is green at 79 passed / 0 failed. cargo fmt --check and cargo clippy --no-deps --lib are clean.

The trap: no lane can catch this end to end

CI cannot prove this fixed. The lanes run with no module or with a test artifact, which is exactly why the bug reached a user. The test above proves the dispatch exists; it cannot prove the module answers it. The only end-to-end proof is the real app, and the maintainer can confirm it by clicking Sync on Brain → Sources and seeing a non-zero sync_triggered in [memory_sources] apply_all_in_rpc: complete.

Impact

Restores the manual sync trigger, Composio toolkit-syncability checks, first-time connection bootstrap, and the typed maintenance diagnosis. No behaviour change for anything already working: scheduled sync runs inside the module and never crossed this bridge.

Left for a separate decision, deliberately not in this PR

1. GuardedSourceSync and GuardedMaintenance have the identical hole in all four members. It is latent, not reachable: every call site resolves through binding.provider(), which returns the unguarded provider (binding.rs:93, the same field as unguarded_provider), so no current caller reaches it.

I did not fix it here because the guard's forwards are not mechanical — each one must choose admit_write or admit_read, and that is a security-tier decision, not a transcription. Getting it wrong lets a readonly operator trigger a sync that spends money. The current behaviour fails closed (denies), so leaving it is safe; adding a forward with the wrong tier would fail open. My reading, for whoever takes it: run_source_sync and bootstrap_connection are writes (both ingest or persist), is_toolkit_syncable and diagnose are reads.

2. The defaults themselves are the root cause and will hide the next member. The durable fix is to remove the default bodies from these members so the compiler names every implementor that is missing one. That is a breaking trait change in tinymemory-api touching every implementor, so it belongs in its own change with its own review.

3. Nothing in CI compares the artifact's METHODS list against the host's module_call! arms. A test doing that would have caught all four statically. is_compatible has no call sites (grep -rn is_compatible src/ returns two doc comments), but note it would not have caught this: it compares host and artifact capability sets that here already agreed.

Related

Submission Checklist

  • Tests added: the_defaulted_members_dispatch_to_the_module_instead_of_refusing covers all four members. The failure path is the per-member revert-check table above.
  • N/A: diff coverage. The changed lines are four module_call! arms plus one import; all four are executed by the new test, which fails if any is removed.
  • N/A: no feature rows added, removed, or renamed.
  • N/A: no feature IDs affected.
  • No new external network dependencies introduced. The test runs with the module host disabled and dials nothing.
  • N/A: does not touch release-cut surfaces.
  • Linked issue closed via Closes #5801.

Impact (platform)

Desktop. No migration, no schema change, no config change.


AI Authored PR Metadata

Linear Issue

  • Key: N/A
  • URL: N/A

Commit & Branch

  • Branch: fix/5801-module-bridge-source-sync
  • Commit SHA: f9a89b2b8

Validation Run

  • N/A: pnpm --filter openhuman-app format:check — no frontend files changed.
  • N/A: pnpm typecheck — no TypeScript changed.
  • Focused tests: cargo test -p openhuman --lib -- openhuman::modules:: — 79 passed, 0 failed. Plus the four individual revert-checks above.
  • Rust fmt/check: cargo fmt -p openhuman -- --check clean; cargo clippy -p openhuman --no-deps --lib clean.
  • N/A: Tauri fmt/check — no Tauri code changed.

Validation Blocked

  • command: end-to-end verification against the real pinned artifact
  • error: not blocked by a failure — no lane loads the real module, by design
  • impact: the dispatch is proven by test; that the module answers it is provable only in the running app. See the trap note above.

Behavior Changes

  • Intended behavior change: four members now reach the module instead of returning Unsupported.
  • User-visible effect: the manual Sync button works; Composio connection bootstrap and syncability checks work.

Parity Contract

  • Legacy behavior preserved: yes for every already-working path. Scheduled sync is untouched.
  • Guard/fallback/dispatch parity checks: the capability gate is unchanged — as_source_sync() already returned Some and still does. Only the member dispatch changed.

Duplicate / Superseded PR Handling

  • Duplicate PR(s): none
  • Canonical PR: this one
  • Resolution: N/A

Summary by CodeRabbit

  • New Features

    • Added memory maintenance diagnostics.
    • Added source synchronization capabilities, including running syncs, bootstrapping connections, and checking toolkit compatibility.
  • Bug Fixes

    • Memory operations now correctly forward requests and return meaningful errors when the module is unavailable.
    • Coding-session ingestion now allows additional time based on the configured ingestion budget.
  • Tests

    • Added regression coverage for memory diagnostics and source synchronization behavior.

@M3gA-Mind
M3gA-Mind requested a review from a team August 26, 2026 21:46

@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

@tinysweeper tinysweeper Bot added the priority: p3 Whenever. Cosmetic, a nicety, or a cleanup with no user visible effect. label Aug 26, 2026
@coderabbitai

coderabbitai Bot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Important

Review skipped

No new commits to review since the last review.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 54a11928-4a57-4196-838b-dd989eb27f8b

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 09770f7a-fd0b-4115-943e-b4654726795f

📥 Commits

Reviewing files that changed from the base of the PR and between f9a89b2 and 4404c8f.

📒 Files selected for processing (2)
  • src/openhuman/modules/memory.rs
  • src/openhuman/modules/memory_tests.rs

Included review availability: Your plan provides up to 10 included reviews per hour; 3 remain after this review.


📝 Walkthrough

Walkthrough

The memory provider now forwards diagnosis and source-sync operations through the module bus. Coding-session ingestion uses a budget-based timeout with a 30-second grace period. A disabled-host regression test covers the forwarded methods.

Changes

Memory provider forwarding and ingestion timing

Layer / File(s) Summary
Provider bus forwarding
src/openhuman/modules/memory.rs, src/openhuman/modules/memory_tests.rs
The provider forwards diagnose, run_source_sync, bootstrap_connection, and is_toolkit_syncable through module_call!. The test confirms these methods do not return trait-default Unsupported errors when the module is disabled.
Budget-based ingestion timeout
src/openhuman/modules/memory.rs
ingest_coding_sessions now uses ingest_budget(request.max_sessions) plus INGEST_BUS_GRACE, which is set to 30 seconds.

Estimated code review effort: 2 (Simple) | ~10 minutes

Merge Risk: ⚪ Minimal · up to 4404c

This is a localized bridge fix that routes four previously refused calls to the module; the reported tests and checks are clean, and no actionable merge-blocking risk remains beyond normal review.

Suggested reviewers: senamakel

Poem

A rabbit sends diagnosis through the memory hall,
Source sync answers each careful call.
Coding sessions gain time to complete,
Thirty seconds make the deadline sweet.
The module bus keeps every path neat.

🚥 Pre-merge checks | ✅ 2 | ❌ 3

❌ Failed checks (3 warnings)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The PR implements the three required ModuleMemoryProvider source-sync bridge calls from issue #5801 and preserves scheduled synchronization. It does not implement the required forwarding methods for G… Add forwarding implementations for RunSourceSync, BootstrapConnection, and IsToolkitSyncable in GuardedSourceSync, or update the linked issue and obtain explicit approval to defer that requirement.
Out of Scope Changes check ⚠️ Warning The PR includes changes outside issue #5801, including forwarding MemoryMaintenance::diagnose and changing the coding-session ingestion timeout. These changes are not part of the linked issue's manual… Remove the unrelated diagnose and coding-session timeout changes, or link the relevant requirements and explain why they belong in this PR.
Docstring Coverage ⚠️ Warning Docstring coverage is 22.22% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 9 functions across 2 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: forwarding four defaulted memory module members instead of returning Unsupported.
Full details: Linked Issues check

Explanation

The PR implements the three required ModuleMemoryProvider source-sync bridge calls from issue #5801 and preserves scheduled synchronization. It does not implement the required forwarding methods for GuardedSourceSync.

Full details: Out of Scope Changes check

Explanation

The PR includes changes outside issue #5801, including forwarding MemoryMaintenance::diagnose and changing the coding-session ingestion timeout. These changes are not part of the linked issue's manual source-sync bridge fix.


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

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f9a89b2b84

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

module_call!(self, "purge_all", "PurgeAll", ())
}
async fn diagnose(&self) -> Result<Diagnosis, MemoryError> {
module_call!(self, "diagnose", "Diagnose", ())

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Use contract constants for the bridged members

The four new dispatches hard-code "Diagnose", "RunSourceSync", "BootstrapConnection", and "IsToolkitSyncable" even though these members have canonical constants in the module contract. The disabled-host test fails before .call(...), so it cannot detect a misspelling or an upstream rename; such drift will compile successfully and surface only as MemberNotFound in deployed module-backed flows. Import and use the contract constants for all four calls instead.

AGENTS.md reference: AGENTS.md:L241-L243

Useful? React with 👍 / 👎.

coderabbitai[bot]
coderabbitai Bot previously approved these changes Aug 26, 2026
…sing

`MemorySourceSync::run_source_sync`, `bootstrap_connection` and
`is_toolkit_syncable`, and `MemoryMaintenance::diagnose`, each carry a default
body that returns `Unsupported`. `ModuleMemoryProvider` implemented every
required member and silently inherited all four defaults, so each call was
answered by the default rather than dispatched to the module.

A defaulted trait member cannot break an implementor at compile time, which is
why this was invisible: when the members were added to the contract the bridge
kept compiling and began refusing at runtime.

The pinned artifact serves all four. They are declared in the module's METHODS
list (tinymemory-module/src/lib.rs:774) and their wire names are canonical bus
constants (tinymemory-bus/src/names.rs:287-300). The host simply never sent the
call: before this change `grep -rn RunSourceSync src/` returned nothing.

Symptom: the manual "Sync now" / "All in" button failed for every source with
`unsupported capability: source_sync`, while the module's own scheduler kept
ingesting normally because it runs inside the module and never crosses this
bridge.

The capability list is untouched. It was already correct: `as_source_sync()`
returned `Some` and the refusal came one call later.

Closes tinyhumansai#5801
@M3gA-Mind

Copy link
Copy Markdown
Collaborator Author

Rebased onto 5630b00db. Conflict was with #5803 and is resolved.

What conflicted: only memory_tests.rs, and only because both sides appended at the end of the file and shared the trailing );/}. memory.rs auto-merged cleanly — #5803 edits ingest_coding_sessions in the MemoryCodingSessions impl, my four arms are in MemoryMaintenance and MemorySourceSync. No semantic overlap. Both sides' tests are kept and all pass: 81 in openhuman::modules::, including the_ingest_bus_deadline_always_outlasts_the_rpc_budget, the_ingest_bus_grace_is_wide_enough_to_order_the_two_timers and the_defaulted_members_dispatch_to_the_module_instead_of_refusing. fmt and clippy clean.


But #5803 surfaces a real problem with run_source_sync, and I have not fixed it here

#5803 gave IngestCodingSessions a derived bus deadline because tinybus' flat 30 s DEFAULT_TIMEOUT was abandoning a healthy 35 s import. run_source_sync has the same defect, and worse odds.

From the app session that produced #5801, the syncs that succeeded took:

source items duration
Gmail ca_ml7K8z4dTbIB 250 1m 24s
GitHub ca_tnftuGIRcr_I 979 1m 17s

Both roughly 3x the 30 s default. And unlike ingest_coding_sessions, source sync has no RPC-level budget at all — neither sync_rpc (sources/rpc.rs:563) nor apply_all_in_rpc (:1023) wraps the call in tokio::time::timeout. The flat 30 s is the only deadline in the system.

So once this PR lands, a real Sync will dispatch to the module, the module will sync correctly, and the caller will be released at 30 s with a timeout error while the work completes at ~80 s. That is #5802's shape exactly, and #5803's own comment says why it cannot be waved off: "A timeout does not cancel the remote work — tinybus cannot — it stops waiting and frees the caller."

This is still strictly better than today (the sync currently never runs at all), so it is not a reason to hold this PR. But it means clicking Sync may still show a failure for a sync that succeeded, and whoever verifies should expect that rather than read it as this fix not working.

I did not fix it here on purpose. The fix needs a budget to derive from, and there is no ingest_budget equivalent for source sync — sizing one means deciding how long a user should wait before being told a sync is still running, which is a product call, not a transcription. Inventing a constant tuned to the two durations above would be a heuristic fitted to one session's data.

Recommended shape, mirroring what #5803 established:

  1. a sync_budget() in memory::sources::rpc sized to the work (source kind and/or item count), used as the RPC-level tokio::time::timeout so the clean structured message wins;
  2. run_source_sync's bus deadline derived as sync_budget() + a grace, reusing INGEST_BUS_GRACE or a sibling, so the two cannot drift.

bootstrap_connection plausibly needs the same treatment (it fetches a profile and registers triggers). is_toolkit_syncable and diagnose are quick reads and are fine on the default.

Happy to file this as its own issue, or to implement it here if you would rather it ship together — say which.

@M3gA-Mind

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor
⚠️ Action not completed

Already reviewed the last commit. Use @coderabbitai full review to rerun a review of the entire changeset.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@M3gA-Mind
M3gA-Mind merged commit e544834 into tinyhumansai:main Aug 27, 2026
28 of 30 checks passed
M3gA-Mind added a commit to M3gA-Mind/openhuman that referenced this pull request Sep 2, 2026
…memory sources

Two e2e gaps found in the coverage audit of recently merged PRs. Both paths
could break completely today without a single lane going red.

tinyhumansai#5808 / tinyhumansai#5801 — `MemorySourceSync::run_source_sync` is a DEFAULTED contract
member. `ModuleMemoryProvider` inherited its `Unsupported` body instead of
bridging, so "Sync now" answered `unsupported capability: source_sync` on a
build whose module could sync fine. A defaulted member that was never bridged
is indistinguishable from a bridged one at compile time, which is why it
shipped — so the new test asserts the RUNTIME answer.

The discriminator: `binding::build` binds `module_provider` whenever the
`modules` feature is on, so this RPC really does reach the bridged member. An
unbridged member refuses the capability BEFORE any transport is attempted; a
bridged one gets as far as the module. Those two failures differ in the
message, and only the second is correct.

tinyhumansai#5725 — `reset_tree` and `flush_now` were routed through
`Maintenance::reset_derived_index` / `flush_pending`. Nothing exercised either
afterwards: in the raw-coverage lane both names appear only as string literals
fed to `memory::schema::schemas(...)`, and in `worker_c_modules_e2e.rs` they
sit in a 68-method loop whose helper passes on an error response. The new test
drives both RPCs and asserts they reach a driver that serves Maintenance,
keying on the host-side `"does not serve Maintenance"` refusal — the one
failure produced before any driver call, so it is what proves the hop happened.

Neither test asserts success. That would need a live module artifact fetched
over the network, which this lane must not depend on; the bugs these pin were
never "wrong data" but "the call is refused before it is attempted".

Revert-checked, both:

  run_source_sync bridge removed  -> FAILED at memory_sources_e2e.rs:952,
    "Got: unsupported capability: source_sync" (the tinyhumansai#5801 string verbatim)
  as_maintenance() -> None        -> FAILED at memory_sources_e2e.rs:1029,
    "Got: flush_now: driver 'tinymemory' does not serve Maintenance"

Both restored afterwards; the fix files are byte-identical to main.
M3gA-Mind added a commit to M3gA-Mind/openhuman that referenced this pull request Sep 2, 2026
…memory sources

Two e2e gaps found in the coverage audit of recently merged PRs. Both paths
could break completely today without a single lane going red.

tinyhumansai#5808 / tinyhumansai#5801 — `MemorySourceSync::run_source_sync` is a DEFAULTED contract
member. `ModuleMemoryProvider` inherited its `Unsupported` body instead of
bridging, so "Sync now" answered `unsupported capability: source_sync` on a
build whose module could sync fine. A defaulted member that was never bridged
is indistinguishable from a bridged one at compile time, which is why it
shipped — so the new test asserts the RUNTIME answer.

The discriminator: `binding::build` binds `module_provider` whenever the
`modules` feature is on, so this RPC really does reach the bridged member. An
unbridged member refuses the capability BEFORE any transport is attempted; a
bridged one gets as far as the module. Those two failures differ in the
message, and only the second is correct.

tinyhumansai#5725 — `reset_tree` and `flush_now` were routed through
`Maintenance::reset_derived_index` / `flush_pending`. Nothing exercised either
afterwards: in the raw-coverage lane both names appear only as string literals
fed to `memory::schema::schemas(...)`, and in `worker_c_modules_e2e.rs` they
sit in a 68-method loop whose helper passes on an error response. The new test
drives both RPCs and asserts they reach a driver that serves Maintenance,
keying on the host-side `"does not serve Maintenance"` refusal — the one
failure produced before any driver call, so it is what proves the hop happened.

Neither test asserts success. That would need a live module artifact fetched
over the network, which this lane must not depend on; the bugs these pin were
never "wrong data" but "the call is refused before it is attempted".

Revert-checked, both:

  run_source_sync bridge removed  -> FAILED at memory_sources_e2e.rs:952,
    "Got: unsupported capability: source_sync" (the tinyhumansai#5801 string verbatim)
  as_maintenance() -> None        -> FAILED at memory_sources_e2e.rs:1029,
    "Got: flush_now: driver 'tinymemory' does not serve Maintenance"

Both restored afterwards; the fix files are byte-identical to main.
M3gA-Mind added a commit to M3gA-Mind/openhuman that referenced this pull request Sep 2, 2026
…memory sources

Two e2e gaps found in the coverage audit of recently merged PRs. Both paths
could break completely today without a single lane going red.

tinyhumansai#5808 / tinyhumansai#5801 — `MemorySourceSync::run_source_sync` is a DEFAULTED contract
member. `ModuleMemoryProvider` inherited its `Unsupported` body instead of
bridging, so "Sync now" answered `unsupported capability: source_sync` on a
build whose module could sync fine. A defaulted member that was never bridged
is indistinguishable from a bridged one at compile time, which is why it
shipped — so this asserts the RUNTIME answer.

The discriminator: `binding::build` binds `module_provider` whenever the
`modules` feature is on, so this RPC really does reach the bridged member. An
unbridged member refuses the capability BEFORE any transport is attempted; a
bridged one gets as far as the module.

tinyhumansai#5725 — `reset_tree` and `flush_now` were routed through
`Maintenance::reset_derived_index` / `flush_pending`. Nothing exercised either
afterwards: in the raw-coverage lane both names appear only as string literals
fed to `memory::schema::schemas(...)`, and in `worker_c_modules_e2e.rs` they
sit in a 68-method loop whose helper passes on an error response.

This commit also carries the two review findings raised on the PR, which were
both correct and were fixed in a follow-up now folded in by the rebase:

  - `sources_sync_...` excluded only "unsupported capability" and
    "source_sync". The other pre-dispatch refusal — `sync_rpc` bailing with
    "the bound memory driver '<id>' does not serve source sync"
    (`memory/sources/rpc_part_01.rs:560-564`) — spells it with a SPACE, so it
    matched neither string and the test passed green while `run_source_sync`
    was never reached. Now rejected. Proven: forcing
    `ModuleMemoryProvider::as_source_sync()` to `None` fails the new assertion
    with the real message; before the change that same revert passed.
  - `tree_reset_and_flush_...` excluded one string, so a renamed or removed RPC
    answered `unknown method: <name>`, contained no "does not serve
    Maintenance", and passed without dispatching. Now rejected, plus a check
    that the response is a result or an error rather than neither.

Neither test asserts success. That would need a live module artifact fetched
over the network, which this lane must not depend on; the bugs these pin were
never "wrong data" but "the call is refused before it is attempted".

Rebased onto edee560. The conflict with the merged relative-folder-path
tests (tinyhumansai#5959) was textual, not semantic: both sides append independent tests to
the tail of this file and share the same setup boilerplate, which is what git
interleaved. Resolved by taking main's file whole and appending these two
tests, so both sets survive intact.
senamakel pushed a commit to nocstah/openhuman that referenced this pull request Sep 11, 2026
…ridge-source-sync\n\nfix(memory): bridge the four defaulted module members instead of refusing\n
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

2 participants