@massa-ai/cursor-plugin 1.27.0 → 1.30.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,5 +1,5 @@
1
1
  {
2
2
  "name": "massa-ai",
3
- "version": "1.27.0",
3
+ "version": "1.30.0",
4
4
  "description": "massa-ai — semantic code search, memory, and context compression for Cursor"
5
5
  }
package/README.md CHANGED
@@ -62,7 +62,7 @@ If you are building a VS Code extension for Cursor, you can register the plugin
62
62
  vscode.cursor.plugins.registerPath("/abs/path/to/apps/cursor-plugin");
63
63
  ```
64
64
 
65
- Cursor auto-discovers `skills/`, `hooks/hooks.json`, and `agents/` inside the registered directory. MCP is not bundled — Cursor reads `~/.cursor/mcp.json`, which `scripts/install-agents.sh` owns. The `.cursor-plugin/plugin.json` manifest is optional — Cursor discovers the subdirectories without it, but including one aids marketplace submission later.
65
+ Cursor 3.14 loads user-local plugins from `~/.cursor/plugins/local/<name>/` and also bridges Claude marketplace plugins from `~/.claude`, but subagents are discovered only from the flat `~/.cursor/agents/*.md` (or project `.cursor/agents/`) directory — never from a plugin's `agents/` subtree. `install.sh` therefore copies the specialists to `~/.cursor/agents/`; `hooks/hooks.json` entries are merged into `~/.cursor/hooks.json` pointing at the installed hook binary. Cursor reads no global rules file: the AGENTS.md bootstrap must be pasted into Cursor Settings → Rules or provided per project root. MCP is not bundled — Cursor reads `~/.cursor/mcp.json`, which `scripts/install-agents.sh` owns. The `.cursor-plugin/plugin.json` manifest is optional — Cursor discovers the subdirectories without it, but including one aids marketplace submission later.
66
66
 
67
67
  Use `unregisterPath` to remove:
68
68
 
@@ -1,8 +1,7 @@
1
1
  ---
2
2
  name: massa-ai-judge
3
- description: Read-only debate-panel evaluator for judge-with-debate. Score an artifact against the meta-judge's evaluation specification with quoted evidence, then defend or revise scores across up to 3 debate rounds until the panel reaches consensus. Writes only its own judge-N report file per dispatch. Never judges outside the specification, never revises without quoted evidence.
3
+ description: Debate-panel evaluator for judge-with-debate. Score an artifact against the meta-judge's evaluation specification with quoted evidence, then defend or revise scores across up to 3 debate rounds until the panel reaches consensus. Writes only its own judge-N report file per dispatch. Never judges outside the specification, never revises without quoted evidence.
4
4
  model: inherit
5
- readonly: true
6
5
  ---
7
6
  # Judge Agent Skill
8
7
 
@@ -1,8 +1,7 @@
1
1
  ---
2
2
  name: massa-ai-judge
3
- description: Read-only debate-panel evaluator for judge-with-debate. Score an artifact against the meta-judge's evaluation specification with quoted evidence, then defend or revise scores across up to 3 debate rounds until the panel reaches consensus. Writes only its own judge-N report file per dispatch. Never judges outside the specification, never revises without quoted evidence.
3
+ description: Debate-panel evaluator for judge-with-debate. Score an artifact against the meta-judge's evaluation specification with quoted evidence, then defend or revise scores across up to 3 debate rounds until the panel reaches consensus. Writes only its own judge-N report file per dispatch. Never judges outside the specification, never revises without quoted evidence.
4
4
  model: inherit
5
- readonly: true
6
5
  ---
7
6
  # Judge Agent Skill
8
7
 
@@ -1,8 +1,7 @@
1
1
  ---
2
2
  name: massa-ai-judge
3
- description: Read-only debate-panel evaluator for judge-with-debate. Score an artifact against the meta-judge's evaluation specification with quoted evidence, then defend or revise scores across up to 3 debate rounds until the panel reaches consensus. Writes only its own judge-N report file per dispatch. Never judges outside the specification, never revises without quoted evidence.
3
+ description: Debate-panel evaluator for judge-with-debate. Score an artifact against the meta-judge's evaluation specification with quoted evidence, then defend or revise scores across up to 3 debate rounds until the panel reaches consensus. Writes only its own judge-N report file per dispatch. Never judges outside the specification, never revises without quoted evidence.
4
4
  model: inherit
5
- readonly: true
6
5
  ---
7
6
  # Judge Agent Skill
8
7
 
@@ -1,8 +1,7 @@
1
1
  ---
2
2
  name: massa-ai-judge
3
- description: Read-only debate-panel evaluator for judge-with-debate. Score an artifact against the meta-judge's evaluation specification with quoted evidence, then defend or revise scores across up to 3 debate rounds until the panel reaches consensus. Writes only its own judge-N report file per dispatch. Never judges outside the specification, never revises without quoted evidence.
3
+ description: Debate-panel evaluator for judge-with-debate. Score an artifact against the meta-judge's evaluation specification with quoted evidence, then defend or revise scores across up to 3 debate rounds until the panel reaches consensus. Writes only its own judge-N report file per dispatch. Never judges outside the specification, never revises without quoted evidence.
4
4
  model: inherit
5
- readonly: true
6
5
  ---
7
6
  # Judge Agent Skill
8
7
 
@@ -1,8 +1,7 @@
1
1
  ---
2
2
  name: massa-ai-judge
3
- description: Read-only debate-panel evaluator for judge-with-debate. Score an artifact against the meta-judge's evaluation specification with quoted evidence, then defend or revise scores across up to 3 debate rounds until the panel reaches consensus. Writes only its own judge-N report file per dispatch. Never judges outside the specification, never revises without quoted evidence.
3
+ description: Debate-panel evaluator for judge-with-debate. Score an artifact against the meta-judge's evaluation specification with quoted evidence, then defend or revise scores across up to 3 debate rounds until the panel reaches consensus. Writes only its own judge-N report file per dispatch. Never judges outside the specification, never revises without quoted evidence.
4
4
  model: inherit
5
- readonly: true
6
5
  ---
7
6
  # Judge Agent Skill
8
7
 
@@ -1,8 +1,7 @@
1
1
  ---
2
2
  name: massa-ai-judge
3
- description: Read-only debate-panel evaluator for judge-with-debate. Score an artifact against the meta-judge's evaluation specification with quoted evidence, then defend or revise scores across up to 3 debate rounds until the panel reaches consensus. Writes only its own judge-N report file per dispatch. Never judges outside the specification, never revises without quoted evidence.
3
+ description: Debate-panel evaluator for judge-with-debate. Score an artifact against the meta-judge's evaluation specification with quoted evidence, then defend or revise scores across up to 3 debate rounds until the panel reaches consensus. Writes only its own judge-N report file per dispatch. Never judges outside the specification, never revises without quoted evidence.
4
4
  model: inherit
5
- readonly: true
6
5
  ---
7
6
  # Judge Agent Skill
8
7
 
package/install.sh CHANGED
@@ -11,8 +11,19 @@
11
11
  # MCP registration is delegated to scripts/install-agents.sh, the single writer
12
12
  # of host MCP config. This installer no longer ships a plugin-local mcp.json.
13
13
  #
14
+ # Cursor 3.14 also bridges the Claude marketplace registry from ~/.claude and
15
+ # loads any plugin listed there IN ADDITION to a local install — a machine
16
+ # with both would load massa-ai twice and fire every hook twice (AD-017). At
17
+ # USER scope, this installer prefers the bridge: when ~/.claude lists massa-ai
18
+ # as installed and enabled, it skips its own local plugin copy and hook
19
+ # wiring (removing a pre-existing local copy so one run converges), while
20
+ # still writing the flat subagents, harness skills, and MCP registration this
21
+ # installer always owns. Project-scope installs are unaffected — ~/.claude is
22
+ # a user surface, never a project one.
23
+ #
14
24
  # Idempotent: re-running is a no-op when owned entries already present.
15
- # Uninstall removes only ownership-marked entries + the plugin directory.
25
+ # Uninstall removes only ownership-marked entries + the plugin directory,
26
+ # regardless of which route (bridge or local) installed them.
16
27
  #
17
28
  # Usage:
18
29
  # apps/cursor-plugin/install.sh # install at user scope (~/.cursor)
@@ -51,26 +62,121 @@ done
51
62
  source "$SCRIPT_DIR/../../scripts/banner.sh"
52
63
  massa_ai_banner
53
64
 
65
+ # ── Generated-bundle contract (T7, design Component 4 / UGB-05..07) ─────────
66
+ # Why: apps/*-plugin generated subtrees (skills/, agents/, agent-profiles/,
67
+ # hooks/massa-ai-hook, lib/opencode-config.cjs) are gitignored build
68
+ # output (UGB-01) — a repo checkout must regenerate them before this
69
+ # installer copies or registers anything; a published tarball ships them
70
+ # pre-generated and has no generator sources to run at all. Runs before
71
+ # any host-config mutation (before CURSOR_DIR resolution below). Cursor
72
+ # has no PLUGIN_SOURCE_ROOT (no marketplace registration path), so
73
+ # REPO_ROOT — already the checkout root this script lives in — is the
74
+ # detection root, exactly mirroring $SCRIPT_DIR/../.. for the other hosts.
75
+ # Impacts: UGB-05 checkout generates, UGB-06 tarball skips, UGB-07 loud
76
+ # failure before mutation, UGB-08 (skip-env honored for harness runs).
77
+ # Test: apps/cursor-plugin/__tests__/install.test.ts (skip-branch + loud-failure cases)
78
+ if [[ -f "$REPO_ROOT/scripts/generate-skill-artifacts.ts" ]]; then
79
+ if [[ "${MASSA_AI_SKIP_ARTIFACT_GENERATION:-0}" != "1" ]]; then
80
+ if ! command -v bun &>/dev/null; then
81
+ echo "Error: bun required to generate plugin bundles in a repo checkout (scripts/generate-*.ts)" >&2
82
+ exit 3
83
+ fi
84
+ bun "$REPO_ROOT/scripts/generate-skill-artifacts.ts"
85
+ bun "$REPO_ROOT/scripts/generate-subagent-artifacts.ts"
86
+ fi
87
+ fi
88
+ # Tarball installs (generator sources absent) skip the block above entirely
89
+ # and fall straight through to this sentinel, which every context must pass:
90
+ # the bundle this installer is about to copy/register has to actually exist.
91
+ if [[ ! -f "$SCRIPT_DIR/skills/massa-ai/SKILL.md" ]]; then
92
+ echo "Error: missing $SCRIPT_DIR/skills/massa-ai/SKILL.md — run 'bun run generate:artifacts' first" >&2
93
+ exit 1
94
+ fi
95
+ if [[ ! -d "$SCRIPT_DIR/agents" ]] || [[ -z "$(ls -A "$SCRIPT_DIR/agents" 2>/dev/null)" ]]; then
96
+ echo "Error: missing or empty $SCRIPT_DIR/agents — run 'bun run generate:artifacts' first" >&2
97
+ exit 1
98
+ fi
99
+
54
100
  # Resolve target base dir
55
101
  if [[ "$SCOPE" == "project" ]]; then
56
102
  CURSOR_DIR="$(pwd)/.cursor"
57
103
  else
58
104
  CURSOR_DIR="$HOME/.cursor"
59
105
  fi
60
- # Cursor discovers locally-installed plugins under plugins/local/<name>/, not
61
- # plugins/<name>/. Installing to the latter is why massa-ai never appeared in
62
- # Cursor's plugin list even though every file was written correctly.
63
- #
64
- # UNVERIFIED against a running Cursor.app — this path comes from Cursor's
65
- # plugin documentation, not from an observed load, because Cursor is not
66
- # installed on the machine this was developed on. Treat it as lower confidence
67
- # than the Claude/Codex routes, which were verified end-to-end.
106
+ # Two verified Cursor 3.14 load surfaces (observed live in "Cursor Plugins"
107
+ # exthost logs, 2026-08-05): user-local plugins ARE loaded from
108
+ # plugins/local/<name>/ ("loadUserLocalPlugin massa-ai loaded"), and Cursor
109
+ # additionally bridges Claude marketplace plugins from ~/.claude
110
+ # ("loadClaudePlugin massa-ai@massa-ai") — so a machine with the Claude
111
+ # plugin installed loads massa-ai twice. Subagents, however, are discovered
112
+ # only from the flat .cursor/agents/*.md directory (cursor.com/docs/subagents
113
+ # — no subdirectories), and there is no global rules file. So: PLUGIN_DIR
114
+ # carries the manifest, hook binary, and command skills; everything else
115
+ # Cursor must SEE goes to its dedicated read paths — $CURSOR_AGENTS_DIR
116
+ # (subagents), $CURSOR_DIR/skills/ (harness skills), $CURSOR_DIR/hooks.json,
117
+ # and $CURSOR_DIR/mcp.json (install-agents.sh).
68
118
  PLUGIN_DIR="$CURSOR_DIR/plugins/local/massa-ai"
119
+ # The only directory Cursor discovers subagents from (project scope:
120
+ # ./.cursor/agents/). Flat .md files, real copies, massa-ai- prefix owned.
121
+ CURSOR_AGENTS_DIR="$CURSOR_DIR/agents"
69
122
  # Pre-fix installs wrote here; removed on install so the two cannot both be
70
123
  # discovered and register duplicate hooks.
71
124
  LEGACY_PLUGIN_DIR="$CURSOR_DIR/plugins/massa-ai"
72
125
  HOOKS_JSON="$CURSOR_DIR/hooks.json"
73
126
 
127
+ # ── Claude-bridge detection (PAU-08/09/10) ──────────────────────────────────
128
+ # Probe contract pinned against a read-only capture of this machine's live
129
+ # ~/.claude registry files (2026-08-05) — never invented:
130
+ # - $CLAUDE_PLUGIN_REGISTRY must parse and list a non-empty
131
+ # plugins["massa-ai@massa-ai"] array
132
+ # - $CLAUDE_SETTINGS_JSON's enabledPlugins["massa-ai@massa-ai"] must not be
133
+ # literal false — an absent settings.json, or an absent key, is treated
134
+ # as enabled (matching Claude's own default)
135
+ # - any parse failure on either file → NOT detected (local fallback)
136
+ # User-scope only: ~/.claude is a per-user surface, so a --project plugin
137
+ # install always keeps the local branch regardless of what ~/.claude holds.
138
+ CLAUDE_PLUGIN_REGISTRY="$HOME/.claude/plugins/installed_plugins.json"
139
+ CLAUDE_SETTINGS_JSON="$HOME/.claude/settings.json"
140
+
141
+ claude_bridge_detected() {
142
+ [[ "$SCOPE" == "project" ]] && return 1
143
+ [[ -f "$CLAUDE_PLUGIN_REGISTRY" ]] || return 1
144
+
145
+ local runner=""
146
+ if command -v node &>/dev/null; then runner="node"
147
+ elif command -v bun &>/dev/null; then runner="bun"
148
+ else return 1
149
+ fi
150
+
151
+ "$runner" - "$CLAUDE_PLUGIN_REGISTRY" "$CLAUDE_SETTINGS_JSON" <<'NODE'
152
+ const fs = require("fs");
153
+ const [, , registryFile, settingsFile] = process.argv;
154
+
155
+ try {
156
+ const registry = JSON.parse(fs.readFileSync(registryFile, "utf8"));
157
+ const listed = registry && registry.plugins && registry.plugins["massa-ai@massa-ai"];
158
+ if (!Array.isArray(listed) || listed.length === 0) process.exit(1);
159
+ } catch {
160
+ process.exit(1);
161
+ }
162
+
163
+ try {
164
+ const raw = fs.readFileSync(settingsFile, "utf8");
165
+ if (raw.trim()) {
166
+ const settings = JSON.parse(raw);
167
+ const enabled = settings && settings.enabledPlugins && settings.enabledPlugins["massa-ai@massa-ai"];
168
+ if (enabled === false) process.exit(1);
169
+ }
170
+ } catch (e) {
171
+ // Absent settings.json is treated as enabled (Claude's own default); any
172
+ // other read/parse failure means the probe cannot trust this surface.
173
+ if (e.code !== "ENOENT") process.exit(1);
174
+ }
175
+
176
+ process.exit(0);
177
+ NODE
178
+ }
179
+
74
180
  # The 7 Cursor events → binary subcommands. The command path uses the
75
181
  # INSTALLED plugin dir (not the placeholder), so Cursor invokes the copy.
76
182
  # Cursor hooks.json shape: { "version": 1, "hooks": { "<event>": [...] } }
@@ -342,13 +448,15 @@ record_plugin_version() {
342
448
  local version installed_at route
343
449
  version="$(sed -n 's/.*"version"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' "$SCRIPT_DIR/package.json" | head -n 1)"
344
450
  installed_at="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
345
- # installRoute (T9, design F1): installer-owned, engine-read-only. Cursor
346
- # has one install shape (file copy) and no marketplace distinction, so this
347
- # is unconditionally "file" — recorded for data-model consistency with the
348
- # other three hosts even though the switch engine never reads it for Cursor
349
- # (hosts.ts skips Cursor unconditionally: every tier resolves to inherit).
350
- # Written on EVERY install path.
351
- route="file"
451
+ # installRoute (T6, design Component 4): installer-owned, engine-read-only.
452
+ # "bridge" when ~/.claude's Claude marketplace plugin is what Cursor
453
+ # actually loads (this run skipped its own local copy); "local" otherwise.
454
+ # The switch engine still never reads it for Cursor (hosts.ts skips Cursor
455
+ # unconditionally: every tier resolves to inherit) — recorded for
456
+ # data-model consistency with the other three hosts, and now also read by
457
+ # the harness sentinel probe (T4/T5), which treats both routes alike (same
458
+ # flat-agents glob). Written on EVERY install path.
459
+ if [[ "$IS_BRIDGE" -eq 1 ]]; then route="bridge"; else route="local"; fi
352
460
 
353
461
  # Tolerant of a corrupt/missing state file (rewrites a minimal valid one —
354
462
  # AC-8). A record-write failure warns but never fails the install: the next
@@ -394,6 +502,19 @@ if [[ "$UNINSTALL" -eq 1 ]]; then
394
502
  merge_hooks_json "$HOOKS_JSON" "uninstall"
395
503
  echo " - removed massa-ai hook entries from $HOOKS_JSON"
396
504
  fi
505
+ # Remove the massa-ai-owned subagents from Cursor's discovery directory.
506
+ # Prefix glob only: user-authored agents in the same flat dir survive.
507
+ if [[ -d "$CURSOR_AGENTS_DIR" ]]; then
508
+ removed_agents=0
509
+ for agent in "$CURSOR_AGENTS_DIR/"massa-ai-*.md; do
510
+ [[ -f "$agent" ]] || continue
511
+ rm -f "$agent"
512
+ removed_agents=$((removed_agents + 1))
513
+ done
514
+ if [[ "$removed_agents" -gt 0 ]]; then
515
+ echo " - removed $removed_agents massa-ai subagents from $CURSOR_AGENTS_DIR"
516
+ fi
517
+ fi
397
518
  # Remove plugin directory
398
519
  if [[ -d "$LEGACY_PLUGIN_DIR" ]]; then
399
520
  rm -rf "$LEGACY_PLUGIN_DIR"
@@ -409,59 +530,101 @@ if [[ "$UNINSTALL" -eq 1 ]]; then
409
530
  fi
410
531
 
411
532
  # ── Install ──────────────────────────────────────────────────────────────────
412
- vecho "Installing massa-ai Cursor plugin to: $PLUGIN_DIR"
413
- # Migration: a pre-fix install left a copy at plugins/massa-ai. Leaving it in
414
- # place risks Cursor discovering both and firing every hook twice, so it goes
415
- # before the new location is written.
416
- if [[ -d "$LEGACY_PLUGIN_DIR" ]]; then
417
- rm -rf "$LEGACY_PLUGIN_DIR"
418
- echo -e " - removed pre-fix plugin copy at $LEGACY_PLUGIN_DIR"
533
+ # PAU-08/09: bridge-preferred, local-fallback. Computed once, used to decide
534
+ # both which artifacts this run writes and what installRoute gets recorded.
535
+ IS_BRIDGE=0
536
+ if claude_bridge_detected; then
537
+ IS_BRIDGE=1
419
538
  fi
420
- mkdir -p "$PLUGIN_DIR/.cursor-plugin" "$PLUGIN_DIR/skills" "$PLUGIN_DIR/hooks" "$PLUGIN_DIR/agents"
421
-
422
- # Copy manifest
423
- cp "$SCRIPT_DIR/.cursor-plugin/plugin.json" "$PLUGIN_DIR/.cursor-plugin/plugin.json"
424
- vecho " + .cursor-plugin/plugin.json"
425
539
 
426
- # Copy the 6 host-command skills (each in a subdirectory: skills/<name>/SKILL.md).
427
- # massa-ai/, persona-router/, and agents/ are the PDO-06 harness bundle, not a
428
- # Cursor command skill — they are installed separately, into the shared
429
- # harness skills directory (see "Skills bundling" below), not into this
430
- # plugin-cache skills/ tree.
431
540
  skill_count=0
432
- for src in "$SCRIPT_DIR/skills/"*/SKILL.md; do
433
- name="$(basename "$(dirname "$src")")"
434
- case "$name" in
435
- massa-ai|persona-router|agents) continue ;;
436
- esac
437
- mkdir -p "$PLUGIN_DIR/skills/$name"
438
- cp "$src" "$PLUGIN_DIR/skills/$name/SKILL.md"
439
- vecho " + skills/$name/SKILL.md"
440
- skill_count=$((skill_count + 1))
441
- done
541
+ specialist_count=0
542
+
543
+ if [[ "$IS_BRIDGE" -eq 1 ]]; then
544
+ vecho "Installing massa-ai Cursor plugin (Claude-bridge route): ~/.claude already lists massa-ai as installed and enabled, so Cursor loads it via the bridge."
545
+ # Converge (PAU-08, spec edge case): a pre-existing local install (current
546
+ # or pre-fix legacy location) must not double-load alongside the bridge, so
547
+ # one run here ends with exactly one load path. Owned hook entries are
548
+ # stripped with the SAME filter merge_hooks_json's "uninstall" mode already
549
+ # uses — the bridge delivers hooks instead.
550
+ if [[ -d "$LEGACY_PLUGIN_DIR" ]]; then
551
+ rm -rf "$LEGACY_PLUGIN_DIR"
552
+ echo -e " - removed pre-fix plugin copy at $LEGACY_PLUGIN_DIR"
553
+ fi
554
+ if [[ -d "$PLUGIN_DIR" ]]; then
555
+ rm -rf "$PLUGIN_DIR"
556
+ echo -e " - removed local plugin copy at $PLUGIN_DIR (Claude bridge already loads massa-ai)"
557
+ fi
558
+ if [[ -f "$HOOKS_JSON" ]]; then
559
+ merge_hooks_json "$HOOKS_JSON" "uninstall"
560
+ echo -e " - removed massa-ai hook entries from $HOOKS_JSON (the bridge delivers hooks instead)"
561
+ fi
562
+ else
563
+ vecho "Installing massa-ai Cursor plugin to: $PLUGIN_DIR"
564
+ # Migration: a pre-fix install left a copy at plugins/massa-ai. Leaving it in
565
+ # place risks Cursor discovering both and firing every hook twice, so it goes
566
+ # before the new location is written.
567
+ if [[ -d "$LEGACY_PLUGIN_DIR" ]]; then
568
+ rm -rf "$LEGACY_PLUGIN_DIR"
569
+ echo -e " - removed pre-fix plugin copy at $LEGACY_PLUGIN_DIR"
570
+ fi
571
+ mkdir -p "$PLUGIN_DIR/.cursor-plugin" "$PLUGIN_DIR/skills" "$PLUGIN_DIR/hooks"
572
+ # Migration: pre-fix installs bundled agents inside the plugin dir, which
573
+ # Cursor never reads. Drop that copy so upgraders converge on the one real
574
+ # discovery surface and a future Cursor plugin scan cannot double-register.
575
+ if [[ -d "$PLUGIN_DIR/agents" ]]; then
576
+ rm -rf "$PLUGIN_DIR/agents"
577
+ echo -e " - removed pre-fix agents copy at $PLUGIN_DIR/agents (Cursor reads $CURSOR_AGENTS_DIR)"
578
+ fi
579
+
580
+ # Copy manifest
581
+ cp "$SCRIPT_DIR/.cursor-plugin/plugin.json" "$PLUGIN_DIR/.cursor-plugin/plugin.json"
582
+ vecho " + .cursor-plugin/plugin.json"
583
+
584
+ # Copy the 6 host-command skills (each in a subdirectory: skills/<name>/SKILL.md).
585
+ # massa-ai/, persona-router/, and agents/ are the PDO-06 harness bundle, not a
586
+ # Cursor command skill — they are installed separately, into the shared
587
+ # harness skills directory (see "Skills bundling" below), not into this
588
+ # plugin-cache skills/ tree.
589
+ for src in "$SCRIPT_DIR/skills/"*/SKILL.md; do
590
+ name="$(basename "$(dirname "$src")")"
591
+ case "$name" in
592
+ massa-ai|persona-router|agents) continue ;;
593
+ esac
594
+ mkdir -p "$PLUGIN_DIR/skills/$name"
595
+ cp "$src" "$PLUGIN_DIR/skills/$name/SKILL.md"
596
+ vecho " + skills/$name/SKILL.md"
597
+ skill_count=$((skill_count + 1))
598
+ done
442
599
 
