Files
ocp/CHANGELOG.md
taodengandClaude Opus 4.7 7d64cd3158 fix(plugin): revert default to 3456 + correct v3.16.1 narrative; v3.16.2
v3.16.1's narrative ("OCP server moved to 3478 default in v3.14+") was
incorrect. OCP source default has been 3456 since 593d0dc (initial
release) and never changed. The single observation of 3478 is the
maintainer's Mac mini, whose plist was rewritten with --port 3478
during a 2026-05-08 PR #71 dogfood smoke-test accident (see
~/.cc-rules/memory/learnings/subagent_setup_mjs_prod_host_collision.md).
The drift was never reconciled and v3.16.1 mistakenly canonised the
post-accident port as the new default.

This release reverts:
- ocp-plugin/index.js fallback → http://127.0.0.1:3456
- openclaw.plugin.json configSchema.proxyUrl.default → http://127.0.0.1:3456
- README §Environment Variables CLAUDE_PROXY_PORT default → 3456
- top-level package.json → 3.16.2

PR #95's env-reading path (OCP_PROXY_URL → CLAUDE_PROXY_PORT → fallback)
is preserved — that part was good design and stays. Only the hardcoded
fallback default changes.

Hosts whose OCP plist injects a non-default port must also inject the
same CLAUDE_PROXY_PORT into the OpenClaw plist for the plugin to follow
(documented in the new index.js comment block).

Mac mini's plist was reverted from 3478 to 3456 as part of this deploy
(per-host correction; no source code reflects host-specific state).

CHANGELOG includes an explicit erratum entry under v3.16.1 marking it
superseded.

Process note: this PR was triggered by maintainer asking "why was the
port changed?" — the answer revealed I (PM) wrote v3.16.1's CHANGELOG
without running `git log -G "3478" -- setup.mjs`. Iron Rule 2
(evidence-first) was violated. Future commits asserting historical
facts must include the grep that confirmed them.

No cli.js citation needed: OCP-internal plugin + docs, no server.mjs
change.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-12 12:15:21 +10:00

14 KiB
Raw Permalink Blame History

Changelog

v3.16.2 — 2026-05-12

Fixes — corrects v3.16.1

The v3.16.1 fix was directionally correct (plugin now reads env first, falls back to a hardcoded default) but the narrative and the hardcoded default were both wrong.

What v3.16.1 said: "OCP server moved to 3478 default in v3.14+; plugin lagged at 3456." What is actually true:

  • OCP server source default has been 3456 since 593d0dc (initial release) and has never changed. Every line in server.mjs, setup.mjs, and the ocp CLI still uses 3456 as the documented and code-level default.
  • The single OCP installation observed on 3478 is the maintainer's Mac mini, whose plist was rewritten with --port 3478 during a PR #71 dogfood smoke-test accident on 2026-05-08 (see ~/.cc-rules/memory/learnings/subagent_setup_mjs_prod_host_collision.md). The plist drift was never reconciled back to source default, and v3.16.1 incorrectly canonised the post-accident value as if it had been a release decision.

This release:

  • Restores the plugin fallback to http://127.0.0.1:3456 to match server source default.
  • Updates openclaw.plugin.json configSchema.proxyUrl.default back to 3456.
  • Restores README §"Environment Variables" CLAUDE_PROXY_PORT default to 3456.
  • Plugin reads OCP_PROXY_URL env (full URL) first, then CLAUDE_PROXY_PORT env (port only), then falls back to 3456. Hosts whose OCP plist injects a non-default port must also inject the same CLAUDE_PROXY_PORT into the OpenClaw plist for the plugin to follow.
  • Maintainer's Mac mini plist was reverted from 3478 to 3456 as part of this release deploy (no source change reflects this; it was a one-host correction).

Governance

  • No cli.js citation needed (no server.mjs change). ALIGNMENT.md Rule 2 not engaged.

v3.16.1 — 2026-05-12 (superseded — narrative incorrect; see v3.16.2 erratum)

Fixes (as shipped — note erratum above)

  • OCP plugin port lagocp-plugin/index.js hard-coded http://127.0.0.1:3456. While OCP server moved to 3478 in v3.14+, (corrected v3.16.2: no such move ever happened.) The Mac mini's plist was on 3478 only as residue from a dogfood accident. Result: /ocp slash commands from the home Telegram bot returned "OCP error: fetch failed". v3.16.1 changed the plugin default to 3478 (wrong direction; v3.16.2 reverts to 3456).

Governance

  • No cli.js citation needed (no server.mjs change). ALIGNMENT.md Rule 2 not engaged.

v3.16.0 — 2026-05-10

