Route isolated vector-search children through one private host entrypoint for the existing SQLite, sqlite-vec and text helpers.
Preserve the contributor repair, query results, cancellation, admission and index-publication behavior. Matched native-child measurements improve by 86.3%; real Gateway calls and independent behavior validation confirm the improvement with unchanged results.
Co-authored-by: Ayaan Zaidi <hi@obviy.us>
Five copies of the same in-memory one-shot ticket (48-hex token, 60 s TTL,
unref'd expiry timer, single-use consume) and seven copies of "write a raw
HTTP status and destroy the socket" had accumulated across the desktop
observer bridge, the node desktop/portal stream broker, sandbox noVNC auth,
the browser extension relay, the browser screencast, voice-call realtime
upgrades, and core upgrade routing. The browser screencast also hand-rolled
the ping/pong keepalive that core already owned.
One shared store now owns ticket generation, shape checks, timers, and
expiry callbacks; one helper writes upgrade rejections (flushing before
destroy) for every status the callers use; the keepalive helper takes a
structural socket so plugins need no `ws` types. Bundled plugins reach all
three through the private-local `openclaw/plugin-sdk/websocket-runtime`
subpath, which keeps the public SDK surface budget unchanged.
Migrated sites: src/gateway/desktop/observe-bridge.ts,
src/gateway/desktop/node-stream-broker.ts, src/agents/sandbox/novnc-auth.ts,
src/gateway/server/plugins-http.ts, src/gateway/server-http-upgrades.ts,
src/gateway/server/http-work-admission.ts,
extensions/browser/src/browser/screencast/{tokens,upgrade}.ts,
extensions/browser/src/browser/extension-relay/{relay-server,gateway-relay-route}.ts,
extensions/voice-call/src/webhook/realtime-handler.ts.
Deliberately unchanged: the artifact-transfer capability tokens (revocable
serving authority, 43-char base64url contract), the Mattermost client
keepalive (own ping/pong deadlines and reconnect coupling), and the diffs
plugin's persistent hashed artifact tokens. The voice-call 401 rejection now
also sends `Connection: close`; relay upgrade sockets gain an error guard so
a client reset during rejection cannot surface as an unhandled error.
Preserve requester revocation with shared-store revokeSignal and listener cleanup.
* fix(gateway): reduce cold model-runtime request stalls
Bind provider/auth/config operations at the native plugin loader boundary
instead of importing broad host execution graphs during registration.
Keep descriptor construction light and defer execution-only Codex/OpenAI
work to its canonical owners without changing synchronous auth, process,
logging, or lifecycle semantics.
Preserve full runtime readiness, authored cache/override identity, mutable
runtime method views, and invocation-bound latest session lineage. Remove
obsolete wrappers and the unused eager conversation startup path.
The isolated source reproduction reduced prepared refresh from roughly
291 seconds to 17 seconds on the same historical Linux proof setup. The
latest integrated ARM64 profile still measures 19 seconds; this does not
claim that all cold source-registration blocking is eliminated. Compiled
Gateway/browser catalog proof returned in 568 ms.
Protected Gateway/browser tests use fresh secretless VM/containers only.
No timeout/assertion, configuration, schema, dependency, or SDK budget
expansion. New private host seams require coordinated host/plugin release,
not independent publication with an older compatibility floor.
Refs #139867
* fix(plugins): finish native runtime import boundaries
Keep unused native policy facets lazy, use canonical type and profile-ID leaves, and reuse SDK lazy-method forwarding. Remove obsolete provider wrappers and repair lifecycle/catalog fixtures without weakening assertions or deadlines.
Validated with the original 273-file CLI selection (6841 passed, 85 skipped), the complete changed gate in a fresh secretless container, the final build, and isolated review. Context: #139911 and #139867.
* test(doctor): supply native auth in memory startup fixture
Register the real OpenAI plugin with the host model-auth contract while preserving all semantic-data, migration, SecretRef, and degraded-owner assertions. Both cases and the original 259-case CI shard pass in a fresh secretless container; typed lint and isolated review pass. No production changes.
* refactor: simplify command rendering and diagnostic plumbing
* refactor(providers): share exact effort profile parsing
Keep model overrides and API fallbacks in their provider owners. The shared helper has no runtime imports so eager policy loading retains its narrow dependency graph.
Official plugin packages gain a host runtime dependency. Publish this with the next synchronized core and plugin release, whose canonical release sync advances pluginApi floors; do not publish these plugins alone with the existing older API floor.
* chore: prune removed provider assertion allowances
* fix(talk): avoid full plugin imports during cold catalog discovery
Use optional capability catalog entries backed by the same provider factories and native host operations as full registration. Preserve prepared generations, active descriptors, installed-plugin registration, and explicit empty-family semantics. Account for exactly three approved public catalog type exports.
* fix(plugins): complete cold catalog boundary integration
Keep catalog descriptors separate from native host-operation types, and
move DeepInfra shared model types and constants to their leaf owner.
Recognize manifest-loaded catalog entrypoints and remove the unused xAI
transcription wrapper while retaining the production factory tests.
Preserve real module exports under existing test overrides. Keep all
assertions, deadlines, public SDK exports, and approved budgets unchanged.
* feat: let plugins customize the Control UI
* fix: harden feature plugin lifecycle and artifact activation
* fix(plugins): complete native UI integration
* fix(plugins): preserve hook ownership and composer styling
* chore(workboard): refresh generated browser assets
* test(android): hold reconciliation replies until delivery checks
* refactor(plugins): simplify feature UI ownership
Share bundle validation and scoped host-handle cleanup. Consolidate
Workboard component and draft-save lifecycles, and remove unreachable
loading/enablement paths and retired select styles.
Keep both compiler regression matrices through shared fixtures, remove
duplicate tests, and regenerate the reduced locale catalog and browser
asset references.
* test(ui): return session snapshots from worker stop fixtures
* fix(ui): hydrate session rosters from selected agents
Use the application selection owner for bootstrap and reconnect, retain its filtered query for later refreshes, and remove duplicate sidebar refreshes. Cover delayed bootstrap, saved selection, and offline selection changes.
Refresh generated protocol and browser assets after the rebase, and share hydration fixtures and roster reconciliation helpers.
* perf(ui): defer plugin initialization and customization
Load plugin assets with the existing lazy SDK host and load customization controls on demand. Keep activation cleanup with the runtime and preserve dialog reload state across close and reopen.
Remove retired Workboard selectors, move glyph styling into the plugin, and regenerate its browser revision. Preserve the existing startup payload limits.
* refactor(ui): separate native asset loading from host services
* test(plugins): align UI integration with current main
Refresh canonical Workboard assets and the Control UI boot inventory after rebasing. Match the current bootstrap signature, delegated permission policy, and widget Delete label in existing regressions.
* chore(workboard): refresh browser revision after rebase
* chore(ui): refresh generated assets after main sync
* fix(plugins): preserve native UI lifetimes after main sync
Keep saved plugin panels closable while their registration is unavailable and prevent actions withdrawn during resolution from starting. Defer native view mounting code through plugin activation while preserving synchronous built-in rendering.
Integrate the shared Dashboard side-panel lifecycle, remove the session helper type cycle, reuse core Gateway classification, and consolidate menu coverage. Refresh generated assets after the main rebase.
Validated with focused Gateway/UI tests, failing/passing lifetime regressions, 14 browser scenarios, typechecks, lint, cycle and assertion guards, and the enforced Control UI performance check.
* chore(ui): refresh boot manifest after main rebase
* chore(ui): refresh feature integration after main update
Preserve current composer admission and sidebar ownership while adopting the canonical formatter output and browser assets. Complete the existing panel fixture with the new desktop-focus contract.
* test(ui): verify native plugin asset admission
* test(ui): await service worker activation in phone proof
* refactor(plugins): remove redundant UI plumbing
* feat(plugins): gate custom UI behind an experimental lab
* fix(plugins): align Labs helper types with callers
* style(ui): format retained plugin panel definitions
* test(ui): preserve minimized dashboard in native plugin flow
* fix: preserve plugin UI edits and refresh ordering
Synchronize reapplied template fields, fence shared widget reads across moves, and retain newer mutation errors through queued refreshes. Verify immutable browser assets when Windows reports a directory collision. Keep the checkout helper terminal exit outside exception handlers to avoid Python 3.9 context-cycle hangs.
* test: align plugin UI proof with current panel layout
* test: repair plugin UI validation and generated checkout helper
* test: bind session search fixtures to their selection owner
* fix: preserve session search ownership and execution denial proof
* test: use a real page element for plugin sidebar fixtures
* fix: respect native plugin UI deployment boundaries
* test: share UI fixture isolation across runners
* refactor: share the native plugin asset root
* test: check failure trailers on their owning stream
* fix(models): refresh Chutes and Cerebras native pricing
Use owner-native advertised rates without pinning generated model costs during merge-mode setup. Preserve metadata when native prices disappear, reject malformed feeds, and keep explicit user rates intact. Fixes#134248.
* chore: clean up pricing tests and isolated landing workflow
Remove unused Chutes fake-timer plumbing. Select a complete, writable landing checkout before native review and preserve generated review identity stamps without weakening isolation or merge guards.
This reverts commit 5d7bd83a4a.
Roll back PR #113115 at maintainer request, restoring the previous Matrix and runtime behavior while preserving subsequent main changes. Retain only the publication-safe synthetic model name in an existing test fixture.
* feat(matrix): add intelligent multi-agent turn-taking
* fix(matrix): enforce receiver context and finalization ownership
Resolve Matrix context visibility through each live receiver and intersect classifier context without duplicating the transport journal. Invalidate monitor-bound decisions, preserve native thread correlation, and bound the complete classifier request.
Keep CLI runtime-binding failures terminal, publish validated replacements atomically, clean failed preparations, and preserve intentional discard semantics. Add regressions for policy isolation, lifecycle changes, input bounds, and runtime drift.
Co-authored-by: Benjamin Badejo <ben@benbadejo.com>
* test(matrix): align finalization coverage with main
Extract receiver access preparation into its existing owner and preserve source-finalization assertions in a focused suite. Update stale nested activity fixtures and normalize concurrent gate results.
Co-authored-by: Benjamin Badejo <ben@benbadejo.com>
* fix(matrix): stream provisional previews before freshness review
Keep source-owned preview callbacks live during generation while committed
assistant events and block replies remain behind terminal acceptance.
Preserve global finalization hook buffering and avoid replaying previews
when deferred events drain.
Cover the real preparation/subscription boundary for local continue,
redraft and discard plus global-hook quarantine. Repair the Matrix access
type declaration and rebalance complete CLI test families under the
existing type-shard limit.
Co-authored-by: Benjamin Badejo <ben@benbadejo.com>
* fix(agents): settle transcript projection before finalization retries
Reuse the existing owned-retry projection barrier after rejecting a final candidate. Cover both global and source-local finalization alongside compaction, and clarify Matrix preview behavior with global finalization hooks.
Co-authored-by: Benjamin Badejo <ben@benbadejo.com>
* fix(codex): restrict native tools during finalization retries
Apply the existing native tool policy and MCP attestation to ordinary
tools-disabled retries while preserving their lifecycle and Stop hooks.
Keep strong policy modes isolated and reuse the prepared restriction in
start/resume verification. Cover inherited MCP, managed requirements,
transient bindings, restored tools, and authoritative finalization.
Clarify external-tool isolation versus native compute in Matrix docs and
keep the projection retry fixture aligned with the literal revision type.
Co-authored-by: Benjamin Badejo <ben@benbadejo.com>
* test(codex): align native lifecycle fixtures with tool policy
Use ordinary tool-enabled startup, schema and cleanup fixtures. Preserve
the shared web-disabled cleanup configuration and expect no app-policy
fingerprint when no plugin policy is configured. Keep restriction,
cleanup, cancellation and retry assertions intact without larger timeouts.
Consolidate adjacent native planning defaults without changing their
values, property order or precedence, and remove a shadowed test binding.
Co-authored-by: Benjamin Badejo <ben@benbadejo.com>
---------
Co-authored-by: Benjamin Badejo <ben@benbadejo.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
* fix(browser): preserve controlled document navigation authority
* fix(browser): checkpoint relay lifecycle and cold-start repair
Preserve the reviewed browser repair candidate before refreshing main and finalizing the private Gateway configuration SDK boundary. Validation and real browser proof remain pending; this checkpoint is not a land-ready claim.
* fix(browser): isolate native bootstrap configuration imports
Use a private Gateway config runtime facade for bundled port lookups while preserving the shipped public core export. Keep private declarations out of the package and finish the relay auth-test cleanup check.
* test(browser): align bootstrap script contract with native build
* test(voice-call): await notification hangups before teardown
* fix(browser): unblock compiled native-host bootstrap
Load canonical config and pairing only after native-host validation. Keep
pure Browser URL and port helpers out of transport and mixed runtime
barrels, register the existing private CDP SDK export, and remove obsolete
bridge exports.
Run the extracted compiled-host integration case in the existing artifact
CI job with exact report validation. Preserve the custom installation
context, native framing, private Node trampoline, and 10-second deadline.
* fix(build): map private Browser SDK declarations
Complete browser-cdp registration in the shared plugin package-boundary
paths and XAI's matching override. Keep the SDK JavaScript-only in the
published package while using package-built declarations inside the repo.
The unchanged package-boundary contract reproduced the missing mapping
before this fix. No native-host runtime, fixture, assertion, or deadline
changes are included.
* feat(channels): introduce bots when they join group rooms
* feat(channels): add Discord and Telegram join introductions
* fix(channels): isolate untrusted evidence and select allowed join targets
* refactor(channels): scope joinIntro to implementing channels
* fix(channels): keep a delivered join introduction settled when its durable commit fails
* feat(channels): read more room history and document join introductions in detail
* chore(config): regenerate bundled channel metadata after rebase
* perf(plugins): keep provider policy artifacts on leaf module graphs
Provider policy artifacts (provider-policy-api.js) load eagerly whenever a
provider is resolved, but five of them imported the provider-model-shared
barrel at runtime, dragging the transports/compat/state graph into every
policy load. In contexts without a native TS require hook (Vitest workers,
non-tsx source runs) jiti compiled that whole graph: ~65s of event-loop
starvation on the first embedded run, which is what pushed
run.session-permissions.test.ts past its 120s timeout before #129582.
Add openclaw/plugin-sdk/claude-model-runtime, a narrow family-level and
local-only subpath re-exporting the Claude identity/thinking helpers from
their leaf owners (@openclaw/llm-core, plugins/provider-claude-thinking).
Switch anthropic, anthropic-vertex, and opencode policy artifacts to it, and
amazon-bedrock plus ollama to the already-plugin-visible
@openclaw/model-catalog-core leaves. The barrel keeps re-exporting the same
symbols, so no existing consumer changes.
Measured on the embedded-runner host route (first run, Vitest worker):
65540ms -> 6627ms; jiti self-time 23.4s -> 1.3s, statSync 18.6s -> 0.7s.
run.shared-integration.test.ts drops from 167s to 65s as a side effect.
Also pin run.inherited-auth-owner.test.ts to the mocked plugin-harness route
(its assertions are provider-agnostic; 37.6s -> sub-second test time) and
document the no-provider default-route trap on overflowBaseRunParams.
Follow-up to #129582.
* chore(plugins): register claude-model-runtime boundary aliases
The extension package boundary contract requires every local-only plugin-sdk
entrypoint to carry a d.ts path alias in the shared boundary map and xai's
derived override set; CI's contracts-plugin lane caught the missing entries.
* chore(release): exclude claude-model-runtime declarations from the pack
Local-only plugin-sdk entrypoints ship runtime .js only; the release check
derives the required pack exclusion from the local-only registry and CI's
core-tooling lane caught the missing package.json files entry.
* test(agents): assert the mocked harness route in auth-owner proof
ClawSweeper P2: without the agentHarnessId assertion a silent fall-back to
the built-in host harness would still pass the auth-owner assertions while
proving the wrong route; fail loudly like run.session-permissions.test.ts.
* refactor(plugins): retire deactivate hook alias
* refactor(plugin-sdk): prune retired facade exports
* test(logging): isolate logger test controls
* refactor(logging): internalize file transport controls
* test(plugin-sdk): preserve retired facade coverage
* test(auto-reply): remove stale diagnostic imports
* refactor(logging): delete dead config-read guard
shouldSkipMutatingLoggingConfigRead had no production caller even on main;
it survived the dead-export scan only via logger's testApi re-export. The
test-isolation commit removed that mask, exposing the fossil. Delete the
guard, its test-only re-export, its mock entry, and its dedicated test file.
* refactor(plugin-sdk): retire due compatibility subpaths
* test(plugin-sdk): type group policy predicates
* refactor(plugin-sdk): split removed subpath records
* refactor(secrets): remove retired collector barrel
* test(plugin-sdk): tighten wildcard surface pin
* refactor(plugin-sdk): retire matrix facade metadata
* style(plugin-sdk): format facade metadata
* fix(ci): load channel setup contracts from source
Repair the main-owned regression from 99d662473c (Peter Steinberger): the new env-contract test could consume stale ignored dist metadata instead of the checked-in plugin declaration.
* test(plugin-sdk): refresh API baseline after rebase
* perf(doctor): keep telegram doctor enumeration off the runtime graph
Telegram's built doctor artifact reached execa through dist chunking, so a
source-run host (pnpm dev, tsx CLI, vitest) could not require it and silently
dropped all 9 telegram legacy config rules plus its state migration. The
artifact also pulled telegram's runtime stores, making it a 674-chunk outlier
that dominated doctor enumeration.
Root cause: `src/token.ts` took the broad `plugin-sdk/provider-auth` barrel for
`resolveDefaultSecretProviderAlias`, dragging the auth-profile store, provider
runtime, and plugin install graph (execa, kysely, commander) into the closure.
The alias now has a narrow `plugin-sdk/secret-provider-alias` leaf, and
provider-auth re-exports it so its runtime surface is unchanged.
Thread-binding, sent-message, and sticker-cache row shapes, keys, and legacy
sidecar readers move to `*.legacy-state.ts` leaves. The doctor closure keeps
the rows and drops the ACP, session-binding, send, logger, and plugin-runtime
graphs the stores also load.
The postbuild control-plane verifier only required each artifact in a plain
Node child, the one host where these graphs resolve fine, so it proved nothing
about the invariant that broke. It now also walks each built doctor artifact's
static import closure and fails when it reaches the process-spawn graph, which
is the dist-level analogue of the source closure guard.
Guard rules added for provider-auth, acp-runtime, and conversation-runtime; the
telegram boundary test became a real closure assertion instead of a string grep.
* fix(doctor): drop dead export surface from the telegram legacy-state split
Knip and oxlint caught leftovers from the split: the leaves exported helpers
only they use, the store modules re-exported constants nobody imports from them
anymore, and thread-bindings kept a `testing` barrel whose last production
caller was the migration path that now reads the leaf directly. Tests import the
constants from the leaf that owns them, and the reset helper directly.
The closure gate's failure message still interpolated a `host` field left over
from a probe-host approach that was reverted before commit; the existing verifier
test caught it. The gate now has its own coverage: a transitive chunk edge to a
forbidden dependency is reported, while dynamic imports and non-doctor contract
surfaces are not.
* fix(doctor): adopt the upstream telegram thread-binding store split
`main` landed an equivalent thread-binding leaf as `thread-bindings-store.ts`
while this branch was open, so the branch-local `thread-bindings.legacy-state.ts`
is dropped rather than kept as a second path for the same rows.
`state-migrations.ts` now reaches token.js through the lazy import `main` added,
so `token.ts` is no longer in the doctor closure at all. The narrow
`secret-provider-alias` leaf still matters: telegram's contract-api closure
reaches `provider-auth` through `token.ts` on current `main`, which is the same
execa/kysely/commander graph, so the barrel is repaired at its source instead of
being deferred a second time.
* fix(scripts): type the built doctor closure gate for the TypeScript migration
The gate was authored against the `.mjs` script and landed in the `.mts` file
`main` migrated to, so its parameters were implicitly `any` and `check:test-types`
failed. Adds the explicit signatures plus the violation type.
Regenerates the plugin-sdk API baseline: `provider-auth` re-exports the default
secret-provider alias from the new leaf, so its module hash moves while its
runtime export surface stays identical.
* refactor(plugin-sdk): delete the heavy runtime-doctor barrel
Nothing may pull the state-db/kysely graph through a doctor barrel anymore.
The barrel's remaining heavy exports move to two narrow private-local
subpaths, each with a single purpose:
- doctor-repair-runtime: install-path diagnosis, plugin config removal, and
state-database schema detect/repair (matrix doctor, voice-call lazy import)
- plugin-state-store-runtime: the sync keyed-store factory. It stays out of
plugin-state-runtime because hot channel entrypoints import that at module
load and opening a store pulls the state-database graph.
Doctor closures also stop pulling ssrf-runtime (fetch-guard + gateway net)
for two legacy private-network helpers that live in the lighter ssrf-policy
subpath: mattermost, nextcloud-talk, tlon, matrix.
The closure guard now forbids the two new heavy subpaths instead of the
deleted barrel, so the invariant keeps being enforced where it still applies.
* perf(doctor): keep heavy graphs out of every doctor closure
Doctor enumeration cold-loads each declaring plugin's contract closure, so
one heavy import in a closure is paid by the whole sweep. Four barrels were
still dragging unrelated graphs in for trivial helpers; each is repaired at
the leaf rather than by caching downstream:
- Legacy private-network config migration moves to a config leaf. It only
reshapes records, but lived beside the SSRF runtime (DNS, proxy, logging),
costing mattermost ~2.7s. ssrf-policy re-exports it, surface unchanged.
- Streaming config readers move to a leaf. They read two config keys, but
streaming.ts also formats tool aggregates, pulling tool-display/logging/
acp-core; that cost slack ~2.3s.
- signal took the channel-secret barrel for isRecord; the canonical plugin
record guard is string-coerce-runtime (root AGENTS.md).
- llm-task took the provider-model barrel for parseModelRef, now a narrow
model-ref-parse subpath.
Full doctor enumeration of all 42 declaring plugins, built mode:
legacy config rules 6668ms -> 1265ms, state migrations 184ms -> 127ms.
No plugin remains an outlier; the slowest is now ~380ms against a ~200ms floor.
Public export surfaces of every touched SDK subpath are byte-identical
(verified by diffing built module exports before/after); the API baseline
hashes move only because re-exported declarations emit differently.
The closure guard gains rules for each repaired barrel so the invariant
holds for future closures.
* fix(release): exclude new private-local declarations from the published package
Same pack-path rule as c41da3759f3: private-local subpaths ship without d.ts.
* fix(doctor): repair the closure guard violations that break main
The landed guard fails on main: three closures import heavy barrels for one
symbol each. Two more surfaced once the guard learned about the provider-model
barrel. Each gets a narrow subpath at the leaf:
- telegram sent-message-cache + state-migrations took the session-store barrel
(session accessor + state-db) for resolveStorePath -> session-store-paths
- discord thread-bindings.state took the channel-outbound barrel (reply
pipeline + channel registry) for one identity write -> outbound-echo-runtime
- discord model-picker took the provider-model barrel for normalizeProviderId,
which model-ref-parse now exposes beside parseModelRef
The guard also stops walking artifacts of plugins whose manifest declares no
doctor surface. Such a declaration gates the artifact off every enumeration
path exactly as resolvePluginDoctorContracts does, so its closure cost is never
paid; anthropic ("doctorContract": {}) was being held to a cost it cannot
incur. Absent declarations still load eagerly and stay enforced.
Side effect worth naming: discord's built doctor contract now loads again.
On main both discord and telegram fail to require in packaged builds (an
ESM-only transitive dep) and silently lose their repairs; this restores
discord and takes enumerated legacy config rules from 87 to 99. Telegram's
built artifact still pulls execa through dist chunking - a build-level defect
with a different owner, filed as follow-up.
* perf(doctor): slim remaining heavy doctor contract closures
Follow-up to #120698: several doctor closures still cold-loaded multi-second
kysely-bearing graphs through other broad barrels (session-store-runtime,
realtime-voice, channel-outbound, logging-core, memory-host-core/-events,
sqlite-runtime, persistent-dedupe, and plugin-local barrels).
- lazy-import heavy helpers inside async migration bodies (codex, msteams,
zalouser, workboard, matrix inbound-dedupe, memory-core migrations)
- bypass plugin-local barrels to defining modules (reef protocol,
memory-core short-term-promotion)
- move to lighter existing subpaths (slack -> channel-streaming, matrix
logger -> security-runtime, memory-wiki -> agent-scope-runtime, which now
also exports resolveSessionAgentId)
- add narrow openclaw/plugin-sdk/realtime-voice-activation for discord's
sync wake-name doctor rules
- split src/infra/kysely-sync-cache-state.ts so sqlite-transaction clears
Kysely caches without value-loading kysely; split the memory-host-sdk
kysely bridge off the schema/transaction bridge
- guard: forbid the heavy barrels in doctor closures with per-kind scoping
Cold enumeration per plugin: discord 52.6s->0.3s, msteams 30.9s->0.5s,
codex 29.6s->2.6s, zalouser 28.8s->2.3s, matrix 27.2s->3.2s,
slack 17.5s->1.5s, reef 9.9s->0.7s, memory-core 6.4s->3.6s,
workboard 3.4s->0.25s; all kysely-free except llm-task (named follow-up).
* fix(plugins): route slack streaming compat through a focused streaming-config subpath
The channel-streaming compat barrel is deprecated for extension production
code (deprecated-api-usage guard + SDK package contract). Add the narrow
non-deprecated openclaw/plugin-sdk/channel-streaming-config subpath for the
pure streaming config readers, and drop the now consumer-less
short-term-promotion barrel re-exports knip flagged.
* test(plugins): register memory-host-sdk kysely bridge in package boundary inventory
* fix(plugins): classify realtime-voice-activation as private-local
ClawSweeper P2: the subpath exports only a default target, which is the
private-local shape; register it in plugin-sdk-private-local-only-subpaths,
the package-boundary d.ts alias maps, and correct the public surface budgets
(realtime-voice-activation no longer counts as public).
* fix(release): exclude realtime-voice-activation declarations from the published package
Private-local subpaths ship without d.ts; register the files negation the
release pack-path check requires.
* perf(plugins): declare doctor contract surfaces
* perf(doctor): slim migration import closures
* perf(plugins): narrow doctor declaration record surface and wire owner-test lane
Registry records carry only the doctorContract declaration instead of the whole
parsed manifest, and check:changed now selects the src/plugins-owned declaration
honesty and closure-guard tests for extension module/manifest changes so
cross-lane drift cannot pass PR classification.
* fix(doctor): keep control-plane dist imports require-safe
Keep doctor and channel control-plane chunks off exec-class dependencies, and enforce native require(esm) loading during postbuild.
* chore(plugin-sdk): regenerate API baseline
* chore(plugin-sdk): sync export ordering
* fix(plugins): satisfy doctor contract CI boundaries
* perf(doctor): make qqbot doctor closure dependency-light
qqbot was the last plugin above 5s in doctor state-migration enumeration
(~8s under tsx/jiti). The cost was not the state-key builder (already a
leaf): its doctor closure value-imported the runtime-doctor SDK barrel,
whose plugin-state-store/state-db re-exports pull kysely (~330 modules),
plus security-runtime for one fileExists (~200 modules), all resolved
per-module by jiti during enumeration.
Split the migration-define helpers and light re-exports into a new
private-local plugin-sdk/runtime-doctor-migrations subpath; runtime-doctor
re-exports it so its public surface is byte-identical (API baseline hash
unchanged). qqbot's doctor-contract and state-migrations now import only
the light subpath, swapping fileExists for the equivalent async
legacyStateFileExists already in the closure.
qqbot enumeration: ~8.0s/531 modules -> ~0.25s/18 modules.
* chore(plugin-sdk): drop private-local subpath from API baseline
runtime-doctor-migrations is private-local-only; the baseline tracks public
modules, and the earlier line was generated before the classification.
* fix(plugins): register runtime-doctor-migrations boundary paths
The private-local subpath list feeds the extension package boundary map;
the shared paths config and xai's derived overrides must carry the same
entry or the boundary contract test fails.
* feat(plugins): mirror local coding sessions to a remote Beam receiver
* fix(plugins): satisfy static gates for the Beam mirror seam
* fix(plugins): import the config type from the narrow contracts subpath
* fix(plugins): require catalog consent and loopback-only plaintext for the Beam mirror