cursor-guard 1.2.0 → 1.3.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/README.md CHANGED
@@ -132,10 +132,23 @@ Edit `.cursor-guard.json` to define which files to protect:
132
132
  "ignore": ["node_modules/**", "dist/**"],
133
133
  "auto_backup_interval_seconds": 60,
134
134
  "secrets_patterns": [".env", ".env.*", "*.key", "*.pem"],
135
+ "pre_restore_backup": "always",
135
136
  "retention": { "mode": "days", "days": 30 }
136
137
  }
137
138
  ```
138
139
 
140
+ #### `pre_restore_backup` — restore behavior control
141
+
142
+ | Value | Behavior |
143
+ |-------|----------|
144
+ | `"always"` (default) | Automatically preserve current version before every restore. No prompt. |
145
+ | `"ask"` | Prompt you each time: "Preserve current version before restore? (Y/n)" — you decide per restore. |
146
+ | `"never"` | Never preserve current version before restore (not recommended). |
147
+
148
+ Regardless of config, you can always override per-request:
149
+ - Say "don't preserve current version" to skip even when config is `"always"`
150
+ - Say "preserve current first" to force even when config is `"never"`
151
+
139
152
  ---
140
153
 
141
154
  ## Auto-Backup Script
@@ -157,7 +170,9 @@ The script uses Git plumbing commands to snapshot to `cursor-guard/auto-backup`
157
170
 
158
171
  ## Recovery
159
172
 
160
- If something goes wrong, just tell the AI agent in natural language:
173
+ If something goes wrong, just tell the AI agent in natural language.
174
+
175
+ **Default behavior**: Before any restore, the agent automatically preserves your current version so you can undo the restore if needed. You don't need to ask for this — it happens by default. To skip, explicitly say "don't preserve current version" or "skip backup before restore".
161
176
 
162
177
  ### By time
163
178
 
@@ -176,7 +191,14 @@ If something goes wrong, just tell the AI agent in natural language:
176
191
  > "restore src/app.py to 10 minutes ago"
177
192
  > "restore src/app.py to the previous version"
178
193
 
179
- The agent will automatically search Git history and auto-backup snapshots, show you matching versions to choose from, and restore after your confirmation.
194
+ The agent will:
195
+ 1. **Preserve your current version** first (unless you opt out)
196
+ 2. Search Git history and auto-backup snapshots
197
+ 3. Show matching versions for you to choose
198
+ 4. Restore after your confirmation
199
+ 5. Report both the pre-restore backup ref and the restore result
200
+
201
+ If the pre-restore backup fails, the agent will **not** proceed — it will wait for your explicit confirmation before restoring without a safety net.
180
202
 
181
203
  ### Recovery priority
182
204
 
package/README.zh-CN.md CHANGED
@@ -132,10 +132,23 @@ cp .cursor/skills/cursor-guard/references/cursor-guard.example.json .cursor-guar
132
132
  "ignore": ["node_modules/**", "dist/**"],
133
133
  "auto_backup_interval_seconds": 60,
134
134
  "secrets_patterns": [".env", ".env.*", "*.key", "*.pem"],
135
+ "pre_restore_backup": "always",
135
136
  "retention": { "mode": "days", "days": 30 }
136
137
  }
137
138
  ```
138
139
 
140
+ #### `pre_restore_backup` — 恢复前保留行为控制
141
+
142
+ | 值 | 行为 |
143
+ |----|------|
144
+ | `"always"`(默认) | 每次恢复前自动保留当前版本,无需确认。 |
145
+ | `"ask"` | 每次恢复前询问你:"恢复前是否保留当前版本?(Y/n)"——由你逐次决定。 |
146
+ | `"never"` | 恢复前不保留当前版本(不推荐)。 |
147
+
148
+ 无论配置如何,你始终可以在单次请求中覆盖:
149
+ - 说"不保留当前版本"可跳过保留(即使配置为 `"always"`)
150
+ - 说"先保留当前版本"可强制保留(即使配置为 `"never"`)
151
+
139
152
  ---
140
153
 
141
154
  ## 自动备份脚本
@@ -157,7 +170,9 @@ cp .cursor/skills/cursor-guard/references/cursor-guard.example.json .cursor-guar
157
170
 
158
171
  ## 恢复
159
172
 
