@massa-ai/cursor-plugin 1.11.0 → 1.12.1

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.11.0",
3
+ "version": "1.12.1",
4
4
  "description": "massa-ai — semantic code search, memory, and context compression for Cursor"
5
5
  }
package/install.sh CHANGED
@@ -247,7 +247,13 @@ if (typeof data.platforms !== "object" || data.platforms === null || Array.isArr
247
247
  data.platforms = {};
248
248
  }
249
249
  data.version = 2;
250
+ const prev = data.platforms[host];
250
251
  data.platforms[host] = { root, skillsOwner: "plugin", skills: ["massa-ai", "persona-router"] };
252
+ // The whole-record replace must not drop the plugin version record a previous
253
+ // successful install wrote (R2) — re-attach it.
254
+ if (prev && typeof prev === "object" && !Array.isArray(prev) && prev.plugin && typeof prev.plugin === "object") {
255
+ data.platforms[host].plugin = prev.plugin;
256
+ }
251
257
  fs.mkdirSync(path.dirname(file), { recursive: true });
252
258
  fs.writeFileSync(file, JSON.stringify(data, null, 2) + "\n");
253
259
  NODE
@@ -273,28 +279,87 @@ try {
273
279
  }
274
280
  NODE
275
281
  )"
276
- [[ "$raw_owner" == "plugin" ]] || return 0
277
-
278
- local name
279
- for name in massa-ai persona-router; do
280
- rm -rf "$HARNESS_SKILLS_DIR/$name"
281
- done
282
- rmdir "$HARNESS_SKILLS_DIR" 2>/dev/null || true
283
- echo " - removed plugin-owned harness skills from $HARNESS_SKILLS_DIR"
282
+ [[ "$raw_owner" == "plugin" ]] && {
283
+ local name
284
+ for name in massa-ai persona-router; do
285
+ rm -rf "$HARNESS_SKILLS_DIR/$name"
286
+ done
287
+ rmdir "$HARNESS_SKILLS_DIR" 2>/dev/null || true
288
+ echo " - removed plugin-owned harness skills from $HARNESS_SKILLS_DIR"
289
+ }
284
290
 
291
+ # AC-15: a plugin-owned platform keeps the whole-record delete (clean-slate
292
+ # semantics unchanged); any other platform loses only its plugin version
293
+ # record while root/skills/skillsOwner survive (Plan Challenge C-4).
285
294
  "$runner" - "$HARNESS_STATE_FILE" "$HARNESS_HOST" <<'NODE'
286
295
  const fs = require("fs");
287
296
  const [, , file, host] = process.argv;
288
297
  try {
289
298
  const data = JSON.parse(fs.readFileSync(file, "utf8"));
290
- if (data && data.platforms && data.platforms[host] && data.platforms[host].skillsOwner === "plugin") {
291
- delete data.platforms[host];
292
- fs.writeFileSync(file, JSON.stringify(data, null, 2) + "\n");
299
+ const rec = data && data.platforms && data.platforms[host];
300
+ if (rec && typeof rec === "object") {
301
+ if (rec.skillsOwner === "plugin") {
302
+ delete data.platforms[host];
303
+ fs.writeFileSync(file, JSON.stringify(data, null, 2) + "\n");
304
+ } else if (rec.plugin && typeof rec.plugin === "object") {
305
+ delete rec.plugin;
306
+ fs.writeFileSync(file, JSON.stringify(data, null, 2) + "\n");
307
+ }
293
308
  }
294
309
  } catch { /* nothing to clean up */ }
295
310
  NODE
296
311
  }
297
312
 
313
+ # ── Plugin version recording (PAI-03/04/07) ─────────────────────────────────
314
+ # Why: the harness gates re-runs on the recorded bundle version, so a
315
+ # successful install records it — but ONLY as the final step of the
316
+ # install path. A version written before a later step fails would mark a
317
+ # broken install "current" and skip it forever (AC-16, Plan Challenge C-1).
318
+ # Impacts: PAI-03 record, PAI-04 upgrade trigger, PAI-07 uninstall, AC-3/16.
319
+ # Test: bash scripts/tests/test-plugin-auto-install.sh (Section 3 e2e chain)
320
+ record_plugin_version() {
321
+ local runner=""
322
+ if command -v node &>/dev/null; then runner="node"
323
+ elif command -v bun &>/dev/null; then runner="bun"
324
+ else
325
+ echo " ⚠ node or bun required to record the plugin version — next run will reinstall" >&2
326
+ return 0
327
+ fi
328
+
329
+ local version installed_at
330
+ version="$(sed -n 's/.*"version"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' "$SCRIPT_DIR/package.json" | head -n 1)"
331
+ installed_at="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
332
+
333
+ # Tolerant of a corrupt/missing state file (rewrites a minimal valid one —
334
+ # AC-8). A record-write failure warns but never fails the install: the next
335
+ # run treats the host as unknown-version and reinstalls.
336
+ "$runner" - "$HARNESS_STATE_FILE" "$HARNESS_HOST" "$CURSOR_DIR" "$version" "$installed_at" <<'NODE' || \
337
+ echo " ⚠ could not record the plugin version — next run will reinstall (unknown version)" >&2
338
+ const fs = require("fs");
339
+ const path = require("path");
340
+ const [, , file, host, root, version, installedAt] = process.argv;
341
+ let data = { version: 2, platforms: {} };
342
+ try {
343
+ const existing = JSON.parse(fs.readFileSync(file, "utf8"));
344
+ if (existing && typeof existing === "object" && !Array.isArray(existing)) data = existing;
345
+ } catch { /* fresh */ }
346
+ if (typeof data.platforms !== "object" || data.platforms === null || Array.isArray(data.platforms)) {
347
+ data.platforms = {};
348
+ }
349
+ data.version = 2;
350
+ // Preserve every unrelated field; a missing record gets the minimal shape the
351
+ // strict skills reader accepts (non-empty root + a skills list).
352
+ const rec =
353
+ data.platforms[host] && typeof data.platforms[host] === "object" && !Array.isArray(data.platforms[host])
354
+ ? data.platforms[host]
355
+ : { root, skillsOwner: "plugin", skills: [] };
356
+ rec.plugin = { version, installedAt };
357
+ data.platforms[host] = rec;
358
+ fs.mkdirSync(path.dirname(file), { recursive: true });
359
+ fs.writeFileSync(file, JSON.stringify(data, null, 2) + "\n");
360
+ NODE
361
+ }
362
+
298
363
  # ── Uninstall ───────────────────────────────────────────────────────────────
299
364
  if [[ "$UNINSTALL" -eq 1 ]]; then
300
365
  echo "Uninstalling massa-ai Cursor plugin (scope: $SCOPE)..."
@@ -432,4 +497,8 @@ else
432
497
  vecho ""
433
498
  vecho "Done. Restart Cursor to pick up the plugin."
434
499
  vecho "💡 MCP is registered in ~/.cursor/mcp.json by scripts/install-agents.sh (single writer)."
435
- fi
500
+ fi
501
+
502
+ # Final step of the install path: record the bundle version. Reached only when
503
+ # every fallible step succeeded (AC-16) — never on --uninstall (exits above).
504
+ record_plugin_version
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@massa-ai/cursor-plugin",
3
- "version": "1.11.0",
3
+ "version": "1.12.1",
4
4
  "description": "massa-ai plugin for Cursor — semantic code search, memory, and context compression",
5
5
  "files": [
6
6
  "agents",