[plugin sdk] Add workflow action, outbound, scheduler, and retry host seams#72383
[plugin sdk] Add workflow action, outbound, scheduler, and retry host seams#72383100yenadmin wants to merge 29 commits intoopenclaw:mainfrom
Conversation
Greptile SummaryThis PR adds the runtime seams for advanced workflow plugins: plugin-attributed agent event emission ( Two minor issues worth addressing: the finalize retry budget map accumulates entries without cleanup, and Confidence Score: 4/5Safe to merge; the two P2 findings are non-blocking and don't affect correctness on the happy path. No P0 or P1 issues found. Two P2 issues: (1) the finalize retry budget map is never pruned, causing gradual memory growth in long-running processes; (2) an invalid src/agents/harness/lifecycle-hook-helpers.ts (retry budget leak) and src/plugins/host-hook-workflow.ts (invalid date handling in resolveSchedule) Prompt To Fix All With AIThis is a comment left during a code review.
Path: src/agents/harness/lifecycle-hook-helpers.ts
Line: 95-113
Comment:
**Retry budget map grows without bound**
The `FINALIZE_RETRY_BUDGET_KEY` singleton `Map<string, number>` is written on every finalize retry invocation but never pruned. Each unique `(runId + instruction)` pair adds a permanent entry that survives for the life of the process. Since `runId` changes every agent run, a long-running server that regularly triggers finalize retries will accumulate one entry per retry-eligible run indefinitely.
The budget map should be cleared when a run terminates — either by hooking into the terminal lifecycle event in `dispatchPluginAgentEventSubscriptions` (which already clears `runContextByRunId` on end/error) or by adding a cleanup step to `clearPluginHostRuntimeState`.
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/host-hook-workflow.ts
Line: 147-148
Comment:
**Invalid `at` date throws unhandled `RangeError`**
If a plugin passes an invalid date string as `params.at`, `new Date(params.at)` produces an `Invalid Date` object and the immediately following `.toISOString()` call throws `RangeError: Invalid time value`. Because there is no `try/catch` in `schedulePluginSessionTurn`, this propagates as a rejected Promise rather than the documented `undefined` return. A `isNaN(at.getTime())` guard before calling `toISOString()` would fix this.
```suggestion
const at = params.at instanceof Date ? params.at : new Date(params.at);
if (isNaN(at.getTime())) {
return undefined;
}
return { kind: "at", at: at.toISOString() };
```
How can I resolve this? If you propose a fix, please make it concise.Reviews (1): Last reviewed commit: "fix(plugin-sdk): type priority next-turn..." | Re-trigger Greptile |
There was a problem hiding this comment.
Pull request overview
This PR extends the Plugin SDK + runtime with “workflow host seams” that let advanced plugins coordinate durable session state, UI descriptors, outbound events/attachments, scheduler-driven wakeups, and bounded finalize retries—without embedding any product-specific workflow implementation.
Changes:
- Add new host-hook contracts/types and registry plumbing for session extensions, next-turn injections (incl. priority), trusted tool policies, tool metadata, control UI descriptors, agent event subscriptions, run context, session scheduler jobs, and session actions.
- Wire new seams through the gateway (new RPC methods + schemas), session row projection, cleanup paths (reset/delete/reload), and tool policy enforcement.
- Update embedded runner prompt-building to drain next-turn injections once per run (cache) and support new hook types (
agent_turn_prepare,heartbeat_prompt_contribution) + appendContext.
Reviewed changes
Copilot reviewed 80 out of 80 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 entries for new host-hook-related files. |
| test/helpers/plugins/plugin-api.ts | Extends test plugin API stub with new host-hook seam methods. |
| src/wizard/setup.plugin-config.test.ts | Adjusts mocks for plugin-registry/manifest interactions. |
| src/plugins/update.test.ts | Resets modules before dynamic import to avoid mock/module leakage. |
| src/plugins/types.ts | Re-exports host-hook types; extends plugin command result and command definition fields; adds new OpenClawPluginApi methods. |
| src/plugins/trusted-tool-policy.ts | Implements bundled-only trusted tool policy evaluation chain. |
| src/plugins/synthetic-auth.runtime.test.ts | Updates test typing for syntheticAuthRefs field. |
| src/plugins/status.ts | Propagates syntheticAuthRefs into plugin status records. |
| src/plugins/status.test-helpers.ts | Extends plugin load result helper with host-hook registry arrays. |
| src/plugins/runtime.ts | Adds agent-event bridge subscription lifecycle + cleanup on registry swap/reset. |
| src/plugins/registry.ts | Adds registration/validation + API wiring for host-hook seams; adds reserved-command ownership handling; adds operator-scope validation helpers. |
| src/plugins/registry-types.ts | Extends PluginRegistry/PluginRecord types to include host-hook registrations and syntheticAuthRefs. |
| src/plugins/registry-empty.ts | Initializes empty registry with new host-hook arrays. |
| src/plugins/public-surface-loader.test.ts | Adds vi.resetModules() to stabilize module/mocking behavior across tests. |
| src/plugins/provider-auth-choices.test.ts | Switches to dynamic imports + module resets; adds manifest-registry mock; resets provider-auth alias cache. |
| src/plugins/loader.ts | Threads syntheticAuthRefs into plugin record creation and load paths. |
| src/plugins/installed-plugin-index-record-builder.ts | Copies syntheticAuthRefs defensively when building installed index records. |
| src/plugins/install.npm-spec.test.ts | Uses dynamic import after vi.resetModules() for stable module state in tests. |
| src/plugins/host-hooks.ts | Defines host-hook public types (session extensions/actions, UI descriptors, events, scheduler, run context, attachments, etc.) + injection context builder. |
| src/plugins/host-hook-workflow.ts | Implements emitAgentEvent, session attachment send, and session turn scheduling via cron. |
| src/plugins/host-hook-turn-types.ts | Defines next-turn injection types + new hook event/result types for turn prepare and heartbeat prompt contributions. |
| src/plugins/host-hook-state.ts | Implements durable session extension storage, enqueue/drain for next-turn injections (incl. TTL/priority), and projection logic. |
| src/plugins/host-hook-runtime.ts | Implements run-scoped plugin context store + agent event dispatch + scheduler job tracking/cleanup. |
| src/plugins/host-hook-json.ts | Defines JSON-compat types and runtime validation helper isPluginJsonValue. |
| src/plugins/host-hook-cleanup.ts | Implements deterministic cleanup for plugin-owned session state, runtime lifecycles, scheduler jobs, and run context. |
| src/plugins/hooks.ts | Adds agent_turn_prepare and heartbeat_prompt_contribution hook runners; adds context mapping to inject getSessionExtension into tool-hook contexts; preserves finalize retry merge behavior. |
| src/plugins/hook-types.ts | Extends hook name set + handler map; adds new hook types and appendContext; adds retry option to before_agent_finalize results; adds getSessionExtension to tool hook context. |
| src/plugins/hook-before-agent-start.types.ts | Adds appendContext to before_prompt_build result and prompt mutation field list. |
| src/plugins/contracts/host-hook-fixture.ts | Adds a generic fixture plugin registering the new host-hook seams. |
| src/plugins/commands.ts | Enforces requiredScopes for gateway-invoked plugin commands, with admin override. |
| src/plugins/commands.test.ts | Adds coverage for reserved-command bypass not applying to native aliases. |
| src/plugins/command-registration.ts | Adds reserved-command checks and optional bypass for bundled plugins claiming reserved ownership. |
| src/plugins/channel-plugin-ids.test.ts | Expands mocks/fixtures for manifest registry split loads and installed index snapshot integration. |
| src/plugins/captured-registration.ts | Captures registrations for the new host-hook seam methods in test harness. |
| src/plugins/bundled-runtime-deps.test.ts | Refactors child_process mocking + dynamic import for stable module state. |
| src/plugins/api-builder.ts | Extends API builder with no-op implementations for new seam methods. |
| src/plugin-sdk/plugin-entry.ts | Re-exports new host-hook types through plugin SDK entry surface. |
| src/plugin-sdk/core.ts | Re-exports new host-hook types through plugin SDK core surface. |
| src/hooks/install.test.ts | Refactors to dynamic imports + stable exec mocking across tests. |
| src/gateway/test-helpers.plugin-registry.ts | Extends stub registry with 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 gateway session rows. |
| src/gateway/session-reset-service.ts | Runs plugin host cleanup on session reset/delete paths. |
| src/gateway/server-methods/tools-catalog.ts | Projects plugin tool metadata (displayName/description/risk/tags) into tools.catalog response. |
| src/gateway/server-methods/sessions.ts | Adds sessions.pluginPatch handler to mutate registered plugin session extension namespaces. |
| src/gateway/server-methods/plugin-host-hooks.ts | Adds gateway handlers for plugins.uiDescriptors and plugins.sessionAction. |
| src/gateway/server-methods.ts | Registers new plugin host hook gateway handlers. |
| src/gateway/server-methods-list.ts | Adds method names for new gateway RPC methods. |
| src/gateway/protocol/schema/types.ts | Exposes new schema-derived protocol types for plugin host hook methods. |
| src/gateway/protocol/schema/sessions.ts | Adds schemas for sessions.pluginPatch params/results. |
| src/gateway/protocol/schema/protocol-schemas.ts | Registers new schemas for plugin-related gateway methods and sessions.pluginPatch. |
| src/gateway/protocol/schema/plugins.ts | Adds schema definitions for plugin UI descriptors and session action RPC. |
| src/gateway/protocol/schema/agents-models-skills.ts | Extends tool catalog/effective tool schemas with risk/tags fields. |
| src/gateway/protocol/schema.ts | Re-exports plugin schemas. |
| src/gateway/protocol/index.ts | Adds AJV validators for new gateway methods and re-exports schemas. |
| src/gateway/operator-scopes.ts | Adds KNOWN_OPERATOR_SCOPES and isOperatorScope validator. |
| src/gateway/method-scopes.ts | Adds method-to-scope mappings for the new plugin gateway methods and sessions.pluginPatch. |
| src/config/sessions/types.ts | Adds persisted session fields for plugin extensions and next-turn injection queue records. |
| src/auto-reply/reply/commands-plugin.ts | Strips continueAgent from reply payload and sets shouldContinue accordingly. |
| src/auto-reply/reply/commands-plugin.test.ts | Adds test to ensure continueAgent doesn’t leak into reply payload. |
| src/agents/tools-effective-inventory.types.ts | Extends effective tool inventory entries with risk/tags. |
| src/agents/tools-effective-inventory.ts | Projects plugin tool metadata into effective inventory entries. |
| src/agents/tools-effective-inventory.test.ts | Adds coverage for projecting plugin tool metadata into effective inventory. |
| src/agents/pi-tools.before-tool-call.ts | Runs trusted tool policies before normal hooks; unifies approval flow; preserves trusted-policy param rewrites. |
| src/agents/pi-tools.before-tool-call.integration.e2e.test.ts | Adds assertion that tool execute path still runs after policy/hook integration. |
| src/agents/pi-tools.before-tool-call.embedded-mode.test.ts | Adds tests for trusted-policy approval routing and param preservation; ensures plugin registry reset. |
| src/agents/pi-tool-definition-adapter.ts | Ensures before_tool_call receives normalized params record. |
| src/agents/pi-embedded-runner/run/attempt.ts | Applies appendContext during prompt construction. |
| src/agents/pi-embedded-runner/run/attempt.test.ts | Updates prompt hook result expectations for appendContext and new hook names. |
| src/agents/pi-embedded-runner/run/attempt.prompt-helpers.ts | Drains next-turn injections, runs new hooks, adds run-scoped drain cache and appendContext composition; supports heartbeat-only contributions. |
| src/agents/pi-embedded-runner/run/attempt.prompt-helpers.test.ts | Adds tests for drain cache behavior and re-drain after eviction/forget. |
| src/agents/pi-embedded-runner/run.ts | Clears per-run drain cache on run termination. |
| src/agents/harness/lifecycle-hook-helpers.ts | Adds bounded finalize retry handling using a global retry budget keyed by run/idempotency. |
| docs/plugins/sdk-overview.md | Documents new workflow host hook seams at the SDK level. |
| docs/plugins/hooks.md | Documents new hook names, trusted tool policy behavior, session extensions/injections, and cleanup semantics. |
| docs/.generated/plugin-sdk-api-baseline.sha256 | Updates generated SDK API baseline hashes. |
| apps/shared/OpenClawKit/Sources/OpenClawProtocol/GatewayModels.swift | Updates Swift gateway models for new protocol types and fields (pluginPatch, tool risk/tags, UI descriptors). |
| apps/macos/Sources/OpenClawProtocol/GatewayModels.swift | Same Swift protocol model updates for macOS target. |
| CHANGELOG.md | Adds changelog entry for the new Plugin SDK host hooks. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 881a0ee4c0
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
Codex automated review: keeping this open. Keep this PR open. Current main contains the merged #72287 host-hook foundation, but it still does not implement this PR’s workflow action dispatch, host-mediated outbound attachments, scheduled session wakeups, priority next-turn ordering, plugin-emitted workflow events through OpenClawPluginApi, or bounded finalize-retry contract. The PR is an active public SDK/Gateway contract change with security-sensitive review threads, not conservative cleanup. Best possible solution: Keep this PR open as the workflow-seam implementation layer above #72287. Maintainers should review or reject the proposed SDK/Gateway contracts explicitly, resolve the remaining security-sensitive review threads, and require protocol/API generation plus focused host-hook contract tests before landing. If the APIs are accepted, this PR or an equivalent implementation should add typed session actions, host-mediated attachments, scheduled session turns, priority next-turn injections, trusted session reads, and bounded finalize retry semantics on top of the already-merged foundation. What I checked:
Remaining risk / open question:
Codex Review notes: model gpt-5.5, reasoning high; reviewed against ad57a6d61658. |
881a0ee to
812b52e
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 812b52e6ec
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
…gisterToolMetadata doc Address Copilot review threads on PR openclaw#72383: 1. schema/plugins.ts: PluginJsonValueSchema used Type.This() inside a Type.Union without a recursive scope, which produces an invalid schema (unresolved $ref) at AJV compile time. Wrap the union in Type.Cyclic({...}, "PluginJsonValue") with explicit Type.Ref. Targeted vitest passes 54/54 across src/gateway/protocol. 2. plugins/types.ts: registerToolMetadata docstring claimed it applies to "plugin-owned or core tool", but the registry + projection logic intentionally scopes to (pluginId, toolName) so plugins cannot decorate other plugins' tools or core tools. Updated the doc to match.
…cy params + correct CHANGELOG PR ref Address Copilot review threads on PR openclaw#72383: 1. protocol/schema/plugins.ts + server-methods/plugin-host-hooks.ts: plugin session-action failures (`{ ok: false, error, code?, details? }`) are now returned as a successful RPC with `ok: false` + typed error fields, not as transport-level errorShape. Schema now declares `error?`, `code?`, `details?` on the result. Distinguishes plugin- declared failures from transport-level RPC failures (validation, schema mismatch, dispatch error). 2. trusted-tool-policy.ts: `decision.params` is validated as a plain object via `isPlainObject` before being applied. A buggy trusted policy returning a non-object (string/array/primitive) no longer propagates into the tool runtime / `before_tool_call` hooks. Fixes the matching pi-tools.before-tool-call.ts:446 concern at the source. 3. CHANGELOG.md: corrected the entry to describe THIS PR's content (workflow action, outbound, scheduler, retry host seams + protocol surfaces) and reference (openclaw#72383) instead of (openclaw#72287).
…ionActionResultSchema
Per copilot review on plugins.ts:69 — `plugins.sessionAction` returns plugin-
declared failures as a successful RPC with `{ ok: false, error, code?, details? }`
(see server-methods/plugin-host-hooks.ts:119), but the schema only allowed
`{ ok, result?, continueAgent?, reply? }` with `additionalProperties: false`.
Generated clients (Swift, etc.) would either drop the failure fields or fail to
decode the response. The previous commit (89444ba1) updated the server but the
schema patch was missed; this completes the contract by adding optional
`error`, `code`, `details` to the result so the wire shape and the schema agree.
…ompt hooks present Per chatgpt-codex P2 review on prepare.ts:331 — eagerly invoking `loadOpenClawHistoryMessages()` on every CLI run forces avoidable disk read + JSON parse latency even when the registered hook set never reads `messages`. The previous (pre-PR) call site had a `hasHooks(...)` guard; restore the equivalent gate at the callsite by checking whether the registered hooks include any of the message-consuming hooks (`agent_turn_prepare`, `before_prompt_build`, `before_agent_start`) before loading. `heartbeat_prompt_contribution` does not consume messages and is intentionally excluded.
1a27d30 to
c082aa3
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f7e3cd4f1f
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f87a9f1a29
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 99c09bd962
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f3902bec88
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c5512d062b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f90a6f400b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if (action.schema !== undefined && !isPluginJsonValue(action.schema)) { | ||
| pushDiagnostic({ | ||
| level: "error", | ||
| pluginId: record.id, | ||
| source: record.source, | ||
| message: `session action schema must be JSON-compatible: ${id}`, | ||
| }); |
There was a problem hiding this comment.
Reject invalid session action schemas during registration
registerSessionAction only checks action.schema for JSON compatibility, so non-object or malformed JSON Schema values can be accepted into the registry and only fail later at request time (plugins.sessionAction checks object shape and then compiles/uses the schema). In practice, a JS plugin can register an action that appears valid at load time but will always return request/dispatch errors when invoked, which turns a registration contract issue into a runtime failure path. Validate schema shape/compilability when registering the action so broken schemas are surfaced as diagnostics before the plugin is activated.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ddc7ff033e
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| return registerPluginSessionSchedulerJob({ | ||
| pluginId: params.pluginId, | ||
| pluginName: params.pluginName, | ||
| job: { | ||
| id: jobId, |
There was a problem hiding this comment.
Prune completed session-turn jobs from runtime registry
schedulePluginSessionTurn always registers each created cron job in runtime state, and the default name path generates unique IDs (randomUUID) so repeated one-shot scheduling continuously adds new entries. Those entries are only removed during explicit host cleanup (disable/reset/delete), not when deleteAfterRun jobs fire and disappear, so long-lived plugins that schedule many wakeups will accumulate stale scheduler records and growing in-memory state.
Useful? React with 👍 / 👎.
| if (result && result.ok === false) { | ||
| if (typeof result.error !== "string" || !result.error.trim()) { | ||
| respond( |
There was a problem hiding this comment.
Reject failure-shaped action results without ok=false
The failure path is only selected when result.ok === false, so untyped/JS plugin handlers that return { error: "..." } (or code/details) without an explicit ok: false fall through to the success response and are returned as { ok: true }. This silently hides plugin-declared failures from clients and can make UI/automation treat failed actions as successful; these failure fields should be rejected unless ok is explicitly false.
Useful? React with 👍 / 👎.
|
Superseded by #73384 now that #72287 has merged.\n\nThis PR's workflow action, outbound attachment, scheduler, finalize-retry, validation, and cleanup work has been preserved in the consolidated follow-up branch with the original commit history retained for review order. Please move review and CI attention to #73384 so maintainers have one current |
Summary
Follow-up to #72287 that adds the generic workflow seams needed by plugins that coordinate multi-step host workflows: typed Control UI actions, outbound session attachments, host-mediated session wakeups, trusted policy reads, priority next-turn injections, and bounded finalize retry preservation.
This remains generic plugin infrastructure. It does not add Plan Mode product logic, prompts,
/planbehavior, Telegram behavior, or bundled Plan Mode UI. The point is to make workflow plugins possible through host contracts instead of one-off core patches.Current update: the earlier long-form maintainer explanation was accidentally compressed during stack-status cleanup. This body restores/reconstructs that explanation and keeps later status updates as comments rather than replacing the PR description.
Expansion note: This follow-up grew during the final hardening pass from workflow affordances into production-safe host-mediated actions, attachments, scheduling, retry, and cleanup semantics. The added detail is intentional: maintainers should see both the unique workflow-seam scope and the inherited lower-stack diff noise.
Stack Position
Review this PR after #72287 conceptually. It depends on the foundation contracts, then adds the host workflow operations that real plugins need once they can own state, descriptors, policy, and next-turn context.
What This Adds
plugins.sessionActionsendSessionAttachmentscheduleSessionTurnbefore_agent_finalizeretry preservationagent_turn_prepareapply in CLI prompt assembly too.Workflow Diagram
sequenceDiagram autonumber participant UI as Control UI participant GW as Gateway participant Plugin participant State as Plugin Session State participant Queue as Next-turn Queue participant Scheduler participant Runner UI->>GW: plugins.sessionAction({pluginId, actionId, sessionKey, params}) GW->>Plugin: validate and dispatch action Plugin->>State: update plugin-owned JSON state Plugin->>Queue: enqueue priority next-turn injection Plugin-->>GW: typed JSON result GW-->>UI: render action result Plugin->>Scheduler: scheduleSessionTurn for follow-up if needed Scheduler->>Runner: wake session at due time Runner->>Queue: drain priority injections Runner->>Plugin: agent_turn_prepare / finalization hooksWhy This Is Separate From #72287
#72287 creates the foundation: state, descriptors, trusted policy, events, scheduler ownership, run context, cleanup, metadata, and prompt injection. This PR adds the higher-level workflow operations that use those foundations:
That split keeps the foundation reviewable while still proving that the host-hook model can support real workflows.
What This Enables Beyond Plan Mode
Concrete plugin classes:
Safety And Production Boundaries
ok:falseresults rather than crashing the workflow.Non-Scope
This PR does not implement a Plan Mode product plugin. It intentionally avoids:
/plancommand behaviorThose should be built on top of these generic seams after the host contracts are accepted.
Validation
Focused validation run for this branch/stack:
pnpm test 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 --checkAdditional inherited/follow-up validation from the stack is tracked in PR comments so the body stays focused on what this PR contributes.