Features

  • ocp doctor --check oauth (PR #93) — fast path that runs only the OAuth check, skipping version detection / from-version / git operations / models endpoint. ~50ms vs. full doctor's ~200-500ms. Use cases: AI agent repair loops, post-claude auth login verify, quick health gates. Help text in cmd_doctor_help now reflects working behaviour.
  • ocp update --rollback --gc — manually garbage-collect old upgrade snapshots. Retention policy: keep last 5 snapshots OR snapshots newer than 30 days OR the single most recent (always-keep safety net). --dry-run previews. Successful ocp update runs auto-GC at the end of the full path; light path does not (no snapshot created there).

Behavior changes

  • After a successful cross-minor ocp update, the auto-GC emits [gc] removed N old snapshots to stderr if any were collected. Safe to ignore; manual gc is ocp update --rollback --gc.

Governance

  • No cli.js citation needed (no server.mjs change). ALIGNMENT.md Rule 2 not engaged.
  • PR #93 (--check oauth) merged separately; this release bundles it with the GC feature.

v3.15.1 — 2026-05-10

Fixes

  • doctor: dynamic latest_version from origin/main:package.json — v3.15.0 doctor used a hard-coded latest = "v3.14.0" fallback, which made any v3.15.0+ install report kind = upgrade (against a stale value). ocp update would then attempt git checkout v3.14.0 — a downgrade. Doctor now fetches git -C ~/ocp show origin/main:package.json to determine the actual latest version; on failure (offline, fresh clone with no remote), falls back to currentVersion so kind = noop instead of recommending a downgrade.

v3.15.0 — 2026-05-10

Features

  • ocp doctor — health & upgrade-readiness check; primary entry for AI-driven debugging. --json mode emits a next_action with ai_executable[] for agents to run verbatim and human_required[] for steps requiring the user (typically only OAuth).
  • ocp update cross-version path — for cross-minor jumps (e.g. v3.10 → v3.14), ocp update now runs doctor → snapshot → setup.mjs (with the plist env-merge from PR #90) → service restart → post-flight /health + /v1/models verification. Same-patch updates retain the existing light path; users see no change for routine patch bumps.
  • ocp update --rollback — restore the most recent (or specified) upgrade snapshot. Snapshots are saved to ~/.ocp/upgrade-snapshot-<ISO-ts>/ and never auto-deleted.
  • Fresh-install routingocp update on installations < v3.4.0 routes to a fresh-install flow (with --yes to skip confirmation; AI agents pass this). OAuth survives via Claude Code's credential store; users do not re-OAuth unless their token was independently broken.
  • AI prompt blocks in README — §Installation, §Upgrading, and §Troubleshooting each start with a copy-paste prompt for Claude Code / Cursor / Copilot, so users can drive install / setup / upgrade through their existing AI assistant.

Behavior changes

  • ocp update may take 1030s longer when a cross-minor jump triggers the full path (snapshot + post-flight). Patch bumps are unchanged.
  • Pre-v3.4.0 installs are routed to fresh-install rather than failing silently or half-migrating.

Governance

  • No cli.js citation needed (no server.mjs change). ALIGNMENT.md Rule 2 not engaged.
  • Depends on PR #90 (plist env merge bug fix; merged before this release).

v3.14.0 — 2026-05-10

Features (security hardening)

  • Per-key session isolation (PR #86, S1) — the sessions Map in server.mjs is now keyed by ${keyName}|${conversationId} instead of bare conversationId. Before this fix, two clients using distinct API keys but the same session_id value (e.g. both defaulting to "default") would share the same cli.js subprocess and conversation history, creating a cross-tenant leak path. Post-fix each (key, session) pair is isolated end-to-end, extending the per-key cache isolation shipped in v3.13.0 D1 to the session layer.
  • On-disk credential file modes 0700/0600 (PR #87, S2) — setup.mjs now creates ~/.ocp at mode 0700 and both admin-key and ocp.db at mode 0600. An idempotent reconcileFileModes() call in server.mjs startup tightens any existing installation to these modes automatically on every launch, so existing prod boxes fix themselves without manual chmod. Before this fix, all three files were created at the process's default umask (typically world-readable 0644 / 0755), leaving plaintext credentials readable by other local users.
  • /api/usage default scope = self; admin all-keys requires ?all=true (PR #88, S3) — the usage endpoint now applies a least-privilege default: anonymous callers receive only their own rows, non-admin authenticated callers receive only their own rows, and admin callers receive only their own rows unless they explicitly pass ?all=true. When ?all=true is used, an audit log line is emitted. Before this fix, any admin-token holder could silently enumerate usage data for every key on the server.

Behavior changes

  • Breaking change for admin tooling: /api/usage no longer returns all-keys data by default. Existing cron jobs, dashboards, or scripts that rely on the admin token seeing all-keys output must add ?all=true to their request URL after upgrading to v3.14.0.
  • File mode reconcile at server startup logs a one-line notice per path when mode is tightened (e.g. [security] tightened ~/.ocp/ocp.db → 0600). No action is required from the operator; the reconcile is idempotent and silent when modes are already correct.
  • sessions Map key is now ${keyName}|${conversationId} internally. No client-visible wire change — the session_id field in request/response is unchanged.

Verification

  • Stress-test pass: 11/11 phases including S1/S2/S3 security regression checks (Phase E, I, J). 35-minute sustained run, 60 calls, 0 errors, 0 timeouts. RSS dropped 51→47 MB across the window. Per-key cache isolation, singleflight, cache_control bypass, quota enforcement, file-mode reconcile, and scope guard against escalation all verified against running code.

Governance

  • All three PRs (#86, #87, #88) include the explicit cli.js-citation-not-applicable disclaimer (per PR #75 pattern) since they are OCP-internal access-control, session-state, and file-permission changes with no corresponding cli.js operation to cite.

No new env vars / no public API surface change beyond the documented breaking change

This release adds no new env vars or endpoints. The only externally visible change is the /api/usage scope guard (breaking for admin all-keys consumers; see Behavior changes above).

v3.13.0 — 2026-05-07

Features (cache layer hardening)

  • Per-key cache isolation (D1) — the cache key now includes the API key id, so distinct keys never share cache entries. Anonymous/unauthenticated callers share one anon pool. Hash format upgraded to v2; legacy v1-format rows orphan and are reaped by the existing TTL cleanup interval (no migration script).
  • cache_control bypass (D2) — when a request carries an Anthropic cache_control annotation (top-level or nested in a content array), OCP skips its own cache entirely. The caller is using Anthropic-side prompt caching deliberately, and OCP must not interfere. A cache_skipped{reason: cache_control_present} log line is emitted on bypass.
  • Chunked stream replay (D3) — when a streaming request hits the cache, the cached content is now emitted as multiple SSE chunks (80 codepoints/chunk, codepoint-safe via Array.from()) instead of a single large delta. Multibyte characters (CJK / emoji) stay intact.
  • Singleflight stampede protection (D4) — concurrent identical cache-miss requests now share one upstream cli.js spawn instead of spawning N processes. Followers receive byte-identical responses to what the leader returns. All-or-nothing failure semantics: if the leader errors, all followers receive the same error. Streaming-path singleflight is explicitly out of scope (TODO left for follow-up).

Behavior changes

  • /cache/stats response now includes additive fields inflight and requesters (current in-flight singleflight entries and total waiting callers). Existing fields entries, totalHits, sizeBytes are preserved unchanged.

Governance

No new env vars / no public API surface change

This release adds no new env vars or endpoints. All four improvements are internal correctness/concurrency upgrades to the existing CLAUDE_CACHE_TTL-gated cache layer. No client-observable wire shape change.

v3.12.0 — 2026-04-25

Features

  • Streaming heartbeat — opt-in SSE comment frame (: keepalive\n\n) emitted during silent windows on the streaming response. Controlled by CLAUDE_HEARTBEAT_INTERVAL env var (ms; 0 = disabled, default). Covers both pre-first-byte and mid-stream tool-use pauses. Addresses #47. See design doc.
  • X-Accel-Buffering: no response header added to SSE responses so heartbeats survive nginx/Cloudflare default buffering.

Behavior changes

  • SSE headers are now sent immediately after the claude CLI spawns successfully, not on first stdout byte. The rare "spawn succeeded but subprocess died before any byte" path now closes the SSE stream cleanly rather than returning a JSON error.

Config additions

Variable Default Description
CLAUDE_HEARTBEAT_INTERVAL 0 (disabled) Interval in ms for SSE keepalive comment frames on streaming path. Resets on every real frame.

v3.11.1 — 2026-04-21

Fixes

  • Concurrency slot leak on subprocess timeout (#37). The request-timeout handler called proc.kill("SIGTERM") without decrementing stats.activeRequests. A subprocess stuck in a syscall that ignored SIGTERM would hold its slot until (or beyond) the 5s SIGKILL escalation actually reaped it. Slot release is now wired to proc.once("exit", cleanup) so every termination path — normal close, error, SIGTERM, SIGKILL — releases the slot exactly once.

v3.11.0 — 2026-04-20

Features

  • ocp update now automatically syncs OpenClaw's registry with the latest models (scripts/sync-openclaw.mjs)
  • Server logs warn if OpenClaw registry drifts from models.json

Refactor

  • models.json is now the single source of truth for model list
  • server.mjs and setup.mjs derive MODEL_MAP/MODELS from models.json
  • Adding a new model is now a one-file edit

Fixes

  • OpenClaw's model dropdown now shows all 4 current models (opus-4-7, opus-4-6, sonnet-4-6, haiku-4.5) on existing installs after ocp update. Previously setup.mjs only wrote the registry at install time.