443
- # Copy hooks.json (the placeholder version — installer replaces paths)
444
- cp "$SCRIPT_DIR/hooks/hooks.json" "$PLUGIN_DIR/hooks/hooks.json"
445
- vecho " + hooks/hooks.json"
446
-
447
- # Older installs shipped a plugin-local mcp.json here. Cursor reads
448
- # ~/.cursor/mcp.json, not the plugin dir, and MCP is now owned by
449
- # scripts/install-agents.sh — drop the residue so upgraders converge.
450
- if [[ -f "$PLUGIN_DIR/mcp.json" ]]; then
451
- rm -f "$PLUGIN_DIR/mcp.json"
452
- # Not gated by --quiet: this deletes a file in the user's home, so it is a
453
- # mutation notice rather than per-file chatter.
454
- echo -e " - removed stale mcp.json (MCP is now registered in ~/.cursor/mcp.json)"
600
+ # Copy hooks.json (the placeholder version — installer replaces paths)
601
+ cp "$SCRIPT_DIR/hooks/hooks.json" "$PLUGIN_DIR/hooks/hooks.json"
602
+ vecho " + hooks/hooks.json"
603
+
604
+ # Older installs shipped a plugin-local mcp.json here. Cursor reads
605
+ # ~/.cursor/mcp.json, not the plugin dir, and MCP is now owned by
606
+ # scripts/install-agents.sh — drop the residue so upgraders converge.
607
+ if [[ -f "$PLUGIN_DIR/mcp.json" ]]; then
608
+ rm -f "$PLUGIN_DIR/mcp.json"
609
+ # Not gated by --quiet: this deletes a file in the user's home, so it is a
610
+ # mutation notice rather than per-file chatter.
611
+ echo -e " - removed stale mcp.json (MCP is now registered in ~/.cursor/mcp.json)"
612
+ fi
455
613
  fi
