Commit Graph

9 Commits

Author SHA1 Message Date
Peter Steinberger
e4d1b7e0d3 refactor(plugins): move plugin contributions into the registry bundle (#117372)
* refactor(plugins): move plugin contributions into the registry bundle

* fix(plugins): guard embedding owner union and drop unused test-util imports

* fix(plugins): break registry facade import cycles

* fix(plugins): remove obsolete registry snapshot seams

* test(gateway): preserve plugin runtime mock exports

* test(auto-reply): install builder registry in diagnostics fixture

* test(plugins): activate registry-backed capability fixtures
2026-08-01 06:57:01 -07:00
Peter Steinberger
80b0e78d62 fix(plugins): hash loader cache keys so plugin config never leaks into diagnostics (#117237) 2026-07-31 22:46:49 -07:00
Vincent Koc
80707db7ab fix(plugins): bound hook execution and retire stale registrations (#115695)
* fix(plugins): bound hooks and own legacy registrations

* docs(hooks): clarify internal handler ownership

* fix(cli): retain message hook shutdown deadline
2026-07-29 16:44:05 +08:00
Peter Steinberger
8a2852bdfa refactor(plugins): reuse lifecycle-owned metadata snapshot (#114807) 2026-07-27 20:29:14 -04:00
Peter Steinberger
431da14410 fix(plugins): load standalone files without manifests (#111515) 2026-07-19 12:21:11 -07:00
Yuval Dinodia
c17a81b470 fix(plugins): roll back cleared runtime registrations when an activating reload aborts (#103812)
* fix(plugins): roll back cleared runtime registrations when an activating reload aborts

loadOpenClawPlugins clears the process-global agent-harness, plugin-command,
compaction, detached-task, interactive-handler, embedding, memory-embedding,
and memory stores up front on an activating load and only re-registers them at
the end via activatePluginRegistry. The body has a finally with no catch, so a
throw during discovery or manifest load (a corrupted or half-written plugin
manifest mid-upgrade) leaves the previously active registry marked active while
its runtime stores are gone process-wide; the gateway reload driver only logs
and swallows the error.

Snapshot the process-global stores before the clear with the existing
snapshotPluginProcessGlobalState helper and restore them on any throw before
activation. clearActivatedPluginRuntimeState moves next to the snapshot and
restore helpers it pairs with in plugin-registration-transaction.ts, which
already owns atomic plugin registration state and imports from every module the
clear touches; loader.ts re-exports it so existing callers are unchanged.

* fix(plugins): make reload rollback activation-safe

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-18 18:11:16 -07:00
Yuval Dinodia
73cf9a8bed fix(plugins): plugins.deny is bypassed by a mixed-case manifest id (#109237)
* fix(plugins): canonicalize manifest plugin ids to lowercase

Plugin config policy lists (plugins.deny, plugins.allow, plugins.entries)
are lowercase-normalized through normalizePluginId, but a plugin's
self-declared manifest id was only trimmed, never lowercased. A plugin
publishing "id": "Malicious-Scraper" therefore never matched an operator
denylist entry of "malicious-scraper" and fell through to default
activation, loading its hooks, channels, secret integrations, and tools.
The same gap let a mixed-case spelling evade the core reserved-id check.

Canonicalize the id at the manifest parse boundary where
PluginManifestRecord.id is minted, so every downstream policy consumer
compares against the same canonical form.

* test(plugins): prove mixed-case deny at gateway startup

* test(plugins): assert denied gateway record is absent

* test(plugins): materialize allowed secret fixture

* fix(plugins): compare a derived policy key instead of rewriting manifest identity

Manifest ids stay exactly as declared. Deny, allow, and per-entry checks now
compare a lowercase policy key derived at each enforcement boundary, matching
the lowercase-normalized config lists.

The previous approach lowercased PluginManifestRecord.id at the parse boundary.
That id is also matched against the plugin runtime export id, and a mismatch is
a hard load failure, so an existing plugin declaring the same mixed-case id in
both its manifest and its runtime export would stop loading after upgrade.

The Gateway fixture now declares a mixed-case manifest id with a matching
mixed-case runtime export, covering that upgrade case, and drops the allowlist
that previously scoped discovery by a lowercase id and masked the denylist
behavior under test.

* fix(plugins): close mixed-case policy gaps

* test(plugins): use tracked policy fixture temp dir

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 23:13:13 -07:00
Peter Steinberger
f81f9d8570 chore: enforce max-lines suppression ratchet (#107315)
* ci: enforce max-lines suppression ratchet

* chore: prune stale max-lines suppression

* fix: close max-lines ratchet enforcement gaps

* fix: harden max-lines ratchet checks

* fix(ci): satisfy max-lines ratchet checks

* style: format max-lines declarations

* fix(ci): match oxlint suppression grammar

* test: isolate max-lines git fixtures

* chore: prune resolved max-lines debt

* test: skip newline path fixture on Windows

* fix: harden max-lines suppression ratchet

* chore: refresh max-lines baseline

* fix: close max-lines ratchet bypasses

* fix: derive ratchet base from PR merge tree

* fix: support older Git in staged ratchet

* fix: align max-lines declarations and baseline

* chore: refresh max-lines baseline for current main

* fix: exclude generated wizard locales from max-lines

* chore: prune resolved max-lines debt
2026-07-14 09:27:02 -07:00
Peter Steinberger
507038c456 refactor: split oversized test suites (#106354)
* refactor: split oversized test suites

* test: classify split modules as test utilities

* test: preserve bundled routing after suite splits

* style: format unit-fast routing import

* test: preserve owner routing for split suites
2026-07-13 07:01:08 -07:00