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.
|
|
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
|
-
|
|
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
|
-
|
|
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 = '
|
|
223
|
+
f.warning = 'protected path — will 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
|
|
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
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
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;
|