Fix stale OpenCode plugin cache doctor check#199
Conversation
There was a problem hiding this comment.
2 issues found across 3 files
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
There was a problem hiding this comment.
2 issues found across 3 files (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="packages/cli/src/commands/doctor-opencode-cache.ts">
<violation number="1" location="packages/cli/src/commands/doctor-opencode-cache.ts:5">
P1: Exported plugin constants are duplicated in other modules; adapters/opencode.ts hard-codes the same cache paths instead of using the new helper, risking divergence and stale-cache regressions.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
| @@ -0,0 +1,100 @@ | |||
| import { existsSync, readFileSync, rmSync } from "node:fs"; | |||
There was a problem hiding this comment.
P1: Exported plugin constants are duplicated in other modules; adapters/opencode.ts hard-codes the same cache paths instead of using the new helper, risking divergence and stale-cache regressions.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/cli/src/commands/doctor-opencode-cache.ts, line 5:
<comment>Exported plugin constants are duplicated in other modules; adapters/opencode.ts hard-codes the same cache paths instead of using the new helper, risking divergence and stale-cache regressions.</comment>
<file context>
@@ -2,12 +2,13 @@ import { existsSync, readFileSync, rmSync } from "node:fs";
-const PLUGIN_NAME = "@cortexkit/opencode-magic-context";
-const PLUGIN_ENTRY_WITH_VERSION = `${PLUGIN_NAME}@latest`;
+export const OPENCODE_PLUGIN_NAME = "@cortexkit/opencode-magic-context";
+export const OPENCODE_PLUGIN_ENTRY_WITH_VERSION = `${OPENCODE_PLUGIN_NAME}@latest`;
</file context>
There was a problem hiding this comment.
1 issue found across 7 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="packages/cli/src/commands/doctor-opencode-cache.ts">
<violation number="1" location="packages/cli/src/commands/doctor-opencode-cache.ts:17">
P2: Bulk cache deletion is not atomic and fails to report partial-clear outcomes, so a mid-loop deletion failure leaves the cache partially cleared while the returned result reports a single `error` path that may already be deleted.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
| } | ||
|
|
||
| function readCachedPluginVersion(pluginCacheDir: string): string | undefined { | ||
| try { |
There was a problem hiding this comment.
P2: Bulk cache deletion is not atomic and fails to report partial-clear outcomes, so a mid-loop deletion failure leaves the cache partially cleared while the returned result reports a single error path that may already be deleted.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/cli/src/commands/doctor-opencode-cache.ts, line 17:
<comment>Bulk cache deletion is not atomic and fails to report partial-clear outcomes, so a mid-loop deletion failure leaves the cache partially cleared while the returned result reports a single `error` path that may already be deleted.</comment>
<file context>
@@ -0,0 +1,89 @@
+}
+
+function readCachedPluginVersion(pluginCacheDir: string): string | undefined {
+ try {
+ const installedPkgPath = getOpenCodePluginPackageJsonPath(pluginCacheDir);
+ if (!existsSync(installedPkgPath)) return undefined;
</file context>
Follow-up to #199 (cubic P2): the bulk cache clear ran all roots inside one try/catch, so a mid-loop rmSync failure aborted the rest and the error result reported clearTargets[0] - a root that may have already been deleted - while hiding that one root was cleared. Now each root is removed independently: the error result points at the root that ACTUALLY failed, successfully-cleared roots still get removed, and partial outcomes are reported accurately. Added an injected-remover seam so the per-root failure path is deterministically tested. Gate: CLI 213/0, tsc + biome clean. Co-authored-by: Alfonso [Magic Context] <288211368+alfonso-magic-context@users.noreply.github.com>
Bump the in-app announcement to 0.30.0 (Desktop detection #196, badge #198, doctor cache #199) and add release notes. Fix a SQLITE_BUSY flake in thinking-block-safety.test.ts: openContextDbWritable opened the context DB without a busy_timeout, so under loaded CI a write could collide with the live plugin's handle and fail immediately instead of waiting. Added PRAGMA busy_timeout = 5000, matching the other e2e tests that share the context DB. Not a logic change; the audit fixes do not touch the tagging path this test exercises. Co-authored-by: Alfonso [Magic Context] <288211368+alfonso-magic-context@users.noreply.github.com>
|
Shipped in v0.30.0. Thanks for the fix, @coleleavitt, the root cause was spot on: the check compared against the CLI's own version rather than the plugin's latest published version, so a stale Merged with a small follow-up so each cache root is cleared independently (a failure on one root reports the root that actually failed, not an already-deleted one) and the cache is preserved rather than cleared when the version check is offline. |
Summary
Verification
bun src/index.ts doctor --harness opencode; it cleared cached @cortexkit/opencode-magic-context 0.26.0 and opencode restarted with Magic Context 0.29.1Need help on this PR? Tag
/codesmithwith what you need. Autofix is disabled.Summary by cubic
Fixes stale OpenCode plugin cache handling in
doctorby comparing the cached@cortexkit/opencode-magic-contextto the plugin’s npm latest and safely handling offline cases. Adds shared helpers for plugin cache paths and version files to reduce duplication and improve detection across commands.Bug Fixes
--forceclears it.Refactors
lib/opencode-plugin-cachewithOPENCODE_PLUGIN_NAME,OPENCODE_PLUGIN_ENTRY_WITH_VERSION,getOpenCodePluginCacheRoots, andgetOpenCodePluginPackageJsonPaths; adopted indoctor-opencode, diagnostics, setup, and adapter.doctor-opencode-cache.clearPluginCache({ force, latestVersion }); tests cover stale, matching, versionless, offline, and force-clear paths.Written for commit 0b02bc2. Summary will update on new commits.
Greptile Summary
This PR fixes the stale OpenCode plugin cache check in
doctorby fetching the plugin package's own npm latest version (instead of using the CLI package version as a proxy), then clearing the cache only when it is outdated. It also extracts shared cache path helpers and plugin name constants into a newlib/opencode-plugin-cache.tsmodule, and adds a focusedcommands/doctor-opencode-cache.tshelper with full regression coverage.doctor-opencode.tsnow fetchespluginNpmLatestfor@cortexkit/opencode-magic-contextin parallel with the CLI npm check and passes it toclearPluginCache; the newcheck_unavailableresult action handles the offline case gracefully (preserves cache, warns the user, respects--force).OPENCODE_PLUGIN_NAME,OPENCODE_PLUGIN_ENTRY_WITH_VERSION,getOpenCodePluginCacheRoots, andgetOpenCodePluginPackageJsonPathsare now defined once and imported everywhere, eliminating four separate local constant definitions.XDG_CACHE_HOMEis correctly saved and restored per test.Confidence Score: 5/5
Safe to merge; the bug fix is well-scoped and all affected code paths are covered by new tests.
The change correctly queries the plugin's own npm registry endpoint rather than using the CLI version as a stand-in, and the offline/force/versionless edge cases are all exercised by the new test suite. The only outstanding item is a diagnostic report field that still echoes the CLI version as "latest" for the plugin — an informational inaccuracy that does not affect doctor's decision-making logic.
packages/cli/src/lib/diagnostics-opencode.ts — getPluginCacheInfo still returns getSelfVersion() as the plugin's latest, which can misrepresent the plugin version in bug-report bundles.
Important Files Changed
Sequence Diagram
%%{init: {'theme': 'neutral'}}%% sequenceDiagram participant D as doctor-opencode.ts participant N as npm registry participant C as doctor-opencode-cache.ts participant FS as filesystem D->>N: "fetchNpmLatest("@cortexkit/magic-context")" D->>N: "fetchNpmLatest("@cortexkit/opencode-magic-context")" N-->>D: npmLatest (CLI) N-->>D: pluginNpmLatest (plugin, or null if offline) D->>C: "clearPluginCache({ force, latestVersion: pluginNpmLatest })" C->>FS: getOpenCodePluginCacheRoots() FS-->>C: existingRoots alt no cache found C-->>D: "{ action: not_found }" else "latestVersion=null and not forced" C-->>D: "{ action: check_unavailable }" else latestVersion provided C->>FS: readCachedPluginVersion(each root) FS-->>C: cached versions C->>C: "filter cached !== latestVersion" alt all entries up to date C-->>D: "{ action: up_to_date }" else stale or versionless entries C->>FS: rmSync(clearTargets) C-->>D: "{ action: cleared, paths }" end else "force=true" C->>FS: rmSync(all roots) C-->>D: "{ action: cleared }" end%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%% sequenceDiagram participant D as doctor-opencode.ts participant N as npm registry participant C as doctor-opencode-cache.ts participant FS as filesystem D->>N: "fetchNpmLatest("@cortexkit/magic-context")" D->>N: "fetchNpmLatest("@cortexkit/opencode-magic-context")" N-->>D: npmLatest (CLI) N-->>D: pluginNpmLatest (plugin, or null if offline) D->>C: "clearPluginCache({ force, latestVersion: pluginNpmLatest })" C->>FS: getOpenCodePluginCacheRoots() FS-->>C: existingRoots alt no cache found C-->>D: "{ action: not_found }" else "latestVersion=null and not forced" C-->>D: "{ action: check_unavailable }" else latestVersion provided C->>FS: readCachedPluginVersion(each root) FS-->>C: cached versions C->>C: "filter cached !== latestVersion" alt all entries up to date C-->>D: "{ action: up_to_date }" else stale or versionless entries C->>FS: rmSync(clearTargets) C-->>D: "{ action: cleared, paths }" end else "force=true" C->>FS: rmSync(all roots) C-->>D: "{ action: cleared }" endReviews (4): Last reviewed commit: "Fix offline plugin cache handling" | Re-trigger Greptile