160
- 出问题时,直接用自然语言告诉 AI 代理即可:
173
+ 出问题时,直接用自然语言告诉 AI 代理即可。
174
+
175
+ **默认行为**:执行任何恢复操作前,代理会自动保留你的当前版本,方便恢复后反悔。无需额外请求,这是默认行为。如需跳过,请明确说"不保留当前版本"或"直接覆盖恢复"。
161
176
 
162
177
  ### 按时间恢复
163
178
 
@@ -176,7 +191,14 @@ cp .cursor/skills/cursor-guard/references/cursor-guard.example.json .cursor-guar
176
191
  > "把 src/app.py 恢复到10分钟前"
177
192
  > "把 src/app.py 恢复到上一个版本"
178
193
 
179
- 代理会自动搜索 Git 历史和自动备份快照,列出匹配版本供你选择,确认后执行恢复。
194
+ 代理会:
195
+ 1. **先保留你的当前版本**(除非你明确选择跳过)
196
+ 2. 搜索 Git 历史和自动备份快照
197
+ 3. 列出匹配版本供你选择
198
+ 4. 确认后执行恢复
199
+ 5. 报告恢复前备份引用和恢复结果
200
+
201
+ 如果保留当前版本失败,代理**不会**继续恢复——会等你明确确认后才会在没有安全网的情况下恢复。
180
202
 
181
203
  ### 恢复优先级
182
204
 
