fix(ce-update): derive cache dir from CLAUDE_PLUGIN_ROOT parent (#645)
Some checks failed
CI / pr-title (push) Has been cancelled
CI / test (push) Has been cancelled
Release PR / release-pr (push) Has been cancelled
Release PR / publish-cli (push) Has been cancelled

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Trevin Chow
2026-04-22 08:42:28 -07:00
committed by GitHub
parent 86d9a2c55f
commit 6155b9de3c
2 changed files with 46 additions and 7 deletions

View File

@@ -17,21 +17,28 @@ version, and fix stale marketplace/cache state if it doesn't. Claude Code only.
## Pre-resolved context
The three sections below contain pre-resolved data. Only the **Plugin root
path** determines whether this session is Claude Code — if it contains an error
The sections below contain pre-resolved data. Only the **Plugin root path**
determines whether this session is Claude Code — if it contains an error
sentinel, an empty value, or a literal `${CLAUDE_PLUGIN_ROOT}` string, tell the
user this skill only works in Claude Code and stop. The other two sections may
user this skill only works in Claude Code and stop. The other sections may
contain error sentinels even in valid Claude Code sessions; the decision logic
below handles those cases.
`CLAUDE_PLUGIN_ROOT` points at the currently-loaded plugin version directory
(e.g. `~/.claude/plugins/cache/<marketplace>/compound-engineering/<version>`),
so the plugin cache directory that holds every cached version is its parent.
**Plugin root path:**
!`echo "${CLAUDE_PLUGIN_ROOT}" 2>/dev/null || echo '__CE_UPDATE_ROOT_FAILED__'`
**Latest released version:**
!`gh release list --repo EveryInc/compound-engineering-plugin --limit 30 --json tagName --jq '[.[] | select(.tagName | startswith("compound-engineering-v"))][0].tagName | sub("compound-engineering-v";"")' 2>/dev/null || echo '__CE_UPDATE_VERSION_FAILED__'`
**Plugin cache directory:**
!`case "$(dirname "${CLAUDE_PLUGIN_ROOT:-}")" in */cache/*/compound-engineering) dirname "${CLAUDE_PLUGIN_ROOT}" ;; *) echo '__CE_UPDATE_CACHE_FAILED__' ;; esac`
**Cached version folder(s):**
!`ls "${CLAUDE_PLUGIN_ROOT}/cache/compound-engineering-plugin/compound-engineering/" 2>/dev/null || echo '__CE_UPDATE_CACHE_FAILED__'`
!`case "$(dirname "${CLAUDE_PLUGIN_ROOT:-}")" in */cache/*/compound-engineering) ls "$(dirname "${CLAUDE_PLUGIN_ROOT}")" 2>/dev/null ;; *) echo '__CE_UPDATE_CACHE_FAILED__' ;; esac`
## Decision logic
@@ -56,12 +63,12 @@ Take the **latest released version** and the **cached folder list**.
- Tell the user: "compound-engineering **v{version}** is installed and up to date."
**Out of date or corrupted** — multiple cached folders exist, OR the single folder name
does not match the latest version. Use the **Plugin root path** value from above to
construct the delete path.
does not match the latest version. Use the **Plugin cache directory** value from above
as the delete path.
**Clear the stale cache:**
```bash
rm -rf "<plugin-root-path>/cache/compound-engineering-plugin/compound-engineering"
rm -rf "<plugin-cache-directory>"
```
Tell the user:

View File

@@ -0,0 +1,32 @@
import { readFileSync } from "fs"
import path from "path"
import { describe, expect, test } from "bun:test"
// Regression guard for https://github.com/EveryInc/compound-engineering-plugin/issues/556.
//
// `CLAUDE_PLUGIN_ROOT` is set by the Claude Code harness to the currently-loaded
// plugin version directory (e.g. `~/.claude/plugins/cache/<marketplace>/compound-engineering/<version>`).
// It is NOT the plugins cache root. Appending `/cache/<anything>/compound-engineering/`
// onto it produces a path that never exists, which causes the cache-probe to fail
// and emit the `__CE_UPDATE_CACHE_FAILED__` sentinel on every healthy install.
//
// This has regressed twice. Fail fast if the antipattern reappears.
describe("ce-update SKILL.md", () => {
const skillPath = path.join(
process.cwd(),
"plugins/compound-engineering/skills/ce-update/SKILL.md",
)
const body = readFileSync(skillPath, "utf8")
test("does not append a /cache/<marketplace>/ suffix onto CLAUDE_PLUGIN_ROOT", () => {
// Matches any `${CLAUDE_PLUGIN_ROOT}/cache/<segment>/` or `${CLAUDE_PLUGIN_ROOT}/cache/<segment>"`
// pattern. The harness variable is already under `cache/<marketplace>/`,
// so concatenating another `cache/...` segment is always wrong.
const antiPattern = /\$\{CLAUDE_PLUGIN_ROOT\}\/cache\//
expect(
antiPattern.test(body),
"ce-update/SKILL.md reintroduced the ${CLAUDE_PLUGIN_ROOT}/cache/... antipattern — derive the cache dir from dirname \"${CLAUDE_PLUGIN_ROOT}\" instead.",
).toBe(false)
})
})