456
614
 
457
- # Copy agents — every generated subagent specialist (auto-discovered by Cursor
458
- # from the plugin's agents/ dir). All of them, navigator included, are generated
459
- # from skills/agents/*/SKILL.md and owned by the massa-ai- name prefix (CRS-04).
460
- specialist_count=0
615
+ # Flat agents and harness skills are written in BOTH branches (PAU-08/09):
616
+ # Cursor discovers subagents only from the flat directory regardless of which
617
+ # plugin-load path is active, and MCP/harness-skills ownership is independent
618
+ # of it too. Prune-then-copy so a specialist deleted from the bundle cannot
619
+ # linger installed. All of them, navigator included, are generated from
620
+ # skills/agents/*/SKILL.md and owned by the massa-ai- name prefix (CRS-04) —
621
+ # user-authored agents are untouched.
622
+ mkdir -p "$CURSOR_AGENTS_DIR"
623
+ rm -f "$CURSOR_AGENTS_DIR/"massa-ai-*.md
461
624
  for src in "$SCRIPT_DIR/agents/"massa-ai-*.md; do
462
625
  [[ -f "$src" ]] || continue
463
626
  name="$(basename "$src")"
464
- cp "$src" "$PLUGIN_DIR/agents/$name"
627
+ cp "$src" "$CURSOR_AGENTS_DIR/$name"
465
628
  vecho " + $name"