package/SKILL.md CHANGED
@@ -44,6 +44,12 @@ On first trigger in a session, check if the workspace root contains `.cursor-gua
44
44
  // Built-in defaults: .env, .env.*, *.key, *.pem, *.p12, *.pfx, credentials*
45
45
  "secrets_patterns": [".env", ".env.*", "*.key", "*.pem"],
46
46
 
47
+ // Controls behavior before restore operations.
48
+ // "always" (default): automatically preserve current version before every restore.
49
+ // "ask": prompt the user each time to decide.
50
+ // "never": skip preservation entirely (not recommended).
51
+ "pre_restore_backup": "always",
52
+
47
53
  // Retention for shadow copies. mode: "days" | "count" | "size"
48
54
  "retention": { "mode": "days", "days": 30, "max_count": 100, "max_size_mb": 500 }
49
55
  }
@@ -302,7 +308,111 @@ Recommended: #1 (closest to target time). Restore this one? / 推荐 #1(最接
302
308
  - If still nothing, report clearly: "No snapshot found before that time. The earliest available is [hash] at [time]. Do you want to use it?"
303
309
  - **Never silently pick a version.** Always show and confirm.
304
310
 
305
- ### Step 4: Execute Recovery
311
+ ### Step 4: Preserve Current Version Before Restore
312
+
313
+ > **Rule: `restore_requires_preserve_current_by_default`**
314
+ >
315
+ > The behavior is controlled by `pre_restore_backup` in `.cursor-guard.json` (default: `"always"`).
316
+
317
+ **4a. Determine preservation mode**
318
+
319
+ Read `pre_restore_backup` from config (§0). Three modes:
320
+
321
+ | Config value | Behavior |
322
+ |-------------|----------|
323
+ | `"always"` (default) | Automatically preserve current version. No prompt. Jump to 4b. |
324
+ | `"ask"` | Prompt the user: "恢复前是否保留当前版本?(Y/n)" / "Preserve current version before restore? (Y/n)". If user answers yes/default → jump to 4b. If user answers no → inform and jump to Step 5. |
325
+ | `"never"` | Skip preservation entirely. Inform: "配置已设为不保留当前版本 (pre_restore_backup=never),直接恢复。" and jump to Step 5. |
326
+
327
+ **Override rules** (apply regardless of config):
328
+ - If the user **explicitly** says "不保留当前版本" / "skip backup before restore" in the current message → skip, even if config is `"always"`.
329
+ - If the user **explicitly** says "先保留当前版本" / "preserve current first" → preserve, even if config is `"never"`.
330
+ - User's explicit instruction in the current message always takes priority over config.
331
+
332
+ **4b. Determine preservation scope**
333
+
334
+ | Restore scope | What to preserve |
335
+ |---------------|-----------------|
336
+ | Single file | Only that file's current state |
337
+ | Multiple files | All files that will be overwritten |
338
+ | Entire project | Full project snapshot |
339
+
340
+ **4c. Check if there are changes to preserve**
341
+
342
+ ```bash
343
+ # For single file: check if file differs from the restore target
344
+ git diff <target-commit> -- <file>
345
+
346
+ # For project: check overall status
347
+ git status --porcelain
348
+ ```
349
+
350
+ If the file/project is **identical** to the restore target (no diff), inform:
351
+ "当前版本与目标版本相同,无需保留,跳过备份。" / "Current version is identical to target, no backup needed."
352
+ Then jump to Step 5.
353
+
354
+ If the working tree is clean AND HEAD matches the restore target, inform:
355
+ "当前无可保留变更,直接恢复。" / "No changes to preserve, proceeding with restore."
356
+ Then jump to Step 5.
357
+
358
+ **4d. Create preservation snapshot**
359
+
360
+ Use the same temp-index plumbing as §2a to avoid polluting the user's staging area:
361
+
362
+ **Git repo (preferred):**
363
+
364
+ ```powershell
365
+ $guardIdx = Join-Path (git rev-parse --git-dir) "guard-pre-restore-index"
366
+ $env:GIT_INDEX_FILE = $guardIdx
367
+
368
+ # For single file: read HEAD tree then update just the target file
369
+ git read-tree HEAD
370
+ git add -- <file>
371
+
372
+ # For project: snapshot everything
373
+ git read-tree HEAD
374
+ git add -A
375
+
376
+ $tree = git write-tree
377
+ $env:GIT_INDEX_FILE = $null
378
+ Remove-Item $guardIdx -Force -ErrorAction SilentlyContinue
379
+
380
+ $commit = git commit-tree $tree -p HEAD -m "guard: preserve current before restore to <target>"
381
+ git update-ref refs/guard/pre-restore $commit
382
+ ```
383
+
384
+ Record the short hash and the ref `refs/guard/pre-restore`.
385
+
386
+ **Non-Git fallback (shadow copy):**
387
+
388
+ ```powershell
389
+ $ts = Get-Date -Format 'yyyyMMdd_HHmmss'
390
+ $dir = ".cursor-guard-backup/pre-restore-$ts"
391
+ New-Item -ItemType Directory -Force $dir | Out-Null
392
+ Copy-Item "<file>" "$dir/<file>"
393
+ ```
394
+
395
+ **4e. Handle preservation failure**
396
+
397
+ If the snapshot fails (e.g. disk full, permission error):
398
+ 1. **Do NOT proceed with restore.** Default is to abort.
399
+ 2. Inform the user: "当前版本保留失败。默认不继续恢复;如果你确认不保留当前状态也要继续,请明确说明。" / "Failed to preserve current version. Restore aborted by default. If you want to continue without backup, please confirm explicitly."
400
+ 3. Only proceed if the user explicitly confirms: "即使不保留也继续" / "continue without backup".
401
+
402
+ **4f. Inform user of preservation result**
403
+
404
+ Before executing restore, tell the user:
405
+ ```
406
+ 在恢复前,我已保留当前版本:
407
+ - 备份引用: refs/guard/pre-restore (abc1234)
408
+ - 恢复方式: git restore --source=refs/guard/pre-restore -- <file>
409
+
410
+ Current version preserved before restore:
411
+ - Backup ref: refs/guard/pre-restore (abc1234)
412
+ - To undo: git restore --source=refs/guard/pre-restore -- <file>
413
+ ```
414
+
415
+ ### Step 5: Execute Recovery
306
416
 
307
417
  **Single file recovery:**
308
418
 
@@ -330,12 +440,23 @@ Get-ChildItem .cursor-guard-backup/ -Directory | Sort-Object Name -Descending
330
440
  Copy-Item ".cursor-guard-backup/<timestamp>/<file>" "<original-path>"
331
441
  ```
332
442
 
333
- ### Step 5: Verify & Report
443
+ ### Step 6: Verify & Report
334
444
 
335
445
  After restoring, always:
336
446
  1. Show the restored file content (or diff) so the user can verify
