Repository navigation
feat: add the execution-history plugin - #13
Conversation
Greptile SummaryAdds
Confidence Score: 5/5Safe to merge — all blocking issues from the prior review round are addressed and no new defects were found in the changed code. The buffer-cleanup guarantee, the ExecutionFinished fallthrough fix, the RunStatus validation, and the pagination display fix are all correctly implemented. The two remaining findings are both non-blocking suggestions (interaction kind defensive guard and a spurious "none" atom fetch on initial render). No files require special attention — the core write path in store.ts and the HTTP handler wiring are solid. Important Files Changed
Sequence DiagramsequenceDiagram
participant Engine as Execution Engine
participant Observer as ExecutionObserver
participant Store as ExecutionHistoryStore
participant Buffer as RunBuffer (in-memory)
participant Storage as PluginStorage (D1/sqlite)
participant API as HTTP API
participant UI as Runs Page (React)
Engine->>Observer: ExecutionStarted
Observer->>Store: handleEvent
Store->>Buffer: buffers.set(executionId, ...)
Store->>Storage: runsC.put(status: running)
Engine->>Observer: ToolCallStarted / ToolCallFinished
Observer->>Store: handleEvent
Store->>Buffer: buffer.toolCalls.set(...)
Engine->>Observer: InteractionStarted
Observer->>Store: handleEvent
Store->>Buffer: buffer.interactions.set(...)
Store->>Storage: runsC.put(status: waiting_for_interaction)
Engine->>Observer: InteractionResolved
Observer->>Store: handleEvent
Store->>Buffer: buffer.interactions.set(...updated)
Engine->>Observer: ExecutionFinished
Observer->>Store: handleEvent
Store->>Storage: "runsC.put(terminal) + toolCallsC.put* + interactionsC.put*"
Store->>Buffer: buffers.delete(executionId) via Effect.ensuring
UI->>API: GET /execution-history/runs
API->>Storage: runsC.query + runsC.count
API-->>UI: runs + total
UI->>API: GET /execution-history/runs/:id
API->>Storage: runsC.get + toolCallsC.query + interactionsC.query
API-->>UI: RunDetailResponse
Reviews (4): Last reviewed commit: "fix(plugin-execution-history): address G..." | Re-trigger Greptile |
08a80c1 to
11d40f4
Compare
915777b to
2484437
Compare
- Buffer leak: wrap the ExecutionFinished flush in Effect.ensuring so the RunBuffer is always released, even when a write fails or is interrupted. - Exhaustive dispatch: route ExecutionFinished by an explicit tag guard instead of a fallthrough, so a future ExecutionEvent variant isn't silently recorded as a finished run. - statusFilter: keep only valid RunStatus literals (Schema.is) rather than casting, so ?status=bogus can't reach the storage where-clause. - Runs page: fix the 'showing 1-0' label on an empty page; make prettyJson actually indent (decode via Schema, re-stringify with two-space indent — only JSON.parse is lint-banned).
2484437 to
1e981af
Compare
Adds the **execution-observer foundation** — the seam the history and metrics plugins build on. - New `ExecutionObserver` contract in the SDK: six tagged lifecycle events (`ExecutionStarted`/`Finished`, `ToolCallStarted`/`Finished`, `InteractionStarted`/`Resolved`) + `composeExecutionObservers`, with a `plugin.runtime.executionObserver` hook. - The execution engine emits the events (re-derived onto the current Queue-based pause model), exposes `Executor.owner`, and tags the run span with the execution id + trigger. - `makeExecutionStack` composes plugin observers — one seam covers every HTTP host and the MCP Durable Objects; local's fixed-execution + in-process MCP are wired directly. **Behaviour-neutral / opt-in:** with no plugin observing, every path is a no-op. Gates: `format:check`, `lint`, full-monorepo `typecheck`, and observer unit tests all green. Live app verification still to come. <!-- stack:links:start --> ### [Stack](https://github.com/kitlangton/stack) 1. **#12** 👈 current 2. #13 3. #14 <!-- stack:links:end -->
…nd observer New opt-in @executor-js/plugin-execution-history package. It contributes no tools — only a pure execution-history sink built on the existing pluginStorage collection facade (no new tables, no migrations; works on D1/libSQL/sqlite/ postgres uniformly, owner-scoped automatically). Three indexed collections (runs, toolCalls, interactions) back the history. The store consumes the engine's ExecutionEvent stream via runtime.executionObserver with a buffered-batch write model: the run row is written eagerly on start and on pause (durable while waiting), tool-call/interaction detail is buffered in memory and flushed as one batch on ExecutionFinished — keeping per-run writes to ~2 + one batch (important for D1's subrequest budget). The read surface (executor.executionHistory.list/get/listToolCalls) pushes filters, ordering and pagination down to SQL via the indexed query facade. code + trigger are retained across the run's re-writes (with a fallback to the persisted row if the buffer is lost).
Adds the ./api entry: an executionHistory HttpApiGroup (GET /execution-history/ runs with status/trigger/time/interaction/limit/offset/sort query params, plus /runs/:executionId and /runs/:executionId/tool-calls), a handler layer that reads the executor.executionHistory extension via an extensionService tag, and executionHistoryHttpPlugin — the HTTP-augmented variant that layers routes/ handlers/extensionService onto the base plugin. Follows the graphql/onepassword convention: the base SDK plugin (the '.' entry) never loads @executor-js/api (held as a peer/dev dep); only hosts that compose an HttpApi import the augmented plugin from /api. Routes are flat and plugin- prefixed (no :scopeId) because the per-request executor is already owner-scoped.
Adds the ./react + ./client entries: an atom HTTP client over the executionHistory API group, atoms for the runs list/detail/tool-calls, a RunsPage (runs table with status/trigger/started/duration/tool-count columns, a status filter, offset pagination, and a 4-section detail drawer — Properties, Tool calls, Logs, Interaction), and a defineClientPlugin that registers it at /plugins/executionHistory/ with a 'Runs' nav entry. Mounts through the existing /plugins/$pluginId/$ catch-all with zero router changes. Built on the existing @executor-js/react shadcn-style primitives (Table, Sheet, Tabs, Badge, Select) — no new design system or charting dep. The branch's keyboard-nav, live auto-refresh, and command-palette filter are deferred. React deps are peer/optional, mirroring the graphql plugin.
- Buffer leak: wrap the ExecutionFinished flush in Effect.ensuring so the RunBuffer is always released, even when a write fails or is interrupted. - Exhaustive dispatch: route ExecutionFinished by an explicit tag guard instead of a fallthrough, so a future ExecutionEvent variant isn't silently recorded as a finished run. - statusFilter: keep only valid RunStatus literals (Schema.is) rather than casting, so ?status=bogus can't reach the storage where-clause. - Runs page: fix the 'showing 1-0' label on an empty page; make prettyJson actually indent (decode via Schema, re-stringify with two-space indent — only JSON.parse is lint-banned).
1e981af to
a06c2d6
Compare
Adds **`@executor-js/plugin-execution-metrics`** — an opt-in metrics sink built on the observer foundation. - Base plugin drives Effect Metric counters + an execution-duration histogram from the event stream. - `./api`: an auth-gated `GET /execution-metrics/metrics` Prometheus scrape (`executionMetricsHttpPlugin`). - `./cloudflare`: a Workers Analytics Engine sink (`writeDataPoint`) — per-isolate Effect metrics being meaningless on a Worker fleet. Wired opt-in on host-cloudflare, gated on the `ANALYTICS` binding. Base `.` entry free of `@executor-js/api` and `@cloudflare/workers-types`. Stacked on the execution-observer foundation. Gates: `format:check`, `lint`, full-monorepo `typecheck`, and metrics-render tests green (an adversarial-verify pass caught + fixed a Prometheus histogram-bucket bug). <!-- stack:links:start --> ### [Stack](https://github.com/kitlangton/stack) 1. #12 2. #13 3. **#14** 👈 current <!-- stack:links:end -->
Adds the **execution-observer foundation** — the seam the history and metrics plugins build on. - New `ExecutionObserver` contract in the SDK: six tagged lifecycle events (`ExecutionStarted`/`Finished`, `ToolCallStarted`/`Finished`, `InteractionStarted`/`Resolved`) + `composeExecutionObservers`, with a `plugin.runtime.executionObserver` hook. - The execution engine emits the events (re-derived onto the current Queue-based pause model), exposes `Executor.owner`, and tags the run span with the execution id + trigger. - `makeExecutionStack` composes plugin observers — one seam covers every HTTP host and the MCP Durable Objects; local's fixed-execution + in-process MCP are wired directly. **Behaviour-neutral / opt-in:** with no plugin observing, every path is a no-op. Gates: `format:check`, `lint`, full-monorepo `typecheck`, and observer unit tests all green. Live app verification still to come. <!-- stack:links:start --> 1. **#12** 👈 current 2. #13 3. #14 <!-- stack:links:end -->
Adds **`@executor-js/plugin-execution-history`** — an opt-in execution-history sink built on the observer foundation. - Records every run (plus its tool calls and interactions) into three owner-scoped `pluginStorage` collections via a buffered-batch writer — **no new tables, no migrations**; works on D1/libSQL/sqlite/postgres. - `./api`: a scoped read API (`list`/`get`/`listToolCalls`) over HttpApi (`executionHistoryHttpPlugin`). - `./client`: a Runs page at `/plugins/executionHistory/` (table, status filter, pagination, 4-tab detail drawer) — mounts via the existing plugins catch-all with zero router changes. The base `.` entry never loads the API or React layers. Fully opt-in (not registered in any default config). Stacked on the execution-observer foundation. Gates: `format:check`, `lint`, full-monorepo `typecheck`, unit + handler tests green. Runs-page live render still to verify. <!-- stack:links:start --> ### [Stack](https://github.com/kitlangton/stack) 1. #12 2. **#13** 👈 current 3. #14 <!-- stack:links:end -->
Adds **`@executor-js/plugin-execution-metrics`** — an opt-in metrics sink built on the observer foundation. - Base plugin drives Effect Metric counters + an execution-duration histogram from the event stream. - `./api`: an auth-gated `GET /execution-metrics/metrics` Prometheus scrape (`executionMetricsHttpPlugin`). - `./cloudflare`: a Workers Analytics Engine sink (`writeDataPoint`) — per-isolate Effect metrics being meaningless on a Worker fleet. Wired opt-in on host-cloudflare, gated on the `ANALYTICS` binding. Base `.` entry free of `@executor-js/api` and `@cloudflare/workers-types`. Stacked on the execution-observer foundation. Gates: `format:check`, `lint`, full-monorepo `typecheck`, and metrics-render tests green (an adversarial-verify pass caught + fixed a Prometheus histogram-bucket bug). <!-- stack:links:start --> 1. #12 2. #13 3. **#14** 👈 current <!-- stack:links:end -->
Adds the **execution-observer foundation** — the seam the history and metrics plugins build on. - New `ExecutionObserver` contract in the SDK: six tagged lifecycle events (`ExecutionStarted`/`Finished`, `ToolCallStarted`/`Finished`, `InteractionStarted`/`Resolved`) + `composeExecutionObservers`, with a `plugin.runtime.executionObserver` hook. - The execution engine emits the events (re-derived onto the current Queue-based pause model), exposes `Executor.owner`, and tags the run span with the execution id + trigger. - `makeExecutionStack` composes plugin observers — one seam covers every HTTP host and the MCP Durable Objects; local's fixed-execution + in-process MCP are wired directly. **Behaviour-neutral / opt-in:** with no plugin observing, every path is a no-op. Gates: `format:check`, `lint`, full-monorepo `typecheck`, and observer unit tests all green. Live app verification still to come. <!-- stack:links:start --> 1. **#12** 👈 current 2. #13 3. #14 <!-- stack:links:end -->
Adds **`@executor-js/plugin-execution-history`** — an opt-in execution-history sink built on the observer foundation. - Records every run (plus its tool calls and interactions) into three owner-scoped `pluginStorage` collections via a buffered-batch writer — **no new tables, no migrations**; works on D1/libSQL/sqlite/postgres. - `./api`: a scoped read API (`list`/`get`/`listToolCalls`) over HttpApi (`executionHistoryHttpPlugin`). - `./client`: a Runs page at `/plugins/executionHistory/` (table, status filter, pagination, 4-tab detail drawer) — mounts via the existing plugins catch-all with zero router changes. The base `.` entry never loads the API or React layers. Fully opt-in (not registered in any default config). Stacked on the execution-observer foundation. Gates: `format:check`, `lint`, full-monorepo `typecheck`, unit + handler tests green. Runs-page live render still to verify. <!-- stack:links:start --> ### [Stack](https://github.com/kitlangton/stack) 1. #12 2. **#13** 👈 current 3. #14 <!-- stack:links:end -->
Adds **`@executor-js/plugin-execution-metrics`** — an opt-in metrics sink built on the observer foundation. - Base plugin drives Effect Metric counters + an execution-duration histogram from the event stream. - `./api`: an auth-gated `GET /execution-metrics/metrics` Prometheus scrape (`executionMetricsHttpPlugin`). - `./cloudflare`: a Workers Analytics Engine sink (`writeDataPoint`) — per-isolate Effect metrics being meaningless on a Worker fleet. Wired opt-in on host-cloudflare, gated on the `ANALYTICS` binding. Base `.` entry free of `@executor-js/api` and `@cloudflare/workers-types`. Stacked on the execution-observer foundation. Gates: `format:check`, `lint`, full-monorepo `typecheck`, and metrics-render tests green (an adversarial-verify pass caught + fixed a Prometheus histogram-bucket bug). <!-- stack:links:start --> 1. #12 2. #13 3. **#14** 👈 current <!-- stack:links:end -->
Adds the **execution-observer foundation** — the seam the history and metrics plugins build on. - New `ExecutionObserver` contract in the SDK: six tagged lifecycle events (`ExecutionStarted`/`Finished`, `ToolCallStarted`/`Finished`, `InteractionStarted`/`Resolved`) + `composeExecutionObservers`, with a `plugin.runtime.executionObserver` hook. - The execution engine emits the events (re-derived onto the current Queue-based pause model), exposes `Executor.owner`, and tags the run span with the execution id + trigger. - `makeExecutionStack` composes plugin observers — one seam covers every HTTP host and the MCP Durable Objects; local's fixed-execution + in-process MCP are wired directly. **Behaviour-neutral / opt-in:** with no plugin observing, every path is a no-op. Gates: `format:check`, `lint`, full-monorepo `typecheck`, and observer unit tests all green. Live app verification still to come. <!-- stack:links:start --> 1. **#12** 👈 current 2. #13 3. #14 <!-- stack:links:end -->
Adds **`@executor-js/plugin-execution-history`** — an opt-in execution-history sink built on the observer foundation. - Records every run (plus its tool calls and interactions) into three owner-scoped `pluginStorage` collections via a buffered-batch writer — **no new tables, no migrations**; works on D1/libSQL/sqlite/postgres. - `./api`: a scoped read API (`list`/`get`/`listToolCalls`) over HttpApi (`executionHistoryHttpPlugin`). - `./client`: a Runs page at `/plugins/executionHistory/` (table, status filter, pagination, 4-tab detail drawer) — mounts via the existing plugins catch-all with zero router changes. The base `.` entry never loads the API or React layers. Fully opt-in (not registered in any default config). Stacked on the execution-observer foundation. Gates: `format:check`, `lint`, full-monorepo `typecheck`, unit + handler tests green. Runs-page live render still to verify. <!-- stack:links:start --> ### [Stack](https://github.com/kitlangton/stack) 1. #12 2. **#13** 👈 current 3. #14 <!-- stack:links:end -->
Adds **`@executor-js/plugin-execution-metrics`** — an opt-in metrics sink built on the observer foundation. - Base plugin drives Effect Metric counters + an execution-duration histogram from the event stream. - `./api`: an auth-gated `GET /execution-metrics/metrics` Prometheus scrape (`executionMetricsHttpPlugin`). - `./cloudflare`: a Workers Analytics Engine sink (`writeDataPoint`) — per-isolate Effect metrics being meaningless on a Worker fleet. Wired opt-in on host-cloudflare, gated on the `ANALYTICS` binding. Base `.` entry free of `@executor-js/api` and `@cloudflare/workers-types`. Stacked on the execution-observer foundation. Gates: `format:check`, `lint`, full-monorepo `typecheck`, and metrics-render tests green (an adversarial-verify pass caught + fixed a Prometheus histogram-bucket bug). <!-- stack:links:start --> 1. #12 2. #13 3. **#14** 👈 current <!-- stack:links:end -->
Adds the **execution-observer foundation** — the seam the history and metrics plugins build on. - New `ExecutionObserver` contract in the SDK: six tagged lifecycle events (`ExecutionStarted`/`Finished`, `ToolCallStarted`/`Finished`, `InteractionStarted`/`Resolved`) + `composeExecutionObservers`, with a `plugin.runtime.executionObserver` hook. - The execution engine emits the events (re-derived onto the current Queue-based pause model), exposes `Executor.owner`, and tags the run span with the execution id + trigger. - `makeExecutionStack` composes plugin observers — one seam covers every HTTP host and the MCP Durable Objects; local's fixed-execution + in-process MCP are wired directly. **Behaviour-neutral / opt-in:** with no plugin observing, every path is a no-op. Gates: `format:check`, `lint`, full-monorepo `typecheck`, and observer unit tests all green. Live app verification still to come. <!-- stack:links:start --> 1. **#12** 👈 current 2. #13 3. #14 <!-- stack:links:end -->
Adds **`@executor-js/plugin-execution-history`** — an opt-in execution-history sink built on the observer foundation. - Records every run (plus its tool calls and interactions) into three owner-scoped `pluginStorage` collections via a buffered-batch writer — **no new tables, no migrations**; works on D1/libSQL/sqlite/postgres. - `./api`: a scoped read API (`list`/`get`/`listToolCalls`) over HttpApi (`executionHistoryHttpPlugin`). - `./client`: a Runs page at `/plugins/executionHistory/` (table, status filter, pagination, 4-tab detail drawer) — mounts via the existing plugins catch-all with zero router changes. The base `.` entry never loads the API or React layers. Fully opt-in (not registered in any default config). Stacked on the execution-observer foundation. Gates: `format:check`, `lint`, full-monorepo `typecheck`, unit + handler tests green. Runs-page live render still to verify. <!-- stack:links:start --> 1. #12 2. **#13** 👈 current 3. #14 <!-- stack:links:end -->
Adds the **execution-observer foundation** — the seam the history and metrics plugins build on. - New `ExecutionObserver` contract in the SDK: six tagged lifecycle events (`ExecutionStarted`/`Finished`, `ToolCallStarted`/`Finished`, `InteractionStarted`/`Resolved`) + `composeExecutionObservers`, with a `plugin.runtime.executionObserver` hook. - The execution engine emits the events (re-derived onto the current Queue-based pause model), exposes `Executor.owner`, and tags the run span with the execution id + trigger. - `makeExecutionStack` composes plugin observers — one seam covers every HTTP host and the MCP Durable Objects; local's fixed-execution + in-process MCP are wired directly. **Behaviour-neutral / opt-in:** with no plugin observing, every path is a no-op. Gates: `format:check`, `lint`, full-monorepo `typecheck`, and observer unit tests all green. Live app verification still to come. <!-- stack:links:start --> 1. **#12** 👈 current 2. #13 3. #14 <!-- stack:links:end -->
Adds **`@executor-js/plugin-execution-history`** — an opt-in execution-history sink built on the observer foundation. - Records every run (plus its tool calls and interactions) into three owner-scoped `pluginStorage` collections via a buffered-batch writer — **no new tables, no migrations**; works on D1/libSQL/sqlite/postgres. - `./api`: a scoped read API (`list`/`get`/`listToolCalls`) over HttpApi (`executionHistoryHttpPlugin`). - `./client`: a Runs page at `/plugins/executionHistory/` (table, status filter, pagination, 4-tab detail drawer) — mounts via the existing plugins catch-all with zero router changes. The base `.` entry never loads the API or React layers. Fully opt-in (not registered in any default config). Stacked on the execution-observer foundation. Gates: `format:check`, `lint`, full-monorepo `typecheck`, unit + handler tests green. Runs-page live render still to verify. <!-- stack:links:start --> 1. #12 2. **#13** 👈 current 3. #14 <!-- stack:links:end -->
Adds the **execution-observer foundation** — the seam the history and metrics plugins build on. - New `ExecutionObserver` contract in the SDK: six tagged lifecycle events (`ExecutionStarted`/`Finished`, `ToolCallStarted`/`Finished`, `InteractionStarted`/`Resolved`) + `composeExecutionObservers`, with a `plugin.runtime.executionObserver` hook. - The execution engine emits the events (re-derived onto the current Queue-based pause model), exposes `Executor.owner`, and tags the run span with the execution id + trigger. - `makeExecutionStack` composes plugin observers — one seam covers every HTTP host and the MCP Durable Objects; local's fixed-execution + in-process MCP are wired directly. **Behaviour-neutral / opt-in:** with no plugin observing, every path is a no-op. Gates: `format:check`, `lint`, full-monorepo `typecheck`, and observer unit tests all green. Live app verification still to come. <!-- stack:links:start --> 1. **#12** 👈 current 2. #13 3. #14 <!-- stack:links:end -->
Adds **`@executor-js/plugin-execution-history`** — an opt-in execution-history sink built on the observer foundation. - Records every run (plus its tool calls and interactions) into three owner-scoped `pluginStorage` collections via a buffered-batch writer — **no new tables, no migrations**; works on D1/libSQL/sqlite/postgres. - `./api`: a scoped read API (`list`/`get`/`listToolCalls`) over HttpApi (`executionHistoryHttpPlugin`). - `./client`: a Runs page at `/plugins/executionHistory/` (table, status filter, pagination, 4-tab detail drawer) — mounts via the existing plugins catch-all with zero router changes. The base `.` entry never loads the API or React layers. Fully opt-in (not registered in any default config). Stacked on the execution-observer foundation. Gates: `format:check`, `lint`, full-monorepo `typecheck`, unit + handler tests green. Runs-page live render still to verify. <!-- stack:links:start --> 1. #12 2. **#13** 👈 current 3. #14 <!-- stack:links:end -->
Adds the **execution-observer foundation** — the seam the history and metrics plugins build on. - New `ExecutionObserver` contract in the SDK: six tagged lifecycle events (`ExecutionStarted`/`Finished`, `ToolCallStarted`/`Finished`, `InteractionStarted`/`Resolved`) + `composeExecutionObservers`, with a `plugin.runtime.executionObserver` hook. - The execution engine emits the events (re-derived onto the current Queue-based pause model), exposes `Executor.owner`, and tags the run span with the execution id + trigger. - `makeExecutionStack` composes plugin observers — one seam covers every HTTP host and the MCP Durable Objects; local's fixed-execution + in-process MCP are wired directly. **Behaviour-neutral / opt-in:** with no plugin observing, every path is a no-op. Gates: `format:check`, `lint`, full-monorepo `typecheck`, and observer unit tests all green. Live app verification still to come. <!-- stack:links:start --> 1. **#12** 👈 current 2. #13 3. #14 <!-- stack:links:end -->
Adds **`@executor-js/plugin-execution-history`** — an opt-in execution-history sink built on the observer foundation. - Records every run (plus its tool calls and interactions) into three owner-scoped `pluginStorage` collections via a buffered-batch writer — **no new tables, no migrations**; works on D1/libSQL/sqlite/postgres. - `./api`: a scoped read API (`list`/`get`/`listToolCalls`) over HttpApi (`executionHistoryHttpPlugin`). - `./client`: a Runs page at `/plugins/executionHistory/` (table, status filter, pagination, 4-tab detail drawer) — mounts via the existing plugins catch-all with zero router changes. The base `.` entry never loads the API or React layers. Fully opt-in (not registered in any default config). Stacked on the execution-observer foundation. Gates: `format:check`, `lint`, full-monorepo `typecheck`, unit + handler tests green. Runs-page live render still to verify. <!-- stack:links:start --> 1. #12 2. **#13** 👈 current 3. #14 <!-- stack:links:end -->
Adds the **execution-observer foundation** — the seam the history and metrics plugins build on. - New `ExecutionObserver` contract in the SDK: six tagged lifecycle events (`ExecutionStarted`/`Finished`, `ToolCallStarted`/`Finished`, `InteractionStarted`/`Resolved`) + `composeExecutionObservers`, with a `plugin.runtime.executionObserver` hook. - The execution engine emits the events (re-derived onto the current Queue-based pause model), exposes `Executor.owner`, and tags the run span with the execution id + trigger. - `makeExecutionStack` composes plugin observers — one seam covers every HTTP host and the MCP Durable Objects; local's fixed-execution + in-process MCP are wired directly. **Behaviour-neutral / opt-in:** with no plugin observing, every path is a no-op. Gates: `format:check`, `lint`, full-monorepo `typecheck`, and observer unit tests all green. Live app verification still to come. <!-- stack:links:start --> 1. **#12** 👈 current 2. #13 3. #14 <!-- stack:links:end -->
Adds **`@executor-js/plugin-execution-history`** — an opt-in execution-history sink built on the observer foundation. - Records every run (plus its tool calls and interactions) into three owner-scoped `pluginStorage` collections via a buffered-batch writer — **no new tables, no migrations**; works on D1/libSQL/sqlite/postgres. - `./api`: a scoped read API (`list`/`get`/`listToolCalls`) over HttpApi (`executionHistoryHttpPlugin`). - `./client`: a Runs page at `/plugins/executionHistory/` (table, status filter, pagination, 4-tab detail drawer) — mounts via the existing plugins catch-all with zero router changes. The base `.` entry never loads the API or React layers. Fully opt-in (not registered in any default config). Stacked on the execution-observer foundation. Gates: `format:check`, `lint`, full-monorepo `typecheck`, unit + handler tests green. Runs-page live render still to verify. <!-- stack:links:start --> 1. #12 2. **#13** 👈 current 3. #14 <!-- stack:links:end -->
Adds the **execution-observer foundation** — the seam the history and metrics plugins build on. - New `ExecutionObserver` contract in the SDK: six tagged lifecycle events (`ExecutionStarted`/`Finished`, `ToolCallStarted`/`Finished`, `InteractionStarted`/`Resolved`) + `composeExecutionObservers`, with a `plugin.runtime.executionObserver` hook. - The execution engine emits the events (re-derived onto the current Queue-based pause model), exposes `Executor.owner`, and tags the run span with the execution id + trigger. - `makeExecutionStack` composes plugin observers — one seam covers every HTTP host and the MCP Durable Objects; local's fixed-execution + in-process MCP are wired directly. **Behaviour-neutral / opt-in:** with no plugin observing, every path is a no-op. Gates: `format:check`, `lint`, full-monorepo `typecheck`, and observer unit tests all green. Live app verification still to come. <!-- stack:links:start --> 1. **#12** 👈 current 2. #13 3. #14 <!-- stack:links:end -->
Adds **`@executor-js/plugin-execution-history`** — an opt-in execution-history sink built on the observer foundation. - Records every run (plus its tool calls and interactions) into three owner-scoped `pluginStorage` collections via a buffered-batch writer — **no new tables, no migrations**; works on D1/libSQL/sqlite/postgres. - `./api`: a scoped read API (`list`/`get`/`listToolCalls`) over HttpApi (`executionHistoryHttpPlugin`). - `./client`: a Runs page at `/plugins/executionHistory/` (table, status filter, pagination, 4-tab detail drawer) — mounts via the existing plugins catch-all with zero router changes. The base `.` entry never loads the API or React layers. Fully opt-in (not registered in any default config). Stacked on the execution-observer foundation. Gates: `format:check`, `lint`, full-monorepo `typecheck`, unit + handler tests green. Runs-page live render still to verify. <!-- stack:links:start --> 1. #12 2. **#13** 👈 current 3. #14 <!-- stack:links:end -->
Adds the **execution-observer foundation** — the seam the history and metrics plugins build on. - New `ExecutionObserver` contract in the SDK: six tagged lifecycle events (`ExecutionStarted`/`Finished`, `ToolCallStarted`/`Finished`, `InteractionStarted`/`Resolved`) + `composeExecutionObservers`, with a `plugin.runtime.executionObserver` hook. - The execution engine emits the events (re-derived onto the current Queue-based pause model), exposes `Executor.owner`, and tags the run span with the execution id + trigger. - `makeExecutionStack` composes plugin observers — one seam covers every HTTP host and the MCP Durable Objects; local's fixed-execution + in-process MCP are wired directly. **Behaviour-neutral / opt-in:** with no plugin observing, every path is a no-op. Gates: `format:check`, `lint`, full-monorepo `typecheck`, and observer unit tests all green. Live app verification still to come. <!-- stack:links:start --> 1. **#12** 👈 current 2. #13 3. #14 <!-- stack:links:end -->
Adds **`@executor-js/plugin-execution-history`** — an opt-in execution-history sink built on the observer foundation. - Records every run (plus its tool calls and interactions) into three owner-scoped `pluginStorage` collections via a buffered-batch writer — **no new tables, no migrations**; works on D1/libSQL/sqlite/postgres. - `./api`: a scoped read API (`list`/`get`/`listToolCalls`) over HttpApi (`executionHistoryHttpPlugin`). - `./client`: a Runs page at `/plugins/executionHistory/` (table, status filter, pagination, 4-tab detail drawer) — mounts via the existing plugins catch-all with zero router changes. The base `.` entry never loads the API or React layers. Fully opt-in (not registered in any default config). Stacked on the execution-observer foundation. Gates: `format:check`, `lint`, full-monorepo `typecheck`, unit + handler tests green. Runs-page live render still to verify. <!-- stack:links:start --> 1. #12 2. **#13** 👈 current 3. #14 <!-- stack:links:end -->
Adds
@executor-js/plugin-execution-history— an opt-in execution-history sink built on the observer foundation.pluginStoragecollections via a buffered-batch writer — no new tables, no migrations; works on D1/libSQL/sqlite/postgres../api: a scoped read API (list/get/listToolCalls) over HttpApi (executionHistoryHttpPlugin)../client: a Runs page at/plugins/executionHistory/(table, status filter, pagination, 4-tab detail drawer) — mounts via the existing plugins catch-all with zero router changes.The base
.entry never loads the API or React layers. Fully opt-in (not registered in any default config).Stacked on the execution-observer foundation. Gates:
format:check,lint, full-monorepotypecheck, unit + handler tests green. Runs-page live render still to verify.Stack