master-skill 0.12.12 → 0.12.13

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.
@@ -9,7 +9,7 @@
9
9
  {
10
10
  "name": "master-skill",
11
11
  "description": "FoJin-powered Buddhist AI persona framework — source-grounded, boundary-aware, fidelity-tested, runtime-ready. 15 prebuilt masters across 印度/汉传/藏传/南传 plus compare, debate, and curriculum meta-skills.",
12
- "version": "0.12.12",
12
+ "version": "0.12.13",
13
13
  "source": "./",
14
14
  "author": {
15
15
  "name": "xr843",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "master-skill",
3
3
  "description": "FoJin-powered Buddhist AI persona framework — source-grounded, boundary-aware, fidelity-tested, runtime-ready. 15 prebuilt masters across 印度/汉传/藏传/南传 plus compare, debate, and curriculum meta-skills.",
4
- "version": "0.12.12",
4
+ "version": "0.12.13",
5
5
  "author": {
6
6
  "name": "xr843",
7
7
  "email": "xr843@users.noreply.github.com"
@@ -2,7 +2,7 @@
2
2
  "name": "master-skill",
3
3
  "displayName": "Master Skill",
4
4
  "description": "FoJin-powered Buddhist AI persona framework — source-grounded, boundary-aware, fidelity-tested, runtime-ready. 15 prebuilt masters across 印度/汉传/藏传/南传.",
5
- "version": "0.12.12",
5
+ "version": "0.12.13",
6
6
  "author": {
7
7
  "name": "xr843",
8
8
  "email": "xr843@users.noreply.github.com"
package/bin/cli.mjs CHANGED
@@ -405,7 +405,40 @@ function cmdInstallAll(label = "Installing") {
405
405
  return cmdInstall(all);
406
406
  }
407
407
 
408
- function cmdUninstall(names) {
408
+ // Directories under create-master/masters/ — personas the user generated. `update`
409
+ // carries them across (replaceGeneratorInstall); `uninstall` must not quietly
410
+ // delete them either.
411
+ function generatedPersonas(generatorDir) {
412
+ const mastersDir = path.join(generatorDir, "masters");
413
+ if (!fs.existsSync(mastersDir)) return [];
414
+ return fs
415
+ .readdirSync(mastersDir, { withFileTypes: true })
416
+ .filter((entry) => entry.isDirectory())
417
+ .map((entry) => entry.name)
418
+ .sort();
419
+ }
420
+
421
+ // Links in the skills directory that `master_builder.py --register` made into
422
+ // this generator's masters/. Resolved with realpath so a Windows junction is
423
+ // recognised as well as a symlink.
424
+ function registrationsInto(generatorDir) {
425
+ const mastersDir = path.join(generatorDir, "masters");
426
+ if (!fs.existsSync(mastersDir) || !fs.existsSync(SKILLS_DIR)) return [];
427
+ const realMasters = fs.realpathSync(mastersDir);
428
+ return fs
429
+ .readdirSync(SKILLS_DIR, { withFileTypes: true })
430
+ .filter((entry) => entry.isSymbolicLink())
431
+ .map((entry) => path.join(SKILLS_DIR, entry.name))
432
+ .filter((link) => {
433
+ try {
434
+ return fs.realpathSync(link).startsWith(realMasters + path.sep);
435
+ } catch {
436
+ return false;
437
+ }
438
+ });
439
+ }
440
+
441
+ function cmdUninstall(names, { force = false } = {}) {
409
442
  let failed = 0;
410
443
  for (const name of names) {
411
444
  if (!isSafeName(name)) {
@@ -429,6 +462,26 @@ function cmdUninstall(names) {
429
462
  failed++;
430
463
  continue;
431
464
  }
465
+ if (skill.kind === "generator") {
466
+ // Until 2026-09-17 this removed the whole directory, masters/ included:
467
+ // every persona the user had generated was deleted with "✓ removed" and
468
+ // exit 0, and the links registered for them were left pointing at nothing.
469
+ const generated = generatedPersonas(dest);
470
+ if (generated.length && !force) {
471
+ console.log(
472
+ ` ✗ ${name} — holds ${generated.length} persona(s) you generated: ${generated.join(", ")}`
473
+ );
474
+ console.log(
475
+ ` Uninstalling deletes ${path.join(dest, "masters")}. Move it somewhere safe first, or rerun with --force.`
476
+ );
477
+ failed++;
478
+ continue;
479
+ }
480
+ for (const link of registrationsInto(dest)) {
481
+ fs.unlinkSync(link);
482
+ console.log(` ✓ ${path.basename(link)} link removed (${link})`);
483
+ }
484
+ }
432
485
  fs.rmSync(dest, { recursive: true, force: true });
433
486
  console.log(` ✓ ${name} removed (${dest})`);
434
487
  }
@@ -513,7 +566,9 @@ function installedProblems() {
513
566
  }
514
567
 
515
568
  // Personas registered by create-master are links into create-master/masters/;
516
- // uninstalling the generator leaves them pointing at nothing.
569
+ // deleting or moving a generated persona by hand leaves its link pointing at
570
+ // nothing. (`uninstall create-master` refuses while personas exist, and with
571
+ // --force removes their links itself.)
517
572
  if (fs.existsSync(SKILLS_DIR)) {
518
573
  for (const entry of fs.readdirSync(SKILLS_DIR, { withFileTypes: true })) {
519
574
  if (!entry.isSymbolicLink()) continue;
@@ -909,6 +964,8 @@ Usage:
909
964
  master-skill doctor Check local install and runtime paths
910
965
  master-skill doctor --json Print diagnostics as JSON
911
966
  master-skill uninstall <name...> Remove installed skills
967
+ master-skill uninstall create-master --force
968
+ Also delete the personas you generated (refused otherwise)
912
969
  master-skill --version Print version
913
970
  master-skill --help Show this help
914
971
 
@@ -936,7 +993,8 @@ Examples:
936
993
  if (CATALOG) {
937
994
  const args = process.argv.slice(2);
938
995
  const json = args.includes("--json");
939
- const positionalArgs = args.filter((arg) => arg !== "--json");
996
+ const force = args.includes("--force");
997
+ const positionalArgs = args.filter((arg) => arg !== "--json" && arg !== "--force");
940
998
  const cmd = positionalArgs[0];
941
999
 
942
1000
  if (!cmd || cmd === "--help" || cmd === "-h") {
@@ -977,7 +1035,7 @@ if (CATALOG) {
977
1035
  console.log("Usage: master-skill uninstall <name...>");
978
1036
  process.exitCode = 1;
979
1037
  } else {
980
- if (cmdUninstall(rest) > 0) process.exitCode = 1;
1038
+ if (cmdUninstall(rest, { force }) > 0) process.exitCode = 1;
981
1039
  }
982
1040
  } else {
983
1041
  console.log(`Unknown command: ${cmd}\nRun master-skill --help for usage.`);
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "master-skill",
3
3
  "description": "FoJin-powered Buddhist AI persona framework — source-grounded, boundary-aware, fidelity-tested, runtime-ready. 15 prebuilt masters across 印度/汉传/藏传/南传.",
4
- "version": "0.12.12",
4
+ "version": "0.12.13",
5
5
  "contextFileName": "GEMINI.md"
6
6
  }
@@ -61,7 +61,8 @@ emit_modes_only() {
61
61
  if [ -n "${CURSOR_PLUGIN_ROOT:-}" ]; then
62
62
  printf '{"additional_context": %s}\n' "$MODES_JSON"
63
63
  elif [ -n "${CLAUDE_PLUGIN_ROOT:-}" ] && [ -z "${COPILOT_CLI:-}" ]; then
64
- printf '{"hookSpecificOutput": {"additionalContext": %s}}\n' "$MODES_JSON"
64
+ # hookEventName is required; without it Claude Code rejects the payload.
65
+ printf '{"hookSpecificOutput": {"hookEventName": "SessionStart", "additionalContext": %s}}\n' "$MODES_JSON"
65
66
  else
66
67
  printf '{"additionalContext": %s}\n' "$MODES_JSON"
67
68
  fi
@@ -136,7 +136,17 @@ def wrap_for_host(context: str, env: dict) -> dict:
136
136
  if env.get("CURSOR_PLUGIN_ROOT"):
137
137
  return {"additional_context": context}
138
138
  if env.get("CLAUDE_PLUGIN_ROOT") and not env.get("COPILOT_CLI"):
139
- return {"hookSpecificOutput": {"additionalContext": context}}
139
+ # `hookEventName` is required. Without it Claude Code 2.1.273 rejects the
140
+ # whole payload — "Hook JSON output validation failed — hookSpecificOutput
141
+ # is missing required field hookEventName" — shows that error at every
142
+ # session start, and injects nothing. Measured 2026-09-17 in an isolated
143
+ # plugin install; the transcript recorded `hook_non_blocking_error`.
144
+ return {
145
+ "hookSpecificOutput": {
146
+ "hookEventName": "SessionStart",
147
+ "additionalContext": context,
148
+ }
149
+ }
140
150
  return {"additionalContext": context}
141
151
 
142
152
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "master-skill",
3
- "version": "0.12.12",
3
+ "version": "0.12.13",
4
4
  "type": "module",
5
5
  "description": "FoJin-powered Buddhist AI persona framework — source-grounded, boundary-aware, fidelity-tested, runtime-ready. 15 pre-built masters across 印度 / 汉传 / 藏传 / 南传, plus /compare-masters, /master-debate, and /master-curriculum.",
6
6
  "bin": {