466
629
  specialist_count=$((specialist_count + 1))
467
630
  done
@@ -469,31 +632,33 @@ vecho " + ${specialist_count} subagent specialists (generated from skills/agent
469
632
 
470
633
  # Skills bundling (PDO-08, 09): install massa-ai/persona-router into the
471
634
  # shared harness skills directory, unless scripts/install-skills.sh already
472
- # owns it for this platform.
635
+ # owns it for this platform. Runs in both branches (same reasoning as above).
473
636
  vecho ""
474
637
  install_bundled_skills
475
638
 
476
- # Copy the real hooks/massa-ai-hook this plugin already ships (T14/PDO-14: a
477
- # generated real file, no longer a symlink into apps/claude-plugin/ — that
478
- # path does not exist in a registry tarball install, where $REPO_ROOT is not
479
- # this monorepo. $CLAUDE_PLUGIN_BIN is kept only as a repo-checkout fallback.
480
- if [[ -f "$SCRIPT_DIR/hooks/massa-ai-hook" ]]; then
481
- cp "$SCRIPT_DIR/hooks/massa-ai-hook" "$PLUGIN_DIR/hooks/massa-ai-hook"
482
- chmod +x "$PLUGIN_DIR/hooks/massa-ai-hook"
483
- vecho " + hooks/massa-ai-hook"
484
- elif [[ -f "$CLAUDE_PLUGIN_BIN" ]]; then
485
- ln -sfn "$CLAUDE_PLUGIN_BIN" "$PLUGIN_DIR/hooks/massa-ai-hook"
486
- vecho " + hooks/massa-ai-hook → $CLAUDE_PLUGIN_BIN"
487
- else
488
- echo " ⚠ Warning: no massa-ai-hook binary found" >&2
489
- echo " Hooks will not fire until the binary is available." >&2
490
- fi
639
+ if [[ "$IS_BRIDGE" -ne 1 ]]; then
640
+ # Copy the real hooks/massa-ai-hook this plugin already ships (T14/PDO-14: a
641
+ # generated real file, no longer a symlink into apps/claude-plugin/ — that
642
+ # path does not exist in a registry tarball install, where $REPO_ROOT is not
643
+ # this monorepo. $CLAUDE_PLUGIN_BIN is kept only as a repo-checkout fallback.
644
+ if [[ -f "$SCRIPT_DIR/hooks/massa-ai-hook" ]]; then
645
+ cp "$SCRIPT_DIR/hooks/massa-ai-hook" "$PLUGIN_DIR/hooks/massa-ai-hook"
646
+ chmod +x "$PLUGIN_DIR/hooks/massa-ai-hook"
647
+ vecho " + hooks/massa-ai-hook"
648
+ elif [[ -f "$CLAUDE_PLUGIN_BIN" ]]; then
649
+ ln -sfn "$CLAUDE_PLUGIN_BIN" "$PLUGIN_DIR/hooks/massa-ai-hook"
650
+ vecho " + hooks/massa-ai-hook → $CLAUDE_PLUGIN_BIN"
651
+ else
652
+ echo " ⚠ Warning: no massa-ai-hook binary found" >&2
653
+ echo " Hooks will not fire until the binary is available." >&2
654
+ fi
491
655
 
