From b0c6fbbb556c46110026e2fab715835a51997927 Mon Sep 17 00:00:00 2001 From: Mark Goldenstein Date: Mon, 3 Aug 2026 18:51:15 -0700 Subject: [PATCH 1/3] Prepare OpenClaw 2026.7.1-2 compatibility release --- CHANGELOG.md | 6 + README.md | 2 +- docs/REFERENCE.md | 8 +- openclaw.plugin.json | 2 +- package.json | 8 +- pnpm-lock.yaml | 151 +++++++++++++------------- scripts/validate-release-metadata.mjs | 19 +++- tests/plugin-entry.test.ts | 29 ++--- 8 files changed, 124 insertions(+), 101 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index eff1e9a..5c9d622 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [4.7.7] - 2026-08-03 + +### Changed +- Validated and retargeted package and plugin SDK build metadata to OpenClaw `2026.7.1-2` while retaining the compatible OpenClaw `2026.7.1` install, plugin API, Gateway, and peer dependency floor. +- Confirmed that the OpenClaw correction release's singleton-array npm metadata fix requires no changes to Code Agent tools, callbacks, wake routing, worktree flows, plan approval, or harness model restrictions. + ## [4.7.6] - 2026-07-15 ### Changed diff --git a/README.md b/README.md index 63215c9..4e0c956 100644 --- a/README.md +++ b/README.md @@ -128,7 +128,7 @@ Because worktree isolation defaults to `delegate`, `defaultWorkdir` should norma Chat-launched sessions route updates back to their originating chat thread. For agent-launched tool sessions without an origin route, configure `fallbackChannel` or `agentChannels` in the reference guide. -The current package targets, validates against, and requires OpenClaw `2026.7.1`. Its install, plugin API, Gateway, and peer dependency metadata all use that same minimum so OpenClaw and ClawHub reject older hosts before installation. OpenClaw `2026.7.1` changes Codex app-server, Telegram delivery, cron/session delivery, tool visibility, approval, and plugin update behavior, but `openclaw-code-agent` does not need new SDK imports for those changes: the manifest already declares `contracts.tools`, the plugin still imports only `openclaw/plugin-sdk/plugin-entry`, and its own session store, wake routing, callbacks, worktree flows, and harness model restrictions remain plugin-owned. Current callback behavior around native callback data, routed follow-ups, retryable stale plan approval buttons, and serialized plan decisions remains plugin-owned. +The current package targets and validates against OpenClaw `2026.7.1-2` while retaining OpenClaw `2026.7.1` as its install, plugin API, Gateway, and peer dependency minimum. The correction release only fixes singleton-array npm metadata handling for plugin installs and updates, so no host config migration or Code Agent runtime change is required. The manifest still declares `contracts.tools`, the plugin still imports only `openclaw/plugin-sdk/plugin-entry`, and its own session store, wake routing, callbacks, worktree flows, and Codex/Claude model restrictions remain plugin-owned. Current callback behavior around native callback data, routed follow-ups, retryable stale plan approval buttons, and serialized plan decisions remains unchanged. If you use Codex, make sure the local `codex` command or `OPENCLAW_CODEX_APP_SERVER_COMMAND` override is available and authenticated. Codex-specific defaults live under `harnesses.codex`: `reasoningEffort` is sent as `reasoningEffort`, and `fastMode: true` sends `service_tier: "fast"` on Codex App Server thread, resume, and turn payloads. The Codex harness starts the app server with stdio listener args by default, only sends UUID-shaped backend thread IDs to `thread/resume`, and reports startup timeouts with redacted recent stderr. When Codex auth is inconsistent, this is the recommended `~/.codex/config.toml` setting: diff --git a/docs/REFERENCE.md b/docs/REFERENCE.md index 665304d..4469253 100644 --- a/docs/REFERENCE.md +++ b/docs/REFERENCE.md @@ -28,13 +28,13 @@ Sessions are multi-turn. Active sessions accept follow-up messages via `agent_re Current releases treat persisted session storage as new-schema-only. If startup finds an older or invalid session store, the plugin archives it to a timestamped `.legacy-*.json` backup and starts with a fresh index instead of migrating rows in place. -### OpenClaw 2026.7.1 SDK Readiness +### OpenClaw 2026.7.1-2 SDK Readiness -The current `openclaw-code-agent` package is validated against and requires OpenClaw `2026.7.1`. Package install, plugin API, Gateway, peer dependency, and build metadata now share that minimum so registry and host compatibility checks cannot select the package for an older OpenClaw installation. +The current `openclaw-code-agent` package is validated against OpenClaw `2026.7.1-2` and retains OpenClaw `2026.7.1` as its minimum compatible host. Exact build metadata and the development dependency record the tested correction release, while package install, plugin API, Gateway, and peer dependency metadata continue to reject hosts older than `2026.7.1` without unnecessarily excluding the compatible base release. -Hosts already running OpenClaw `2026.7.1` need no host config change. No new OpenClaw SDK imports were needed for `2026.7.1`: this plugin still depends only on the stable plugin-entry surface. Runtime code still imports only `openclaw/plugin-sdk/plugin-entry` from the OpenClaw SDK, `openclaw.plugin.json` already declares tools through `contracts.tools`, package-level OpenClaw readiness stays in `package.json`, pnpm build policy and overrides live in `pnpm-workspace.yaml`, and code-agent session storage remains plugin-owned. Current callback handling, plan approval, session wake/routing, Codex harness behavior, and worktree follow-through remain plugin-owned compatibility surfaces. +Hosts already running OpenClaw `2026.7.1` need no host config change. OpenClaw `2026.7.1-2` only normalizes singleton-array output from newer `npm view --json` clients and continues to reject ambiguous multi-version arrays. No new SDK imports or Code Agent runtime changes are needed: runtime code still imports only `openclaw/plugin-sdk/plugin-entry`, `openclaw.plugin.json` already declares tools through `contracts.tools`, pnpm build policy and overrides remain in `pnpm-workspace.yaml`, and code-agent session storage remains plugin-owned. Current Start Plan and approval callbacks, Telegram/topic routing, completion and cron/session wakes, Codex and Claude model restrictions, runtime tool visibility, disabled bundled-plugin boundaries, and plan/worktree follow-through remain unchanged. -Configuration guidance for `2026.7.1`: +Configuration guidance for the `2026.7.1` compatibility floor and tested `2026.7.1-2` correction release: - If `plugins.allow` is present, add `openclaw-code-agent`. OpenClaw treats that allowlist as exclusive, so `tools.allow` cannot make this plugin's tools available when the owning plugin is blocked. - New OpenClaw configs default `plugins.bundledDiscovery` to `allowlist`, so a restrictive `plugins.allow` list can also block omitted bundled provider or runtime plugins. OpenClaw `2026.7.1` continues to discover externally installed channel plugins at Gateway startup, but that host-side discovery does not make those plugins implicitly available to OCA sessions. Disabled or omitted adjacent plugins remain unavailable unless explicitly enabled or auto-enabled by their own OpenClaw contracts. diff --git a/openclaw.plugin.json b/openclaw.plugin.json index c84b40b..f2daa43 100644 --- a/openclaw.plugin.json +++ b/openclaw.plugin.json @@ -2,7 +2,7 @@ "id": "openclaw-code-agent", "name": "Code Agent", "description": "Multi-session coding-agent orchestration from OpenClaw chat", - "version": "4.7.6", + "version": "4.7.7", "contracts": { "tools": [ "agent_launch", diff --git a/package.json b/package.json index 277605c..5f6a4c1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "openclaw-code-agent", - "version": "4.7.6", + "version": "4.7.7", "type": "module", "packageManager": "pnpm@11.15.1", "main": "dist/index.js", @@ -40,8 +40,8 @@ "minGatewayVersion": "2026.7.1" }, "build": { - "openclawVersion": "2026.7.1", - "pluginSdkVersion": "2026.7.1" + "openclawVersion": "2026.7.1-2", + "pluginSdkVersion": "2026.7.1-2" } }, "files": [ @@ -58,7 +58,7 @@ "@types/node": "^26.0.1", "esbuild": "^0.28.1", "nanoid": "^6.0.0", - "openclaw": "2026.7.1", + "openclaw": "2026.7.1-2", "tsx": "^4.21.0", "typescript": "^7.0.2" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e614b1a..afbac21 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -40,11 +40,11 @@ importers: specifier: ^6.0.0 version: 6.0.0 openclaw: - specifier: 2026.7.1 - version: 2026.7.1 + specifier: 2026.7.1-2 + version: 2026.7.1-2 tsx: specifier: ^4.21.0 - version: 4.23.1 + version: 4.23.5 typescript: specifier: ^7.0.2 version: 7.0.2 @@ -385,8 +385,8 @@ packages: resolution: {integrity: sha512-juG5VWh4qAivzTAeMzvY9xs9HY5rAcr2E4I7tiSSCokRFi7XIZCAu92ZkSTsIj1OPceCifL3cpfteP3pDT9/QQ==} engines: {node: '>=14.0.0'} - '@openclaw/ai@2026.7.1': - resolution: {integrity: sha512-FsKy5DXSHf4qyN8Huoz/10HZRgoEwLF4uk8UWaCafaIler+q5Fsl51HcrIqIrEe0S38OT7LOaxnR++MOshAlmw==} + '@openclaw/ai@2026.7.1-2': + resolution: {integrity: sha512-st+NH0cxlQqdbEur//yYqM7WlYBjeEBnop3cztJTSCONKjv6LNoGguI9cH65asZG94FdM/39z857isRGPnZvEw==} engines: {node: '>=22.19.0'} '@openclaw/fs-safe@0.4.1': @@ -430,8 +430,8 @@ packages: '@protobufjs/pool@1.1.0': resolution: {integrity: sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==} - '@protobufjs/utf8@1.1.1': - resolution: {integrity: sha512-oOAWABowe8EAbMyWKM0tYDKi8Yaox52D+HWZhAIJqQXbqe0xI/GV7FhLWqlEKreMkfDjshR5FKgi3mnle0h6Eg==} + '@protobufjs/utf8@1.1.2': + resolution: {integrity: sha512-b1UQwcEZ4yCnMCD8DAL1VlbvBJE9/IX4FTIp7BG1xYpf29SLazLSrqUkj4w7Y5y7cCVP6E5tcqqcI0xemPkHug==} '@silvia-odwyer/photon-node@0.3.4': resolution: {integrity: sha512-bnly4BKB3KDTFxrUIcgCLbaeVVS8lrAkri1pEzskpmxu9MdfGQTy8b8EgcD83ywD3RPMsIulY8xJH5Awa+t9fA==} @@ -616,8 +616,8 @@ packages: bignumber.js@9.3.1: resolution: {integrity: sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==} - bn.js@4.12.3: - resolution: {integrity: sha512-fGTi3gxV/23FTYdAoUtLYp6qySe2KE3teyZitipKNRuVYcBkoP/bB3guXN/XVKUe9mxCHXnc9C4ocyz8OmgN0g==} + bn.js@4.12.5: + resolution: {integrity: sha512-3aRg6/JxfffFD+OlOjOFR3Vo79l39ooBTFucxx+MT3dhCtzn3EmiUPQo+6/OZuI2jbXi3YKgmiTFBgChQMwIRQ==} body-parser@2.3.0: resolution: {integrity: sha512-2cGmJupaNgg+QUwVLAucDuWuoMZ6EX9iHDRswZ5lsNYEmwPaRknMPCLZz07yTzVq/83p4o/wzbDZbBrTvGGTIw==} @@ -629,9 +629,9 @@ packages: bottleneck@2.19.5: resolution: {integrity: sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw==} - brace-expansion@5.0.7: - resolution: {integrity: sha512-7oFy703dxfY3/NLxC1fh2SUCQ0H9rmAY+5EpDVfXjUTTs+HEwR2nYaqLv+GWcTsumwxPfiz6CzCNkwXwBUwqCA==} - engines: {node: 18 || 20 || >=22} + brace-expansion@5.0.9: + resolution: {integrity: sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==} + engines: {node: 20 || >=22} buffer-equal-constant-time@1.0.1: resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==} @@ -845,8 +845,8 @@ packages: resolution: {integrity: sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==} engines: {node: '>=18.0.0'} - express-rate-limit@8.5.2: - resolution: {integrity: sha512-5Kb34ipNX694DH48vN9irak1Qx30nb0PLYHXfJgw4YEjiC3ZEmZJhwOp+VfiCYwFzvFTdB9QkArYS5kXa2cx2A==} + express-rate-limit@8.6.1: + resolution: {integrity: sha512-0D493aP61w0TJ2A0wy27riRsO7FMQ7FK+KUHOKCSfPvYo0R55aiC6emCVgFUeShH0fq0ICPVzNcgoS+BsbXQCA==} engines: {node: '>= 16'} peerDependencies: express: '>= 4.11' @@ -912,8 +912,8 @@ packages: function-bind@1.1.2: resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - gaxios@7.1.5: - resolution: {integrity: sha512-5FZy72Rh8LhtjmvDrKkI+lVhrsQrVKVsItxMoDm5mNQE+xR0WVIIs+jzPSJgBvKVsLi24fZhXJIsNI0bihDzFg==} + gaxios@7.3.0: + resolution: {integrity: sha512-RB5vLV+vvQeoFPCX4QMK6/hjVkbIamPp1QSUD0CiZcnj12qbpiL+pLbYtgD+oZkWl0tl9z+o2Utp+MpM3QRhBA==} engines: {node: '>=18'} gcp-metadata@8.1.2: @@ -940,8 +940,8 @@ packages: resolution: {integrity: sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==} engines: {node: 18 || 20 || >=22} - google-auth-library@10.7.0: - resolution: {integrity: sha512-QpTAbNJ36TliZLx3TTtahR8HG0hN9RllL1e3FymOvQSIKK8JmgV58H924ub2wa2DsS3ANjjP1Aw1N+Ramc8hqQ==} + google-auth-library@10.9.1: + resolution: {integrity: sha512-i1ydyHrqcIxXkWh/uBmVkzCvIuq5yiK2ATndIe5XxKholrG/MTYP9xGYka4sQhrbIAgGjL2B6NOE7rFaiF3fXw==} engines: {node: '>=18'} google-logging-utils@1.1.3: @@ -997,8 +997,8 @@ packages: resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} engines: {node: '>= 14'} - iconv-lite@0.7.2: - resolution: {integrity: sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==} + iconv-lite@0.7.3: + resolution: {integrity: sha512-IKXpvIzjnC9XTAUbVBcMfGS0EPaIXtW6v+zr+RRp+hqULEpo0owZax6wyRwPOJbWbzjYspQwusTsfVr0ifh4uQ==} engines: {node: '>=0.10.0'} ieee754@1.2.1: @@ -1014,8 +1014,8 @@ packages: inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - ip-address@10.2.0: - resolution: {integrity: sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==} + ip-address@10.4.0: + resolution: {integrity: sha512-oSK96Grm3aP6OrS263xVxbNDGVL7rzBtYdpGqlDG8iQdoenDoTs/nkki+DflYbAEE8Xl6o5YxhxlrKvI3nqKXQ==} engines: {node: '>= 12'} ipaddr.js@1.9.1: @@ -1039,8 +1039,8 @@ packages: resolution: {integrity: sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==} hasBin: true - jose@6.2.3: - resolution: {integrity: sha512-YYVDInQKFJfR/xa3ojUTl8c2KoTwiL1R5Wg9YCydwH0x0B9grbzlg5HC7mMjCtUJjbQ/YnGEZIhI5tCgfTb4Hw==} + jose@6.2.7: + resolution: {integrity: sha512-hq1OB1bALKfydZNoViyg6hPVGV4i93ny9Op+n4zP5RSf7SCZEXa/TsG2O3IEr7+WlHRTPnpqDmHfMH6qXAD60w==} json-bigint@1.0.0: resolution: {integrity: sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==} @@ -1092,8 +1092,8 @@ packages: long@5.3.2: resolution: {integrity: sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==} - lru-cache@11.5.1: - resolution: {integrity: sha512-RPimw/7aMdv2oqRrxKwvZXcPfwBrn/JZ2xYcY9Hus/6LaS3VOAKVWKWgNLCFSiOm1ESXinjsDlidVU7JlnCN2A==} + lru-cache@11.5.2: + resolution: {integrity: sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==} engines: {node: 20 || >=22} marked@18.0.5: @@ -1105,8 +1105,8 @@ packages: resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} engines: {node: '>= 0.4'} - media-typer@1.1.0: - resolution: {integrity: sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==} + media-typer@1.1.1: + resolution: {integrity: sha512-yz3xRaG20c6/BOzvYoDaGtPmGscs7YivItZEEqe6GbwNfHuxu9YNmvnEkMzKldAGY4/80pRcQRZSEnhquk9XuQ==} engines: {node: '>= 0.8'} merge-descriptors@2.0.0: @@ -1151,8 +1151,8 @@ packages: resolution: {integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==} engines: {node: '>= 0.6'} - node-addon-api@8.8.0: - resolution: {integrity: sha512-c5Ko1fZJIJmzhFIkhRN76WTq+fC6tWnGy9CXA0fA+XygsWZmEwG8vmbkNqxMyoaa0Tin4djul49NzdVcJJcjeA==} + node-addon-api@8.9.1: + resolution: {integrity: sha512-4eUQWVPCUUUiBjLnHS3cXWeC6ryoPUc0U3rP7IuzapoGbzMqd/r6KKO0clr0b+snQhsrueFEhCZDdK+LK7hxKg==} engines: {node: ^18 || ^20 || >= 21} node-domexception@1.0.0: @@ -1219,8 +1219,8 @@ packages: zod: optional: true - openclaw@2026.7.1: - resolution: {integrity: sha512-ge/Xss99CHAjPL/ikmH/UFoiOrjcxDB4sW3y9mhyCD+dYW3wzV7TKbAVdkrXFgAG2d2BjpJofP97zUZ+umxo8g==} + openclaw@2026.7.1-2: + resolution: {integrity: sha512-ycF3yPcbjN6bUPeaUx6Mh6vze1hQWoD3CT/wWcmD7a8xaHHHRUaAlaq+lFxMHf1ssEgODVAwjlzYqp2twkYZ7g==} engines: {node: '>=22.22.3 <23 || >=24.15.0 <25 || >=25.9.0'} hasBin: true @@ -1304,8 +1304,8 @@ packages: quickjs-wasi@3.0.2: resolution: {integrity: sha512-SyfPzlrfz67/kv0SogmQgW4c2I1klkLcbvj9Y2gc1h7+VylmvuGevFljLXibGKajKJKiJV29d4S6FQLA6Sc80A==} - range-parser@1.2.1: - resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} + range-parser@1.3.0: + resolution: {integrity: sha512-hek2mFQpPuI4E1BBKrSto+BU3e3x4xuarsbiwr3+lf7p44juvFMV0XFWQAP3xUyqXA4RrXLIoaSUGbSt056ZMw==} engines: {node: '>= 0.6'} rastermill@0.3.1: @@ -1492,8 +1492,8 @@ packages: resolution: {integrity: sha512-XuELoRpMR+sq8fuWwX7P0bcj+PRNiicOKDEb3fGNURhxWVyykCi9BNq7c4uVz7h7P0sj8qgBsr5SWS6yBClq3g==} engines: {node: '>=16'} - tsx@4.23.1: - resolution: {integrity: sha512-GQHnkIfxyx1wYCOS/wonik5MVRZU9hi1TEZmzGZSCJB1y9YgoZ8H6itNE/u4suE+yLmOzuE4E5S4TZ/ZX2wcWQ==} + tsx@4.23.5: + resolution: {integrity: sha512-rw55FUaqOoI7RvlQwLbhO4nSDApnQ4/CykPuiQ/EPvtrX3WA9Ig55jIt9VvbBJbzJuj12ueRu4PMZ2SxPVbihg==} engines: {node: '>=18.0.0'} hasBin: true @@ -1616,8 +1616,8 @@ packages: resolution: {integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==} engines: {node: '>=8'} - yargs@17.7.2: - resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + yargs@17.7.3: + resolution: {integrity: sha512-GZtjxm/J/4TSxuL3FNYjCmLktBTnIw/rVmKSIyKeYAZpmJB2ig9VauCC5xsa82GNKVKDAqpOn3KVzNt0zmrU0g==} engines: {node: '>=12'} zod-to-json-schema@3.25.2: @@ -1781,7 +1781,7 @@ snapshots: '@google/genai@2.10.0(@modelcontextprotocol/sdk@1.29.0(zod@4.4.3))': dependencies: - google-auth-library: 10.7.0 + google-auth-library: 10.9.1 p-retry: 4.6.2 protobufjs: 7.6.3 ws: 8.21.0 @@ -1869,9 +1869,9 @@ snapshots: eventsource: 3.0.7 eventsource-parser: 3.1.0 express: 5.2.1 - express-rate-limit: 8.5.2(express@5.2.1) + express-rate-limit: 8.6.1(express@5.2.1) hono: 4.12.27 - jose: 6.2.3 + jose: 6.2.7 json-schema-typed: 8.0.2 pkce-challenge: 5.0.1 raw-body: 3.0.2 @@ -1882,7 +1882,7 @@ snapshots: '@mozilla/readability@0.6.0': {} - '@openclaw/ai@2026.7.1(@modelcontextprotocol/sdk@1.29.0(zod@4.4.3))(ws@8.21.0)(zod@4.4.3)': + '@openclaw/ai@2026.7.1-2(@modelcontextprotocol/sdk@1.29.0(zod@4.4.3))(ws@8.21.0)(zod@4.4.3)': dependencies: '@anthropic-ai/sdk': 0.109.1(zod@4.4.3) '@google/genai': 2.10.0(@modelcontextprotocol/sdk@1.29.0(zod@4.4.3)) @@ -1933,7 +1933,7 @@ snapshots: '@protobufjs/pool@1.1.0': {} - '@protobufjs/utf8@1.1.1': {} + '@protobufjs/utf8@1.1.2': {} '@silvia-odwyer/photon-node@0.3.4': {} @@ -2044,7 +2044,7 @@ snapshots: asn1.js@5.4.1: dependencies: - bn.js: 4.12.3 + bn.js: 4.12.5 inherits: 2.0.4 minimalistic-assert: 1.0.1 safer-buffer: 2.1.2 @@ -2055,7 +2055,7 @@ snapshots: bignumber.js@9.3.1: {} - bn.js@4.12.3: {} + bn.js@4.12.5: {} body-parser@2.3.0: dependencies: @@ -2063,7 +2063,7 @@ snapshots: content-type: 2.0.0 debug: 4.4.3 http-errors: 2.0.1 - iconv-lite: 0.7.2 + iconv-lite: 0.7.3 on-finished: 2.4.1 qs: 6.15.2 raw-body: 3.0.2 @@ -2075,7 +2075,7 @@ snapshots: bottleneck@2.19.5: {} - brace-expansion@5.0.7: + brace-expansion@5.0.9: dependencies: balanced-match: 4.0.4 @@ -2269,10 +2269,13 @@ snapshots: dependencies: eventsource-parser: 3.1.0 - express-rate-limit@8.5.2(express@5.2.1): + express-rate-limit@8.6.1(express@5.2.1): dependencies: + debug: 4.4.3 express: 5.2.1 - ip-address: 10.2.0 + ip-address: 10.4.0 + transitivePeerDependencies: + - supports-color express@5.2.1: dependencies: @@ -2297,7 +2300,7 @@ snapshots: parseurl: 1.3.3 proxy-addr: 2.0.7 qs: 6.15.2 - range-parser: 1.2.1 + range-parser: 1.3.0 router: 2.2.0 send: 1.2.1 serve-static: 2.2.1 @@ -2368,7 +2371,7 @@ snapshots: function-bind@1.1.2: {} - gaxios@7.1.5: + gaxios@7.3.0: dependencies: extend: 3.0.2 https-proxy-agent: 7.0.6 @@ -2378,7 +2381,7 @@ snapshots: gcp-metadata@8.1.2: dependencies: - gaxios: 7.1.5 + gaxios: 7.3.0 google-logging-utils: 1.1.3 json-bigint: 1.0.0 transitivePeerDependencies: @@ -2412,11 +2415,11 @@ snapshots: minipass: 7.1.3 path-scurry: 2.0.2 - google-auth-library@10.7.0: + google-auth-library@10.9.1: dependencies: base64-js: 1.5.1 ecdsa-sig-formatter: 1.0.11 - gaxios: 7.1.5 + gaxios: 7.3.0 gcp-metadata: 8.1.2 google-logging-utils: 1.1.3 jws: 4.0.1 @@ -2451,7 +2454,7 @@ snapshots: hosted-git-info@10.1.1: dependencies: - lru-cache: 11.5.1 + lru-cache: 11.5.2 html-escaper@3.0.3: {} @@ -2479,7 +2482,7 @@ snapshots: transitivePeerDependencies: - supports-color - iconv-lite@0.7.2: + iconv-lite@0.7.3: dependencies: safer-buffer: 2.1.2 @@ -2491,7 +2494,7 @@ snapshots: inherits@2.0.4: {} - ip-address@10.2.0: {} + ip-address@10.4.0: {} ipaddr.js@1.9.1: {} @@ -2505,7 +2508,7 @@ snapshots: jiti@2.7.0: {} - jose@6.2.3: {} + jose@6.2.7: {} json-bigint@1.0.0: dependencies: @@ -2560,13 +2563,13 @@ snapshots: long@5.3.2: {} - lru-cache@11.5.1: {} + lru-cache@11.5.2: {} marked@18.0.5: {} math-intrinsics@1.1.0: {} - media-typer@1.1.0: {} + media-typer@1.1.1: {} merge-descriptors@2.0.0: {} @@ -2580,7 +2583,7 @@ snapshots: minimatch@10.2.5: dependencies: - brace-expansion: 5.0.7 + brace-expansion: 5.0.9 minimist@1.2.8: {} @@ -2596,7 +2599,7 @@ snapshots: negotiator@1.0.0: {} - node-addon-api@8.8.0: {} + node-addon-api@8.9.1: {} node-domexception@1.0.0: {} @@ -2604,7 +2607,7 @@ snapshots: dependencies: https-proxy-agent: 7.0.6 ws: 8.21.0 - yargs: 17.7.2 + yargs: 17.7.3 transitivePeerDependencies: - bufferutil - supports-color @@ -2643,7 +2646,7 @@ snapshots: ws: 8.21.0 zod: 4.4.3 - openclaw@2026.7.1: + openclaw@2026.7.1-2: dependencies: '@agentclientprotocol/sdk': 1.1.0(zod@4.4.3) '@anthropic-ai/sdk': 0.109.1(zod@4.4.3) @@ -2658,7 +2661,7 @@ snapshots: '@mistralai/mistralai': 2.4.0 '@modelcontextprotocol/sdk': 1.29.0(zod@4.4.3) '@mozilla/readability': 0.6.0 - '@openclaw/ai': 2026.7.1(@modelcontextprotocol/sdk@1.29.0(zod@4.4.3))(ws@8.21.0)(zod@4.4.3) + '@openclaw/ai': 2026.7.1-2(@modelcontextprotocol/sdk@1.29.0(zod@4.4.3))(ws@8.21.0)(zod@4.4.3) '@openclaw/fs-safe': 0.4.1 '@openclaw/proxyline': 0.3.3(undici@8.5.0) '@silvia-odwyer/photon-node': 0.3.4 @@ -2743,7 +2746,7 @@ snapshots: path-scurry@2.0.2: dependencies: - lru-cache: 11.5.1 + lru-cache: 11.5.2 minipass: 7.1.3 path-to-regexp@8.4.2: {} @@ -2773,7 +2776,7 @@ snapshots: '@protobufjs/inquire': 1.1.2 '@protobufjs/path': 1.1.2 '@protobufjs/pool': 1.1.0 - '@protobufjs/utf8': 1.1.1 + '@protobufjs/utf8': 1.1.2 '@types/node': 26.1.2 long: 5.3.2 @@ -2794,7 +2797,7 @@ snapshots: quickjs-wasi@3.0.2: {} - range-parser@1.2.1: {} + range-parser@1.3.0: {} rastermill@0.3.1: dependencies: @@ -2804,7 +2807,7 @@ snapshots: dependencies: bytes: 3.1.2 http-errors: 2.0.1 - iconv-lite: 0.7.2 + iconv-lite: 0.7.3 unpipe: 1.0.0 readable-stream@2.3.8: @@ -2856,7 +2859,7 @@ snapshots: mime-types: 3.0.2 ms: 2.1.3 on-finished: 2.4.1 - range-parser: 1.2.1 + range-parser: 1.3.0 statuses: 2.0.2 transitivePeerDependencies: - supports-color @@ -2990,7 +2993,7 @@ snapshots: tree-sitter-bash@0.25.1: dependencies: - node-addon-api: 8.8.0 + node-addon-api: 8.9.1 node-gyp-build: 4.8.4 ts-algebra@2.0.0: {} @@ -2999,7 +3002,7 @@ snapshots: tslog@4.10.2: {} - tsx@4.23.1: + tsx@4.23.5: dependencies: esbuild: 0.28.1 optionalDependencies: @@ -3008,7 +3011,7 @@ snapshots: type-is@2.1.0: dependencies: content-type: 2.0.0 - media-typer: 1.1.0 + media-typer: 1.1.1 mime-types: 3.0.2 typebox@1.3.3: {} @@ -3124,7 +3127,7 @@ snapshots: y18n: 4.0.3 yargs-parser: 18.1.3 - yargs@17.7.2: + yargs@17.7.3: dependencies: cliui: 8.0.1 escalade: 3.2.0 diff --git a/scripts/validate-release-metadata.mjs b/scripts/validate-release-metadata.mjs index e304b72..5de41bb 100644 --- a/scripts/validate-release-metadata.mjs +++ b/scripts/validate-release-metadata.mjs @@ -5,7 +5,8 @@ import { fileURLToPath } from "node:url"; const scriptPath = fileURLToPath(import.meta.url); const rootDir = dirname(dirname(scriptPath)); -const defaultOpenClawTargetVersion = "2026.7.1"; +const defaultOpenClawTargetVersion = "2026.7.1-2"; +const defaultOpenClawCompatibilityFloor = "2026.7.1"; const exactOpenClawVersionPattern = /^\d{4}\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/u; export function normalizeOpenClawTargetVersion(value = defaultOpenClawTargetVersion) { @@ -38,9 +39,13 @@ export function validateReleaseMetadata(options = {}) { const { releaseVersion, openclawTargetVersion = defaultOpenClawTargetVersion, + openclawCompatibilityFloor = defaultOpenClawCompatibilityFloor, baseDir = rootDir, } = options; const normalizedOpenClawTargetVersion = normalizeOpenClawTargetVersion(openclawTargetVersion); + const normalizedOpenClawCompatibilityFloor = normalizeOpenClawTargetVersion( + openclawCompatibilityFloor, + ); const { packageVersion, pluginVersion, @@ -102,7 +107,7 @@ export function validateReleaseMetadata(options = {}) { ); } - const expectedRange = `>=${normalizedOpenClawTargetVersion}`; + const expectedRange = `>=${normalizedOpenClawCompatibilityFloor}`; if (openclawInstall.minHostVersion !== expectedRange) { throw new Error( `OpenClaw install minHostVersion mismatch: expected ${expectedRange}, got ${openclawInstall.minHostVersion}`, @@ -115,9 +120,9 @@ export function validateReleaseMetadata(options = {}) { ); } - if (openclawCompat?.minGatewayVersion !== normalizedOpenClawTargetVersion) { + if (openclawCompat?.minGatewayVersion !== normalizedOpenClawCompatibilityFloor) { throw new Error( - `OpenClaw minGatewayVersion mismatch: expected ${normalizedOpenClawTargetVersion}, got ${openclawCompat?.minGatewayVersion}`, + `OpenClaw minGatewayVersion mismatch: expected ${normalizedOpenClawCompatibilityFloor}, got ${openclawCompat?.minGatewayVersion}`, ); } @@ -140,6 +145,12 @@ export function validateReleaseMetadata(options = {}) { throw new Error(`pnpm-lock.yaml is not pinned to OpenClaw ${openclawVersion}`); } + if (packageJson.devDependencies?.openclaw !== normalizedOpenClawTargetVersion) { + throw new Error( + `OpenClaw dev dependency mismatch: expected ${normalizedOpenClawTargetVersion}, got ${packageJson.devDependencies?.openclaw}`, + ); + } + if (packageJson.packageManager !== "pnpm@11.15.1") { throw new Error(`Unexpected package manager: ${packageJson.packageManager}`); } diff --git a/tests/plugin-entry.test.ts b/tests/plugin-entry.test.ts index 189aed1..72dcf85 100644 --- a/tests/plugin-entry.test.ts +++ b/tests/plugin-entry.test.ts @@ -72,8 +72,8 @@ describe("plugin entry source", () => { validateReleaseMetadata(); assert.equal(packageVersion, pluginVersion); assert.equal(pluginName, "Code Agent"); - assert.equal(openclawVersion, "2026.7.1"); - assert.equal(pluginSdkVersion, "2026.7.1"); + assert.equal(openclawVersion, "2026.7.1-2"); + assert.equal(pluginSdkVersion, "2026.7.1-2"); assert.equal(openclawInstall.npmSpec, "openclaw-code-agent"); assert.equal(openclawInstall.defaultChoice, "npm"); assert.equal(openclawInstall.minHostVersion, ">=2026.7.1"); @@ -109,7 +109,7 @@ describe("plugin entry source", () => { assert.doesNotMatch(activeWorkflowSources, /\bnpm audit\b/); }); - it("requires v2026.7.1 across all public OpenClaw compatibility metadata", () => { + it("targets v2026.7.1-2 while retaining the v2026.7.1 compatibility floor", () => { const packageJson = JSON.parse(readFileSync(join(rootDir, "package.json"), "utf8")) as { dependencies?: Record; openclaw?: { @@ -127,18 +127,21 @@ describe("plugin entry source", () => { assert.equal(packageJson.openclaw?.install?.minHostVersion, ">=2026.7.1"); assert.equal(packageJson.openclaw?.compat?.pluginApi, ">=2026.7.1"); assert.equal(packageJson.openclaw?.compat?.minGatewayVersion, "2026.7.1"); - assert.equal(packageJson.openclaw?.build?.openclawVersion, "2026.7.1"); - assert.equal(packageJson.openclaw?.build?.pluginSdkVersion, "2026.7.1"); + assert.equal(packageJson.openclaw?.build?.openclawVersion, "2026.7.1-2"); + assert.equal(packageJson.openclaw?.build?.pluginSdkVersion, "2026.7.1-2"); assert.equal(packageJson.peerDependencies?.openclaw, ">=2026.7.1"); - assert.equal(packageJson.devDependencies?.openclaw, "2026.7.1"); + assert.equal(packageJson.devDependencies?.openclaw, "2026.7.1-2"); assert.doesNotMatch(readFileSync(join(rootDir, "pnpm-lock.yaml"), "utf8"), /uuid@9\.0\.1/); }); it("accepts exact and range-shaped manual OpenClaw release targets", () => { - assert.equal(normalizeOpenClawTargetVersion("2026.7.1"), "2026.7.1"); + assert.equal(normalizeOpenClawTargetVersion("2026.7.1-2"), "2026.7.1-2"); assert.equal(normalizeOpenClawTargetVersion(">=2026.7.1"), "2026.7.1"); assert.doesNotThrow(() => - validateReleaseMetadata({ openclawTargetVersion: ">=2026.7.1" }), + validateReleaseMetadata({ + openclawTargetVersion: "2026.7.1-2", + openclawCompatibilityFloor: ">=2026.7.1", + }), ); assert.throws( () => normalizeOpenClawTargetVersion("^2026.7.1"), @@ -442,15 +445,15 @@ describe("plugin entry source", () => { assert.doesNotMatch(apiSource, /openclaw\/plugin-sdk\/discord/); }); - it("documents 2026.7.1 plugin allowlist and apply_patch policy boundaries", () => { + it("documents the 2026.7.1-2 target and 2026.7.1 compatibility boundaries", () => { const reference = readFileSync(join(rootDir, "docs", "REFERENCE.md"), "utf8"); const readme = readFileSync(join(rootDir, "README.md"), "utf8"); const changelog = readFileSync(join(rootDir, "CHANGELOG.md"), "utf8"); - assert.match(reference, /OpenClaw 2026\.7\.1 SDK Readiness/); - assert.match(reference, /validated against and requires OpenClaw `2026\.7\.1`/); - assert.match(readme, /targets, validates against, and requires OpenClaw `2026\.7\.1`/); - assert.match(changelog, /Retargeted the OpenClaw package and plugin SDK validation metadata to `2026\.7\.1`/); + assert.match(reference, /OpenClaw 2026\.7\.1-2 SDK Readiness/); + assert.match(reference, /validated against OpenClaw `2026\.7\.1-2`/); + assert.match(readme, /targets and validates against OpenClaw `2026\.7\.1-2`/); + assert.match(changelog, /retargeted package and plugin SDK build metadata to OpenClaw `2026\.7\.1-2`/i); assert.match(changelog, /Codex app-server, Telegram and topic routing, cron\/session delivery/); assert.match(readme, /retryable stale plan approval buttons/); assert.match(reference, /pnpm-workspace\.yaml/); From 48e24af8995fa806084048c8b4f4d9a29b8d296b Mon Sep 17 00:00:00 2001 From: Mark Goldenstein Date: Mon, 3 Aug 2026 19:05:07 -0700 Subject: [PATCH 2/3] Fix production dependency audit blockers --- CHANGELOG.md | 4 ++ docs/DEVELOPMENT.md | 2 + package.json | 2 +- pnpm-lock.yaml | 28 +++++------ pnpm-workspace.yaml | 6 ++- scripts/check-release-age-exceptions.mjs | 63 ++++++++++++++++++++++++ tests/release-age-exceptions.test.ts | 39 +++++++++++++++ 7 files changed, 127 insertions(+), 17 deletions(-) create mode 100644 scripts/check-release-age-exceptions.mjs create mode 100644 tests/release-age-exceptions.test.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c9d622..a6639f2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - Validated and retargeted package and plugin SDK build metadata to OpenClaw `2026.7.1-2` while retaining the compatible OpenClaw `2026.7.1` install, plugin API, Gateway, and peer dependency floor. - Confirmed that the OpenClaw correction release's singleton-array npm metadata fix requires no changes to Code Agent tools, callbacks, wake routing, worktree flows, plan approval, or harness model restrictions. +- Pinned patched `fast-uri` and Hono transitive releases, with a machine-checked, exact-version exception that permits only `hono@4.12.34` through the normal 24-hour release-age quarantine and expires after the quarantine clears. + +### Fixed +- Removed the production dependency advisories for `fast-uri` URI authority parsing and Hono CORS-header regular-expression denial of service without weakening the repository-wide release-age policy. ## [4.7.6] - 2026-07-15 diff --git a/docs/DEVELOPMENT.md b/docs/DEVELOPMENT.md index 169ee59..b54bbcf 100644 --- a/docs/DEVELOPMENT.md +++ b/docs/DEVELOPMENT.md @@ -81,6 +81,8 @@ Security automation should work like this: - Version maintenance: Dependabot updates the JavaScript dependency set through the npm ecosystem support that covers pnpm projects. - Full snapshot audit: run `pnpm audit` when you need the current advisory set for the full resolved pnpm graph, including dev dependencies. +The 24-hour minimum-release-age policy remains the default for every dependency. If a security-fixed release must be admitted before that quarantine ends, use an exact `package@version` entry in `minimumReleaseAgeExclude` immediately preceded by a `security-exception` comment containing the advisory, publication time, quarantine end, and removal deadline. `pnpm check-static-guardrails` rejects malformed, non-exact, or expired exceptions; remove the entry and comment once the deadline passes. + OpenClaw 2026.7.1 requires Node 22.22.3 or newer when using Node 22; CI and release verification pin that patch floor. Plugin-behavior review should also include: ```bash diff --git a/package.json b/package.json index 5f6a4c1..849e904 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "scripts": { "audit:prod": "pnpm audit --prod", "build": "esbuild index.ts --bundle --splitting --platform=node --target=node22 --format=esm --outdir=dist --entry-names=index --chunk-names=chunks/[name] --minify --charset=utf8 --pure:console.log --pure:console.warn --pure:console.info --pure:console.debug --external:@anthropic-ai/claude-agent-sdk --external:openclaw/plugin-sdk/plugin-entry", - "check-static-guardrails": "node scripts/check-static-guardrails.mjs", + "check-static-guardrails": "node scripts/check-static-guardrails.mjs && node scripts/check-release-age-exceptions.mjs", "check-plugin-security": "node scripts/check-plugin-security.mjs", "test": "node scripts/run-tests.mjs", "test:integ:crabbox": "node scripts/run-tests.mjs tests/oca-codex-crabbox-integ.test.ts tests/oca-plugin-workflows-integ.test.ts tests/oca-codex-telegram-proof.test.ts tests/oca-codex-proof-app-server.test.ts tests/oca-codex-proof-workflow.test.ts", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index afbac21..17e5a1d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -16,9 +16,9 @@ overrides: path-to-regexp@>=8.0.0 <8.4.0: '>=8.4.0' '@anthropic-ai/sdk@<0.93.0': 0.93.0 ip-address@<10.1.1: 10.1.1 - fast-uri@<=3.1.3: 3.1.4 + fast-uri@<3.1.5: 3.1.5 qs@<6.15.2: 6.15.2 - hono@<4.12.27: 4.12.27 + hono@<4.12.34: 4.12.34 '@hono/node-server@<2.0.10': 2.0.10 undici@>=8.0.0 <8.5.0: 8.5.0 @@ -324,7 +324,7 @@ packages: resolution: {integrity: sha512-ZcnNVhKTmyDJeg0UlnZjvM73JBsTAuhrH/J4fjwGOw59PwOW51r4J+p6CsKZWXdKSme4MFqU62CZMOsdDrU4CA==} engines: {node: '>=20'} peerDependencies: - hono: 4.12.27 + hono: 4.12.34 '@isaacs/fs-minipass@4.0.1': resolution: {integrity: sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==} @@ -870,8 +870,8 @@ packages: fast-string-width@3.0.2: resolution: {integrity: sha512-gX8LrtNEI5hq8DVUfRQMbr5lpaS4nMIWV+7XEbXk2b8kiQIizgnlr12B4dA3ZEx3308ze0O4Q1R+cHts8kyUJg==} - fast-uri@3.1.4: - resolution: {integrity: sha512-8JnbkQ4juDyvYs4mgFGQqg4yCYtFDtUtmp2QIQq11ZZe5CFQ5wcqm1rqDgAh/QdMySuBnPzMUiJUNZG5N/AiQw==} + fast-uri@3.1.5: + resolution: {integrity: sha512-gHwA1O9LDIcKunMKhObS/HimwtehO1nPUECKAu5TpKgaO19fcWEl4bliWe1jWxVFvIXztJjjQ4L8XQ1EU9f7Jw==} fast-wrap-ansi@0.2.2: resolution: {integrity: sha512-7F2Fl+TjRSenLqlU3UjSH0iyqopqoZIu7eZVpEirP2g1GtWa2G/ecEmBdgz31+Mxr+ELclgg6sokpSFIQiZ02Q==} @@ -971,8 +971,8 @@ packages: resolution: {integrity: sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w==} engines: {node: '>=12.0.0'} - hono@4.12.27: - resolution: {integrity: sha512-1yrb/+w6HWQJrUCLkJ2IF5jNIPvvFkblV5RNOYl6bV+OA6p9GLcMpHFFGTosSvHvcAUibuUukRqhlYI4z32C7Q==} + hono@4.12.34: + resolution: {integrity: sha512-GqXJqY/xJkJmuloTrnV1ZEXG3fqte+VjkUqoRNZXcrUidiUOP4fMSIHHY4tsqZBK++kVyWmt/AAfSUuy57/eSA==} engines: {node: '>=16.9.0'} hosted-git-info@10.1.1: @@ -1813,9 +1813,9 @@ snapshots: transitivePeerDependencies: - supports-color - '@hono/node-server@2.0.10(hono@4.12.27)': + '@hono/node-server@2.0.10(hono@4.12.34)': dependencies: - hono: 4.12.27 + hono: 4.12.34 '@isaacs/fs-minipass@4.0.1': dependencies: @@ -1860,7 +1860,7 @@ snapshots: '@modelcontextprotocol/sdk@1.29.0(zod@4.4.3)': dependencies: - '@hono/node-server': 2.0.10(hono@4.12.27) + '@hono/node-server': 2.0.10(hono@4.12.34) ajv: 8.20.0 ajv-formats: 3.0.1(ajv@8.20.0) content-type: 1.0.5 @@ -1870,7 +1870,7 @@ snapshots: eventsource-parser: 3.1.0 express: 5.2.1 express-rate-limit: 8.6.1(express@5.2.1) - hono: 4.12.27 + hono: 4.12.34 jose: 6.2.7 json-schema-typed: 8.0.2 pkce-challenge: 5.0.1 @@ -2032,7 +2032,7 @@ snapshots: ajv@8.20.0: dependencies: fast-deep-equal: 3.1.3 - fast-uri: 3.1.4 + fast-uri: 3.1.5 json-schema-traverse: 1.0.0 require-from-string: 2.0.2 @@ -2322,7 +2322,7 @@ snapshots: dependencies: fast-string-truncated-width: 3.0.3 - fast-uri@3.1.4: {} + fast-uri@3.1.5: {} fast-wrap-ansi@0.2.2: dependencies: @@ -2450,7 +2450,7 @@ snapshots: highlight.js@11.11.1: {} - hono@4.12.27: {} + hono@4.12.34: {} hosted-git-info@10.1.1: dependencies: diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index a01b328..4af05de 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -9,6 +9,8 @@ allowBuilds: tree-sitter-bash: false minimumReleaseAgeExclude: + # security-exception advisory=GHSA-8j4g-w8fx-2239 published=2026-08-03T02:36:40.543Z quarantineEnds=2026-08-04T02:36:40.543Z expires=2026-08-05T02:36:40.543Z + - hono@4.12.34 - '@anthropic-ai/claude-agent-sdk-darwin-arm64@0.3.216' - '@anthropic-ai/claude-agent-sdk-darwin-x64@0.3.216' - '@anthropic-ai/claude-agent-sdk-linux-arm64-musl@0.3.216' @@ -31,8 +33,8 @@ overrides: path-to-regexp@>=8.0.0 <8.4.0: ">=8.4.0" "@anthropic-ai/sdk@<0.93.0": 0.93.0 ip-address@<10.1.1: 10.1.1 - fast-uri@<=3.1.3: 3.1.4 + fast-uri@<3.1.5: 3.1.5 qs@<6.15.2: 6.15.2 - hono@<4.12.27: 4.12.27 + hono@<4.12.34: 4.12.34 "@hono/node-server@<2.0.10": 2.0.10 undici@>=8.0.0 <8.5.0: 8.5.0 diff --git a/scripts/check-release-age-exceptions.mjs b/scripts/check-release-age-exceptions.mjs new file mode 100644 index 0000000..e59fc2d --- /dev/null +++ b/scripts/check-release-age-exceptions.mjs @@ -0,0 +1,63 @@ +import { readFile } from "node:fs/promises"; + +const marker = /^\s*#\s*security-exception\s+(.+)\s*$/; +const entry = /^\s*-\s*['"]?([^'"\s]+)['"]?\s*$/; +const exactPackageVersion = /^(?:@[^/@]+\/[^/@]+|[^@/]+)@(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)(?:-[0-9A-Za-z.-]+)?$/; + +export function parseSecurityExceptions(source) { + const lines = source.split(/\r?\n/); + const exceptions = []; + + for (let index = 0; index < lines.length; index += 1) { + const match = marker.exec(lines[index]); + if (!match) continue; + + const fields = Object.fromEntries( + match[1].split(/\s+/).map((part) => { + const separator = part.indexOf("="); + if (separator < 1) throw new Error(`Malformed security exception field on line ${index + 1}: ${part}`); + return [part.slice(0, separator), part.slice(separator + 1)]; + }), + ); + const packageMatch = entry.exec(lines[index + 1] ?? ""); + if (!packageMatch) throw new Error(`Security exception on line ${index + 1} must immediately precede one package entry`); + exceptions.push({ ...fields, package: packageMatch[1], line: index + 1 }); + } + + return exceptions; +} + +export function validateSecurityExceptions(source, now = new Date()) { + const exceptions = parseSecurityExceptions(source); + for (const exception of exceptions) { + if (!exactPackageVersion.test(exception.package)) { + throw new Error(`Security exception on line ${exception.line} is not an exact package@version: ${exception.package}`); + } + if (!/^GHSA-[0-9a-z-]+$/.test(exception.advisory ?? "")) { + throw new Error(`Security exception on line ${exception.line} requires a GHSA advisory`); + } + + const published = Date.parse(exception.published ?? ""); + const quarantineEnds = Date.parse(exception.quarantineEnds ?? ""); + const expires = Date.parse(exception.expires ?? ""); + if (![published, quarantineEnds, expires].every(Number.isFinite)) { + throw new Error(`Security exception on line ${exception.line} requires valid published, quarantineEnds, and expires timestamps`); + } + if (quarantineEnds !== published + 24 * 60 * 60 * 1000) { + throw new Error(`Security exception on line ${exception.line} must use the repository's 24-hour quarantine`); + } + if (expires <= quarantineEnds) { + throw new Error(`Security exception on line ${exception.line} must expire after quarantine ends`); + } + if (now.getTime() >= expires) { + throw new Error(`Security exception on line ${exception.line} expired at ${exception.expires}; remove it`); + } + } + return exceptions; +} + +if (import.meta.url === `file://${process.argv[1]}`) { + const workspaceFile = new URL("../pnpm-workspace.yaml", import.meta.url); + const exceptions = validateSecurityExceptions(await readFile(workspaceFile, "utf8")); + console.log(`Validated ${exceptions.length} temporary release-age security exception(s).`); +} diff --git a/tests/release-age-exceptions.test.ts b/tests/release-age-exceptions.test.ts new file mode 100644 index 0000000..b8ddbd6 --- /dev/null +++ b/tests/release-age-exceptions.test.ts @@ -0,0 +1,39 @@ +import assert from "node:assert/strict"; +import { describe, it } from "node:test"; + +import { validateSecurityExceptions } from "../scripts/check-release-age-exceptions.mjs"; + +const exception = (packageSpec = "hono@4.12.34", expires = "2026-08-05T02:36:40.543Z") => ` +minimumReleaseAgeExclude: + # security-exception advisory=GHSA-8j4g-w8fx-2239 published=2026-08-03T02:36:40.543Z quarantineEnds=2026-08-04T02:36:40.543Z expires=${expires} + - ${packageSpec} +`; + +describe("release-age security exceptions", () => { + it("accepts a documented exact-version exception before its deadline", () => { + const exceptions = validateSecurityExceptions(exception(), new Date("2026-08-04T12:00:00Z")); + assert.equal(exceptions[0]?.package, "hono@4.12.34"); + }); + + it("rejects a range that could bypass quarantine for later releases", () => { + assert.throws( + () => validateSecurityExceptions(exception("hono@^4.12.34"), new Date("2026-08-04T12:00:00Z")), + /not an exact package@version/, + ); + }); + + it("rejects an expired exception so it cannot become permanent", () => { + assert.throws( + () => validateSecurityExceptions(exception(), new Date("2026-08-05T02:36:40.543Z")), + /expired at/, + ); + }); + + it("rejects a quarantine interval shorter than the repository policy", () => { + const source = exception().replace("2026-08-04T02:36:40.543Z", "2026-08-03T03:36:40.543Z"); + assert.throws( + () => validateSecurityExceptions(source, new Date("2026-08-03T03:00:00Z")), + /24-hour quarantine/, + ); + }); +}); From 4391201dfbcbc694c6edbca3668c799e56cfe36e Mon Sep 17 00:00:00 2001 From: Mark Goldenstein Date: Mon, 3 Aug 2026 19:33:26 -0700 Subject: [PATCH 3/3] Fix correction release compatibility floor --- CHANGELOG.md | 2 +- README.md | 2 +- docs/REFERENCE.md | 6 +++--- package.json | 8 ++++---- scripts/validate-release-metadata.mjs | 2 +- tests/plugin-entry.test.ts | 16 ++++++++-------- 6 files changed, 18 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a6639f2..5ccc108 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [4.7.7] - 2026-08-03 ### Changed -- Validated and retargeted package and plugin SDK build metadata to OpenClaw `2026.7.1-2` while retaining the compatible OpenClaw `2026.7.1` install, plugin API, Gateway, and peer dependency floor. +- Validated and retargeted package and plugin SDK build metadata to OpenClaw `2026.7.1-2`, using that correction release as the install, plugin API, Gateway, and peer dependency floor so both it and stable `2026.7.1` satisfy the declared compatibility contract. - Confirmed that the OpenClaw correction release's singleton-array npm metadata fix requires no changes to Code Agent tools, callbacks, wake routing, worktree flows, plan approval, or harness model restrictions. - Pinned patched `fast-uri` and Hono transitive releases, with a machine-checked, exact-version exception that permits only `hono@4.12.34` through the normal 24-hour release-age quarantine and expires after the quarantine clears. diff --git a/README.md b/README.md index 4e0c956..131bd8b 100644 --- a/README.md +++ b/README.md @@ -128,7 +128,7 @@ Because worktree isolation defaults to `delegate`, `defaultWorkdir` should norma Chat-launched sessions route updates back to their originating chat thread. For agent-launched tool sessions without an origin route, configure `fallbackChannel` or `agentChannels` in the reference guide. -The current package targets and validates against OpenClaw `2026.7.1-2` while retaining OpenClaw `2026.7.1` as its install, plugin API, Gateway, and peer dependency minimum. The correction release only fixes singleton-array npm metadata handling for plugin installs and updates, so no host config migration or Code Agent runtime change is required. The manifest still declares `contracts.tools`, the plugin still imports only `openclaw/plugin-sdk/plugin-entry`, and its own session store, wake routing, callbacks, worktree flows, and Codex/Claude model restrictions remain plugin-owned. Current callback behavior around native callback data, routed follow-ups, retryable stale plan approval buttons, and serialized plan decisions remains unchanged. +The current package targets and validates against OpenClaw `2026.7.1-2`. Its install, plugin API, Gateway, and peer dependency floor is `2026.7.1-2`, which includes both that numeric correction release and the higher-precedence stable `2026.7.1` release under SemVer ordering. The correction release only fixes singleton-array npm metadata handling for plugin installs and updates, so no host config migration or Code Agent runtime change is required. The manifest still declares `contracts.tools`, the plugin still imports only `openclaw/plugin-sdk/plugin-entry`, and its own session store, wake routing, callbacks, worktree flows, and Codex/Claude model restrictions remain plugin-owned. Current callback behavior around native callback data, routed follow-ups, retryable stale plan approval buttons, and serialized plan decisions remains unchanged. If you use Codex, make sure the local `codex` command or `OPENCLAW_CODEX_APP_SERVER_COMMAND` override is available and authenticated. Codex-specific defaults live under `harnesses.codex`: `reasoningEffort` is sent as `reasoningEffort`, and `fastMode: true` sends `service_tier: "fast"` on Codex App Server thread, resume, and turn payloads. The Codex harness starts the app server with stdio listener args by default, only sends UUID-shaped backend thread IDs to `thread/resume`, and reports startup timeouts with redacted recent stderr. When Codex auth is inconsistent, this is the recommended `~/.codex/config.toml` setting: diff --git a/docs/REFERENCE.md b/docs/REFERENCE.md index 4469253..f40de04 100644 --- a/docs/REFERENCE.md +++ b/docs/REFERENCE.md @@ -30,11 +30,11 @@ Current releases treat persisted session storage as new-schema-only. If startup ### OpenClaw 2026.7.1-2 SDK Readiness -The current `openclaw-code-agent` package is validated against OpenClaw `2026.7.1-2` and retains OpenClaw `2026.7.1` as its minimum compatible host. Exact build metadata and the development dependency record the tested correction release, while package install, plugin API, Gateway, and peer dependency metadata continue to reject hosts older than `2026.7.1` without unnecessarily excluding the compatible base release. +The current `openclaw-code-agent` package is validated against OpenClaw `2026.7.1-2`. Exact build metadata and the development dependency record that tested correction release. Package install, plugin API, Gateway, and peer dependency metadata use `2026.7.1-2` as their floor so standard SemVer checks accept the correction release itself as well as the higher-precedence stable `2026.7.1` release, while rejecting older hosts. Hosts already running OpenClaw `2026.7.1` need no host config change. OpenClaw `2026.7.1-2` only normalizes singleton-array output from newer `npm view --json` clients and continues to reject ambiguous multi-version arrays. No new SDK imports or Code Agent runtime changes are needed: runtime code still imports only `openclaw/plugin-sdk/plugin-entry`, `openclaw.plugin.json` already declares tools through `contracts.tools`, pnpm build policy and overrides remain in `pnpm-workspace.yaml`, and code-agent session storage remains plugin-owned. Current Start Plan and approval callbacks, Telegram/topic routing, completion and cron/session wakes, Codex and Claude model restrictions, runtime tool visibility, disabled bundled-plugin boundaries, and plan/worktree follow-through remain unchanged. -Configuration guidance for the `2026.7.1` compatibility floor and tested `2026.7.1-2` correction release: +Configuration guidance for the `2026.7.1-2` compatibility floor and tested correction release: - If `plugins.allow` is present, add `openclaw-code-agent`. OpenClaw treats that allowlist as exclusive, so `tools.allow` cannot make this plugin's tools available when the owning plugin is blocked. - New OpenClaw configs default `plugins.bundledDiscovery` to `allowlist`, so a restrictive `plugins.allow` list can also block omitted bundled provider or runtime plugins. OpenClaw `2026.7.1` continues to discover externally installed channel plugins at Gateway startup, but that host-side discovery does not make those plugins implicitly available to OCA sessions. Disabled or omitted adjacent plugins remain unavailable unless explicitly enabled or auto-enabled by their own OpenClaw contracts. @@ -56,7 +56,7 @@ Configuration guidance for the `2026.7.1` compatibility floor and tested `2026.7 - Installed plugins that register host-trusted pre-tool policies must declare `contracts.trustedToolPolicies`. This plugin does not register trusted pre-tool policies, so no manifest contract is needed beyond the existing `contracts.tools` list. - The removed upstream sender-owner tool gating path does not replace this plugin's auth boundary. Chat commands remain auth-required, and Telegram/Discord callbacks still require authorized senders before `agent_respond`, plan approval, merge, PR, cleanup, or Start Plan actions are applied. OpenClaw's plugin write ownership checks are host-side package safety checks; OCA should not claim ownership of host or adjacent plugin package writes. - Legacy `defaultModel`, `model`, `reasoningEffort`, and global `allowedModels` are compatibility fields only. New configs should not use them. -- Managed external-plugin npm installs now use per-plugin project roots and enforce `openclaw.compat.pluginApi` when selecting compatible package versions. This package aligns that range, its Gateway minimum, and its peer dependency with the release-tested OpenClaw `2026.7.1` host; keep `openclaw.extensions` pointing at the built `dist/index.js` artifact. +- Managed external-plugin npm installs now use per-plugin project roots and enforce `openclaw.compat.pluginApi` when selecting compatible package versions. This package aligns that range, its Gateway minimum, and its peer dependency with the release-tested OpenClaw `2026.7.1-2` correction release; the floor also accepts stable `2026.7.1`. Keep `openclaw.extensions` pointing at the built `dist/index.js` artifact. - OpenClaw `2026.7.1` removes built-in dangerous-code blocking from plugin installs and deprecates `--dangerously-force-unsafe-install`; operators who require a host-specific allow/block decision should configure `security.installPolicy`. OCA's release smoke installs only its freshly packed artifact under an isolated temporary home and does not read or migrate operator state. - `tools.deny` does not disable OpenClaw's `apply_patch` tool by itself in current OpenClaw. To restrict patch edits, configure OpenClaw `tools.exec.applyPatch.enabled`, `tools.exec.applyPatch.workspaceOnly`, or `tools.exec.applyPatch.allowModels`. diff --git a/package.json b/package.json index 849e904..1dd8da9 100644 --- a/package.json +++ b/package.json @@ -33,11 +33,11 @@ "install": { "npmSpec": "openclaw-code-agent", "defaultChoice": "npm", - "minHostVersion": ">=2026.7.1" + "minHostVersion": ">=2026.7.1-2" }, "compat": { - "pluginApi": ">=2026.7.1", - "minGatewayVersion": "2026.7.1" + "pluginApi": ">=2026.7.1-2", + "minGatewayVersion": "2026.7.1-2" }, "build": { "openclawVersion": "2026.7.1-2", @@ -95,7 +95,7 @@ }, "description": "An OpenClaw plugin that orchestrates coding agent sessions as managed background processes. Launch, monitor, and control coding agents (Claude Code, Codex, experimental OpenCode, and more) directly from your AI gateway.", "peerDependencies": { - "openclaw": ">=2026.7.1" + "openclaw": ">=2026.7.1-2" }, "overrides": { "basic-ftp": "5.3.1", diff --git a/scripts/validate-release-metadata.mjs b/scripts/validate-release-metadata.mjs index 5de41bb..2efddf1 100644 --- a/scripts/validate-release-metadata.mjs +++ b/scripts/validate-release-metadata.mjs @@ -6,7 +6,7 @@ import { fileURLToPath } from "node:url"; const scriptPath = fileURLToPath(import.meta.url); const rootDir = dirname(dirname(scriptPath)); const defaultOpenClawTargetVersion = "2026.7.1-2"; -const defaultOpenClawCompatibilityFloor = "2026.7.1"; +const defaultOpenClawCompatibilityFloor = "2026.7.1-2"; const exactOpenClawVersionPattern = /^\d{4}\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/u; export function normalizeOpenClawTargetVersion(value = defaultOpenClawTargetVersion) { diff --git a/tests/plugin-entry.test.ts b/tests/plugin-entry.test.ts index 72dcf85..3b9f44e 100644 --- a/tests/plugin-entry.test.ts +++ b/tests/plugin-entry.test.ts @@ -76,7 +76,7 @@ describe("plugin entry source", () => { assert.equal(pluginSdkVersion, "2026.7.1-2"); assert.equal(openclawInstall.npmSpec, "openclaw-code-agent"); assert.equal(openclawInstall.defaultChoice, "npm"); - assert.equal(openclawInstall.minHostVersion, ">=2026.7.1"); + assert.equal(openclawInstall.minHostVersion, ">=2026.7.1-2"); const cliOutput = execFileSync("node", ["scripts/validate-release-metadata.mjs"], { cwd: rootDir, @@ -85,7 +85,7 @@ describe("plugin entry source", () => { assert.match(cliOutput, /openclaw\.plugin\.name=Code Agent/); assert.match(cliOutput, /openclaw\.install\.npmSpec=openclaw-code-agent/); assert.match(cliOutput, /openclaw\.install\.defaultChoice=npm/); - assert.match(cliOutput, /openclaw\.install\.minHostVersion=>=2026\.7\.1/); + assert.match(cliOutput, /openclaw\.install\.minHostVersion=>=2026\.7\.1-2/); }); it("keeps security audit automation on the pnpm-only path", () => { @@ -109,7 +109,7 @@ describe("plugin entry source", () => { assert.doesNotMatch(activeWorkflowSources, /\bnpm audit\b/); }); - it("targets v2026.7.1-2 while retaining the v2026.7.1 compatibility floor", () => { + it("uses a correction-release floor that includes v2026.7.1-2 and stable v2026.7.1", () => { const packageJson = JSON.parse(readFileSync(join(rootDir, "package.json"), "utf8")) as { dependencies?: Record; openclaw?: { @@ -124,12 +124,12 @@ describe("plugin entry source", () => { assert.equal(packageJson.dependencies?.["@anthropic-ai/claude-agent-sdk"], "^0.3.216"); assert.equal(packageJson.openclaw?.install?.npmSpec, "openclaw-code-agent"); assert.equal(packageJson.openclaw?.install?.defaultChoice, "npm"); - assert.equal(packageJson.openclaw?.install?.minHostVersion, ">=2026.7.1"); - assert.equal(packageJson.openclaw?.compat?.pluginApi, ">=2026.7.1"); - assert.equal(packageJson.openclaw?.compat?.minGatewayVersion, "2026.7.1"); + assert.equal(packageJson.openclaw?.install?.minHostVersion, ">=2026.7.1-2"); + assert.equal(packageJson.openclaw?.compat?.pluginApi, ">=2026.7.1-2"); + assert.equal(packageJson.openclaw?.compat?.minGatewayVersion, "2026.7.1-2"); assert.equal(packageJson.openclaw?.build?.openclawVersion, "2026.7.1-2"); assert.equal(packageJson.openclaw?.build?.pluginSdkVersion, "2026.7.1-2"); - assert.equal(packageJson.peerDependencies?.openclaw, ">=2026.7.1"); + assert.equal(packageJson.peerDependencies?.openclaw, ">=2026.7.1-2"); assert.equal(packageJson.devDependencies?.openclaw, "2026.7.1-2"); assert.doesNotMatch(readFileSync(join(rootDir, "pnpm-lock.yaml"), "utf8"), /uuid@9\.0\.1/); }); @@ -140,7 +140,7 @@ describe("plugin entry source", () => { assert.doesNotThrow(() => validateReleaseMetadata({ openclawTargetVersion: "2026.7.1-2", - openclawCompatibilityFloor: ">=2026.7.1", + openclawCompatibilityFloor: ">=2026.7.1-2", }), ); assert.throws(