Skip to content

Bump omercnet/omp to 1.3.2 - #199

Open
github-actions[bot] wants to merge 1 commit into
mainfrom
bump/omercnet/omp-1.3.2
Open

github-actions[bot] wants to merge 1 commit into
mainfrom
bump/omercnet/omp-1.3.2

Conversation

@github-actions

@github-actions github-actions Bot commented Oct 8, 2026

Copy link
Copy Markdown
Contributor

omercnet/omp: {"kind":"npm","package":"@omercnet/paseo-omp","version":"1.2.0","resolved":"https://registry.npmjs.org/@omercnet/paseo-omp/-/paseo-omp-1.2.0.tgz","integrity":"sha512-ueZede5D34hoNrdF4y6DBaomErA+hHcv+bcz0Sd6eArQKqF8L6ecKXdBe2tEZd3Ev8uQwxMHuiDQhMBx3q6gOw=="} -> {"kind":"npm","package":"@omercnet/paseo-omp","version":"1.3.2","resolved":"https://registry.npmjs.org/@omercnet/paseo-omp/-/paseo-omp-1.3.2.tgz","integrity":"sha512-WnW5siuFtdOqgXcBtzri5Zc1ZQCS/qOCU6ZSukLoy3G6waKS86yjhzwOVlNfqv2TXLDeYDHIrtk9EqbUqicV8w=="}
Provenance verified: built from https://github.com/omercnet/paseo-plugins/tree/HEAD/paseo-omp at 45b6656c5963468b10d41206e4386eabf528db23.
Submitted by @omercnet.

Merging approves this version. The published index keeps pointing at the previous one until then.

Artifact diff
diff -ruN a/package/OVERVIEW.md b/package/OVERVIEW.md
--- a/package/OVERVIEW.md	1970-01-01 00:00:00.000000000 +0000
+++ b/package/OVERVIEW.md	1985-10-26 08:15:00.000000000 +0000
@@ -0,0 +1,24 @@
+OMP adds an agent provider for the OMP coding agent, plus an OMP sidebar and workspace panel for configuring it. Choose **OMP Plugin** when creating an agent, and Paseo runs OMP on the daemon host and maps its prompts, images, steering, tool permissions, subagents, session history and conversation rewind into Paseo. It runs alongside Paseo's bundled `omp` provider without changing it or migrating existing `omp` agents. Sessions created by an earlier alpha preview may need to be re-imported after an upgrade.
+
+## Setup
+
+- Paseo 0.9.2 through 0.9.x, 0.10.x or 0.11.x.
+- OMP 18.1.15 or newer on the daemon host, speaking RPC protocol v2. Older runtimes are rejected.
+- Provider options let you change the OMP command, set environment values, choose an output redaction mode and set a session directory and timeout. Named OMP profiles appear as separate `OMP · <profile>` providers.
+
+## What the sidebar and panel do
+
+- Edit OMP settings and project configuration for the default store or a named profile.
+- Manage OMP's own plugins, and view quota history, memory, hub processes, session history and a support report.
+- An **MCP** composer control runs OMP's MCP management in the current session, with authorization prompts shown in the chat.
+
+## Reads and sends
+
+- Runs the OMP command as a process on the daemon host. Its output is passed to Paseo as produced, apart from validation and length limits.
+- Reads OMP's settings, configuration, session transcripts, quota history, memory and hub state on the host, and writes OMP's settings file when you edit settings in the panel.
+- With the default output redaction, nothing is redacted, so do not put credentials in prompts or tool output. The optional `configured-values` mode replaces configured credential values on a best-effort basis.
+- Opens only http and https links, through Paseo.
+
+## Limits
+
+Structured output schemas, archive and unarchive, revert of files, and exact MCP tool pre-approval are not supported, and requests for them fail visibly. Changing the approval mode of a running session needs a new session.
diff -ruN a/package/README.md b/package/README.md
--- a/package/README.md	1985-10-26 08:15:00.000000000 +0000
+++ b/package/README.md	1985-10-26 08:15:00.000000000 +0000
@@ -2,7 +2,7 @@
 
 Community OMP integration for Paseo. The plugin registers the distinct `omp-plugin` provider plus named profile providers and coexists with Paseo's bundled `omp` provider.
 
-> **Alpha preview:** persistence and protocol contracts are tested, but upgrades may still require re-importing sessions created by an earlier preview.
+> **Stable:** see [Support](SUPPORT.md) for supported versions and known limitations, and review release notes for any migration requirements before upgrading.
 
 ## Demo
 
@@ -38,7 +38,7 @@
 - [Compatibility, limitations, and support](SUPPORT.md)
 - [Test matrix and release verification](TESTING.md)
 - [Core-provider issue and parity audit](docs/core-provider-issue-audit.md)
-- [Alpha release checklist](docs/alpha-release-checklist.md)
+- [Release checklist](docs/release-checklist.md)
 
 The plugin uses public Paseo 0.9 and 0.10 provider and client contracts and registers distinct `omp-plugin` and `omp-plugin-<profile>` identities; it does not modify the bundled `omp` provider.
 
@@ -54,8 +54,8 @@
 
 ## Paseo provider SDK coverage
 