337
- 2. Report the recovery in the status block (§6)
338
- 3. Suggest creating a new snapshot of the current (restored) state
447
+ 2. Report the recovery in the status block (§6a), including **both** the pre-restore backup ref and the restore target
448
+ 3. Tell the user how to undo the restore if needed
449
+
450
+ **Status block for restore operations:**
451
+
452
+ ```markdown
453
+ **Cursor Guard — restore status**
454
+ - **Pre-restore backup**: `refs/guard/pre-restore` (`<short-hash>`) or `shadow copy at .cursor-guard-backup/pre-restore-<ts>/` or `skipped (user opted out)` or `skipped (no changes)`
455
+ - **Restored to**: `<target-hash>` / `<target description>`
456
+ - **Scope**: single file `<path>` / N files / entire project
457
+ - **Result**: success / failed
458
+ - **To undo restore**: `git restore --source=refs/guard/pre-restore -- <file>`
459
+ ```
339
460
 
340
461
  ---
341
462
 
@@ -360,15 +481,17 @@ Skip the block for unrelated turns.
360
481
 
361
482
  1. **MUST snapshot before high-risk ops** — git commit or shadow copy. No exceptions unless user explicitly declines.
362
483
  2. **MUST Read before Write** — never overwrite a file the agent hasn't read in the current turn.
363
- 3. **Do not** treat Timeline/Checkpoints as the only or primary recovery path.
364
- 4. **Do not** recommend Checkpoints as long-term or sole backup.
365
- 5. **No automatic push** to remotes; local commits only unless user requests push.
366
- 6. **Be honest** about limits: terminal side effects, binary files, and non-tracked paths are not fully reversible without prior commits.
367
- 7. **Do not** run `git clean`, `reset --hard`, or other destructive Git commands unless the user clearly asked; always show what would be affected first.
368
- 8. **Do not** delete files via the Delete tool without explicit per-file confirmation from the user.
369
- 9. **Do not** modify or delete `.cursor-guard.json` unless the user explicitly asks accidental config changes silently alter protection scope.
370
- 10. **Use `--no-verify`** on all guard snapshot commits to bypass pre-commit hooks that could fail or modify files.
371
- 11. **Concurrent agents**: if multiple Agent threads are active, warn the user to avoid simultaneous writes to the same file. Snapshots cannot prevent race conditions between parallel agents.
484
+ 3. **MUST preserve current version before restore** every restore operation must first snapshot the current state (§5a Step 4). Skip ONLY when: (a) user explicitly opts out, (b) current state is identical to target, or (c) no changes exist. If preservation fails, abort restore by default.
485
+ 4. **Do not** treat Timeline/Checkpoints as the only or primary recovery path.
486
+ 5. **Do not** recommend Checkpoints as long-term or sole backup.
487
+ 6. **No automatic push** to remotes; local commits only unless user requests push.
488
+ 7. **Be honest** about limits: terminal side effects, binary files, and non-tracked paths are not fully reversible without prior commits.
489
+ 8. **Do not** run `git clean`, `reset --hard`, or other destructive Git commands unless the user clearly asked; always show what would be affected first.
490
+ 9. **Do not** delete files via the Delete tool without explicit per-file confirmation from the user.
491
+ 10. **Do not** modify or delete `.cursor-guard.json` unless the user explicitly asks accidental config changes silently alter protection scope.
492
+ 11. **Use `--no-verify`** on all guard snapshot commits to bypass pre-commit hooks that could fail or modify files.
493
+ 12. **Concurrent agents**: if multiple Agent threads are active, warn the user to avoid simultaneous writes to the same file. Snapshots cannot prevent race conditions between parallel agents.
494
+ 13. **Preservation must not pollute** — all pre-restore backups use temp index + dedicated ref (`refs/guard/pre-restore`). The user's staging area, working tree, and commit history on their branch are never modified by the preservation process.
372
495
 
373
496
  ---
374
497
 
@@ -376,7 +499,7 @@ Skip the block for unrelated turns.
376
499
 
377
500
  - If the workspace has `.cursor-guard.json`, the agent MUST read and follow it (see §0).
378
501
  - If `.cursor-guard-backup/` folder exists, align shadow copy paths with it.
379
- - Template config: [references/cursor-guard.example.json](references/cursor-guard.example.json) — copy to workspace root and customize.
502
+ - Template config: [references/cursor-guard.example.json](references/cursor-guard.example.json) — copy to workspace root and customize. Field docs: [references/config-reference.md](references/config-reference.md).
380
503
 
381
504
  ---
382
505
 
@@ -386,3 +509,5 @@ Skip the block for unrelated turns.
386
509
  - Auto-backup script: [references/auto-backup.ps1](references/auto-backup.ps1)