492
- # Merge hooks.json (array-append, backup, idempotent)
493
- vecho ""
494
- vecho "Merging hooks into $HOOKS_JSON..."
495
- merge_hooks_json "$HOOKS_JSON" "install"
496
- vecho " + 7 massa-ai hook events wired (array-append, user hooks preserved)"
656
+ # Merge hooks.json (array-append, backup, idempotent)
657
+ vecho ""
658
+ vecho "Merging hooks into $HOOKS_JSON..."
659
+ merge_hooks_json "$HOOKS_JSON" "install"
660
+ vecho " + 7 massa-ai hook events wired (array-append, user hooks preserved)"
661
+ fi
497
662
 
498
663
  # ── MCP registration (delegated) ─────────────────────────────────────────────
499
664
  # scripts/install-agents.sh is the single writer of host MCP config. It writes
@@ -517,10 +682,17 @@ fi
517
682
 
518
683
  # Summary line in quiet mode
519
684
  if [ "${MASSA_AI_VERBOSE:-0}" != "1" ]; then
520
- ok "cursor plugin installed (${skill_count} skills, ${specialist_count} specialists, 7 hooks)"
685
+ if [[ "$IS_BRIDGE" -eq 1 ]]; then
686
+ ok "cursor plugin: using the Claude bridge (${specialist_count} specialists) — hooks delivered by the bridge, not installed locally"
687
+ else
688
+ ok "cursor plugin installed (${skill_count} skills, ${specialist_count} specialists, 7 hooks)"
689
+ fi
521
690
  else