-The capability inventory is pinned to `@getpaseo/plugin` 0.11.0-beta.3 (PR #251), with nightly
-compatibility checks against supported 0.9 and 0.10 hosts. Provider capability scoring still covers
+The capability inventory is pinned to `@getpaseo/plugin` 0.11.1, with nightly compatibility checks
+against supported 0.9 and 0.10 hosts and the latest/beta channels. Provider capability scoring covers
 all 17 entries in the SDK's `PROVIDER_CAPABILITIES`; the separate provider/client SDK table below
 also tracks the 0.11 registration, screen, and sidebar APIs. This measures strict SDK surface
 coverage, not general product quality.
@@ -79,7 +79,7 @@
 | `session.archive` | **0%** | Not advertised. Paseo may archive its agent record, but OMP has no native transcript archive operation. |
 | `session.configure` | **50%** | Live model and thinking changes commit and republish native state. Live approval-mode changes require a new session, and non-empty SDK `settings` are rejected. |
 | `session.list` | **100%** | Bounded host-wide and cwd-scoped discovery, search, previews, profile-specific session roots, and cleanup-reservation guards. |
-| `session.persistence` | **100%** | Versioned opaque handles, exact resume, import, replay-before-ready, runtime recovery, and cleanup quarantine. |
+| `session.persistence` | **100%** | Versioned opaque handles, exact resume, import, replay-before-ready, runtime recovery, and cleanup quarantine. Archived agents whose recorded workspace has been removed load read-only from their authorized transcript when Paseo opens them with its `history` purpose, without spawning OMP or connecting MCP servers; interactive create and resume still require the workspace. |
 | `session.revert.both` | **0%** | Not advertised because OMP cannot atomically rewind conversation and workspace files. |
 | `session.revert.conversation` | **100%** | Native branch-based conversation rewind, replay deduplication, ownership transfer, and failure quarantine. |
 | `session.revert.files` | **0%** | Not advertised because OMP does not expose a native file-only rewind contract. |
@@ -95,7 +95,7 @@
 | --- | ---: | --- |
 | Registration metadata and sanitized SVG icon | **100%** | Stable `omp-plugin` identity, label, description, and bundled icon. |
 | Strict `providerOptionsSchema` | **100%** | Command, literal environment, names-only profile inherited environment, output-redaction mode, session directory, RPC timeout, and role-model options are validated and normalized. Host-wide inherited names are separately persisted and merged at launch. |
-| Availability diagnostics | **50%** | The plugin implements a `checkAvailability` hook with bounded checks that distinguish missing, unrunnable, incompatible, and available OMP runtimes, but no released daemon calls it (no upstream reference at v0.10.2 or v0.11.0-beta.3). Hosts treat the provider as available when a connection opens, and launch failures surface at session start. |
+| Availability diagnostics | **50%** | The plugin implements a `checkAvailability` hook with bounded checks that distinguish missing, unrunnable, incompatible, and available OMP runtimes, but Paseo 0.10.2 and 0.11.1 do not call it. Hosts treat the provider as available when a connection opens, and launch failures surface at session start. |
 | Catalog cache identity | **100%** | Hash includes effective options, merged host/profile inherited-environment names, settings, scope, cwd, and default command, but never resolves or fingerprints inherited values. |
 | Models, modes, and thinking catalog | **100%** | Native catalog is mapped to opaque public model IDs with committed defaults and permission-gated modes. |
 | Connection `send` / `onEvent` / `close` lifecycle | **100%** | Request correlation, multi-session ownership, process recovery, teardown, and provider reload/removal are covered. |
@@ -124,7 +124,7 @@
 
 OMP `18.1.15` is the oldest version tested end to end. The direct provider's hard compatibility gate is `rpc-ui` protocol v2: metadata-free legacy ready frames and v1-only runtimes are rejected before a provider session opens because they cannot support the advertised persistence and conversation-rewind capabilities. Typed tool approvals remain capability-gated and fall back as described above. For terminal completion, a matching `agent_end.requestId` is authoritative and mismatches are ignored before state changes. Released OMP 18.2.x builds that omit that field use an ordered fallback requiring a fresh correlated native user entry followed by current-turn assistant activity, an idle non-compacting runtime, and no conflicting permission, tool, steer, or child-session work. Ambiguous events while OMP is active are ignored; unresolved ambiguity after confirmed idle fails only the Paseo turn. This trades a bounded residual same-agent stale-event risk for compatibility with released OMP instead of terminating and lazily restarting the runtime after every later prompt. Paseo clients, including mobile clients inside reconnect grace, do not own or terminate the daemon-managed OMP session.
 
-Paseo 0.9.2 is the minimum supported stable release, and 0.10.1 is supported. The controlled Docker canary remains pinned to official 0.9.2; nightly SDK checks cover the newest 0.9, 0.10, and latest releases. The canary preserves nested provider-subagent ancestry and spawning-tool links, and validates npm-managed plugin sources, platform-owned external URL opening, and whole-item timeline transforms before Overview grouping.
+Paseo 0.9.2 is the minimum supported stable release, and 0.10.1 is supported. The controlled Docker canary is pinned to official 0.11.1; nightly SDK checks cover the newest 0.9 and 0.10 patches plus the latest and beta channels. Older Paseo lines are covered by that typecheck/unit matrix, not the current Docker canary. The canary preserves nested provider-subagent ancestry and spawning-tool links, and validates npm-managed plugin sources, platform-owned external URL opening, and whole-item timeline transforms before Overview grouping.
 
 Install, update, disable, or remove `paseo-omp` independently of the bundled provider. Verify the provider snapshot contains `omp-plugin` after installation; a bundled `omp` entry may remain present and is not modified by this plugin.
 
diff -ruN a/package/client/omp-config-surface.tsx b/package/client/omp-config-surface.tsx
--- a/package/client/omp-config-surface.tsx	1985-10-26 08:15:00.000000000 +0000
+++ b/package/client/omp-config-surface.tsx	1985-10-26 08:15:00.000000000 +0000
@@ -195,6 +195,19 @@
     </>
   );
 }
