Skip to content

feat: add the execution-observer foundation - #12

Merged
aryasaatvik merged 6 commits into
devfrom
feat/observer-foundation
Jun 13, 2026
Merged

aryasaatvik merged 6 commits into
devfrom
feat/observer-foundation

Conversation

@aryasaatvik

@aryasaatvik aryasaatvik commented Jun 13, 2026 •

Copy link
Copy Markdown
Owner

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

  1. feat: add the execution-observer foundation #12 👈 current
  2. feat: add the execution-history plugin #13
  3. feat: add the execution-metrics plugin #14

@aryasaatvik
aryasaatvik marked this pull request as ready for review June 13, 2026 19:06
@greptile-apps

greptile-apps Bot commented Jun 13, 2026 •

Copy link
Copy Markdown

Greptile Summary

This PR introduces the execution-observer foundation: a typed lifecycle event stream (ExecutionStarted/Finished, ToolCallStarted/Finished, InteractionStarted/Resolved) that the engine emits, with plugins subscribing via a new runtime.executionObserver hook composed by makeExecutionStack and the two local wiring points.

  • execution-observer.ts defines the six tagged event classes, the ExecutionObserver interface, and composeExecutionObservers with parallel fan-out (concurrency: "unbounded") and per-observer error isolation via Effect.catchCause.
  • engine.ts brackets both the inline and pausable execution paths with ExecutionStarted/Finished events, wraps the invoker with observeToolCalls, and mirrors InteractionResolved on the tapCause path in the pausable handler so every InteractionStarted is paired even on interrupt.
  • executor.ts exposes Executor.owner so engine-level machinery can attribute events without re-threading identity; makeExecutionStack, app.ts, and main.ts each wire composeExecutionObservers at the correct seam for their host.

Confidence Score: 5/5

Safe to merge — the observer is fully opt-in, every event is emitted under error isolation, and all existing execution paths are unaffected when no plugin registers an observer.

The new lifecycle stream is additive and behaviour-neutral: the no-op default means zero runtime change for current hosts. Both the inline and pausable paths correctly pair every Started event with a Finished counterpart — including on the interrupt/failure path via tapCause. The only finding is a test assertion that works today but relies on an implicit assumption about Effect's synchronous scheduler ordering.

No files require special attention.

Important Files Changed

Filename Overview
packages/core/sdk/src/execution-observer.ts New file: defines all execution lifecycle event types (6 tagged classes), ExecutionObserver interface, noopExecutionObserver, ignoreExecutionObserverErrors, and composeExecutionObservers with correct parallel fan-out (concurrency: "unbounded") and per-observer error isolation.
packages/core/execution/src/engine.ts Wires execution observer into both the inline and pausable execution paths; ExecutionStarted/Finished bracket each run, ToolCallStarted/Finished bracket each invoke, and InteractionStarted/Resolved bracket each elicitation in both paths with tapCause on the interrupt/failure path.
packages/core/sdk/src/execution-observer.test.ts Unit tests for composeExecutionObservers; the fan-out isolation test asserts ordered results (["first", "last"]) from concurrent execution, which works today for synchronous Effect.sync effects but is an implicit scheduler-ordering assumption.
packages/core/execution/src/engine-observer.test.ts Integration test verifying the full lifecycle event sequence (ExecutionStarted → ToolCallStarted → ToolCallFinished → ExecutionFinished) and the no-op path; event ordering assertions are safe here as they check first/last slot, not mid-sequence order.
packages/core/api/src/server/execution-stack.ts Adds composeExecutionObservers wiring inside makeExecutionStack; plugins() is correctly cast to the caller's phantom TPlugins type so extensions lookup aligns, and the no-op path is preserved when no plugin registers an observer.
packages/core/sdk/src/plugin.ts Adds optional runtime.executionObserver hook to PluginSpec; uses NoInfer to prevent TypeScript from widening TExtension through the self parameter, which is the correct technique for this constraint.
apps/local/src/app.ts Passes plugins to localFixedExecutionLayer so composeExecutionObservers can run; local bypasses makeExecutionStack so this is the correct wiring point.
apps/local/src/main.ts Also wires composeExecutionObservers for the local in-process MCP engine; correctly passes executor as extensions since Executor extends PluginExtensions.
packages/core/sdk/src/executor.ts Exposes owner: OwnerBinding on the Executor type and wires ownerBinding into createExecutor; clean addition with no side effects on existing call sites.

Sequence Diagram

sequenceDiagram
    participant C as Caller
    participant E as Engine (startPausableExecution)
    participant O as ExecutionObserver(s)
    participant F as Daemon Fiber

    C->>E: "executeWithPause(code, {trigger})"
    E->>O: "ExecutionStarted {executionId, owner, trigger}"
    E->>F: forkDetach(codeExecutor.execute)
    E->>E: awaitCompletionOrPause (race Fiber.join vs Queue.take)

    alt No elicitation (completes directly)
        F->>O: "ToolCallStarted {executionId, toolCallId, path}"
        F->>O: "ToolCallFinished {executionId, toolCallId, status}"
        F->>O: "ExecutionFinished {executionId, status: completed}"
        F-->>E: Fiber.join resolves
        E-->>C: "{status: completed}"
    else Elicitation required (pause path)
        F->>O: "InteractionStarted {executionId, interactionId}"
        F->>E: Queue.offer(paused)
        E-->>C: "{status: paused, execution}"
        Note over F: Fiber blocked on Deferred.await
        C->>E: resume(pauseId, response)
        E->>F: Deferred.succeed(response)
        F->>O: "InteractionResolved {status: accepted/declined/cancelled}"
        Note over F,O: tapCause also emits InteractionResolved on interrupt/failure
        F->>O: "ExecutionFinished {executionId, status}"
        F-->>E: Fiber.join resolves
        E-->>C: "{status: completed}"
    end
