--- name: update-openclaw description: Use when bumping the pinned OpenClaw core version (openclaw npm package), when preparing a Pinchy release, or when the user asks to "update OpenClaw" / "upgrade OpenClaw" / check for a newer OpenClaw version. --- # Update the pinned OpenClaw version ## Overview Pinchy pins the OpenClaw core runtime version in two places that a drift guard keeps in lockstep: - `packages/web/package.json` → `dependencies.openclaw` - `Dockerfile.openclaw` → `RUN npm install -g openclaw@` `packages/web/src/__tests__/lib/openclaw-version-pin-drift.test.ts` greps `Dockerfile.openclaw` for the literal `npm install -g openclaw@` line and fails if it doesn't match `package.json`. Both places also feed `/api/version`. **Core principle: OpenClaw upgrades have repeatedly broken Pinchy in ways `pnpm test`/`tsc` don't catch**, because the breakage is in runtime protocol behavior (session keys, `tools.allow` semantics, `config.apply` timing, plugin manifest resolution) — see the `reference_oc_*` / `reference_openclaw_*` memory entries about past compatibility cliffs. Never treat "npm view shows a newer version" as a green light by itself. Read the release notes for every version between current and target first. ## Procedure 1. **Check current vs. latest.** ```bash grep openclaw packages/web/package.json npm view openclaw version npm view openclaw versions --json | tail -20 # see every point release in between ``` 2. **Read every release's notes between current (exclusive) and target (inclusive)** — not just the target's diff summary, since intermediate point releases can carry changes too: ```bash gh release list --repo openclaw/openclaw --limit 20 gh release view v --repo openclaw/openclaw ``` Read the full text, not just headline "Highlights" — the "Additional ... fixes" subsections often contain the entry that actually matters to us. Work through it against these four questions, in this order, and write down what you find for each before moving to step 3: **a. Incompatibility risk.** Anything touching session keys, `tools.allow` semantics, `config.apply` timing, plugin config/manifest resolution, or provider `baseUrl` handling — the areas that have bitten us before (see `reference_oc_*` / `reference_openclaw_*` memory entries). Look at sections titled "Sessions", "Gateway, Security, and Trust", "Plugins and Packaging", and any breaking/migration language anywhere else. **Watch especially for new gateway-startup / config self-healing behavior** — these don't show up in `pnpm test`/`tsc` at all and only fail in the docker E2Es. **The `agent:bootstrap` hook contract is one of these silent dependencies.** `config/pinchy-hooks/bootstrap-memory-group-filter/` (the #369 leak fix) assumes the event carries `context.bootstrapFiles` (array) and `context.sessionKey` (string), that reassigning `context.bootstrapFiles` is read back by the caller, and that internal hooks load via native `import()`. If the notes touch bootstrap/hook events, session-key shape, or the internal hook loader, verify against the installed dist that these still hold — the hook now `console.warn`s instead of failing open, so also check the gateway logs on the staging deploy for that warning. A silent contract change here re-opens a P0 `eu-ai-act` memory leak. See the hook's `HOOK.md` Verification section for the exact staging check. Real example the 2026.6.11 bump tripped: OpenClaw 2026.6.x added startup config auto-restore — on a size-drop / missing-meta vs last-known-good it restores `openclaw.json.last-good` over `openclaw.json` at gateway start (`recoverConfigFromLastKnownGood`). This broke the setup-wizard reset (it deleted `openclaw.json` but not the backups, so OC restored the prior test's config referencing wiped secrets → crash-loop). If notes mention config backup / last-known-good / recovery / restore, expect the setup-wizard + integration E2Es to need reset-choreography updates. **b. Resolved issues we have workarounds for.** Grep our own code for the upstream issue/PR numbers and version-guard comments before reading notes: ```bash git grep -rniE "openclaw/openclaw#[0-9]+|openclaw issue|version.?guard|workaround|TODO\(#" -- packages/ config/ | grep -vi node_modules ``` For each hit, check the upstream issue state (`gh issue view --repo openclaw/openclaw --json state,closedAt`). But **"issue closed" is necessary, not sufficient** — a closed issue is where naive audits go wrong. Before removing any workaround, confirm ALL of: 1. **The fix shipped in a release ≤ our target pin.** Close date ≠ release date, and release notes often don't name the issue. When in doubt, inspect the actually-installed bundle in `node_modules/.pnpm/openclaw@/node_modules/openclaw/dist` for the fixed code, not just the changelog. 2. **The fix targets OUR code path**, not a sibling. Real example: openclaw #75534 (config.apply no-op restart, tracked on our side by #215) fixed OpenClaw's _own_ `writeConfigFile` short-circuit — but Pinchy writes the config file itself and then calls `config.apply`, a different path whose `env.*`→default-`restart` mechanism was still present verbatim in 2026.6.11. Issue closed, workaround NOT removable. 3. **The workaround is actually a bug-workaround**, not a defensive error-UX classifier or an architectural decoupling that stays valuable after the bug is fixed. Real examples that are NOT removable-on-close: the `thought_signature` error classifier (`model-error-classifier.ts`, #338 — renders graceful UX whenever the upstream error surfaces, and its removal is gated on an _empirical_ live-path condition, not the issue state), and the Telegram store-based `allowFrom` (#47458 — a restart-avoiding design choice, see `reference_ollama_local_rewrite_decoupling.md` for the "decoupling, not a version workaround" pattern). 4. **Prefer the tracking issue's own stated verification** (e.g. "remove X, run E2E `agent-create-no-restart.spec.ts`, confirm it stays green") over bundle archaeology. Bundle-reading can prove a workaround is STILL needed (mechanism present) but is weak evidence that one is safe to REMOVE — that needs the prescribed test. Memory: `reference_config_apply_rate_limit_drop.md` warns version guards can _become_ bugs after an upstream fix, so this cuts both ways. If all four hold, remove the workaround in the same change with a test proving native behavior now covers it. Otherwise leave it and record why. **c. Features we built ourselves that OpenClaw now does natively.** Scan for "native", new config keys, or new built-in capabilities in areas where Pinchy has a bespoke plugin or workaround (e.g. transcript capture, session identity, memory, approvals — see `reference_pinchy_owned_transcript.md`, `reference_openclaw_approval_primitives.md`, `reference_mcp_native_credential_proxy.md` for precedent: MCP was migrated from a Pinchy-built plugin to native `mcp.servers` + a thin credential proxy once OpenClaw grew native support). **Same feature name ≠ same scope — check whether the native capability covers the REASON we built the bespoke version, not just its surface.** Real example: 2026.6.10 added a native "session-transcript SDK" (read, append, publish, lock), which sounds like it could replace `pinchy-transcript`. But its methods are all keyed by `{ agentId, sessionKey, sessionId }` — **session-scoped**. Pinchy owns `channel_messages` precisely because it needs a _channel-lifetime_ record that survives `/new`/reset/compaction (per PR #553 / `reference_pinchy_owned_transcript.md`); adopting the session-scoped SDK would reintroduce the exact blank-on-`/new` bug it fixed. So: not adoptable. If a native capability genuinely covers the reason, flag it as a follow-up simplification; if it only matches the name, record why it doesn't fit so the next bump doesn't re-litigate it. **d. New OpenClaw features worth exposing in Pinchy.** Anything new that fits Pinchy's enterprise-governance angle (permissions, audit, channels, models) or that Pinchy's target audience (self-hosted enterprise teams, see "Product Context" in `AGENTS.md`) would plausibly want surfaced in the UI/API. Note these separately as feature ideas — they are out of scope for the bump itself, not blockers. 3. **Summarize findings against the four questions before touching code.** If (a) is empty, treat the bump as safe to proceed. If (a) is non-empty, flag it to the user before proceeding — don't silently absorb a breaking change into a routine bump. (b), (c), and (d) don't block the bump, but report them: (b) as follow-up cleanup candidates (ideally done alongside the bump if small), (c)/(d) as things worth a tracked issue or a `spawn_task`-style follow-up rather than silently doing nothing with them. 4. **Bump both pinned locations** to the same target version: - `packages/web/package.json` → `dependencies.openclaw` - `Dockerfile.openclaw` → the `npm install -g openclaw@...` line 5. **Check `openclaw-node`** (`packages/web/package.json` → `dependencies["openclaw-node"]`, our own client library in `~/projects/openclaw-node/`) for a matching newer release too — `npm view openclaw-node version`. If it needs a release and we own it: openclaw-node has NO `pnpm release` script (that's Pinchy's mechanism). Its actual release flow (v0.13.0/v0.13.1 precedent): add a CHANGELOG entry, bump `package.json`, commit `chore: release vX.Y.Z` on main, wait for CI on that commit, then `gh release create vX.Y.Z` — the GitHub release triggers `publish.yml`, which re-verifies CI and publishes to npm. Verify with `npm view openclaw-node version` before bumping the Pinchy pin. 6. **Install and verify:** ```bash pnpm install pnpm -C packages/web vitest run src/__tests__/lib/openclaw-version-pin-drift.test.ts node --test config/__tests__/bootstrap-memory-group-filter.test.mjs # #369 hook contract pnpm test pnpm build ``` Note: the hook test above proves the filter logic, not that OpenClaw still fires the hook. If the notes touched bootstrap/hook/session-key behavior, run the HOOK.md staging check before shipping. 7. **Don't commit automatically.** Report the diff (`git status --short`, `git diff --stat`) and let the user decide to commit/PR — this touches a runtime dependency, not just app code. ## If a release note flags something sensitive Don't just bump anyway. Options, in order of preference: - Pin to the last version before the risky change and note why in a commit message / to the user. - Do the bump on a branch, add/adjust a regression test for the specific behavior the release note describes, then bump. - Ask the user whether to proceed if the tradeoff isn't yours to make alone.