Files
PaperClipAI/maps/feature-map/plugins.md
T
Nicky LeachandPaperclip 9f4a956b90 Add durable agent runtime synchronization hooks (#16499)
## Thinking Path

> - Paperclip manages agents and their runtime configuration.
> - Plugins can maintain external agent computers.
> - Configuration and file saves currently miss durable plugin delivery.
> - A transient activity notification cannot recover after interruption.
> - This pull request adds an opt-in agent runtime resource stream.
> - The existing dispatcher delivers and acknowledges its committed
work.
> - Plugins can prepare computers when configuration changes.

## Linked Issues or Issue Description

Related: #15631 and #16203 establish agent lifecycle and native durable
delivery.

**Problem**

Plugins cannot reliably react to agent configuration and instruction
changes without polling or waiting for execution.

**Proposed solution**

Add an opt-in `agent_runtime` stream to the existing resource journal.
Record changes at the database mutation and managed file audit
boundaries. Wake the dispatcher with content-free commit notifications.
Provide scoped runtime inputs to the selected lifecycle plugin.

**Alternatives considered**

Route-only activity events miss service and background writers.
Scheduled scans delay changes and repeatedly query unchanged state.

**Roadmap alignment**

This extends the existing plugin and agent configuration work.

## What Changed

- Add durable update/delete events for agent runtime state, including an
existing-agent baseline.
- Capture configuration changes, instruction edits, deletion, restore,
and managed run writeback.
- Add commit notifications and a reconnect scan. Register one listener
for configured, enabled runtime subscribers. Release it when none
remain.
- Keep HTTP startup independent of queued plugin callbacks.
- Add `ctx.agents.getRuntime`. Require lifecycle capability, invocation
company, enabled plugin, and owning lifecycle selection.
- Keep legacy agent/project subscriptions isolated. Manual inbox reads
retain both legacy streams.
- Resolve recovered instruction paths without reading or hashing bundle
contents. Use the company reporting graph for runtime health.
- Repair missed file events on identical save/deletion retries after a
journal failure; preserve content tokens and conditional-write checks.
- Correlate file audits with runtime revisions to deduplicate recorded
retries without a new table. Bound the lookup with the existing
company/timestamp index.
- Document the contract, migration, access boundaries, and
session-connection requirement.

## Verification

- Rebased the full stack onto origin/master after #16507.
- Final replayed stack: `pnpm -r typecheck` and `pnpm build` passed.
- All 132 affected runtime, skill, connector, publication, instruction,
managed-agent, and delivery tests passed after the latest-master rebase.
Workspace typecheck and build passed.
- Journal failure injection verifies recovery on identical file writes,
deletions, and instruction retries from an acknowledged inbox.
- Deduplication follow-up: 80 runtime/instruction/delivery tests and
server typecheck passed. Repeated retries create no audit/events; old
hashes returning after an intervening commit still repair delivery.
Built-in/native instruction writer regressions passed all 56 tests.
- PR 1 follow-up tests cover valid/cyclic reporting chains, listener
registration failure, multiple subscribers, global/company disable,
re-enable, unload, and startup with blocked callbacks.
- Database coverage includes rollback, journal failure, no-op
suppression, file saves/deletion, ordering/replay, owner/company denial,
independent-client commits, and real listener loss/reconnect.
- SDK/shared suites passed 1,059 tests during implementation.
CLI/delivery regressions also passed.
- Migration safety, map checks, diff whitespace, and local secrets/PII
scan passed.
- Hosted CI and security checks are fully green at `b296405e2`. Standard
Greptile and Apex both returned 5/5 with no unresolved findings.
- The broad local suite encountered an unchanged diagnostic test that
rejects the word "private" from an error stack. This worktree lives
under /private/tmp. The same unchanged diagnostic suite passed all 108
tests in the original checkout. Hosted full-suite checks provide
exact-head verification.

## Risks

- Apply migration 0347 before enabling a runtime subscriber. Runtime
notifications require session-level PostgreSQL LISTEN. Transaction-mode
poolers are unsupported for this opt-in feature.
- Database triggers share the mutation transaction. Journal failure
prevents configuration commits. Trigger work adds a journal insert to
relevant changes.
- Filesystem publication and SQL commit are separate boundaries. Direct
filesystem edits do not emit hooks. External clients must fence stale
revisions and retain conditional-write checks.
- The reader returns only that plugin's own instance secrets. Keep them
out of UI data, logs, plugin state, and agent files.
- No private transport integration or live remote computer qualification
is included.

## Model Used

OpenAI Codex, GPT-6, with reasoning, repository inspection, code
execution, and testing. The exact deployment model ID and context window
are not exposed in this session.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` /
`Closes: #` / `Refs: #` OR (b) described the issue in-PR following the
relevant issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub references)
- [x] My branch name describes the change and contains no internal
Paperclip ticket id
- [x] I have run tests locally and they pass (focused suites; broad
local limitation documented above)
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-16 07:53:04 -07:00