+
+function ToolBoundaryCard({ styles }: { styles: OmpConfigStyles }) {
+  return (
+    <SectionCard styles={styles} title="Tool access boundary (fail-closed)">
+      <Text style={styles.muted}>
+        A session toolPolicy (exact preapproval grants) is rejected at startup. OMP set_host_tools
+        cannot preserve those grants exactly, and the plugin never broadens them. Use paseoTools to
+        scope which caller-scoped Paseo tools reach OMP as MCP host tools. Use disallowedTools only
+        for known native OMP built-ins: unknown names are rejected, and it never filters MCP tools.
+      </Text>
+    </SectionCard>
+  );
+}
 function toneColor(theme: PluginSurfaceProps["theme"], tone: BinaryHealthSummary["tone"]): string {
   if (tone === "ok") return theme.colors.statusSuccess;
   if (tone === "warning") return theme.colors.statusWarning;
@@ -1136,6 +1149,7 @@
       {view === "plugin" ? (
         <>
           <PluginConfigurationSection styles={styles} />
+          <ToolBoundaryCard styles={styles} />
           {!cwd ? <ProviderLaunchSettingsSection theme={theme} /> : null}
         </>
       ) : null}
diff -ruN a/package/client/quota-popover.tsx b/package/client/quota-popover.tsx
--- a/package/client/quota-popover.tsx	1985-10-26 08:15:00.000000000 +0000
+++ b/package/client/quota-popover.tsx	1985-10-26 08:15:00.000000000 +0000
@@ -101,6 +101,9 @@
   return (
     <View style={styles.root}>
       <Text style={styles.muted}>{storeLabel(store)}</Text>
+      <Text style={styles.muted}>
+        Last recorded usage from the local agent database, not read live from the provider.
+      </Text>
       {currentProvider && !hasCurrent ? (
         <Text style={styles.muted}>
           {`No recorded quota yet for ${quotaProviderLabel(currentProvider)} (this session's provider).`}
diff -ruN a/package/index.client.tsx b/package/index.client.tsx
--- a/package/index.client.tsx	1985-10-26 08:15:00.000000000 +0000
+++ b/package/index.client.tsx	1985-10-26 08:15:00.000000000 +0000
@@ -351,7 +351,7 @@
         workspaceId: entry.workspaceId,
         agentId: agent.id,
         button: {
-          title: "OMP provider quotas",
+          title: "OMP provider quotas (last recorded usage, not live)",
           icon: quotaProviderIcon(entry.quotaProvider, "unknown"),
           label: "Quota",
           visible: false,
diff -ruN a/package/index.server.ts b/package/index.server.ts
--- a/package/index.server.ts	1985-10-26 08:15:00.000000000 +0000
+++ b/package/index.server.ts	1985-10-26 08:15:00.000000000 +0000
@@ -17,7 +17,7 @@
 import { OmpOperationalFailureCollector } from "./server/operational-failure-diagnostics";
 import { withOmpStore } from "./server/paths";
 import { OmpProtocolViolationCollector } from "./server/protocol-violation-diagnostics";
-import { withOmpWorkspaceIdentity } from "./server/provider/host-tools";
+import { withOmpSessionOpenEnv } from "./server/provider/host-tools";
 import {
   createProfileOmpProvider,
   discoverOmpProfiles,
@@ -97,9 +97,9 @@
   server.handle(openOmpMcpAuthorizationInPaseoBrowser, (input) =>
     resolveOpenOmpMcpAuthorizationInPaseoBrowser(input, browserAuthorizationRegistry),
   );
-  const removeIdentityHook = server.before("agent.session_open", ({ request }) => {
+  const removeSessionOpenHook = server.before("agent.session_open", ({ request }) => {
     if (request.provider !== "omp-plugin" && !request.provider.startsWith("omp-plugin-")) return;
-    return withOmpWorkspaceIdentity(request);
+    return withOmpSessionOpenEnv(request);
   });
   server.registerProvider(
     createOmpProvider({
@@ -111,6 +111,6 @@
   );
   return () => {
     browserAuthorizationRegistry.clear();
-    removeIdentityHook();
+    removeSessionOpenHook();
   };
 }
diff -ruN a/package/package.json b/package/package.json
--- a/package/package.json	1985-10-26 08:15:00.000000000 +0000
+++ b/package/package.json	1985-10-26 08:15:00.000000000 +0000
@@ -1,6 +1,6 @@
 {
   "name": "@omercnet/paseo-omp",
-  "version": "1.2.0",
+  "version": "1.3.2",
   "type": "module",
   "description": "Paseo integration for OMP, including its direct provider and workspace tooling.",
   "license": "MIT",
@@ -37,7 +37,8 @@
     "client",
     "server",
     "shared",
-    "paseo-plugin.json"
+    "paseo-plugin.json",
+    "OVERVIEW.md"
   ],
   "scripts": {
     "check": "biome check .",
@@ -51,16 +52,16 @@
     "typecheck": "tsc --noEmit -p tsconfig.client.json && tsc --noEmit -p tsconfig.server.json && tsc --noEmit -p tsconfig.tests.json"
   },
   "dependencies": {
-    "@getpaseo/protocol": "0.11.0-beta.3",
+    "@getpaseo/protocol": "0.11.1",
     "@modelcontextprotocol/sdk": "1.30.0",
     "yaml": "^2.9.0"
   },
   "devDependencies": {
     "@biomejs/biome": "^2.5.10",
-    "@getpaseo/cli": "0.11.0-beta.3",
-    "@getpaseo/client": "0.11.0-beta.3",
-    "@getpaseo/plugin": "0.11.0-beta.3",
-    "@getpaseo/server": "0.11.0-beta.3",
+    "@getpaseo/cli": "0.11.1",
+    "@getpaseo/client": "0.11.1",
+    "@getpaseo/plugin": "0.11.1",
+    "@getpaseo/server": "0.11.1",
     "@oh-my-pi/pi-agent-core": "18.2.0",
     "@oh-my-pi/pi-coding-agent": "18.2.0",
     "@tanstack/react-query": "^5.102.3",
diff -ruN a/package/server/package-version.ts b/package/server/package-version.ts
--- a/package/server/package-version.ts	1985-10-26 08:15:00.000000000 +0000
+++ b/package/server/package-version.ts	1985-10-26 08:15:00.000000000 +0000
@@ -1,2 +1,2 @@
 /** Release Please keeps this bundle-safe constant aligned with package.json. */
-export const PASEO_OMP_PACKAGE_VERSION = "1.2.0"; // x-release-please-version
+export const PASEO_OMP_PACKAGE_VERSION = "1.3.2"; // x-release-please-version
diff -ruN a/package/server/provider/catalog.ts b/package/server/provider/catalog.ts
--- a/package/server/provider/catalog.ts	1985-10-26 08:15:00.000000000 +0000
+++ b/package/server/provider/catalog.ts	1985-10-26 08:15:00.000000000 +0000
@@ -49,7 +49,7 @@
   { id: "xhigh", label: "XHigh", description: "Extra-high reasoning" },
   { id: "max", label: "Max", description: "Maximum reasoning" },
 ];
-export const OMP_MAX_CATALOG_MODELS = 256;
+export const OMP_MAX_CATALOG_MODELS = 4096;
 
 export function selectOmpModels(
   models: readonly OmpModel[],
diff -ruN a/package/server/provider/config-normalization.ts b/package/server/provider/config-normalization.ts
--- a/package/server/provider/config-normalization.ts	1985-10-26 08:15:00.000000000 +0000
+++ b/package/server/provider/config-normalization.ts	1985-10-26 08:15:00.000000000 +0000
@@ -12,6 +12,7 @@
 import { MAX_INHERITED_ENVIRONMENT_NAMES } from "../../shared/provider-launch-settings";
 import { parseOmpProviderOptions } from "./provider-options";
 import { OmpPublicError } from "./security";
+import { withoutOmpSessionPurpose } from "./session-purpose";
 import { OmpModeSchema } from "./settings";
 
 const OMP_BUILTIN_TOOL_NAMES = [
@@ -84,7 +85,7 @@
     mode: "full",
     noSession: true,
     ...(providerOptions.command ? { command: providerOptions.command } : {}),
-    ...(providerOptions.env ? { env: providerOptions.env } : {}),
+    ...(providerOptions.env ? { env: withoutOmpSessionPurpose(providerOptions.env) } : {}),
     ...(inheritEnv ? { inheritEnv } : {}),
     outputRedaction: providerOptions.outputRedaction,
     ...(params.sessionDir ? { sessionDir: params.sessionDir } : {}),
@@ -136,7 +137,7 @@
     .deniedTools;
   const tools = allowedOmpTools(deniedTools);
   const params = options.params ?? {};
-  const env = { ...options.env, ...config.env };
+  const env = withoutOmpSessionPurpose({ ...options.env, ...config.env });
   const inheritEnv = mergeOmpInheritedEnvironmentNames(hostInheritEnv, options.inheritEnv);
   return {
     cwd: config.cwd,
diff -ruN a/package/server/provider/connection.ts b/package/server/provider/connection.ts
--- a/package/server/provider/connection.ts	1985-10-26 08:15:00.000000000 +0000
+++ b/package/server/provider/connection.ts	1985-10-26 08:15:00.000000000 +0000
@@ -32,7 +32,9 @@
   OmpPublicError,
   utf8Bytes,
 } from "./security";
-import { OmpProviderSession, ompPersistenceSessionId } from "./session";
+import { type OmpOpenedSession, OmpProviderSession, ompPersistenceSessionId } from "./session";
+import { OmpHistorySession } from "./session-history";
+import { isOmpHistoryOnlyOpen } from "./session-purpose";
 
 type ProviderConfigurationCompat = {
   providerOptions?: Readonly<Record<string, unknown>>;
@@ -747,7 +749,7 @@
     string,
     {
       token: symbol;
-      session: OmpProviderSession;
+      session: OmpOpenedSession;
       nativeSessionId?: string;
       removeBrowserAuthorization?: () => void;
     }
@@ -909,10 +911,15 @@
         opening.set(input.sessionId, { token, controller, settled: openingSettled.promise });
         let nativeSessionId: string | undefined;
         let persistentOpening = false;
-        let session: OmpProviderSession | undefined;
+        let historyOnly = false;
+        let session: OmpOpenedSession | undefined;
         try {
+          historyOnly = isOmpHistoryOnlyOpen(input);
           nativeSessionId = ompPersistenceSessionId(input);
-          if (nativeSessionId) {
+          if (historyOnly) {
+            // History reads one authorized transcript and runs nothing, so it takes no native
+            // session reservation and neither blocks nor is blocked by an interactive session.
+          } else if (nativeSessionId) {
             await nativeReservations.reserve(nativeSessionId, token, controller.signal);
           } else if (input.config.persist) {
             await nativeReservations.beginPersistentOpen(token, controller.signal);
@@ -955,23 +962,35 @@
           const retireRewindSession = () => {
             deleteSession(input.sessionId, token);
           };
-          session = await OmpProviderSession.open(
-            input,
-            runtime,
-            safeCapabilities,
-            sessionEmit,
-            transitionNativeSession,
-            quarantineRewindCleanup,
-            retireRewindSession,
-            scheduler,
-            replayTimeoutMs,
-            controller.signal,
-            environment,
-            mcpConnector,
-            mcpInitializationTimeoutMs,
-            reportOperationalFailure,
-            (await resolveHostInheritEnv?.()) ?? [],
-          );
+          const hostInheritEnv = (await resolveHostInheritEnv?.()) ?? [];
+          session = historyOnly
+            ? await OmpHistorySession.open(
+                input,
+                runtime,
+                safeCapabilities,
+                sessionEmit,
+                replayTimeoutMs,
+                environment,
+                hostInheritEnv,
+                scheduler,
+              )
+            : await OmpProviderSession.open(
+                input,
+                runtime,
+                safeCapabilities,
+                sessionEmit,
+                transitionNativeSession,
+                quarantineRewindCleanup,
+                retireRewindSession,
+                scheduler,
+                replayTimeoutMs,
+                controller.signal,
+                environment,
+                mcpConnector,
+                mcpInitializationTimeoutMs,
+                reportOperationalFailure,
+                hostInheritEnv,
+              );
           const discoveredNativeSessionId = session.persistenceSessionId;
           if (discoveredNativeSessionId) nativeSessionId = discoveredNativeSessionId;
           if (persistentOpening) {
@@ -995,10 +1014,13 @@
             return;
           }
           const browserAgentId = input.config.env.PASEO_AGENT_ID?.trim() || input.sessionId;
-          const browserAuthorization = browserAuthorizationRegistry?.register(
-            browserAgentId,
-            session.openPaseoBrowser.bind(session),
-          );
+          // A history session has no live Paseo browser tools to authorize.
+          const browserAuthorization = historyOnly
+            ? undefined
+            : browserAuthorizationRegistry?.register(
+                browserAgentId,
+                session.openPaseoBrowser.bind(session),
+              );
           session.setBrowserAuthorizationIssuer(browserAuthorization?.issue ?? null);
           const removeBrowserAuthorization = browserAuthorization
             ? () => {
@@ -1155,7 +1177,7 @@
     for (const result of operationResults) {
       if (result.status === "rejected") failures.push(result.reason);
     }
-    const seenSessions = new Set<OmpProviderSession>();
+    const seenSessions = new Set<OmpOpenedSession>();
     const seenCleanups = new Set<Promise<void>>();
     const cleanupBatch: Promise<void>[] = [];
     for (const [sessionId, { session, nativeSessionId, token }] of sessions) {
diff -ruN a/package/server/provider/host-tools.ts b/package/server/provider/host-tools.ts
--- a/package/server/provider/host-tools.ts	1985-10-26 08:15:00.000000000 +0000
+++ b/package/server/provider/host-tools.ts	1985-10-26 08:15:00.000000000 +0000
@@ -29,6 +29,7 @@
   truncateUtf8,
   utf8Bytes,
 } from "./security";
+import { withOmpSessionPurpose } from "./session-purpose";
 
 type HostToolFailureStage = Extract<
   OmpOperationalFailure,
@@ -1025,3 +1026,19 @@
   else delete env.PASEO_WORKSPACE_ID;
   return { ...request, env };
 }
+
+/**
+ * The complete env transform for an OMP `agent.session_open` hook: the caller's identity plus the
+ * host-decided launch purpose. Registered once by the plugin and exercised directly by tests.
+ */
+export function withOmpSessionOpenEnv<
+  T extends {
+    agentId: string;
+    workspaceId: string | null;
+    reason?: string;
+    purpose?: string;
+    env: Record<string, string>;
+  },
+>(request: T) {
+  return withOmpSessionPurpose(withOmpWorkspaceIdentity(request));
+}
diff -ruN a/package/server/provider/omp-rpc-transport.ts b/package/server/provider/omp-rpc-transport.ts
--- a/package/server/provider/omp-rpc-transport.ts	1985-10-26 08:15:00.000000000 +0000
+++ b/package/server/provider/omp-rpc-transport.ts	1985-10-26 08:15:00.000000000 +0000
@@ -887,7 +887,7 @@
       : isHistory
         ? 400_000
         : pending.command === "get_available_models"
-          ? 16_384
+          ? 131_072
           : 2_048;
     const violation = jsonBoundViolation(
       boundedFrame,
diff -ruN a/package/server/provider/session-history.ts b/package/server/provider/session-history.ts
--- a/package/server/provider/session-history.ts	1970-01-01 00:00:00.000000000 +0000
+++ b/package/server/provider/session-history.ts	1985-10-26 08:15:00.000000000 +0000
@@ -0,0 +1,330 @@
+import type {
+  ProviderConfigState,
+  ProviderEvent,
+  ProviderInput,
+  ProviderSessionConfig,
+} from "@getpaseo/plugin/server/provider";
+import { normalizeOmpSessionConfig } from "./config-normalization";
+import type { OmpRuntime } from "./omp-rpc";
+import { buildOmpSpawnRequest } from "./omp-rpc-environment";
+import {
+  configuredOutputRedactionValues,
+  OmpPublicDataSerializer,
+  OmpPublicError,
+  utf8Bytes,
+} from "./security";
+import {
+  authorizeNativeSession,
+  fixedSessionMode,
+  type OmpOpenedSession,
+  ompPersistenceSessionId,
+  REPLAY_TIMEOUT_MS,
+  waitForReplay,
+} from "./session";
+import { OmpSubsessionProjector } from "./subsessions";
+import {
+  defaultOmpTimelineScheduler,
+  OmpTimelineProjector,
+  type OmpTimelineScheduler,
+} from "./timeline-projector";
+
+type SessionOpenInput = Extract<ProviderInput, { type: "session.open" }>;
+type SessionPromptInput = Extract<ProviderInput, { type: "session.prompt" }>;
+type SessionInterruptInput = Extract<ProviderInput, { type: "session.interrupt" }>;
+type SessionConfigureInput = Extract<ProviderInput, { type: "session.configure" }>;
+type SessionRevertInput = Extract<ProviderInput, { type: "session.revert" }>;
+type SessionCloseInput = Extract<ProviderInput, { type: "session.close" }>;
+type SessionPermissionInput = Extract<ProviderInput, { type: "session.permission" }>;
+type Emit = (event: ProviderEvent) => void;
+
+// A history session replays a persisted journal and runs nothing. It advertises no prompt,
+// permission, configuration, or rewind capability, so the host rejects those requests itself.
+const HISTORY_CAPABILITIES: readonly string[] = [
+  "session.persistence",
+  "session.subsession",
+  "timeline.plugin",
+];
+const READ_ONLY_MESSAGE = "OMP history sessions are read-only";
+
+/**
+ * Serves a persisted OMP session from its authorized transcript alone. It exists for sessions
+ * whose recorded working directory is gone: no runtime process is spawned, no MCP server is
+ * connected, and the working directory is never touched. The native session identity, workspace
+ * authorization, and transcript ownership checks are the same ones a live resume performs.
+ */
+export class OmpHistorySession implements OmpOpenedSession {
+  readonly id: string;
+  readonly cwd: string;
+
+  private readonly lifetime = new AbortController();
+  private readonly dataFilter: OmpPublicDataSerializer;
+  private readonly projector: OmpTimelineProjector;
+  private readonly subsessions: OmpSubsessionProjector | null;
+  private disposed = false;
+  private sessionClosedPublished = false;
+
+  private constructor(
+    id: string,
+    private readonly config: ProviderSessionConfig,
+    private readonly runtime: OmpRuntime,
+    private readonly readTranscript: NonNullable<OmpRuntime["readPersistedSessionTranscript"]>,
+    private readonly nativeSessionId: string,
+    private readonly transcriptFile: string,
+    private readonly configState: ProviderConfigState,
+    redactionValues: readonly string[],
+    private readonly capabilities: readonly string[],
+    private readonly emit: Emit,
+    private readonly replayTimeoutMs: number,
+    scheduler: OmpTimelineScheduler,
+  ) {
+    this.id = id;
+    this.cwd = config.cwd;
+    this.dataFilter = new OmpPublicDataSerializer(redactionValues);
+    const pluginTimeline = capabilities.includes("timeline.plugin");
+    this.projector = new OmpTimelineProjector(
+      id,
+      emit,
+      scheduler,
+      redactionValues,
+      false,
+      pluginTimeline,
+    );
+    // Same identity key as a live persisted session, so child session ids stay stable across
+    // a history load and a later interactive resume of the same native session.
+    this.subsessions = capabilities.includes("session.subsession")
+      ? new OmpSubsessionProjector(
+          id,
+          `persisted:${nativeSessionId}`,
+          transcriptFile,
+          config.cwd,
+          emit,
+          scheduler,
+          () => {},
+          redactionValues,
+          pluginTimeline,
+        )
+      : null;
+  }
+
+  get persistenceSessionId(): string {
+    return this.nativeSessionId;
+  }
+
+  static async open(
+    input: SessionOpenInput,
+    runtime: OmpRuntime,
+    capabilities: readonly string[],
+    emit: Emit,
+    replayTimeoutMs = REPLAY_TIMEOUT_MS,
+    environment?: NodeJS.ProcessEnv,
+    hostInheritEnv: readonly string[] = [],
+    scheduler: OmpTimelineScheduler = defaultOmpTimelineScheduler,
+  ): Promise<OmpHistorySession> {
+    const nativeSessionId = ompPersistenceSessionId(input);
+    if (!nativeSessionId || input.history !== "replay" || !input.config.persist) {
+      throw new OmpPublicError("OMP history purpose requires a persisted session replay");
+    }
+    const normalized = normalizeOmpSessionConfig(
+      input.config,
+      capabilities.includes("permission"),
+      hostInheritEnv,
+    );
+    if (input.config.title && utf8Bytes(input.config.title) > 256) {
+      throw new OmpPublicError("OMP session title is too large");
+    }
+    const readTranscript = runtime.readPersistedSessionTranscript?.bind(runtime);
+    if (!readTranscript) throw new OmpPublicError("OMP session history cannot be replayed safely");
+    // The same workspace and native-identity authorization as a live resume; only the spawn is
+    // skipped. The recorded cwd is compared, never opened.
+    const descriptor = await authorizeNativeSession(
+      runtime,
+      nativeSessionId,
+      input.config.cwd,
+      normalized.sessionDir,
+    );
+    if (!descriptor.transcriptFile) {
+      throw new OmpPublicError("OMP session transcript could not be resolved in this workspace");
+    }
+    const configuredValues = configuredOutputRedactionValues(
+      normalized.outputRedaction ?? "none",
+      normalized.env,
+      input.config.mcpServers,
+    );
+    // Inherited values are redacted exactly as a live session would: they come from the same
+    // spawn-request builder, which only reads the server environment.
+    const redactionValues =
+      normalized.outputRedaction === "configured-values"
+        ? [
+            ...configuredValues,
+            ...buildOmpSpawnRequest({
+              ...normalized,
+              environment,
+              // A resume never reapplies the system prompt or thinking selection.
+              systemPrompt: undefined,
+              thinkingOption: undefined,
+              resumeSessionId: nativeSessionId,
+              resumeSessionFile: descriptor.transcriptFile,
+            }).inheritedRedactionValues,
+          ]
+        : configuredValues;
+    const configState: ProviderConfigState = {
+      ...(input.config.model ? { model: input.config.model } : {}),
+      mode: normalized.mode ?? "full",
+      ...(input.config.thinkingOption ? { thinkingOption: input.config.thinkingOption } : {}),
+      models: [],
+      modes: [fixedSessionMode(normalized.mode)],
+      thinkingOptions: [],
+      settings: [],
+    };
+    return new OmpHistorySession(
+      input.sessionId,
+      input.config,
+      runtime,
+      readTranscript,
+      nativeSessionId,
+      descriptor.transcriptFile,
+      configState,
+      redactionValues,
+      capabilities.filter((capability) => HISTORY_CAPABILITIES.includes(capability)),
+      emit,
+      replayTimeoutMs,
+      scheduler,
+    );
+  }
+
+  async publishOpened(requestId: string): Promise<void> {
+    this.emit({
+      type: "session.opened",
+      requestId,
+      sessionId: this.id,
+      capabilities: this.capabilities,
+      restoration: "core",
+      cwd: this.cwd,
+      persistence: { version: 1, data: { sessionId: this.nativeSessionId } },
+      ...(this.config.title ? { title: this.dataFilter.text(this.config.title, 256) } : {}),
+    });
+    this.emit({ type: "session.config", sessionId: this.id, config: this.configState });
+    await this.replayHistory();
+    this.emit({ type: "session.ready", requestId, sessionId: this.id });
+  }
+
+  private async replayHistory(): Promise<void> {
+    this.lifetime.signal.throwIfAborted();
+    const replay = new AbortController();
+    const onAbort = () =>
+      replay.abort(new OmpPublicError("OMP session history replay was canceled"));
+    this.lifetime.signal.addEventListener("abort", onAbort, { once: true });
+    const timeoutHandle = setTimeout(
+      () => replay.abort(new OmpPublicError("OMP session history replay timed out")),
+      this.replayTimeoutMs,
+    );
+    try {
+      const transcript = await waitForReplay(
+        this.readTranscript({
+          sessionFile: this.transcriptFile,
+          sessionId: this.nativeSessionId,
+          cwd: this.cwd,
+          signal: replay.signal,
+        }),
+        replay.signal,
+      );
+      if (transcript.imageReplayWarning) {
+        this.emit({
+          type: "timeline.item",
+          sessionId: this.id,
+          item: {
+            id: "omp:replay-image-unavailable",
+            type: "notification",
+            level: "warning",
+            message: "OMP skipped one or more unavailable images while replaying this session.",
+          },
+        });
+      }
+      for (const message of transcript.messages) {
+        replay.signal.throwIfAborted();
+        this.projector.projectReplayMessage(message);
+      }
+      this.projector.finishReplay();
+      await this.subsessions?.replay(transcript.messages, undefined, this.runtime, replay.signal);
+      replay.signal.throwIfAborted();
+    } catch (error) {
+      if (replay.signal.aborted) throw replay.signal.reason;
+      throw error;
+    } finally {
+      clearTimeout(timeoutHandle);
+      this.lifetime.signal.removeEventListener("abort", onAbort);
+    }
+  }
+
+  openPaseoBrowser(): Promise<void> {
+    return Promise.reject(new OmpPublicError(READ_ONLY_MESSAGE));
+  }
+
+  setBrowserAuthorizationIssuer(issue: ((url: string) => string | undefined) | null): void {
+    this.projector.setBrowserAuthorizationIssuer(issue);
+  }
+
+  prompt(input: SessionPromptInput): Promise<void> {
+    this.emit({
+      type: "session.prompt_result",
+      sessionId: this.id,
+      clientMessageId: input.prompt.clientMessageId,
+      result: { type: "failed", error: { message: READ_ONLY_MESSAGE } },
+    });
+    return Promise.resolve();
+  }
+
+  permission(_input: SessionPermissionInput): Promise<void> {
+    return Promise.reject(new OmpPublicError("OMP history sessions have no pending permissions"));
+  }
+
+  configure(input: SessionConfigureInput): Promise<void> {
+    this.emit({
+      type: "request.failed",
+      requestId: input.requestId,
+      error: { message: READ_ONLY_MESSAGE },
+    });
+    return Promise.resolve();
+  }
+
+  revert(input: SessionRevertInput): Promise<void> {
+    this.emit({
+      type: "request.failed",
+      requestId: input.requestId,
+      error: { message: READ_ONLY_MESSAGE },
+    });
+    return Promise.resolve();
+  }
+
+  interrupt(input: SessionInterruptInput): Promise<void> {
+    this.emit({ type: "request.completed", requestId: input.requestId });
+    return Promise.resolve();
+  }
+
+  beginConnectionShutdown(): void {
+    this.lifetime.abort(new Error("OMP provider connection closed"));
+  }
+
+  abortOpen(): Promise<void> {
+    this.dispose();
+    return Promise.resolve();
+  }
+
+  close(input?: SessionCloseInput): Promise<void> {
+    this.dispose();
+    if (!this.sessionClosedPublished) {
+      this.sessionClosedPublished = true;
+      this.emit({ type: "session.closed", sessionId: this.id });
+    }
+    if (input) this.emit({ type: "request.completed", requestId: input.requestId });
+    return Promise.resolve();
+  }
+
+  private dispose(): void {
+    if (this.disposed) return;
+    this.disposed = true;
+    this.lifetime.abort(new Error("OMP provider session closed"));
+    this.subsessions?.close();
+    this.projector.close();
+  }
+}
diff -ruN a/package/server/provider/session-purpose.ts b/package/server/provider/session-purpose.ts
--- a/package/server/provider/session-purpose.ts	1970-01-01 00:00:00.000000000 +0000
+++ b/package/server/provider/session-purpose.ts	1985-10-26 08:15:00.000000000 +0000
@@ -0,0 +1,56 @@
+import type { ProviderInput } from "@getpaseo/plugin/server/provider";
+import { OmpPublicError } from "./security";
+
+type SessionOpenInput = Extract<ProviderInput, { type: "session.open" }>;
+
+/**
+ * Paseo tells plugins why a session is being opened only through `before("agent.session_open")`
+ * hooks, whose sole writable field is `env`; the plugin provider protocol forwards that env
+ * untouched as `session.open.config.env`. The hook is therefore the single writer of this launch
+ * marker and the connection is the single reader. It is never part of the stored agent config.
+ */
+export const OMP_SESSION_PURPOSE_ENV = "PASEO_OMP_SESSION_PURPOSE";
+const HISTORY_PURPOSE = "history";
+
+/**
+ * Derives the launch marker from the host-decided purpose. Any marker already present is caller
+ * input (for example `env` on agent creation), so it is always discarded first: only a host
+ * resume whose purpose is history can produce it, and an absent purpose (older hosts) never does.
+ */
+export function withOmpSessionPurpose<
+  T extends { reason?: string; purpose?: string; env: Record<string, string> },
+>(request: T): Omit<T, "env"> & { env: Record<string, string> } {
+  const env: Record<string, string> = { ...request.env };
+  delete env[OMP_SESSION_PURPOSE_ENV];
+  if (request.purpose === HISTORY_PURPOSE && request.reason === "resume") {
+    env[OMP_SESSION_PURPOSE_ENV] = HISTORY_PURPOSE;
+  }
+  return { ...request, env };
+}
+
+/**
+ * True when this open must be served from the persisted transcript alone, without a runtime
+ * process or any working-directory access. The marker only narrows a persisted replay: it can
+ * never be satisfied by a create, a non-replaying open, or a non-persisted config.
+ */
+export function isOmpHistoryOnlyOpen(input: SessionOpenInput): boolean {
+  const marker = input.config.env[OMP_SESSION_PURPOSE_ENV];
+  if (marker === undefined) return false;
+  if (marker !== HISTORY_PURPOSE) throw new OmpPublicError("Invalid OMP session purpose");
+  if (input.history !== "replay" || !input.persistence || !input.config.persist) {
+    throw new OmpPublicError("OMP history purpose requires a persisted session replay");
+  }
+  return true;
+}
+
+/**
+ * Removes the reserved launch marker from any env bound for an OMP process. The marker steers
+ * the plugin only; it must never be forwarded to, or settable through per-agent provider options
+ * for, a real OMP runtime.
+ */
+export function withoutOmpSessionPurpose(
+  env: Readonly<Record<string, string>>,
+): Record<string, string> {
+  const { [OMP_SESSION_PURPOSE_ENV]: _reserved, ...rest } = env;
+  return rest;
+}
diff -ruN a/package/server/provider/session.ts b/package/server/provider/session.ts
--- a/package/server/provider/session.ts	1985-10-26 08:15:00.000000000 +0000
+++ b/package/server/provider/session.ts	1985-10-26 08:15:00.000000000 +0000
@@ -93,6 +93,23 @@
 type RewindSessionRetirement = () => void;
 type SessionPermissionInput = Extract<ProviderInput, { type: "session.permission" }>;
 type Emit = (event: ProviderEvent) => void;
+
+/** The surface a connection drives for every opened session, live or history-only. */
+export interface OmpOpenedSession {
+  readonly persistenceSessionId: string | undefined;
+  openPaseoBrowser(url: string): Promise<void>;
+  setBrowserAuthorizationIssuer(issue: ((url: string) => string | undefined) | null): void;
+  publishOpened(requestId: string): Promise<void>;
+  prompt(input: SessionPromptInput): Promise<void>;
+  permission(input: SessionPermissionInput): Promise<void>;
+  configure(input: SessionConfigureInput): Promise<void>;
+  revert(input: SessionRevertInput): Promise<void>;
+  interrupt(input: SessionInterruptInput): Promise<void>;
+  close(input?: SessionCloseInput): Promise<void>;
+  abortOpen(): Promise<void>;
+  beginConnectionShutdown(): void;
+}
+
 const LOCAL_ONLY_SETTLE_MS = 5_000;
 const AGENT_END_STATE_TIMEOUT_MS = 2_000;
 const AGENT_END_HISTORY_TIMEOUT_MS = 2_000;
@@ -119,7 +136,7 @@
 const MAX_UNCLAIMED_BRANCH_BYTES = 4 * 1024 * 1024;
 class OmpCatalogEscape extends OmpPublicError {}
 const MAX_REPLAY_MESSAGES = 100_000;
-const REPLAY_TIMEOUT_MS = 20_000;
+export const REPLAY_TIMEOUT_MS = 20_000;
 const _OMP_ASK_USER_FREEFORM_SENTINEL = "✏️ Type custom response...";
 const _MAX_FREEFORM_RESPONSE_BYTES = 64 * 1024;
 const OMP_BUILTIN_COMMANDS: readonly OmpAvailableCommand[] = [
@@ -162,7 +179,7 @@
   return model?.reasoning === false ? undefined : level;
 }
 
-function fixedSessionMode(modeId = "full") {
+export function fixedSessionMode(modeId = "full") {
   const mode = OMP_MODES.find((candidate) => candidate.id === modeId);
   if (!mode) throw new OmpPublicError("OMP mode is unavailable");
   return {
@@ -194,7 +211,7 @@
   }
 }
 
-async function authorizeNativeSession(
+export async function authorizeNativeSession(
   runtime: OmpRuntime,
   sessionId: string,
   cwd: string,
@@ -228,7 +245,7 @@
   return total;
 }
 
-async function waitForReplay<T>(operation: Promise<T>, signal: AbortSignal): Promise<T> {
+export async function waitForReplay<T>(operation: Promise<T>, signal: AbortSignal): Promise<T> {
   signal.throwIfAborted();
   const aborted = Promise.withResolvers<never>();
   const onAbort = () => aborted.reject(signal.reason);
@@ -271,7 +288,7 @@
     throw new AggregateError(failures, "OMP session initialization cleanup failed");
   }
 }
-export class OmpProviderSession {
+export class OmpProviderSession implements OmpOpenedSession {
   readonly id: string;
   readonly cwd: string;
 
diff -ruN a/package/server/provider/subsessions.ts b/package/server/provider/subsessions.ts
--- a/package/server/provider/subsessions.ts	1985-10-26 08:15:00.000000000 +0000
+++ b/package/server/provider/subsessions.ts	1985-10-26 08:15:00.000000000 +0000
@@ -390,7 +390,8 @@
   }
   async replay(
     messages: readonly OmpMessage[],
-    runtimeSession: OmpRuntimeSession,
+    // Undefined replays the persisted journal only; history sessions have no live runtime to ask.
+    runtimeSession: OmpRuntimeSession | undefined,
     runtime: OmpRuntime,
     signal: AbortSignal,
   ): Promise<void> {
@@ -411,12 +412,14 @@
         0,
       );
       let snapshots: OmpSubagentSnapshot[] = [];
-      try {
-        snapshots = await waitForReplay(runtimeSession.getSubagents(), signal);
-      } catch (error) {
-        if (signal.aborted) throw error;
+      if (runtimeSession) {
+        try {
+          snapshots = await waitForReplay(runtimeSession.getSubagents(), signal);
+        } catch (error) {
+          if (signal.aborted) throw error;
+        }
+        await this.replaySnapshots(snapshots, runtimeSession, runtime, visited, budget, signal);
       }
-      await this.replaySnapshots(snapshots, runtimeSession, runtime, visited, budget, signal);
       signal.throwIfAborted();
       this.reconcileSnapshots(snapshots);
       completed = true;
diff -ruN a/package/shared/omp-models.ts b/package/shared/omp-models.ts
--- a/package/shared/omp-models.ts	1985-10-26 08:15:00.000000000 +0000
+++ b/package/shared/omp-models.ts	1985-10-26 08:15:00.000000000 +0000
@@ -5,7 +5,7 @@
 
 const OMP_MODEL_TEXT_LIMIT = 256;
 const OMP_MODEL_SELECTOR_LIMIT = OMP_MODEL_TEXT_LIMIT * 2 + 1;
-const OMP_MODEL_LIST_LIMIT = 256;
+const OMP_MODEL_LIST_LIMIT = 4_096;
 const OMP_MODEL_INPUT_LIMIT = 16;
 const OMP_THINKING_LEVEL_LIMIT = 16;
 const OMP_THINKING_LEVEL_TEXT_LIMIT = 32;

This version ships OVERVIEW.md, so the registry's copy is removed in this bump.

Inline validation passed: npm test and the checks from node scripts/validate.ts --online --changed. The default GITHUB_TOKEN does not trigger the PR validation workflow.

@github-actions github-actions Bot added the bump Pinned artifact update label Oct 8, 2026

@paseo-bot paseo-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OMP 1.3.2 remains unpublished because its runtime dependency installation is not locked. Your shipped OVERVIEW.md completes the listing page; no overview-only release is needed.

Please publish a new version with npm-shrinkwrap.json at the package root, locking all runtime dependencies and their transitive tree with resolved sources and integrity. For the npm artifact, remove the catalog preparation command from paseo-plugin.json, or change it to consume the shipped lockfile without --no-package-lock or floating installs. Then update this PR’s artifact pin. The current package has no lockfile, declares yaml: "^2.9.0", and its preparation script can run another unlocked npm install when it finds an ancestor catalog. See REVIEW.md’s packaging requirement and the publishing guide’s build guidance.

Optional next release: mention that archived history can now open read-only after its workspace is removed, so users understand when OMP will run and when it only reads transcripts.

Review data
  • Reviewed head: 5dd5e3fe8687ec4e38d80506a1a3864d850d59b6. REVIEW.md blob: 7268134d240de9e474c52480f4937af4e369a6e2.
  • npm @omercnet/paseo-omp@1.2.0 → 1.3.2. Both pinned tarballs downloaded, SHA-512 matched records and npm metadata, archive paths/types checked before extraction. New integrity: sha512-WnW5siuFtdOqgXcBtzri5Zc1ZQCS/qOCU6ZSukLoy3G6waKS86yjhzwOVlNfqv2TXLDeYDHIrtk9EqbUqicV8w==. Provenance backs registry commit 45b6656c5963468b10d41206e4386eabf528db23; existing ownership/submitter unchanged.
  • 97 old and 100 new files; complete independent 941-line diff inspected. Changes include author overview, quota/tool-boundary text, larger bounded model catalog responses, updated SDK dependency, and history-only session handling. New history path checks persisted replay and host-derived purpose, authorizes the native ID and recorded cwd, reads the transcript, and rejects prompt/configure/revert/browser operations. Interactive launches strip the reserved marker (server/provider/session-purpose.ts, session-history.ts, connection.ts, config-normalization.ts); authorization uses the existing exact session/cwd lookup (session.ts:214-232).
  • Runtime dependencies: protocol 0.11.1, MCP SDK 1.30.0, yaml ^2.9.0. No lockfile or bundled installed tree is shipped. Manifest invokes node scripts/prepare-dependencies.mjs; full invoked script read. Its ancestor catalog search (:8-16) conditionally stages package.json and invokes npm install --omit=dev --ignore-scripts --no-package-lock --workspaces=false (:19-50). It otherwise returns without installing. This script is unchanged; the runtime tree was already unlocked in 1.2.0. No package install lifecycle hooks.
  • Existing purposeful OMP/MCP process launches, settings/transcript/quota reads, settings edits and provider environment handling remain. The changed history path does not spawn OMP or connect MCP; it reads authorized history. No new unrelated outbound destination was found in the delta. Full dependency internals and the eventual installed tree remain uninspected because that tree is not fixed; no security approval is claimed.
  • Shipped overview takes precedence and fallback deletion is correct. No bot registry edits needed. Trusted current-main online validation passes, including existing listing media URL checks, but does not enforce dependency locking. Prior PR #161’s packaging discussion was read; this is an author-fixable packaging requirement under current policy, without a new maintainer safety decision.
  • No plugin/dependency code installed, built or run. Live provider sessions were not exercised. No linked submission issue or author discussion was found.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bump Pinned artifact update

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants