cursor-guard 4.2.1 → 4.2.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cursor-guard",
3
- "version": "4.2.1",
3
+ "version": "4.2.2",
4
4
  "description": "Protects code from accidental AI overwrite or deletion in Cursor IDE — mandatory pre-write snapshots, review-before-apply, local Git safety net, and deterministic recovery. | 保护代码免受 Cursor AI 代理意外覆写或删除——强制写前快照、预览再执行、本地 Git 安全网、确定性恢复。",
5
5
  "keywords": [
6
6
  "cursor",
@@ -110,7 +110,16 @@ console.log(` MCP server: ${serverExists ? 'OK' : 'MISSING'}`);
110
110
  console.log(` MCP SDK: ${sdkExists ? 'OK' : 'MISSING — run npm install in skill dir'}`);
111
111
 
112
112
  console.log(`\n Installation complete!\n`);
113
- console.log(' ⚠ If MCP was already configured, restart Cursor (or Ctrl+Shift+P →');
113
+
114
+ // Detect git repo and recommend committing
115
+ let isGitRepoDir = false;
116
+ try { isGitRepoDir = fs.existsSync(path.join(projectDir, '.git')); } catch { /* ignore */ }
117
+ if (!isGlobal && isGitRepoDir) {
118
+ console.log(' ** Important: commit now to prevent restore from reverting the skill **');
119
+ console.log(` git add .cursor/ .cursor-guard.json && git commit -m "chore: install cursor-guard"\n`);
120
+ }
121
+
122
+ console.log(' If MCP was already configured, restart Cursor (or Ctrl+Shift+P ->');
114
123
  console.log(' "Developer: Reload Window") to load the updated MCP server.\n');
115
124
  console.log(' Next steps:');
116
125
  console.log(' 1. The skill activates automatically in Cursor Agent conversations.');
@@ -21,10 +21,13 @@ function validateRelativePath(file) {
21
21
  const VALID_SHADOW_SOURCE = /^\d{8}_\d{6}(_\d{3})?$|^pre-restore-\d{8}_\d{6}(_\d{3})?$/;
22
22
 
23
23
  const TOOL_DIRS = ['.cursor/', '.cursor\\'];
24
+ const GUARD_CONFIGS = ['.cursor-guard.json'];
24
25
 
25
26
  function isToolPath(filePath) {
26
27
  const normalized = filePath.replace(/\\/g, '/');
27
- return TOOL_DIRS.some(d => normalized.startsWith(d));
28
+ if (TOOL_DIRS.some(d => normalized.startsWith(d))) return true;
29
+ if (GUARD_CONFIGS.includes(normalized)) return true;
30
+ return false;
28
31
  }
29
32
 
30
33
  function validateShadowSource(source) {
@@ -217,7 +220,7 @@ function previewProjectRestore(projectDir, source) {
217
220
 
218
221
  for (const f of files) {
219
222
  if (isToolPath(f.path)) {
220
- f.warning = 'tool directoryrestoring may downgrade cursor-guard or other tools';
223
+ f.warning = 'protected pathwill be preserved from HEAD to prevent tool/config downgrade';
221
224
  }
222
225
  }
223
226
 
@@ -282,14 +285,16 @@ function executeProjectRestore(projectDir, source, opts = {}) {
282
285
  cwd: projectDir, stdio: 'pipe',
283
286
  });
284
287
 
285
- // Restore .cursor/ back from HEAD to prevent tool/skill downgrade
288
+ // Restore protected paths from HEAD to prevent tool/skill/config downgrade
286
289
  const head = git(['rev-parse', 'HEAD'], { cwd: projectDir, allowFail: true });
287
290
  if (head) {
288
- try {
289
- execFileSync('git', ['restore', `--source=HEAD`, '--', '.cursor/'], {
290
- cwd: projectDir, stdio: 'pipe',
291
- });
292
- } catch { /* .cursor/ may not exist in HEAD, that's fine */ }
291
+ for (const p of ['.cursor/', ...GUARD_CONFIGS]) {
292
+ try {
293
+ execFileSync('git', ['restore', `--source=HEAD`, '--', p], {
294
+ cwd: projectDir, stdio: 'pipe',
295
+ });
296
+ } catch { /* may not exist in HEAD, that's fine */ }
297
+ }
293
298
  }
294
299
 
295
300
  let untrackedCleaned = 0;