fix(claude-mem-heal): create legacy marketplace junction/symlink (BUG-012)#70
Merged
Merged
Conversation
…-012)
The thedotmack/claude-mem plugin's bundled hooks.json hardcodes the fallback
discovery path `marketplaces/thedotmack/plugin/scripts/...` (the marketplace's
declared `name`), but Claude Code clones the marketplace under the GitHub repo
name `marketplaces/thedotmack-claude-mem/`. When CLAUDE_PLUGIN_ROOT is unset or
stale (the typical Windows case where the plugin cache stays unpopulated),
plugin hooks fall through to that path and fail with `claude-mem: plugin
scripts not found` -> exit 1, blocking UserPromptSubmit. On Windows the
visible symptom is `printf: write error: Permission denied` (Git Bash + hook
subprocess sandbox quirk); on Linux it would fail more cleanly with the
not-found message.
Same root cause silently neuters scripts/claude-mem-heal.{sh,ps1}: both
hardcoded `marketplaces/thedotmack/plugin` -> dir absent -> heal no-ops.
Upstream .mcp.json / missing-zod patches never reach the actual install.
Fix (both heal scripts):
- New ensure_marketplace_compat_symlink() / Repair-MarketplaceCompatJunction
function. Creates symlink (Linux) / Junction (Windows, no admin) from
`marketplaces/thedotmack` -> `marketplaces/thedotmack-claude-mem` when the
source exists and the target is absent. Idempotent: skip otherwise.
- Extend marketplace healing walks to cover both legacy and current path
variants (path-aware backstop in case junction creation fails).
- Bats parity assertions in tests/setup-{linux,windows}.bats lock the
junction-creation block in both heal scripts.
Empirically validated on Windows: junction created on first run (LinkType
= Junction, Target = thedotmack-claude-mem), silent on second run (exit 0,
no output) -- contract preserved. Linux side: bash -n + manual review only;
no Linux test machine available this session.
Specs: specs/BUG-012-claude-mem-marketplace-junction/{proposal,tasks,verification}.md
Discovered during BUG-011 hook-failure diagnosis. Sibling of PR #69.
Co-Authored-By: Claude Opus 4.7 <[email protected]>
Two failures in CI test job for PR #70: 1. `grep -qF '-ItemType Junction'` -> GNU grep parses `-ItemType` as flag set before checking the pattern. Fix: add `--` separator before the pattern. Same convention used by the existing `--ignore-scripts` assert above. 2. `grep -B2 -A6 'ln -s.*thedotmack-claude-mem'` -> the literal `ln -s` line in claude-mem-heal.sh is `ln -s "$actual" "$legacy"` (no marketplace name on that line; the name is in the earlier variable assignment). The regex never matched, so `-B2 -A6` returned empty and the piped grep failed. Rewrite to grep the actual guard expressions: `[ ! -d "$actual" ]` (source-exists check) and `[ -e "$legacy" ]` (target-absent check) -- both required for the idempotence contract. All four patterns verified locally against the heal scripts. Co-Authored-By: Claude Opus 4.7 <[email protected]>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
thedotmack/claude-memplugin's bundledhooks.jsonhardcodes the fallback discovery pathmarketplaces/thedotmack/plugin/scripts/...(the marketplace's declaredname), but Claude Code clones the marketplace under the GitHub repo namemarketplaces/thedotmack-claude-mem/. WhenCLAUDE_PLUGIN_ROOTis unset/stale (typical Windows case — plugin cache stays unpopulated), plugin hooks hit the broken fallback,exit 1, and block UserPromptSubmit.scripts/claude-mem-heal.{sh,ps1}— both hardcodedmarketplaces/thedotmack/plugin, no-op'd on dir-absent, never applied upstream.mcp.json/ missing-zod patches to the actual install.marketplaces/thedotmack→marketplaces/thedotmack-claude-memwhen the source exists and target is absent. Heal walks extended to cover both legacy and current marketplace paths.Why this bug only surfaced on Windows
On Linux, Claude Code typically injects
CLAUDE_PLUGIN_ROOTcorrectly at hook invocation, so the broken fallback is never consulted. On Windows the plugin cache (cache/thedotmack/claude-mem/) stays empty, the env var stays unset or stale, and the fallback IS consulted — landing on the non-existentmarketplaces/thedotmack/plugin/. The visible Windows symptom (printf: write error: Permission denied) is Git Bash + Claude Code's hook subprocess sandbox quirk; the underlyingexit 1is cross-OS. Fix applied to both heal scripts for parity.Empirical validation (Windows)
Second run is silent (exit 0, no output) —
silent-on-healthycontract preserved.Test plan
tests/setup-linux.bats+ 2 intests/setup-windows.bats.shellcheck --severity=error scripts/claude-mem-heal.shclean.pwsh -Command "Invoke-ScriptAnalyzer -Path scripts/claude-mem-heal.ps1 -Severity Error"clean (locally: clean).bash -n scripts/claude-mem-heal.shclean (locally: clean).claude-mem-heal.ps1(locally: clean).Discovered during
BUG-011 hook-failure diagnosis (PR #69). Sibling fix — same plugin, different layer.
Spec
specs/BUG-012-claude-mem-marketplace-junction/{proposal,tasks,verification}.md