ticket: refine plugin feature layering

This commit is contained in:
2026-06-14 01:28:42 +09:00
parent 234ffbff2e
commit 0f7cac62ef
13 changed files with 447 additions and 202 deletions
+74 -68
View File
@@ -1,82 +1,88 @@
---
title: "Plugin: define extension surface for hooks and tools"
state: "planning"
created_at: "2026-05-31T01:00:05Z"
updated_at: "2026-06-03T12:25:05Z"
title: 'Plugin: define extension surface for hooks and tools'
state: 'planning'
created_at: '2026-05-31T01:00:05Z'
updated_at: '2026-06-13T15:29:21Z'
assignee: null
---
## Goal
Design Yoi's Plugin surface as the user-facing package/config/runtime layer built on top of `pod::feature`.
`pod::feature` is the internal API substrate for contribution registration: Tools, Hooks, BackgroundTasks, Services, diagnostics, and lifecycle integration. Plugin is the layer that makes that substrate usable by users and workspaces through package metadata, enablement config, runtime choices, provenance, and Plugin-layer permissions.
MCP is not the Plugin model and should not be treated as a Plugin permission backend. MCP is a separate protocol-backed integration layer that also uses the feature API and owns its own MCP-specific enablement/trust policy.
## Background
insomnia currently has internal Hook / Tool concepts, plus a separate planned MCP integration ticket (`mcp-integration`). The next design step is to define the project-level Plugin surface: how user/project-provided extensions can contribute Tools and Hooks without weakening scope, permission, history, or prompt-context invariants.
Yoi already has internal extension-like surfaces:
The plugin surface should not be a grab bag of arbitrary code execution. Candidate extension mechanisms have different trust and protocol properties:
- Tools via `llm_worker::ToolRegistry` / `ToolDefinition`
- Hooks via `HookRegistry` / `HookEvent` / `HookAction`
- Feature contribution declarations in `pod::feature`
- Built-in features such as task and ticket tools
- MCP: protocol-bound external tool/resource/prompt provider surface.
- TOML/config-only hooks: declarative configuration for simple hook behavior without arbitrary code.
- WASM: planned first programmable plugin runtime for Hooks and Tools, with explicit capability imports and sandboxing.
- General scripting languages: considered, but not the initial direction because arbitrary script execution broadens the trust/runtime surface too quickly.
The Plugin surface should expose extension points without letting external packages bypass Worker history, prompt/context invariants, scoped tool permissions, or role/profile configuration.
## Related work
- `work-items/open/20260529-161928-mcp-integration/` — MCP integration as one plugin backend / external capability bridge.
- `work-items/open/20260603-122317-plugin-feature-contribution-registry/` — implementation-oriented runtime registry split-out for built-in and external feature contributions.
- `work-items/open/20260603-122317-hook-public-surface-hardening/` — prerequisite hardening for public Hook contribution safety.
- Existing internal hooks/tools code: `crates/pod`, `crates/tools`, `crates/llm-worker`.
- Manifest permission policy and scope enforcement must remain authoritative for plugin-provided tools.
Prior Hook hardening work constrains model-visible context mutation so Plugin exposure can stay safe. Plugin design should reuse those safe surfaces rather than creating a parallel tool/hook runtime.
## Requirements
- Define a Plugin surface that can provide:
- Tools callable by the LLM through the normal ToolRegistry / permission / scope path;
- Hooks observing or influencing Pod/Worker lifecycle through the existing Hook boundary, not by directly mutating worker history/context.
- Separate plugin description/registration from plugin runtime implementation.
- A plugin manifest should declare provided tools/hooks, required capabilities, configuration schema or config values, and trust/runtime type.
- Runtime implementations can include MCP, declarative config hooks, and WASM in separate phases.
- Keep MCP as a related backend, not the whole plugin model.
- MCP servers remain untrusted external capability providers bridged through allowlists, bounded output, scope/permission policy, and explicit resource/prompt use.
- Define a declarative hook path for simple TOML/config-only behavior where code execution is unnecessary.
- Define a WASM plugin direction for programmable Hooks/Tools.
- WASM modules must receive explicit host imports/capabilities only.
- File/network/process access must not be ambient; all external effects go through host-provided capability APIs and existing policy checks.
- Tool outputs must be bounded and recorded through normal history/tool-result paths.
- Preserve LLM context/history invariants.
- Plugins must not inject cross-turn invisible context.
- If plugin output becomes model-visible, it must enter through durable history/tool/hook paths according to existing rules.
- Preserve scope and permission invariants.
- Plugin-provided tools must not bypass `ScopedFs`, manifest tool permission policy, child scope delegation, or web/network policy.
- Clarify trust model and lifecycle.
- Builtin vs project vs user plugins.
- Discovery/enablement through manifest/profile/config.
- Versioning / compatibility boundaries.
- Diagnostics when a plugin cannot load or asks for unavailable capabilities.
## Non-goals
- Implementing the full WASM runtime in the first design step.
- Implementing MCP itself beyond referencing the existing MCP integration ticket.
- Supporting arbitrary host scripting languages as a first-class plugin runtime.
- Allowing plugins to mutate session history, memory, prompt context, or scope outside approved APIs.
- Adding UI plugin systems or TUI rendering extensions.
## Suggested phases
1. **Design / architecture note**
- Define Plugin, PluginManifest, PluginRuntimeKind, Tool contribution, Hook contribution, capability request, and trust/source model.
- Map MCP, declarative hooks, and WASM onto that model.
2. **Internal registry boundary**
- Detailed implementation is split to `plugin-feature-contribution-registry` so this ticket can stay focused on the architecture surface and invariants.
3. **Declarative hooks MVP**
- Add a non-code configuration path for simple hook behavior if an immediate use case exists.
4. **WASM spike**
- Evaluate runtime (`wasmtime` or alternative), host imports, resource limits, serialization, and Nix/package impact.
5. **MCP bridge alignment**
- Ensure `mcp-integration` plugs into the same Tool/permission/output boundary rather than becoming a parallel extension path.
- Define Plugin as a user-facing layer over `pod::feature`, not as the feature API itself.
- Plugin package/config/runtime code eventually contributes through `pod::feature`.
- `pod::feature` remains responsible for contribution declarations, lifecycle, diagnostics, and registration plumbing.
- Plugin remains responsible for package enablement, provenance, runtime selection, and Plugin-layer permission/trust policy.
- Define supported contribution categories.
- Tools
- Hooks
- Background tasks / services, if included in the initial model
- Future extensions must remain explicit contribution categories, not arbitrary host access.
- Define Plugin-layer permission and trust model separately from `pod::feature`.
- Do not rely on feature-level `HostAuthority` / authority grants for Plugin permissions.
- Plugin grants should be tied to package identity/runtime/user or workspace config, not to feature install reports.
- Plugin policy must decide which contribution categories and host APIs a Plugin runtime can use.
- Define runtime families separately.
- Declarative/config-only Plugins
- WASM or another sandboxed runtime, if/when selected
- External process/plugin bridge, if/when selected
- MCP remains a separate feature-backed protocol integration, not the Plugin permission model.
- Hook Plugins must use the hardened public Hook surface.
- no raw hidden `Item` injection
- no prompt/context mutation outside durable history-aware paths
- explicit supported `HookAction` subset only
- Tool Plugins must register ordinary Yoi tools.
- normal tool schema exposure
- normal PreToolCall permission path
- normal tool-result history path
- bounded result serialization
- Plugin metadata and package content are untrusted input.
- Plugin enablement must be explicit.
- package presence/discovery alone cannot enable or execute Plugin code
- workspace/user config must opt in to package/runtime/contribution activation
- The design must document the boundary among Plugin, MCP, and built-in Features.
## Acceptance criteria
- The repository has a documented plugin architecture proposal covering Tools, Hooks, runtimes, capability model, trust model, and discovery/enablement.
- MCP is positioned as one plugin backend / bridge and linked to `mcp-integration`, not treated as the only extension mechanism.
- The proposal explicitly explains why arbitrary scripting languages are deferred and why WASM is the initial programmable runtime direction.
- The design preserves existing scope, permission, history, and prompt-context invariants.
- Follow-up implementation tickets can be cut independently for declarative hooks, WASM runtime, and MCP bridge integration.
- Any code changes in this ticket, if taken beyond design docs, are limited to safe internal boundaries and have focused tests.
- A design note or Ticket plan defines Plugin as a user-facing layer over `pod::feature`.
- The plan states that Plugin permissions are Plugin-layer policy and are not implemented by `pod::feature` `HostAuthority` grants.
- The plan states that MCP is a separate feature-backed integration with MCP-specific enablement/trust policy.
- Contribution categories and runtime families are named with explicit in/out of scope decisions for the first implementation slice.
- The public Hook safety invariants from `00001KT6Q08R8` remain intact.
- Tool Plugins are required to use ordinary ToolRegistry / permission / history / bounded-result paths.
- No design path allows Plugin package presence alone to execute code or mutate context.
- The design identifies which follow-up Tickets own package format, runtime implementation, and Plugin permission details.
## Suggested decomposition
1. Public Hook surface hardening. Completed by `00001KT6Q08R8`.
2. Feature contribution API substrate. Completed initial slice by `00001KT6Q08R9`; dynamic provider work continues in `00001KTR81P9X`.
3. Plugin package/discovery format. Tracked by `00001KT0Z4BK8`.
4. Plugin permission/runtime policy Ticket. Create or refine after runtime family is selected; do not put this policy into `pod::feature`.
5. MCP local stdio integration. Tracked separately by `00001KTR82RB7`; it uses feature API but is not Plugin permission work.
## Notes
- This Ticket is a design coordination Ticket; implementation should be split into concrete Tickets rather than landing a broad Plugin platform in one change.
- Keep Plugin permission terms distinct from `HostAuthority`. If `HostAuthority` remains in code, it is not the Plugin policy surface.
- Avoid adding support for arbitrary scripting languages until package identity, runtime sandbox/trust, and permission policy are explicit.
+18
View File
@@ -39,4 +39,22 @@ Two implementation-oriented prerequisite tickets are split out:
This preserves the desired detachable shape: feature state remains in the feature/extension module, while Pod interaction happens through existing durable host surfaces. WorkItem management should be implemented as a built-in feature contribution once the registry boundary is in place, rather than as a special Pod context-injection path.
---
<!-- event: decision author: hare at: 2026-06-13T15:29:21Z -->
## Decision
決定:
- `pod::feature` は API / contribution substrate として扱い、Plugin や MCP の権限管理を担わせない。
- Plugin は `pod::feature` をユーザー向け package/config/runtime 形式で使わせる層であり、Plugin permission / trust policy は Plugin layer で定義する。
- MCP は `pod::feature` 上に protocol-backed integration layer を構築するが、MCP server enablement / command-env-secret policy / trust boundary / MCP-specific permission は MCP layer が独自に持つ。
- MCP local stdio server の OS-level side effects は Yoi feature authority では制御できないため、feature-layer authority / grant を MCP や Plugin の permission model に流用しない。
反映:
- `00001KTR81P9X` は authority ではなく provider lifecycle / dynamic contribution / normal ToolRegistry path / untrusted normalization に絞る。
- `00001KTR82RB7` は MCP 固有の explicit config と trust model を持つ。
- `00001KSXRQ4G8``00001KT0Z4BK8` は Plugin permission を Plugin layer として扱い、MCP を初期 Plugin packaging/runtime から分離する。
---