387
510
  - Config JSON Schema: [references/cursor-guard.schema.json](references/cursor-guard.schema.json)
388
511
  - Example config: [references/cursor-guard.example.json](references/cursor-guard.example.json)
512
+ - Config field reference (EN): [references/config-reference.md](references/config-reference.md)
513
+ - 配置参数说明(中文): [references/config-reference.zh-CN.md](references/config-reference.zh-CN.md)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cursor-guard",
3
- "version": "1.2.0",
3
+ "version": "1.3.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",
@@ -0,0 +1,134 @@
1
+ # Configuration Reference
2
+
3
+ This document explains every field in `.cursor-guard.json`.
4
+
5
+ > Example file: [cursor-guard.example.json](cursor-guard.example.json)
6
+ >
7
+ > JSON Schema: [cursor-guard.schema.json](cursor-guard.schema.json)
8
+
9
+ ---
10
+
11
+ ## `protect`
12
+
13
+ - **Type**: `string[]` (glob patterns)
14
+ - **Default**: not set (all files protected)
15
+
16
+ Whitelist glob patterns relative to workspace root. Only matching files get backup protection. If empty or missing, all files are protected.
17
+
18
+ ```json
19
+ "protect": ["src/**", "lib/**", "package.json"]
20
+ ```
21
+
22
+ ---
23
+
24
+ ## `ignore`
25
+
26
+ - **Type**: `string[]` (glob patterns)
27
+ - **Default**: not set
28
+
29
+ Blacklist glob patterns. Matching files are excluded from protection even if they match `protect`. Applied on top of `.gitignore`.
30
+
31
+ **Resolution rules**:
32
+
33
+ | Scenario | Behavior |
34
+ |----------|----------|
35
+ | Both `protect` and `ignore` set | File must match `protect` AND not match `ignore` |
36
+ | Only `protect` set | Only matching files are protected |
37
+ | Only `ignore` set | Everything protected except matches |
38
+ | Neither set | Protect everything |
39
+
40
+ ```json
41
+ "ignore": ["node_modules/**", "dist/**", "*.log"]
42
+ ```
43
+
44
+ ---
45
+
46
+ ## `backup_strategy`
47
+
48
+ - **Type**: `string`
49
+ - **Allowed**: `"git"` | `"shadow"` | `"both"`
50
+ - **Default**: `"git"`
51
+
52
+ | Value | Description |
53
+ |-------|-------------|
54
+ | `"git"` | Local commits to dedicated branch `cursor-guard/auto-backup` |
55
+ | `"shadow"` | File copies to `.cursor-guard-backup/<timestamp>/` |
56
+ | `"both"` | Git branch snapshot + shadow copies |
57
+
58
+ ```json
59
+ "backup_strategy": "git"
60
+ ```
61
+
62
+ ---
63
+
64
+ ## `auto_backup_interval_seconds`
65
+
66
+ - **Type**: `integer`
67
+ - **Minimum**: `5`
68
+ - **Default**: `60`
69
+
70
+ Interval in seconds for `auto-backup.ps1` to check for changes and create snapshots.
71
+
72
+ ```json
73
+ "auto_backup_interval_seconds": 60
74
+ ```
75
+
76
+ ---
77
+
78
+ ## `secrets_patterns`
79
+
80
+ - **Type**: `string[]` (glob patterns)
81
+ - **Default**: built-in list (see below)
82
+
83
+ Glob patterns for sensitive files. Matching files are **auto-excluded** from backup, even if within `protect` scope. Built-in defaults (always active): `.env`, `.env.*`, `*.key`, `*.pem`, `*.p12`, `*.pfx`, `credentials*`. Set this field to override with your own patterns.
84
+
85
+ ```json
86
+ "secrets_patterns": [".env", ".env.*", "*.key", "*.pem"]
87
+ ```
88
+
89
+ ---
90
+
91
+ ## `pre_restore_backup`
92
+
93
+ - **Type**: `string`
94
+ - **Allowed**: `"always"` | `"ask"` | `"never"`
95
+ - **Default**: `"always"`
96
+
97
+ | Value | Description |
98
+ |-------|-------------|
99
+ | `"always"` | Auto-preserve current version before every restore. No prompt. |
100
+ | `"ask"` | Prompt user each time: "Preserve current version?" |
101
+ | `"never"` | Skip preservation entirely (not recommended). |
102
+
103
+ Regardless of this config, the user's explicit instruction in the current message always takes priority. Say "don't preserve" to skip, or "preserve first" to force.
104
+
105
+ ```json
106
+ "pre_restore_backup": "always"
107
+ ```
108
+
109
+ ---
110
+
111
+ ## `retention`
112
+
113
+ - **Type**: `object`
114
+ - **Default**: `{ "mode": "days", "days": 30 }`
115
+
116
+ Retention policy for **shadow copies** only. Git branch snapshots are not auto-cleaned — manage them manually. Controls automatic cleanup of old `.cursor-guard-backup/` directories.
117
+
118
+ ### Sub-fields
119
+
120
+ | Field | Type | Default | Description |
121
+ |-------|------|---------|-------------|
122
+ | `mode` | `"days"` \| `"count"` \| `"size"` | `"days"` | Cleanup strategy |
123
+ | `days` | `integer` | `30` | Keep snapshots from last N days (when mode=days) |
124
+ | `max_count` | `integer` | `100` | Keep N newest snapshots (when mode=count) |
125
+ | `max_size_mb` | `integer` | `500` | Keep total size under N MB (when mode=size) |
126
+
127
+ ```json
128
+ "retention": {
129
+ "mode": "days",
130
+ "days": 30,
131
+ "max_count": 100,
132
+ "max_size_mb": 500
133
+ }
134
+ ```
@@ -0,0 +1,134 @@
1
+ # 配置参数说明
2
+
3
+ 本文档说明 `.cursor-guard.json` 中的每个配置项。
4
+
5
+ > 示例文件:[cursor-guard.example.json](cursor-guard.example.json)
6
+ >
7
+ > JSON Schema:[cursor-guard.schema.json](cursor-guard.schema.json)
8
+
9
+ ---
10
+
11
+ ## `protect`
12
+
13
+ - **类型**:`string[]`(glob 模式)
14
+ - **默认值**:未设置(保护所有文件)
15
+
16
+ 白名单 glob 模式,相对于工作区根目录。只有匹配的文件才会被保护。留空或不设置则保护所有文件。
17
+
18
+ ```json
19
+ "protect": ["src/**", "lib/**", "package.json"]
20
+ ```
21
+
22
+ ---
23
+
24
+ ## `ignore`
25
+
26
+ - **类型**:`string[]`(glob 模式)
27
+ - **默认值**:未设置
28
+
29
+ 黑名单 glob 模式。匹配的文件即使被 `protect` 包含也会排除。在 `.gitignore` 基础上额外生效。
30
+
31
+ **解析规则**:
32
+
33
+ | 场景 | 行为 |
34
+ |------|------|
35
+ | 同时设置 `protect` 和 `ignore` | 文件须匹配 protect 且不匹配 ignore |
36
+ | 仅设置 `protect` | 仅匹配文件被保护 |
37
+ | 仅设置 `ignore` | 除匹配文件外全部保护 |
38
+ | 都不设置 | 保护全部文件 |
39
+
40
+ ```json
41
+ "ignore": ["node_modules/**", "dist/**", "*.log"]
42
+ ```
43
+
44
+ ---
45
+
46
+ ## `backup_strategy`
47
+
48
+ - **类型**:`string`
49
+ - **可选值**:`"git"` | `"shadow"` | `"both"`
50
+ - **默认值**:`"git"`
51
+
52
+ | 值 | 说明 |
53
+ |----|------|
54
+ | `"git"` | 提交到专用分支 `cursor-guard/auto-backup` |
55
+ | `"shadow"` | 文件拷贝到 `.cursor-guard-backup/<timestamp>/` |
56
+ | `"both"` | Git 分支快照 + 影子拷贝同时进行 |
57
+
58
+ ```json
59
+ "backup_strategy": "git"
60
+ ```
61
+
62
+ ---
63
+
64
+ ## `auto_backup_interval_seconds`
65
+
66
+ - **类型**:`integer`
67
+ - **最小值**:`5`
68
+ - **默认值**:`60`
69
+
70
+ 自动备份脚本 `auto-backup.ps1` 检查变更并创建快照的间隔秒数。
71
+
72
+ ```json
73
+ "auto_backup_interval_seconds": 60
74
+ ```
75
+
76
+ ---
77
+
78
+ ## `secrets_patterns`
79
+
80
+ - **类型**:`string[]`(glob 模式)
81
+ - **默认值**:内置列表(见下)
82
+
83
+ 敏感文件 glob 模式。匹配的文件**自动排除**备份,即使在 `protect` 范围内。内置默认值(始终生效):`.env`、`.env.*`、`*.key`、`*.pem`、`*.p12`、`*.pfx`、`credentials*`。设置此字段可覆盖为自定义模式。
84
+
85
+ ```json
86
+ "secrets_patterns": [".env", ".env.*", "*.key", "*.pem"]
87
+ ```
88
+
89
+ ---
90
+
91
+ ## `pre_restore_backup`
92
+
93
+ - **类型**:`string`
94
+ - **可选值**:`"always"` | `"ask"` | `"never"`
95
+ - **默认值**:`"always"`
96
+
97
+ | 值 | 说明 |
98
+ |----|------|
99
+ | `"always"` | 恢复前自动保留当前版本,无需确认。 |
100
+ | `"ask"` | 每次恢复前询问用户是否保留当前版本。 |
101
+ | `"never"` | 不保留当前版本(不推荐)。 |
102
+
103
+ 无论此配置如何,用户在当前消息中的明确指令始终优先。说"不保留当前版本"可跳过,说"先保留当前版本"可强制保留。
104
+
105
+ ```json
106
+ "pre_restore_backup": "always"
107
+ ```
108
+
109
+ ---
110
+
111
+ ## `retention`
112
+
113
+ - **类型**:`object`
114
+ - **默认值**:`{ "mode": "days", "days": 30 }`
115
+
116
+ 仅针对**影子拷贝**的保留策略。Git 分支快照不会自动清理,需手动管理。控制 `.cursor-guard-backup/` 旧目录的自动清理。
117
+
118
+ ### 子字段
119
+
120
+ | 字段 | 类型 | 默认值 | 说明 |
121
+ |------|------|--------|------|
122
+ | `mode` | `"days"` \| `"count"` \| `"size"` | `"days"` | 清理策略 |
123
+ | `days` | `integer` | `30` | 保留最近 N 天的快照(mode=days 时生效) |
124
+ | `max_count` | `integer` | `100` | 保留最新 N 份快照(mode=count 时生效) |
125
+ | `max_size_mb` | `integer` | `500` | 总大小不超过 N MB(mode=size 时生效) |
126
+
127
+ ```json
128
+ "retention": {
129
+ "mode": "days",
130
+ "days": 30,
131
+ "max_count": 100,
132
+ "max_size_mb": 500
133
+ }
134
+ ```
@@ -1,8 +1,4 @@
1
1
  {
2
- "_comment_schema": "Optional: add \"$schema\" pointing to cursor-guard.schema.json for IDE validation. Adjust the path to where you placed the schema file.",
3
-
4
- "_comment_mode": "Two modes: whitelist (set 'protect') or blacklist (set 'ignore'). If both are set, 'protect' is checked first, then 'ignore' excludes from it.",
5
-
6
2
  "protect": [
7
3
  "src/**",
8
4
  "lib/**",
@@ -12,7 +8,6 @@
12
8
  "tsconfig.json",
13
9
  ".env.example"
14
10
  ],
15
-
16
11
  "ignore": [
17
12
  "node_modules/**",
18
13
  "dist/**",
@@ -23,19 +18,15 @@
23
18
  "*.tmp",
24
19
  ".cursor-guard-backup/**"
25
20
  ],
26
-
27
21
  "backup_strategy": "git",
28
22
  "auto_backup_interval_seconds": 60,
29
-
30
- "_comment_secrets": "Glob patterns for sensitive files — auto-excluded from backup even if matched by 'protect'. Built-in defaults: .env, .env.*, *.key, *.pem, *.p12, *.pfx, credentials*",
31
23
  "secrets_patterns": [
32
24
  ".env",
33
25
  ".env.*",
34
26
  "*.key",
35
27
  "*.pem"
36
28
  ],
37
-
38
- "_comment_retention": "Retention policy for shadow copies. mode: 'days' (default, keep N days), 'count' (keep N newest snapshots), 'size' (keep total under N MB).",
29
+ "pre_restore_backup": "always",
39
30
  "retention": {
40
31
  "mode": "days",
41
32
  "days": 30,
@@ -31,6 +31,12 @@
31
31
  "items": { "type": "string" },
32
32
  "description": "Glob patterns for sensitive files auto-excluded from backups. Built-in defaults: .env, .env.*, *.key, *.pem, *.p12, *.pfx, credentials*"
33
33
  },
34
+ "pre_restore_backup": {
35
+ "type": "string",
36
+ "enum": ["always", "ask", "never"],
37
+ "default": "always",
38
+ "description": "'always' (default): automatically preserve current version before every restore. 'ask': prompt the user each time to choose whether to preserve. 'never': skip preservation entirely (not recommended)."
39
+ },
34
40
  "retention": {
35
41
  "type": "object",
36
42
  "description": "Controls automatic cleanup of old shadow-copy snapshots.",
@@ -4,6 +4,72 @@ Replace `<path>` / `<file>` with real paths. Run from repository root. **Review
4
4
 
5
5
  ---
6
6
 
7
+ ## Preserve current version before restore / 恢复前保留当前版本
8
+
9
+ > **Default behavior**: Every restore operation must first preserve current state.
10
+ >
11
+ > **默认行为**:每次恢复操作前必须先保留当前版本。
12
+
13
+ ### Single file / 单文件
14
+
15
+ ```powershell
16
+ # Preserve current file state via temp index (does not touch staging area)
17
+ # 通过临时索引保留当前文件(不影响暂存区)
18
+ $guardIdx = Join-Path (git rev-parse --git-dir) "guard-pre-restore-index"
19
+ $env:GIT_INDEX_FILE = $guardIdx
20
+ git read-tree HEAD
21
+ git add -- <file>
22
+ $tree = git write-tree
23
+ $env:GIT_INDEX_FILE = $null
24
+ Remove-Item $guardIdx -Force -ErrorAction SilentlyContinue
25
+ $commit = git commit-tree $tree -p HEAD -m "guard: preserve current before restore"
26
+ git update-ref refs/guard/pre-restore $commit
27
+ Write-Host "Pre-restore backup: $($commit.Substring(0,7))"
28
+ ```
29
+
30
+ ### Entire project / 整个项目
31
+
32
+ ```powershell
33
+ # Same as above but with git add -A
34
+ $guardIdx = Join-Path (git rev-parse --git-dir) "guard-pre-restore-index"
35
+ $env:GIT_INDEX_FILE = $guardIdx
36
+ git read-tree HEAD
37
+ git add -A
38
+ $tree = git write-tree
39
+ $env:GIT_INDEX_FILE = $null
40
+ Remove-Item $guardIdx -Force -ErrorAction SilentlyContinue
41
+ $commit = git commit-tree $tree -p HEAD -m "guard: preserve current before restore"
42
+ git update-ref refs/guard/pre-restore $commit
43
+ Write-Host "Pre-restore backup: $($commit.Substring(0,7))"
44
+ ```
45
+
46
+ ### Non-Git fallback (shadow copy) / 非 Git 备选方案
47
+
48
+ ```powershell
49
+ $ts = Get-Date -Format 'yyyyMMdd_HHmmss'
50
+ $dir = ".cursor-guard-backup/pre-restore-$ts"
51
+ New-Item -ItemType Directory -Force $dir | Out-Null
52
+ Copy-Item "<file>" "$dir/<filename>"
53
+ Write-Host "Pre-restore shadow copy: $dir"
54
+ ```
55
+
56
+ ### Undo a restore (recover pre-restore state) / 撤销恢复(回到恢复前的状态)
57
+
58
+ ```bash
59
+ # Restore single file to pre-restore state
60
+ # 将单个文件恢复到恢复前的状态
61
+ git restore --source=refs/guard/pre-restore -- <file>
62
+
63
+ # Restore entire project to pre-restore state
64
+ # 将整个项目恢复到恢复前的状态
65
+ git restore --source=refs/guard/pre-restore -- .
66
+
67
+ # From shadow copy / 从影子拷贝恢复
68
+ Copy-Item ".cursor-guard-backup/pre-restore-<ts>/<file>" "<original-path>"
69
+ ```
70
+
71
+ ---
72
+
7
73
  ## Inspect current state
8
74
 
9
75
  ```bash