@massa-ai/claude-plugin 1.46.0 → 1.47.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "massa-ai",
3
- "version": "1.46.0",
3
+ "version": "1.47.0",
4
4
  "description": "massa-ai — semantic code search, durable memory, symbol graph, and context compression",
5
5
  "author": {
6
6
  "name": "Luiz Massa",
package/install.sh CHANGED
@@ -528,6 +528,89 @@ try {
528
528
  NODE
529
529
  }
530
530
 
531
+ # ── Marketplace install-path resolution (T19, CPP-07) ───────────────────────
532
+ # Mirrors packages/shared/src/profile-switch/claude-marketplace.ts's
533
+ # resolveClaudeMarketplaceRoot exactly (same selection rule: scope:"user"
534
+ # preferred, then most recent lastUpdated, then last entry in array order;
535
+ # require the resolved installPath to exist on disk) so the shell installer
536
+ # and the TS switch engine agree on which cache directory is "current".
537
+ # Never caches — the path is version pinned and moves on every
538
+ # `claude plugin update`. Prints the resolved installPath, or "" when
539
+ # unresolvable (absent/corrupt registry, no record, or a path that doesn't
540
+ # exist on disk). Never throws.
541
+ resolve_claude_install_path() {
542
+ local runner="$1"
543
+ "$runner" - "$PLUGIN_REGISTRY" "$PLUGIN_ID" <<'NODE'
544
+ const fs = require("fs");
545
+ const [, , file, id] = process.argv;
546
+ try {
547
+ const data = JSON.parse(fs.readFileSync(file, "utf8"));
548
+ const records = data && data.plugins ? data.plugins[id] : null;
549
+ if (!Array.isArray(records) || records.length === 0) process.exit(0);
550
+ const userScoped = records.filter((r) => r && r.scope === "user");
551
+ const pool = userScoped.length > 0 ? userScoped : records;
552
+ let best;
553
+ let bestTime = -Infinity;
554
+ for (const record of pool) {
555
+ const parsed = record && record.lastUpdated ? Date.parse(record.lastUpdated) : NaN;
556
+ if (Number.isFinite(parsed) && parsed >= bestTime) {
557
+ best = record;
558
+ bestTime = parsed;
559
+ }
560
+ }
561
+ const selected = best || pool[pool.length - 1];
562
+ const installPath = selected && selected.installPath;
563
+ if (!installPath) process.exit(0);
564
+ if (!fs.existsSync(installPath)) process.exit(0);
565
+ process.stdout.write(installPath);
566
+ } catch { /* unresolvable — absent file, unreadable file, unparseable JSON */ }
567
+ NODE
568
+ }
569
+
570
+ # Re-applies the recorded model profile to the marketplace install root after
571
+ # a `claude plugin update` succeeds (CPP-07). AD-015 (read-only): this
572
+ # function, like recorded_profile above, NEVER writes
573
+ # platforms.claude.modelProfile — the switch engine
574
+ # (packages/shared/src/profile-switch/) is its sole writer. An update moves
575
+ # installPath to a new version-pinned cache directory, whose agents/ ships
576
+ # the bundle's DEFAULT profile; without this re-apply step a switched
577
+ # operator would silently revert to that default on every update (context.md
578
+ # finding #4). Every failure path is a logged no-op, never a failure — a
579
+ # missing recorded profile, an unresolvable install path, or a profile the
580
+ # new bundle doesn't ship under agent-profiles/ all mean "nothing to
581
+ # re-apply", not an install error.
582
+ apply_recorded_profile_after_update() {
583
+ local runner="$1"
584
+ local install_path profile variant_dir copied=0 f name
585
+ install_path="$(resolve_claude_install_path "$runner")"
586
+ if [[ -z "$install_path" ]]; then
587
+ vecho " ↷ no resolvable marketplace install path — skipping recorded-profile re-apply"
588
+ return 0
589
+ fi
590
+ profile="$(recorded_profile "$runner")"
591
+ if [[ -z "$profile" ]]; then
592
+ vecho " ↷ no recorded model profile for claude — skipping recorded-profile re-apply"
593
+ return 0
594
+ fi
595
+ variant_dir="$install_path/agent-profiles/$profile"
596
+ if [[ ! -d "$variant_dir" ]]; then
597
+ echo " ⚠ recorded model profile '$profile' is not available under the updated bundle at $install_path — leaving its default agents in place" >&2
598
+ return 0
599
+ fi
600
+ mkdir -p "$install_path/agents"
601
+ for f in "$variant_dir/"massa-ai-*.md; do
602
+ [[ -f "$f" ]] || continue
603
+ name="$(basename "$f")"
604
+ cp "$f" "$install_path/agents/$name"
605
+ copied=$((copied + 1))
606
+ done
607
+ if [[ "$copied" -gt 0 ]]; then
608
+ vecho " ↷ re-applied recorded model profile '$profile' (${copied} files) to $install_path/agents"
609
+ else
610
+ vecho " ↷ recorded model profile '$profile' variant directory has no massa-ai-*.md files — nothing to re-apply"
611
+ fi
612
+ }
613
+
531
614
  # ── Plugin-registry registration (delegated to the claude CLI) ──────────────
532
615
  # The CLI owns the registry format, so it is the only supported way to make the
533
616
  # plugin appear in /plugin. Every failure path returns non-zero and the caller
@@ -623,6 +706,10 @@ refresh_marketplace_cache() {
623
706
  if installer_host_cli_supports claude plugin update; then
624
707
  if claude plugin update "$PLUGIN_ID" </dev/null >/dev/null 2>&1; then
625
708
  vecho " + refreshed marketplace cache: ${served} → ${bundle}"
709
+ # CPP-07: an update just moved installPath to a new version-pinned
710
+ # cache directory; re-apply any previously recorded model profile
711
+ # before it silently reverts to the new bundle's default agents.
712
+ apply_recorded_profile_after_update "$runner"
626
713
  else
627
714
  echo " ⚠ 'claude plugin update ${PLUGIN_ID}' failed — Claude keeps serving ${served}; re-run the installer or run the update manually" >&2
628
715
  fi
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@massa-ai/claude-plugin",
3
- "version": "1.46.0",
3
+ "version": "1.47.0",
4
4
  "description": "massa-ai plugin for Claude Code — semantic code search, durable memory, symbol graph, and context compression",
5
5
  "files": [
6
6
  "agents",