Loading

Fix All in Codex Fix All in Cursor Cloud Agents Fix All in Claude Code Fix All in Cursor

Reviews (3): Last reviewed commit: "fix(execution): parallelize observer fan..." | Re-trigger Greptile

Comment thread packages/core/sdk/src/execution-observer.ts
Comment thread packages/core/execution/src/engine.ts Outdated
… hook

The pull-model execution lifecycle stream the engine emits: six tagged events
(ExecutionStarted/Finished, ToolCallStarted/Finished, InteractionStarted/
Resolved), the ExecutionObserver interface, and composeExecutionObservers which
fans each event to every plugin's runtime.executionObserver with per-observer
error suppression. Events carry owner: OwnerBinding (tenant + subject) since the
v2 restructure removed ScopeId. Adds the optional PluginSpec.runtime hook.
…n span

createExecutionEngine takes an optional observer and emits the six
ExecutionEvents around a run: ExecutionStarted (with trigger), tool calls
bracketed via an invoker wrapper, elicitations via InteractionStarted/Resolved
on both the inline and pause/resume paths, and ExecutionFinished on the forked
fiber. The observer defaults to no-op, so hosts that register none are
unaffected. Each run mints its own ExecutionId, distinct from the per-pause
resume handle. execute/executeWithPause gain a trigger option, and the
mcp.execute span is annotated with the run id + trigger so traces correlate to a
run. Exposes Executor.owner so events can attribute work without re-threading
identity.
The shared (user, org) -> { executor, engine } factory composes every
registered plugin's runtime.executionObserver and passes it to the engine.
Cloud, self-host, host-cloudflare and the MCP Durable Objects all build through
this factory, so one seam wires the observer for every HTTP and DO path. No
plugin observing = no-op.
Local's fixed-execution seam and in-process MCP handler build the engine
directly rather than through makeExecutionStack, so compose the observer at both.
Other hosts inherit it from the shared factory.
@aryasaatvik
aryasaatvik force-pushed the feat/observer-foundation branch from 08a80c1 to 11d40f4 Compare June 13, 2026 19:32
…events on interrupt

Addresses Greptile review on #12:
- composeExecutionObservers fans events to observers with concurrency:
  unbounded, so a slow sink (DB-backed history) no longer serializes behind
  another (metrics push). Per-observer error isolation is unchanged.
- The pausable elicitation path now emits InteractionResolved on the
  failure/interrupt branch too (via tapCause), so a fiber killed while blocked
  on the response Deferred still pairs its InteractionStarted — matching the
  inline path.
@aryasaatvik
aryasaatvik merged commit 5081a1a into dev Jun 13, 2026
10 of 13 checks passed
aryasaatvik added a commit that referenced this pull request Jun 13, 2026
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 -->
aryasaatvik added a commit that referenced this pull request Jun 13, 2026
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 -->
aryasaatvik added a commit that referenced this pull request Jun 23, 2026
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 -->
aryasaatvik added a commit that referenced this pull request Jun 23, 2026
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 -->
aryasaatvik added a commit that referenced this pull request Jun 23, 2026
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 -->
aryasaatvik added a commit that referenced this pull request Jun 23, 2026
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 -->
aryasaatvik added a commit that referenced this pull request Jun 23, 2026
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 -->
aryasaatvik added a commit that referenced this pull request Jun 23, 2026
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 -->
aryasaatvik added a commit that referenced this pull request Aug 18, 2026
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 -->
aryasaatvik added a commit that referenced this pull request Aug 18, 2026
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 -->
aryasaatvik added a commit that referenced this pull request Aug 18, 2026
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 -->
aryasaatvik added a commit that referenced this pull request Aug 23, 2026
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 -->
aryasaatvik added a commit that referenced this pull request Aug 23, 2026
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 -->
aryasaatvik added a commit that referenced this pull request Aug 27, 2026
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 -->
aryasaatvik added a commit that referenced this pull request Aug 27, 2026
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 -->
aryasaatvik added a commit that referenced this pull request Aug 28, 2026
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 -->
aryasaatvik added a commit that referenced this pull request Aug 28, 2026
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 -->
aryasaatvik added a commit that referenced this pull request Aug 29, 2026
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 -->
aryasaatvik added a commit that referenced this pull request Aug 29, 2026
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 -->
aryasaatvik added a commit that referenced this pull request Aug 31, 2026
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 -->
aryasaatvik added a commit that referenced this pull request Aug 31, 2026
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 -->
aryasaatvik added a commit that referenced this pull request Sep 13, 2026
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 -->
aryasaatvik added a commit that referenced this pull request Sep 13, 2026
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 -->
aryasaatvik added a commit that referenced this pull request Sep 18, 2026
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 -->
aryasaatvik added a commit that referenced this pull request Sep 18, 2026
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 -->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant