mover-os 4.7.3 → 4.7.4

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 (2) hide show
  1. package/install.js +42 -11
  2. package/package.json +1 -1
package/install.js CHANGED
@@ -17,6 +17,18 @@ const { execSync } = require("child_process");
17
17
 
18
18
  const VERSION = "4";
19
19
 
20
+ // ─── Windows path normalization ─────────────────────────────────────────────
21
+ // Git Bash / MSYS / WSL surface paths like "/c/Users/foo" inside terminals
22
+ // that Node treats as drive-less when run from PowerShell or cmd. path.resolve
23
+ // then prepends the *current* drive, producing "C:\c\Users\foo". Convert
24
+ // "/c/Users/foo" → "C:\Users\foo" before any path.join(vaultPath, ...) call.
25
+ function normalizeWinPath(p) {
26
+ if (process.platform !== "win32" || !p) return p;
27
+ const m = p.match(/^\/([a-zA-Z])\/(.*)$/);
28
+ if (m) return `${m[1].toUpperCase()}:\\${m[2].replace(/\//g, "\\")}`;
29
+ return p;
30
+ }
31
+
20
32
  // ─── JSON output helper ──────────────────────────────────────────────────────
21
33
  function jsonOut(command, data, ok = true) {
22
34
  const envelope = {
@@ -1053,12 +1065,14 @@ function detectChanges(bundleDir, vaultPath, selectedAgentIds) {
1053
1065
 
1054
1066
  if (fs.existsSync(wfSrc)) {
1055
1067
  for (const file of fs.readdirSync(wfSrc).filter((f) => f.endsWith(".md"))) {
1056
- const srcContent = fs.readFileSync(path.join(wfSrc, file), "utf8");
1068
+ const srcContent = fs.readFileSync(path.join(wfSrc, file), "utf8")
1069
+ .replace(/\r\n/g, "\n").replace(/\r/g, "\n");
1057
1070
  const destFile = wfDest && path.join(wfDest, file);
1058
1071
  if (!destFile || !fs.existsSync(destFile)) {
1059
1072
  result.workflows.push({ file, status: "new" });
1060
1073
  } else {
1061
- const destContent = fs.readFileSync(destFile, "utf8");
1074
+ const destContent = fs.readFileSync(destFile, "utf8")
1075
+ .replace(/\r\n/g, "\n").replace(/\r/g, "\n");
1062
1076
  result.workflows.push({
1063
1077
  file,
1064
1078
  status: srcContent === destContent ? "unchanged" : "changed",
@@ -1097,8 +1111,10 @@ function detectChanges(bundleDir, vaultPath, selectedAgentIds) {
1097
1111
  ].filter(Boolean);
1098
1112
  const rulesDest = rulesDests.find((d) => fs.existsSync(d));
1099
1113
  if (fs.existsSync(rulesSrc) && rulesDest) {
1100
- const srcContent = fs.readFileSync(rulesSrc, "utf8");
1101
- const destContent = fs.readFileSync(rulesDest, "utf8");
1114
+ const srcContent = fs.readFileSync(rulesSrc, "utf8")
1115
+ .replace(/\r\n/g, "\n").replace(/\r/g, "\n");
1116
+ const destContent = fs.readFileSync(rulesDest, "utf8")
1117
+ .replace(/\r\n/g, "\n").replace(/\r/g, "\n");
1102
1118
  result.rules = srcContent === destContent ? "unchanged" : "changed";
1103
1119
  } else {
1104
1120
  result.rules = "unchanged";
@@ -1115,12 +1131,14 @@ function detectChanges(bundleDir, vaultPath, selectedAgentIds) {
1115
1131
  } else {
1116
1132
  const relNorm = entryRel.replace(/\\/g, "/");
1117
1133
  if (relNorm.includes("02_Areas") && relNorm.includes("Engine")) continue;
1118
- const srcContent = fs.readFileSync(path.join(dir, entry.name), "utf8");
1134
+ const srcContent = fs.readFileSync(path.join(dir, entry.name), "utf8")
1135
+ .replace(/\r\n/g, "\n").replace(/\r/g, "\n");
1119
1136
  const destFile = path.join(vaultPath, entryRel);
1120
1137
  if (!fs.existsSync(destFile)) {
1121
1138
  result.templates.push({ file: entryRel, status: "new" });
1122
1139
  } else {
1123
- const destContent = fs.readFileSync(destFile, "utf8");
1140
+ const destContent = fs.readFileSync(destFile, "utf8")
1141
+ .replace(/\r\n/g, "\n").replace(/\r/g, "\n");
1124
1142
  result.templates.push({
1125
1143
  file: entryRel,
1126
1144
  status: srcContent === destContent ? "unchanged" : "changed",
@@ -1147,12 +1165,14 @@ function detectChanges(bundleDir, vaultPath, selectedAgentIds) {
1147
1165
  if (entry.isDirectory()) {
1148
1166
  const skillFile = path.join(full, "SKILL.md");
1149
1167
  if (fs.existsSync(skillFile)) {
1150
- const srcContent = fs.readFileSync(skillFile, "utf8");
1168
+ const srcContent = fs.readFileSync(skillFile, "utf8")
1169
+ .replace(/\r\n/g, "\n").replace(/\r/g, "\n");
1151
1170
  const destSkill = path.join(skillsDest, entry.name, "SKILL.md");
1152
1171
  if (!fs.existsSync(destSkill)) {
1153
1172
  result.skills.push({ file: entry.name, status: "new" });
1154
1173
  } else {
1155
- const destContent = fs.readFileSync(destSkill, "utf8");
1174
+ const destContent = fs.readFileSync(destSkill, "utf8")
1175
+ .replace(/\r\n/g, "\n").replace(/\r/g, "\n");
1156
1176
  result.skills.push({ file: entry.name, status: srcContent === destContent ? "unchanged" : "changed" });
1157
1177
  }
1158
1178
  } else {
@@ -5280,8 +5300,12 @@ async function cmdUpdateComprehensive(opts, bundleDir, startTime) {
5280
5300
  }
5281
5301
  }
5282
5302
  fs.writeFileSync(path.join(vaultPath, ".mover-version"), `${require("./package.json").version}\n`, "utf8");
5283
- writeMoverConfig(vaultPath, selectedIds);
5303
+ writeMoverConfig(vaultPath, selectedIds, updateKey);
5284
5304
  barLn();
5305
+ if (totalChanged > 0) {
5306
+ barLn(dim(" Restart your AI session to load updated rules and skills."));
5307
+ barLn();
5308
+ }
5285
5309
  const elapsed = ((Date.now() - startTime) / 1000).toFixed(1);
5286
5310
  await successAnimation(`${totalChanged} files updated in ${elapsed}s.`);
5287
5311
  return;
@@ -5610,7 +5634,7 @@ async function cmdUpdateComprehensive(opts, bundleDir, startTime) {
5610
5634
  }
5611
5635
  }
5612
5636
  saveUpdateManifest(newManifest);
5613
- writeMoverConfig(vaultPath, selectedIds);
5637
+ writeMoverConfig(vaultPath, selectedIds, updateKey);
5614
5638
 
5615
5639
  // ── Summary ──
5616
5640
  barLn();
@@ -5630,6 +5654,10 @@ async function cmdUpdateComprehensive(opts, bundleDir, startTime) {
5630
5654
  }
5631
5655
 
5632
5656
  barLn();
5657
+ if (updated.length > 0 || autoMerged.length > 0) {
5658
+ barLn(dim(" Restart your AI session to load updated rules and skills."));
5659
+ barLn();
5660
+ }
5633
5661
  const elapsed = ((Date.now() - startTime) / 1000).toFixed(1);
5634
5662
  if (needsUpdate) {
5635
5663
  outro(`System updated. Run ${bold("/update")} to resolve ${conflicts.length} conflict${conflicts.length > 1 ? "s" : ""}. ${dim(`(${elapsed}s)`)}`);
@@ -5643,13 +5671,15 @@ function resolveVaultPath(explicitVault) {
5643
5671
  if (explicitVault) {
5644
5672
  let v = explicitVault;
5645
5673
  if (v.startsWith("~")) v = path.join(os.homedir(), v.slice(1));
5674
+ v = normalizeWinPath(v);
5646
5675
  return path.resolve(v);
5647
5676
  }
5648
5677
  // Try config.json
5649
5678
  const cfgPath = path.join(os.homedir(), ".mover", "config.json");
5650
5679
  if (fs.existsSync(cfgPath)) {
5651
5680
  try {
5652
- const v = JSON.parse(fs.readFileSync(cfgPath, "utf8")).vaultPath;
5681
+ let v = JSON.parse(fs.readFileSync(cfgPath, "utf8")).vaultPath;
5682
+ v = normalizeWinPath(v);
5653
5683
  if (v && fs.existsSync(v)) return v;
5654
5684
  } catch {}
5655
5685
  }
@@ -5913,6 +5943,7 @@ async function main() {
5913
5943
  }
5914
5944
 
5915
5945
  if (vaultPath.startsWith("~")) vaultPath = path.join(os.homedir(), vaultPath.slice(1));
5946
+ vaultPath = normalizeWinPath(vaultPath);
5916
5947
  vaultPath = path.resolve(vaultPath);
5917
5948
 
5918
5949
  // ── Fresh install only — redirect if existing ──
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mover-os",
3
- "version": "4.7.3",
3
+ "version": "4.7.4",
4
4
  "description": "Your AI co-founder. Remembers your goals, pushes back when you drift. Works with 15 AI agents.",
5
5
  "bin": {
6
6
  "moveros": "install.js"