@kaged/plugin-host

JSON-RPC stdio transport, plugin process lifecycle with health checks and rate limiting, multi-plugin supervisor with role enforcement and tool registry

15
source files
14
test files
~7.4k
lines
✓ 322 pass
tests
pass
typecheck
clean
lint

Test results 322

parseCapability: filesystem > read:fs parses correctly [0.160ms]
parseCapability: filesystem > write:fs parses correctly [0.030ms]
parseCapability: filesystem > read:fs rejects relative path [0.100ms]
parseCapability: filesystem > write:fs rejects relative path [0.030ms]
parseCapability: exec > exec parses correctly [0.050ms]
parseCapability: exec > exec with full binary path [0.030ms]
parseCapability: exec > exec rejects missing path [0.030ms]
parseCapability: exec > exec rejects relative path [0.030ms]
parseCapability: exec > exec rejects empty binary [0.030ms]
parseCapability: net > net:[] → none [0.020ms]
parseCapability: net > net:* → all [0.020ms]
parseCapability: net > net:host:port → host_port [0.080ms]
parseCapability: net > net:host:* → host_all [0.030ms]
parseCapability: net > net rejects invalid port [0.030ms]
parseCapability: net > net rejects port 0 [0.030ms]
parseCapability: net > net rejects port 70000 [0.030ms]
parseCapability: net > net rejects empty host [0.030ms]
parseCapability: storage > kaged:storage:read [0.020ms]
parseCapability: storage > kaged:storage:write [0.010ms]
parseCapability: unrecognized > unknown format throws [0.030ms]
parseCapability: unrecognized > error includes the offending capability string [0.050ms]
parseCapabilities > parses array of capabilities [0.110ms]
parseCapabilities > empty array returns empty [0.020ms]
validateCapabilitiesUsed > all used capabilities are declared → empty violations [0.100ms]
validateCapabilitiesUsed > extra used capabilities → returns violations [0.020ms]
validateCapabilitiesUsed > empty used → no violations [0.020ms]
validateCapabilitiesUsed > empty declared, non-empty used → all are violations [0.020ms]
mergePluginConfig > merges disjoint project and system config [0.200ms]
mergePluginConfig > empty configs merge to empty object [0.030ms]
mergePluginConfig > project-only config (no system schema) passes through [0.040ms]
mergePluginConfig > system-only config (no project schema) passes through [0.030ms]
mergePluginConfig > rejects project config containing system-only fields [0.070ms]
mergePluginConfig > multiple system-only fields in project config produce multiple errors [0.070ms]
mergePluginConfig > system config fields not in system schema are still merged [0.040ms]
mergePluginConfig > system config values take precedence over project config for non-system-schema fields [0.040ms]
mergePluginConfigWithAgentOverrides > agent overrides project config fields [0.110ms]
mergePluginConfigWithAgentOverrides > empty agent overrides preserves base config [0.040ms]
mergePluginConfigWithAgentOverrides > rejects agent overrides that touch system config fields [0.050ms]
mergePluginConfigWithAgentOverrides > agent overrides add new project-side fields [0.030ms]
JsonRpcConnection: sendRequest > sends valid JSON-RPC request with incrementing ids [2.34ms]
JsonRpcConnection: sendRequest > resolves when response arrives [0.670ms]
JsonRpcConnection: sendRequest > rejects on error response [0.280ms]
JsonRpcConnection: sendRequest > rejects on timeout [51.16ms]
JsonRpcConnection: sendRequest > rejects when connection is closed [0.330ms]
JsonRpcConnection: sendNotification > sends notification without id [0.330ms]
JsonRpcConnection: sendNotification > skips sending when closed [0.170ms]
JsonRpcConnection: sendResponse > sends success response [0.420ms]
JsonRpcConnection: sendErrorResponse > sends error response [0.330ms]
JsonRpcConnection: incoming message routing > routes notifications to onNotification callback [10.43ms]
JsonRpcConnection: incoming message routing > routes requests to onRequest callback [11.47ms]
JsonRpcConnection: incoming message routing > reports protocol error for batch messages [10.64ms]
JsonRpcConnection: incoming message routing > reports protocol error for invalid JSON [11.39ms]
JsonRpcConnection: incoming message routing > reports protocol error for response with unknown id [11.91ms]
JsonRpcConnection: multi-line buffering > handles multiple messages in one chunk [12.35ms]
JsonRpcConnection: multi-line buffering > handles message split across chunks [17.26ms]
JsonRpcConnection: multi-line buffering > skips empty lines [10.87ms]
JsonRpcConnection: oversize message rejection > rejects messages exceeding max size [12.26ms]
JsonRpcConnection: close behavior > isClosed returns true after close() [0.380ms]
JsonRpcConnection: close behavior > close() rejects pending requests [0.640ms]
JsonRpcConnection: close behavior > close() is idempotent [0.190ms]
JsonRpcConnection: close behavior > stream close triggers onClose and rejects pending [0.660ms]
JsonRpcConnection: concurrent requests > routes responses to correct pending requests [0.980ms]
validateKnobValue — range > accepts value within bounds [0.480ms]
validateKnobValue — range > accepts min boundary [0.060ms]
validateKnobValue — range > accepts max boundary [0.050ms]
validateKnobValue — range > rejects below min [0.270ms]
validateKnobValue — range > rejects above max [0.080ms]
validateKnobValue — range > rejects non-number [0.080ms]
validateKnobValue — range > rejects NaN [0.070ms]
validateKnobValue — range > rejects invalid step [0.070ms]
validateKnobValue — range > accepts valid step 0.3 [0.070ms]
validateKnobValue — int_range > accepts integer within bounds [0.210ms]
validateKnobValue — int_range > rejects float [0.110ms]
validateKnobValue — int_range > rejects below min [0.080ms]
validateKnobValue — int_range > rejects above max [0.060ms]
validateKnobValue — int_range > rejects non-number [0.050ms]
validateKnobValue — int_range > validates step alignment [0.110ms]
validateKnobValue — enum > accepts valid value [0.180ms]
validateKnobValue — enum > rejects invalid value [0.080ms]
validateKnobValue — enum > rejects non-string [0.060ms]
validateKnobValue — boolean > accepts true [0.120ms]
validateKnobValue — boolean > accepts false [0.040ms]
validateKnobValue — boolean > rejects string 'true' [0.070ms]
validateKnobValue — text > accepts valid short lowercase string [0.240ms]
validateKnobValue — text > rejects exceeding max_length [0.080ms]
validateKnobValue — text > rejects pattern mismatch [0.090ms]
validateKnobValue — text > rejects non-string [0.050ms]
validateKnobValue — text > text without constraints accepts any string [0.070ms]
validateKnobValue — multiline > accepts multiline string [0.160ms]
validateKnobValue — multiline > rejects exceeding max_length [0.080ms]
validateKnobValue — multiline > rejects non-string [0.060ms]
validateKnobValue — model_alias > accepts null [0.100ms]
validateKnobValue — model_alias > accepts valid string [0.070ms]
validateKnobValue — model_alias > rejects empty string [0.070ms]
validateKnobValue — model_alias > rejects non-string non-null [0.050ms]
validateKnobValue — path > accepts config: prefix [0.320ms]
validateKnobValue — path > accepts project: prefix [0.060ms]
validateKnobValue — path > rejects other prefix [0.110ms]
validateKnobValue — path > rejects non-string [0.050ms]
validateKnobValue — path > path without prefixes constraint accepts anything [0.060ms]
validateAllKnobValues > validates all values successfully [0.250ms]
validateAllKnobValues > collects multiple errors [0.100ms]
validateAllKnobValues > reports unknown knob names [0.080ms]
validateAllKnobValues > empty values returns no errors [0.060ms]
parseManifest: roles field (ADR-0024) > accepts roles: [observer] [40.91ms]
parseManifest: roles field (ADR-0024) > accepts roles: [observer, compactor] [2.74ms]
parseManifest: roles field (ADR-0024) > defaults roles to [observer] when hooks is non-empty and roles omitted [2.03ms]
parseManifest: roles field (ADR-0024) > defaults roles to [] when no hooks are subscribed [1.68ms]
parseManifest: roles field (ADR-0024) > rejects unknown role [2.66ms]
parseManifest: roles field (ADR-0024) > rejects compactor role without pre_compact hook subscription [1.58ms]
parseManifest: roles field (ADR-0024) > rejects duplicate roles [1.79ms]
parseManifest: hooks field (ADR-0023) > accepts on_session_start [1.12ms]
parseManifest: hooks field (ADR-0023) > accepts on_session_idle [1.08ms]
parseManifest: hooks field (ADR-0023) > accepts pre_compact [0.960ms]
parseManifest: hooks field (ADR-0023) > accepts all four hooks together [1.11ms]
parseManifest: hooks field (ADR-0023) > defaults hooks to [] when omitted [0.870ms]
parseManifest: hooks field (ADR-0023) > rejects unknown hook name [0.940ms]
parseManifest: hooks field (ADR-0023) > rejects duplicate hook entries [1.01ms]
parseManifest: tools field (ADR-0023) > accepts tools declaration [4.07ms]
parseManifest: tools field (ADR-0023) > defaults tools to [] when omitted [0.880ms]
parseManifest: tools field (ADR-0023) > rejects tool name with uppercase [1.29ms]
parseManifest: tools field (ADR-0023) > rejects tool name with dots (must be single segment; prefix is applied at registration) [1.38ms]
parseManifest: tools field (ADR-0023) > rejects duplicate tool names within same manifest [1.44ms]
parseManifest: tools field (ADR-0023) > rejects tool missing required parameters_schema [0.920ms]
parseManifest: methods optional when tools or hooks present (ADR-0023) > methods empty + tools non-empty is OK [1.05ms]
parseManifest: methods optional when tools or hooks present (ADR-0023) > methods empty + hooks non-empty is OK [0.760ms]
parseManifest: methods optional when tools or hooks present (ADR-0023) > methods omitted + tools non-empty is OK [0.930ms]
parseManifest: system_config_schema (ADR-0023) > accepts system_config_schema [1.12ms]
parseManifest: system_config_schema (ADR-0023) > defaults systemConfigSchema to undefined when omitted [0.690ms]
parseManifest: system_config_schema (ADR-0023) > rejects field-name collision between config_schema and system_config_schema [1.30ms]
parseManifest: knobs (ADR-0024) > accepts knob with type=range [1.97ms]
parseManifest: knobs (ADR-0024) > accepts knob with type=enum + labels map [1.82ms]
parseManifest: knobs (ADR-0024) > accepts knob with type=int_range [1.48ms]
parseManifest: knobs (ADR-0024) > accepts knob with type=boolean [1.25ms]
parseManifest: knobs (ADR-0024) > accepts knob with type=text [1.30ms]
parseManifest: knobs (ADR-0024) > accepts knob with type=path + prefixes [1.25ms]
parseManifest: knobs (ADR-0024) > accepts knob with type=model_alias [1.26ms]
parseManifest: knobs (ADR-0024) > rejects knob with unknown type [1.26ms]
parseManifest: knobs (ADR-0024) > rejects knob with binds_to referencing a non-existent config_schema field [1.24ms]
parseManifest: knobs (ADR-0024) > rejects knob with binds_to pointing into system_config_schema [1.51ms]
parseManifest: knobs (ADR-0024) > rejects knob with binds_to that does not start with 'config.' [1.08ms]
parseManifest: knobs (ADR-0024) > defaults knobs to empty record when omitted [0.820ms]
parseManifest: hook_timeout_sec (ADR-0023) > accepts a valid hook_timeout_sec [0.600ms]
parseManifest: hook_timeout_sec (ADR-0023) > defaults hook_timeout_sec to 10 [0.530ms]
parseManifest: hook_timeout_sec (ADR-0023) > rejects hook_timeout_sec greater than 60 [0.600ms]
parseManifest: memory-markdown manifest integration > the actual memory-markdown manifest at plugins/project/memory-markdown/kaged-plugin.yaml parses [22.52ms]
parseManifest: valid manifests > parses full manifest [1.70ms]
parseManifest: valid manifests > parses minimal manifest with defaults [0.760ms]
parseManifest: invalid YAML > throws ManifestValidationError on broken YAML [1.09ms]
parseManifest: schema violations > missing name [0.650ms]
parseManifest: schema violations > invalid name format (uppercase) [0.630ms]
parseManifest: schema violations > name too long [0.630ms]
parseManifest: schema violations > missing methods AND missing hooks AND missing tools (plugin does nothing) [0.540ms]
parseManifest: schema violations > empty methods array AND no hooks AND no tools (plugin does nothing) [0.580ms]
parseManifest: schema violations > invalid method name (reserved prefix) [0.650ms]
parseManifest: schema violations > invalid method name (single segment) [0.600ms]
parseManifest: schema violations > description too long [0.660ms]
parseManifest: schema violations > shutdown_timeout_sec too high [0.590ms]
parseManifest: schema violations > health_interval_sec too low [0.560ms]
parseManifest: schema violations > invalid homepage URL [1.16ms]
parseManifest: schema violations > error includes issues array [0.430ms]
PluginCallContext: canonical shape > daemon-level context has all agent fields null [0.200ms]
PluginCallContext: canonical shape > agent-run context has all four agent fields populated [0.080ms]
PluginCallContext: canonical shape > nested subagent path is accepted [0.060ms]
PluginCallContext: canonical shape > operator_id may be null in insecure-mode daemon-level call [0.050ms]
PluginCallContext: canonical shape > request_id is always required (non-empty string) [0.110ms]
PluginCallContext: invariant — agent fields are all-or-none > project_id set but agent_path null is a contract violation [0.090ms]
PluginCallContext: invariant — agent fields are all-or-none > agent_path set but project_id null is a contract violation [0.100ms]
PluginCallContext: invariant — agent fields are all-or-none > session_id set but agent_path null is a contract violation [0.080ms]
PluginCallContext: invariant — agent fields are all-or-none > project_id+agent_path set but session_id null is a contract violation [0.080ms]
PluginCallContext: invariant — agent fields are all-or-none > error message names which fields are inconsistent [0.090ms]
buildPluginCallContext: helper builder > daemon-level call: operator + request_id only [0.080ms]
buildPluginCallContext: helper builder > agent-run: all four fields propagated [0.050ms]
buildPluginCallContext: helper builder > builder validates the invariant — partial agent fields throw [0.080ms]
buildPluginCallContext: helper builder > missing request_id throws [0.050ms]
buildPluginCallContext: helper builder > null operator_id is accepted (insecure-mode daemon-level call) [0.040ms]
PluginProcess.fireHook: gating > returns not_running when plugin is disabled [0.820ms]
PluginProcess.fireHook: gating > returns not_subscribed when plugin does not list the hook [26.43ms]
PluginProcess.fireHook: gating > returns not_subscribed for pre_compact when only on_session_start subscribed [22.59ms]
PluginProcess.fireHook: successful dispatch > on_session_start sends kaged.hook.on_session_start with _context and returns inject [35.35ms]
PluginProcess.fireHook: successful dispatch > on_session_idle sends transcript params and returns ok with null result [33.66ms]
PluginProcess.fireHook: successful dispatch > pre_compact passes role and strategy params [33.76ms]
PluginProcess.fireHook: failure handling > JSON-RPC error response returns error status with audit [35.80ms]
PluginProcess.fireHook: failure handling > timeout returns timeout status with audit [1.03s]
PluginProcess.fireHook: failure handling > uses hookTimeoutSec from manifest (not default METHOD_CALL_TIMEOUT_MS) [1.02s]
PluginSupervisor.fireHook > returns empty array for empty pluginNames [0.680ms]
PluginSupervisor.fireHook > returns not_found for unknown plugin [0.170ms]
PluginSupervisor.fireHook > fires hooks in order on registered plugins (not_running since disabled) [0.500ms]
PluginSupervisor.fireHook > mixed results: found + not_found + not_subscribed [0.270ms]
plugin machine: disabled → spawning (enable) > disabled + enable → spawning [0.060ms]
plugin machine: disabled → spawning (enable) > emits spawn_process, send_initialize, audit [0.080ms]
plugin machine: disabled → spawning (enable) > running + enable → TransitionError [0.150ms]
plugin machine: spawning → running (handshake_ok) > spawning + handshake_ok → running [0.050ms]
plugin machine: spawning → running (handshake_ok) > emits send_initialized, reset_failure_counter, audit [0.070ms]
plugin machine: spawning → running (handshake_ok) > running + handshake_ok → TransitionError [0.060ms]
plugin machine: spawning → failed (handshake_fail) > spawning + handshake_fail → failed [0.100ms]
plugin machine: spawning → failed (handshake_fail) > emits kill_process, mark_failed, audit [0.070ms]
plugin machine: crash with backoff > running + crash (first failure) → crashed with 1s backoff [0.090ms]
plugin machine: crash with backoff > running + crash (2nd failure) → crashed with 2s backoff [0.110ms]
plugin machine: crash with backoff > running + crash (4th failure) → crashed with 8s backoff [0.040ms]
plugin machine: crash with backoff > running + crash (5th failure) → failed [0.070ms]
plugin machine: crash with backoff > spawning + crash → crashed (process died during handshake) [0.040ms]
plugin machine: crash with backoff > disabled + crash → TransitionError [0.070ms]
plugin machine: health_fail_limit > running + health_fail_limit (first) → crashed [0.170ms]
plugin machine: health_fail_limit > running + health_fail_limit (5th) → failed [0.040ms]
plugin machine: health_fail_limit > disabled + health_fail_limit → TransitionError [0.080ms]
plugin machine: crashed → spawning (restart) > crashed + restart → spawning [0.070ms]
plugin machine: crashed → spawning (restart) > running + restart → TransitionError [0.060ms]
plugin machine: running → stopped (shutdown) > running + shutdown → stopped [0.090ms]
plugin machine: running → stopped (shutdown) > disabled + shutdown → TransitionError [0.050ms]
plugin machine: any → disabled (disable) > running + disable → disabled (kills process) [0.110ms]
plugin machine: any → disabled (disable) > spawning + disable → disabled (kills process) [0.060ms]
plugin machine: any → disabled (disable) > crashed + disable → disabled (no kill needed) [0.050ms]
plugin machine: any → disabled (disable) > failed + disable → disabled [0.030ms]
plugin machine: any → disabled (disable) > stopped + disable → disabled [0.030ms]
plugin machine: any → disabled (disable) > disabled + disable → TransitionError [0.050ms]
plugin machine: failed → spawning (operator_enable) > failed + operator_enable → spawning [0.110ms]
plugin machine: failed → spawning (operator_enable) > running + operator_enable → TransitionError [0.050ms]
plugin machine: failed → spawning (operator_enable) > disabled + operator_enable → TransitionError [0.070ms]
plugin machine: full lifecycle > disabled → enable → handshake → running → shutdown → stopped [0.090ms]
plugin machine: full lifecycle > crash → restart → handshake → running [0.070ms]
plugin machine: full lifecycle > repeated crashes → failed → operator_enable → spawning [0.050ms]
PluginTransitionError properties > includes from and event [0.090ms]
PluginProcess: initial state > starts in disabled state [0.200ms]
PluginProcess: enable + handshake > enable transitions to spawning and sends initialize [22.33ms]
PluginProcess: enable + handshake > handshake failure on name mismatch → failed state [22.91ms]
PluginProcess: enable + handshake > handshake failure on api_version mismatch → failed state [21.69ms]
PluginProcess: enable + handshake > handshake failure on capability overreach → failed state [21.72ms]
PluginProcess: spawn environment > builds correct spawn env with protected keys [11.75ms]
PluginProcess: method calls > callMethod sends request with _context and returns result [33.25ms]
PluginProcess: method calls > callMethod throws when not running [0.290ms]
PluginProcess: notification handling > forwards plugin notifications via callback [32.48ms]
PluginProcess: state change tracking > fires onStateChange for each transition [23.34ms]
PluginProcess: shutdown > sends shutdown notification [22.39ms]
PluginProcess: shutdown > shutdown on non-running state is no-op [0.140ms]
PluginProcess: disable > disable from running kills process [22.63ms]
PluginSupervisor: registration > registerPlugin adds a plugin [0.230ms]
PluginSupervisor: registration > registerPlugin rejects duplicate names [0.170ms]
PluginSupervisor: registration > registerPlugin rejects after startAll [0.690ms]
PluginSupervisor: registration > registerFromYaml parses YAML and registers [1.25ms]
PluginSupervisor: listing > listPlugins returns sorted list [0.980ms]
PluginSupervisor: listing > listPlugins returns empty for fresh supervisor [0.060ms]
PluginSupervisor: listing > getPluginInfo returns correct details [0.150ms]
PluginSupervisor: listing > getPluginInfo returns null for unknown plugin [0.030ms]
PluginSupervisor: listing > getPluginState returns state for registered plugin [0.090ms]
PluginSupervisor: listing > getPluginState returns null for unknown plugin [0.030ms]
PluginSupervisor: hasPlugin > returns true for registered plugin [0.060ms]
PluginSupervisor: hasPlugin > returns false for unregistered plugin [0.030ms]
PluginSupervisor: enable/disable > enablePlugin throws for unknown plugin [0.190ms]
PluginSupervisor: enable/disable > disablePlugin throws for unknown plugin [0.150ms]
PluginSupervisor: callMethod > callMethod throws for unknown plugin [0.130ms]
PluginSupervisor: isStarted flag > isStarted is false initially [0.040ms]
PluginSupervisor: isStarted flag > isStarted is true after startAll [0.130ms]
PluginSupervisor: isStarted flag > isStarted is false after stopAll [0.110ms]
PluginSupervisor: isStarted flag > startAll is idempotent [0.130ms]
PluginSupervisor: audit events > emits plugin.disabled audit for disabled plugins on register [0.200ms]
PluginSupervisor: multiple plugins > registers and lists multiple plugins [0.170ms]
PluginSupervisor: stopAll with no plugins > stopAll on empty supervisor completes [0.140ms]
isValidMethodName > valid: two segments [0.040ms]
isValidMethodName > valid: three segments [0.020ms]
isValidMethodName > valid: four segments [0.020ms]
isValidMethodName > valid: with underscores [0.020ms]
isValidMethodName > valid: with digits [0.020ms]
isValidMethodName > invalid: single segment [0.020ms]
isValidMethodName > invalid: five segments [0.020ms]
isValidMethodName > invalid: uppercase [0.010ms]
isValidMethodName > invalid: starts with digit [0.020ms]
isValidMethodName > invalid: hyphens [0.020ms]
isValidMethodName > invalid: empty [0.020ms]
isValidMethodName > invalid: segment starts with digit [0.020ms]
isReservedMethod > kaged.* is reserved [0.070ms]
isReservedMethod > system.* is reserved [0.020ms]
isReservedMethod > presets.list is not reserved [0.020ms]
validatePluginMethodName > valid method passes [0.060ms]
validatePluginMethodName > invalid format throws ProtocolError [0.060ms]
validatePluginMethodName > reserved name throws ProtocolError [0.050ms]
validatePluginMethodName > error code is -32600 [0.050ms]
validatePluginMethods > all valid passes [0.070ms]
validatePluginMethods > one invalid throws [0.080ms]
JSON-RPC message classification > request [0.060ms]
JSON-RPC message classification > notification (no id) [0.040ms]
JSON-RPC message classification > success response [0.040ms]
JSON-RPC message classification > error response [0.030ms]
JSON-RPC message classification > batch [0.050ms]
JSON-RPC message classification > null is not any type [0.030ms]
classifyMessage > classifies request [0.060ms]
classifyMessage > classifies notification [0.040ms]
classifyMessage > classifies response [0.040ms]
classifyMessage > classifies batch [0.030ms]
classifyMessage > invalid JSON → invalid [0.020ms]
classifyMessage > valid JSON but not JSON-RPC → invalid [0.050ms]
JSON_RPC_ERRORS > has expected codes [0.090ms]
pluginStoragePrefix > simple name [0.040ms]
pluginStoragePrefix > hyphenated name converted to underscores [0.020ms]
pluginStoragePrefix > name with no hyphens [0.020ms]
validateAgentPluginRoles > empty manifests list returns no errors [0.850ms]
validateAgentPluginRoles > single observer returns no errors [0.140ms]
validateAgentPluginRoles > single compactor returns no errors [0.050ms]
validateAgentPluginRoles > multiple observers returns no errors [0.060ms]
validateAgentPluginRoles > two compactors returns error on the second [0.090ms]
validateAgentPluginRoles > three compactors returns errors on second and third [0.080ms]
validateAgentPluginRoles > compactor + observers returns no errors [0.050ms]
validateAgentPluginRoles > observers + two compactors returns error only on second compactor [0.060ms]
validateAgentPluginRoles > plugins with empty roles are fine [0.050ms]
validateAgentPluginRoles > dual-role plugin (observer+compactor) counts as the compactor [0.070ms]
prefixToolName > joins plugin name and tool name with dot [0.050ms]
prefixToolName > single-segment plugin name [0.020ms]
checkBuiltInNamespaceCollision > returns null for non-colliding names [0.090ms]
checkBuiltInNamespaceCollision > returns warning for 'file' [0.050ms]
checkBuiltInNamespaceCollision > returns warning for 'search' [0.020ms]
checkBuiltInNamespaceCollision > returns warning for 'lsp' [0.020ms]
checkBuiltInNamespaceCollision > returns warning for 'dap' [0.020ms]
checkBuiltInNamespaceCollision > returns warning for 'kaged' [0.020ms]
checkBuiltInNamespaceCollision > does not match partial overlaps like 'file-utils' [0.030ms]
buildToolRegistry > empty manifests list returns empty result [0.200ms]
buildToolRegistry > registers tools with prefixed names [0.220ms]
buildToolRegistry > detects tool name collision between plugins [0.100ms]
buildToolRegistry > first plugin wins on collision — second is rejected [0.070ms]
buildToolRegistry > multiple plugins with different tools coexist [0.080ms]
buildToolRegistry > emits warning for built-in namespace collision [0.060ms]
buildToolRegistry > plugin with no tools contributes nothing [0.040ms]
buildToolRegistry > rejects prefixed names that don't match the pattern [0.060ms]

Mentioned in

Type Document
adr ADR-0008: Plugins are subprocesses over JSON-RPC on stdio
adr ADR-0023: Project-plugin lifecycle hooks, per-agent declaration, isolation as a core principle
adr ADR-0024: Context compaction is kaged-owned, layered, observable, and operator-tunable
adr ADR-0028: 3rd-party OAuth provider auth — token lifecycle and credential management
adr ADR-0042: Package distribution, CI, and the release pipeline
adr ADR-0047: Session Notifications — Event Routing, Channels, and the Service-Worker Bridge
adr ADR-0049: Providers are dynamically-loaded modules from an operator-local store; catalog from a self-hosted models.dev mirror; @kaged/llm becomes resolver + loader + middleware
spec Spec: Agent Tooling
spec Spec: Agent Harness
spec Spec: Daemon
spec Spec: HTTP + WebSocket API
spec Spec: Local config
spec Spec: Plugin Host
spec Spec: Project DSL
spec Spec: Sandbox
spec Spec: Session Manager