@massa-ai/claude-plugin 1.25.0 → 1.26.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.
Files changed (89) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/agent-profiles/balanced/massa-ai-architecture-specialist.md +63 -0
  3. package/agent-profiles/balanced/massa-ai-audit-specialist.md +79 -0
  4. package/agent-profiles/balanced/massa-ai-builder.md +65 -0
  5. package/agent-profiles/balanced/massa-ai-context-curator.md +65 -0
  6. package/agent-profiles/balanced/massa-ai-documentation-agent.md +63 -0
  7. package/agent-profiles/balanced/massa-ai-furps-analyst.md +69 -0
  8. package/agent-profiles/balanced/massa-ai-investigator.md +66 -0
  9. package/agent-profiles/balanced/massa-ai-judge.md +100 -0
  10. package/agent-profiles/balanced/massa-ai-meta-judge.md +87 -0
  11. package/agent-profiles/balanced/massa-ai-mobile-specialist.md +80 -0
  12. package/agent-profiles/balanced/massa-ai-navigator.md +73 -0
  13. package/agent-profiles/balanced/massa-ai-plan-critic.md +88 -0
  14. package/agent-profiles/balanced/massa-ai-planner.md +63 -0
  15. package/agent-profiles/balanced/massa-ai-requirements-analyst.md +62 -0
  16. package/agent-profiles/balanced/massa-ai-reviewer.md +64 -0
  17. package/agent-profiles/balanced/massa-ai-test-engineer.md +64 -0
  18. package/agent-profiles/balanced/massa-ai-verification-agent.md +63 -0
  19. package/agent-profiles/cheap/massa-ai-architecture-specialist.md +63 -0
  20. package/agent-profiles/cheap/massa-ai-audit-specialist.md +79 -0
  21. package/agent-profiles/cheap/massa-ai-builder.md +65 -0
  22. package/agent-profiles/cheap/massa-ai-context-curator.md +65 -0
  23. package/agent-profiles/cheap/massa-ai-documentation-agent.md +63 -0
  24. package/agent-profiles/cheap/massa-ai-furps-analyst.md +69 -0
  25. package/agent-profiles/cheap/massa-ai-investigator.md +66 -0
  26. package/agent-profiles/cheap/massa-ai-judge.md +100 -0
  27. package/agent-profiles/cheap/massa-ai-meta-judge.md +87 -0
  28. package/agent-profiles/cheap/massa-ai-mobile-specialist.md +80 -0
  29. package/agent-profiles/cheap/massa-ai-navigator.md +73 -0
  30. package/agent-profiles/cheap/massa-ai-plan-critic.md +88 -0
  31. package/agent-profiles/cheap/massa-ai-planner.md +63 -0
  32. package/agent-profiles/cheap/massa-ai-requirements-analyst.md +62 -0
  33. package/agent-profiles/cheap/massa-ai-reviewer.md +64 -0
  34. package/agent-profiles/cheap/massa-ai-test-engineer.md +64 -0
  35. package/agent-profiles/cheap/massa-ai-verification-agent.md +63 -0
  36. package/agent-profiles/heavy/massa-ai-architecture-specialist.md +63 -0
  37. package/agent-profiles/heavy/massa-ai-audit-specialist.md +79 -0
  38. package/agent-profiles/heavy/massa-ai-builder.md +65 -0
  39. package/agent-profiles/heavy/massa-ai-context-curator.md +65 -0
  40. package/agent-profiles/heavy/massa-ai-documentation-agent.md +63 -0
  41. package/agent-profiles/heavy/massa-ai-furps-analyst.md +69 -0
  42. package/agent-profiles/heavy/massa-ai-investigator.md +66 -0
  43. package/agent-profiles/heavy/massa-ai-judge.md +100 -0
  44. package/agent-profiles/heavy/massa-ai-meta-judge.md +87 -0
  45. package/agent-profiles/heavy/massa-ai-mobile-specialist.md +80 -0
  46. package/agent-profiles/heavy/massa-ai-navigator.md +73 -0
  47. package/agent-profiles/heavy/massa-ai-plan-critic.md +88 -0
  48. package/agent-profiles/heavy/massa-ai-planner.md +63 -0
  49. package/agent-profiles/heavy/massa-ai-requirements-analyst.md +62 -0
  50. package/agent-profiles/heavy/massa-ai-reviewer.md +64 -0
  51. package/agent-profiles/heavy/massa-ai-test-engineer.md +64 -0
  52. package/agent-profiles/heavy/massa-ai-verification-agent.md +63 -0
  53. package/agent-profiles/home/massa-ai-architecture-specialist.md +63 -0
  54. package/agent-profiles/home/massa-ai-audit-specialist.md +79 -0
  55. package/agent-profiles/home/massa-ai-builder.md +65 -0
  56. package/agent-profiles/home/massa-ai-context-curator.md +65 -0
  57. package/agent-profiles/home/massa-ai-documentation-agent.md +63 -0
  58. package/agent-profiles/home/massa-ai-furps-analyst.md +69 -0
  59. package/agent-profiles/home/massa-ai-investigator.md +66 -0
  60. package/agent-profiles/home/massa-ai-judge.md +100 -0
  61. package/agent-profiles/home/massa-ai-meta-judge.md +87 -0
  62. package/agent-profiles/home/massa-ai-mobile-specialist.md +80 -0
  63. package/agent-profiles/home/massa-ai-navigator.md +73 -0
  64. package/agent-profiles/home/massa-ai-plan-critic.md +88 -0
  65. package/agent-profiles/home/massa-ai-planner.md +63 -0
  66. package/agent-profiles/home/massa-ai-requirements-analyst.md +62 -0
  67. package/agent-profiles/home/massa-ai-reviewer.md +64 -0
  68. package/agent-profiles/home/massa-ai-test-engineer.md +64 -0
  69. package/agent-profiles/home/massa-ai-verification-agent.md +63 -0
  70. package/agent-profiles/work/massa-ai-architecture-specialist.md +63 -0
  71. package/agent-profiles/work/massa-ai-audit-specialist.md +79 -0
  72. package/agent-profiles/work/massa-ai-builder.md +65 -0
  73. package/agent-profiles/work/massa-ai-context-curator.md +65 -0
  74. package/agent-profiles/work/massa-ai-documentation-agent.md +63 -0
  75. package/agent-profiles/work/massa-ai-furps-analyst.md +69 -0
  76. package/agent-profiles/work/massa-ai-investigator.md +66 -0
  77. package/agent-profiles/work/massa-ai-judge.md +100 -0
  78. package/agent-profiles/work/massa-ai-meta-judge.md +87 -0
  79. package/agent-profiles/work/massa-ai-mobile-specialist.md +80 -0
  80. package/agent-profiles/work/massa-ai-navigator.md +73 -0
  81. package/agent-profiles/work/massa-ai-plan-critic.md +88 -0
  82. package/agent-profiles/work/massa-ai-planner.md +63 -0
  83. package/agent-profiles/work/massa-ai-requirements-analyst.md +62 -0
  84. package/agent-profiles/work/massa-ai-reviewer.md +64 -0
  85. package/agent-profiles/work/massa-ai-test-engineer.md +64 -0
  86. package/agent-profiles/work/massa-ai-verification-agent.md +63 -0
  87. package/install.sh +103 -8
  88. package/package.json +2 -1
  89. package/skills/profile/SKILL.md +39 -0
