cursor-guard 4.9.8 → 4.9.9
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 +10 -1
- package/README.zh-CN.md +10 -1
- package/ROADMAP.md +11 -4
- package/docs/RELEASE.md +196 -0
- package/package.json +2 -1
- package/references/dashboard/public/app.js +79 -79
- package/references/dashboard/public/style.css +264 -159
- package/references/lib/core/core.test.js +139 -101
- package/references/lib/core/snapshot.js +8 -4
- package/references/mcp/server.js +73 -72
- package/references/vscode-extension/dist/{cursor-guard-ide-4.9.8.vsix → cursor-guard-ide-4.9.9.vsix} +0 -0
- package/references/vscode-extension/dist/dashboard/public/app.js +79 -79
- package/references/vscode-extension/dist/dashboard/public/style.css +264 -159
- package/references/vscode-extension/dist/extension.js +9 -2
- package/references/vscode-extension/dist/guard-version.json +1 -1
- package/references/vscode-extension/dist/lib/core/snapshot.js +8 -4
- package/references/vscode-extension/dist/lib/dashboard-manager.js +110 -103
- package/references/vscode-extension/dist/lib/sidebar-webview.js +447 -156
- package/references/vscode-extension/dist/mcp/server.js +9 -6
- package/references/vscode-extension/dist/package.json +1 -1
- package/references/vscode-extension/dist/skill/ROADMAP.md +11 -4
- package/references/vscode-extension/extension.js +9 -2
- package/references/vscode-extension/lib/dashboard-manager.js +110 -103
- package/references/vscode-extension/lib/sidebar-webview.js +447 -156
- package/references/vscode-extension/package.json +1 -1
package/README.md
CHANGED
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
|
|
6
6
|
Protects your code from accidental AI overwrite or deletion in [Cursor](https://cursor.com).
|
|
7
7
|
|
|
8
|
-
**[中文文档](README.zh-CN.md)**
|
|
8
|
+
**[中文文档](README.zh-CN.md)**
|
|
9
|
+
**Release / 发版(maintainers & AI):** [docs/RELEASE.md](docs/RELEASE.md)
|
|
9
10
|
|
|
10
11
|
---
|
|
11
12
|
|
|
@@ -467,6 +468,12 @@ The skill activates on these signals:
|
|
|
467
468
|
|
|
468
469
|
## Changelog
|
|
469
470
|
|
|
471
|
+
### v4.9.9 — Dedicated release guide (`docs/RELEASE.md`)
|
|
472
|
+
|
|
473
|
+
- **Docs**: New bilingual **[docs/RELEASE.md](docs/RELEASE.md)** for maintainers, developers, and AI agents (full procedure, Windows `gh` + UTF-8 `--notes-file`, npm OTP)
|
|
474
|
+
- **Docs**: README / README.zh-CN link to the guide from the header and the release-checklist section; `npm run release:checklist` footer points to the same file
|
|
475
|
+
- **Packaging**: `docs/RELEASE.md` added to npm `files` so it ships with the package
|
|
476
|
+
|
|
470
477
|
### v4.9.8 — Release docs, checklist script, sidebar brand asset
|
|
471
478
|
|
|
472
479
|
- **Docs**: Bilingual **Release checklist** sections in README / README.zh-CN; steps tied to root `package.json` `version` so VSIX file name, Git tag, and npm stay consistent
|
|
@@ -628,6 +635,8 @@ The skill activates on these signals:
|
|
|
628
635
|
|
|
629
636
|
**Single source of truth**: the `version` field in the **repository root** `package.json`. Running `references/vscode-extension/build-vsix.js` copies that value into the extension `package.json` and `guard-version.json`, so the VSIX and npm tarball stay aligned.
|
|
630
637
|
|
|
638
|
+
**Full guide (bilingual, for humans and AI agents):** [docs/RELEASE.md](docs/RELEASE.md) — includes **Windows `gh` + UTF-8**: use `--notes-file` for GitHub Release bodies so Chinese text does not become mojibake.
|
|
639
|
+
|
|
631
640
|
### Generate a filled-in table (recommended)
|
|
632
641
|
|
|
633
642
|
From the repository root:
|
package/README.zh-CN.md
CHANGED
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
|
|
6
6
|
保护你的代码免受 [Cursor](https://cursor.com) AI 代理意外覆写或删除。
|
|
7
7
|
|
|
8
|
-
**[English](README.md)**
|
|
8
|
+
**[English](README.md)**
|
|
9
|
+
**发版流程(维护者 / 其他开发者 / AI):** [docs/RELEASE.md](docs/RELEASE.md)
|
|
9
10
|
|
|
10
11
|
---
|
|
11
12
|
|
|
@@ -467,6 +468,12 @@ code --install-extension .
|
|
|
467
468
|
|
|
468
469
|
## 更新日志
|
|
469
470
|
|
|
471
|
+
### v4.9.9 — 独立发版指南 docs/RELEASE.md
|
|
472
|
+
|
|
473
|
+
- **文档**:新增中英双语 **[docs/RELEASE.md](docs/RELEASE.md)**,面向维护者、其他开发者及 **AI 助手**(完整步骤、Windows 下 `gh` 与 UTF-8 `--notes-file`、npm OTP 等)
|
|
474
|
+
- **文档**:README / README.zh-CN 顶部与发版小节增加指向该指南的链接;`npm run release:checklist` 输出末尾提示同一文件
|
|
475
|
+
- **打包**:`docs/RELEASE.md` 已加入 npm `files`,随包分发
|
|
476
|
+
|
|
470
477
|
### v4.9.8 — 发版文档、清单脚本、侧边栏品牌资源
|
|
471
478
|
|
|
472
479
|
- **文档**:在 README / README.zh-CN 增加双语**发版检查清单**,步骤与根目录 `package.json` 的 `version` 绑定,避免 VSIX 名、Git 标签、npm 版本各写各的
|
|
@@ -627,6 +634,8 @@ code --install-extension .
|
|
|
627
634
|
|
|
628
635
|
**唯一版本源**:仓库**根目录** `package.json` 里的 **`version`**。执行 `references/vscode-extension/build-vsix.js` 时,会把同一版本写入扩展内的 `package.json` 与 `guard-version.json`,因此 VSIX 与 npm 包版本一致。
|
|
629
636
|
|
|
637
|
+
**完整发版指南(中英双语,给人看也给 AI 执行):** [docs/RELEASE.md](docs/RELEASE.md) — 内含 **Windows 下 GitHub CLI**:Release 正文请用 UTF-8 文件 + `gh … --notes-file`,避免中文乱码。
|
|
638
|
+
|
|
630
639
|
### 生成已填好版本号的表格(推荐)
|
|
631
640
|
|
|
632
641
|
在仓库根目录执行:
|
package/ROADMAP.md
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
> 本文档描述 cursor-guard 从 V2 到 V7 的长期演进方向。
|
|
4
4
|
> 每一代向下兼容,低版本功能永远不废弃。
|
|
5
5
|
>
|
|
6
|
-
> **当前版本**:`V4.9.
|
|
7
|
-
> **文档状态**:`V2` ~ `V4.9.
|
|
6
|
+
> **当前版本**:`V4.9.9`
|
|
7
|
+
> **文档状态**:`V2` ~ `V4.9.9` 已完成交付(含 V5 intent/audit 基础),`V5` 主体规划中
|
|
8
8
|
|
|
9
9
|
## 阅读导航
|
|
10
10
|
|
|
@@ -734,6 +734,12 @@ V4 经过 4 轮系统性代码审查,修复了以下关键问题:
|
|
|
734
734
|
}
|
|
735
735
|
```
|
|
736
736
|
|
|
737
|
+
### V4.9.9:独立发版指南(人 + AI)✅
|
|
738
|
+
| 能力 | 说明 |
|
|
739
|
+
|------|------|
|
|
740
|
+
| **docs/RELEASE.md** | 中英双语完整发版流程:版本源、VSIX、Git、GitHub Release、npm OTP;**Windows 下 `gh` 须用 UTF-8 文件 + `--notes-file`** 避免 Release 正文乱码;专设「给其他 AI 助手」摘要 |
|
|
741
|
+
| **入口** | README / README.zh-CN 顶部与发版小节链接;`print-release-checklist.js` 末尾提示;`package.json` `files` 纳入该文档以便 npm tarball 携带 |
|
|
742
|
+
|
|
737
743
|
### V4.9.8:发版流程文档化 + 侧边栏品牌占位 ✅
|
|
738
744
|
| 能力 | 说明 |
|
|
739
745
|
|------|------|
|
|
@@ -1620,7 +1626,8 @@ V4.3.5 ───── ✅ Summary 增量 diff-tree 修复 + 变更列堆叠布
|
|
|
1620
1626
|
V4.4.0 ───── ✅ V4 收官:首次快照 summary + doctor 完整性/retention 检查 + init 升级检测
|
|
1621
1627
|
V4.9.0 ───── ✅ 事件驱动 watcher + 实时侧边栏计时
|
|
1622
1628
|
V4.9.5 ───── ✅ 修复 `.git` 写入导致的疯狂自触发备份
|
|
1623
|
-
V4.9.
|
|
1629
|
+
V4.9.9 ───── ✅ docs/RELEASE.md 发版指南(人 + AI)+ gh UTF-8 说明 ← 当前版本
|
|
1630
|
+
V4.9.8 ───── ✅ 发版清单(README 双语 + checklist 脚本)+ 侧边栏品牌图
|
|
1624
1631
|
V4.9.7 ───── ✅ 预警体验打磨 + 语言同步 + watcher 单例保护
|
|
1625
1632
|
│
|
|
1626
1633
|
│ 前提:MVP 已跑通,需要把提示从“能用”打磨到“适合常开”
|
|
@@ -1710,4 +1717,4 @@ V7 的"可验证治理"是这条产品线的逻辑终点——该保护的都保
|
|
|
1710
1717
|
---
|
|
1711
1718
|
|
|
1712
1719
|
*最后更新:2026-03-22*
|
|
1713
|
-
*版本:v1.
|
|
1720
|
+
*版本:v1.9(V4.9.9,增加 docs/RELEASE.md 双语发版指南与 README 入口;历史含 V4.9.8 发版清单与侧边栏品牌、事件驱动 watcher、`pre_warning` 等)*
|
package/docs/RELEASE.md
ADDED
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
# Release guide / 发版流程指南
|
|
2
|
+
|
|
3
|
+
**Audience / 读者**:本仓库维护者、其他开发者、以及需要代为执行发版步骤的 **AI 助手**(Agent)。
|
|
4
|
+
**Repo / 仓库**:<https://github.com/zhangqiang8vipp/cursor-guard>
|
|
5
|
+
|
|
6
|
+
**Jump / 跳转**:[English](#english-for-maintainers-and-ai-agents) · [中文(维护者与 AI)](#中文维护者与-ai-助手)
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## English (for maintainers and AI agents)
|
|
11
|
+
|
|
12
|
+
### Single source of truth
|
|
13
|
+
|
|
14
|
+
- All release versions come from the **repository root** `package.json` → field **`version`** (semver, e.g. `4.9.8`).
|
|
15
|
+
- `references/vscode-extension/build-vsix.js` reads that value and writes the same version into:
|
|
16
|
+
- `references/vscode-extension/dist/package.json`
|
|
17
|
+
- `references/vscode-extension/dist/guard-version.json`
|
|
18
|
+
- The **npm** package name is `cursor-guard@<version>`. The **VSIX** file name is always `cursor-guard-ide-<version>.vsix`.
|
|
19
|
+
|
|
20
|
+
Never hand-type an old version in release notes while the repo already has a higher `version`.
|
|
21
|
+
|
|
22
|
+
### Quick machine-readable checklist
|
|
23
|
+
|
|
24
|
+
From the repo root:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npm run release:checklist
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Copy the printed table into your tracker. It is always aligned with the current `package.json`.
|
|
31
|
+
|
|
32
|
+
### Step-by-step release procedure
|
|
33
|
+
|
|
34
|
+
1. **Bump version**
|
|
35
|
+
Edit root `package.json` → `version`. Optionally sync `package-lock.json` (`npm install` or manual bump of the top-level `version` fields).
|
|
36
|
+
|
|
37
|
+
2. **Run tests (recommended)**
|
|
38
|
+
```bash
|
|
39
|
+
npm test
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
3. **Build the VSIX**
|
|
43
|
+
```bash
|
|
44
|
+
cd references/vscode-extension
|
|
45
|
+
node build-vsix.js
|
|
46
|
+
cd dist
|
|
47
|
+
npx --yes @vscode/vsce package --no-dependencies
|
|
48
|
+
```
|
|
49
|
+
Output: `references/vscode-extension/dist/cursor-guard-ide-<version>.vsix`.
|
|
50
|
+
|
|
51
|
+
4. **Commit**
|
|
52
|
+
Include source changes, updated `dist/` if your workflow commits it, and the new `.vsix` if you ship it from the repo. Use a clear message, e.g. `release: vX.Y.Z — …`.
|
|
53
|
+
|
|
54
|
+
5. **Tag and push**
|
|
55
|
+
```bash
|
|
56
|
+
git tag -a vX.Y.Z -m "vX.Y.Z"
|
|
57
|
+
git push origin <default-branch>
|
|
58
|
+
git push origin vX.Y.Z
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
6. **GitHub Release + attach VSIX**
|
|
62
|
+
- Create a release for tag `vX.Y.Z` and attach `cursor-guard-ide-X.Y.Z.vsix`.
|
|
63
|
+
- **Windows + GitHub CLI (`gh`) — avoid mojibake in release notes**
|
|
64
|
+
On Windows, passing long Chinese (or mixed) text inline with `gh release edit --notes "..."` often corrupts encoding (garbled text on GitHub).
|
|
65
|
+
**Always** put the body in a **UTF-8** file and use:
|
|
66
|
+
```bash
|
|
67
|
+
gh release create vX.Y.Z path/to/cursor-guard-ide-X.Y.Z.vsix --title "Cursor Guard vX.Y.Z" --notes-file RELEASE_NOTES.md
|
|
68
|
+
```
|
|
69
|
+
or for an existing release:
|
|
70
|
+
```bash
|
|
71
|
+
gh release edit vX.Y.Z --notes-file RELEASE_NOTES.md
|
|
72
|
+
```
|
|
73
|
+
Save `RELEASE_NOTES.md` as UTF-8 in VS Code / Cursor (default). Keep the release **title** ASCII-only if your shell is unreliable with Unicode.
|
|
74
|
+
- This repo’s `.gitignore` includes `.release-notes-*.md` so temporary note files are not committed by mistake.
|
|
75
|
+
|
|
76
|
+
7. **Maintenance branches (optional)**
|
|
77
|
+
If you use branches like `release/v4.8.x`, fast-forward them to the current default branch when your policy requires it.
|
|
78
|
+
|
|
79
|
+
8. **npm publish**
|
|
80
|
+
From the repo root:
|
|
81
|
+
```bash
|
|
82
|
+
npm publish --access public
|
|
83
|
+
```
|
|
84
|
+
If npm returns **EOTP**, open the URL it prints, complete authentication in the browser, then run `npm publish` again. AI agents cannot complete OTP for you.
|
|
85
|
+
|
|
86
|
+
9. **VS Code Marketplace (optional)**
|
|
87
|
+
Not required for GitHub Release + VSIX. If you publish there, use a personal access token and `npx @vscode/vsce publish` from `references/vscode-extension/dist` (see VS Code publishing docs).
|
|
88
|
+
|
|
89
|
+
### Hints for AI agents
|
|
90
|
+
|
|
91
|
+
- Read root `package.json` → `version` before claiming a release number.
|
|
92
|
+
- Prefer `npm run release:checklist` over inventing version strings.
|
|
93
|
+
- After editing release notes on Windows, use **`gh … --notes-file`** with a UTF-8 file; do not rely on huge `--notes "…"` strings in PowerShell.
|
|
94
|
+
- Do not echo npm OTP URLs as “user must visit” without also explaining they must complete the flow in a real browser.
|
|
95
|
+
- Never paste publish tokens into chat logs.
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## 中文(维护者与 AI 助手)
|
|
100
|
+
|
|
101
|
+
### 唯一版本源
|
|
102
|
+
|
|
103
|
+
- 一切发版版本号以**仓库根目录** `package.json` 的 **`version`** 为准(semver,例如 `4.9.8`)。
|
|
104
|
+
- 执行 `references/vscode-extension/build-vsix.js` 时,会把同一版本写入扩展构建产物中的 `package.json` 与 `guard-version.json`。
|
|
105
|
+
- **npm** 包为 `cursor-guard@<version>`;**VSIX** 固定命名为 `cursor-guard-ide-<version>.vsix`。
|
|
106
|
+
|
|
107
|
+
仓库已是新版本时,不要在对外说明里仍写旧的版本号(例如仍写 4.9.5)。
|
|
108
|
+
|
|
109
|
+
### 一键打印检查表
|
|
110
|
+
|
|
111
|
+
在仓库根目录:
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
npm run release:checklist
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
将终端输出复制到你的发版记录即可,内容与当前 `package.json` 一致。
|
|
118
|
+
|
|
119
|
+
### 发版步骤(建议顺序)
|
|
120
|
+
|
|
121
|
+
1. **改版本号**
|
|
122
|
+
修改根目录 `package.json` 的 `version`。如需,同步 `package-lock.json` 顶部版本字段或执行 `npm install` 更新锁文件。
|
|
123
|
+
|
|
124
|
+
2. **测试(建议)**
|
|
125
|
+
```bash
|
|
126
|
+
npm test
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
3. **构建 VSIX**
|
|
130
|
+
```bash
|
|
131
|
+
cd references/vscode-extension
|
|
132
|
+
node build-vsix.js
|
|
133
|
+
cd dist
|
|
134
|
+
npx --yes @vscode/vsce package --no-dependencies
|
|
135
|
+
```
|
|
136
|
+
得到:`references/vscode-extension/dist/cursor-guard-ide-<version>.vsix`。
|
|
137
|
+
|
|
138
|
+
4. **Git 提交**
|
|
139
|
+
按你们仓库习惯包含源码与 `dist/`(若纳入版本控制)及新的 `.vsix`。提交信息建议含 `release: vX.Y.Z`。
|
|
140
|
+
|
|
141
|
+
5. **打标签并推送**
|
|
142
|
+
```bash
|
|
143
|
+
git tag -a vX.Y.Z -m "vX.Y.Z"
|
|
144
|
+
git push origin <默认分支>
|
|
145
|
+
git push origin vX.Y.Z
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
6. **GitHub Release 并上传 VSIX**
|
|
149
|
+
- 为标签 `vX.Y.Z` 创建 Release,上传对应 VSIX。
|
|
150
|
+
- **Windows 上使用 `gh` 写中文说明时务必注意编码**
|
|
151
|
+
在 PowerShell 里用很长的 `gh release edit --notes "……中文……"` 容易导致 GitHub 上显示**乱码**。
|
|
152
|
+
**正确做法**:把正文保存为 **UTF-8** 的 Markdown 文件(如 `RELEASE_NOTES.md`,用 Cursor/VS Code 保存即可),然后执行:
|
|
153
|
+
```bash
|
|
154
|
+
gh release create vX.Y.Z ./references/vscode-extension/dist/cursor-guard-ide-X.Y.Z.vsix --title "Cursor Guard vX.Y.Z" --notes-file RELEASE_NOTES.md
|
|
155
|
+
```
|
|
156
|
+
或已有 Release 时:
|
|
157
|
+
```bash
|
|
158
|
+
gh release edit vX.Y.Z --notes-file RELEASE_NOTES.md
|
|
159
|
+
```
|
|
160
|
+
**标题**建议只用 ASCII(如 `Cursor Guard v4.9.8`),避免控制台编码问题。
|
|
161
|
+
- 本仓库 `.gitignore` 已忽略 `.release-notes-*.md`,避免临时说明文件被误提交。
|
|
162
|
+
|
|
163
|
+
7. **release 维护分支(可选)**
|
|
164
|
+
若使用 `release/v4.8.x` 等分支,按团队策略决定是否快进到当前默认分支。
|
|
165
|
+
|
|
166
|
+
8. **npm 发布**
|
|
167
|
+
在仓库根目录:
|
|
168
|
+
```bash
|
|
169
|
+
npm publish --access public
|
|
170
|
+
```
|
|
171
|
+
若提示 **OTP / 二次验证**,在浏览器完成 npm 提示的认证后**再执行一次** `npm publish`。AI 无法代替你完成浏览器验证。
|
|
172
|
+
|
|
173
|
+
9. **VS Code 扩展市场(可选)**
|
|
174
|
+
非必须;多数用户通过 GitHub Release + VSIX 安装即可。若上架市场,需 PAT 与 `vsce publish`(见官方文档)。
|
|
175
|
+
|
|
176
|
+
### 给其他 AI 助手的摘要
|
|
177
|
+
|
|
178
|
+
- 发版前先读根目录 `package.json` 的 `version`,不要臆造版本号。
|
|
179
|
+
- 优先执行 `npm run release:checklist` 生成与仓库一致的步骤表。
|
|
180
|
+
- 在 Windows 上更新 GitHub Release 正文时,用 **`gh … --notes-file`** + UTF-8 文件,避免在命令行里直接塞长中文。
|
|
181
|
+
- 不要在对话中粘贴 npm / GitHub 令牌;OTP 必须用户本人在浏览器完成。
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
## Related files / 相关文件
|
|
186
|
+
|
|
187
|
+
| File | Purpose |
|
|
188
|
+
|------|---------|
|
|
189
|
+
| `scripts/print-release-checklist.js` | Implements `npm run release:checklist` |
|
|
190
|
+
| `references/vscode-extension/build-vsix.js` | Assembles `dist/` and syncs version from root `package.json` |
|
|
191
|
+
| `README.md` / `README.zh-CN.md` | Short “Release checklist” sections + link here |
|
|
192
|
+
| `.gitignore` | Ignores `.release-notes-*.md` |
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
*Last updated / 最后更新: 2026-03-22(v4.9.9:随包分发与 README 入口)*
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cursor-guard",
|
|
3
|
-
"version": "4.9.
|
|
3
|
+
"version": "4.9.9",
|
|
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",
|
|
@@ -38,6 +38,7 @@
|
|
|
38
38
|
"SKILL.md",
|
|
39
39
|
"README.md",
|
|
40
40
|
"README.zh-CN.md",
|
|
41
|
+
"docs/RELEASE.md",
|
|
41
42
|
"ROADMAP.md",
|
|
42
43
|
"LICENSE",
|
|
43
44
|
"references/auto-backup.ps1",
|
|
@@ -60,16 +60,16 @@ const I18N = {
|
|
|
60
60
|
'alert.action.deleted': 'Deleted',
|
|
61
61
|
'alert.action.renamed': 'Renamed',
|
|
62
62
|
'alert.breakdown': '{added} added, {modified} modified, {deleted} deleted',
|
|
63
|
-
'alert.suggestion': 'Check recent changes and consider creating a manual snapshot',
|
|
64
|
-
'alert.viewFiles': 'View file details ({n} files)',
|
|
65
|
-
'preWarning.title': 'Pre-Warning',
|
|
66
|
-
'preWarning.none': 'No destructive edit risk detected',
|
|
67
|
-
'preWarning.active': 'Delete Risk',
|
|
68
|
-
'preWarning.file': 'File',
|
|
69
|
-
'preWarning.risk': 'Risk',
|
|
70
|
-
'preWarning.methods': 'Methods removed',
|
|
71
|
-
'preWarning.suggestion': 'Review this deletion before applying or restore from the latest snapshot',
|
|
72
|
-
'modal.alertFiles': 'Alert File Details',
|
|
63
|
+
'alert.suggestion': 'Check recent changes and consider creating a manual snapshot',
|
|
64
|
+
'alert.viewFiles': 'View file details ({n} files)',
|
|
65
|
+
'preWarning.title': 'Pre-Warning',
|
|
66
|
+
'preWarning.none': 'No destructive edit risk detected',
|
|
67
|
+
'preWarning.active': 'Delete Risk',
|
|
68
|
+
'preWarning.file': 'File',
|
|
69
|
+
'preWarning.risk': 'Risk',
|
|
70
|
+
'preWarning.methods': 'Methods removed',
|
|
71
|
+
'preWarning.suggestion': 'Review this deletion before applying or restore from the latest snapshot',
|
|
72
|
+
'modal.alertFiles': 'Alert File Details',
|
|
73
73
|
'modal.col.restore': 'Restore',
|
|
74
74
|
'modal.copyRestore': 'Copy cmd',
|
|
75
75
|
'modal.restorePreDelete':'Restore pre-delete',
|
|
@@ -177,9 +177,9 @@ const I18N = {
|
|
|
177
177
|
'issue.disk_critically_low': 'Disk space critically low ({gb} GB free)',
|
|
178
178
|
'issue.disk_low': 'Disk space low ({gb} GB free)',
|
|
179
179
|
'issue.git_backup_stale': 'Last git backup is stale ({rel})',
|
|
180
|
-
'issue.active_alert': 'Active alert: {type} — {count} files in {window}s',
|
|
181
|
-
'issue.pre_warning_active': 'Pre-warning active: {summary}',
|
|
182
|
-
'issue.alert_high_velocity': 'High volume of file changes detected. Consider reviewing recent modifications and creating a manual snapshot.',
|
|
180
|
+
'issue.active_alert': 'Active alert: {type} — {count} files in {window}s',
|
|
181
|
+
'issue.pre_warning_active': 'Pre-warning active: {summary}',
|
|
182
|
+
'issue.alert_high_velocity': 'High volume of file changes detected. Consider reviewing recent modifications and creating a manual snapshot.',
|
|
183
183
|
|
|
184
184
|
'check.Git installed': 'Git installed',
|
|
185
185
|
'check.Git repository': 'Git repository',
|
|
@@ -296,16 +296,16 @@ const I18N = {
|
|
|
296
296
|
'alert.action.deleted': '删除',
|
|
297
297
|
'alert.action.renamed': '重命名',
|
|
298
298
|
'alert.breakdown': '新增 {added} · 修改 {modified} · 删除 {deleted}',
|
|
299
|
-
'alert.suggestion': '建议检查近期变更,并考虑手动创建快照',
|
|
300
|
-
'alert.viewFiles': '查看文件详情({n} 个文件)',
|
|
301
|
-
'preWarning.title': '事先预警',
|
|
302
|
-
'preWarning.none': '未检测到破坏性编辑风险',
|
|
303
|
-
'preWarning.active': '删除风险',
|
|
304
|
-
'preWarning.file': '文件',
|
|
305
|
-
'preWarning.risk': '风险',
|
|
306
|
-
'preWarning.methods': '移除的方法数',
|
|
307
|
-
'preWarning.suggestion': '建议在应用前检查这次删除,或直接从最新快照恢复',
|
|
308
|
-
'modal.alertFiles': '告警文件详情',
|
|
299
|
+
'alert.suggestion': '建议检查近期变更,并考虑手动创建快照',
|
|
300
|
+
'alert.viewFiles': '查看文件详情({n} 个文件)',
|
|
301
|
+
'preWarning.title': '事先预警',
|
|
302
|
+
'preWarning.none': '未检测到破坏性编辑风险',
|
|
303
|
+
'preWarning.active': '删除风险',
|
|
304
|
+
'preWarning.file': '文件',
|
|
305
|
+
'preWarning.risk': '风险',
|
|
306
|
+
'preWarning.methods': '移除的方法数',
|
|
307
|
+
'preWarning.suggestion': '建议在应用前检查这次删除,或直接从最新快照恢复',
|
|
308
|
+
'modal.alertFiles': '告警文件详情',
|
|
309
309
|
'modal.col.restore': '恢复',
|
|
310
310
|
'modal.copyRestore': '复制命令',
|
|
311
311
|
'modal.restorePreDelete':'恢复删除前',
|
|
@@ -414,8 +414,8 @@ const I18N = {
|
|
|
414
414
|
'issue.disk_low': '磁盘空间不足({gb} GB 可用)',
|
|
415
415
|
'issue.git_backup_stale': '最近 Git 备份已过时({rel})',
|
|
416
416
|
'issue.active_alert': '活跃告警:{type}——{count} 个文件在 {window} 秒内变更',
|
|
417
|
-
'issue.pre_warning_active': '事先预警生效:{summary}',
|
|
418
|
-
'issue.alert_high_velocity': '检测到大量文件变更,建议检查最近修改并手动创建快照。',
|
|
417
|
+
'issue.pre_warning_active': '事先预警生效:{summary}',
|
|
418
|
+
'issue.alert_high_velocity': '检测到大量文件变更,建议检查最近修改并手动创建快照。',
|
|
419
419
|
|
|
420
420
|
'check.Git installed': 'Git 安装状态',
|
|
421
421
|
'check.Git repository': 'Git 仓库',
|
|
@@ -573,9 +573,9 @@ const ISSUE_PATTERNS = [
|
|
|
573
573
|
{ re: /^Disk space low \((.+?) GB free\)$/, key: 'issue.disk_low', extract: ['gb'] },
|
|
574
574
|
{ re: /^Last git backup is stale \((.+?)\)$/, key: 'issue.git_backup_stale', extract: ['rel'] },
|
|
575
575
|
{ re: /^Active alert: (.+?) — (\d+) files in (\d+)s$/, key: 'issue.active_alert', extract: ['type', 'count', 'window'] },
|
|
576
|
-
{ re: /^Pre-warning active: (.+)$/, key: 'issue.pre_warning_active', extract: ['summary'] },
|
|
577
|
-
{ re: /^High volume of file changes/, key: 'issue.alert_high_velocity' },
|
|
578
|
-
];
|
|
576
|
+
{ re: /^Pre-warning active: (.+)$/, key: 'issue.pre_warning_active', extract: ['summary'] },
|
|
577
|
+
{ re: /^High volume of file changes/, key: 'issue.alert_high_velocity' },
|
|
578
|
+
];
|
|
579
579
|
|
|
580
580
|
function translateIssue(text) {
|
|
581
581
|
for (const p of ISSUE_PATTERNS) {
|
|
@@ -867,14 +867,14 @@ function renderAll() {
|
|
|
867
867
|
|
|
868
868
|
/* ── Rendering: Overview ──────────────────────────────────── */
|
|
869
869
|
|
|
870
|
-
function renderOverview(d) {
|
|
871
|
-
renderHealthCard(d.health);
|
|
872
|
-
renderGitBackupCard(d.lastBackup);
|
|
873
|
-
renderShadowBackupCard(d.lastBackup);
|
|
874
|
-
renderPreWarningCard(d.preWarnings);
|
|
875
|
-
renderWatcherCard(d.watcher);
|
|
876
|
-
renderAlertCard(d.alerts);
|
|
877
|
-
}
|
|
870
|
+
function renderOverview(d) {
|
|
871
|
+
renderHealthCard(d.health);
|
|
872
|
+
renderGitBackupCard(d.lastBackup);
|
|
873
|
+
renderShadowBackupCard(d.lastBackup);
|
|
874
|
+
renderPreWarningCard(d.preWarnings);
|
|
875
|
+
renderWatcherCard(d.watcher);
|
|
876
|
+
renderAlertCard(d.alerts);
|
|
877
|
+
}
|
|
878
878
|
|
|
879
879
|
function renderHealthCard(health) {
|
|
880
880
|
const el = $('#card-health');
|
|
@@ -907,9 +907,9 @@ function renderGitBackupCard(lastBackup) {
|
|
|
907
907
|
`;
|
|
908
908
|
}
|
|
909
909
|
|
|
910
|
-
function renderShadowBackupCard(lastBackup) {
|
|
911
|
-
const el = $('#card-shadow-backup');
|
|
912
|
-
const s = lastBackup?.shadow;
|
|
910
|
+
function renderShadowBackupCard(lastBackup) {
|
|
911
|
+
const el = $('#card-shadow-backup');
|
|
912
|
+
const s = lastBackup?.shadow;
|
|
913
913
|
if (!s) {
|
|
914
914
|
el.innerHTML = `<div class="card-label">${t('shadowBackup.title')}</div><div class="card-empty">${t('shadowBackup.none')}</div>`;
|
|
915
915
|
return;
|
|
@@ -917,40 +917,40 @@ function renderShadowBackupCard(lastBackup) {
|
|
|
917
917
|
el.innerHTML = `
|
|
918
918
|
<div class="card-label">${t('shadowBackup.title')}</div>
|
|
919
919
|
<div class="card-value">${esc(relativeTime(s.timestamp))}</div>
|
|
920
|
-
<div class="card-detail text-muted text-sm">${esc(formatTime(s.timestamp))}</div>
|
|
921
|
-
`;
|
|
922
|
-
}
|
|
923
|
-
|
|
924
|
-
function renderPreWarningCard(preWarnings) {
|
|
925
|
-
const el = $('#card-prewarning');
|
|
926
|
-
if (!preWarnings?.active) {
|
|
927
|
-
el.innerHTML = `
|
|
928
|
-
<div class="card-label">${t('preWarning.title')}</div>
|
|
929
|
-
<div class="card-status"><span class="status-dot status-healthy"></span><span>${t('preWarning.none')}</span></div>
|
|
930
|
-
`;
|
|
931
|
-
return;
|
|
932
|
-
}
|
|
933
|
-
|
|
934
|
-
const warning = preWarnings.latest || {};
|
|
935
|
-
const file = warning.file || '-';
|
|
936
|
-
const risk = warning.riskPercent !== undefined ? `${warning.riskPercent}%` : '-';
|
|
937
|
-
const methods = warning.removedMethodCount || 0;
|
|
938
|
-
|
|
939
|
-
el.innerHTML = `
|
|
940
|
-
<div class="card-label">${t('preWarning.title')}</div>
|
|
941
|
-
<div class="card-status"><span class="status-dot status-warning"></span><span class="status-text status-warning">${t('preWarning.active')}</span></div>
|
|
942
|
-
<div class="alert-details">
|
|
943
|
-
<div class="alert-detail-row"><span class="alert-detail-label">${t('preWarning.file')}</span><span class="text-mono">${esc(file)}</span></div>
|
|
944
|
-
<div class="alert-detail-row"><span class="alert-detail-label">${t('preWarning.risk')}</span><span>${esc(risk)}</span></div>
|
|
945
|
-
${methods > 0 ? `<div class="alert-detail-row"><span class="alert-detail-label">${t('preWarning.methods')}</span><span>${methods}</span></div>` : ''}
|
|
946
|
-
<div class="alert-detail-row alert-breakdown text-sm">${esc(warning.summary || t('preWarning.suggestion'))}</div>
|
|
947
|
-
<div class="alert-detail-row alert-suggestion text-sm text-muted">${t('preWarning.suggestion')}</div>
|
|
948
|
-
</div>
|
|
949
|
-
`;
|
|
950
|
-
}
|
|
951
|
-
|
|
952
|
-
function renderWatcherCard(watcher) {
|
|
953
|
-
const el = $('#card-watcher');
|
|
920
|
+
<div class="card-detail text-muted text-sm">${esc(formatTime(s.timestamp))}</div>
|
|
921
|
+
`;
|
|
922
|
+
}
|
|
923
|
+
|
|
924
|
+
function renderPreWarningCard(preWarnings) {
|
|
925
|
+
const el = $('#card-prewarning');
|
|
926
|
+
if (!preWarnings?.active) {
|
|
927
|
+
el.innerHTML = `
|
|
928
|
+
<div class="card-label">${t('preWarning.title')}</div>
|
|
929
|
+
<div class="card-status"><span class="status-dot status-healthy"></span><span>${t('preWarning.none')}</span></div>
|
|
930
|
+
`;
|
|
931
|
+
return;
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
const warning = preWarnings.latest || {};
|
|
935
|
+
const file = warning.file || '-';
|
|
936
|
+
const risk = warning.riskPercent !== undefined ? `${warning.riskPercent}%` : '-';
|
|
937
|
+
const methods = warning.removedMethodCount || 0;
|
|
938
|
+
|
|
939
|
+
el.innerHTML = `
|
|
940
|
+
<div class="card-label">${t('preWarning.title')}</div>
|
|
941
|
+
<div class="card-status"><span class="status-dot status-warning"></span><span class="status-text status-warning">${t('preWarning.active')}</span></div>
|
|
942
|
+
<div class="alert-details">
|
|
943
|
+
<div class="alert-detail-row"><span class="alert-detail-label">${t('preWarning.file')}</span><span class="text-mono">${esc(file)}</span></div>
|
|
944
|
+
<div class="alert-detail-row"><span class="alert-detail-label">${t('preWarning.risk')}</span><span>${esc(risk)}</span></div>
|
|
945
|
+
${methods > 0 ? `<div class="alert-detail-row"><span class="alert-detail-label">${t('preWarning.methods')}</span><span>${methods}</span></div>` : ''}
|
|
946
|
+
<div class="alert-detail-row alert-breakdown text-sm">${esc(warning.summary || t('preWarning.suggestion'))}</div>
|
|
947
|
+
<div class="alert-detail-row alert-suggestion text-sm text-muted">${t('preWarning.suggestion')}</div>
|
|
948
|
+
</div>
|
|
949
|
+
`;
|
|
950
|
+
}
|
|
951
|
+
|
|
952
|
+
function renderWatcherCard(watcher) {
|
|
953
|
+
const el = $('#card-watcher');
|
|
954
954
|
let st = 'stopped';
|
|
955
955
|
if (watcher?.running) st = 'running';
|
|
956
956
|
else if (watcher?.stale) st = 'stale';
|
|
@@ -1295,18 +1295,18 @@ function renderProtection(scope) {
|
|
|
1295
1295
|
|
|
1296
1296
|
el.innerHTML = `
|
|
1297
1297
|
<div class="protection-grid">
|
|
1298
|
-
<div class="pattern-card">
|
|
1298
|
+
<div class="pattern-card pattern-card--protect">
|
|
1299
1299
|
<h4>${t('protection.protect')}</h4>
|
|
1300
1300
|
${isAll
|
|
1301
|
-
? `<p class="
|
|
1302
|
-
: `<ul class="pattern-list">${protectList.map(p => `<li class="pattern-item">${esc(p)}</li>`).join('')}</ul>`
|
|
1301
|
+
? `<p class="pattern-empty pattern-empty--protect text-sm">${t('protection.allFiles')}</p>`
|
|
1302
|
+
: `<ul class="pattern-list">${protectList.map(p => `<li class="pattern-item pattern-item--protect">${esc(p)}</li>`).join('')}</ul>`
|
|
1303
1303
|
}
|
|
1304
1304
|
</div>
|
|
1305
|
-
<div class="pattern-card">
|
|
1305
|
+
<div class="pattern-card pattern-card--ignore">
|
|
1306
1306
|
<h4>${t('protection.ignore')}</h4>
|
|
1307
1307
|
${ignoreList.length === 0
|
|
1308
|
-
? `<p class="
|
|
1309
|
-
: `<ul class="pattern-list">${ignoreList.map(p => `<li class="pattern-item">${esc(p)}</li>`).join('')}</ul>`
|
|
1308
|
+
? `<p class="pattern-empty pattern-empty--ignore text-sm">${t('protection.noIgnore')}</p>`
|
|
1309
|
+
: `<ul class="pattern-list">${ignoreList.map(p => `<li class="pattern-item pattern-item--ignore">${esc(p)}</li>`).join('')}</ul>`
|
|
1310
1310
|
}
|
|
1311
1311
|
</div>
|
|
1312
1312
|
</div>
|