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@<version>
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
Check current vs. latest.
grep openclaw packages/web/package.json
npm view openclaw version
npm view openclaw versions --json | tail -20 # see every point release in between
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:
gh release list --repo openclaw/openclaw --limit 20
gh release view v<version> --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.warns 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:
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:
- 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@<target>/node_modules/openclaw/dist for
the fixed code, not just the changelog.
- 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.
- 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).
- 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.
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.
Bump both pinned locations to the same target version:
packages/web/package.json → dependencies.openclaw
Dockerfile.openclaw → the npm install -g openclaw@... line
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.
Install and verify:
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.
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.
1---2name: update-openclaw3description: 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.4---56# Update the pinned OpenClaw version78## Overview910Pinchy pins the OpenClaw core runtime version in two places that a drift11guard keeps in lockstep:1213- `packages/web/package.json` → `dependencies.openclaw`14- `Dockerfile.openclaw` → `RUN npm install -g openclaw@<version>`1516`packages/web/src/__tests__/lib/openclaw-version-pin-drift.test.ts` greps17`Dockerfile.openclaw` for the literal `npm install -g openclaw@` line and18fails if it doesn't match `package.json`. Both places also feed19`/api/version`.2021**Core principle: OpenClaw upgrades have repeatedly broken Pinchy in ways22`pnpm test`/`tsc` don't catch**, because the breakage is in runtime protocol23behavior (session keys, `tools.allow` semantics, `config.apply` timing,24plugin manifest resolution) — see the `reference_oc_*` / `reference_openclaw_*`25memory entries about past compatibility cliffs. Never treat "npm view shows a26newer version" as a green light by itself. Read the release notes for every27version between current and target first.2829## Procedure30311. **Check current vs. latest.**3233 ```bash34 grep openclaw packages/web/package.json35 npm view openclaw version36 npm view openclaw versions --json | tail -20 # see every point release in between37 ```38392. **Read every release's notes between current (exclusive) and target40 (inclusive)** — not just the target's diff summary, since intermediate41 point releases can carry changes too:4243 ```bash44 gh release list --repo openclaw/openclaw --limit 2045 gh release view v<version> --repo openclaw/openclaw46 ```4748 Read the full text, not just headline "Highlights" — the "Additional ...49 fixes" subsections often contain the entry that actually matters to us.50 Work through it against these four questions, in this order, and write51 down what you find for each before moving to step 3:5253 **a. Incompatibility risk.** Anything touching session keys, `tools.allow`54 semantics, `config.apply` timing, plugin config/manifest resolution, or55 provider `baseUrl` handling — the areas that have bitten us before (see56 `reference_oc_*` / `reference_openclaw_*` memory entries). Look at57 sections titled "Sessions", "Gateway, Security, and Trust", "Plugins and58 Packaging", and any breaking/migration language anywhere else. **Watch59 especially for new gateway-startup / config self-healing behavior** — these60 don't show up in `pnpm test`/`tsc` at all and only fail in the docker E2Es.61 **The `agent:bootstrap` hook contract is one of these silent dependencies.**62 `config/pinchy-hooks/bootstrap-memory-group-filter/` (the #369 leak fix)63 assumes the event carries `context.bootstrapFiles` (array) and64 `context.sessionKey` (string), that reassigning `context.bootstrapFiles` is65 read back by the caller, and that internal hooks load via native `import()`.66 If the notes touch bootstrap/hook events, session-key shape, or the internal67 hook loader, verify against the installed dist that these still hold — the68 hook now `console.warn`s instead of failing open, so also check the gateway69 logs on the staging deploy for that warning. A silent contract change here70 re-opens a P0 `eu-ai-act` memory leak. See the hook's `HOOK.md` Verification71 section for the exact staging check.72 Real example the 2026.6.11 bump tripped: OpenClaw 2026.6.x added startup73 config auto-restore — on a size-drop / missing-meta vs last-known-good it74 restores `openclaw.json.last-good` over `openclaw.json` at gateway start75 (`recoverConfigFromLastKnownGood`). This broke the setup-wizard reset (it76 deleted `openclaw.json` but not the backups, so OC restored the prior test's77 config referencing wiped secrets → crash-loop). If notes mention config78 backup / last-known-good / recovery / restore, expect the setup-wizard +79 integration E2Es to need reset-choreography updates.8081 **b. Resolved issues we have workarounds for.** Grep our own code for82 the upstream issue/PR numbers and version-guard comments before reading83 notes:8485 ```bash86 git grep -rniE "openclaw/openclaw#[0-9]+|openclaw issue|version.?guard|workaround|TODO\(#" -- packages/ config/ | grep -vi node_modules87 ```8889 For each hit, check the upstream issue state (`gh issue view <n> --repo90openclaw/openclaw --json state,closedAt`). But **"issue closed" is91 necessary, not sufficient** — a closed issue is where naive audits go92 wrong. Before removing any workaround, confirm ALL of:9394 1. **The fix shipped in a release ≤ our target pin.** Close date ≠ release95 date, and release notes often don't name the issue. When in doubt,96 inspect the actually-installed bundle in97 `node_modules/.pnpm/openclaw@<target>/node_modules/openclaw/dist` for98 the fixed code, not just the changelog.99 2. **The fix targets OUR code path**, not a sibling. Real example: openclaw100 #75534 (config.apply no-op restart, tracked on our side by #215) fixed101 OpenClaw's _own_ `writeConfigFile` short-circuit — but Pinchy writes the102 config file itself and then calls `config.apply`, a different path whose103 `env.*`→default-`restart` mechanism was still present verbatim in104 2026.6.11. Issue closed, workaround NOT removable.105 3. **The workaround is actually a bug-workaround**, not a defensive106 error-UX classifier or an architectural decoupling that stays valuable107 after the bug is fixed. Real examples that are NOT removable-on-close:108 the `thought_signature` error classifier (`model-error-classifier.ts`,109 #338 — renders graceful UX whenever the upstream error surfaces, and its110 removal is gated on an _empirical_ live-path condition, not the issue111 state), and the Telegram store-based `allowFrom` (#47458 — a112 restart-avoiding design choice, see113 `reference_ollama_local_rewrite_decoupling.md` for the "decoupling, not a114 version workaround" pattern).115 4. **Prefer the tracking issue's own stated verification** (e.g. "remove X,116 run E2E `agent-create-no-restart.spec.ts`, confirm it stays green") over117 bundle archaeology. Bundle-reading can prove a workaround is STILL needed118 (mechanism present) but is weak evidence that one is safe to REMOVE —119 that needs the prescribed test. Memory: `reference_config_apply_rate_limit_drop.md`120 warns version guards can _become_ bugs after an upstream fix, so this121 cuts both ways.122123 If all four hold, remove the workaround in the same change with a test124 proving native behavior now covers it. Otherwise leave it and record why.125126 **c. Features we built ourselves that OpenClaw now does natively.** Scan127 for "native", new config keys, or new built-in capabilities in areas where128 Pinchy has a bespoke plugin or workaround (e.g. transcript capture,129 session identity, memory, approvals — see `reference_pinchy_owned_transcript.md`,130 `reference_openclaw_approval_primitives.md`, `reference_mcp_native_credential_proxy.md`131 for precedent: MCP was migrated from a Pinchy-built plugin to native132 `mcp.servers` + a thin credential proxy once OpenClaw grew native support).133 **Same feature name ≠ same scope — check whether the native capability134 covers the REASON we built the bespoke version, not just its surface.**135 Real example: 2026.6.10 added a native "session-transcript SDK" (read,136 append, publish, lock), which sounds like it could replace `pinchy-transcript`.137 But its methods are all keyed by `{ agentId, sessionKey, sessionId }` —138 **session-scoped**. Pinchy owns `channel_messages` precisely because it139 needs a _channel-lifetime_ record that survives `/new`/reset/compaction140 (per PR #553 / `reference_pinchy_owned_transcript.md`); adopting the141 session-scoped SDK would reintroduce the exact blank-on-`/new` bug it fixed.142 So: not adoptable. If a native capability genuinely covers the reason,143 flag it as a follow-up simplification; if it only matches the name, record144 why it doesn't fit so the next bump doesn't re-litigate it.145146 **d. New OpenClaw features worth exposing in Pinchy.** Anything new that147 fits Pinchy's enterprise-governance angle (permissions, audit, channels,148 models) or that Pinchy's target audience (self-hosted enterprise teams,149 see "Product Context" in `AGENTS.md`) would plausibly want surfaced in the150 UI/API. Note these separately as feature ideas — they are out of scope151 for the bump itself, not blockers.1521533. **Summarize findings against the four questions before touching code.**154 If (a) is empty, treat the bump as safe to proceed. If (a) is non-empty,155 flag it to the user before proceeding — don't silently absorb a breaking156 change into a routine bump. (b), (c), and (d) don't block the bump, but157 report them: (b) as follow-up cleanup candidates (ideally done alongside158 the bump if small), (c)/(d) as things worth a tracked issue or a159 `spawn_task`-style follow-up rather than silently doing nothing with them.1601614. **Bump both pinned locations** to the same target version:162 - `packages/web/package.json` → `dependencies.openclaw`163 - `Dockerfile.openclaw` → the `npm install -g openclaw@...` line1641655. **Check `openclaw-node`** (`packages/web/package.json` →166 `dependencies["openclaw-node"]`, our own client library in167 `~/projects/openclaw-node/`) for a matching newer release too —168 `npm view openclaw-node version`. If it needs a release and we own it:169 openclaw-node has NO `pnpm release` script (that's Pinchy's mechanism).170 Its actual release flow (v0.13.0/v0.13.1 precedent): add a CHANGELOG171 entry, bump `package.json`, commit `chore: release vX.Y.Z` on main, wait172 for CI on that commit, then `gh release create vX.Y.Z` — the GitHub173 release triggers `publish.yml`, which re-verifies CI and publishes to174 npm. Verify with `npm view openclaw-node version` before bumping the175 Pinchy pin.1761776. **Install and verify:**178179 ```bash180 pnpm install181 pnpm -C packages/web vitest run src/__tests__/lib/openclaw-version-pin-drift.test.ts182 node --test config/__tests__/bootstrap-memory-group-filter.test.mjs # #369 hook contract183 pnpm test184 pnpm build185 ```186187 Note: the hook test above proves the filter logic, not that OpenClaw still188 fires the hook. If the notes touched bootstrap/hook/session-key behavior,189 run the HOOK.md staging check before shipping.1901917. **Don't commit automatically.** Report the diff (`git status --short`,192 `git diff --stat`) and let the user decide to commit/PR — this touches a193 runtime dependency, not just app code.194195## If a release note flags something sensitive196197Don't just bump anyway. Options, in order of preference:198199- Pin to the last version before the risky change and note why in a commit200 message / to the user.201- Do the bump on a branch, add/adjust a regression test for the specific202 behavior the release note describes, then bump.203- Ask the user whether to proceed if the tradeoff isn't yours to make alone.