Independent review of the plugin host found eight defects; each is fixed here and
the reproducible ones are covered by two new invariant tests (red on the previous
head, green now).
- Async plugin code: `await ctx.<facade>.<async method>` works (the facade probe
reports coroutine methods and the host returns a coroutine function), and ctx
calls made from coroutines keep the caller's session. The wire origin is now a
ContextVar carried onto host event-loop tasks, and the host's fallback context
starts empty instead of copying whichever caller created the host.
- Memory / context-engine / cron providers survive a host crash: proxies record
the host generation, and a category proxy reloads its plugin into the new host
on next use (bounded by the same restart budget). A proxy from an earlier host
can no longer address a recycled object id.
- Hosted provider objects no longer leak: the host imports a category plugin's
module once and drops objects whose Hermes proxies were collected.
- Every public attribute of a hosted object is read live (class-level defaults
included), and attributes Hermes assigns reach the plugin's object unless they
hold a live handle.
- A user memory provider's config_schema.py runs in the plugin host.
- Dashboard plugin APIs resolve the plugin in the requesting profile (its copy,
its plugins.enabled, its host) and keep repeated headers such as Set-Cookie.
- platform_actions coroutines run on the gateway loop their adapters use.
- Each incoming request gets its own thread (no pool exhaustion under nested
callbacks); a late close from a replaced host no longer triggers a reload; the
model-provider extraction cache is keyed by full path.