522
691
  vecho ""
523
692
  vecho "Done. Restart Cursor to pick up the plugin."
693
+ if [[ "$IS_BRIDGE" -eq 1 ]]; then
694
+ vecho "💡 massa-ai loads via the Claude bridge (~/.claude) — local plugin/hook install skipped."
695
+ fi
524
696
  vecho "💡 MCP is registered in ~/.cursor/mcp.json by scripts/install-agents.sh (single writer)."
525
697
  fi
526
698
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@massa-ai/cursor-plugin",
3
- "version": "1.27.0",
3
+ "version": "1.30.0",
4
4
  "description": "massa-ai plugin for Cursor — semantic code search, memory, and context compression",
5
5
  "files": [
6
6
  "agents",
@@ -1,12 +1,12 @@
1
1
  ---
2
2
  name: judge
3
- description: Read-only debate-panel evaluator for judge-with-debate. Score an artifact against the meta-judge's evaluation specification with quoted evidence, then defend or revise scores across up to 3 debate rounds until the panel reaches consensus. Writes only its own judge-N report file per dispatch. Never judges outside the specification, never revises without quoted evidence.
3
+ description: Debate-panel evaluator for judge-with-debate. Score an artifact against the meta-judge's evaluation specification with quoted evidence, then defend or revise scores across up to 3 debate rounds until the panel reaches consensus. Writes only its own judge-N report file per dispatch. Never judges outside the specification, never revises without quoted evidence.
4
4
  license: MIT
5
5
  metadata:
6
6
  author: S1LV4, luizgmassa
7
- version: "1.1.0"
7
+ version: "1.2.0"
8
8
  model_tier: deep
9
- permission: read-only
9
+ permission: write
10
10
  ---
11
11
 
12
12
  # Judge Agent Skill
@@ -46,7 +46,7 @@ Before reading any massa-ai file:
46
46
  Never pass `workflowSessionId` in that field. Use `synapse_task_begin`/`synapse_task_end`
47
47
  for task envelopes and `synapse_prefetch` to warm the buffer on file open.
48
48
  - Prefer the shared v2 retrieval order; fall back gracefully if the massa-ai
49
- server or Synapse is unavailable. The full tool surface includes 52 tools
49
+ server or Synapse is unavailable. The full tool surface includes 54 tools
50
50
  (see `references/mcp-tools.md`): indexing, search, symbol graph
51
51
  (`trace_path`, `impact_analysis`, `get_architecture`), memory CRUD
52
52
  (`remember`, `recall`, `memory_update`, `memory_delete`), checkpoints
@@ -80,6 +80,8 @@ Before reading any massa-ai file:
80
80
  requirement meaning, scope boundaries, destructive/irreversible choices,
81
81
  contradictory evidence — ask the user rather than choose silently. Facts
82
82
  are looked up; decisions are asked.
83
+ - Before writing or changing implementation code, load
84
+ `references/coding-guidelines.md` if not already loaded.
83
85
  - Complete Evidence Gate before claiming done.
84
86
 
85
87
  Use internal references only when needed:
@@ -164,6 +166,9 @@ current context already contains it.
164
166
  | `commit` | draft or create safe Conventional Commits with Jira branch prefixes and audit report exclusions | `workflows/commit.md` |
165
167
  | `the-fool` | direct challenge, red-team, pre-mortem, evidence audit | `workflows/the-fool.md` |
166
168
  | `judge-with-debate` | standalone multi-judge debate evaluation of user-supplied artifacts | `workflows/judge-with-debate.md` |
169
+ | `pr-review` | review a hosted GitHub PR / GitLab MR and post findings via `gh`/`glab` | `workflows/pr-review.md` |
170
+ | `to-prd` | turn the current conversation into a PRD without a new interview | `workflows/to-prd.md` |
171
+ | `skill-architect` | design and build a new skill through structured conversation | `workflows/skill-architect.md` |
167
172
  | `furps-refinement` | FURPS+ refinement of a PRD and/or ADR before implementation, with The Fool pre-validation and DoR coverage | `workflows/refinement/furps-refinement.md` |
168
173
  | `general` | coding work with no more specific workflow | `workflows/general.md` |
169
174
 
@@ -176,8 +181,8 @@ match or no match is resolved deterministically without asking.
176
181
  Deterministic routing precedence, first match wins:
177
182
 
178
183
  1. **Explicit route:** user names a massa-ai workflow, report family, saved finding type, or asks for a direct challenge.
179
- 2. **Requested artifact:** ADR, RFC, TDD, Jira ticket, commit, session guide, audit report, implementation audit report, mobile Figma report, or FURPS refinement report.
180
- 3. **Target type:** broken behavior/error -> `debug`; saved audit finding -> matching `*-fix`; implementation scope review -> `implementation-audit`; Maestro E2E/device automation target -> `maestro`, `maestro-audit`, or child-only `maestro-fix` before generic tests workflows; security/privacy/auth finding -> security workflow; tests/flakes/coverage finding -> tests workflow; supplied Figma/screenshot mobile UI design -> `design`; mobile Figma compare/audit -> `mobile-figma-audit`; saved `MFM-*` findings -> `mobile-figma-fix`.
184
+ 2. **Requested artifact:** ADR, RFC, TDD, Jira ticket, commit, session guide, audit report, implementation audit report, mobile Figma report, FURPS refinement report, PRD synthesized from the current conversation -> `to-prd` (explicit request only; refining an existing PRD stays `furps-refinement`), or new SKILL.md / skill design -> `skill-architect`.
185
+ 3. **Target type:** broken behavior/error -> `debug`; hosted PR/MR reference (number or URL) to review with posted findings -> `pr-review` (local working diff stays with audit routes); saved audit finding -> matching `*-fix`; implementation scope review -> `implementation-audit`; Maestro E2E/device automation target -> `maestro`, `maestro-audit`, or child-only `maestro-fix` before generic tests workflows; security/privacy/auth finding -> security workflow; tests/flakes/coverage finding -> tests workflow; supplied Figma/screenshot mobile UI design -> `design`; mobile Figma compare/audit -> `mobile-figma-audit`; saved `MFM-*` findings -> `mobile-figma-fix`.
181
186
  4. **Primary verb:** create/add/implement -> `feature` unless the concrete target is new Maestro flow work, which routes to `maestro`; restructure without behavior change -> `refactor`; inspect/understand only -> `exploration`; record selected decision -> `adr`; compare open options -> `rfc`; design settled implementation -> `tdd`; refine/quality-check an existing PRD or ADR document (not implementation auditing) -> `furps-refinement`.
182
187
  5. **Risk domain escalation:** migrations, irreversible operations, auth/privacy, cross-service contracts, public compatibility, or work over 10 files routes to `spec-driven` unless the user explicitly requests a narrower workflow and accepts the containment.
183
188
  6. **General fallback:** use `general` only after a one-line General fallback preflight names the specialized workflow considered, rejected reason, and why fallback does not change verification or mutation behavior.
@@ -148,7 +148,7 @@ only, never a dispatch target.
148
148
 
149
149
  ## Capability Packet
150
150
 
151
- **This section is the sole canonical Capability Packet definition.** `references/subagent-design.md` and the root `skills/AGENTS.md` registry defer to or mirror this list; `scripts/__tests__/capability-packet-parity.test.ts` fails when the `skills/AGENTS.md` mirror diverges. Bespoke packets (judge panel, FURPS analyst, phase-batch worker) are declared specializations that map onto these fields in their own workflow files.
151
+ **This section is the sole canonical Capability Packet definition.** `references/subagent-design.md` mirrors this list and the root `skills/AGENTS.md` registry points here without restating it. Bespoke packets (judge panel, FURPS analyst, phase-batch worker) are declared specializations that map onto these fields in their own workflow files.
152
152
 
153
153
  **A subagent inherits nothing from the parent session** — no skills, no personas, no loaded references, no conversation history. Everything the subagent needs is named explicitly in the packet, including the exact reference file paths it must read itself.
154
154