@light-merlin-dark/skill-sync 0.1.1 → 0.1.3

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.3
4
+ - Makefile release: robust GitHub release notes generation via `--notes-file` and correct escaping of `awk $0`.
5
+
6
+ ## 0.1.2
7
+ - Report installed “orphan” skills during `skill-sync check` (helps explain why a harness skill UI didn’t update)
8
+ - Add `make release` target (pre-publish → npm publish → git tag + push → GitHub release create/update)
9
+ - Minor: manager skill naming support (codex-style capitalized display)
10
+
3
11
  ## 0.1.1
4
12
  - Add source-topology diagnostics for duplicate skill slugs in configured project roots
5
13
  - Surface resolved duplicates as warnings and unresolved duplicates as blocking errors in `check` and `sources`
package/SKILL.md CHANGED
@@ -73,6 +73,9 @@ skill-sync harnesses --json
73
73
  ## Safety Rules
74
74
 
75
75
  - Prefer `check` before `sync`.
76
- - Do not overwrite unmanaged conflicts by hand; inspect why they exist first.
76
+ - If `check` reports a `conflict` due to an existing *unmanaged* install (common case: a skill folder already exists in a harness root like `~/.hermes/skills/<skill>`), resolve by either:
77
+ - removing the unmanaged directory/file and re-running `sync`, or
78
+ - restoring via `skill-sync backup restore <backup-id>`.
79
+ Do not leave mixed symlink + real directories behind.
77
80
  - Use `--home` for isolated testing against a fake home directory.
78
81
  - Use `--projects-root` when you need to constrain discovery to a specific source tree.
package/dist/index.js CHANGED
@@ -1288,12 +1288,52 @@ function buildSyncPlan(skills, harnesses, config, state, sourceDiagnostics) {
1288
1288
  }
1289
1289
  harnessPlan.entries.sort((a, b) => a.destinationPath.localeCompare(b.destinationPath));
1290
1290
  }
1291
+ const orphanSkills = [];
1292
+ for (const harnessPlan of harnessPlans) {
1293
+ const desiredSet = desiredByHarness.get(harnessPlan.harness.id) || new Set;
1294
+ let children = [];
1295
+ try {
1296
+ children = readdirSync3(harnessPlan.harness.rootPath);
1297
+ } catch {
1298
+ continue;
1299
+ }
1300
+ for (const child of children) {
1301
+ const destinationPath = join5(harnessPlan.harness.rootPath, child);
1302
+ if (desiredSet.has(destinationPath)) {
1303
+ continue;
1304
+ }
1305
+ if (state.managedEntries[destinationPath]) {
1306
+ continue;
1307
+ }
1308
+ const inspection = inspectEntry(destinationPath);
1309
+ if (!inspection.exists) {
1310
+ continue;
1311
+ }
1312
+ let hasSkillMd = false;
1313
+ if (inspection.type === "directory") {
1314
+ hasSkillMd = existsSync6(join5(destinationPath, "SKILL.md"));
1315
+ } else if (inspection.type === "symlink" && inspection.resolvedTarget) {
1316
+ hasSkillMd = existsSync6(join5(inspection.resolvedTarget, "SKILL.md"));
1317
+ }
1318
+ if (!hasSkillMd) {
1319
+ continue;
1320
+ }
1321
+ orphanSkills.push({
1322
+ harnessId: harnessPlan.harness.id,
1323
+ harnessRoot: harnessPlan.harness.rootPath,
1324
+ installName: child,
1325
+ destinationPath,
1326
+ inspection
1327
+ });
1328
+ }
1329
+ }
1291
1330
  return {
1292
1331
  harnesses: harnessPlans,
1293
1332
  changes,
1294
1333
  conflicts,
1295
1334
  ok,
1296
- sourceDiagnostics: sourceDiagnostics || { warnings: [], errors: [] }
1335
+ sourceDiagnostics: sourceDiagnostics || { warnings: [], errors: [] },
1336
+ orphanSkills: orphanSkills.length ? orphanSkills : undefined
1297
1337
  };
1298
1338
  }
1299
1339
  function buildPlannedEntry(skill, harness, installName, destinationPath, state, config) {
@@ -1450,6 +1490,16 @@ function print(value, json) {
1450
1490
  function renderPlan(plan) {
1451
1491
  const lines = [];
1452
1492
  appendSourceDiagnostics(lines, plan.sourceDiagnostics);
1493
+ if (plan.orphanSkills && plan.orphanSkills.length > 0) {
1494
+ if (lines.length > 0) {
1495
+ lines.push("");
1496
+ }
1497
+ lines.push("Orphan installed skills:");
1498
+ for (const orphan of plan.orphanSkills) {
1499
+ const resolved = orphan.inspection.type === "symlink" ? orphan.inspection.resolvedTarget || orphan.inspection.linkTarget : undefined;
1500
+ lines.push(`- ${orphan.harnessId}/${orphan.installName} ${orphan.destinationPath}${resolved ? ` -> ${resolved}` : ""}`);
1501
+ }
1502
+ }
1453
1503
  const counts = countPlanActions(plan);
1454
1504
  if (lines.length > 0) {
1455
1505
  lines.push("");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@light-merlin-dark/skill-sync",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "Sync local repo-backed agent skills across Codex, Claude Code, Cursor, Gemini, Hermes, and other harnesses.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",