From fcaaf9dc25921cee142b2da239a8465d792140b3 Mon Sep 17 00:00:00 2001 From: Brent Rager Date: Mon, 17 Aug 2026 18:29:19 -0400 Subject: [PATCH] =?UTF-8?q?th-9e792d:=20reconcile=20parity=20docs=20?= =?UTF-8?q?=E2=80=94=20durable=20backend=20+=20telemetry=20+=20knowledge?= =?UTF-8?q?=20now=20in=20all=20five?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The docs understated what ships after epic th-9e792d merged: - Durable-execution BACKEND (Temporal) now ships in all five languages, not Rust-only: Rust's smooth-operator-temporal crate plus new optional Go/TS/ Python/.NET packages, with the server-side selection seam (dependency-injected) in all five servers. Kept the shared ADR-030 caveats honest (terminal result only, no token-delta streaming, costUsd=0, config-only seeding) and reframed them as one shared follow-up across all five — not a Rust-vs-others gap. - Server gen_ai OTel spans now in all five servers — added a PARITY §3 row. - Durable knowledge + ACL-knowledge Postgres stores now in Go/TS/Python too (◐, since the checkpoint store is still pending there and the TS/Python knowledge stores aren't yet wired into the live dispatcher). - Engine exceptions "except two" -> "except ONE" (sandbox/integrity only). Docs only; no code change. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01YbN45JeWDbcjvFqGJvmVD3 --- PARITY-STATUS.md | 22 ++++++++++++++++------ README.md | 4 ++-- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/PARITY-STATUS.md b/PARITY-STATUS.md index 1638e142..d6e90278 100644 --- a/PARITY-STATUS.md +++ b/PARITY-STATUS.md @@ -34,6 +34,7 @@ Rust is the reference; TypeScript, Python, Go and C#/.NET are native ports. Thes | Provider routing: presets, per-activity slots, fallback chains, per-model quirks, LiteLLM alias resolution | ✅ all five | | SEP extension host: manifest, capabilities, tool/provider/UI/command lanes, restart backoff, bounded observe lane | ✅ all five | | Durable-execution **seam** (`AgentExecutor` + activities + `TurnPolicy`) | ✅ all five | +| Durable-execution **backend** (Temporal: crash-safe resume, durable HITL signals, durable-wait timer) | ✅ all five [^durable] | ### Why the claim holds @@ -45,14 +46,17 @@ Three shared corpora are generated **from the Rust reference** and replayed by a On the service side, all five servers replay [`spec/conformance/scenarios`](spec/conformance) — in **this** repo — against the engine's deterministic mock, so they must emit identical protocol output. +[^durable]: The durable backend is a separate, **optional, feature-gated per-language package** — Rust's `smooth-operator-temporal` crate plus new Go / TypeScript / Python / .NET packages ([core-repo PRs #170, #168, #169, #173](https://github.com/SmooAI/smooth-operator-core/pulls)) — each with a client-side `AgentExecutor` that starts the Temporal workflow, durable HITL via approve/deny signals, and a durable-wait timer, e2e-tested against a real ephemeral Temporal server. The server-side selection seam (env `SMOOTH_AGENT_DURABLE_EXECUTOR`, backend **dependency-injected** so the published server keeps no hard Temporal dep) is in all five servers ([this repo PRs #450, #451, #452, #455](https://github.com/SmooAI/smooth-operator/pulls)); no engine pulls a Temporal SDK into your dependency tree by default. **Shared ADR-030 follow-up — the same in every language, Rust reference included, *not* a Rust-vs-others gap:** the durable path yields only a terminal result (no token-delta streaming) and reports `costUsd=0` on the workflow result, and the executor seeds from agent config only (no prior-thread history / per-turn-per-org tool registry). This is the remaining "workflow→streaming adapter bridge" product question. + --- -## 2. Rust-first — the engine's two honest exceptions +## 2. Rust-first — the engine's one honest exception | Surface | Status | | --- | --- | | **Extension sandbox / integrity hardening** | **Rust-first.** Capability *declarations* are parsed and honoured in all five, but process-level confinement and manifest-integrity verification are Rust-only. See [Extension-Sandboxing-Design.md](https://github.com/SmooAI/smooth-operator-core/blob/main/docs/Extension-Sandboxing-Design.md). | -| **Durable-execution backend** | **Rust-first.** The `AgentExecutor` seam is in all five with an in-process executor that delegates verbatim to `run`, so the seam changes nothing until something plugs in. Only Rust ships a real backend — the separate, feature-gated `smooth-operator-temporal` crate (turn as a Temporal workflow, model/tool calls as activities: crash-safe resume, durable HITL signals, durable timers). The other four carry a `TODO(ADR-030)` naming the opt-in package their backend belongs in; no engine pulls a Temporal SDK into your dependency tree. | + +The **durable-execution backend** used to sit here as the second Rust-first exception; it no longer does. The Temporal backend ships as an optional per-language package in all five, and the server-side selection seam is in all five servers — see the durable backend row in §1 and its footnote for the one shared ADR-030 streaming/cost follow-up that remains (identical across all five, not a parity gap). --- @@ -65,14 +69,15 @@ All five servers carry the transport core: frame dispatch, per-turn engine, sess | Transport core (dispatch · sessions · auth · drain) | ✅ | ✅ | ✅ | ✅ | ✅ | | Shared scenario conformance corpus | ✅ | ✅ | ✅ | ✅ | ✅ | | Postgres conversation store | ✅ | ✅ | ✅ | ✅ | ✅ | +| Server `gen_ai.*` OTel telemetry (chat + tool spans · redacted tool args · env-gated OTLP) | ✅ | ✅ | ✅ | ✅ | ✅ | | Second storage backend (DynamoDB + S3 Vectors) | ✅ | — | — | — | — | -| Persistent checkpoint / knowledge / ACL-knowledge stores | ✅ | ✅ | — | — | ◐ [^py-knowledge] | +| Persistent checkpoint / knowledge / ACL-knowledge stores [^knowledge] | ✅ | ✅ | ◐ | ◐ | ◐ | | Deep ingestion + ACL surface | ✅ | ✅ | ◐ | ◐ | ◐ | | Backplane `attach`/`detach` | ✅ | — | ✅ | ✅ | ✅ | | Backplane `publish` (event fan-out) | ✅ | — | ✅ | ✅ | — | | **Cross-pod backplane (Redis / NATS)** | ✅ | — | — | — | — | -[^py-knowledge]: Python now has the durable **knowledge + ACL-knowledge** stores (`postgres_knowledge.py`: `PostgresVectorKnowledge` / `PostgresAclKnowledge`, on the shared `knowledge_vectors` table + pgvector). The persistent **checkpoint** store is still pending, so the cell is ◐ rather than ✅. +[^knowledge]: The durable **knowledge + ACL-knowledge** Postgres stores now ship in **Go, TypeScript and Python** too ([PRs #442, #443, #444](https://github.com/SmooAI/smooth-operator/pulls)) — on the shared `knowledge_vectors` table + pgvector — alongside Rust and .NET (which already had them, e.g. Python's `postgres_knowledge.py`: `PostgresVectorKnowledge` / `PostgresAclKnowledge`). These three cells stay **◐ rather than ✅** for two honest reasons: the persistent **checkpoint** store is still pending in Go/TS/Python, and the **TS + Python** knowledge stores are shipped and contract-tested but **not yet wired into the live dispatcher** (a sync-engine vs async-pg bridge). The **second storage backend** (DynamoDB + S3-Vectors, the row above) remains Rust-only. **The operational consequence:** only the **Rust** server scales past one replica today. Go, TypeScript and Python run an in-memory backplane — correct for a single process, silently wrong the moment you run two pods, because an event published on pod A never reaches a socket held by pod B. C# has no backplane surface at all. @@ -83,7 +88,7 @@ All five servers carry the transport core: frame dispatch, per-turn engine, sess Three items, in the order they'd bite: 1. **Cross-pod backplane beyond Rust.** Go and TypeScript have the full `attach`/`detach`/`publish` surface but only an in-memory implementation; **Python has `attach`/`detach` with no `publish`**; **C# has no backplane at all**. Redis/NATS adapters exist only for Rust. Until a language has one, treat its server as single-replica. -2. **Durable backend beyond Rust.** Per-language Temporal packages (the seam is already in place, so this is additive and needs no engine change). +2. **Durable path → streaming/cost adapter bridge (ADR-030) — done shipping, one shared follow-up left.** The Temporal backend now ships as an optional per-language package in **all five** and the server-side selection seam is in **all five** servers (§1 durable backend row + footnote), so this is no longer a language gap. What remains is identical across every language, Rust reference included: the durable path returns only a terminal result (no token-delta streaming) and reports `costUsd=0` on the workflow result, and the executor seeds from agent config only. Bridging the workflow result back onto the streaming/cost surface is the open ADR-030 product question. 3. **`seq` is under-specified in the shared schema.** [`spec/extension/methods/event.schema.json`](spec/extension/methods/event.schema.json) marks `seq` optional (`required: ["event", "context"]`), but **all five** engines always emit it on an `event` frame, and all five correctly omit it on the out-of-band `events_lost` marker. The implementations agree with each other and the schema is looser than all of them — so a sixth implementation could legally omit `seq`, pass conformance, and break the gap-detection that `events_lost` depends on. Tighten the schema to match the implementations rather than the reverse. --- @@ -104,8 +109,13 @@ rg -n 'attach|detach|publish' go/server/backplane.go \ rust/smooth-operator/src/backplane.rs rg -ril backplane dotnet/ # expect: no matches -# Durable backend: expect matches only under rust/ +# Durable backend: temporal packages now ship in all five (rust/ go/ typescript/ python/ dotnet/), +# and the server-side selection seam (SMOOTH_AGENT_DURABLE_EXECUTOR) is in all five servers. find . -iname '*temporal*' -not -path '*/target/*' -not -path '*/node_modules/*' +rg -n 'SMOOTH_AGENT_DURABLE_EXECUTOR' rust/ go/ typescript/ python/ dotnet/ + +# Server gen_ai OTel telemetry present in all five servers? (chat + tool spans) +rg -n 'gen_ai\.chat|gen_ai\.tool' rust/ go/ typescript/ python/ dotnet/ ``` Last verified against `main` on 2026-08-17. diff --git a/README.md b/README.md index 8105b617..3702d6a3 100644 --- a/README.md +++ b/README.md @@ -266,9 +266,9 @@ One protocol, defined once in [`spec/`](spec) (JSON Schema). Everything else is | Surface | Status | | --- | --- | -| **Engine** ([`smooth-operator-core`](https://github.com/SmooAI/smooth-operator-core)) | **5-language parity engine** — Rust · C# · Python · TypeScript · Go, each published (crates.io / NuGet / PyPI / npm / Go module). Rust is the reference; the others mirror its surface. Every engine capability is in all five today except two, both stated plainly in [PARITY-STATUS.md](PARITY-STATUS.md): the extension **sandbox / integrity hardening** is Rust-first, and the durable-execution **backend** ships only for Rust (the seam it plugs into is in all five). | +| **Engine** ([`smooth-operator-core`](https://github.com/SmooAI/smooth-operator-core)) | **5-language parity engine** — Rust · C# · Python · TypeScript · Go, each published (crates.io / NuGet / PyPI / npm / Go module). Rust is the reference; the others mirror its surface. Every engine capability is in all five today except **one**, stated plainly in [PARITY-STATUS.md](PARITY-STATUS.md): the extension **sandbox / integrity hardening** is Rust-first. The durable-execution **backend** (Temporal) now ships as an optional per-language package in **all five**, with the server-side selection seam in all five servers — leaving only the one shared ADR-030 streaming/cost follow-up that applies equally to every language, Rust included. | | **Protocol clients** | **All five languages** — TypeScript (`@smooai/smooth-operator`), Go, .NET (with a `Microsoft.Extensions.AI` `IChatClient` facade), Python, Rust. The TS side also ships a **React binding** and an **embeddable widget**. | -| **Servers** | **All five languages** — Rust · C# · Python · TypeScript · Go, each consuming its own language's engine so a host can run the full service in its native stack. All five carry the transport core: frame dispatch · per-turn engine · sessions · auth · graceful drain, plus a Postgres store for conversations/messages/participants/sessions. Depth past that is uneven and worth knowing before you pick one: **Rust** is the only server with pluggable storage backends (Postgres *and* DynamoDB) and the only one with a **cross-pod backplane** (Redis / NATS) — the rest run an in-memory backplane, so they are single-replica. **C#** adds persistent checkpoint, knowledge-base and ACL-knowledge stores, and carries the deepest ingestion/ACL surface after Rust, but ships **no backplane at all** today. **Python/TS/Go** are transport-core servers. **All five run the shared scenario conformance corpus** — driven by the engine's deterministic mock, so they must produce identical protocol output. The corpus already caught and fixed real error-handling divergences in the TS and C# servers. See [PARITY-STATUS.md](PARITY-STATUS.md) for the verified breakdown. | +| **Servers** | **All five languages** — Rust · C# · Python · TypeScript · Go, each consuming its own language's engine so a host can run the full service in its native stack. All five carry the transport core: frame dispatch · per-turn engine · sessions · auth · graceful drain, plus a Postgres store for conversations/messages/participants/sessions. Depth past that is uneven and worth knowing before you pick one: **Rust** is the only server with pluggable storage backends (Postgres *and* DynamoDB) and the only one with a **cross-pod backplane** (Redis / NATS) — the rest run an in-memory backplane, so they are single-replica. **C#** adds persistent checkpoint, knowledge-base and ACL-knowledge stores, and carries the deepest ingestion/ACL surface after Rust, but ships **no backplane at all** today. **Go, TypeScript and Python** now also carry the durable **knowledge + ACL-knowledge** Postgres stores (the persistent **checkpoint** store is still Rust/.NET-only, and the TS/Python knowledge stores aren't yet wired into the live dispatcher). **All five servers now emit `gen_ai.*` OpenTelemetry spans** (chat + tool, redacted tool args, env-gated OTLP). **All five run the shared scenario conformance corpus** — driven by the engine's deterministic mock, so they must produce identical protocol output. The corpus already caught and fixed real error-handling divergences in the TS and C# servers. See [PARITY-STATUS.md](PARITY-STATUS.md) for the verified breakdown. | ---