[plugin sdk] Add advanced workflow plugin contract fixtures#72384
[plugin sdk] Add advanced workflow plugin contract fixtures#72384100yenadmin wants to merge 37 commits intoopenclaw:mainfrom
Conversation
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
There was a problem hiding this comment.
Pull request overview
Adds SDK-first “advanced workflow” plugin contract fixtures and integration tests, along with the supporting host-hook seams (session extensions, next-turn injections, trusted tool policy, Control UI descriptors, agent events, scheduler ownership/cleanup, run context, and scoped session actions) needed to exercise these workflows end-to-end through the registry, gateway, hooks, and runtime.
Changes:
- Introduces host-hook types + runtime/state/cleanup/workflow helpers and wires them into plugin registry/runtime, gateway handlers, session rows, and tool policy execution order.
- Adds reusable advanced workflow fixtures + contract tests covering UI descriptor projection, session actions, policy gating, scheduling/cleanup, attachments, and finalize-retry control.
- Expands protocol schemas/client models and tool catalog/effective inventory projections to include plugin tool metadata (risk/tags) and new plugin host-hook gateway methods.
Reviewed changes
Copilot reviewed 82 out of 82 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| test/scripts/lint-suppressions.test.ts | Adds lint suppression expectations for new host-hook-related files. |
| test/helpers/plugins/plugin-api.ts | Extends test plugin API stub with new host-hook methods. |
| src/wizard/setup.plugin-config.test.ts | Updates mocks to account for plugin-registry manifest registry wiring. |
| src/plugins/update.test.ts | Resets module state before dynamic import to avoid cross-test cache issues. |
| src/plugins/types.ts | Re-exports host-hook types; extends command result with continueAgent; adds command scopes/ownership; extends OpenClawPluginApi host-hook surface. |
| src/plugins/trusted-tool-policy.ts | Implements trusted (bundled-only) pre-tool policy runner. |
| src/plugins/synthetic-auth.runtime.test.ts | Adjusts snapshot typing for syntheticAuthRefs. |
| src/plugins/status.ts | Projects syntheticAuthRefs into plugin status record. |
| src/plugins/status.test-helpers.ts | Updates plugin load result test helper with new registry arrays. |
| src/plugins/runtime.ts | Bridges agent events into plugin subscriptions; triggers cleanup when registries are swapped; resets bridge in tests. |
| src/plugins/registry.ts | Adds host-hook registration/validation; wires new API methods; adds reserved command ownership validation; scopes operator scope validation via isOperatorScope. |
| src/plugins/registry-types.ts | Extends PluginRegistry/PluginRecord types to include host-hook registrations + syntheticAuthRefs. |
| src/plugins/registry-empty.ts | Initializes new registry arrays in empty registry. |
| src/plugins/public-surface-loader.test.ts | Adds module reset points for isolation across mocked imports. |
| src/plugins/provider-auth-choices.test.ts | Updates mocks/import style; ensures provider auth alias cache reset; verifies manifest registry is consulted. |
| src/plugins/loader.ts | Threads syntheticAuthRefs through plugin record creation/loads. |
| src/plugins/installed-plugin-index-record-builder.ts | Clones syntheticAuthRefs into index record when present. |
| src/plugins/install.npm-spec.test.ts | Switches to resetModules + dynamic import pattern for isolation. |
| src/plugins/host-hooks.ts | Defines host-hook contract types and helpers (JSON type, session extensions, UI descriptors, actions, events, scheduler, attachments, etc.). |
| src/plugins/host-hook-workflow.ts | Implements emitAgentEvent, scheduleSessionTurn, and sendSessionAttachment host workflow helpers. |
| src/plugins/host-hook-turn-types.ts | Defines next-turn injection + new hook event/result types. |
| src/plugins/host-hook-state.ts | Implements durable session extension storage, injection enqueue/drain, and session projection. |
| src/plugins/host-hook-runtime.ts | Implements run-scoped plugin context, scheduler job tracking/cleanup, and event subscription dispatch. |
| src/plugins/host-hook-json.ts | Defines JSON-compatible value type + runtime validator. |
| src/plugins/host-hook-cleanup.ts | Implements cleanup of plugin-owned session/run/scheduler state and registry swap cleanup. |
| src/plugins/hooks.ts | Adds agent_turn_prepare + heartbeat_prompt_contribution hook execution; adds before_tool_call getSessionExtension context mapping; merges appendContext. |
| src/plugins/hook-types.ts | Adds new hook names/types, appendContext, tool ctx getSessionExtension, and finalize retry fields. |
| src/plugins/hook-before-agent-start.types.ts | Adds appendContext to before_prompt_build results and prompt mutation fields list. |
| src/plugins/contracts/host-hook-fixture.ts | Adds generic fixture plugin to exercise new host-hook surfaces. |
| src/plugins/contracts/advanced-workflow-fixtures.ts | Adds reusable workflow archetype fixtures (approval, policy gate, background monitor, artifact reply, retry control). |
| src/plugins/contracts/advanced-workflow-fixtures.contract.test.ts | Adds integration/contract tests validating host-hook seams end-to-end. |
| src/plugins/commands.ts | Enforces required gateway operator scopes for plugin commands (with admin bypass). |
| src/plugins/commands.test.ts | Adds coverage for reserved command ownership scoping vs native aliases. |
| src/plugins/command-registration.ts | Adds reserved-name helper + allowReservedCommandNames plumbing into validation/registration. |
| src/plugins/channel-plugin-ids.test.ts | Updates manifest registry / installed-index / plugin-registry mocks for startup plugin id resolution tests. |
| src/plugins/captured-registration.ts | Captures host-hook registrations during plugin registration capture. |
| src/plugins/bundled-runtime-deps.test.ts | Reworks child_process mocking + resetModules/dynamic import for isolation. |
| src/plugins/api-builder.ts | Adds no-op implementations + handler wiring for new OpenClawPluginApi host-hook methods. |
| src/plugin-sdk/plugin-entry.ts | Re-exports new host-hook types through SDK entry. |
| src/plugin-sdk/core.ts | Re-exports new host-hook types through SDK core. |
| src/hooks/install.test.ts | Reworks exec mocking + resetModules/dynamic import for isolation and typed helpers. |
| src/gateway/test-helpers.plugin-registry.ts | Extends stub plugin registry with new host-hook arrays. |
| src/gateway/session-utils.types.ts | Adds pluginExtensions projection field to GatewaySessionRow. |
| src/gateway/session-utils.ts | Projects registered plugin session extensions into session rows. |
| src/gateway/session-reset-service.ts | Runs plugin host cleanup during session reset/delete paths. |
| src/gateway/server-methods/tools-catalog.ts | Projects plugin tool metadata (displayName/description/risk/tags) into tool catalog (scoped to owning plugin). |
| src/gateway/server-methods/sessions.ts | Adds sessions.pluginPatch handler for plugin session extensions with JSON validation and session change emission. |
| src/gateway/server-methods/plugin-host-hooks.ts | Adds gateway methods for Control UI descriptors + typed plugin session actions with scope checks. |
| src/gateway/server-methods.ts | Registers new plugin host-hook gateway handlers. |
| src/gateway/server-methods-list.ts | Adds plugins.* and sessions.pluginPatch to the public method list. |
| src/gateway/protocol/schema/types.ts | Exposes new schema types for plugin host-hook methods. |
| src/gateway/protocol/schema/sessions.ts | Adds SessionsPluginPatch params/result schemas. |
| src/gateway/protocol/schema/protocol-schemas.ts | Registers new plugin-related schemas. |
| src/gateway/protocol/schema/plugins.ts | Adds schemas for plugin UI descriptors + session action calls/results. |
| src/gateway/protocol/schema/agents-models-skills.ts | Extends tool catalog/effective entry schemas with risk/tags. |
| src/gateway/protocol/schema.ts | Re-exports plugin schemas. |
| src/gateway/protocol/index.ts | Adds ajv validators/exports for new plugin + sessions.pluginPatch params. |
| src/gateway/operator-scopes.ts | Adds known-scope set + isOperatorScope guard for validating untyped plugin scope strings. |
| src/gateway/method-scopes.ts | Assigns scopes to new gateway methods (plugins.uiDescriptors/read, plugins.sessionAction/write, sessions.pluginPatch/admin). |
| src/config/sessions/types.ts | Adds persisted pluginExtensions + pluginNextTurnInjections to session store entries. |
| src/auto-reply/reply/commands-plugin.ts | Supports continueAgent from plugin command results and strips it from outbound reply payload. |
| src/auto-reply/reply/commands-plugin.test.ts | Adds coverage for continueAgent behavior and reply payload shaping. |
| src/agents/tools-effective-inventory.types.ts | Extends effective inventory entries with risk/tags. |
| src/agents/tools-effective-inventory.ts | Projects plugin tool metadata into effective inventory (scoped to owning plugin). |
| src/agents/tools-effective-inventory.test.ts | Adds coverage for metadata projection into effective inventory. |
| src/agents/pi-tools.before-tool-call.ts | Runs trusted tool policies before normal hooks; factors approval gating into shared helper; preserves policy-adjusted params. |
| src/agents/pi-tools.before-tool-call.integration.e2e.test.ts | Tightens assertion about tool execution call passthrough. |
| src/agents/pi-tools.before-tool-call.embedded-mode.test.ts | Adds tests for trusted policy approval/params behavior; ensures active registry resets. |
| src/agents/pi-tool-definition-adapter.ts | Ensures before_tool_call receives params as a record (consistent coercion). |
| src/agents/pi-embedded-runner/run/attempt.ts | Applies appendContext when building effective prompt. |
| src/agents/pi-embedded-runner/run/attempt.test.ts | Updates prompt hook resolution tests for appendContext + heartbeat-only contributions. |
| src/agents/pi-embedded-runner/run/attempt.prompt-helpers.ts | Drains next-turn injections into prompt build; adds agent_turn_prepare + heartbeat prompt contributions; adds per-run drain cache + explicit eviction. |
| src/agents/pi-embedded-runner/run/attempt.prompt-helpers.test.ts | Adds tests for run-scoped drain cache behavior. |
| src/agents/pi-embedded-runner/run.ts | Evicts drained-injection cache on run completion. |
| src/agents/harness/lifecycle-hook-helpers.ts | Adds bounded finalize retry budget enforcement keyed by run + idempotencyKey/instruction. |
| docs/plugins/sdk-overview.md | Documents new host-hook workflow plugin seams in SDK overview. |
| docs/plugins/hooks.md | Documents new hooks, trusted tool policies, and session extension/injection semantics. |
| docs/.generated/plugin-sdk-api-baseline.sha256 | Updates API baseline hashes. |
| apps/shared/OpenClawKit/Sources/OpenClawProtocol/GatewayModels.swift | Updates generated Swift gateway models for new plugin/session/tool schema fields. |
| apps/macos/Sources/OpenClawProtocol/GatewayModels.swift | Updates generated Swift gateway models for new plugin/session/tool schema fields. |
| CHANGELOG.md | Adds changelog entry describing new plugin SDK host hook capabilities. |
Greptile SummaryThis PR adds contract fixture tests for the advanced workflow plugin seams (approval workflows, policy gates, background monitors, artifact replies, and retry control) introduced in #72383, along with the runtime infrastructure they exercise (
Confidence Score: 3/5Safe to merge with caution — the retry budget leak is a real defect that will surface in watch-mode test runs and gradually in production. One P1 (retry budget never pruned, causing test isolation failure in watch mode and unbounded memory growth in production) and one P2 (inbound_claim fixture unconditionally claims all messages). The P1 is isolated to a new subsystem but the bug is definite, not speculative, capping the score at 4; the combination with a P2 pulls it to 3. src/agents/harness/lifecycle-hook-helpers.ts (retry budget Map has no cleanup path) and src/plugins/contracts/advanced-workflow-fixtures.ts (inbound_claim guard) Prompt To Fix All With AIThis is a comment left during a code review.
Path: src/agents/harness/lifecycle-hook-helpers.ts
Line: 99-115
Comment:
**Retry budget Map never pruned — test isolation bug and production leak**
The `FINALIZE_RETRY_BUDGET_KEY` global singleton `Map` accumulates one entry per unique `runId:idempotencyKey` pair and is never cleared. There is no exported helper to reset it, and `clearPluginHostRuntimeState()` only touches `runContextByRunId` and `schedulerJobsByPlugin` — it does not reach this Map.
**Test impact:** the `afterEach` in `advanced-workflow-fixtures.contract.test.ts` calls `clearPluginHostRuntimeState()` but that does nothing here. In vitest watch mode (or any scenario where the same process re-runs the test), the `"retry-run:retry-control-fixture"` key already has `count=2` from the previous run, so the first assertion (`{ action: "revise" }`) will fail and return `{ action: "continue" }` instead.
**Production impact:** every agent run that triggers a retry adds a permanent `Map` entry keyed by `runId`, which is typically a unique ID — the Map grows without bound over the lifetime of the process.
A minimal fix is to expose a reset function (e.g. `clearFinalizeRetryBudgetForTest`) and call it from both `clearPluginHostRuntimeState` (or an equivalent test-reset utility) and the `afterEach` block in the test. Alternatively, treat terminal lifecycle events as the cleanup trigger, the same way `clearPluginRunContext` is called from `dispatchPluginAgentEventSubscriptions`.
How can I resolve this? If you propose a fix, please make it concise.
---
This is a comment left during a code review.
Path: src/plugins/contracts/advanced-workflow-fixtures.ts
Line: 90-93
Comment:
**`inbound_claim` guard ignores session approval state**
The handler unconditionally returns `handled: true` regardless of whether an approval is actually in `pending` state in the session store. Any message arriving after the plugin is registered — including ones that arrive after the approval resolves — will be silently swallowed with the "approval is pending" reply.
Since these are contract fixtures intended to guide plugin authors, a more accurate fixture would read the approval extension state (which the event context provides via `sessionKey`) and only claim the message when `status === "pending"`. As written, the fixture demonstrates the hook signature correctly but models incorrect conditional-guard behavior that could mislead implementors.
How can I resolve this? If you propose a fix, please make it concise.Reviews (1): Last reviewed commit: "fix(plugin-sdk): align inbound guard fix..." | Re-trigger Greptile |
|
Codex automated review: keeping this open. Keep this PR open. Current main has the merged foundation host-hook contracts, but it does not contain this PR’s unique advanced workflow fixture files or the workflow action/outbound/scheduler/finalize-retry SDK seams those fixtures exercise. It is also stacked on same-author open #72383, so it remains an active implementation candidate rather than conservative cleanup material. Best possible solution: Keep this PR open as the advanced workflow contract-fixture layer. Review or resolve #72383 first, then rebase this PR and review the unique fixture files against the accepted workflow APIs with focused contract and security validation for session actions, outbound attachments, scheduled turns, priority next-turn injections, trusted policy state reads, cleanup, and bounded finalize retry behavior. What I checked:
Remaining risk / open question:
Codex Review notes: model gpt-5.5, reasoning high; reviewed against fb40ed99a7f0. |
55212de to
030be78
Compare
030be78 to
e0ee915
Compare
dbb44c4 to
728c3b4
Compare
728c3b4 to
153ca0b
Compare
153ca0b to
120a26f
Compare
120a26f to
8505ecc
Compare
8505ecc to
bec2e71
Compare
bec2e71 to
8f3104d
Compare
8f3104d to
4e9b4e5
Compare
4e9b4e5 to
c6bfbc7
Compare
|
Superseded by #73384 now that #72287 has merged.\n\nThe advanced workflow fixture proofs from this PR are included in the consolidated follow-up after the workflow seam commits. The fixture commits are still separate in #73384 so reviewers can inspect the approval, policy gate, background monitor, artifact reply, and finalize-retry examples without chasing inherited stack noise here. |
Summary
Contract-fixture follow-up to #72287 and #72383. This PR adds advanced workflow fixtures that exercise the generic host-hook seams as realistic plugin archetypes, without adding product-specific Plan Mode behavior.
The purpose is proof, not product. The fixtures show that the foundation and workflow seams compose into deploy approvals, policy gates, background monitors, artifact replies, and finalize retry control through SDK contracts alone.
Current update: the earlier detailed maintainer explanation was accidentally compressed during stack cleanup. This body restores/reconstructs the detailed explanation and keeps current stack/check status in comments.
Expansion note: This fixture PR grew from proof tests into a realistic adversarial fixture suite after the hardening pass found places where contracts needed executable examples. Its unique purpose is to demonstrate plugin archetypes over the generic seams, not to add product behavior.
Stack Position
Review this PR as the executable proof layer. It should not be judged as product code for Plan Mode; it is a contract-fixture suite showing that multiple plugin classes can be implemented with the generic seams.
Fixture Archetypes
What Each Fixture Proves
before_agent_finalizeretry.End-To-End Composition
Why These Fixtures Matter
Contract fixtures are the difference between "the SDK has many methods" and "the host guarantees these workflows keep working." These tests make the expected composition explicit:
Review Hardening Included
Non-Scope
This is not Plan Mode product implementation:
/plancommand behaviorPlan Mode can later reuse the same seams, but these fixtures remain generic deploy/compliance/SLA/artifact/review archetypes.
Validation
Focused validation run for this branch/stack:
pnpm test src/plugins/contracts/advanced-workflow-fixtures.contract.test.ts src/plugins/contracts/host-hooks.contract.test.ts src/agents/harness/lifecycle-hook-helpers.test.ts src/plugins/hooks.before-agent-finalize.test.tspnpm plugin-sdk:api:checkgit diff --check