6.8 KiB
Raw Blame History

navigation
navigation
section sectionOrder order
Apps, channels, and extensions 50 60

Plugins

Operators install and configure plugins, inspect their status and errors, and use their contributed pages, tools, and managed resources within the plugin’s granted capabilities.

Implementation: plugin manager, plugin settings, plugin page.

Agent access: companion.

Sub-features

  • installation: install a trusted test package or local development plugin through supported controls.
  • configuration: save validated configuration and inspect activation/failure state.
  • contributions: open plugin routes, settings, tools, and contributed resource tabs.
  • lifecycle: disable/remove or reload a disposable plugin and observe cleanup.

How to get to it (user POV)

plugin-administration

Open Settings → Plugins where permitted, or the CLI plugin commands.

plugin-contribution

Open /plugins/:pluginId, a registered plugin route, or its contributed company/project settings surface.

Driving it with Playwright and the Paperclip CLI

Preconditions: follow the baseline. Use a known local fixture plugin with bounded capabilities. Record installed version and any declared external dependencies.

plugin-administration

Automated: install authorization and plugin settings cover route/UI contracts.

Manual: Install the fixture, supply its configuration, activate it, and inspect status. Save an invalid configuration and verify a useful error. Disable/remove the disposable plugin and check its tools and managed resources no longer behave as active.

plugin-contribution

Automated: static plugin UI and company settings contribution cover serving/host behavior.

Manual: Open the contributed page by navigation and cold deep link, perform a harmless plugin action, and inspect its real outcome. Switch company and test an actor without the capability. Reload with the plugin unavailable and verify the host reports that state.

Gotchas

  • Installation/lifecycle is instance-level; configuration can be company-scoped. Settings lives at /company/settings/instance/plugins. npm installation and bundled-local installation are different controls. Developer file-watcher reload is not a lifecycle action in the plugin manager.

  • Installing a plugin does not authorize every host capability or external action.

  • Runtime synchronization is opt-in and uses durable resource delivery. See the contract and database regressions.

  • Plugin-provided routes are dynamic; this map covers the host lifecycle, not every third-party feature.

  • Environment-driver plugins also need the environment checks.

Storybook verification

installation

Scope: ui Storybook: Mount PluginManager trusted package and bundled-local choices, pending install, validation/recoverable error and installed status. Production: POST /plugins/install on a disposable package; enforce instance install authority, trusted path/package validation and correct version. Package and local install are distinct. Sources: Source: PluginManager.tsx, plugins.ts, plugin-install-guard.ts. Tests: plugin-install-route-security.test.ts, plugin-install-autobuild.test.ts, plugin-routes-authz.test.ts

configuration

Scope: ui Storybook: Mount PluginSettings valid/invalid schema inputs, saved configuration, pending/failure and unavailable plugin. Production: GET/POST /plugins/{id}/config and POST config/test must preserve validation/company scope and deliver saved config to real plugin worker/startup. Sources: Source: PluginSettings.tsx, plugins.ts, plugin-config-validator.ts. Tests: PluginSettings.test.tsx, plugin-config-startup-delivery.test.ts, plugin-routes-authz.test.ts

contributions

Scope: ui Storybook: Mount PluginPage and CompanySettingsPluginPage contributed routes/tabs, loading, missing/unavailable plugin and action failures with a known fixture plugin. Production: Serve real static plugin UI; enforce bridge data/action host capabilities and company boundaries; exercise a harmless action and cold deep link. Sources: Source: PluginPage.tsx, CompanySettingsPluginPage.tsx, plugins.ts, plugin-ui-static.ts. Tests: PluginPage.test.tsx, CompanySettingsPluginPage.test.tsx, plugin-ui-static.test.ts, plugin-tenant-isolation.test.ts

lifecycle

Scope: ui Storybook: Mount PluginManager active/disabled/uninstall/upgrade pending and failures; distinguish operator controls from developer watcher reload. Production: POST enable/disable and DELETE /plugins/{id} must stop worker/tool/managed-resource activity and clean owned resources; verify disposable restart/uninstall and developer watcher separately. Sources: Source: PluginManager.tsx, plugins.ts, plugin-lifecycle.ts, plugin-dev-watcher.ts. Tests: plugin-lifecycle-restart.test.ts, plugin-routes-authz.test.ts, plugin-dev-watcher.test.ts

Documentation scope: Plugins, gateways, and tool profiles

Host plugin/gateway/profile lifecycles are mapped. Third-party plugin behaviors and every client transport/provider combination are outside host-wide coverage.