package/install.sh CHANGED
@@ -84,6 +84,15 @@ HOOK_BIN="$SCRIPT_DIR/hooks/massa-ai-hook.ts"
84
84
  # for --project, so this resolves from $HOME, never from $SCOPE.
85
85
  PLUGIN_REGISTRY="$HOME/.claude/plugins/installed_plugins.json"
86
86
 
87
+ # Model-profile variant tree (T8, design Component 3 / MPS-04). Source is the
88
+ # bundle's per-profile agent-profiles/<p>/ (sibling of agents/, A5); dest is
89
+ # the engine's own host path table (packages/shared/src/profile-switch/
90
+ # hosts.ts): $TARGET/massa-ai/agent-profiles/<p>/. File-route only — the
91
+ # marketplace route serves agents in place and switching is refused there
92
+ # regardless (Component 2 topology rules), so there is nothing to install to.
93
+ VARIANTS_SRC="$SCRIPT_DIR/agent-profiles"
94
+ VARIANTS_DEST="$TARGET/massa-ai/agent-profiles"
95
+
87
96
  # The 5 Claude Code events → binary subcommands. The matcher-group entry shape:
88
97
  # { "hooks": [{ "type": "command", "command": "bun run \"<HOOK_BIN>\" <sub>" }],
89
98
  # "_massaAiOwned": true }
@@ -293,10 +302,22 @@ if (typeof data.platforms !== "object" || data.platforms === null || Array.isArr
293
302
  data.version = 2;
294
303
  const prev = data.platforms[host];
295
304
  data.platforms[host] = { root, skillsOwner: "plugin", skills: ["massa-ai", "persona-router"] };
296
- // The whole-record replace must not drop the plugin version record a previous
297
- // successful install wrote (R2) — re-attach it.
298
- if (prev && typeof prev === "object" && !Array.isArray(prev) && prev.plugin && typeof prev.plugin === "object") {
299
- data.platforms[host].plugin = prev.plugin;
305
+ // The whole-record replace must not drop fields a previous successful install
306
+ // wrote (R2) — re-attach them. modelProfile (T10, MPS-03 round-trip
307
+ // obligation) is engine-owned; installRoute is installer-owned but written by
308
+ // a LATER step of this same install (record_plugin_version) — both must
309
+ // survive this earlier whole-record replace or a switched profile / recorded
310
+ // route silently vanishes on the next skills-bundling pass.
311
+ if (prev && typeof prev === "object" && !Array.isArray(prev)) {
312
+ if (prev.plugin && typeof prev.plugin === "object") {
313
+ data.platforms[host].plugin = prev.plugin;
314
+ }
315
+ if (prev.modelProfile && typeof prev.modelProfile === "object") {
316
+ data.platforms[host].modelProfile = prev.modelProfile;
317
+ }
318
+ if (typeof prev.installRoute === "string") {
319
+ data.platforms[host].installRoute = prev.installRoute;
320
+ }
300
321
  }
301
322
  fs.mkdirSync(path.dirname(file), { recursive: true });
302
323
  fs.writeFileSync(file, JSON.stringify(data, null, 2) + "\n");
@@ -372,18 +393,24 @@ record_plugin_version() {
372
393
  return 0
373
394
  fi
374
395
 
375
- local version installed_at
396
+ local version installed_at route
376
397
  version="$(sed -n 's/.*"version"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' "$SCRIPT_DIR/package.json" | head -n 1)"
377
398
  installed_at="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
399
+ # installRoute (T8, design F1): installer-owned, engine-read-only. The
400
+ # marketplace route (register_claude_plugin succeeded) serves agents in
401
+ # place from the bundle; the file route copies them into $TARGET/agents.
402
+ # Written on EVERY install path — an absent field is what makes the switch
403
+ # engine refuse loud rather than guess (hosts.ts detectRoute).
404
+ if [[ "$PLUGIN_ROUTE" -eq 1 ]]; then route="marketplace"; else route="file"; fi
378
405
 
379
406
  # Tolerant of a corrupt/missing state file (rewrites a minimal valid one —
380
407
  # AC-8). A record-write failure warns but never fails the install: the next
381
408
  # run treats the host as unknown-version and reinstalls.
382
- "$runner" - "$HARNESS_STATE_FILE" "$HARNESS_HOST" "$TARGET" "$version" "$installed_at" <<'NODE' || \
409
+ "$runner" - "$HARNESS_STATE_FILE" "$HARNESS_HOST" "$TARGET" "$version" "$installed_at" "$route" <<'NODE' || \
383
410
  echo " ⚠ could not record the plugin version — next run will reinstall (unknown version)" >&2
384
411
  const fs = require("fs");
385
412
  const path = require("path");
386
- const [, , file, host, root, version, installedAt] = process.argv;
413
+ const [, , file, host, root, version, installedAt, installRoute] = process.argv;
387
414
  let data = { version: 2, platforms: {} };
388
415
  try {
389
416
  const existing = JSON.parse(fs.readFileSync(file, "utf8"));
@@ -400,12 +427,54 @@ const rec =
400
427
  ? data.platforms[host]
401
428
  : { root, skillsOwner: "plugin", skills: [] };
402
429
  rec.plugin = { version, installedAt };
430
+ // installRoute is installer-owned (like plugin above); modelProfile is NEVER
431
+ // written here — the switch engine (packages/shared/src/profile-switch/) is
432
+ // its sole writer, and this installer only ever reads it (see
433
+ // apply_recorded_profile below).
434
+ rec.installRoute = installRoute;
403
435
  data.platforms[host] = rec;
404
436
  fs.mkdirSync(path.dirname(file), { recursive: true });
405
437
  fs.writeFileSync(file, JSON.stringify(data, null, 2) + "\n");
406
438
  NODE
407
439
  }
408
440
 
441
+ # ── Model-profile variant tree + recorded-profile re-apply (T8, MPS-04) ─────
442
+ # Read-side only: this installer never writes platforms[host].modelProfile —
443
+ # see the comment above record_plugin_version's NODE block. It only (a)
444
+ # refreshes the on-disk variant tree so an offline switch has files to copy
445
+ # from, and (b) re-applies a previously recorded profile's active agent set on
446
+ # install/upgrade, so a plugin upgrade never silently reverts a switched
447
+ # profile back to the shipped default.
448
+ install_variant_tree() {
449
+ [[ -d "$VARIANTS_SRC" ]] || return 0
450
+ rm -rf "$VARIANTS_DEST"
451
+ mkdir -p "$VARIANTS_DEST"
452
+ cp -R "$VARIANTS_SRC/." "$VARIANTS_DEST/"
453
+ vecho " + model-profile variant tree refreshed at $VARIANTS_DEST"
454
+ }
455
+
456
+ # Prints the recorded profile name (platforms[claude].modelProfile.profile),
457
+ # or an empty string when unset/unreadable. Never throws — a corrupt or
458
+ # missing state file just means "no recorded profile", not an install failure.
459
+ recorded_profile() {
460
+ local runner="$1"
461
+ "$runner" - "$HARNESS_STATE_FILE" "$HARNESS_HOST" <<'NODE'
462
+ const fs = require("fs");
463
+ const [, , file, host] = process.argv;
464
+ try {
465
+ const data = JSON.parse(fs.readFileSync(file, "utf8"));
466
+ const rec = data && data.platforms && data.platforms[host];
467
+ const profile =
468
+ rec && rec.modelProfile && typeof rec.modelProfile.profile === "string"
469
+ ? rec.modelProfile.profile
470
+ : "";
471
+ process.stdout.write(profile);
472
+ } catch {
473
+ process.stdout.write("");
474
+ }
475
+ NODE
476
+ }
477
+
409
478
  # ── Plugin-registry registration (delegated to the claude CLI) ──────────────
410
479
  # The CLI owns the registry format, so it is the only supported way to make the
411
480
  # plugin appear in /plugin. Every failure path returns non-zero and the caller
@@ -541,7 +610,31 @@ else
541
610
 
542
611
  # Subagent specialists (generated from skills/agents/*/SKILL.md, navigator
543
612
  # included). The massa-ai- name prefix is the ownership marker used by uninstall.
544
- for src in "$SCRIPT_DIR/agents/"massa-ai-*.md; do
613
+ #
614
+ # Model-profile re-apply (T8, MPS-04): if a switch previously recorded a
615
+ # profile for this host, and the bundle ships that profile's variant, the
616
+ # ACTIVE set comes from agent-profiles/<profile>/ instead of the shipped
617
+ # default — an upgrade must never silently revert a switched profile.
618
+ # Recorded-but-missing-from-bundle is a loud fallback to the default, never
619
+ # a silent one.
620
+ ACTIVE_AGENTS_SRC="$SCRIPT_DIR/agents"
621
+ json_runner=""
622
+ if command -v node &>/dev/null; then json_runner="node"
623
+ elif command -v bun &>/dev/null; then json_runner="bun"
624
+ fi
625
+ if [[ -n "$json_runner" ]]; then
626
+ RECORDED_PROFILE="$(recorded_profile "$json_runner")"
627
+ if [[ -n "$RECORDED_PROFILE" ]]; then
628
+ if [[ -d "$VARIANTS_SRC/$RECORDED_PROFILE" ]]; then
629
+ ACTIVE_AGENTS_SRC="$VARIANTS_SRC/$RECORDED_PROFILE"
630
+ echo " ↷ re-applying recorded model profile '$RECORDED_PROFILE'"
631
+ else
632
+ echo " ⚠ recorded model profile '$RECORDED_PROFILE' is not in this bundle — falling back to the default profile" >&2
633
+ fi
634
+ fi
635
+ fi
636
+
637
+ for src in "$ACTIVE_AGENTS_SRC/"massa-ai-*.md; do
545
638
  [[ -f "$src" ]] || continue
546
639
  name="$(basename "$src")"
547
640
  cp "$src" "$TARGET/agents/$name"
@@ -549,6 +642,8 @@ else
549
642
  specialist_count=$((specialist_count + 1))
550
643
  done
551
644
  vecho " + ${specialist_count} subagent specialists (generated from skills/agents/*/SKILL.md)"
645
+
646
+ install_variant_tree
552
647
  fi
553
648
 
554
649
  # Skills bundling (PDO-08, 09): install massa-ai/persona-router into the
package/package.json CHANGED
@@ -1,9 +1,10 @@
1
1
  {
2
2
  "name": "@massa-ai/claude-plugin",
3
- "version": "1.25.0",
3
+ "version": "1.26.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",
7
+ "agent-profiles",
7
8
  "commands",
8
9
  "hooks",
9
10
  "!hooks/__tests__",
@@ -0,0 +1,39 @@
1
+ ---
2
+ name: profile
3
+ description: Switch the installed massa-ai agents to a registry model profile (e.g. "work", "cheap", "home") or report the currently active profile per host. Use when the user asks to change/switch the model profile, asks which models the agents currently use, or asks to preview a profile switch. Do NOT use for editing the model registry itself (a registry edit is a massa-ai repository change, not a runtime switch) and do NOT claim the new profile is active before the user restarts the host session.
4
+ license: MIT
5
+ metadata:
6
+ author: Luiz Massa
7
+ version: 1.0.0
8
+ ---
9
+
10
+ # Profile Switch Skill
11
+
12
+ ## Mission
13
+ Drive the one massa-ai model-profile switch engine and relay its report — never a second implementation.
14
+
15
+ ## When To Use
16
+ - The user asks to switch, change, or set the model profile (by name, e.g. "work", "cheap", "home", "balanced").
17
+ - The user asks what profile is currently active, or which profiles are shipped.
18
+ - The user asks to preview a switch without applying it.
19
+
20
+ ## How To Drive It
21
+ There is exactly one switch implementation (`@massa-ai/shared`'s switch engine); every front — this skill, the MCP tools, and both `massa-ai-config` CLIs — calls the same engine and returns the same per-host report shape. Prefer whichever front is already available in the session:
22
+
23
+ - **MCP tools** (preferred when the massa-ai MCP server is connected): call `profile_list` to report shipped profiles + per-host active profile + bundle version, and `profile_set` to switch (`{profile, host?, dryRun?}`).
24
+ - **CLI fallback**: `massa-ai-config profile list` / `massa-ai-config profile show` / `massa-ai-config profile set <name> [--host <h>] [--dry-run]`.
25
+
26
+ Default to a dry run first when the user has not explicitly asked to apply the switch immediately — `dryRun: true` (MCP) or `--dry-run` (CLI) previews the per-host plan and changes nothing.
27
+
28
+ ## Relaying The Result
29
+ Always relay the per-host outcome and the restart notice verbatim in substance, not just "done":
30
+
31
+ - Report each host as switched / skipped (with its reason) / unsupported (with its reason) / failed (with its reason). Cursor is always reported skipped — every tier resolves to inherit, so switching it is a no-op by design, not an error.
32
+ - When at least one host switched (non-dry-run), state explicitly that a session restart of that host is required before the new models take effect — hosts load agent definitions at session start; there is no live in-session switch.
33
+ - On a dry run, say so and that no files changed.
34
+ - On a fully failed request (e.g. unknown profile name), relay the named error and the list of profiles the report says are actually available — never guess a profile name.
35
+
36
+ ## Restrictions
37
+ - Never invent a profile name; only use names the engine's own report lists as shipped/available.
38
+ - Never claim a profile switch is "live" before the affected host's session restarts.
39
+ - Never edit the model-profile registry (`skills/model-profiles.json`) to satisfy a switch request — that is a build-time registry change owned by a different workflow, not a runtime switch.